DBE_PLDEBUGGER Schema
DBE_PLDEBUGGER下系统函数用于单机下调试存储过程,目前支持的接口及其描述如下所示。仅管理员有权限执行这些调试接口,且无权限修改和创建新函数。
当在函数体中创建用户时,调用attach、next、continue、 info_code、step、info_breakpoint、backtrace、 finish中会返回密码的明文。因此不建议用户在函数体中创建用户。
对应权限角色为gs_role_pldebugger,可以由管理员用户通过如下命令将debugger权限赋权给该用户。
GRANT gs_role_pldebugger to user;
需要有两个客户端连接数据库,一个客户端负责执行调试接口作为debug端,另一个客户端执行调试函数,控制server端存储过程执行。示例如下。
准备调试
通过PG_PROC,查找到待调试存储过程的oid,并执行
DBE_PLDEBUGGER.turn_on(oid)
。本客户端就会作为server端使用。调试匿名块时,执行DBE_PLDEBUGGER.turn_on(0)
。1、创建存储过程。
CREATE OR REPLACE PROCEDURE test_debug ( IN x INT) AS BEGIN INSERT INTO t1 (a) VALUES (x); DELETE FROM t1 WHERE a = x; END; /
2、执行如下语句进行查询操作。
SELECT OID FROM PG_PROC WHERE PRONAME='test_debug'; SELECT * FROM DBE_PLDEBUGGER.turn_on(16389);
查询结果为如下:
oid ------- 16389 (1 row) nodename | port ----------+------ datanode | 0 (1 row)
开始调试
server端执行存储过程,会在存储过程内第一条SQL语句前hang住,等待debug端发送的调试消息。仅支持直接执行存储过程的调试,不支持通过trigger调用执行的存储过程调试。匿名块在turn_on后输入执行即可。
call test_debug(1); -- 匿名块 do $$ declare # declaration_section begin # executable_section end; $$ LANGUAGE plpgsql;
再起一个客户端,作为debug端,通过turn_on返回的数据,调用
DBE_PLDEBUGGER.attach
关联到该存储过程上进行调试。SELECT * FROM DBE_PLDEBUGGER.attach('datanode',0);
查询结果显示为如下:
funcoid | funcname | lineno | query ---------+------------+--------+---------------------------------- 16389 | test_debug | 3 | INSERT INTO t1 (a) VALUES (x); (1 row)
在执行attach的客户端调试,执行下一条statement。
SELECT * FROM DBE_PLDEBUGGER.next();
结果显示为如下:
funcoid | funcname | lineno | query ---------+------------+--------+---------------------- 16389 | test_debug | 0 | [EXECUTION FINISHED] (1 row)
在执行attach的客户端调试,可以执行以下变量操作
SELECT * FROM DBE_PLDEBUGGER.info_locals(); --打印全部变量 SELECT * FROM DBE_PLDEBUGGER.set_var('x', 2); --变量赋值 SELECT * FROM DBE_PLDEBUGGER.print_var('x'); --打印单个变量
结果显示为如下:
varname | vartype | value | package_name | isconst ---------+---------+-------+--------------+--------- x | int4 | 1 | | f (1 row) set_var --------- t (1 row) varname | vartype | value | package_name | isconst ---------+---------+-------+--------------+--------- x | int4 | 2 | | f (1 row)
以下几种方式均可以完成当前调试。
直接执行完成当前正在调试的存储过程。
SELECT * FROM DBE_PLDEBUGGER.continue();
结果显示为如下:
funcoid | funcname | lineno | query ---------+------------+--------+---------------------- 16389 | test_debug | 0 | [EXECUTION FINISHED] (1 row)
直接退出当前正在调试的存储过程,不执行尚未执行的语句。
SELECT * FROM DBE_PLDEBUGGER.abort();
结果显示为如下:
abort ------- t (1 row)
client端操作:
1、查看代码信息并识别可以设置断点行号。
SELECT * FROM DBE_PLDEBUGGER.info_code(16389);
结果显示为如下:
lineno | query | canbreak --------+-----------------------------------------------------------+---------- | CREATE OR REPLACE PROCEDURE public.test_debug( IN x INT) | f 1 | AS DECLARE | f 2 | BEGIN | f 3 | INSERT INTO t1 (a) VALUES (x); | t 4 | DELETE FROM t1 WHERE a = x; | t 5 | END; | f 6 | / | f (7 rows)
2、设置断点。
SELECT * FROM DBE_PLDEBUGGER.add_breakpoint(16389,4);
结果显示为如下:
lineno | query | canbreak --------+-----------------------------------------------------------+---------- | CREATE OR REPLACE PROCEDURE public.test_debug( IN x INT) | f 1 | AS DECLARE | f 2 | BEGIN | f 3 | INSERT INTO t1 (a) VALUES (x); | t 4 | DELETE FROM t1 WHERE a = x; | t 5 | END; | f 6 | / | f (7 rows)
3、查看断点信息。
SELECT * FROM DBE_PLDEBUGGER.info_breakpoints();
结果显示为如下:
breakpointno | funcoid | lineno | query | enable --------------+---------+--------+---------------------------------+-------- 0 | 16389 | 4 | DELETE FROM t1 WHERE a = x; | t (1 row)
4、执行至断点。
SELECT * FROM DBE_PLDEBUGGER.continue();
结果显示为如下:
funcoid | funcname | lineno | query ---------+------------+--------+--------------------------------- 16389 | test_debug | 4 | DELETE FROM t1 WHERE a = x; (1 row)
存储过程执行结束后,调试会自动退出,再进行调试需要重新attach关联。如果server端不需要继续调试,可执行turn_off关闭,或退出session。具体调试接口请见下面列表。
表 1 DBE_PLDEBUGGER
debug和server端都可以调用,打印指定存储过程的源语句和各行对应的行号。info_code(0)可查看正在调试中的匿名块源语句和各行对应的行号。