I can insert table column names dynamically the problem is when I want to insert the new or old values in my log table I am getting a string 'old.Colname' or 'new.Colname' instead of old or new value.
DECLARE C_USER VARCHAR(255);
DECLARE VARIABLE OPERATION_EVENT CHAR(8);
DECLARE GROUPIDNO INT;
DECLARE LOGDATAID_NO INT;
DECLARE VARIABLE FN CHAR(31);
DECLARE VARIABLE NEWCOL CHAR(31);
DECLARE VARIABLE OLDCOL CHAR(31);
BEGIN
SELECT CURRENT_USER FROM RDB$DATABASE INTO :C_USER;
IF (DELETING) THEN
BEGIN
OPERATION_EVENT = 'DELETE';
END
ELSE
BEGIN
IF (UPDATING) THEN
OPERATION_EVENT = 'UPDATE';
ELSE
OPERATION_EVENT = 'INSERT';
END
SELECT MAX(GROUPID) FROM LOG_DATA INTO :GROUPIDNO;
IF(GROUPIDNO IS NULL) THEN
GROUPIDNO = 1;
ELSE
GROUPIDNO = GROUPIDNO + 1;
IF(INSERTING) THEN
BEGIN
FOR SELECT RDB$FIELD_NAME FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'ARAC' INTO :FN DO
BEGIN
OLDCOL = 'old.'||:FN;
NEWCOL = 'new.'||:FN;
INSERT INTO LOG_DATA (OLD_VALUE,NEW_VALUE, COLUMN_NAME, TABLE_NAME, OPERATION,
CREATEDAT,USERS,GROUPID,LOGDATAID)
VALUES (:OLDCOL,:NEWCOL,:FN,'ARAC',trim(:OPERATION_EVENT),
current_timestamp,:C_USER,:GROUPIDNO,:LOGDATAID_NO + 1);
END
END
Here is a screen shot of my log table, I want to insert the old and new values, but column names are being inserted as strings instead
The problem is that you are trying to reference the old and new context as strings, and that is not possible. The specific problem is:
This produces a string with value
'old.<whatever the value of FN is>'
(and same fornew
). It does not produce the value of the column with the name inFN
from theOLD
orNEW
contexts.Unfortunately, it is not possible to dynamically reference the columns in the
OLD
andNEW
contexts by name. You will explicitly need to useOLD.columnname
andNEW.columnname
in your code, which means that you will need to write (or generate) a trigger that inserts each column individually.Alternatively, you could upgrade to Firebird 3, and use a UDR to define a trigger in native code, C# or Java (or other supported languages). These UDR engines allow you to dynamically reference the columns in the old and new context.
As an example, using the FB/Java external engine (check the readme in the repository on how to install FB/Java):
Create a
CHANGELOG
table:And a FB/Java trigger:
This FB/Java trigger is very generic and can be used for multiple tables. I haven't tested this trigger with all datatypes. For example, to be able to make the trigger work correctly with columns of type blob or other binary types will require additional work.
Build the trigger and load it into the database using the fbjava-deployer utility of FB/Java.
Then define the trigger on the table you want (in this case, I defined it on the
TEST_CHANGELOG
table):The external name defines the routine to call (
nl.lawinegevaar.fbjava.experiment.ChangelogTrigger.logChanges()
) and the name of the (single) primary key column of the table (ID
), which is used to log the identifier in theROW_ID
column.