На этой консультации, мы изучим механику использования ODBC API.
  Ваша программа не общается непосредственно с драйверами ODBC, она пользуется услугами менеджера ODBC. Управление работой менеджера осуществляется с помощью API функций к которым вы можете обращатся непосредственно из своей программы, вы должны только подключить odbc32.inc и odbc32.lib, а так же windows.inc.
  Шаги которые необходимо предпринять для соединения с базой данных следующие:
  Когда вы закончите работу с базой данных, вы должны закрыть связь с ней следующим образом:
ВЫДЕЛЕНИЕ ПАМЯТИ ДЛЯ ИДЕНТИФИКАТОРА
  В версиях ODBC до 3.x, вам нужно вызывать отдельные функции, чтобы выделить память для идентификатора окружения, соединения иинструкции (SQLAllocEnv, SQLAllocConnect, SQLAllocStmt). Теперь под ODBC 3.x все функции заменяются SQLAllocHandle, которая имеет следующий синтаксис:
SQLRETURN SQLAllocHandle(SQLSMALLINT HandleType,
SQLHANDLE InputHandle,
SQLHANDLE * OutputHandlePtr
);
  Вышеуказанный синтаксис может утомить ваш взор, поэтому мы его немного упростим.
SQLAllocHandle proto HandleType:DWORD,
InputHandle:DWORD,
OutputHandlePtr:DWORD
  SQLRETURN определен как тип SQLSMALLINT, SQLSMALLINT определен как короткое целое, т.e. слово (16 бит). Таким образом функция возвращает выходную величину в ax, а не в eax, что является очень важным. Однако параметр передаётся функции под Win32 в 32-битном стеке. Поэтому, даже если параметр определён как словный (16-бит) вы должны его расширить до 32-бит. Вот почему HandleType - dword вместо word. Вы можете cвериться с библиотекой импорта: odbc32.lib. Вход для SQLAllocHandleэто _SQLAllocHandle@12. Эта запись означает, что комбинированный размер параметров составляет 12 байт (3 слова). Тем не менее, это не означает, что функциональный прототип C - неверный. SQLAllocHandle будет только использовать младшее слово HandleTypeи игнорировать старшее слово. Таким образом функциональный прототип C - корректен пока наш asm-функциональный прототип соответствует сказанному выше.
  С типом SQL разберёмся более обстоятельно. Рассмотрим входные функциональные параметры и обратную величину.
SQL_HANDLE_ENV идентификатор окружения SQL_HANDLE_DBC идентификатор соединения SQL_HANDLE_STMT идентификатор запроса SQL_HANDLE_DESC идентификатор дескриптора
Дескриптор - это коллекция метаданных, которые описывают параметры инструкций SQL или столбцов с набором результатов, которые обрабатываются приложением или драйвером.
  Возможные возвращаемые значения SQLAllocHandle могут быть:
 
| SQL_SUCCESS | Функция завершена успешно |
| SQL_SUCCESS_WITH_INFO | Функция завершена успешно, но с предупреждением |
| SQL_ERROR | Функция потерпела неудачу. |
| SQL_INVALID_HANDLE | Идентификатор переданный функции, недействителен |
  Выполнилась ли функция успешно или потерпела неудачу, вы можете получить подробную информацию относительно этого, вызывая SQLGetDiagRecили SQLGetDiagField. Они играют ту же самую роль, что и GetLastError в Win32 API.
  Пример:
.data?
hEnv dd ?
.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
ВЫБОР ВЕРСИИ ODBC
  После выделения памяти для идентификатора окружения вы должны установить атрибут окружения, SQL_ATTR_ODBC_VERSION, в соответствующее значение. Установка значения атрибута окружения делается, вызовом SQLSetEnvAttr. К настоящему времени вы должны знать, что имеются также функции SQLSetConnectAttr и SQLSetStmtAttr. SQLSetEnvAttr определена как:
SQLSetEnvAttr proto EnvironmentHandle:DWORD,
Attribute:DWORD,
ValuePtr:DWORD,
StringLength:DWORD
  Список возможных возвращаемых значений идентичен SQLAllocHandle.
  Пример:
.data?
hEnv dd ?
.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLSetEnvAttr, hEnv, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, NULL
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
ВЫДЕЛЕНИЕ ПАМЯТИ ДЛЯ ИДЕНТИФИКАТОРА ПОДКЛЮЧЕНИЯ
  Этот шаг подобен выделению памяти для ид. окружения, вы также вызываете SQLAllocHandle, но передаёте другое значение параметра.
  Пример:
.data?
hEnv dd ?
hConn dd ?
.code
invoke SQLAllocHandle, SQL_HANDLE_ENV, SQL_HANDLE_NULL, addr hEnv
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLSetEnvAttr, hEnv, SQL_ATTR_ODBC_VERSION, SQL_OV_ODBC3, NULL
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
invoke SQLAllocHandle, SQL_HANDLE_DBC, hEnv, addr hConn
.if ax==SQL_SUCCESS || ax==SQL_SUCCESS_WITH_INFO
УСТАНОВКА СВЯЗИ
  Теперь мы готовы сделать попытку фактического подключения к источнику данных через выбранный ODBC драйвер. Имеются фактически три функции ODBC, которые мы можем использовать, чтобы достичь этой цели. Они предлагают различную степень "выбора", который вы можете сделать.
 
| SQLConnect | Ядро | Это - самая простая функция. Требуется только DSN (название источника Данных) и необязательное название пользователя и пароль. Она не предлагает интерфейса GUI типа подсказки пользователю в виде диалого окна для получения дополнительной информации. Вы должны использовать эту функцию, если вы уже имеете DSN для заданной базы данных. |
| SQLDriverConnect | Ядро | Эта функция предлагает более широкий спектр услуг чем SQLConnect. Вы можете соединяться с источником данных, который не определен в системной информации, то есть без DNS. Кроме того, вы можете определить, отобразит ли эта функция диалоговое окно, запрашивающее пользователя для получения дополнительной информации. Например, если вы опустили имя файла базы данных, она будет инструктировать ODBC драйвер об отображении диалогового окна, запрашивающего пользователя выбрать базу данных, для соединения с ней. |
| SQLBrowseConnect | Уровень 1 | Эта функция предлагает перечисление источников данных во время выполнения. Она обеспечивает более гибкий интерфейс в сравнении с SQLDriverConnect, потому что вы можете вызывать SQLBrowseConnect неско раз последовательно, каждый раз запрашивая пользователя для получения более конкретной информации, пока наконец вы не получите рабочую строку подключения. |
  Я буду исследовать сначала SQLConnect. Чтобы использовать SQLConnect, вы должны знать кое-что относительно DSN. DSN расшифровывается как Название Источника Данных, т.е. это строка, которая уникально идентифицирует источник данных. DSN идентифицирует строение данных, которое содержит информацию о том, как соединиться с удельным источником данных. Информация включает и то, какой ODBC-драйвер использовать и с какой базой данных соединиться. Вы создаете, изменяете и удаляете DSN, используя 32-разрядного ODBC Администратора в панели управления.
  SQLConnect имеет следующий синтаксис:
SQLConnect proto ConnectionHandle:DWORD
pDSN:DWORD,
DSNLength:DWORD,
pUserName:DWORD,
NameLength:DWORD,
pPassword:DWORD,
PasswordLength:DWORD
  По минимуму, SQLConnect требует идентификатор соединения, DSN и их длинну: имя пользователя и пароль необязательны, если источник данных не требует их. Список возможных возвращаемых значений идентичен таковому SQLAllocHandle. Предположим мы имеем DSN называемый "Продажи" в нашей системе, и мы хотим соединиться с ним. Мы можем сделать это следующим образом:
.data
DSN db "Sales",0
.code
......
invoke SQLConnect, hConn, addr DSN, sizeof DSN,0,0,0,0
  Один из недостатоков SQLConnect - то, что, вы должны создать DSN прежде, чем сможете соединяться с источником данных. SQLDriverConnect предлагает более гибкий вариант. Она имеет следующий синтаксис:
SQLDriverConnect proto ConnectionHandle:DWORD,
hWnd:DWORD,
pInConnectString:DWORD,
InStringLength:DWORD,
pOutConnectString:DWORD,
OutBufferSize:DWORD,
pOutConnectStringLength:DWORD,
DriverCompletion:DWORD
SQL_DRIVER_PROMPT ODBC драйвер запрашивает пользователя относительно информации. Эта информация используется для создания строки подключения. SQL_DRIVER_COMPLETE
SQL_DRIVER_COMPLETE_REQUIREDODBC драйвер запросит пользователя только, если строка подключения, составленная в вашей программе не закончена. SQL_DRIVER_NOPROMPT ODBC драйвер не будет запрашивать пользователя для получения дополнительной информации.
  Пример:
.data
strConnect db "DBQ=c:\data\test.mdb;DRIVER={Microsoft Access Driver (*.mdb)};",0
.data?
buffer db 1024 dup(?)
OutStringLength dd ?
.code
.....
invoke SQLDriverConnect, hConn, hWnd, addr strConnect, sizeof strConnect,
addr buffer, sizeof buffer, addr OutBufferLength, SQL_DRIVER_COMPLETE
РАЗЪЕДИНЕНИЕ С ИСТОЧНИКОМ ДАННЫХ
  После того, как подключение сделано успешно, вы можете создать одну или большее количество инструкций и сделать запрос источнику данных. Я буду исследовать эту часть на следующей консультации. Пока, давайте предположим, что вы уже отработали с источником данных, и должны разъединится с ним, вызывая SQLDisconnect. Эта функция проста (Это отражение грубой и грустной действительности о том, что разрушение - намного проще чем конструкция или созидание). Требуется только один параметр, маркер подключения.
invoke SQLDisconnect, hConn
УДАЛЕНИЕ ИДЕНТИФИКАТОРОВ ПОДКЛЮЧЕНИЯ И СРЕДЫ
  После успешного разъединения вы можете уничтожить идентификаторы подключения и среды, вызывая SQLFreeHandle. Это - новая функция, вводимая в ODBC 3.x., она заменяет SQLFreeConnect, SQLFreeEnvи SQLFreeStmt. SQLFreeHandle имеет следующий синтаксис:
SQLFreeHandle proto HandleType:DWORD, Handle:DWORD
  Например:
invoke SQLFreeHandle, SQL_HANDLE_DBC, hConn invoke SQLFreeHandle, SQL_HANDLE_ENV, hEnv
[C] Iczelion, пер. SheSan