67.pldbgapi
67.1.插件pldbgapi简介
插件pldbgapi是KingbaseES 的一个扩展插件。主要用于PL/pgSQL语言的存储过程/函数的代码调试。
插件名为 pldbgapi
插件版本 V1.1
67.2.插件pldbgapi加载方式
KingbaseES数据库默认将他添加到 kingbase.conf 文件的 shared_preload_libraries 中,重启数据库时自动加载。因此只需要在客户端工具执行create extension命令即可。
-- 创建插件create extension pldbgapi;
67.3.插件pldbgapi的参数配置
pldbgapi扩展插件无需配置任何参数。
67.4.插件pldbgapi使用方法
67.4.1.pldebugger调试流程
以下详细介绍其局部断点调试和全局断点调试流程的命令行调试流程。只是在目标后端与调试端建立连接的流程有稍微差别,实际的调试的流程总体一致。
pldebugger 的调试操作是建立在目标后端和调试端正常通信的前提下,其详细的调试流程如下:
创建监听,局部断点调试根据调试对象的OID去建立监听,全局断点调试则不需要带调试对象的OID而是创建全局监听。
创建连接,全局调试与局部调试的连接方式稍有不同,对于局部调试,首先是调用待调试的对象,让目标后端进程以通信服务器端的身份发起连接,然后在调试端调用端口连接函数pldbg_attah_to_port让调试端以通信客户端的身份与目标后端建立连接;对于全局断点调试,先设置全局断点,然后调用pldbg_wait_for_target函数发起连接并等待接受目标后端的连接。此时调用待调试的对象就可以与调试端建立通信连接。
调试设置,可以根据需要设置和删除断点信息,包括局部断点和全局断点。
执行调试操作,pldebugger提供了三种调试执行的方式,分别为单步进入(step into)、单步跳过(step over)以及继续执行(continue)。
信息查询,在调试执行的过程中,可以查询源代码信息,查询和修改变量值,查询调用堆栈以及当前系统版本等。
67.4.2.接口函数
pldebugger调试工具支持对PL/pgSQL语言的函数或存储过程进行调试操作,包括操作断点、执行代码、调试数据、查看调用堆栈、查看源码信息、查看版本信息等功能。 并提供局部断点调试与全局断点调试两种调试模式。
调试接口函数列表如下:
67.4.2.1.plpgsql_oid_debug 函数
功能描述
在同一个session下负责监听该函数或存储过程,创建监听状态。该函数在建立监听的过程中会设置一个系统默认断点,行号为‘-1’。
语法格式
FUNCTION plpgsql_oid_debug( FUNCTIONOID OID ) RETURNS INTEGER
参数说明
返回值说明
调用成功返回0,调用失败无返回值,存在报错信息如下:
当OID输入为0时报错信息:no target specified。
当OID无效时报错信息:cache lookup failed for FUNCTION。
当不是owner 或superuser时报错信息:must be owner or superuser to create a breakpoint。
67.4.2.2.pldbg_attach_to_port 函数
功能描述
此函数用于响应PLDBGBREAK端口号。该函数连接到监听给定端口的Target Backend端,从而形成Debugger Client,启动调试过程,等待后续调试工作。 一个Debugger Client能够响应多个不同PLDBGBREAK端口,即可以支持多个并发会话。
语法格式
FUNCTION pldbg_attach_to_port(portNumber INTEGER) RETURNS INTEGER
参数说明
返回值说明
返回标识此特定调试的会话句柄。
67.4.2.3.pldbg_create_listener 函数
功能描述
创建一个TCP端口,为全局断点创建一个监听器,方便后续函数连接到该目标进程。
语法格式
FUNCTION pldbg_create_listener() RETURNS INTEGER
返回值说明
调用成功返回debug_session号。
67.4.2.4.pldbg_set_global_breakpoint 函数
功能描述
创建一个全局断点。
语法格式
FUNCTION pldbg_set_global_breakpoint( session INT, FUNCTION OID, lineNumber INT, targetPID INT ) RETURNS boolean
参数说明
返回值说明
调用成功返回t,调用失败会报错。
67.4.2.5.pldbg_wait_for_target 函数
功能描述
发起socket连接,等待目标后端进程调用自定义函数或者存储过程来连接到调试端,以触发全局断点。
语法格式
FUNCTION pldbg_wait_for_target( session INTEGER ) RETURNS INTEGER
参数说明
返回值说明
调用成功返回target backend的PID。
67.4.2.6.pldbg_set_breakpoint 函数
功能描述
在目标进程中设置一个“局部”断点。
此函数将PLDBG_SET_BREAKPOINT指令发送到Targert Backend端,在自定义函数或者存储过程的指定位置设置断点,然后等待下一个可执行语句到达该目标断点。
语法格式
FUNCTION pldbg_set_breakpoint( session INTEGER, FUNCTION OID, lineNumber INTEGER ) RETURNS boolean
参数说明
返回值说明
断点设置成功返回为t,断点设置失败返回为f。
67.4.2.7.pldbg_get_breakpoints 函数
功能描述
显示设置的所有断点。此函数将PLDBG_GET_BREAKPOINTS指令发送到Targert Backend端,返回查询到的断点元组信息。如果没有断点信息,则返回为空。
语法格式
FUNCTION pldbg_get_breakpoints( session INTEGER ) RETURNS SETOF breakpoint
参数说明
返回值说明
返回一组“breakpoint”元组信息,该元组信息包括自定义函数或者存储过程的OID,断点设置的行号lineNumber,Target端的名字targetName。
67.4.2.8.pldbg_drop_breakpoint 函数
功能描述
在目标进程中删除一个指定行号的断点。此函数将PLDBG_CLEAR_BREAKPOINT指令发送到Targert Backend端,删除指定断点信息,并返回删除成功与否的状态。
语法格式
FUNCTION pldbg_drop_breakpoint( session INTEGER, FUNCTION OID, lineNumber INTEGER ) RETURNS boolean
参数说明
返回值说明
断点删除成功返回t,断点删除失败返回f。
67.4.2.9.pldbg_wait_for_breakpoint 函数
功能描述
调用该函数,可以返回刚建立连接时断点所在行的信息。
语法格式
FUNCTION pldbg_wait_for_breakpoint( session INTEGER ) RETURNS breakpoint
参数说明
返回值说明
此函数返回类型为一个“breakpoint”的元组,该元组包含自定义函数或者存储过程的OID以及刚建立连接时停止的行号。
67.4.2.10.pldbg_step_into 函数
功能描述
单步执行,遇到子函数或子存储过程会进入到相应的部分。 此函数将PLDBG_STEP_INTO命令发送到Targert Backend,等待目标后端进程执行语句后,等待下一个可执行语句到达目标。
语法格式
FUNCTION pldbg_step_into( session INTEGER ) RETURNS breakpoint
参数说明
返回值说明
此函数返回类型为“breakpoint”的元组(但不一定是真正的断点信息,因为单步执行有可能遇到断点,有可能没有遇见断点)。 该元组包含自定义函数或者存储过程的OID以及目标当前停止的行号,以及自定义函数或者存储过程名。
67.4.2.11.pldbg_step_over 函数
功能描述
单步执行,遇见子函数或子存储过程会跳过内部执行过程。此函数将PLDBG_STEP_OVER命令 发送到Targert Backend,待目标后端进程执行语句后,等待下一个可执行语句到达目标,并将执行后需要返回的结果返回。
语法格式
FUNCTION pldbg_step_over( session INTEGER ) RETURNS breakpoint
参数说明
返回值说明
此函数返回类型为“breakpoint”的元组(但不一定是真正的断点信息,因为单步执行有可能遇到断点,有可能没有遇见断点)。 该元组包含自定义函数或者存储过程的OID以及目标当前停止的行号,以及自定义函数或者存储过程名。
67.4.2.12.pldbg_continue 函数
功能描述
从当前位置继续执行,直到遇见下一个断点,如果没有断点,将直接执行到自定义函数或存储过程的最后。 此函数将“PLDBG_CONTINUE”指令发送到Targert Backend端,目标后端进程执行,然后等待目标到达下一个断点,并返回相应的结果信息。
语法格式
FUNCTION pldbg_continue( session INTEGER ) RETURNS breakpoint
参数说明
返回值说明
此函数返回类型为“breakpoint”的元组,该元组包含自定义函数或者存储过程的OID以及目标当前停止的行号,以及自定义函数或者存储过程名。
67.4.2.13.pldbg_abort_target 函数
功能描述
终止当前的执行。此函数将PLDBG_ABORT命令发送到Targert Backend,然后终止当前的执行,并返回终止成功与否的状态。
语法格式
FUNCTION pldbg_abort_target( session INTEGER ) RETURNS SETOF boolean
参数说明
返回值说明
终止成功返回t。
67.4.2.14.pldbg_get_variables 函数
功能描述
获取一个变量或者参数的信息列表。此函数将PLDBG_GET_VARIABLES 指令发送到Targert Backend端,服务器查询到所有变量的信息后返回变量或参数的信息列表。
语法格式
FUNCTION pldbg_get_variables( session INTEGER ) RETURNS SETOF var
参数说明
返回值说明
返回一个var元组集合,包含信息:VarName;Class;lineNumber;Unique;isConst;notNull;dataTypeOID;value(rest of string)。其中每个变量的含义如下:
varName:变量或参数的名称;
Class:变量或参数的类别。如果自定义函数或存储过程有输入参数时,该参数类型将标记为“A”,语句块里的参数将标记为“L”;
lineNumber:声明变量或参数的行号;
Unique:标记该名称在自定义函数或者存储过程范围内是否唯一,如果名称不是唯一,调试器客户端将使用行号来区分同名的变量或参数;
isConst:标记变量或参数是否为常量;
notNull:标记变量或参数是否不为空;
dataTypeOID:该变量sys_type中对应的OID;
value(rest of string):变量的值。
67.4.2.15.pldbg_deposit_value 函数
功能描述
在调试过程中,将一个新值赋给指定的变量。此函数将PLDBG_DEPOSIT指令发送到Targert Backend端,服务器查询该变量然后修改变量的值,最后将修改成功与否的状态返回。
语法格式
FUNCTION pldbg_deposit_value( session INTEGER, varName TEXT, lineNumber INTEGER, value TEXT ) RETURNS boolean
参数说明
返回值说明
新值设置成功返回t,新值设置失败返回f。
67.4.2.16.pldbg_get_stack 函数
功能描述
从Targert Backend端获取调用堆栈信息。此函数将PLDBG_GET_STACK指令发送到Targert Backend端,返回相应调用堆栈信息。
语法格式
FUNCTION pldbg_get_stack( session INTEGER ) RETURNS SETOF frame
参数说明
返回值说明
返回一组堆栈框架信息元组,包含:CallCount;targetName;funcOID;lineNumber;arguments(rest of string)。
CallCount:堆栈深度。
targetName:调用函数或存储过程的名称。
funcOID:自定义函数或者存储过程OID。
lineNumber:当前停留的行号。
arguments(rest of string):参数的信息。
67.4.2.17.pldbg_select_frame 函数
功能描述
将调试器焦点(当前在堆栈中的执行位置)更改为指定的帧。此函数将PLDBG_SELECT_FRAME命令发送到Targert Backend,然后循环查询指定的帧,如果传入的帧不存在,将返回当前帧的信息,如果传入的帧信息存在,将返回相应的查询信息。
语法格式
FUNCTION pldbg_select_frame( session INTEGER, frame INTEGER ) RETURNS breakpoint
参数说明
返回值说明
此函数返回类型为“breakpoint”的元组,其中包含自定义函数或者存储过程OID,以及当前目标在选定帧中停止的行号。
67.4.2.18.pldbg_get_source 函数
功能描述
从Target Backend获取自定义函数或存储过程正在执行的源代码。此函数将包含PLDBG_GET_SOURCE, FUNCTIONOID的字符串发送到Targert Backend,查询源代码信息并返回。
语法格式
FUNCTION pldbg_get_source( session INTEGER, func OID ) RETURNS TEXT
参数说明
返回值说明
返回给定函数或存储过程的源代码信息。
67.4.2.19.pldbg_get_proxy_info 函数
功能描述
获取服务器版本,Proxy Backend API版本等信息。
语法格式
FUNCTION pldbg_get_proxy_info() RETURNS proxyInfo
返回值说明
返回服务器和代理API的版本信息。
67.4.2.20.局部断点调试示例
创建调试环境和用例:
--创建pldebugger环境create extension pldbgapi;--创建用来调试的存储过程CREATE OR REPLACE PROCEDURE public.pro1()language 'plpgsql'AS $$BEGINraise notice '123';raise notice 'success';END;$$;CREATE OR REPLACE PROCEDURE public.pro4()LANGUAGE 'plpgsql'AS$$declarei int := 2;begini = 3;raise notice 'i= %',i;i = 4;raise notice 'i= %',i;raise notice '0:ready.....';beginraise notice '1:ready.....';call pro1();beginraise notice 'success';end;end;end;$$;--查询出需要调试的存储过程的oidselect oid from sys_proc where proname = 'pro4';oid-------16918(1 row)
application client:
--应用端开启局部监听select plpgsql_oid_debug(16918);plsql_oid_debug-------------------0(1 row)--开始调试存储过程pro4call pro4();NOTICE: PLDBGBREAK:3--该进程控制器转交给另一进程,直至调试结束,3为连接的端口号
debugger client:
--调试端连接select pldbg_attach_to_port(3);pldbg_attach_to_port----------------------1(1 row)--查看源码select pldbg_get_source(1,16918);pldbg_get_source--------------------------------------+declare +i int := 2; +begin +i = 3;+raise notice 'i= %',i;+i = 4;+raise notice 'i= %',i;+raise notice '0:ready.....'; +begin +raise notice '1:ready.....';+call pro1();+begin +raise notice 'success'; +end; +end; +end(1 row)--设置断点select pldbg_set_breakpoint(1,16918,7);pldbg_set_breakpoint----------------------------t(1 row)select pldbg_set_breakpoint(1,16918,12);pldbg_set_breakpoint----------------------t(1 row)select pldbg_set_breakpoint(1,16918,15);pldbg_set_breakpoint----------------------t(1 row)--获取当前设置的断点信息select pldbg_get_breakpoints(1);pldbg_get_breakpoints-----------------------(16918,-1,"")(16918,12,"")(16918,15,"")(16918,7,"")(4 rows)--单步执行,遇到子程序进入select pldbg_step_into(1);pldbg_step_into-----------------------(16918,7,"pro4()")(1 row)select pldbg_step_into(1);pldbg_step_into-----------------------(16918,8,"pro4()")(1 row)select pldbg_step_into(1);pldbg_step_into-----------------------(16918,9,"pro4()")(1 row)--单步执行,遇到子程序跳过select pldbg_step_over(1);pldbg_step_over-----------------------(16918,10,"pro4()")(1 row)--继续执行程序,直到断点处或者程序结束select pldbg_continue(1);pldbg_continue----------------------(16918,13,"pro4()")(1 row)--当application client执行完毕后,debug client进程会挂起,直到application client再次执行测试函数或存储过程select pldbg_continue(1);
application client:
--应用端存储过程执行完成call pro4();NOTICE: PLDBGBREAK:3NOTICE: i= 3NOTICE: i= 4NOTICE: 0:ready.....NOTICE: 1:ready.....NOTICE: 123NOTICE: successNOTICE: successCALL--再次调起call pro4();
debugger client:
--调试端进入调试状态,调用pldbg_abort_target,终止调试select pldbg_abort_target(1);pldbg_abort_target--------------------t(1 row)
application client:
—当debug client 调用select pldbg_abort_target(1)后,执行被终止 call pro4(); ERROR: canceling statement due to user request CONTEXT: PL/pgSQL FUNCTION pro4() line 5 at assignment
67.4.2.21.全局断点调试示例
debugger client:
--调试端创建全局监听select pldbg_create_listener();pldbg_create_listener-----------------------1(1 row)--设置全局断点,未指定行号默认为-1,即BEGIN块的第一行select pldbg_set_global_breakpoint(1,16918,null,null);pldbg_set_global_breakpoint-----------------------------t(1 row)--等待测试函数被调用,无测试函数调用该进程会挂起select pldbg_wait_for_target(1);
application client:
--应用端执行测试函数call pro4();
debugger client:
--测试函数调用后,返回测试函数session的进程号,开始调试select pldbg_wait_for_target(1);pldbg_wait_for_target-----------------------------235966(1 row)--设置局部断点select pldbg_set_breakpoint(1,16918,5);pldbg_set_breakpoint----------------------t(1 row)--设置全局断点select pldbg_set_global_breakpoint(1,16918,12,null);pldbg_set_global_breakpoint-----------------------------t(1 row)--获取变量信息select pldbg_get_variables(1);pldbg_get_variables---------------------------(i,L,3,t,f,f,23,2)(1 row)--单步进入select pldbg_step_into(1);pldbg_step_into-----------------------(16918,7,"pro4()")(1 row)select pldbg_step_into(1);pldbg_step_into-----------------------(16918,8,"pro4()")(1 row)--获取修改后的变量信息select pldbg_get_variables(1);pldbg_get_variables---------------------(i,L,3,t,f,f,23,3)(1 row)--继续执行到断点处select pldbg_continue(1);pldbg_continue---------------------(16918,13,"pro4()")(1 row)--单步进入子程序pro1select pldbg_step_into(1);pldbg_step_into--------------------(16917,4,"pro1()")(1 row)--获取堆栈信息select pldbg_get_stack(1);pldbg_get_stack--------------------------(0,"pro1()",16917,3,"")(1,"pro4()",16918,12,"")(2 rows)--追溯堆栈信息select pldbg_select_frame(1,1);pldbg_select_frame---------------------(16918,13,"pro4()")(1 row)--继续执行到程序结束后挂起,等待下一次程序调用select pldbg_continue(1);pldbg_continue---------------------(16918,15,"pro4()")(1 row)select pldbg_continue(1);
application client:
--应用端程序执行完成call pro4();NOTICE: i= 3NOTICE: i= 4NOTICE: 0:readyNOTICE: 1:readyNOTICE: 123NOTICE: successNOTICE: successCALL
67.4.2.22.修改调试时数据及删除断点调试示例
创建测试环境和用例:
--创建pldebugger环境create extension pldbgapi;--创建用来调试的存储过程create or replace procedure pro5(i int)LANGUAGE 'plpgsql'as $$declarej int;beginraise notice 'i = %',i;j = i;raise notice 'j = %',j;j = 1;raise notice 'j = %',j;i = 2;raise notice 'i = %',i;end;$$;--查询出需要调试的存储过程的oidselect oid from sys_proc where proname = 'pro5';oid-------16919(1 row)
debugger client:
--创建全局监听select pldbg_create_listener();pldbg_create_listener-----------------------1(1 row)--设置全局断点select pldbg_set_global_breakpoint(1,16919,null,null);pldbg_set_global_breakpoint-----------------------------t(1 row)--等待测试存储过程调用select pldbg_wait_for_target(1);
application client:
call pro5(3);
debugger client:
--子程序已调用,开始调试select pldbg_wait_for_target(1);pldbg_wait_for_target-----------------------------313888(1 row)--返回建立连接时断点所在行的信息(全局断点行号为null,默认当前在BEGIN块的第一行)select pldbg_wait_for_breakpoint(1);pldbg_wait_for_breakpoint---------------------------(16919,6,"pro5(integer)")(1 row)--单步执行select pldbg_step_into(1);pldbg_step_into---------------------------(16919,7,"pro5(integer)")(1 row)--获取存储过程源码select pldbg_get_source(1,16919);pldbg_get_source-----------------------------+declare+j int; +begin +raise notice 'i = %',i;+j = i; +raise notice 'j = %',j;+j = 1; +raise notice 'j = %',j;+i = 2; +raise notice 'i = %',i;+end;(1 row)--查看变量的值select pldbg_get_variables(1);pldbg_get_variables-----------------------(i,A,0,t,f,f,23,3)(j,L,3,t,f,f,23,NULL)(2 rows)--修改变量j的值select pldbg_deposit_value(1, 'j', 3, '10');pldbg_deposit_value---------------------f(1 row)--再次查看变量j的值,已被改变select pldbg_get_variables(1);pldbg_get_variables---------------------------(i,A,0,t,f,f,23,3)(j,L,3,t,f,f,23,10)(2 rows)--单步执行,变量j在程序中被赋值select pldbg_step_into(1);pldbg_step_into---------------------------(16919,8,"pro5(integer)")(1 row)--查看变量j的值,已改变select pldbg_get_variables(1);pldbg_get_variables---------------------------(i,A,0,t,f,f,23,3)(j,L,3,t,f,f,23,3)(2 rows)--设置局部断点select pldbg_set_breakpoint(1,16919,5);pldbg_set_breakpoint----------------------t(1 row)select pldbg_set_breakpoint(1,16919,7);pldbg_set_breakpoint----------------------t(1 row)select pldbg_set_breakpoint(1,16919,9);pldbg_set_breakpoint----------------------t(1 row)--查看断点信息select pldbg_get_breakpoints(1);pldbg_get_breakpoints-----------------------(16919,-1,"")(16919,7,"")(16919,9,"")(16919,-1,"")(16919,5,"")(5 rows)--删除断点select pldbg_drop_breakpoint(1,16919,5);pldbg_drop_breakpoint-----------------------t(1 row)select pldbg_drop_breakpoint(1,16919,9);pldbg_drop_breakpoint-----------------------t(1 row)--查看断点信息select pldbg_get_breakpoints(1);pldbg_get_breakpoints-----------------------------(16919,-1,"")(16919,7,"")(16919,-1,"")(3 rows)--设置全局断点select pldbg_set_global_breakpoint(1,16919,11,null);pldbg_set_global_breakpoint-----------------------------t(1 row)--查看断点信息select pldbg_get_breakpoints(1);pldbg_get_breakpoints-----------------------------(16919,11,"")(16919,-1,"")(16919,7,"")(16919,-1,"")(4 rows)--设置断点行号为0时无效select pldbg_drop_breakpoint(1,16919,0);pldbg_drop_breakpoint-----------------------f(1 row)--设置断点行号为NULL时无效select pldbg_drop_breakpoint(1,16919,NULL);pldbg_drop_breakpoint-----------------------(1 row)--查看断点信息,0和NULL断点都未设置成功select pldbg_get_breakpoints(1);pldbg_get_breakpoints-----------------------(16919,11,"")(16919,-1,"")(16919,7,"")(16919,-1,"")(4 rows)--查看版本信息select * from pldbg_get_proxy_info();serverversionstr| serverversionnum | proxyapiver | serverprocessid---------------------------------------------------------------------------------------------------------+------------------+-------------+-----------------PostgreSQL 12.1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 0623 (Red Hat 4.8.5-36), 64-bit | 120001 | 3 |311197(1 row)
67.5.插件pldbgapi卸载方法
卸载pldbgapi插件接口,只需要执行以下命令:
-- 删除插件drop extension pldbgapi;
67.6.插件pldbgapi升级方法
若该插件有升级版本则通过 alter extension 来升级插件。
示例,由 1.1 升级到 1.2:
ALTER EXTENSION pldbgapi UPDATE TO '1.2';