metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-03-17 08:02 pm

Автоматический вывод типов запросов и bind-параметров в СУБД

Я знаю, что меня читают люди, использующие всякие разнообразные СУБД.
В связи с этим у меня есть такой хитрый вопрос, связанный с использованием bind-параметров в запросах: насколько распространена среди разных серверов (а так же клиентских либ и компонентов доступа) такая фича, что при парсинге запроса он возвращает список параметров и их типы?

Дело в том, что более-менее напрямую я использую только Firebird и он после prepare возвращает информацию о используемых параметрах и их типах (когда-то в версии 1.5.х, что ли, его плющило на тему вывода типов, но давно было, вроде исправили и вообще я уже забыл что там было).

Т.е. если мы представим селект как функцию вроде select :: p0 -> p1 -> p2 -> ... -> [(f0,f1,...)] то Firebird выводит тип этой функции из текста запроса и информации о таблицах. Это невероятно удобно, т.к. позволяет использовать SQL запрос+пару таблиц с дополнительными метаданными в качестве DSL для описания достаточно большого класса отчетов, покрывающего 90% всех потребностей в опердени. Т.е я из списка параметров и таблицы типа (параметр, юзеровское имя, справочник, формат) генерю UI для ввода этих самых параметров, а из типа результата запроса дельфи автоматом заполняет всю метаинформацию для DBGrid.

Из других СУБД я использую MSSQL и Sqlite, но через ADO.NET, в котором параметры, судя по всему, принципиально не заполняются автоматически и их нужно вносить в DbCommand или SqlCommand вручную. Т.е. я не знаю, умеет ли сервер это делать вообще. Это выбешивает просто невероятно, т.к. работы становится в несколько раз больше. Я уже подумываю написать собственный парсер запросов или вообще DSL с выводом типов и генерацией SQL запросов для описания запросов/датасетов, чтобы не заниматься этой многословной хренью.

PostgreSQL заполняет bind-параметры после prepare, но непонятно кто это делает - сервер, клиентская либа или компоненты доступа. И на сервер он гонит запросы плейн-текстом, т.е. запросто может оказаться что подстановка вообще делается клиентской либой в лоб, без всякого вывода типов.

А как вообще принято эти параметры заполнять и кто это делает - сервер, клиентская либа, компоненты доступа или вообще вручную по жизни?

[identity profile] zamotivator.livejournal.com 2010-03-17 08:44 pm (UTC)(link)
erlang + epgsql + postgresql + /dev/hands
dataGroups(Conn,[SortIndex,SortDir,From,To]) ->
    {ok, Types, Names, Rows} =
	dbaccess:process_query(
	  Conn,
	  "SELECT group_id as id, group_name as name, count(*) as count
           FROM object_info
           JOIN object_group on object_info.group_id = object_group.id
           GROUP BY group_id,group_name" ++ dbaccess:remote_table(SortIndex,SortDir,From,To),[]),
    {ok, data, Types, Names, Rows}.
Edited 2010-03-17 20:45 (UTC)

[identity profile] rssh.livejournal.com 2010-03-17 08:44 pm (UTC)(link)
1. Так как в Jdbc есть функция getResultSetMetainfo(), то все БД, поддерживающие jdbc это так или иначе умеют типизировать результаты запросов

2. С параметрами сложнее. В общем случае - не знаю; в postgresql есть pQdescribePrepared http://www.postgresql.org/docs/8.4/interactive/libpq-exec.html#LIBPQ-EXEC-MAIN (И кстати запросы он на чсервер отадет по разному в зависимотси от вресии протокола)

// кстати - а когда надо знать именно выведенный тип параметров ?
Кажись наоборот - ты же их (параметры) даешь всегда.

[identity profile] enternet.livejournal.com 2010-03-17 09:01 pm (UTC)(link)
Наврядли возможно дать точный ответ. mssql тупо подставляет null при подготовке запроса. Т.е. раз сам сервер не выводит типы параметров, то думаю и клиенту рассчитывать не на что. С другой стороны, чтобы дать полную гарантию нужно тщательно изучить возможности нового и старого протоколов и клиентских библиотек. Я думаю что никто не будет этим заниматься.

[identity profile] ennor.livejournal.com 2010-03-17 09:24 pm (UTC)(link)
В MSSQL этим занимается DAL, но как я понял, разные провайдеры доступа работают по-разному. В случае использования ODBC или SQL Native Client (MSDASQL и SQLNCLI, соответственно) действительно приходится вызывать .Parameters.Add() ручками столько раз, сколько надо. Если же заюзать OLEDB Provider for MS SQL Server (SQLOLEDB кажется, не ручаюсь за точность), то сразу при скармливании ему текста запроса он отсылает его на сервер и получает в ответ метаданные (точно приходят параметры, возможно .Fields() тоже заполняется).

Точнее не опишу, действительно очень давно последний раз писал какой-либо код по эту сторону СУБД.

[identity profile] dmitry-vk.livejournal.com 2010-03-18 01:54 am (UTC)(link)
sqlite позволяет определить число и имена параметров у подготовленного запроса (см. http://sqlite.org/c3ref/bind_parameter_count.html, http://sqlite.org/c3ref/bind_parameter_name.html). По понятным причинам (динамическая типизация sqlite'а) вывода типов параметров нет.

[identity profile] molnij.livejournal.com 2010-03-18 04:43 am (UTC)(link)
Oracle + ODAC
возвращает, кто из них - точно не знаю, но учитывая, что для этого идёт отправка на сервер, видимо все-таки сервер.

[identity profile] blacklion.livejournal.com 2010-03-18 08:48 am (UTC)(link)
SQLite вообще ничего не знает про типы :)