![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Нужна критика :) - репликации в FB
Андрей Жук © (2005-09-12 18:04:00)Текущее состояние дел.
В БД в таблицах, в которых нужно делать репликацию, добавил поле LAST_UPDATED. Заполняется триггером.
Создал дополнительную таблицу APP_TABLES со следующей структурой
CREATE TABLE APP_TABLES (
TABLE_ID IDENTIFIER NOT NULL /* IDENTIFIER = INTEGER NOT NULL */,
TABLE_NAME NAME NOT NULL /* NAME = VARCHAR(82) DEFAULT 'unknown' NOT NULL */,
TABLE_DESC DESCRIPTION /* DESCRIPTION = VARCHAR(255) */,
IS_LOGGED BOOLEAN /* BOOLEAN = VARCHAR(1) DEFAULT 'U' NOT NULL CHECK (value in ('Y','N','U')) */,
PRIMARY_KEY NAME COLLATE WIN1251_UA /* NAME = VARCHAR(82) DEFAULT 'unknown' NOT NULL */,
EXPORT_ORDER NONIDENTIFIER /* NONIDENTIFIER = INTEGER */
);
Создана таблица точек сохранения
CREATE TABLE APP_SAVEPOINTS (
SAVEPOINT_ID IDENTIFIER NOT NULL /* IDENTIFIER = INTEGER NOT NULL */,
SAVEPOINT_NAME NAME NOT NULL /* NAME = VARCHAR(82) DEFAULT 'unknown' NOT NULL */,
SAVEPOINT_DESC DESCRIPTION /* DESCRIPTION = VARCHAR(255) */,
SAVEPOINT_DATETIME TIMESTAMP NOT NULL,
SAVEPOINT_CREATOR NAME COLLATE WIN1251_UA /* NAME = VARCHAR(82) DEFAULT 'unknown' NOT NULL */,
IS_ACTIVE BOOLEAN DEFAULT 'N' NOT NULL COLLATE WIN1251_UA /* BOOLEAN = VARCHAR(1) DEFAULT 'U' NOT NULL CHECK (value in ('Y','N','U')) */
);
Создана процедура, которая делает XML изменившихся параметров
CREATE PROCEDURE GET_UPDATES
RETURNS (
RES VARCHAR(32000))
AS
DECLARE VARIABLE TMP VARCHAR(4096);
DECLARE VARIABLE TABLE_NAME CHAR(31);
DECLARE VARIABLE FIELD_NAME CHAR(31);
DECLARE VARIABLE XML VARCHAR(4096);
DECLARE VARIABLE TABLE_ID INTEGER;
DECLARE VARIABLE RECORD_ID INTEGER;
DECLARE VARIABLE FIELD_CHAR INTEGER;
DECLARE VARIABLE FIELD_NULL INTEGER;
DECLARE VARIABLE PK CHAR(31);
BEGIN
TABLE_ID = 1;
FOR
SELECT RDB$RELATIONS.RDB$RELATION_NAME, APP_TABLES.primary_key
FROM RDB$RELATIONS, APP_TABLES
WHERE RDB$RELATIONS.RDB$SYSTEM_FLAG = 0 AND
RDB$RELATIONS.RDB$RELATION_NAME = APP_TABLES.TABLE_NAME AND
APP_TABLES.IS_LOGGED = 'Y'
ORDER BY APP_TABLES.EXPORT_ORDER
INTO :TABLE_NAME,:PK
DO
BEGIN
RES = '<table id="'||:TABLE_ID||'">';
SUSPEND;
TABLE_ID = :TABLE_ID + 1;
RES = '<table_name>'||rtrim(:TABLE_NAME)||'</table_name>';
SUSPEND;
RES = '<primary_key>'||rtrim(:PK)||'</primary_key>';
SUSPEND;
TMP = 'SELECT ';
FOR SELECT RDB$RELATION_FIELDS.RDB$FIELD_NAME,
coalesce(RDB$FIELDS.RDB$CHARACTER_LENGTH,-1),
coalesce(RDB$RELATION_FIELDS.RDB$NULL_FLAG,0)
FROM RDB$RELATION_FIELDS, RDB$FIELDS
WHERE
RDB$RELATION_FIELDS.RDB$FIELD_SOURCE = RDB$FIELDS.RDB$FIELD_NAME AND
RDB$RELATION_FIELDS.RDB$RELATION_NAME = :TABLE_NAME
ORDER BY RDB$RELATION_FIELDS.RDB$FIELD_POSITION
INTO :FIELD_NAME, :FIELD_CHAR, :FIELD_NULL
DO
begin
if (:FIELD_NULL=0) then
BEGIN
if (:FIELD_CHAR=-1) then
TMP = TMP || '''<' || rtrim(:FIELD_NAME) || '>''||coalesce(cast(' || rtrim(:FIELD_NAME) || ' as varchar(32)),'''')||''</' || rtrim(:FIELD_NAME) || '>''||';
else
TMP = TMP || '''<' || rtrim(:FIELD_NAME) || '>''||coalesce(cast(' || rtrim(:FIELD_NAME) || ' as varchar('||:FIELD_CHAR||')),'''')||''</' || rtrim(:FIELD_NAME) || '>''||';
END
else
TMP = TMP || '''<' || rtrim(:FIELD_NAME) || '>''||' || rtrim(:FIELD_NAME) || '||''</' || rtrim(:FIELD_NAME) || '>''||';
end
XML = TMP||''''' FROM '||rtrim(:TABLE_NAME) || ' WHERE LAST_UPDATED>=(SELECT COALESCE(MAX(SAVEPOINT_DATETIME),''22.11.2004'') FROM APP_SAVEPOINTS WHERE IS_ACTIVE=''Y'')';
RECORD_ID = 1;
FOR EXECUTE STATEMENT :XML INTO :RES DO
begin
RES = '<RECORD id="'||:RECORD_ID||'">'||RES||'</RECORD>';
SUSPEND;
RECORD_ID = :RECORD_ID + 1;
end
RES = '</table>';
SUSPEND;
END
END
Таким образом, мы получаем все изменения, произошедшие в нужных нам таблицах с последней точки сохранения.
Структура полученного XML-файла
<export>
<table>
<table_name>Имя таблицы</table_name>
<primary_key>Первичный ключ таблицы</primary_key>
<record>Запись. Поля заранее неизвестны</record>
... все остальные записи
</table>
... все остальные таблицы
</export>
Полученный XML нужно распарсить (это на завтра задание) и сделать insert/update
size=20 (2005-09-12 19:29:00) [1]
> А как такое может быть?
ну если конечно это генератор
Андрей Жук (2005-09-12 19:27:00) [2]
> этот ключ на одной точке 10, а на другой 33 хотя это
> одна и таже запись.
А как такое может быть?
Андрей Жук (2005-09-12 19:26:00) [3]Ну бэкапы-то само-собой.
> Тяжело в бинарный файл выгрузить?
Так структура же такого файла заранее неизвестна. Появятся новые поля - ничего менять не придется.
Нашел у себя ошибку - не учитываются удаления.
size=20 (2005-09-12 19:25:00) [4]
> <primary_key>Первичный ключ таблицы</primary_key>
этот ключ на одной точке 10, а на другой 33 хотя это одна и таже запись. Как ты их найдешь?
что делаешь при удалении записи?
Соловьев (2005-09-12 19:22:00) [5]Ав чем прикол XML? Чтобы легче жилось? Тяжело в бинарный файл выгрузить?
Тот же TClientDataSet и FIBPlus...
pasha_golub (2005-09-12 19:04:00) [6]Э-э-э, а если диск с БД навернется? вместе с бекапом...