Skip to content

pg_stat_statements always reports "installed but could not be queried" (SAVEPOINT fails in autocommit=True connection) #259

@pablocastilla

Description

@pablocastilla

Summary

In v1.22.0 (pgsqltoolsservice v3.2.0), the pg_stat_statements capability probe
always fails for all databases and all PostgreSQL versions. The extension shows
the warning "pg_stat_statements is installed but could not be queried" regardless
of server configuration.

Steps to Reproduce

  1. Install extension v1.22.0 (ms-ossdata.vscode-pgsql@1.22.0)
  2. Connect to any PostgreSQL server with pg_stat_statements loaded
  3. Open the Performance Dashboard
  4. Observe: "pg_stat_statements is installed but could not be queried" banner always shown

Root Cause

The probe in ossdbtoolsservice.metrics.server_configuration executes:

await cur.execute("SAVEPOINT pgss_probe")
await cur.execute("SELECT 1 FROM pg_stat_statements LIMIT 1")
await cur.execute("RELEASE SAVEPOINT pgss_probe")

However, the pooled connections used by the metrics service have autocommit=True (evidenced by 
Query._restore_autocommit_state which "Restores connection to autocommit mode"). PostgreSQL rejects SAVEPOINT
outside a transaction block:

psycopg.errors.NoActiveSqlTransaction: SAVEPOINT can only be used in transaction blocks

This exception is caught and sets queryable=False, reason="query_failed"making pg_stat_statements appear broken
on every database, regardless of server configuration or PostgreSQL version.

Confirmed with: PostgreSQL 18 (TimescaleDB), PG18 + pg_stat_statements 1.11. Affects all databases, including
vanilla ones with no custom objects.

Evidence

Direct reproduction with psycopg3:

import psycopg
from psycopg_pool import ConnectionPool

pool = ConnectionPool(conninfo, min_size=1, kwargs={"autocommit": True})
with pool.connection() as conn:
    cur = conn.cursor()
    cur.execute("SAVEPOINT pgss_probe")
    # → psycopg.errors.NoActiveSqlTransaction: SAVEPOINT can only be used in transaction blocks

With autocommit=False the probe succeeds correctly.

Suggested Fix

Replace SAVEPOINT/RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINT with BEGIN/COMMIT/ROLLBACK in the probe. BEGIN works
correctly in autocommit=True mode and achieves the same isolation goal:

try:
    await cur.execute("BEGIN")
    await cur.execute("SELECT 1 FROM pg_stat_statements LIMIT 1")
    await cur.execute("COMMIT")
    queryable = True
except Exception as e:
    await conn.execute("ROLLBACK")
    queryable = False
    reason = "query_failed"

Alternatively, ensure the probe runs on a connection with autocommit=False.

Workaround (Binary Patch)

For users who need an immediate fix, the 3 SQL string constants can be replaced in-place in 
ossdbtoolsservice_main.exe (same byte length, PostgreSQL ignores trailing whitespace):

┌───────────────────────────────────────────────┬───────────────────────────────────────────────┐
│ OriginalReplacement                                   │
├───────────────────────────────────────────────┼───────────────────────────────────────────────┤
│ SAVEPOINT pgss_probe (20 bytes)               │ BEGIN                (20 bytes)               │
├───────────────────────────────────────────────┼───────────────────────────────────────────────┤
│ RELEASE SAVEPOINT pgss_probe (28 bytes)       │ COMMIT                       (28 bytes)       │
├───────────────────────────────────────────────┼───────────────────────────────────────────────┤
│ ROLLBACK TO SAVEPOINT pgss_probe (32 bytes)   │ ROLLBACK                         (32 bytes)   │
└───────────────────────────────────────────────┴───────────────────────────────────────────────┘

The strings are in the ossdbtoolsservice.metrics.server_configuration module, compressed at PYZ offset 13105066
within the embedded PYZ archive.

Environment

- Extension: ms-ossdata.vscode-pgsql v1.22.0
- Tools service: pgsqltoolsservice v3.2.0
- OS: Windows 11 x64
- PostgreSQL: 18 (TimescaleDB)
- VS Code: latest

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions