Back
0
0

2025-01-05

Goodbye Boring Command Line: How to Debug PostgreSQL with VSCode GUI

by Zhang Chen

A few days ago in my hands-on series, I mentioned using VSCode + Linux VM to debug PostgreSQL source code. Some fellow developers asked me about the detailed process, so this article will describe the complete workflow to help you get started.

Environment Setup

Configure Linux Virtual Machine

VM Version

For new environments, I recommend installing CentOS 8 or above, as the current official VSCode version requires glibc 2.28 or higher.

Starting with VS Code release 1.99 (March 2025), the prebuilt servers distributed by VS Code are only compatible with Linux distributions that are based on glibc 2.28 or later.

If you don't want to spend extra time compiling a higher version of glibc, install CentOS 8.3 directly.

[root@node1 ~]# cat /etc/redhat-release
CentOS Linux release 8.3.2011

Database Compilation and Installation

I won't go into detail about database compilation. Download the source code, extract it, install the required dependencies, and execute compilation.

Here are my commonly used parameters:

export CFLAGS='-g -O0 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wformat-security -fno-strict-aliasing -fwrapv'

./configure --prefix=/home/18pg/local --with-perl --with-tcl --with-python --with-openssl --with-pam --without-ldap --with-libxml --with-libxslt --enable-thread-safety --with-wal-blocksize=8 --with-blocksize=8 --enable-dtrace --enable-debug && make -j4 && make install

Configure VSCode

Download VSCode from the official website. After installation, search for the Remote - SSH extension in the Extensions panel and install it.

Install Remote-SSH Extension

Connect to Virtual Machine

After installing the Remote-SSH plugin, a computer icon will appear in the left sidebar. Switch to that panel and click "New Remote".

Create New Remote Connection

The connection format is username@ip. I usually use the root user for developing and debugging PostgreSQL source code.

Connect as Root User

If you need to debug tools like pg_probackup or pg_waldump, you must use the database installation user (e.g., postgres) to access the proper library environment.

Connect as Postgres User

Open Directory

After connecting successfully, select your source code directory.

Select Source Directory

Now you can read the source code directly in VSCode. Even without debugging, VSCode is an excellent source code browsing and searching tool.

Source Code Browser

Debug PostgreSQL Source Code

After opening the source directory, how do we actually run and debug the code?

Configure .vscode Directory

First, create a .vscode folder in your opened source code directory.

Create .vscode Directory

  • Note: Make sure to create it at the top-level directory.

Then create a file named launch.json in the .vscode folder.

Create launch.json

Copy and paste the following content, changing the program path to your own postgres program location:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "postgres",
      "type": "cppdbg",
      "request": "attach",
      "program": "/home/18pg/local/bin/postgres",
      "processId": "${command:pickProcess}",
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ]
}

launch.json Configuration

After creating the launch.json file, click the bug icon on the left sidebar. You'll see an option named postgres, which is the name field we set in launch.json.

Debug Panel

Start a psql Client

Before starting the debugger, go to the Linux command line, execute psql to enter the database, and run select pg_backend_pid() to get the current session's pid. In this case, it's 1044682. Copy this ID.

[18pg@node1 ~]$ psql alldb
psql (18.0)
Type "help" for help.

alldb=# select pg_backend_pid();
 pg_backend_pid
----------------
        1044682
(1 row)

Start postgres Debugger

Click the green triangle, and you'll be prompted to attach to a process.

Start Debugging

Simply paste the ID we copied in the previous step.

Enter Process ID

  • Note: If you don't paste the ID immediately after clicking the green triangle and switch away, a timeout dialog will appear. Just cancel and click the green triangle again.

Timeout Dialog

After entering the ID and pressing Enter, if you see the red box style on the right, the debugging process has started successfully.

Debugger Attached

Set Breakpoints and Debug

Now you can set breakpoints on code you're interested in. For example, I set a breakpoint in the varchar function parsing code. Simply click on the left side of the code line to create a yellow dot, and it will also appear in the "Breakpoints" panel on the right.

Set Breakpoint

Return to the command-line session and execute a SELECT query. The statement will hang.

Execute Query

VSCode will show the following, indicating that the SELECT statement has reached this function.

Breakpoint Hit

  • To go directly from line 518 to 519, click "Step Over"

Step Over Button

  • To enter the PG_GETARG_DATUM function on line 518, click "Step Into"

Step Into Button

  • To skip the current breakpoint and continue to the next breakpoint, click "Continue"

Continue Button

Debug Tool Source Code

When we need to debug PostgreSQL peripheral tools like pg_probackup or pg_waldump, the above debugging approach won't work. We need to adjust the launch.json file content.

Suppose we want to debug the command pg_waldump 0000000100000002000000A1 0000000100000002000000A2. The launch.json content would be:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "pg_waldump",
      "type": "cppdbg",
      "request": "launch",
      "program": "/home/18pg/local/bin/pg_waldump",
      "cwd": "/home/18pg/wal_arch",
      "args": ["0000000100000002000000A1", "0000000100000002000000A2"],
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ]
}

Four changes were made:

  • request method changed from attach to launch
  • program path changed to the pg_waldump program path
  • Added args parameter to set program arguments, each enclosed in quotes and separated by commas
  • Added cwd parameter to set the current execution path, here set to the WAL archive path

With this configuration, clicking the green button is equivalent to directly executing pg_waldump 0000000100000002000000A1 0000000100000002000000A2. We just need to set breakpoints at the code locations we want to observe.

Debug pg_waldump

Additionally, we can write multiple debug programs in the same launch.json file and switch between them freely:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "postgres",
      "type": "cppdbg",
      "request": "attach",
      "program": "/home/18pg/local/bin/postgres",
      "processId": "${command:pickProcess}",
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    },
    {
      "name": "pg_waldump",
      "type": "cppdbg",
      "request": "launch",
      "program": "/home/18pg/local/bin/pg_waldump",
      "cwd": "/home/18pg/wal_arch",
      "args": ["0000000100000002000000A1", "0000000100000002000000A2"],
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ]
    }
  ]
}

Multiple Configurations

Comments (0)

No comments yet. Be the first to comment!