Firebird 剥离程序、触发器视图和 udf
Firebird strip procedures, trggers views and udf
我正在准备我的软件的新版本,从 Firebird 1.5 过渡到 3。我的安装程序备份 Firebird 1.5 数据库并通过 Firebird 3 服务器或嵌入式服务器恢复它,具体取决于安装类型 ( local/multiuser)。这一切都很好。
我想使用新的 Firebird 功能重新创建所有过程触发器和视图,并尝试摆脱我在 1.5 中使用的 UDF。因此,我试图删除所有这些东西,但我偶然发现了我无法删除的问题,例如,使用 FB3 中不存在的 UDF 的视图。由于 Firebird 3 不提供 UDF,我有点卡住了。
删除旧数据库中的那些对象是不可行的,因为我不想破坏这个后备选项。进行两轮 backup/restore 也不是一种选择,因为我们正在谈论相当大的数据库。
我需要让安装程序完成所有这些工作,因为我无法访问所有客户系统。
感谢 Mark,我再次尝试并最终以某种方式将所有视图更改为 "select 1 as test from rdb$database" 工作,然后可以删除它们。
由于我在现场有许多不同版本的模式,所以我不确定我会遇到哪些依赖项。所以我写了这个 PSQL 块,它忽略错误遍历所有这些对象,直到一切都被清理干净。因此,如果这些对象中的任何一个不可删除,我会在迭代 运行 100 次后退出迭代以避免挂起。之后我检查是否有任何过程、视图、触发器和函数仍然存在。如果是这样,我引发异常。
我知道这是一种 "dirty" 解决方案(忽略异常通常是不可行的),但我没有更好的主意,因为既不会发生无限循环也不会发生未检测到的错误,我将使用这种方式。
EXECUTE BLOCK
as
declare x integer;
declare y integer;
declare z integer;
declare s varchar(100);
declare s1 varchar(100);
begin
x=1;
y=0;
while (x>0 and y<100) do
-- we break out of the loop if we have more than 100 rounds as this indicates
-- at least one object could not be deleted.
begin
y=y+1;
for SELECT distinct RDB$VIEW_NAME from RDB$VIEW_RELATIONS into :s do
begin
in autonomous transaction do
execute statement 'alter view ' || s || ' as select 1 as test from rdb$database';
-- Ignore errors here for now
in autonomous transaction do
execute statement 'drop view ' || s;
-- Ignore errors here for now
when any do begin end
end
for SELECT RDB$PROCEDURE_NAME from RDB$PROCEDURES into :s do
begin
in autonomous transaction do
execute statement 'drop procedure ' || s;
-- Ignore errors here for now
when any do begin end
end
for select RDB$TRIGGER_NAME from RDB$TRIGGERS where RDB$SYSTEM_FLAG=0 into :s do
begin
in autonomous transaction do
execute statement 'drop trigger ' || s;
-- Ignore errors here for now
when any do begin end
end
for select RDB$FUNCTION_NAME from RDB$FUNCTIONS into :s do
begin
in autonomous transaction do
execute statement 'drop function ' || s;
-- Ignore errors here for now
when any do begin end
end
for select rdb$constraint_name,rdb$relation_name from RDB$RELATION_CONSTRAINTS where not rdb$relation_name containing ('$') into :s,:s1 do
begin
in autonomous transaction do
execute statement 'alter table ' || s1 || ' drop constraint ' || s;
-- Ignore errors here for now
when any do begin end
end
for select rdb$index_name from rdb$indices where rdb$system_flag=0 into :s do
begin
in autonomous transaction do
execute statement 'drop index ' || s;
-- Ignore errors here for now
when any do begin end
end
x = 0;
SELECT count(*) from RDB$PROCEDURES into :z;
x = x + z;
SELECT count(distinct RDB$VIEW_NAME) from RDB$VIEW_RELATIONS into :z;
x = x + z;
select count(*) from RDB$TRIGGERS where RDB$SYSTEM_FLAG=0 into :z;
x = x + z;
select count(*) from RDB$FUNCTIONS into :z;
x = x + z;
select count(*) from RDB$RELATION_CONSTRAINTS where not rdb$relation_name containing ('$') into :z;
x = x + z;
select count(*) from rdb$indices where rdb$system_flag=0 into :z;
x = x + z;
end
if (x>0) then
-- Raise an exception showing that the block failed
y=x/0;
end
更新:我添加了代码以删除所有约束和索引。
更新 2:保留 "not null" 约束可能是个好主意,因为它们只能通过域重新创建。为此,只需将约束的 select 语句更改为:
for select rdb$constraint_name,rdb$relation_name from RDB$RELATION_CONSTRAINTS
where rdb$constraint_type<>'NOT NULL' and not rdb$relation_name containing ('$') into :s,:s1 do
我正在准备我的软件的新版本,从 Firebird 1.5 过渡到 3。我的安装程序备份 Firebird 1.5 数据库并通过 Firebird 3 服务器或嵌入式服务器恢复它,具体取决于安装类型 ( local/multiuser)。这一切都很好。
我想使用新的 Firebird 功能重新创建所有过程触发器和视图,并尝试摆脱我在 1.5 中使用的 UDF。因此,我试图删除所有这些东西,但我偶然发现了我无法删除的问题,例如,使用 FB3 中不存在的 UDF 的视图。由于 Firebird 3 不提供 UDF,我有点卡住了。
删除旧数据库中的那些对象是不可行的,因为我不想破坏这个后备选项。进行两轮 backup/restore 也不是一种选择,因为我们正在谈论相当大的数据库。
我需要让安装程序完成所有这些工作,因为我无法访问所有客户系统。
感谢 Mark,我再次尝试并最终以某种方式将所有视图更改为 "select 1 as test from rdb$database" 工作,然后可以删除它们。
由于我在现场有许多不同版本的模式,所以我不确定我会遇到哪些依赖项。所以我写了这个 PSQL 块,它忽略错误遍历所有这些对象,直到一切都被清理干净。因此,如果这些对象中的任何一个不可删除,我会在迭代 运行 100 次后退出迭代以避免挂起。之后我检查是否有任何过程、视图、触发器和函数仍然存在。如果是这样,我引发异常。
我知道这是一种 "dirty" 解决方案(忽略异常通常是不可行的),但我没有更好的主意,因为既不会发生无限循环也不会发生未检测到的错误,我将使用这种方式。
EXECUTE BLOCK
as
declare x integer;
declare y integer;
declare z integer;
declare s varchar(100);
declare s1 varchar(100);
begin
x=1;
y=0;
while (x>0 and y<100) do
-- we break out of the loop if we have more than 100 rounds as this indicates
-- at least one object could not be deleted.
begin
y=y+1;
for SELECT distinct RDB$VIEW_NAME from RDB$VIEW_RELATIONS into :s do
begin
in autonomous transaction do
execute statement 'alter view ' || s || ' as select 1 as test from rdb$database';
-- Ignore errors here for now
in autonomous transaction do
execute statement 'drop view ' || s;
-- Ignore errors here for now
when any do begin end
end
for SELECT RDB$PROCEDURE_NAME from RDB$PROCEDURES into :s do
begin
in autonomous transaction do
execute statement 'drop procedure ' || s;
-- Ignore errors here for now
when any do begin end
end
for select RDB$TRIGGER_NAME from RDB$TRIGGERS where RDB$SYSTEM_FLAG=0 into :s do
begin
in autonomous transaction do
execute statement 'drop trigger ' || s;
-- Ignore errors here for now
when any do begin end
end
for select RDB$FUNCTION_NAME from RDB$FUNCTIONS into :s do
begin
in autonomous transaction do
execute statement 'drop function ' || s;
-- Ignore errors here for now
when any do begin end
end
for select rdb$constraint_name,rdb$relation_name from RDB$RELATION_CONSTRAINTS where not rdb$relation_name containing ('$') into :s,:s1 do
begin
in autonomous transaction do
execute statement 'alter table ' || s1 || ' drop constraint ' || s;
-- Ignore errors here for now
when any do begin end
end
for select rdb$index_name from rdb$indices where rdb$system_flag=0 into :s do
begin
in autonomous transaction do
execute statement 'drop index ' || s;
-- Ignore errors here for now
when any do begin end
end
x = 0;
SELECT count(*) from RDB$PROCEDURES into :z;
x = x + z;
SELECT count(distinct RDB$VIEW_NAME) from RDB$VIEW_RELATIONS into :z;
x = x + z;
select count(*) from RDB$TRIGGERS where RDB$SYSTEM_FLAG=0 into :z;
x = x + z;
select count(*) from RDB$FUNCTIONS into :z;
x = x + z;
select count(*) from RDB$RELATION_CONSTRAINTS where not rdb$relation_name containing ('$') into :z;
x = x + z;
select count(*) from rdb$indices where rdb$system_flag=0 into :z;
x = x + z;
end
if (x>0) then
-- Raise an exception showing that the block failed
y=x/0;
end
更新:我添加了代码以删除所有约束和索引。
更新 2:保留 "not null" 约束可能是个好主意,因为它们只能通过域重新创建。为此,只需将约束的 select 语句更改为:
for select rdb$constraint_name,rdb$relation_name from RDB$RELATION_CONSTRAINTS
where rdb$constraint_type<>'NOT NULL' and not rdb$relation_name containing ('$') into :s,:s1 do