人大金仓数据库 KingbaseES PLSQL调试工具-高级功能

金仓数据库KingbaseES PLSQL调试工具-高级功能

关键字:

KingbaseES、调试工具、plsql_pldbgapi、高级功能、人大金仓、KingbaseES

通过之前plsql_pldbgapi基础功能的介绍,我们已经熟悉了调试工具plsql_pldbgapi的基本功能和基础用法,掌握了这些基础之后,我们已经可以使用该插件去调试一些简单、短小的PLSQL程序。下面我们将继续介绍插件plsql_pldbgapi的一些高级功能,以帮助使用 KingbaseES 来编写 PLSQL 程序的开发人员能够使用该插件来调试和分析一些复杂的大型程序。

plsql_pldbgapi的高级功能

除了为程序打断点、单步执行等基础功能之外,plsql_pldbgapi通过很多函数接口提供了大量的进阶功能来应对复杂程序的调试,下面将介绍其中一些重要的进阶功能。

  1. plsql_pldbg_get_variables:

该函数用来获取标识某个特定调试的会话句柄session_id对应的所有变量或者参数的信息列表。类似于GDB中的“p”打印变量命令,不同的是,它会打印出调试对象的所有变量和参数信息。它的调用方法如下:

select * from plsql_pldbg_get_variables(session_id);

该函数会返回一个标识变量信息的集合,该集合中包括所有的变量名,变量所在的行号、变量对应的OID和变量的值等。

  1. plsql_pldbg_get_stack:

该函数用来获取会话句柄session_id对应程序的调用堆栈信息。类似于GDB中的“bt”命令。它的调用方法为:

select * from plsql_pldbg_get_stack(session_id);

该函数会返回一组表示堆栈框架信息的元组,该元组中包含堆栈的深度,调试对象的OID和参数相关信息等。

  1. plsql_pldbg_step_out:

该函数可以忽略当前堆栈的所有断点,从当前的执行点直接跳转到上层堆栈的下一条语句,这样可以很方便地跳出某个复杂的调用堆栈。类似于GDB中的“finish”命令,但不同的是,“finish”不会忽略任何断点。它的调用方式如下:

select plsql_pldbg_step_out(session_id);

  1. plsql_pldbg_run_to_next_exception:

即使发生异常的区域没有被打断点,但只要异常发生,该函数就会让程序停留在导致异常发生的地方。它不会忽略断点,碰到断点会优先停留在断点处。该函数可以帮助开发人员迅速定位异常发生的地方。它的调用方法为:

select plsql_pldbg_run_to_next_exception(session_id);

除了该函数之外,插件plsql_pldbgapi还提供了plsql_pldbg_set_exception_breakpoint_src函数来针对特定异常的处理调试,关于它的用法可以参考KingbaseES的官方手册,此处不再赘述。

  1. plsql_pldbg_step_end:

该函数会让程序的执行点步进到当前堆栈的最后一条语句,碰到断点不会跳过,优先停留在断点处。它的调用方式为:

select plsql_pldbg_step_end(session_id);

  1. plsql_pldbg_set_breakpoint_src:

该函数可以用来插入一个新的断点,也可以用其更新一个原有的断点。跟简单的设置断点函数plsql_pldbg_set_breakpoint不同的是,该函数不仅可以在指定行上设置断点,还具有对断点加注释,选择禁用或启用断点,设置当断点被击中多少次时才生效等各项功能。它的调用方式如下:

select plsql_pldbg_set_breakpoint_src(session_id, f_oid, line_no, status, hitnumber , desc, cond );

其中,session_id是标识某个特定调试的会话句柄;f_oid是欲调试的PLSQL对象的OID;line_no表示该断点设置在源代码中的第line_no行;status表示该断点处于启用还是禁用的状态,它是boolean类型的值,true表示启用断点,false表示禁用断点;hitnumber表示该断点被击中hitnumber次后才会被启用,该功能多用于循环中,例如循环中的断点可以设置为在程序循环运行第hitnumber次后才停在该断点处,当使用此函数更新某个断点时,它的内部击中次数会被重置为0;desc是对断点的描述信息,它是text类型的;cond表示条件断点的条件,也是text类型的,目前暂时不支持设置条件断点,默认值为NULL。

  1. plsql_pldbg_get_breakpoints_src:

该函数可以获取当前调试下的所有断点信息,它的调用方式为:

select * from plsql_pldbg_get_breakpoints_src(session_id);

其中,session_id是标识当前调试的会话句柄,通过类似于查表的这种方式,可以获取所有断点所在的行、断点的状态是启用还是禁用、对断点的描述等各项信息。

plsql_pldbgapi的高级用法

下面我们将以一个具体的调试过程为例,来说明插件plsql_pldbgapi进阶功能的使用方法。我们先假设一个具体的场景:公司根据员工每个月的工资,一次性为其账户上转入总工资,首先创建两张表:

\set SQLTERM ;

DROP TABLE IF EXISTS accounts;

CREATE TABLE accounts(id INT, balance DECIMAL);

INSERT INTO accounts VALUES(1, 20000);

INSERT INTO accounts VALUES(2, 1000);

DROP TABLE IF EXISTS monthlyWages;

CREATE TABLE monthlyWages(month INT, wages DECIMAL);

INSERT INTO monthlyWages VALUES(1, 8100);

INSERT INTO monthlyWages VALUES(2, 8300);

INSERT INTO monthlyWages VALUES(3, 8200);

其中,accounts是管理公司和员工账户的表,id为1的是公司的账户,id为2的是某个员工的账户,balance表示账户的余额;monthlyWages是该员工每个月的工资表,字段month代表月份,wages是对应月份的工资。下面我们创建一个用于转账的存储过程transfer_funds:

\set SQLTERM /

CREATE OR REPLACE PROCEDURE transfer_funds(

    from_account_id INT,  /*转出账户*/

    to_account_id INT,    /*转入账户*/

    months INT            /*总共转入months个月的工资*/

) AS

DECLARE

    current_balance DECIMAL;  /*用来存储转出账户的当前余额*/

    amount DECIMAL;           /*根据月份计算出的总工资*/

    /*定义一个嵌套函数用来根据月份计算出总工资*/

    FUNCTION cal_amount(m INT) RETURN DECIMAL AS

    DECLARE

        everyWages DECIMAL;

        total DECIMAL = 0;

    BEGIN

        /*循环遍历员工的工资表来计算总工资*/

        FOR i IN 1..m LOOP    

            SELECT wages INTO everyWages FROM monthlyWages

            WHERE month = i;

            total = total + everyWages;

        END LOOP;

        RETURN total;

    END;

BEGIN

    /*首先查询出转出账户的当前余额*/

    SELECT balance INTO current_balance FROM accounts

    WHERE id = from_account_id; 

    /*然后调用函数cal_amount计算出欲转入的总工资*/      

    amount = cal_amount(months);  

    /*如果余额小于欲转入的总工资,则抛出一个异常*/    

    IF current_balance < amount THEN  

        RAISE EXCEPTION 'Insufficient funds in the account';

    END IF;

    /*开始转账*/

    UPDATE accounts SET balance = balance - amount  /*扣除转出账户余额*/

    WHERE id = from_account_id;

    UPDATE accounts SET balance = balance + amount  /*增加收款账户余额*/

    WHERE id = to_account_id;

    COMMIT;    /*提交事务*/

EXCEPTION      /*当发生异常时,回滚事务*/

    WHEN OTHERS THEN

        ROLLBACK;

        RAISE NOTICE 'Transfer failed: %', SQLERRM;

END;

/

接下来,调用该存储过程来为该员工转入前3个月的总工资。

\set SQLTERM ;

CALL transfer_funds(1,2,3);

程序运行异常,报错如下:

下面,使用插件plsql_pldbgapi来调试存储过程transfer_funds的运行过程。

首先,使用之前在plsql_pldbgapi基础用法中介绍的方法来创建调试环境,具体的方法在对应文档中已有介绍,此处不再赘述。

应用端

调试端

如上图所示,当调试端和应用端的环境都创建好之后,就可以开始调试了。由于本次程序运行失败的原因是异常造成的,因此,在调试开始时,可以先调用函数plsql_pldbg_run_to_next_exception,这样在整个调试过程中,只要发生异常就可以停留在导致异常的代码处,即使在该处并没有打断点。

调试端

然后,调用函数plsql_pldbg_get_source查看被调试程序的源码,这样可以方便我们根据源代码的行号来打断点(plsql_pldbgapi打断点的行数依据是查看源码时显式的行数,而不是我们在会话中输入代码时的行数)。

调试端

然后调用函数plsql_pldbg_set_breakpoint_src分别在第4行和第13行打断点,并分别给其添加描述“firstbp”和“secondbp”。

调试端

此处在打断点时,我们将函数的最后一个表示条件断点的参数省略掉了,因为它默认为NULL,是可选的,所以可以不写。并且,由于“secondbp”为与LOOP循环中,因为我们将其hitnumber设置为2,表示当它在循环中被击中2次后才会停在此断点处。

打完断点后,首先调用函数plsql_pldbg_get_variables查看程序当前的所有变量信息。

调试端

可以看出,当前total和everywages的值还都是初始的,证明程序还停留在第一个断点处,并没有进入LOOP循环中。然后调用函数plsql_pldbg_continue,让程序继续执行,直到停留在下一个断点处。

调试端

接着,我们继续调用函数plsql_pldbg_get_variables来查看程序当前的所有变量信息。

调试端

此时,可以看到total的值为8100,everywages的值为8300,证明程序的确在第二次到达13行时,停在了第二个断点“secondbp”处。然后继续调用函数plsql_pldbg_continue,让程序继续执行。发现它依然停留在了第13行,说明它还是在循环中。

调试端

停留在13行

此时,调用函数plsql_pldbg_get_stack,查看函数当前的调用堆栈。

调试端

发现,程序当前停留在嵌套函数cal_amount中,然后调用函数plsql_pldbg_step_out忽略断点,直接跳出当前的堆栈。

调试端

从图中可以看出,程序停留在了21行,而我们在21行并没有打断点,说明我们在一开始调用的函数plsql_pldbg_run_to_next_exception起了作用,程序停留在了导致异常发生的地方。此时,我们打印所有变量信息。

调试端

发现current_balance < amount, 所以程序抛出了异常。原来是转出账户的余额不够发该员工3个月的工资。那么我们更改调用参数,先发前两个月的工资。

先发前2个月工资

这次程序可以正常调用,查表发现前2个月工资已经正常发放。

总结

本文详细地介绍了调试工具plsql_pldbgapi中的高级功能和用法,并通过实际的案例演示了如何使用它来调试较复杂的PLSQL代码。通过合理使用plsql_pldbgapi可以提高开发效率,确保代码正确运行,从而高效、安全地维护和使用KingbaseES数据库。更多关于插件plsql_pldbgapi的功能和用法可以参考KingbaseES的官方手册。

参考资料

《KingbaseES插件参考手册》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值