Programming & Debugging Stored Procedures & Functions in DBeaver
Procedural database logic—such as stored procedures, user-defined functions (UDFs), packages, and triggers—powers the transactional backbone of enterprise software. While writing plain SQL selects is straightforward, debugging complex conditional loops, cursor iterations, and transaction rollbacks inside procedural code can be notoriously difficult without an interactive debugger.
DBeaver bridges the gap between text editors and full IDEs by offering native step-by-step procedural debugging, code structure navigation, and compiler error diagnostics.
1. Procedural Programming Architecture in DBeaver
When you connect to an enterprise database (such as PostgreSQL, Oracle, SQL Server, MySQL, or DB2), DBeaver introspects the data catalog to organize routines under:
- Procedures: Routines invoked via
CALL procedure_name(...)that execute transactions and modify state without requiring a scalar return value. - Functions: Routines returning a scalar value, record, or table set (
RETURNS TABLEorSETOF). - Packages (Oracle / DB2): Encapsulated collections of procedures, functions, types, and private variables.
- Triggers: Event-driven routines attached to DDL/DML actions (
BEFORE INSERT,AFTER UPDATE).
2. Authoring & Compiling Stored Routines
To create a new procedure or edit an existing one in DBeaver:
- In the Database Navigator, expand your connection → Schema → Procedures (or Functions).
- Right-click the folder and select Create New Procedure.
- DBeaver generates a dialect-compliant boilerplate skeleton with parameters and return types.
Here is an enterprise-grade PL/pgSQL function template ready for DBeaver compilation:
CREATE OR REPLACE FUNCTION process_monthly_billing(
p_billing_month DATE,
p_grace_period_days INT DEFAULT 5
)
RETURNS TABLE (
customer_id BIGINT,
invoiced_amount NUMERIC(12,2),
status VARCHAR(20)
) AS $$
DECLARE
v_due_date DATE;
v_rec RECORD;
BEGIN
-- Calculate dynamic cutoff date
v_due_date := p_billing_month + p_grace_period_days;
-- Loop through active accounts
FOR v_rec IN
SELECT c.id, COALESCE(SUM(o.total_price), 0.00) AS total
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
AND DATE_TRUNC('month', o.order_date) = p_billing_month
WHERE c.is_active = TRUE
GROUP BY c.id
LOOP
-- Set a breakpoint here to inspect v_rec contents
customer_id := v_rec.id;
invoiced_amount := v_rec.total;
IF invoiced_amount > 0 THEN
status := 'INVOICED';
ELSE
status := 'ZERO_BALANCE';
END IF;
RETURN NEXT;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
Press Ctrl + S to compile. If any syntactic mistakes exist, DBeaver highlights the offending line with a red error badge and displays the server's compiler diagnostic code.
3. Debugger Prerequisites & Configuration
Because database code executes directly inside the remote database engine daemon, DBeaver requires a bridge communication channel to pause execution and read thread memory.
For PostgreSQL, the database server must have the open-source pldbgapi plugin installed. Connect as a database superuser and execute:
CREATE EXTENSION pldbgapi;
Also verify that shared_preload_libraries = 'plugin_debugger' is present in your postgresql.conf file if running on a self-hosted server.
4. Starting a Debug Session in DBeaver
Once prerequisites are verified:
- Locate your function in the Database Navigator.
- Right-click the routine name and select Debug → Debug Stored Procedure.
- A parameter dialog appears: enter test arguments to pass into the function's input parameters.
- Click Start Debugging.
- DBeaver switches to the Debug Perspective, showcasing the Editor, Variables Inspector, Breakpoints Panel, and Call Stack.
5. Breakpoints & Stepping Controls
While in the debug perspective, execution pauses at the first executable statement or designated breakpoints. You navigate execution using standard Eclipse / DBeaver debugging shortcuts:
| Action | Shortcut | Behavior Description |
|---|---|---|
| Toggle Breakpoint | Ctrl + Shift + B | Double-click the editor margin line to toggle a breakpoint. Execution pauses before this line executes. |
| Step Into | F5 | Executes current statement. If the statement calls another stored function, execution jumps inside the called function. |
| Step Over | F6 | Executes current statement and moves to the next line in current scope without diving into sub-calls. |
| Step Return | F7 | Finishes execution of current routine and returns control back to the caller frame. |
| Resume Execution | F8 | Continues continuous execution until the next breakpoint is encountered or the procedure completes. |
| Terminate Session | Ctrl + F2 | Immediately aborts the debug thread and rolls back uncommitted changes. |
6. Inspecting Variables & The Call Stack
The true power of DBeaver's debugger lies in the Variables View:
- Input Parameters: Inspect actual argument values passed by the caller.
- Local Variables: Watch scalar values change in real time as statements execute.
- Row & Record Structs: Expand composite records (like
v_recin the billing loop above) to see nested column values. - Call Stack: When function A calls function B which calls function C, the call stack pane displays the entire execution hierarchy. Click any frame to inspect historical variable values at that level.
7. Robust Exception Handling Patterns
When programming procedural logic, unhandled errors immediately abort transactions. DBeaver allows testing exception handling paths directly by simulating edge case parameters:
BEGIN
-- Code that may trigger division by zero or foreign key violation
UPDATE bank_accounts
SET balance = balance - p_amount
WHERE account_id = p_source_id;
EXCEPTION
WHEN check_violation THEN
-- Trap insufficient funds error safely
INSERT INTO audit_log (event, details)
VALUES ('TRANSFER_FAILED', 'Insufficient balance for account ' || p_source_id);
RAISE NOTICE 'Transaction rolled back: Insufficient funds.';
RETURN FALSE;
WHEN OTHERS THEN
RAISE WARNING 'Unexpected database failure: %', SQLERRM;
RAISE;
END;
8. Common Debugger Issues & Solutions
| Symptom | Probable Cause | Resolution |
|---|---|---|
| "Debug" menu item is disabled | Database engine or driver does not support active debugging protocol. | Ensure connection has appropriate procedural debugging driver/extension (e.g. pldbgapi in PostgreSQL) or upgrade to DBeaver PRO for Oracle/DB2. |
| Breakpoint is never hit | Routine was recompiled after breakpoint was set, altering line index. | Clear breakpoints in the Breakpoints view (Window → Show View → Breakpoints) and re-attach breakpoints on the freshly compiled routine. |
| Session times out | Database server has a low statement_timeout or idle in transaction timeout. |
Increase session timeout parameters before beginning long debugging sessions. |