Доступ к таблицам данных и их модификация с помощью IDAPI (обзор функций)
ВВЕДЕНИЕ
Приход эры клиент-серверной технологии ставит перед разработчиками прикладного программного обеспечения (ПО) нелегкие вопросы: как с минимальными затратами перейти на новую технологию, как максимально сохранить собственные наработки, как обеспечить независимость ПО от источника данных. От того как (и главное чем) крупные производители средств разработки ответят на эти насущные вопросы зависит их популярность, и их успех.
Фирма Borland предлагает богатый выбор продуктов, которые могут использоваться разработчиками прикладного ПО для создания клиентской части в клиент-серверных приложениях: dBase for Windows 5.0, Paradox for Windows 5.0, C++ 4.5 with Database Tools, Delphi95. Все из перечисленных продуктов базируются на едином интерфейсе доступа к источникам данных - IDAPI.
IDAPI (Intergrated Database API) - это технология унифицированного, прозрачного доступа к источникам данных различных форматов, от локальных БД до SQL серверов. Говоря проще, IDAPI - это набор функций, позволяющий строить приложения, не зависящие от формата данных. Кроме этого, IDAPI - это средство масштабирования приложений, предоставляющие разработчикам возможность перейти к современной технологии клиент-сервер.
Базируя новые версии старых, хорошо зарекомендовавших себя персональных СУБД, на технологии IDAPI, фирма Borland пытается поддержать разработчиков на нелегком пути в клиент-серверный мир.
КРАТКАЯ ХАРАКТЕРИСТИКА ТЕХНОЛОГИИ
IDAPI делает упор на навигационый доступ к данным, который реализован в виде курсорной модели. Курсорная модель IDAPI означает:
возможность перемещения в обоих направлениях по набору данных;
упорядочивание данных по индексу;
нахождение записи по индексу;
возможность запомнить текущее положение курсора и вернуться к нему (механизм закладок);
связывание курсоров, для организации отношений типа “один-к-одному” или “один-ко-многим”;
фильтрация данных по критерию;
и многое другое.
Навигационный доступ предоставляет большие возможности, но разработчики IDAPI не забыли и о доступе, основанном на запросах. IDAPI позволяет выполнять SQL и QBE запросы, и если запрос возвращает результат, то приложение получит курсор, указывающий на него. Технология предлагает разработчику смешивать оба типа доступа для построения наиболее эффективных приложений.
IDAPI представляет единый набор функций для доступа как к dBase, Paradox таблицам, так и к SQL серверам (Informix, Interbase, Oracle, Sybase/MS SQL server). Такая концепция реализована через архитектуру, основанную на драйверах. Это позволяет, например, использовать курсор при организации browser для Interbase таблицы или выполнить SQL запрос к локальным dBase данным. Технология IDAPI предусматривает возможность подключения как родных IDAPI драйверов, так и ODBC драйверов, что значительно расширяет границы применения IDAPI.
Реализация технологии
В настоящий момент технология IDAPI реализована для Windows 3.1 и входит в состав dBase 5.0 for Windows, Paradox 5.0 for Windows, Delphi. Кроме этого реализация IDAPI поставляется в виде отдельного пакета: Borland Database Engine (BDE) 2.0. В дальнейшем рассказ о технологии IDAPI будет основываться на ее в реализации BDE 2.0, поэтому термины IDAPI и BDE можно в дальнейшем рассматривать как синонимы.
BDE 2.0 - это полный набор высокопроизводительных средств разработчика, предназначенный для создания приложений управления базами данных в среде Windows. BDE состоит из следующих компонент:
более 150 функций доступа и управления БД (собственно IDAPI), помещенные в Windows DLL;
ядро запросов, поддерживающее как SQL, так и QBE:
три стандартных драйвера для доступа к Paradox, dBase, данным в текстовом формате;
модуль высокопроизводительного доступа к SQL серверам через IDAPI драйверы;
ODBC модуль (IDAPTER), предоставляющий доступ к источникам данных через ODBC драйвер;
50 встроенных языковых драйверов, включая 3 драйвера с кириллицей;
Borland Database Desktop 5.0 - Windows приложение, которое позволяет интерактивно управлять БД;
примеры использования IDAPI для языков программирования С и Паскаль.
Отдельно поставляется пакет IDAPI драйверов (Borland SQL Links 2.0 for Windows), которые обеспечивают доступ к данным на Informix, InterBase, Oracle, Sybase/MS SQL серверах. Каждый драйвер оптимизирован к под конкретные особенности SQL сервера.
Следует понимать, что в состав что BDE не входят средства создания пользовательского интерфейса (формы, отчеты).
АЛГОРИТМ ДОСТУПА К ДАННЫМ
Цель настоящей статьи познакомить с новым продуктом и дать краткое стартовое руководство разработчикам, начинающим использовать IDAPI. Статья построена в виде краткого, не претендующего на полноту, обзора функций IDAPI.
Обзор основных возможностей IDAPI построен как рассмотрение/демонстрация основных шагов, которые выполняет приложение, получая доступ к данным и модифицируя их.
Алгоритм любого приложения, управляющего БД с помощью IDAPI, может быть схематически представлен следующей таблицей:
Шаг
Действие
IDAPI функция
Подготовка
Инициализация database engine
DbiInit
Подготовка
Открытие БД
DbiOpenDataBase
Подготовка
Открытие таблицы и получение курсора
DbiOpenTable
Подготовка
Получение информации о курсоре
DbiGetCursorProps
Подготовка
Резервирование памяти для буфера записи
по усмотрению разработчика (malloc, calloc, new)
Подготовка
Получение информации о дескрипторах полей
DbiGetFieldDescs
Чтение
Позиционирование курсора и считывание записи в буфер
DbiGetNextRecord
Чтение
Считывание некоторого поля записи из буфера
DbiGetField
Обновление
Обновление поля и запись его обратно в буфер
DbiPutField
Обновление
Обновление таблицы новой записью
DbiModifyRecord
Завершение
Закрытие курсора
DbiCloseCursor
Завершение
Закрытие БД
DbiCloseDatabase
Завершение
Закрытие database engine
DbiExit
Рассмотрим теперь каждый шаг подробно.
ПОДГОТОВКА ДОСТУПА К ДАННЫМ
Все основные настройки IDAPI хранятся в специальном конфигурационном файле. Такой способ обеспечивает дополнительную мобильность приложений. При переносе в другую среду не требуется менять само приложение достаточно настроить конфигурационный файл.
Конфигурационный файл (обычно IDAPI.CFG) содержит описание и настройки всех доступных драйверов, настройки IDAPI и описание определяемых пользователем алиасов.
Алиас - это ссылка на конкретную БД по короткому имени. Использование алисов позволяет легко менять местоположение и тип рабочей БД. Помимо местоположения БД алиас содержит тип и настройки драйвера, который используется для доступа к данным.
ИНИЦИАЛИЗАЦИЯ IDAPI
На первом шаге приложение всегда вызывает функцию DbiInit, которая инициализирует IDAPI. Приложение может передать функции DbiInit указатель на структуру DBIEnv, которая содержит начальные установки: рабочую директорию, язык на котором будут выдаваться сообщения об ошибках, имя пользователя, полное имя конфигурационного файла. Но если этот указатель равен NULL, то IDAPI будет использовать настройки по умолчанию, а конфигурационный файл (IDAPI.CFG) будет искаться в следующей последовательности:
Преверяется константа CONFIGFILE01 в секции [IDAPI] файла WIN.INI:
Проверяется стартовая директория;
Если конфигурационный файл не найден, то IDAPI использует настройки по-умолчанию, при этом доступ к SQL серверам не возможен.
ПРИМЕР
rslt=DbiInit(NULL);
Кроме инициализации вызов DbiInit открывает новую сессию. Сессию позволяет изолировать операции доступа к БД без необходимости запускать новую копию приложения. Все дальнейшие действия приложения будут происходит внутри контекста сессии. С точки зрения базы данных, каждая сессия выглядит для нее как отдельный пользователь. К примеру, запросы на блокировку из одной сессии конфликтуют с блокировкой, установленной другой сессией даже в том случае, когда обе сессии принадлежат одному и тому же клиенту. Сессии - это способ полностью изолировать одно действие с базой данных от другого.
Перед тем, как действие с БД будет выполнено в рамках сессии, должна быть открыта одна или более БД. Сессия может одновременно иметь любое количество открытых БД. Каждая сессия может быть настроена независимо в отношении таких вещей, как Call-back-функции, языки для сообщения об ошибках, формат данных и т.д.
ОТКРЫТИЕ БАЗЫ ДАННЫХ
После успешной инициализации IDAPI, приложение открывает базу данных (БД) вызовом функции DbiOpenDatabase. Успешный вызов этой функции возвращает идентификатор БД, который затем используется в большинстве других функций IDAPI. Для подключения к SQL БД вызов функции DbiOpenDatabase должен содержать имя пользователя и пароль.
Следующий пример демонстрирует открытие стандартной БД (Paradox, dBASE, ASCII), помещая нулевой указатель вместо имени БД и ее типа.
rslt=DbiOpenDatabase(NULL, NULL, dbiREADWRITE, dbbiOPENSHARED, NULL, 0, NULL, NULL, &hDb);
Для того чтобы изменить текущую директорию для стандартной БД используется функция DbiSetDirectory
rslt=DbiSetDirectory(hDb, “C:\DATA”);
При открытии SQL БД удобно задавать имя БД, ее местоположение и и настройки IDAPI в алиасе.
Следующий пример открывает именованную БД на SQL сервере.
rslt=DbiOpenDatabase(“myalias”, NULL, dbiREADWRITE, dbiOPENSHARED, “mypassword”, 0, NULL, NULL. &hDb);
ОТКРЫТИЕ ТАБЛИЦЫ ДАННЫХ
После открытия БД приложение открывает таблицу вызовом DbiOpenTable . Входными параметрами для этого вызова являются: имя таблицы, тип драйвера, индекс (по которому будут отсортированы записи), права доступа, способ преобразования данных. В случае успешного выполнения DbiOpenTablе возвращает идентификатор курсора открытой таблицы. В IDAPI курсор - это основное средство доступа к данным. Получить идентификатор курсора означает получить доступ к данным.
Следующий пример открывает Paradox таблицу “MyTable”:
DbiOpenTable(hDb, “MyTable”, szPARADOX, NULL, NULL, 0, dbiREADWRITE, dbiOPENSHARED, xltFIELD, 0, NULL, &hCursor);
Посмотрим повнимательнее на входные параметры вызова DbiOpenTable.
ИМЯ ТАБЛИЦЫ И ТИП ДРАЙВЕРА
Имя таблицы и типа драйвера тесно связаны между собой (PARADOX - “.DB”, dBASE - “.DBF”, ASCIIDRV - “.TXT”). Поэтому тип драйвера может быть опущен, если приложение указывает полное имя таблицы данных в формате Paradox или dBase. Однако если имя таблицы не включает расширение, то тип драйвера должен указывается явно.
Если имя не включает в себя путь, то по умолчанию берется текущая директория БД.
В случае SQL таблицы тип драйвера в вызове DbiOpenTable игнорируется, поскольку требуемый SQL драйвер уже был выбран в момент открытия БД.
СПОСОБ ПРЕОБРАЗОВАНИЯ ДАННЫХ
В IDAPI определены свои типы данных (логические типы), которые могут отличаться от родных типов БД. При выборках полей из таблицы IDAPI может осуществлять преобразование данных из родных типов в логические типы IDAPI. Открывая таблицу, приложение должно указать: выполнять преобразование (xltFIELD способ преобразование) или нет (xltNONE способ преобразование).
Логические типы IDAPI совместимы с типами данных языка С. В частности, поэтому рекомендуется использовать преобразование, хотя приложение может и отключить его. Данная опция действует только при чтении/записи полей функциями DbiGetField и DbiPutField.
ПРАВА ДОСТУПА
Под правами доступа подразумевается право на запись (параметр eOpenMode) и право владения данными (параметр eShareMode): общее или исключительное.
Права доступа к данным задаются в трех ключевых местах (перечислены в порядке убывания приоритета):
Опция OPEN MODE в файле конфигурации IDAPI.CFG
Входные параметры eOpenMode и eShareMode в функции открытия БД DbiOpenDatabase.
Входные параметры eOpenMode и eShareMode в функции открытия таблицы DbiOpenTable.
Как видно, права доступа, указанные в вызове DbiOpenDatabase, имеют больший приоритет, чем при вызове DbiOpenTable. Например, если БД была открыта только для чтения, то никакая таблица в этой БД не может быть открыта для записи. Для того, чтобы таблица могла быть открыта для записи, необходимо чтобы соответствующая БД была открыта для записи.
Аналогичное правило действует и для параметра eShareMode, определяющего будет ли доступ к данным разделяемым или исключительным.
ПОЛУЧЕНИЕ ИНФОРМАЦИИ О СВОЙСТВАХ КУРСОРА.
Открыв таблицу и получив идентификатор курсора, приложение может получить полную информацию об открытой таблице. Для этого приложение вызывает функцию DbiGetCursorProps c идентификатором курсора в качестве входного параметра. Вызов DbiGetCursorProps обычно следует сразу за вызовом DbiOpenTable.
Вызов функции DbiGetCursorProps заполняет структуру CURProps, которая содержит следующую информацию о курсоре (таблице):
структура таблицы (имя, количество полей, количество проверок правильности значений, количество проверок целостности, и др.);
особенности работы IDAPI с данной таблицей (логическая длина записи, физическая длина записи, размер буфера для ключа, способ трансляции данных, имя языкового драйвера, количество используемых фильтров, тип курсора, и др.)
Полную информацию о полях открытой таблицы, дает вызов DbiGetFieldDescs. Дескрипторы полей таблицы дают полную информацию для доступа к каждому полю внутри буфера записи. Он заполняет структуру типа FLDDesc, содержащих следующую информацию: номер поля, имя поля, тип поля, количество символов или единиц, смещение в записи, длина в байтах, и др.
ПОДГОТОВКА БУФЕРА ЗАПИСИ
Операции обмена информацией происходят в IDAPI через буфер записи, поэтому перед тем, как использовать курсор для доступа к данным в таблице, необходимо подготовить этот буфер. Подготовка буфера записи включает в себя резервирование памяти и в некоторых случаях ее инициализацию.
Инициализацию буфера записи необходимо выполнить перед тем, как вставить в таблицу новую запись. Инициализацию буфера осуществляет функция DbiInitRecord. Эта функция корректно инициализирует запись пустыми полями в соответствии с их типом. Для таблиц в формате Paradox функция DbiInitRecord использует при инициализации значения по умолчанию (если последние указаны в таблице).
ПРИМЕР
Следующий пример демонстрирует то, как получить информацию о свойствах курсора, зарезервировать память для буфера записи и массива дескрипторов полей и получить сами дескрипторы.
DBIResult rslt;
pCHAR pRecBuf;
CURProps curProps;
pFLDDesc pFldArray;
rslt=DbiGetCursorProps(hCursor, &curProps);
if (rslt==DBIERR_NONE)
{
pRecBuf = malloc(curProps.iRecBufSize);
pFldArray = (pFLDDesc) malloc(sizeof(FLDDesc) * curProps.iFields);
rslt = DbiGetFieldDescs(hCursor, pFldArray);
.}
ПОЗИЦИОНИРОВАНИЕ КУРСОРА И ВЫБОРКА ЗАПИСЕЙ
Одна из сильных сторон технологии IDAPI - это реализация навигационных возможностей. Для этой цели предусмотрены как функции, выполняющие только позиционирование, так и функции, осуществляющие одновременно и позиционирование и выборку записи в буфер.
ПОЗИЦИОНИРОВАНИЕ КУРСОРА В ПРОМЕЖУТОК МЕЖДУ ЗАПИСЯМИ.
В IDAPI предусмотрены функции, которые позиционируют курсор в промежуток между записями: перед первой записью, в начале файла (DbiSetToBegin); в конце файла (DbiSetToEnd); перед первой записью с заданным значением ключа (DbiSetToKey).
Позиционирование курсора в промежуток между записями может значительно упростить программирование. Например, вызовом функции DbiSetToBegin Вы позиционируете курсор перед первой записью в таблице. Затем Вы можете организовать цикл обработки всех записей в таблице с помощью функции DbiGetNextRecord. (А если бы курсор был позиционирован на первую запись, то циклический вызов функции DbiGetNextRecord пропустил первую запись.)
ПОЗИЦИОНИРОВАНИЕ КУРСОРА НА ЗАПИСЬ И ВЫБОРКА ЗАПИСИ. Кроме функций, позиционирующих курсор в промежуток между записями, в IDAPI содержатся функции, которые указывают непосредственно на запись. Если приложение подготовило буфер записи, то эти функции могут также осуществлять выборку данных. Большинство таких функций позволяют заблокировать запись от доступа другими приложениями. Запись будет оставаться заблокированной до тех пор пока приложение явно не позаботиться об этом или до конца сессии. Ниже приведено краткое описание этих функций.
DbiGetRecord
выборка записи (возвращает код ошибки, если курсор позиционирован в промежуток между записями).
DbiGetNextRecord
позиционирует курсор на следующую запись и осуществляет выборку этой записи.
DbiGetPriorRecord
позиционирует курсор на предыдущую запись и осуществляет выборку этой записи.
DbiGetRelativeRecord
позиционирует курсор на запись, положение которой задается как смещение (положительное или отрицательное) относительно текущего положения курсора и осуществляет выборку этой записи.
DbiGetRecordForKey
позиционирует курсор на запись по заданному ключу и осуществляет выборку этой записи.
ПРИМЕР
В следующий примере курсор устанавливается на начало файла, и затем осуществляется просмотр всей таблицы:
DbiSetToBegin(hCursor);
while(DbiGetNextRecord(hCursor, dbiNOLOCK, pRecBuf, NULL) == DBIERR_NONE)
{
. . .
}
ПОЗИЦИОНИРОВАНИЕ КУРСОРА С ПОМОЩЬЮ ЗАКЛАДОК
При перемещении по таблицам удобно пометить некоторое положение курсора, с тем чтобы в дальнейшем к нему вернуться. Реализацию такой возможности предоставляют закладки.
Закладка это некоторое положение курсора, которое хранится в буфере закладки во внутреннем представлении. Буфер закладки всегда резервируется самим приложением, поэтому количество закладок в принципе не ограничено. IDAPI позволяет сравнить одну закладку с другой и выяснить их относительное положение.
Не для всех типов данных IDAPI гарантирует точный возврат к закладке. Правильный возврат курсора гарантируется только в том случае, если закладка является стабильной. Если закладка не стабильная, то другое приложение, модифицируя таблицу, может изменить настройку закладки.
Необходимую информацию для организации закладки (стабильность закладки, размер буфера, необходимого для хранения закладки) содержит структура CURProps, которую заполняет вызов DbiGetCursorProps (см. ПОЛУЧЕНИЕ ИНФОРМАЦИИ О СВОЙСТВАХ КУРСОРА). Структура CURProps содержит следующие поля, описывающие свойства закладок:
iBookMarkSize
Длина буфера необходимого для хранения одной закладки. Память под буфер всегда резервирует приложение. Размер буфера может измениться после переключения на другой активный индекс (после вызова DbiSwitchToIndex)!
bBookMarkStable
равен TRUE, если курсор поддерживает стабильность закладок
FALSE в противном случае
Стабильность закладок зависит от типа драйвера следующим образом:
dBASE
закладки всегда стабильны
Paradox
закладки стабильны только, если таблица имеет первичный ключ
SQL
закладки стабильны только, если таблица имеет уникальный индекс
ДОБАВЛЕНИЕ, ОБНОВЛЕНИЕ И УДАЛЕНИЕ ЗАПИСЕЙ
Прежде всего, для того чтобы добавить, модифицировать или удалить запись, надо быть уверенным в том, что:
курсор, связанный с таблицей, имеет права записи;
запись не заблокирована другим пользователем.
Кроме того, если приложение собирается модифицировать некоторую запись, оно может заблокировать эту запись, используя функции выборки. Запись останется заблокированной, пока приложение явно не снимет блокировку, или пока не будет закрыта текущая сессия.
ДОБАВЛЕНИЕ ЗАПИСИ
Для того, чтобы добавить новую запись в таблицу, приложение должно выполнить следующие шаги:
Создать пустую запись в буфере записи вызовом функции DbiInitRecord.
Проинициализировать поля создаваемой записи в буфере записи (еще не в таблице) с помощью функции DbiPutField.
Записать содержимое буфера записи в таблицу, используя функции DbiAppendRecord (добавление новой записи в конец таблицы) или DbiInsertRecord (вставка новой записи в таблицу). При использовании функции DbiInsertRecord приложение может заблокировать вставляемую запись.
ОБНОВЛЕНИЕ ЗАПИСИ
Модификация существующей записи осуществляется следующим образом:
Прочитать требуемую запись в буфер записи (установив блокировку, если требуется).
Изменить содержимое обновлямых полей в буфере записи с помощью функции DbiPutField.
Записать содержимое буфера записи в таблицу, используя функцию DbiModifyRecord. Приложение должно указать будет ли снята блокировка с записи после завершения DbiModifyRecord или нет.
УДАЛЕНИЕ ЗАПИСИ
Удаление существующей записи происходит следующим образом:
Установить курсор на удаляемую запись.
Удалить запись с помощью функции DbiDeleteRecord. Если приложение имеет буфер записи, то удаленная запись будет скопирована в буфер.
После удаления записи курсор указывает на промежуток между записями, которые находились вокруг удаленной.
Удаление записей имеет некоторые особенности для разных форматов данных. Для таблиц в формате dBASE удаленная запись не уничтожается в таблице до тех пор, пока приложение не вызовет функцию DbiPackTable.
Из таблицы в формате Paradox нельзя удалить запись, если это может привести к нарушению целостности межтабличных связей. Например, если курсор в главной таблице указывает на запись, которая содержит значения, связанные с подчиненной таблицей, то вызов DbiDeleteRecord закончится неудачей и положение курсора не изменится.
ОПЕРАЦИИ С НЕСКОЛЬКИМИ ЗАПИСЯМИ
IDAPI предоставляет две функции для добавления, обновления и удаления сразу нескольких записей: DbiBatchMove и DbiWriteBlock.
Функция DbiBatchMove может использоваться для добавления, обновления и выделения записей из одной таблицы в другую. Причем исходная таблица и таблица получатель могут быть разных типов. Имеется возможность скопировать таблицу одного типа в новую таблицу другого типа.
Функция DbiBatchMove также может использоваться с текстовым драйвером для импорта и экспорта данных из/в любой другой поддерживаемый формат.
РАБОТА С BLOB ПОЛЯМИ
Под термином BLOB поле (большой двоичный обьект) обычно понимают большой массив информации (например изображение, звук ,...), находящийся в некотором поле записи. IDAPI предоставляет специальные средства для работы с BLOB полями.
Для выборки записей, содержащих BLOB поля, разработчик должен использовать те же вызовы, что и для обычных записей. А для обработки самих BLOB'ов IDAPI предоставляет ряд специальных функций ( DbiOpenBlob, DbiGetBlob, и др.). Рассмотрим основные моменты работы с BLOB полями.
ОТКРЫТИЕ BLOB ПОЛЯ
Перед любым действием с BLOB полем приложение должно открыть BLOB поле. Для этого приложение вызывает функцию DbiOpenBlob и передает в качестве входных параметров идентификатор курсора, указатель на буфер записи, порядковый номер BLOB поля в записи и права доступа. Функция DbiOpenBlob поместит идентификатор открытого BLOB поля в буфер записи. Только после успешного вызова функции DbiOpenBlob приложение может использовать другие функции, работающие с BLOB поле.
Перед открытием BLOB поля для чтения/записи рекомендуется блокировать запись. Это гарантирует отсутствие проблем в том случае, если другое приложение попытается изменить ту же самую запись.
ЧТЕНИЕ ДАННЫХ ИЗ BLOB ПОЛЕЙ
Открыв BLOB поле и получив его идентификатор, приложение может определить размер BLOB поля с помощью вызова DbiGetBlobSize и затем прочитать данные (DbiGetBlob). Функция DbiGetBlob (чтения данных из BLOB поля) позволяет прочитать любую часть BLOB поля. Для этого приложение указывает смещение относительно начала BLOB поля (параметр iOffSet) и длину интересующей порции данных (iLen). После выполнения функция DbiGetBlob возвращает количество прочитанных байт. Это число может быть меньше параметра iLen, если операция чтения достигла конца BLOB поля
Версия IDAPI для Windows 3.1 не позволяет читать массивы данных длиннее чем 65К, поэтому большие BLOB поля придется считывать путем многократных вызовов функции DbiGetBlob.
ОБНОВЛЕНИЕ BLOB ПОЛЕЙ
Для записи данных в BLOB поле приложение должно использовать функцию DbiPutBlob, которая эквивалентна функции DbiPutField для обычных полей. Функции DbiPutField необходимо передать указатель на блок данных, длину блока данных и смещение внутри BLOB поля, с которого начнется запись. Приложение имеет возможность как обновить уже существующую часть BLOB поля, так и добавить новую порцию данных в конец BLOB поля.
После обновления данных в BLOB поле запись, содержащая данное BLOB поле, добавляется или вставляется в таблицу так же, как обычная запись. Как только необходимые изменения внесены в таблицу, приложение должно освободить BLOB поле вызовом DbiFreeBlob.
Следующий пример иллюстрирует обработку BLOB полей:
DBIResult rslt;
pCHAR blobBuf;
UINT32 blobSize, byteRead;
DbiGetRecord(hCursor, dbiNOLOCK, pRecBuf, NULL);
rslt = DbiOpenBlob(hCursor, pRecBuf, 3, dbiREADWRITE);
if(rslt == DBIERR_NONE)
{
DbiGetBlobSize(hCursor, pRecBuf, 3, &blobSize);
blobBuf = malloc(blobSize);
DbiGetBlob(hCursor, pRecBuf, 3, 0, blobSize, (pBYTE) blobBuf, &byteRead);
DbiFreeBlob(hCursor, pRecBufr, 3);
free(blobBuf);
}
СВЯЗАННЫЕ ТАБЛИЦЫ
IDAPI поддерживает концепцию связанных курсоров, которая дает разработчику возможность связать две таблицы по-принципу “один-ко-многим”. Между курсорами двух таблиц может быть установлена связь, если таблицы имеют общее поле, которое должно быть индексным в подчиненной таблице. Связывание двух курсоров заставляет курсор подчиненной таблицы видеть записи, содержащие значения ключа, совпадающее со значениями в текущей записи главной таблицы. Предположим, например, что главная таблица “Заказчики” и подчиненная таблица “Счета” имеют общее поле “Номер Заказчика”. И если это поле в текущей записи главной таблицы равно, например 13, тогда курсор подчиненной таблицы будет видеть только записи, относящиеся к заказчику номер 13.
Главная таблица может иметь несколько подчиненных таблиц. Но подчиненная таблица может связана только с одной главной. Одна подчиненная таблица может одновременно являться главной для другой подчиненной таблицы. IDAPI позволяет установить связь между таблицами любого типа (лишь бы существовал соответствующий драйвер).
УСТАНОВЛЕНИЕ СВЯЗИ
Для связывания двух таблиц приложение должно проделать следующие операции:
Открыть курсоры двух таблиц. Курсор подчиненной таблицы должен иметь активный текущий индекс в поле, которое будет использоваться для связывания.
Подготовить курсоры к связыванию. Для этого приложение вызывает функцию DbiBeginLinkMode для каждого курсора. Функция DbiBeginLinkMode возвращает новый курсор.
Связать два курсора вызовом функции DbiLinkDetail. Типы связываемых полей в главной и в подчиненной таблицах должны совпадать.
ТРАНЗАКЦИИ
Транзакции могут выполняться на всех SQL платформах, которые поддерживает IDAPI.
IDAPI позволяет только одной транзакции быть активной во время одной связи с SQL БД. Попытка начать вторую транзакцию до завершения первой обречена на ошибку.
ТРАНЗАКЦИИ ПО-УМОЛЧАНИЮ
Все SQL операции IDAPI выполняет в контексте транзакции. Даже если приложение явно не выполняет транзакции, SQL драйвер управляет сервером через транзакции незаметно для приложения. Подчеркнем что транзакции по-умолчанию выполняются только с SQL серверами и только если приложение явно не использует транзакции.
ЯВНОЕ ИСПОЛЬЗОВАНИЕ ТРАНЗАКЦИЙ
Для явного использования транзакций, IDAPI предоставляет функции DbiBeginTran и DbiEndTran.
ЗАПРОСЫ
Технология IDAPI предоставляет клиентским приложениям возможность использовать SQL или QBE запросы для доступа как к серверным БД так и к докальным таблицам dBASE и Paradox. IDAPI содержит группу функций обеспечивающих передачу SQL/QBE запросов.
ОСОБЕННОСТИ SQL ЗАПРОСОВ
Для связи со стандартными БД (dBASE, Paradox), IDAPI предоставляет подмножество SQL. Это подмножество может использоваться для организации связи стандартных БД с серверными SQL таблицами (при этом должен быть установлен соответствующий SQL драйвер). Для связи только с SQL БД, IDAPI позволяет использовать родной диалект серверных систем, таких как Oracle или Sybase.
ОСОБЕННОСТИ QBE ЗАПРОСОВ
QBE обеспечивает одинаковый доступ как к данным Paradox или dBase, так и к серверным БД.
ПРЯМОЕ ВЫПОЛНЕНИЕ ЗАПРОСОВ
Для исполнения простых запросов приложение может использовать функцию DbiQExecDirect, которая не требует предварительных действий. Эта функция сразу выполняет запрос и возвращает идентификатор курсора, указывающего на полученный результат. При вызове функции DbiQExecDirect, приложение должно указать идентификатор курсора БД, язык запроса (SQL или QBE) и сам запрос.
Следующий пример показывает, как выполнить SQL запрос с помощью функции DbiQExecDirect:
DBIResult rslt;
hDBICur hCur;
bBYTE szQuery = “Select t.name, t.age”
“from EMPLOYEE “
“where t.age > 30 “
“and t.salary > 1000000 “;
rslt = DbiQExecDirect(hDB, qrylangSQL, szQuery, &hCur);
ВЫПОЛНЕНИЕ ЗАПРОСА ПО ШАГАМ
Если приложению необходимо задать тип результирующей таблицы или задать параметры запроса, то лучше выполнить запрос по шагам. Выполнение запроса по шагам включает в себя:
Подготовку запроса и получение идентификатора запроса (DbiQPrepare)
Задание параметров запроса (DbiSetProp)
Выполнение подготовленного запроса (DbiQExec)
Освобождение ресурсов (DbiQFree)
ТИП РЕЗУЛЬТАТА ЗАПРОСА
Перед выполнением запроса, приложение должно указать, какой тип результата желателен. Результат запроса может быть либо копией оригинальных данных, либо живыми данными. Но даже если приложение указывает живой тип данных, IDAPI не гарантирует получение живого результата. Для того чтобы убедиться в том, какой тип результата вернул запрос, необходимо получить свойство запроса bTempTable (с помощью функции DbiGetCursorProps).
ЗАКЛЮЧЕНИЕ
Тесные рамки статьи не позволяют показать все возможности новой технологии. Но о широте и гибкости IDAPI говорит тот факт, что такие популярные системы доступа к БД как, Paradox, dBase, Delphi, опираются на эту технологию. |