I've got a Firebird database where I want to ensure that every row can be edited by at most one user at a time. For that, I want to put an OWNER
column on every applicable table. It would be a bit tedious to do this by hand for every table, so I tried writing up a way to automate it. First, create a view that gives you all tables that need to be updated:
CREATE VIEW OWNABLE_TABLES_V
(
NAME
)
AS
SELECT tables.RDB$RELATION_NAME
FROM RDB$RELATIONS tables
WHERE (tables.RDB$SYSTEM_FLAG=0) and (tables.rdb$view_source is null)
and not exists (
--table containing names of tables that are exceptions to the rule
select name from META_NOT_OWNABLE
where name = tables.RDB$RELATION_NAME)
and not exists (
select * from RDB$RELATION_FIELDS fields
where (fields.RDB$RELATION_NAME = tables.RDB$RELATION_NAME)
and (fields.RDB$FIELD_NAME = 'OWNER'))
order by tables.RDB$RELATION_NAME;
This works fine.
Then, create a proc to do the maintenance:
CREATE PROCEDURE PREPARE_OWNERSHIP
AS
declare variable name varchar(31);
BEGIN
for select NAME from OWNABLE_TABLES_V into :name do
BEGIN
execute statement replace('ALTER TABLE %T ADD OWNER INTEGER', '%T', :name)
with autonomous transaction;
execute statement replace('ALTER TABLE %T ADD OWNER_TIMEOUT TIMESTAMP', '%T', :name)
with autonomous transaction;
execute statement replace('ALTER TABLE %T ADD CONSTRAINT FK_%T_OWNER foreign key (OWNER) references USERS', '%T', :name)
with autonomous transaction;
END
END
But when I run this one, nothing happens. No errors are reported, but no tables get updated with the new bookkeeping. When I run the proc under the Hopper proc debugger for Firebird, again I don't get any errors.
Any idea what's going wrong, and how to do this right?
I found the problem. After attempting to run it as an EXECUTE BLOCK
statement, I actually got a useful error message: "Unknown token: _OWNER".
Apparently this does not show up when running the proc under the Hopper debugger, but the result of the metadata select that contains the table names has trailing spaces. So the following line:
replace('ALTER TABLE %T ADD CONSTRAINT FK_%T_OWNER foreign key (OWNER) references USERS', '%T', :name)
resolves to something like:
ALTER TABLE TABLENAME ADD CONSTRAINT FK_TABLENAME _OWNER foreign key (OWNER) references USERS
which is obviously invalid. Adding the line name = trim(name);
immediately after the BEGIN
in the for
loop fixed it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.