Инкрементное обновление структуры базы данных

Материал из GedeminWiki
Версия от 14:59, 10 мая 2011; SYSDBA (обсуждение | вклад)

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

После каждого успешного обновления структуры БД заносится запись в таблицу FIN_VERSIONINFO. Таким образом, текущую версию структуры можно извлечь по максимальному идентификатору с помощью запроса:

 SELECT FIRST 1 * FROM fin_versioninfo ORDER BY id DESC

Для изменения структуры БД разработчик создает процедуру типа TProcAddr. Как правило, на одно изменение создается одна процедура. Ниже приведен пример из файла mdf_ConvertBNStatementCommentToBlob:

procedure ModifyRUIDProcedure(IBDB: TIBDatabase; Log: TModifyLog);
var
  FTransaction: TIBTransaction;
  FIBSQL: TIBSQL;
begin
  FTransaction := TIBTransaction.Create(nil);
  FIBSQL := TIBSQL.Create(nil);
  try
    FTransaction.DefaultDatabase := IBDB;
    try
      FTransaction.StartTransaction;
      FIBSQL.Transaction := FTransaction;
      FIBSQL.ParamCheck := False;
 
      FIBSQL.SQL.Text :=
        'CREATE OR ALTER PROCEDURE GD_P_GETRUID(ID INTEGER) '#13#10 +
        '  RETURNS (XID INTEGER, DBID INTEGER) '#13#10 +
        'AS '#13#10 +
        'BEGIN '#13#10 +
        '  XID = NULL; '#13#10 +
        '  DBID = NULL; '#13#10 +
        ' '#13#10 +
        '  IF (NOT :ID IS NULL) THEN '#13#10 +
        '  BEGIN '#13#10 +
        '    IF (:ID < 147000000) THEN '#13#10 +
        '    BEGIN '#13#10 +
        '      XID = :ID; '#13#10 +
        '      DBID = 17; '#13#10 +
        '    END ELSE '#13#10 +
        '    BEGIN '#13#10 +
        '      SELECT xid, dbid '#13#10 +
        '      FROM gd_ruid '#13#10 +
        '      WHERE id=:ID '#13#10 +
        '      INTO :XID, :DBID; '#13#10 +
        ' '#13#10 +
        '      IF (XID IS NULL) THEN '#13#10 +
        '      BEGIN '#13#10 +
        '        XID = ID; '#13#10 +
        '        DBID = GEN_ID(gd_g_dbid, 0); '#13#10 +
        ' '#13#10 +
        '        INSERT INTO gd_ruid(id, xid, dbid, modified, editorkey) '#13#10 +
        '          VALUES(:ID, :XID, :DBID, CURRENT_TIMESTAMP, NULL); '#13#10 +
        '      END '#13#10 +
        '    END '#13#10 +
        '  END '#13#10 +
        ' '#13#10 +
        '  SUSPEND; '#13#10 +
        'END ';
 
      FIBSQL.ExecQuery;
 
      FIBSQL.SQL.Text :=
        'UPDATE OR INSERT INTO fin_versioninfo ' +
        '  VALUES (132, ''0000.0001.0000.0163'', ''28.03.2011'', ''Modify GD_P_GETRUID procedure.'') ' +
        '  MATCHING (id)';
      FIBSQL.ExecQuery;
      FIBSQL.Close;
 
      FTransaction.Commit;
    except
      on E: Exception do
      begin
        Log('Произошла ошибка: ' + E.Message);
        if FTransaction.InTransaction then
          FTransaction.Rollback;
        raise;
      end;
    end;
  finally
    FIBSQL.Free;
    FTransaction.Free;
  end;
end;

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

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

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

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

 FDBVersion <= cProcList[I].ModifyVersion

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

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

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