Модификация структуры базы данных

Материал из GedeminWiki
Версия от 18:31, 15 января 2012; SYSDBA (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Начальная база данных для платформы Гедымин создается из SQL скриптов в каталоге Gedemin\SQL с помощью пакетного файла cr.bat. Формат вызова:

 cr.bat {server[/port]|embed} database [fb\bin path]  

Например, команда:

 cr.bat localhost c:\temp\test.fdb

Создаст чистую базу данных с именем test.fdb в папке c:\temp. Особенность использования данного пакетного файла в том, что при вызове с указанием имени сетевого сервера, диск, где будет располагаться файл базы данных, должен быть подключен на локальном компьютере под той же буквой, какую он имеет на сервере.

Файл cr.bat формирует базу данных в два прохода. Сначала из отдельных скриптов собирается файл temp.sql и передается на вход команды isql. Получившаяся промежуточная база данных обрабатывается утилитой makelbrbtree.exe, которая создает скрипты метаданных для всех таблиц интервальных деревьев. Из исходных и полученных скриптов формируется единый файл etalon.sql из которого создает эталонная база данных.

История изменений структуры базы данных фиксируется в таблице fin_versioninfo. Ее структура и наполнение задаются в файле gd_version.sql. Запись с максимальным идентификатором соответствует текущей версии структуры. Ее можно определить запросом:

 
  SELECT FIRST 1 * FROM fin_versioninfo ORDER BY id DESC

или заглянуть в окно О системе на вкладку Параметры системы.

Структура базы данных поставляемой с "голой" платформой называется эталонной, а сама база данных без пользовательских настроек – эталоном. Эталонная структура может меняться с выходом новых версий файла gedemin.exe. Для обновления существующих баз предусмотрен механизм модификации структуры. Рассмотрим его работу на следующем примере: пусть в эталонную структуру базы данных необходимо добавить некоторую таблицу GD_TEST и связанные с ней два объекта: первичный ключ и триггер для автоматического формирования идентификатора записи.

Последовательность действий по внесению изменений в структуру эталонной базы данных включает следующие шаги:

  1. Создать файл с SQL скриптом или внести изменения в один из существующих файлов.
  2. Добавить в таблицу fin_versioninfo запись.
  3. Добавить имя созданного файла в список в cr.bat.
  4. Написать процедуру модификации структуры базы данных.
  5. Добавить процедуру модификации в список.
  6. Перекомпилировать и запустить gedemin.exe.

1. Создание SQL скрипта

Первым делом создадим в подкаталоге SQL папки GEDEMIN файл с именем gd_test.sql и поместим в него следующий скрипт:

 
  CREATE TABLE gd_test (
    id      dintkey,
    name    dname
  );
 
  ALTER TABLE gd_test ADD CONSTRAINT gd_pk_test_id
    PRIMARY KEY (id);
 
  SET TERM ^ ;
 
  CREATE TRIGGER gd_bi_test
    BEFORE INSERT
    POSITION 0
  AS
  BEGIN
    IF (NEW.id IS NULL) THEN
      NEW.id = GEN_ID(gd_g_unique, 1) + GEN_ID(gd_g_offset, 0);
  END
  ^
 
  SET TERM ; ^
 
  COMMIT;

2. Изменение версии структуры БД

Отыщем в файле fin_versioninfo последний номер версии структуры базы данных и после него добавим команду:

 INSERT INTO fin_versioninfo
   VALUES (100, '0000.0001.0000.0127', '16.01.2008', 'GD_TEST table added');

Обратите внимание, что в вашем случае идентификатор, строковое представление версии БД и дата внесения изменений будут другими! Указанная выше команда -- это только пример!

3. Добавление вызова скрипта в пакетный файл

Откроем файл cr.bat на редактирование. Найдем в нем список команд формирования общего текста из отдельных файлов со скриптами:

...
copy result.sql /a + gd_file.sql               /a result.sql    > nul
copy result.sql /a + gd_block_rule.sql         /a result.sql    > nul
copy result.sql /a + rpl_database.sql          /a result.sql    > nul
 
echo SET NAMES WIN1251;                        >  temp_hdr.sql
echo SET SQL DIALECT 3;                        >> temp_hdr.sql
echo CREATE DATABASE '%database_name%'         >> temp_hdr.sql
echo USER %user_name% PASSWORD %user_pass%     >> temp_hdr.sql 
echo PAGE_SIZE 8192                            >> temp_hdr.sql
echo DEFAULT CHARACTER SET WIN1251;            >> temp_hdr.sql
...

добавим обращение к нашему файлу:

...
copy result.sql /a + gd_file.sql               /a result.sql    > nul
copy result.sql /a + gd_block_rule.sql         /a result.sql    > nul
copy result.sql /a + rpl_database.sql          /a result.sql    > nul
copy result.sql /a + gd_test.sql               /a result.sql    > nul
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
echo SET NAMES WIN1251;                        >  temp_hdr.sql
echo SET SQL DIALECT 3;                        >> temp_hdr.sql
echo CREATE DATABASE '%database_name%'         >> temp_hdr.sql
echo USER %user_name% PASSWORD %user_pass%     >> temp_hdr.sql 
echo PAGE_SIZE 8192                            >> temp_hdr.sql
echo DEFAULT CHARACTER SET WIN1251;            >> temp_hdr.sql
...

4. Создание процедуры модификации структуры БД

После того, как мы создали файл со скриптом и добавили его в список cr.bat, эталонная база будет формироваться с нашей таблицей. Но, как быть с теми базами, которые были созданы ранее? Для внесения изменений в существующую структуру следует создать процедуру модификации типа GdModify.TProcAddr. Обычно, каждая процедура находится в своем файле в подкаталоге Setup. Название юнита принято начинать с префикса mdf_.

На входе процедура получает коннект к базе данных и процедуру обратного вызова для логирования. В общем случае, алгоритм обновления выглядит следующим образом:

  1. Создаются и связываются объекты транзакции и SQL команды
  2. Стартует транзакция
  3. Делаются необходимые проверки
  4. Выполняется одна или несколько SQL команд
  5. Помещаются сообщения в лог о ходе процесса
  6. Добавляется запись в fin_versioninfo о новом номере версии структуры БД
  7. Комитится транзакция
  8. Если произошла ошибка, то сообщение помещается в лог и транзакция откатывается

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

  unit mdf_AddTestTable;
 
  interface
 
  uses
    IBDatabase, gdModify;
 
  procedure AddTestTable(IBDB: TIBDatabase; Log: TModifyLog);
 
  implementation
 
  uses
    IBSQL, SysUtils;
 
  procedure AddTestTable(IBDB: TIBDatabase; Log: TModifyLog);
  var
    FTransaction: TIBTransaction;
    FIBSQL: TIBSQL;
  begin
    Log('Начато добавление таблицы GD_TEST');
    FTransaction := TIBTransaction.Create(nil);
    try
      FTransaction.DefaultDatabase := IBDB;
      FTransaction.StartTransaction;
      try
        FIBSQL := TIBSQL.Create(nil);
        try
          FIBSQL.Transaction := FTransaction;
 
          FIBSQL.SQL.Text := 
            'CREATE TABLE gd_test ( ' + #13#10 +
            '  id      dintkey,     ' + #13#10 +
            '  name    dname        ' + #13#10 +
            ')';
          FIBSQL.ExecQuery;
 
          FIBSQL.SQL.Text := 
            'ALTER TABLE gd_test ADD CONSTRAINT gd_pk_test_id ' + #13#10 +
            '  PRIMARY KEY (id)';
          FIBSQL.ExecQuery;
 
          FIBSQL.SQL.Text := 
            'CREATE TRIGGER gd_bi_test ' + #13#10 +
            '  BEFORE INSERT '           + #13#10 +
            '  POSITION 0 '              + #13#10 +
            'AS '                        + #13#10 +
            'BEGIN '                     + #13#10 +
            '  IF (NEW.id IS NULL) THEN' + #13#10 +
            '    NEW.id = GEN_ID(gd_g_unique, 1) + GEN_ID(gd_g_offset, 0); ' + #13#10 +
            'END';
          FIBSQL.ExecQuery;
 
          FIBSQL.Close;
          FIBSQL.SQL.Text :=
            'UPDATE OR INSERT INTO fin_versioninfo ' +
            '  VALUES (100, ''0000.0001.0000.0127'', ''16.01.2008'', ''GD_TEST table added'') ' +
            '  MATCHING (id)';
          FIBSQL.ExecQuery;
          FIBSQL.Close;
 
          FTransaction.Commit;
          Log('Добавление таблицы GD_TEST успешно завершено');
 
        finally
          FIBSQL.Free;
        end;
      except
        on E: Exception do
        begin
          FTransaction.Rollback;
          Log(E.Message);
        end;
      end;
    finally
      FTransaction.Free;
    end;
  end;  
 
  end.

5. Добавление процедуры в общий список

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

В ходе обновления последовательно выполняются процедуры из массива cProcList, пока выполняется условие:

 FDBVersion <= cProcList[I].ModifyVersion

где FDBVersion -- номер текущей версии структуры БД, cProcList[I].ModifyVersion -- номер версии, указанный для I-той процедуры.

Добавление нашей процедуры в список требует трех простых действий:

  1. Добавить имя нашего модуля в секцию uses юнита mdf_proclist.
  2. Увеличить счетчик mdf_proclist.cProcCount.
  3. Добавить запись в массив mdf_proclist.cProcList. Еще раз обратите внимание на то, что ModifyVersion для нашей процедуры это не тот номер, который она присвоит в результате своего выполнения, а предыдущий!

6. Компиляция и запуск

Теперь можно перекомпилировать и запустить gedemin.exe. При попытке подключения к базе данных с устаревшей структурой под учетной записью Administrator, на экран будет выдано сообщение о необходимости обновить структуру. Не забывайте делать архивные копии базы, перед внесением в нее изменений!

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Инструменты