Изображение квадрата Дюрера

ООО АВТОМАТИКА плюс

Rambler's Top100

Рейтинг@Mail.ru

Упрощаем разработку приложений баз данных Firebird

Версия от 09.05.2012

Содержание

Введение

Данная статья посвящена вопросам разработки приложений баз данных Firebird в среде Delphi. Автором предлагается решение (библиотека IBXFBUtils), позволяющее существенно упростить разработку таких приложений.

Почему Firebird?

Изначально для ответа на этот вопрос автору хотелось обойтись одним абзацем. Но после первого абзаца появился второй, третий, четвертый и т.д. Было принято решение выразить свои мысли в отдельном документе. Так появилась статья Почему мне нравится Firebird. Firebird-сообщество в целом поддерживает идеи, выраженные в этой статье. Как вывод: Firebird - оптимальная СУБД для разработки OLTP-решений (а для разработки "коробочных" приложений - идеальное средство).

Компоненты для работы с Firebird

Автор привык работать с компонентами IBX. Библиотека InterBase Express является стандартной и доступна сразу же после установки Delphi. Надежность и эффективность IBX проверена годами. Более мощная (но платная) библиотека FIBPlus имеет множество преимуществ по сравнению с IBX, однако из этого не следует делать вывод, что IBX не подходит для серьезных приложений. Очень даже подходит - для сколь угодно сложных приложений.

Во всяком случае и IBX и FIBPlus - очень качественные и надежные решения.
Автор видит лишь два серьезных недостатка библиотеки IBX по отношению к FIBPlus:
- к набору данных нельзя привязать 2 транзакции (для чтения и для записи), что осложняет разработку приложений (эта проблема особенно актуальна для новичков);
- IBX в Delphi XE2 x64 не поддерживает БД Firebird (справедливости ради, разработчики IBX официально никогда Firebird не поддерживали).

Ограничения стандартных компонентов IBX

Чаще всего разработчики делают сравнительно простые приложения, состоящие только из одного (основного) потока. При этом размещают на форме (или в TDataModule) все необходимые для работы с БД компоненты (например, TIBDatabase, TIBTransaction, TIBDataSet, TDataSource), настраивают в визуальном режиме необходимые свойства (в том числе SelectSQL, ModifySQL, InsertSQL, DeleteSQL, RefreshSQL для компонентов TIBDataSet) и т.д. Возможностей IBX достаточно для разработки простых приложений, однако, в сложных приложениях разработчику очень часто приходится писать собственные библиотеки функций, упрощающих работу с БД Firebird.

Сами по себе компоненты IBX мало чем помогут:
- при создании базы данных "с нуля" (IBX позволяет создать лишь пустую базу данных; создание таблиц, полей и прочих объектов осуществляется, как правило, в IBExpert);
- при коррекции структуры рабочей базы данных (в этом случае также используют IBExpert);
- при разработке высокопроизводительных многопоточных серверных приложений (в IBX отсутствует пул подключений, что осложняет разработку таких приложений);
- при необходимости хранения в БД разнородной конфигурационной информации (соответствующий механизм в IBX не предусмотрен);
- при резервировании / восстановлении БД (IBX предоставляет необходимые возможности, однако разработчику приходится писать массу собственного кода);
- при необходимости вызова конструкции EXECUTE BLOCK (необходимо помнить весь синтаксис данной конструкции)

Очевидно, что в библиотеке IBX имеется большое количество белых пятен. Решения, предложенные автором, позволяют устранить перечисленные недостатки IBX.

Библиотека функций IBXFBUtils

Использовать данную библиотеку очень просто:
- Для начала ее следует скачать из github.com по ССЫЛКЕ и распаковать архив в любом удобном месте.
- Далее следует запустить Delphi, открыть окно настроек Tools \ Environment Options \ Library \ Library path (для Delphi 7) или Tools \ Options \ Environment Options \ Delphi options \ Library (32-bit Windows) \ Library path (для Delphi XE2) и добавить каталог IBXFBUtils.
- Создать новое VCL-приложение и в разделе Uses добавить модули: ibxFBUtils, fbTypes, IBDatabase, IBCustomDataSet, DB.
- Убедиться, что компиляция проекта проходит успешно.

Вся дальнейшая работа осуществляется с помощью глобальной переменной fb.
В следующем примере осуществляется подключение к базе данных TEST.FDB и добавление записи в таблицу TESTTABLE:

procedure TForm1.Button1Click(Sender: TObject);
var
  fdb: TIBDatabase;
begin
  // Подключаемся к базе данных + создаем транзакцию RCRW
  fdb := fb.CreateConnection('localhost', FBDefPort, 'C:\TEMP\TEST.FDB',
    FBDefUser, FBDefPassword, FBRusCharSet, trRCRW);
  // Добавляем новую запись в таблицу
  fb.InsertRecord(fdb, nil, 'TESTTABLE', ['ID', 'NAME', 'SUMMA'],
    [1, 'FIREBIRD - FOREVER', 100500]);
  // Подтверждение транзакции
  fdb.DefaultTransaction.Commit;
  // Удаление подключения к БД
  fb.FreeConnection(fdb);
end;

Если назначение той или иной функции вызывает вопросы, обратитесь к исходным кодам библиотеки IBXFBUtils.
Важно! Ознакомьтесь с описанием, которое находится в начале модуля ibxFBUtils.pas. Ознакомьтесь с примерами в проекте fbUtilsTest.dpr (модуль TestForm.pas)

Создание базы данных с нуля и коррекция структуры БД

За создание базы данных и коррекцию ее структуры отвечает объект: fb.DBStruct.
Поддерживаются следующие объекты БД (проверено: FB 2.0, FB2.1, FB2.5):
- таблица;
- поле;
- домен;
- проверка (CHECK);
- первичный ключ;
- внешний ключ;
- индекс;
- генератор;
- исключение (только "ERR");
- хранимая процедура;
- триггер;
- автоинкремент (генератор + триггер).
Многие объекты БД Firebird не поддерживаются, однако важнейшие объекты поддерживаются и для создания коробочных приложений их, как правило, достаточно.
Пример создания базы данных с тестовой таблицей:

procedure TForm1.Button1Click(Sender: TObject);
var
  ATable: TfbTableDesc;
begin
  // Пересоздаем объект DefDBDesc (на всякий случай)
  fb.DBStruct.ReCreateDefDataBaseDesc();

  // Добавляем описание доменов
  fb.DBStruct.DefDBDesc.AddDomain('T_NUMBER', 'NUMERIC(15,4)', '', CanNull, '');

  // Добавляем описание таблицы TESTTABLE
  ATable := fb.DBStruct.DefDBDesc.AddTable('TESTTABLE');
  with ATable do
  begin
    // Добавляем описание полей
    AddField('ID',           'INTEGER',     '',   NotNull);
    AddField('RECTYPE',      'SMALLINT',    '',   CanNull);
    AddField('NAME',         'VARCHAR(50)', '',   CanNull);
    AddField('RECDATE',      'TIMESTAMP',   '',   CanNull);
    AddField('SUMMA',        'T_NUMBER',    '0',  CanNull);

    // Описание первичного ключа
    SetPrimaryKey('TESTTABLE_PK', '"ID"');

    // Описание индекса (по возрастанию)
    AddIndex('TESTTABLE_IDX1', False, Ascending, 'RECDATE');

    // Триггер для создания автоинкремента на поле ID
    AddAutoIncTrigger('', 'ID', 'GEN_TESTTABLE_ID', True);

  end;

  // Создание базы данных 
  fb.DBStruct.CheckDefDataBaseStruct('localhost', FBDefPort, 'C:\TEMP\TEST.FDB',
    FBDefUser, FBDefPassword, FBRusCharSet, nil);

end;

Внимание! Если Вы решите скопировать данный пример "один-в-один", то перед его запуском убедитесь в существовании каталога "C:\TEMP\". Автоматическое создание каталогов не выполняется.

Таким образом, описание структуры БД может располагаться непосредственно в исходных кодах. Это весьма удобно, поскольку гарантируется наличие всех необходимых объектов в базе данных. В любой момент Вы можете добавить новый объект к своему описанию и он гарантированно появится в БД.

Если Вам потребуется добавить новый объект в БД, которая уже давно используется и содержит множество таблиц, то Вам достаточно добавить описание лишь для этого объекта и он будет автоматически создан в БД.

Если Вы изменяете исходные коды триггеров или хранимых процедур, то необходимая коррекция БД будет выполнена автоматически.
Допускается коррекция длины полей типа VARCHAR, но только в большую сторону.
Внимание! При исправлении описания объектов "Поле", "Первичный ключ", "Внешний ключ", "Индекс", "Домен", "Проверка" коррекция БД не производится.
Необходимо заранее и тщательно продумывать описание каждого объекта БД.
Удаление объектов из БД не предусмотрено.

Ниже представлены замечания по выбору типов полей и их наименований:

- Для хранения денежных величин, а также любых вещественных чисел с заданным количеством знаков после запятой, используйте тип DECIMAL (или NUMERIC). Данный тип не допускает потери точности.
- Для хранения вещественных чисел с неизвестным количеством знаков после запятой (например, цена закупки, которая вычисляется как сумма закупки, деленная на количество купленных изделий), используйте тип DOUBLE PRECISION.
- Внимание! Никогда не используйте тип FLOAT, т.к. точность хранения вещественных чисел очень низкая.
- Не экономьте на длине строкового поля. Лучше для хранения фамилии сразу выбрать тип поля VARCHAR(100), чем создать короткое поле VARCHAR(20), а затем ломать голову над тем, как его расширить. Тем более, эта цифра не влияет на объем пространства, используемого в файле базы данных - учитываются только реальные символы.
- Для хранения логических значений используйте тип поля INTEGER. Он занимает не больше чем CHAR или VARCHAR, при этом целые числа (1, 0) проще использовать в SQL-запросах, а также в коде программы.
- Наименования полей должны содержать ТОЛЬКО латинские символы и цифры (аналогично идентификаторам в Pascal). Попытки использовать кириллицу, пробелы, апострофы и др. символы зачастую влекут за собой множество проблем.
- Длина имени объектов БД (таблиц, полей и т.п.) должна быть минимальной (но так, чтобы можно было потом разобраться). Firebird накладывает ограничение на длину имени (31 символ), однако часто требуются различные префиксы и суффиксы (например, для таблицы TEST имя первичного ключа может быть: TEST_PRIMARY, имя генератора: GENERATOR_TEST_ID и т.п.), поэтому 31 символ - это совсем не большое число. Рекомендуется префиксы и суффиксы делать как можно короче (TEST_PK вместо TEST_PRIMARY, GEN_TEST вместо GENERATOR_TEST_ID, TEST_IDX1 вместо INDEX_TEST_NAMEOFFIELD и т.п.). Это позволит Вам строго придерживаться принятых Вами правил именования для любых объектов.
- Разумеется, ести таблица называется CATEGORY, то абсолютным абсурдом является дублирование имени таблицы в наименованиях полей: CATEGORY_ID, CATEGORY_NAME. Гораздо лучше сократить: CAT_ID, CAT_NAME и т.д. Но, зачастую, лишние префиксы не используют, т.е. достаточно: ID, NAME (автор многократно убеждался в преимуществах именно этого подхода, особенно при активном использовании языка SQL). Следует учитывать в первую очередь те правила именования, которые уже действуют в Вашей организации.

Использование пула подключений к базе данных

Весьма часто у программистов возникает необходимость в разработке приложений с интенсивным выполнением операций подключения и отключения БД.
Примеры:
- WEB-приложение, обслуживающее большое количество одновременных HTTP-запросов (для каждого запроса требуется подключиться к БД, сохранить необходимую информацию и отключиться от БД).
- TCP-сервер, обслуживающий большое количество одновременных подключений.
- DCOM-сервера, службы и т.п.
Подключение к БД - это весьма ресурсоёмкая операция, длительность которой может достигать несколько секунд. Пул подключений позволяет снизить остроту проблемы, поскольку в этом случае команда "отключение от БД" не приводит к физическому отключению от БД (вместо этого подключение сохраняется в пуле и остается активным). Большинство современных компонентов подключения к БД содержат встроенный пул подключений, однако в IBX его нет.

Библиотека IBXFBUtils предоставляет удобные средства для работы с пулом подключений, при этом используется объект fb.Pool.
Работа с пулом подключений выглядит следующим образом:

procedure TForm1.Button1Click(Sender: TObject);
var
  fdb: TIBDatabase;      // Объект-подключение
  ftran: TIBTransaction; // Транзакция (для записи)
begin
  // Получаем подключение из пула (транзакция будет создана автоматически)
  fdb := fb.Pool.GetConnection('localhost', FBDefPort, 'C:\TEMP\TEST.FDB',
    FBDefUser, FBDefPassword, FBRusCharSet, nil, @ftran);
  try
    // Добавляем новую запись
    fb.InsertRecord(fdb, ftran, 'TESTTABLE', ['ID', 'NAME', 'SUMMA'],
      [2, 'FIREBIRD - FOREVER', 100500]);
    // Подтверждаем транзакцию
    ftran.Commit;
  finally
    // Возвращаем подключение обратно в пул
    // Объект-транзакция будет уничтожен автоматически

    fb.Pool.ReturnConnection(fdb);
  end;
end;

Не рекомендуется длительное время использовать подключение, полученное из пула. После получения подключения из пула и выполнения серии операций с БД, следует незамедлительно вернуть подключение обратно в пул. Благодаря этому количество активных подключений в пуле будет всегда минимальным.

Следует отметить, что на Delphi-форумах весьма часто появляются вопросы по одновременной работе с БД Firebird из параллельных потоков. Ответов (и советов) на подобные вопросы много и они самые разные:
- осуществлять всю работу с БД в каком-то одном потоке (остальные потоки дают команду и ожидают, когда этот поток закончит обработку команды). Данный подход на практике весьма сложен, требует от программиста глубоких знаний по вопросам обеспечения синхронизации между потоками, делает работу с БД крайне низкоэффективной.
- для каждого потока создавать собственное подключение к БД и все необходимые объекты. Это - основной подход, однако при работе с БД из большого числа параллельных потоков, а также при интенсивных коннектах / дисконнектах, снижается общая производительность системы.
- множество других ответов и "советов".

Использование пула подключений упрощает разработку сложных (в том числе многопоточных) приложений и улучшает производительность системы в целом.

Обратите внимание на метод fb.Pool.AddDefaultConnectionProfile(). Он позволяет однократно задать настройки подключения к БД по умолчинию. В дальнейшем для извлечения подключения из пула можно вызвать метод fb.Pool.GetDefaultConnection() с минимальным количеством параметров.

Хранение конфигурационных параметров в базе данных

Хранение структурированной информации в БД - это обычная задача. Несмотря на это, многие разработчики используют INI-файлы для хранения конфигурационных параметров своих приложений. Работа с INI-файлами весьма проста и удобна, однако имеется ряд недостатков:
- невозможно хранить глобальные параметры, которые должны использоваться всеми приложениями, подключенными к БД с разных компьютеров;
- невозможно хранить большие объекты (двоичные, текстовые, графические);
- расширение INI в ОС Windows является опасным, поскольку ОС в случае сбоя может откатить собственное состояние на предыдущую точку восстановления, при этом возвращаются старые версии всех INI-файлов (для избежание подобной проблемы часто используют расширение "*.conf");
- при работе с TIniFile на формат хранения чисел, а также даты/времени, влияют региональные настройки, заданные в ОС (если перед чтением из INI-файла изменились региональные настройки, то программа не сможет считать значение, записанное в файл перед этим);
- сложность хранения многострочного текста, а также строк, содержащих "недопустимые" символы;
- зависимость скорости чтения/записи параметров от размера INI-файла (хотя вряд ли это актуально);
- многие антивирусы при каждом изменении INI-файла перепроверяют его целиком, что в некоторых случаях резко ухудшает производительность системы;
- пользователь может открыть INI-файл в обычном блокноте и испортить его содержимое;
- в рамках одного INI-файла сложно разделить настройки для разных пользователей;
- одновременное обращение к одному INI-файлу из нескольких приложений может привести к его порче (не все ОС предусматривают подобный режим работы с INI-файлами).
(После всего прочитанного не следует пугаться INI-файлов. Это прекрасный механизм, который еще всех нас переживет. Существует разработанный автором модуль SafeIniFiles, устраняющий многие недостатки INI-файлов)

Автором предлагается решение, позволяющее хранить в БД все конфигурационные настройки, при этом процесс написания кода ничем не отличается от работы с объектом TIniFile. Работа с INI-файлами осуществляется с помощью объекта fb.Ini.
procedure TForm1.Button1Click(Sender: TObject);
var
  Ini: TFBIniFile;
  Value: Integer;
begin
  // Создаем объект INI-файл
  Ini := fb.Ini.CreateIni('localhost', FBDefPort, 'C:\TEMP\TEST.FDB',
    FBDefUser, FBDefPassword, FBRusCharSet);
  try
    // Записываем строку в INI-файл
    Ini.WriteString('Params', 'MyString', 'Hello, World!');
    // Читаем целочисленное значение из INI-файла
    Value := Ini.ReadInteger('Params', 'MyValue', 0);
    // Запись даты/времени в INI-файл (упрощенный вариант)
    
  finally
    // Уничтожаем объект INI-файл
    fb.Ini.FreeIni(Ini);
  end;
end;

Предлагаемое решение охватывает все возможности стандартного TIniFile и добавляет множество усовершенствований. При этом могут учитываться:
- наименование INI-файла;
- имя пользователя;
- имя компьютера.
Внимание! Большое количество примеров по работе с INI-файлами Вы найдете в приложении FBUtilsTest. Там же приведена структура таблицы "CONFIGPARAMS" и код ее автоматического создания.
Следует отметить, что решение не рассчитано на хранение слишком большого количества настроек, поскольку запись / чтение каждой настройки занимает ненулевое время (несколько миллисекунд).

Программный бэкап базы данных

Необходимо регулярно делать резервную копию (бэкап) базы данных. Стандартная библиотека IBX предоставляет функции (service-api), необходимые для выполнения бэпака, однако во многих случаях разработчики приложений ими пренебрегают. Предлагаемая библиотека содержит несколько простых функций для выполнения резервирования / восстановления БД с помощью service-api.
Для резервирования / восстановления БД предназначен объект fb.br.
Ниже представлен пример создания резервной копии БД:
fb.br.BackupDatabaseOnServer('localhost', FBDefPort, 'C:\TEMP\TEST.FDB', 'C:\TEMP\mytestdbbackup.fbk', 
  FBDefUser, FBDefPassword, FBDefBackupOptions, BackupRestoreProgressProc);

Пример восстановления из резервной копии:
fb.br.RestoreDatabaseOnServer('localhost', FBDefPort, 'C:\TEMP\TEST_COPY.FDB', 'C:\TEMP\mytestdbbackup.fbk',
  FBDefUser, FBDefPassword, FBDefRestoreOptions + [Replace], BackupRestoreProgressProc);

BackupRestoreProgressProc - это функция обратного вызова, в которую передается информация о ходе выполнения операций. Предусмотрена возможность прерывания операции резервирования / восстановления в любой момент.

Часто требуется возможность загрузки созданного файла резервной копии с сервера на клиент. Для этого предусмотрена функция fb.br.BackupDatabaseAndCopyFromServer.
При необходимости можно загрузить файл резервной копии с клиента на сервер и выполнить восстановление БД. Для этого предусмотрена функция fb.br.CopyBackupToServerAndRestoreDatabase.

Примеры смотрите в приложении FBUtilsTest.

Удобный вызов конструкции EXECUTE BLOCK

Наличие в Firebird'e конструкции EXECUTE BLOCK избавляет от необходимости создавать в БД хранимые процедуры по любому поводу. Фактически EXECUTE BLOCK - это та же самая хранимая процедура, однако она не имеет имени и не хранится в базе данных. Как и хранимые процедуры, EXECUTE BLOCK может возвращать результат (набор данных), а может и не возвращать.
Пример вызова EXECUTE BLOCK, возвращающего набор данных:
var
  ds: TIBDataSet;
begin 
  ds := fb.ExecuteBlock(fdb, ftran,
    'CNT INTEGER, AvgSum DOUBLE PRECISION',         // Поля результирующего набора данных
    '',                                             // Локальные переменные - отсутствуют
    'SELECT COUNT(ID), AVG(SUMMA) FROM TESTTABLE '+ // Выполняем агригирующий запрос
    'INTO :CNT, :AvgSum; '+                         // Сохраняем результат запроса в переменные
    'SUSPEND;');                                    // Отправляем запись клиентскому приложению
  // *** ОПЕРАТОРЫ ДЛЯ ОБРАБОТКИ ПОЛУЧЕННОГО НАБОРА ДАННЫХ *** //
  ds.Free;
end;

Пример вызова EXECUTE BLOCK, не возвращающего набор данных:
  fb.ExecuteBlock(fdb, ftran,
    'vID INTEGER, vName VARCHAR(100)',        // Объявляем локальные переменные
    ' FOR SELECT ID, NAME FROM TESTTABLE '+   // Для каждой строки запроса
    '     WHERE NAME IS NULL ORDER BY 1 '+    // с заданным условием и сортировкой
    ' INTO :vID, :vName '+                    // Сохраняем ID и NAME в переменные
    ' DO '+                                   // выполнить...
    ' BEGIN '+
    '   UPDATE TESTTABLE SET SUMMA=SUMMA+1, NAME=:vName WHERE ID=:vID; '+ // Обновление строки таблицы
    ' END ');

Примеры смотрите в приложении FBUtilsTest.

Простой вызов функций для модификации записей в таблице

Пример добавления записи:
  fb.InsertRecord(fdb, ftran,
    'TESTTABLE',                // Имя таблицы
    ['ID', 'NAME', 'RECDATE'],  // Имена полей таблицы
    [1, 'Наименование', Now]);  // Значения полей (целое, строка, дата/время)

Пример изменения записи:
  fb.UpdateRecord(fdb, ftran,
    'TESTTABLE',                // Имя таблицы
    ['ID'],                     // Ключевые поля
    [1],                        // Значения ключевых полей
    ['SUMMA', 'RECTYPE'],       // Имена полей таблицы
    [1000000, 5]);              // Значения полей

Пример удаления записи:
  fb.DeleteRecord(fdb, ftran,
    'TESTTABLE',                // Имя таблицы
    ['ID'],                     // Ключевые поля
    [1]);                       // Значения ключевых полей

Пример изменения / добавления записи:
  fb.UpdateOrInsertRecord(fdb, ftran,
    'TESTTABLE',                              // Имя таблицы
    ['ID', 'NAME', 'RECDATE', 'SUMMA'],       // Имена полей таблицы
    [1, 'Наименование', Now, Random(100000)], // Значения полей
    ['ID']);                                  // Ключевое поле (для поиска совпадения)

При визуальном программировании подобные функции, как правило, не требуются, но в некоторых других случаях они весьма полезны.

Базовые функции библиотеки

Обращение к базовым функциям осуществляется через объект fb. Подробное описание и реализацию функций смотрите в модуле fbUtilsBase.

Функция Описание
function CreateConnection Создает подключение к базе данных. Возвращает объект TIBDataBase. При необходимости создает объект-транзакцию (заданного типа). По умолчанию устанавливает подключение к БД.
Внимание! Не следует использовать функции CreateConnection, ConnectDB, CreateTransaction, DisconnectDB, FreeConnection, если Вы работаете с пулом подключений fb.Pool (в этом нет необходимости).
procedure ConnectDB Устанавливает подключение к БД (можно безопасно вызывать из параллельных потоков).
procedure DisconnectDB Закрывает подключение к БД.
procedure FreeConnection Уничтожение объекта подключения к БД.
function CreateTransaction Создание объекта транзакции TIBTransaction указанного типа. По умолчанию используется транзакция RCRW и осуществляется автоматический старт транзакции.
function CreateDataSet Создание набора данных TIBDataSet. Не обязательно указывать оба параметра (TIBDataBase и TIBTransaction). Если указать только один из них (а другой - nil), то второй объект будет определен автоматически. Не желательно в качестве AOwner указывать TIBDataBase / TIBTransaction, т.к. в некоторых версиях Delphi присутствует глюк в IBX, который не позволяет этого сделать.
function CreateAndOpenDataSet Создает и открывает набор данных TIBDataSet. SQL - текст SQL-запроса; ParamNames - открытый массив наименований параметров; ParamValues - открытый массив значений параметров.
Если параметры не требуются, то должен быть указан пустой массив: []
Функция автоматически загружает на клиента все записи из набора данных (команда FetchAll).
function CreateAndOpenTable Создает объект TIBDataSet и открывает таблицу. ATable - имя таблицы, AFilter - условие фильтрации, AOrder - поля сортировки. Автоматически выполняет команду FetchAll.
procedure ExecQuery Выполняет заданный SQL-запрос (DML или DDL).
procedure UpdateRecord, InsertRecord, DeleteRecord, UpdateOrInsertRecord Функции для модификации записей в таблице (примеры см. выше). Следует отметить, что KeyFields, KeyValues, FieldNames, AFieldValues - это открытые массивы, поэтому список значений должен располагаться в квадратных скобках.
procedure RecomputeIndexStatistics Осуществляет пересчет индексной статистики.
function GenID Получает очередное значение генератора.
function / procedure  ExecuteBlock Выполняет команду EXECUTE BLOCK (см. выше)
procedure ClearTable Выполняет очистку указанной таблицы ATableName. AWhere - условие поиска записей для удаления. GarbageCollection - определяет, требуется ли сборка мусора. При сборке мусора не следует указывать транзакцию (указать nil).
property DBStruct Функции для создания БД с нуля и коррекции ее структуры.
property Pool Функции для работы с пулом подключений.
property Ini Функции для работы с INI-файлами (в базе данных).
property br Функции для бэкапа / рестора базы данных.
property UserName Запись / чтение глобальной переменной FBUserName
property Password Запись / чтение глобальной переменной FBPassword

Особенности использования библиотеки при разработке многомодульного приложения

Сложный программный проект может состоять из множества исполняемых модулей (EXE и DLL-файлов). В этом случае рекомендуется весь основной исполняемый код библиотеки IBXFBUtils разместить в отдельной библиотеке fbUtils.dll. Для этого необходимо открыть в Delphi проект fbUtils.dpr и в опциях проекта
- указать директиву условной компиляции FBUTILSDLL;
- установить флаг "Build (Link) with runtime packages" и добавить в список пакет "ibxpress".
То же самое следует сделать для всех EXE и DLL, входящих в Ваш программный проект.
Следует учитывать, что в поставку Вашего приложения войдут файлы: fbUtils.dll, rtlNN.bpl, dbrtlNN.bpl, ibxpressNN.bpl (номер NN зависит от версии Delphi).

Разумеется, никто не мешает скомпилировать всю библиотеку IBXFBUtils в виде отдельного run-time-пакета (автор не видит необходимости предоставлять для этого случая отдельную инструкцию).

Особенности использования библиотеки при наличии на компьютере нескольких версий Firebird

Очевидно, что для подключения к БД Firebird Вы должны указывать TCP-порт на котором работает экземпляр Firebird, требуемый вашему приложению. Этот порт (по умолчанию: 3050) настраивается в файле "firefird.conf", который расположен в каталоге с установленным Firebird. В этом же каталоге расположен файл "firebird.msg", в котором хранится текст сообщений об ошибках, а также "firebird.log", хранящий логи работы Firebird. Там же расположен файл "fbclient.dll". Необходимо создать копию этого файла в том же каталоге и переименовать его в "GDS32.dll". Указанные файлы (особенно "firebird.msg" и "GDS32.dll") очень важны для правильного функционирования клиентского приложения. При необходимости Вы можете явно указать место расположения этих файлов. Для этого достаточно подключить к своему проекту модуль "fbUtilsLoading.pas" (при наличии библиотеки fbUtils.dll - достаточно только к ней) и указать правильное значение для констант FirebirdPath и GDS32FileName. Там же Вы можете определить реакцию приложения на возможные ошибки загрузки GDS32.dll. Рекомендуется ознакомиться с описанием, которое приведено в начале модуля "fbUtilsLoading.pas".

Тестирование корректности работы библиотеки IBXFBUtils

Рекомендуется перед началом использования произвести проверку корректности библиотеки IBXFBUtils. Для этого откройте в Delphi проект "fbUtilsTest.dpr" и выполните его компиляцию. Если возникла ошибка, устраните ее причины. После успешной сборки запустите приложение, укажите параметры подключения к тестовой (несуществующей) базе данных и поочередно запустите тесты (начните с пункта "Коррекция структуры БД").

Заключение

Несмотря на то, что реализация IBXFBUtils заняла у автора около месяца, на самом деле в этой библиотеке сосредоточен труд нескольких лет. Были позаимствованы лучшие идеи по работе в Firebird из предыдущих проектов. Библиотека позволяет значительно ускорить разработку приложений баз данных. Конструктивную критику, замечания и предложения по улучшению библиотеки отправляйте на электронную почту автора.

Спасибо за внимание!

Логинов Дмитрий © 2005-2015