Subject | Re: [firebird-support] I can't use new.FIELD in a EXECUTE STATEMENT called into a Trigger |
---|---|
Author | Hans |
Post date | 2009-07-11T04:28:16Z |
An piece of code I put together just doing that
-------------
ALTER PROCEDURE REPLICATOR_CREATE_TRIGGERS( REP_ACTION
VARCHAR( 32 )
, REPLICATE_GENERATORS
CHAR( 1 )
, REPLICATE_CHANGED_FIELDS_ONLY
CHAR( 1 ) )
AS
/* REPLICATE_GENERATORS: Set to 'Y' for mirror replication */
/* If set to 'N' , Generators will not be replicated and */
/* the source and destination datasets must all have all */
/* generators initially set to a far spread intial value. */
/* REPLICATE_CHANGED_FIELDS_ONLY: Set to 'Y' to create */
/* SELECTS on changed Fields only */
/* */
/* Manually create the next relation first */
/*
CREATE TABLE REP_RELATION_FIELDS_IGNORE
(RELATION_NAME VARCHAR( 93 ) NOT NULL,
FIELD_NAME VARCHAR( 93 ) NOT NULL,
PRIMARY KEY (RELATION_NAME, FIELD_NAME))
*/
/* Step 1. Run on Source Database */
/* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS ('CREATE') */
/* Step 2. Run on Destination Database to set privileges */
/* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS ('CREATE') */
/* */
/* then optional remove the auto generated triggers by */
/* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS ('DELETE') */
/* by Hans Hoogstraat Feb 22, 2009 */
/*
DECLARE VARIABLE REPLICATE_GENERATORS CHAR(1) = 'Y';
DECLARE VARIABLE REPLICATE_CHANGED_FIELDS_ONLY CHAR(1) = 'Y';
*/
/* DEBUGGING: If set to 'Y' the trigger output */
/* will be written to the Relation Description */
DECLARE VARIABLE DEBUGGING CHAR(1) = 'N';
DECLARE VARIABLE SQL_LENGTH VARCHAR(5) = '2000';
DECLARE VARIABLE REPLICATOR_UPDATE_GENERATORS VARCHAR(93) =
'REPLICATOR_UPDATE_GENERATORS';
DECLARE VARIABLE REP_USER_NAME VARCHAR(12) = 'REPLICATOR';
DECLARE VARIABLE REP_RELATIONS_CHANGES VARCHAR(93) =
'REP_RELATIONS_CHANGES';
DECLARE VARIABLE REP_RELATIONS_CHANGES_BI VARCHAR(93) =
'REP_RELATIONS_CHANGES_BI';
DECLARE VARIABLE REP_GENERATORS VARCHAR(93) =
'REP_GENERATORS';
DECLARE VARIABLE REP_TRIGGER_SUFFIX VARCHAR(93) = '_REP';
DECLARE VARIABLE REP_RELATION_FIELDS_IGNORE VARCHAR(93) =
'REP_RELATION_FIELDS_IGNORE';
DECLARE VARIABLE LF CHAR(1);
DECLARE VARIABLE PROCEDURE_NAME VARCHAR(93);
DECLARE VARIABLE RELATION_NAME VARCHAR(93);
DECLARE VARIABLE INDEX_NAME VARCHAR(93);
DECLARE VARIABLE FIELD_NAME VARCHAR(93);
DECLARE VARIABLE TRIGGER_NAME VARCHAR(93);
DECLARE VARIABLE IS_KEY CHAR(5);
DECLARE VARIABLE OUTPUT VARCHAR(31000);
DECLARE VARIABLE FIRST CHAR(1);
DECLARE VARIABLE INDICES_FOUND CHAR(1);
BEGIN
REP_ACTION = UPPER(REP_ACTION);
REPLICATE_GENERATORS = UPPER(REPLICATE_GENERATORS);
REPLICATE_CHANGED_FIELDS_ONLY = UPPER(REPLICATE_CHANGED_FIELDS_ONLY);
LF = ASCII_CHAR(10);
/* Create a Relation holding the Fields to ignore during replication */
/* to be filled in manually and will never be deleted by this procedure */
IF (NOT EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :REP_RELATION_FIELDS_IGNORE)) THEN
BEGIN
OUTPUT = 'CREATE TABLE ' || :REP_RELATION_FIELDS_IGNORE
|| LF || '(RELATION_NAME VARCHAR( 93 ) NOT NULL,'
|| LF || ' FIELD_NAME VARCHAR( 93 ) NOT NULL,'
|| LF || ' PRIMARY KEY (RELATION_NAME, FIELD_NAME) )';
EXECUTE STATEMENT :OUTPUT;
END
/* Add procedure REPLICATOR_DROP_TRIGGERS in case we get stuck */
/* use: SELECT * FROM REPLICATOR_DROP_TRIGGERS */
OUTPUT = 'CREATE OR ALTER PROCEDURE REPLICATOR_DROP_TRIGGERS'
|| LF || 'RETURNS (TEMP VARCHAR (100))'
|| LF || 'AS'
|| LF || 'DECLARE VARIABLE TRIGGER_NAME VARCHAR( 93 );'
|| LF || 'DECLARE VARIABLE OUTPUT VARCHAR(100);'
|| LF || 'BEGIN'
|| LF || 'FOR SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS'
|| LF || ' WHERE TRIM(RDB$TRIGGER_NAME) LIKE ''%_REP'''
|| LF || ' AND RDB$SYSTEM_FLAG = 0'
|| LF || ' AND RDB$TRIGGER_TYPE = 114'
|| LF || ' AND RDB$TRIGGER_SEQUENCE = 20'
|| LF || ' ORDER BY RDB$TRIGGER_NAME'
|| LF || ' INTO :TRIGGER_NAME'
|| LF || 'DO'
|| LF || ' BEGIN'
|| LF || ' OUTPUT = ''DROP TRIGGER '' || :TRIGGER_NAME;'
|| LF || ' EXECUTE STATEMENT :OUTPUT;'
|| LF || ''
|| LF || ' TEMP = OUTPUT;'
|| LF || ' SUSPEND;'
|| LF || ' END'
|| LF || 'END';
EXECUTE STATEMENT :OUTPUT;
FOR SELECT R.RDB$RELATION_NAME
FROM RDB$RELATIONS R
JOIN RDB$INDICES I /* MUST HAVE A PRIMARY INDEX
*/
ON I.RDB$RELATION_NAME = R.RDB$RELATION_NAME
AND I.RDB$UNIQUE_FLAG = 1
WHERE R.RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
AND RDB$VIEW_BLR IS NULL
AND COALESCE(R.RDB$RELATION_TYPE,0) = 0 /* NO TEMPORARY */
AND R.RDB$RELATION_NAME <> :REP_RELATIONS_CHANGES
AND R.RDB$RELATION_NAME <> 'REP_RELATION_FIELDS_IGNORE'
AND NOT EXISTS /* NOT MANUALLY IGNORED */
(SELECT 1 FROM REP_RELATION_FIELDS_IGNORE
WHERE UPPER(RELATION_NAME) = R.RDB$RELATION_NAME AND
COALESCE(FIELD_NAME,'') = '')
ORDER BY R.RDB$RELATION_NAME
INTO :RELATION_NAME
DO
BEGIN
RELATION_NAME = TRIM(RELATION_NAME);
TRIGGER_NAME = RELATION_NAME || REP_TRIGGER_SUFFIX;
IF (REP_ACTION = 'DELETE') THEN
BEGIN
IF (EXISTS (SELECT 1 FROM RDB$TRIGGERS
WHERE RDB$RELATION_NAME = :RELATION_NAME
AND RDB$TRIGGER_NAME = :TRIGGER_NAME)) THEN
BEGIN
OUTPUT = 'DROP TRIGGER '
|| TRIGGER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
END
INDICES_FOUND = '';
FOR SELECT RDB$INDEX_NAME
FROM RDB$INDICES
WHERE RDB$RELATION_NAME = :RELATION_NAME
AND RDB$UNIQUE_FLAG = 1
INTO :INDEX_NAME
DO
BEGIN
INDEX_NAME = TRIM(INDEX_NAME);
INDICES_FOUND = 'Y';
IF (REP_ACTION = 'CREATE') THEN
BEGIN
IF (NOT EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = 'REP_GENERATORS')) THEN
BEGIN
OUTPUT = 'CREATE GLOBAL TEMPORARY TABLE ' || 'REP_GENERATORS'
|| LF || '(GENERATOR_NAME CHAR(93) NOT NULL,'
|| LF || 'PREV_GENERATOR_VALUE DECIMAL(18,0),'
|| LF || 'PRIMARY KEY (GENERATOR_NAME) )'
|| LF || 'ON COMMIT PRESERVE ROWS';
EXECUTE STATEMENT :OUTPUT;
END
IF (NOT EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :REP_RELATIONS_CHANGES)) THEN
BEGIN
OUTPUT = 'CREATE TABLE ' || REP_RELATIONS_CHANGES
|| LF || '(REPLICATION_ID DECIMAL(18,0) NOT NULL,'
|| LF || 'RELATION_ACTION CHAR(1),'
|| LF || 'RELATION_SQL VARCHAR(' || SQL_LENGTH ||
'),'
|| LF || 'PRIMARY KEY (REPLICATION_ID) )';
EXECUTE STATEMENT :OUTPUT;
IF (NOT EXISTS (SELECT 1 FROM RDB$GENERATORS
WHERE RDB$GENERATOR_NAME = 'REPLICATION_ID')) THEN
BEGIN
OUTPUT = 'CREATE GENERATOR REPLICATION_ID';
EXECUTE STATEMENT :OUTPUT;
END
OUTPUT = 'CREATE TRIGGER '
|| 'REP_RELATIONS_CHANGES_BI'
|| ' FOR '
|| REP_RELATIONS_CHANGES
|| LF || 'BEFORE INSERT'
|| LF || 'AS'
|| LF || 'BEGIN'
|| LF || 'IF (NEW.REPLICATION_ID IS NULL) THEN'
|| LF || ' NEW.REPLICATION_ID = GEN_ID(REPLICATION_ID,1);'
|| LF || 'END';
EXECUTE STATEMENT :OUTPUT;
END
/* Create Replicator_Update_Generators Procedure */
IF (REPLICATE_GENERATORS = 'Y') THEN
BEGIN
OUTPUT = 'CREATE OR ALTER PROCEDURE REPLICATOR_UPDATE_GENERATORS'
|| LF || 'AS'
|| LF || 'DECLARE VARIABLE RELATION_ACTION CHAR;'
|| LF || 'DECLARE VARIABLE RELATION_SQL VARCHAR(' ||
SQL_LENGTH || ');'
|| LF || ' '
|| LF || 'DECLARE VARIABLE GENERATOR_NAME
VARCHAR(93);'
|| LF || 'DECLARE VARIABLE GENERATOR_VALUE
DECIMAL(18,0);'
|| LF || 'DECLARE VARIABLE PREV_GENERATOR_VALUE
DECIMAL(18,0);'
|| LF || 'DECLARE VARIABLE OUTPUT
VARCHAR(80);'
|| LF || ' '
|| LF || 'BEGIN'
|| LF || 'RELATION_ACTION = ''G'';'
|| LF || ' '
|| LF || 'FOR SELECT RDB$GENERATOR_NAME'
|| LF || ' FROM RDB$GENERATORS'
|| LF || ' WHERE RDB$SYSTEM_FLAG = 0'
|| LF || ' AND EXISTS (SELECT 1 FROM RDB$DEPENDENCIES'
|| LF || ' WHERE RDB$DEPENDED_ON_NAME =
RDB$GENERATOR_NAME)'
|| LF || ' AND RDB$GENERATOR_NAME <> ''REPLICATION_ID'' '
|| LF || ' INTO :GENERATOR_NAME'
|| LF || 'DO'
|| LF || ' BEGIN'
|| LF || ' '
|| LF || ' GENERATOR_NAME = TRIM(GENERATOR_NAME);'
|| LF || ' '
|| LF || ' OUTPUT = ''SELECT GEN_ID ('' || :GENERATOR_NAME
|| '',0) FROM RDB$DATABASE'';'
|| LF || ' '
|| LF || ' EXECUTE STATEMENT :OUTPUT INTO :GENERATOR_VALUE;'
|| LF || ' '
|| LF || ' SELECT PREV_GENERATOR_VALUE FROM REP_GENERATORS'
|| LF || ' WHERE GENERATOR_NAME = :GENERATOR_NAME'
|| LF || ' INTO :PREV_GENERATOR_VALUE;'
|| LF || ' '
|| LF || ' IF (:PREV_GENERATOR_VALUE IS NULL) THEN'
|| LF || ' INSERT INTO REP_GENERATORS'
|| LF || ' (GENERATOR_NAME, PREV_GENERATOR_VALUE)'
|| LF || ' VALUES'
|| LF || ' (:GENERATOR_NAME, :GENERATOR_VALUE);'
|| LF || ' ELSE'
|| LF || ' UPDATE REP_GENERATORS'
|| LF || ' SET PREV_GENERATOR_VALUE =
:GENERATOR_VALUE'
|| LF || ' WHERE GENERATOR_NAME =
:GENERATOR_NAME;'
|| LF || ' '
|| LF || ' IF (COALESCE(:PREV_GENERATOR_VALUE, 0) <>
:GENERATOR_VALUE) THEN'
|| LF || ' BEGIN'
|| LF || ' RELATION_SQL = ''SET GENERATOR '' ||
:GENERATOR_NAME || '' TO '' || :GENERATOR_VALUE;'
|| LF || ' '
|| LF || ' INSERT INTO REP_RELATIONS_CHANGES'
|| LF || ' ( RELATION_ACTION,'
|| LF || ' RELATION_SQL)'
|| LF || ' VALUES'
|| LF || ' (:RELATION_ACTION,'
|| LF || ' :RELATION_SQL);'
|| LF || ' END'
|| LF || ' END'
|| LF || ' '
|| LF || 'END';
EXECUTE STATEMENT :OUTPUT;
END
OUTPUT = 'CREATE OR ALTER TRIGGER '
|| TRIGGER_NAME
|| ' FOR '
|| RELATION_NAME
|| LF || 'AFTER INSERT OR UPDATE OR DELETE'
|| LF || 'POSITION 20'
|| LF || 'AS'
|| LF || 'DECLARE VARIABLE FIRST CHAR;'
|| LF || 'DECLARE VARIABLE RELATION_ACTION CHAR;'
|| LF || 'DECLARE VARIABLE RELATION_SQL VARCHAR(' ||
SQL_LENGTH || ');'
|| LF || 'BEGIN'
|| LF || ''
|| LF || 'IF (USER <> ''' || REP_USER_NAME || ''') THEN'
|| LF || ' BEGIN'
|| LF || ''
|| LF || ' /* Auto Generated Trigger for Replication.
*/'
|| LF || ' /* by Hans Hoogstraat Feb 22, 2009
*/'
|| LF || ''
|| LF || ' /* by
*/'
|| LF || ' /* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS
(''CREATE'') */'
|| LF || ''
|| LF || ' /* and can be removed from all relations by
*/'
|| LF || ' /* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS
(''DELETE'') */'
|| LF || ''
|| LF || ' RELATION_ACTION = CASE'
|| LF || ' WHEN INSERTING THEN ''I'' '
|| LF || ' WHEN UPDATING THEN ''U'' '
|| LF || ' WHEN DELETING THEN ''D'' '
|| LF || ' END;'
|| LF || ''
|| LF || ' IF (DELETING) THEN'
|| LF || ' BEGIN'
|| LF || ''
|| LF || ' RELATION_SQL = ''DELETE FROM ' || RELATION_NAME
|| '''';
FIRST = '';
FOR SELECT S.RDB$FIELD_NAME
FROM RDB$INDEX_SEGMENTS S
WHERE S.RDB$INDEX_NAME = :INDEX_NAME
INTO :FIELD_NAME
DO
BEGIN
FIELD_NAME = TRIM(FIELD_NAME);
IF (FIRST = '') THEN
BEGIN
OUTPUT = OUTPUT || LF || ' || '' WHERE ' || FIELD_NAME || ' =
'
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ';
END
ELSE
BEGIN
OUTPUT = OUTPUT || LF || ' || '' AND ' || FIELD_NAME || ' = '
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ';
END
FIRST = 'N';
END
IF (REPLICATE_CHANGED_FIELDS_ONLY = 'Y') THEN
FIRST = ';';
ELSE
FIRST = '';
OUTPUT = OUTPUT || ';'
|| LF || ' END'
|| LF || ' ELSE'
|| LF || ' BEGIN'
|| LF || ''
|| LF || ' FIRST = '' '';'
|| LF || ''
|| LF || ' RELATION_SQL = ''SELECT ''' || FIRST;
FIRST = ' ';
FOR SELECT S.RDB$FIELD_NAME
FROM RDB$RELATION_FIELDS S
WHERE S.RDB$RELATION_NAME = :RELATION_NAME
AND NOT EXISTS
(SELECT 1 FROM REP_RELATION_FIELDS_IGNORE R
WHERE UPPER(R.FIELD_NAME) = S.RDB$FIELD_NAME
AND UPPER(R.RELATION_NAME) = :RELATION_NAME)
ORDER BY RDB$FIELD_POSITION
INTO :FIELD_NAME
DO
BEGIN
FIELD_NAME = TRIM(FIELD_NAME);
IF (REPLICATE_CHANGED_FIELDS_ONLY = 'Y') THEN
BEGIN
IF (EXISTS (SELECT 1
FROM RDB$INDEX_SEGMENTS S
WHERE S.RDB$INDEX_NAME = :INDEX_NAME
AND S.RDB$FIELD_NAME = :FIELD_NAME)) THEN
IS_KEY = '1 = 1';
ELSE
IS_KEY = '0 = 1';
OUTPUT = OUTPUT || LF || LF || ' IF (' || IS_KEY || ' OR
INSERTING OR (UPDATING AND NEW.' || :FIELD_NAME
|| ' IS DISTINCT FROM OLD.' || :FIELD_NAME || '))
THEN'
|| LF || ' BEGIN'
|| LF || ' RELATION_SQL = RELATION_SQL ||
FIRST || ''' || :FIELD_NAME || ''';'
|| LF || ' FIRST = '','';'
|| LF || ' END' ;
END
ELSE
OUTPUT = OUTPUT || LF || ' || ''' || FIRST || :FIELD_NAME
|| '''';
FIRST = ',';
END
IF (REPLICATE_CHANGED_FIELDS_ONLY = 'Y') THEN
OUTPUT = OUTPUT || LF || LF || ' RELATION_SQL = RELATION_SQL ||
'' FROM ' || RELATION_NAME || ''';';
ELSE
OUTPUT = OUTPUT || LF || ' || '' FROM ' || RELATION_NAME ||
''';';
FIRST = '';
FOR SELECT S.RDB$FIELD_NAME
FROM RDB$INDEX_SEGMENTS S
WHERE S.RDB$INDEX_NAME = :INDEX_NAME
INTO :FIELD_NAME
DO
BEGIN
FIELD_NAME = TRIM(FIELD_NAME);
IF (FIRST = '') THEN
BEGIN
OUTPUT = OUTPUT || LF
|| LF || ' IF (INSERTING) THEN'
|| LF || ' RELATION_SQL = RELATION_SQL || '' WHERE ' ||
FIELD_NAME || ' = '
|| ' '''''' || NEW.' || FIELD_NAME || ' || '''''''' ;'
|| LF || ' ELSE'
|| LF || ' RELATION_SQL = RELATION_SQL || '' WHERE ' ||
FIELD_NAME || ' = '
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ;';
END
ELSE
BEGIN
OUTPUT = OUTPUT || LF
|| LF || ' IF (INSERTING) THEN'
|| LF || ' RELATION_SQL = RELATION_SQL || '' AND ' ||
FIELD_NAME || ' = '
|| ' '''''' || NEW.' || FIELD_NAME || ' || '''''''' ;'
|| LF || ' ELSE'
|| LF || ' RELATION_SQL = RELATION_SQL || '' AND ' ||
FIELD_NAME || ' = '
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ;';
END
FIRST = ',';
END
OUTPUT = OUTPUT || LF || ' END';
OUTPUT = OUTPUT
|| LF || ''
|| LF || ' INSERT INTO REP_RELATIONS_CHANGES'
|| LF || ' ( RELATION_ACTION,'
|| LF || ' RELATION_SQL)'
|| LF || ' VALUES'
|| LF || ' (:RELATION_ACTION,'
|| LF || ' :RELATION_SQL);';
IF (REPLICATE_GENERATORS = 'Y') THEN
BEGIN
OUTPUT = OUTPUT
|| LF || ''
|| LF || ' IF (INSERTING) THEN'
|| LF || ' EXECUTE PROCEDURE
REPLICATOR_UPDATE_GENERATORS;';
END
OUTPUT = OUTPUT
|| LF || ''
|| LF || ' END'
|| LF || ''
|| LF || 'END';
IF (INDICES_FOUND = 'Y') THEN
BEGIN
IF (DEBUGGING = 'Y') THEN /* Write Trigger code to Relation
Description */
BEGIN
UPDATE RDB$RELATIONS
SET RDB$DESCRIPTION = :OUTPUT
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :RELATION_NAME;
END
ELSE /* Create the actual Relation Trigger */
BEGIN
EXECUTE STATEMENT :OUTPUT;
END
END
END
END
END
IF (REP_ACTION = 'CREATE') THEN
BEGIN
FOR SELECT RDB$RELATION_NAME
FROM RDB$RELATIONS
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
AND RDB$VIEW_BLR IS NULL
INTO :RELATION_NAME
DO
BEGIN
RELATION_NAME = TRIM(RELATION_NAME);
/* GRANT DELETE, INSERT, SELECT, UPDATE, REFERENCES */
OUTPUT = 'GRANT ALL ON TABLE ' || :RELATION_NAME || ' TO ' ||
:REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
FOR SELECT RDB$PROCEDURE_NAME FROM RDB$PROCEDURES
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
INTO :PROCEDURE_NAME
DO
BEGIN
PROCEDURE_NAME = TRIM(PROCEDURE_NAME);
OUTPUT = 'GRANT EXECUTE ON PROCEDURE ' || :PROCEDURE_NAME || ' TO ' ||
:REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
END
IF (REP_ACTION = 'DELETE') THEN
BEGIN
IF (EXISTS (SELECT 1 FROM RDB$PROCEDURES
WHERE RDB$PROCEDURE_NAME = 'REPLICATOR_UPDATE_GENERATORS')) THEN
BEGIN
OUTPUT = 'DROP PROCEDURE ' || 'REPLICATOR_UPDATE_GENERATORS';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$TRIGGERS
WHERE RDB$TRIGGER_NAME = 'REP_RELATIONS_CHANGES_BI')) THEN
BEGIN
OUTPUT = 'DROP TRIGGER ' || 'REP_RELATIONS_CHANGES_BI';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$GENERATORS
WHERE RDB$GENERATOR_NAME = 'REPLICATION_ID')) THEN
BEGIN
OUTPUT = 'DROP GENERATOR REPLICATION_ID';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = 'REP_GENERATORS')) THEN
BEGIN
OUTPUT = 'DROP TABLE ' || 'REP_GENERATORS';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :REP_RELATIONS_CHANGES)) THEN
BEGIN
OUTPUT = 'DROP TABLE ' || REP_RELATIONS_CHANGES;
EXECUTE STATEMENT :OUTPUT;
END
IF (0 = 1) THEN /* Keep the rights */
FOR SELECT RDB$RELATION_NAME FROM RDB$RELATIONS
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
AND RDB$VIEW_BLR IS NULL
INTO :RELATION_NAME
DO
BEGIN
RELATION_NAME = TRIM(RELATION_NAME);
OUTPUT = 'REVOKE ALL ON TABLE ' || :RELATION_NAME || ' FROM ' ||
:REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
IF (0 = 1) THEN /* Keep the rights */
FOR SELECT RDB$PROCEDURE_NAME FROM RDB$PROCEDURES
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
INTO :PROCEDURE_NAME
DO
BEGIN
PROCEDURE_NAME = TRIM(PROCEDURE_NAME);
OUTPUT = 'REVOKE EXECUTE ON PROCEDURE ' || :PROCEDURE_NAME || ' FROM '
|| :REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
FOR SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS
WHERE TRIM(RDB$TRIGGER_NAME) LIKE '%' || :REP_TRIGGER_SUFFIX
AND RDB$SYSTEM_FLAG = 0
AND RDB$TRIGGER_TYPE = 114
AND RDB$TRIGGER_SEQUENCE = 20
ORDER BY RDB$TRIGGER_NAME
INTO :TRIGGER_NAME
DO
BEGIN
OUTPUT = 'DROP TRIGGER ' || :TRIGGER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
END
END
------------------------
-------------
ALTER PROCEDURE REPLICATOR_CREATE_TRIGGERS( REP_ACTION
VARCHAR( 32 )
, REPLICATE_GENERATORS
CHAR( 1 )
, REPLICATE_CHANGED_FIELDS_ONLY
CHAR( 1 ) )
AS
/* REPLICATE_GENERATORS: Set to 'Y' for mirror replication */
/* If set to 'N' , Generators will not be replicated and */
/* the source and destination datasets must all have all */
/* generators initially set to a far spread intial value. */
/* REPLICATE_CHANGED_FIELDS_ONLY: Set to 'Y' to create */
/* SELECTS on changed Fields only */
/* */
/* Manually create the next relation first */
/*
CREATE TABLE REP_RELATION_FIELDS_IGNORE
(RELATION_NAME VARCHAR( 93 ) NOT NULL,
FIELD_NAME VARCHAR( 93 ) NOT NULL,
PRIMARY KEY (RELATION_NAME, FIELD_NAME))
*/
/* Step 1. Run on Source Database */
/* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS ('CREATE') */
/* Step 2. Run on Destination Database to set privileges */
/* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS ('CREATE') */
/* */
/* then optional remove the auto generated triggers by */
/* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS ('DELETE') */
/* by Hans Hoogstraat Feb 22, 2009 */
/*
DECLARE VARIABLE REPLICATE_GENERATORS CHAR(1) = 'Y';
DECLARE VARIABLE REPLICATE_CHANGED_FIELDS_ONLY CHAR(1) = 'Y';
*/
/* DEBUGGING: If set to 'Y' the trigger output */
/* will be written to the Relation Description */
DECLARE VARIABLE DEBUGGING CHAR(1) = 'N';
DECLARE VARIABLE SQL_LENGTH VARCHAR(5) = '2000';
DECLARE VARIABLE REPLICATOR_UPDATE_GENERATORS VARCHAR(93) =
'REPLICATOR_UPDATE_GENERATORS';
DECLARE VARIABLE REP_USER_NAME VARCHAR(12) = 'REPLICATOR';
DECLARE VARIABLE REP_RELATIONS_CHANGES VARCHAR(93) =
'REP_RELATIONS_CHANGES';
DECLARE VARIABLE REP_RELATIONS_CHANGES_BI VARCHAR(93) =
'REP_RELATIONS_CHANGES_BI';
DECLARE VARIABLE REP_GENERATORS VARCHAR(93) =
'REP_GENERATORS';
DECLARE VARIABLE REP_TRIGGER_SUFFIX VARCHAR(93) = '_REP';
DECLARE VARIABLE REP_RELATION_FIELDS_IGNORE VARCHAR(93) =
'REP_RELATION_FIELDS_IGNORE';
DECLARE VARIABLE LF CHAR(1);
DECLARE VARIABLE PROCEDURE_NAME VARCHAR(93);
DECLARE VARIABLE RELATION_NAME VARCHAR(93);
DECLARE VARIABLE INDEX_NAME VARCHAR(93);
DECLARE VARIABLE FIELD_NAME VARCHAR(93);
DECLARE VARIABLE TRIGGER_NAME VARCHAR(93);
DECLARE VARIABLE IS_KEY CHAR(5);
DECLARE VARIABLE OUTPUT VARCHAR(31000);
DECLARE VARIABLE FIRST CHAR(1);
DECLARE VARIABLE INDICES_FOUND CHAR(1);
BEGIN
REP_ACTION = UPPER(REP_ACTION);
REPLICATE_GENERATORS = UPPER(REPLICATE_GENERATORS);
REPLICATE_CHANGED_FIELDS_ONLY = UPPER(REPLICATE_CHANGED_FIELDS_ONLY);
LF = ASCII_CHAR(10);
/* Create a Relation holding the Fields to ignore during replication */
/* to be filled in manually and will never be deleted by this procedure */
IF (NOT EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :REP_RELATION_FIELDS_IGNORE)) THEN
BEGIN
OUTPUT = 'CREATE TABLE ' || :REP_RELATION_FIELDS_IGNORE
|| LF || '(RELATION_NAME VARCHAR( 93 ) NOT NULL,'
|| LF || ' FIELD_NAME VARCHAR( 93 ) NOT NULL,'
|| LF || ' PRIMARY KEY (RELATION_NAME, FIELD_NAME) )';
EXECUTE STATEMENT :OUTPUT;
END
/* Add procedure REPLICATOR_DROP_TRIGGERS in case we get stuck */
/* use: SELECT * FROM REPLICATOR_DROP_TRIGGERS */
OUTPUT = 'CREATE OR ALTER PROCEDURE REPLICATOR_DROP_TRIGGERS'
|| LF || 'RETURNS (TEMP VARCHAR (100))'
|| LF || 'AS'
|| LF || 'DECLARE VARIABLE TRIGGER_NAME VARCHAR( 93 );'
|| LF || 'DECLARE VARIABLE OUTPUT VARCHAR(100);'
|| LF || 'BEGIN'
|| LF || 'FOR SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS'
|| LF || ' WHERE TRIM(RDB$TRIGGER_NAME) LIKE ''%_REP'''
|| LF || ' AND RDB$SYSTEM_FLAG = 0'
|| LF || ' AND RDB$TRIGGER_TYPE = 114'
|| LF || ' AND RDB$TRIGGER_SEQUENCE = 20'
|| LF || ' ORDER BY RDB$TRIGGER_NAME'
|| LF || ' INTO :TRIGGER_NAME'
|| LF || 'DO'
|| LF || ' BEGIN'
|| LF || ' OUTPUT = ''DROP TRIGGER '' || :TRIGGER_NAME;'
|| LF || ' EXECUTE STATEMENT :OUTPUT;'
|| LF || ''
|| LF || ' TEMP = OUTPUT;'
|| LF || ' SUSPEND;'
|| LF || ' END'
|| LF || 'END';
EXECUTE STATEMENT :OUTPUT;
FOR SELECT R.RDB$RELATION_NAME
FROM RDB$RELATIONS R
JOIN RDB$INDICES I /* MUST HAVE A PRIMARY INDEX
*/
ON I.RDB$RELATION_NAME = R.RDB$RELATION_NAME
AND I.RDB$UNIQUE_FLAG = 1
WHERE R.RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
AND RDB$VIEW_BLR IS NULL
AND COALESCE(R.RDB$RELATION_TYPE,0) = 0 /* NO TEMPORARY */
AND R.RDB$RELATION_NAME <> :REP_RELATIONS_CHANGES
AND R.RDB$RELATION_NAME <> 'REP_RELATION_FIELDS_IGNORE'
AND NOT EXISTS /* NOT MANUALLY IGNORED */
(SELECT 1 FROM REP_RELATION_FIELDS_IGNORE
WHERE UPPER(RELATION_NAME) = R.RDB$RELATION_NAME AND
COALESCE(FIELD_NAME,'') = '')
ORDER BY R.RDB$RELATION_NAME
INTO :RELATION_NAME
DO
BEGIN
RELATION_NAME = TRIM(RELATION_NAME);
TRIGGER_NAME = RELATION_NAME || REP_TRIGGER_SUFFIX;
IF (REP_ACTION = 'DELETE') THEN
BEGIN
IF (EXISTS (SELECT 1 FROM RDB$TRIGGERS
WHERE RDB$RELATION_NAME = :RELATION_NAME
AND RDB$TRIGGER_NAME = :TRIGGER_NAME)) THEN
BEGIN
OUTPUT = 'DROP TRIGGER '
|| TRIGGER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
END
INDICES_FOUND = '';
FOR SELECT RDB$INDEX_NAME
FROM RDB$INDICES
WHERE RDB$RELATION_NAME = :RELATION_NAME
AND RDB$UNIQUE_FLAG = 1
INTO :INDEX_NAME
DO
BEGIN
INDEX_NAME = TRIM(INDEX_NAME);
INDICES_FOUND = 'Y';
IF (REP_ACTION = 'CREATE') THEN
BEGIN
IF (NOT EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = 'REP_GENERATORS')) THEN
BEGIN
OUTPUT = 'CREATE GLOBAL TEMPORARY TABLE ' || 'REP_GENERATORS'
|| LF || '(GENERATOR_NAME CHAR(93) NOT NULL,'
|| LF || 'PREV_GENERATOR_VALUE DECIMAL(18,0),'
|| LF || 'PRIMARY KEY (GENERATOR_NAME) )'
|| LF || 'ON COMMIT PRESERVE ROWS';
EXECUTE STATEMENT :OUTPUT;
END
IF (NOT EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :REP_RELATIONS_CHANGES)) THEN
BEGIN
OUTPUT = 'CREATE TABLE ' || REP_RELATIONS_CHANGES
|| LF || '(REPLICATION_ID DECIMAL(18,0) NOT NULL,'
|| LF || 'RELATION_ACTION CHAR(1),'
|| LF || 'RELATION_SQL VARCHAR(' || SQL_LENGTH ||
'),'
|| LF || 'PRIMARY KEY (REPLICATION_ID) )';
EXECUTE STATEMENT :OUTPUT;
IF (NOT EXISTS (SELECT 1 FROM RDB$GENERATORS
WHERE RDB$GENERATOR_NAME = 'REPLICATION_ID')) THEN
BEGIN
OUTPUT = 'CREATE GENERATOR REPLICATION_ID';
EXECUTE STATEMENT :OUTPUT;
END
OUTPUT = 'CREATE TRIGGER '
|| 'REP_RELATIONS_CHANGES_BI'
|| ' FOR '
|| REP_RELATIONS_CHANGES
|| LF || 'BEFORE INSERT'
|| LF || 'AS'
|| LF || 'BEGIN'
|| LF || 'IF (NEW.REPLICATION_ID IS NULL) THEN'
|| LF || ' NEW.REPLICATION_ID = GEN_ID(REPLICATION_ID,1);'
|| LF || 'END';
EXECUTE STATEMENT :OUTPUT;
END
/* Create Replicator_Update_Generators Procedure */
IF (REPLICATE_GENERATORS = 'Y') THEN
BEGIN
OUTPUT = 'CREATE OR ALTER PROCEDURE REPLICATOR_UPDATE_GENERATORS'
|| LF || 'AS'
|| LF || 'DECLARE VARIABLE RELATION_ACTION CHAR;'
|| LF || 'DECLARE VARIABLE RELATION_SQL VARCHAR(' ||
SQL_LENGTH || ');'
|| LF || ' '
|| LF || 'DECLARE VARIABLE GENERATOR_NAME
VARCHAR(93);'
|| LF || 'DECLARE VARIABLE GENERATOR_VALUE
DECIMAL(18,0);'
|| LF || 'DECLARE VARIABLE PREV_GENERATOR_VALUE
DECIMAL(18,0);'
|| LF || 'DECLARE VARIABLE OUTPUT
VARCHAR(80);'
|| LF || ' '
|| LF || 'BEGIN'
|| LF || 'RELATION_ACTION = ''G'';'
|| LF || ' '
|| LF || 'FOR SELECT RDB$GENERATOR_NAME'
|| LF || ' FROM RDB$GENERATORS'
|| LF || ' WHERE RDB$SYSTEM_FLAG = 0'
|| LF || ' AND EXISTS (SELECT 1 FROM RDB$DEPENDENCIES'
|| LF || ' WHERE RDB$DEPENDED_ON_NAME =
RDB$GENERATOR_NAME)'
|| LF || ' AND RDB$GENERATOR_NAME <> ''REPLICATION_ID'' '
|| LF || ' INTO :GENERATOR_NAME'
|| LF || 'DO'
|| LF || ' BEGIN'
|| LF || ' '
|| LF || ' GENERATOR_NAME = TRIM(GENERATOR_NAME);'
|| LF || ' '
|| LF || ' OUTPUT = ''SELECT GEN_ID ('' || :GENERATOR_NAME
|| '',0) FROM RDB$DATABASE'';'
|| LF || ' '
|| LF || ' EXECUTE STATEMENT :OUTPUT INTO :GENERATOR_VALUE;'
|| LF || ' '
|| LF || ' SELECT PREV_GENERATOR_VALUE FROM REP_GENERATORS'
|| LF || ' WHERE GENERATOR_NAME = :GENERATOR_NAME'
|| LF || ' INTO :PREV_GENERATOR_VALUE;'
|| LF || ' '
|| LF || ' IF (:PREV_GENERATOR_VALUE IS NULL) THEN'
|| LF || ' INSERT INTO REP_GENERATORS'
|| LF || ' (GENERATOR_NAME, PREV_GENERATOR_VALUE)'
|| LF || ' VALUES'
|| LF || ' (:GENERATOR_NAME, :GENERATOR_VALUE);'
|| LF || ' ELSE'
|| LF || ' UPDATE REP_GENERATORS'
|| LF || ' SET PREV_GENERATOR_VALUE =
:GENERATOR_VALUE'
|| LF || ' WHERE GENERATOR_NAME =
:GENERATOR_NAME;'
|| LF || ' '
|| LF || ' IF (COALESCE(:PREV_GENERATOR_VALUE, 0) <>
:GENERATOR_VALUE) THEN'
|| LF || ' BEGIN'
|| LF || ' RELATION_SQL = ''SET GENERATOR '' ||
:GENERATOR_NAME || '' TO '' || :GENERATOR_VALUE;'
|| LF || ' '
|| LF || ' INSERT INTO REP_RELATIONS_CHANGES'
|| LF || ' ( RELATION_ACTION,'
|| LF || ' RELATION_SQL)'
|| LF || ' VALUES'
|| LF || ' (:RELATION_ACTION,'
|| LF || ' :RELATION_SQL);'
|| LF || ' END'
|| LF || ' END'
|| LF || ' '
|| LF || 'END';
EXECUTE STATEMENT :OUTPUT;
END
OUTPUT = 'CREATE OR ALTER TRIGGER '
|| TRIGGER_NAME
|| ' FOR '
|| RELATION_NAME
|| LF || 'AFTER INSERT OR UPDATE OR DELETE'
|| LF || 'POSITION 20'
|| LF || 'AS'
|| LF || 'DECLARE VARIABLE FIRST CHAR;'
|| LF || 'DECLARE VARIABLE RELATION_ACTION CHAR;'
|| LF || 'DECLARE VARIABLE RELATION_SQL VARCHAR(' ||
SQL_LENGTH || ');'
|| LF || 'BEGIN'
|| LF || ''
|| LF || 'IF (USER <> ''' || REP_USER_NAME || ''') THEN'
|| LF || ' BEGIN'
|| LF || ''
|| LF || ' /* Auto Generated Trigger for Replication.
*/'
|| LF || ' /* by Hans Hoogstraat Feb 22, 2009
*/'
|| LF || ''
|| LF || ' /* by
*/'
|| LF || ' /* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS
(''CREATE'') */'
|| LF || ''
|| LF || ' /* and can be removed from all relations by
*/'
|| LF || ' /* EXECUTE PROCEDURE REPLICATOR_CREATE_TRIGGERS
(''DELETE'') */'
|| LF || ''
|| LF || ' RELATION_ACTION = CASE'
|| LF || ' WHEN INSERTING THEN ''I'' '
|| LF || ' WHEN UPDATING THEN ''U'' '
|| LF || ' WHEN DELETING THEN ''D'' '
|| LF || ' END;'
|| LF || ''
|| LF || ' IF (DELETING) THEN'
|| LF || ' BEGIN'
|| LF || ''
|| LF || ' RELATION_SQL = ''DELETE FROM ' || RELATION_NAME
|| '''';
FIRST = '';
FOR SELECT S.RDB$FIELD_NAME
FROM RDB$INDEX_SEGMENTS S
WHERE S.RDB$INDEX_NAME = :INDEX_NAME
INTO :FIELD_NAME
DO
BEGIN
FIELD_NAME = TRIM(FIELD_NAME);
IF (FIRST = '') THEN
BEGIN
OUTPUT = OUTPUT || LF || ' || '' WHERE ' || FIELD_NAME || ' =
'
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ';
END
ELSE
BEGIN
OUTPUT = OUTPUT || LF || ' || '' AND ' || FIELD_NAME || ' = '
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ';
END
FIRST = 'N';
END
IF (REPLICATE_CHANGED_FIELDS_ONLY = 'Y') THEN
FIRST = ';';
ELSE
FIRST = '';
OUTPUT = OUTPUT || ';'
|| LF || ' END'
|| LF || ' ELSE'
|| LF || ' BEGIN'
|| LF || ''
|| LF || ' FIRST = '' '';'
|| LF || ''
|| LF || ' RELATION_SQL = ''SELECT ''' || FIRST;
FIRST = ' ';
FOR SELECT S.RDB$FIELD_NAME
FROM RDB$RELATION_FIELDS S
WHERE S.RDB$RELATION_NAME = :RELATION_NAME
AND NOT EXISTS
(SELECT 1 FROM REP_RELATION_FIELDS_IGNORE R
WHERE UPPER(R.FIELD_NAME) = S.RDB$FIELD_NAME
AND UPPER(R.RELATION_NAME) = :RELATION_NAME)
ORDER BY RDB$FIELD_POSITION
INTO :FIELD_NAME
DO
BEGIN
FIELD_NAME = TRIM(FIELD_NAME);
IF (REPLICATE_CHANGED_FIELDS_ONLY = 'Y') THEN
BEGIN
IF (EXISTS (SELECT 1
FROM RDB$INDEX_SEGMENTS S
WHERE S.RDB$INDEX_NAME = :INDEX_NAME
AND S.RDB$FIELD_NAME = :FIELD_NAME)) THEN
IS_KEY = '1 = 1';
ELSE
IS_KEY = '0 = 1';
OUTPUT = OUTPUT || LF || LF || ' IF (' || IS_KEY || ' OR
INSERTING OR (UPDATING AND NEW.' || :FIELD_NAME
|| ' IS DISTINCT FROM OLD.' || :FIELD_NAME || '))
THEN'
|| LF || ' BEGIN'
|| LF || ' RELATION_SQL = RELATION_SQL ||
FIRST || ''' || :FIELD_NAME || ''';'
|| LF || ' FIRST = '','';'
|| LF || ' END' ;
END
ELSE
OUTPUT = OUTPUT || LF || ' || ''' || FIRST || :FIELD_NAME
|| '''';
FIRST = ',';
END
IF (REPLICATE_CHANGED_FIELDS_ONLY = 'Y') THEN
OUTPUT = OUTPUT || LF || LF || ' RELATION_SQL = RELATION_SQL ||
'' FROM ' || RELATION_NAME || ''';';
ELSE
OUTPUT = OUTPUT || LF || ' || '' FROM ' || RELATION_NAME ||
''';';
FIRST = '';
FOR SELECT S.RDB$FIELD_NAME
FROM RDB$INDEX_SEGMENTS S
WHERE S.RDB$INDEX_NAME = :INDEX_NAME
INTO :FIELD_NAME
DO
BEGIN
FIELD_NAME = TRIM(FIELD_NAME);
IF (FIRST = '') THEN
BEGIN
OUTPUT = OUTPUT || LF
|| LF || ' IF (INSERTING) THEN'
|| LF || ' RELATION_SQL = RELATION_SQL || '' WHERE ' ||
FIELD_NAME || ' = '
|| ' '''''' || NEW.' || FIELD_NAME || ' || '''''''' ;'
|| LF || ' ELSE'
|| LF || ' RELATION_SQL = RELATION_SQL || '' WHERE ' ||
FIELD_NAME || ' = '
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ;';
END
ELSE
BEGIN
OUTPUT = OUTPUT || LF
|| LF || ' IF (INSERTING) THEN'
|| LF || ' RELATION_SQL = RELATION_SQL || '' AND ' ||
FIELD_NAME || ' = '
|| ' '''''' || NEW.' || FIELD_NAME || ' || '''''''' ;'
|| LF || ' ELSE'
|| LF || ' RELATION_SQL = RELATION_SQL || '' AND ' ||
FIELD_NAME || ' = '
|| ' '''''' || OLD.' || FIELD_NAME || ' || '''''''' ;';
END
FIRST = ',';
END
OUTPUT = OUTPUT || LF || ' END';
OUTPUT = OUTPUT
|| LF || ''
|| LF || ' INSERT INTO REP_RELATIONS_CHANGES'
|| LF || ' ( RELATION_ACTION,'
|| LF || ' RELATION_SQL)'
|| LF || ' VALUES'
|| LF || ' (:RELATION_ACTION,'
|| LF || ' :RELATION_SQL);';
IF (REPLICATE_GENERATORS = 'Y') THEN
BEGIN
OUTPUT = OUTPUT
|| LF || ''
|| LF || ' IF (INSERTING) THEN'
|| LF || ' EXECUTE PROCEDURE
REPLICATOR_UPDATE_GENERATORS;';
END
OUTPUT = OUTPUT
|| LF || ''
|| LF || ' END'
|| LF || ''
|| LF || 'END';
IF (INDICES_FOUND = 'Y') THEN
BEGIN
IF (DEBUGGING = 'Y') THEN /* Write Trigger code to Relation
Description */
BEGIN
UPDATE RDB$RELATIONS
SET RDB$DESCRIPTION = :OUTPUT
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :RELATION_NAME;
END
ELSE /* Create the actual Relation Trigger */
BEGIN
EXECUTE STATEMENT :OUTPUT;
END
END
END
END
END
IF (REP_ACTION = 'CREATE') THEN
BEGIN
FOR SELECT RDB$RELATION_NAME
FROM RDB$RELATIONS
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
AND RDB$VIEW_BLR IS NULL
INTO :RELATION_NAME
DO
BEGIN
RELATION_NAME = TRIM(RELATION_NAME);
/* GRANT DELETE, INSERT, SELECT, UPDATE, REFERENCES */
OUTPUT = 'GRANT ALL ON TABLE ' || :RELATION_NAME || ' TO ' ||
:REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
FOR SELECT RDB$PROCEDURE_NAME FROM RDB$PROCEDURES
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
INTO :PROCEDURE_NAME
DO
BEGIN
PROCEDURE_NAME = TRIM(PROCEDURE_NAME);
OUTPUT = 'GRANT EXECUTE ON PROCEDURE ' || :PROCEDURE_NAME || ' TO ' ||
:REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
END
IF (REP_ACTION = 'DELETE') THEN
BEGIN
IF (EXISTS (SELECT 1 FROM RDB$PROCEDURES
WHERE RDB$PROCEDURE_NAME = 'REPLICATOR_UPDATE_GENERATORS')) THEN
BEGIN
OUTPUT = 'DROP PROCEDURE ' || 'REPLICATOR_UPDATE_GENERATORS';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$TRIGGERS
WHERE RDB$TRIGGER_NAME = 'REP_RELATIONS_CHANGES_BI')) THEN
BEGIN
OUTPUT = 'DROP TRIGGER ' || 'REP_RELATIONS_CHANGES_BI';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$GENERATORS
WHERE RDB$GENERATOR_NAME = 'REPLICATION_ID')) THEN
BEGIN
OUTPUT = 'DROP GENERATOR REPLICATION_ID';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = 'REP_GENERATORS')) THEN
BEGIN
OUTPUT = 'DROP TABLE ' || 'REP_GENERATORS';
EXECUTE STATEMENT :OUTPUT;
END
IF (EXISTS (SELECT 1 FROM RDB$RELATIONS
WHERE RDB$VIEW_BLR IS NULL
AND RDB$RELATION_NAME = :REP_RELATIONS_CHANGES)) THEN
BEGIN
OUTPUT = 'DROP TABLE ' || REP_RELATIONS_CHANGES;
EXECUTE STATEMENT :OUTPUT;
END
IF (0 = 1) THEN /* Keep the rights */
FOR SELECT RDB$RELATION_NAME FROM RDB$RELATIONS
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
AND RDB$VIEW_BLR IS NULL
INTO :RELATION_NAME
DO
BEGIN
RELATION_NAME = TRIM(RELATION_NAME);
OUTPUT = 'REVOKE ALL ON TABLE ' || :RELATION_NAME || ' FROM ' ||
:REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
IF (0 = 1) THEN /* Keep the rights */
FOR SELECT RDB$PROCEDURE_NAME FROM RDB$PROCEDURES
WHERE RDB$SYSTEM_FLAG = 0 /* NO SYSTEM RELATIONS */
INTO :PROCEDURE_NAME
DO
BEGIN
PROCEDURE_NAME = TRIM(PROCEDURE_NAME);
OUTPUT = 'REVOKE EXECUTE ON PROCEDURE ' || :PROCEDURE_NAME || ' FROM '
|| :REP_USER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
FOR SELECT RDB$TRIGGER_NAME FROM RDB$TRIGGERS
WHERE TRIM(RDB$TRIGGER_NAME) LIKE '%' || :REP_TRIGGER_SUFFIX
AND RDB$SYSTEM_FLAG = 0
AND RDB$TRIGGER_TYPE = 114
AND RDB$TRIGGER_SEQUENCE = 20
ORDER BY RDB$TRIGGER_NAME
INTO :TRIGGER_NAME
DO
BEGIN
OUTPUT = 'DROP TRIGGER ' || :TRIGGER_NAME;
EXECUTE STATEMENT :OUTPUT;
END
END
END
------------------------
----- Original Message -----
From: "marc_guillot" <marc_guillot@...>
To: <firebird-support@yahoogroups.com>
Sent: Friday, July 10, 2009 1:45 PM
Subject: [firebird-support] I can't use new.FIELD in a EXECUTE STATEMENT
called into a Trigger
Hello.
In a very simple sample, into a Trigger I can use :
select new.ROW_ID from rdb$database into :ROW_ID
But using EXECUTE STATEMENT this doesn't works :
SQL = 'select new.ROW_ID from rdb$database';
execute statement :SQL into :ROW_ID;
¿ There is any way to access to new. and old. trigger fields into an EXECUTE
STATEMENT call ?
I'm writing some logging triggers that will look at all the fields of the
table (using the system tables) and logging new values of which have
changed.
Thank you.
------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Visit http://www.firebirdsql.org and click the Resources item
on the main (top) menu. Try Knowledgebase and FAQ links !
Also search the knowledgebases at http://www.ibphoenix.com
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Yahoo! Groups Links