Help Center/ GaussDB/ Centralized_8.x/ Schemas/ DBE_PLDEBUGGER Schema
Updated on 2024-06-03 GMT+08:00

DBE_PLDEBUGGER Schema

DBE_PLDEBUGGER Schema system functions are used to debug stored procedures. This chapter describes the interfaces supported by DBE_PLDEBUGGER Schema.

Only an administrator has the permission to execute these debugging interfaces, but does not have the permission to modify or create functions in the schema. Common users can debug only non-system functions in the public schema or user-created schema. Common users are not allowed to debug system functions.

  • When a user is created in the function body, the plaintext password is returned when attach, next, continue, info_code, step, info_breakpoint, backtrace or finish is called. You are advised not to create a user in the function body.
  • During the debugging of a stored procedure, if the stored procedure to be debugged involves lock operations, do not perform operations that may cause deadlocks on the debugging end.
  • The debugging end and the debugged end must be connected to the same database. Otherwise, the API that uses the function OID to obtain function information is unavailable.

The administrator can run the following command to grant the gs_role_pldebugger role and debugger permissions to a user:

GRANT gs_role_pldebugger to user;

Two clients are required to connect to the database. One client is responsible for executing the debugging API as the debug end, and the other client is responsible for executing the debugging function to control the execution of stored procedures on the server. The following is an example:

  • Prepare for debugging.

    Use PG_PROC to find the OID of the stored procedure to be debugged and execute DBE_PLDEBUGGER.turn_on(oid). In this case, the client functions as the server.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    gaussdb=# CREATE OR REPLACE PROCEDURE test_debug ( IN  x INT) 
    AS  
    BEGIN
        INSERT INTO t1 (a) VALUES (x);
        DELETE FROM t1 WHERE a = x;
    END;
    /
    CREATE PROCEDURE
    gaussdb=# SELECT OID FROM PG_PROC WHERE PRONAME='test_debug';
      oid
    -------
     16389
    (1 row)
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.turn_on(16389);
     nodename | port
    ----------+------
     datanode |    0
    (1 row)
    
  • Start debugging.

    When the server executes the stored procedure, the server hangs before the first SQL statement in the stored procedure and waits for the debugging message sent by the debug end. Debugging is supported only by directly executing a stored procedure and cannot be achieved by invoking an executed stored procedure through a trigger.

    1
    gaussdb=# call test_debug(1);
    

    Start another client as the debug end and invoke DBE_PLDEBUGGER.attach to attach with the stored procedure for debugging based on the data returned by turn_on.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.attach('datanode',0);
     funcoid |  funcname  | lineno |              query
    ---------+------------+--------+----------------------------------
       16389 | test_debug |      3 |   INSERT INTO t1 (a) VALUES (x);
    (1 row)
    

    Execute the next statement on the client where the attach operation is performed.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.next();
     funcoid |  funcname  | lineno |        query
    ---------+------------+--------+----------------------
       16389 | test_debug |      0 | [EXECUTION FINISHED]
    (1 row)
    

    Execute the following variable operations on the client where the attach command is performed.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.info_locals(); -- Print all variables.
     varname | vartype | value | package_name | isconst
    ---------+---------+-------+--------------+---------
     x       | int4    | 1     |              | f
    (1 row)
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.set_var('x', 2); -- Assign a value to a variable.
     set_var
    ---------
     t
    (1 row)
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.print_var('x'); -- Print a single variable.
     varname | vartype | value | package_name | isconst
    ---------+---------+-------+--------------+---------
     x       | int4    | 2     |              | f
    (1 row)
    

    Directly execute the stored procedure that is being debugged.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.continue();
     funcoid |  funcname  | lineno |        query
    ---------+------------+--------+----------------------
       16389 | test_debug |      0 | [EXECUTION FINISHED]
    (1 row)
    

    When the stored procedure reports an error, the following information is displayed. In this case, the suspended process logic is triggered.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.continue();
     funcoid |  funcname  | lineno |            query
    ---------+------------+--------+-------------------------------
       16389 | test_debug |      0 | [EXECUTION HAS ERROR OCCURRED!]
    (1 row)
    

    If the suspended process logic is triggered, you can call the error_info_locals,error_backtrace, error_end, and print_var APIs to view information. Other APIs cannot be used anymore. You need to use error_end to end the suspended process logic.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.error_end();
     funcoid |  funcname  | lineno |      query
    ---------+------------+--------+------------------
       16389 | test_debug |      0 | [END HANG ERROR!]
    (1 row)
    

    Exit the stored procedure that is being debugged (the suspended process logic is unavailable), and do not execute statements that have not been executed before.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.abort();
     abort
    -------
     t
    (1 row)
    

    View the code information on the client and identify the line number of the breakpoint that can be set.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    gaussdb=# 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)
    

    Sets a breakpoint.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.add_breakpoint(16389,4);
    breakpointno 
    --------------
                0
    (1 row)
    

    View the breakpoint information.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.info_breakpoints();
     breakpointno | funcoid | lineno |              query              | enable
    --------------+---------+--------+---------------------------------+--------
                0 |   16389 |      4 |     DELETE FROM t1 WHERE a = x; | t
    (1 row)
    

    Execute to the breakpoint.

    1
    2
    3
    4
    5
    gaussdb=# SELECT * FROM DBE_PLDEBUGGER.continue();
     funcoid |  funcname  | lineno |              query
    ---------+------------+--------+---------------------------------
       16389 | test_debug |      4 |     DELETE FROM t1 WHERE a = x;
    (1 row)
    

    After the stored procedure is executed, the debugging automatically exits. To debug the stored procedure again, you need to attach again. If the server does not need to be debugged, run the turn_off command to disable the debugging or exit the session. Table 1 describes the debugging interfaces.

    Table 1 DBE_PLDEBUGGER

    Interface

    Description

    DBE_PLDEBUGGER.turn_on

    Invoked by the server, indicating that the stored procedure can be debugged. After the interface is invoked, the stored procedure is hung to wait for debugging information.

    DBE_PLDEBUGGER.turn_off

    Invoked by the server, indicating that debugging the stored procedure is disabled.

    DBE_PLDEBUGGER.local_debug_server_info

    Invoked by the server to print all stored procedures that have been turned on in the current session.

    DBE_PLDEBUGGER.attach

    Invoked by the debug end to attach with the stored procedure that is being debugged.

    DBE_PLDEBUGGER.info_locals

    Invoked by the debug end to print the current values of variables in the stored procedure that is being debugged.

    DBE_PLDEBUGGER.next

    Invoked by the debug end to execute the next step.

    DBE_PLDEBUGGER.continue

    Invoked by the debug end to continue the execution until the breakpoint or stored procedure ends.

    DBE_PLDEBUGGER.abort

    Invoked by the debug end to stop debugging. The server reports a long jump error.

    DBE_PLDEBUGGER.print_var

    Invoked by the debug end to print the current values of specified variables in the stored procedure that is being debugged.

    DBE_PLDEBUGGER.info_code

    Invoked by the debug end or server to print the source statement of a specified stored procedure and the line number corresponding to each line.

    DBE_PLDEBUGGER.step

    Invoked by the debug end to execute step by step.

    DBE_PLDEBUGGER.add_breakpoint

    Invoked by the debug end to add a breakpoint.

    DBE_PLDEBUGGER.delete_breakpoint

    Invoked by the debug end to delete a breakpoint.

    DBE_PLDEBUGGER.info_breakpoints

    Invoked by the debug end to view all breakpoints.

    DBE_PLDEBUGGER.backtrace

    Invoked by the debug end to check the current call stack.

    DBE_PLDEBUGGER.enable_breakpoint

    Invoked by the debug end to enable breakpoints.

    DBE_PLDEBUGGER.disable_breakpoint

    Invoked by the debug end to disable breakpoints.

    DBE_PLDEBUGGER.finish

    Invoked by the debug end to continue the debugging until the breakpoint is reached or the upper-layer call stack is returned.

    DBE_PLDEBUGGER.set_var

    Invoked by the debug end to assign a value to a variable.