Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x1Gic-0054z5-01 for pgsql-admin@arkaria.postgresql.org; Tue, 01 Sep 2026 05:07:34 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1x1Gib-0043lK-04 for pgsql-admin@arkaria.postgresql.org; Tue, 01 Sep 2026 05:07:33 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x1Gia-0043lB-23 for pgsql-admin@lists.postgresql.org; Tue, 01 Sep 2026 05:07:32 +0000 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1x1GiY-00000002JhX-1oIJ for pgsql-admin@lists.postgresql.org; Tue, 01 Sep 2026 05:07:32 +0000 Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-499ac87c92bso4665235e9.1 for ; Mon, 31 Aug 2026 22:07:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1788239249; x=1788844049; darn=lists.postgresql.org; h=references:to:cc:in-reply-to:date:subject:mime-version:content-type :message-id:from:from:to:cc:subject:date:message-id:reply-to :content-type; bh=2lCkInXnGh5djFjbse+dNknZlvDk1cCqYYS92piCtdw=; b=HM7dwOGHmMa8SOwXNiAavUl5YdrBeTPXfiLcFlmH+NOe8n6a7kLs/rlr1J64sVcxEn ztjkgDYjd1BYi2iLaXa3IX8sptJT9GTOl6IzFr8C7Bs/H6TqGfBqxNH8hQrgk6Ngo0iJ VD5hnbgneNTgV3lGS7Q9zbUxGwA2oQIFBienkw10rufbv16nqht4Q/bu1ae+2Sb3VoBm DpdM/zOlDMwEcVYoc1oAMQsfCDzsXCY4Uog5Is6NPpe4RwIX7lVwyxSOA8Z+5DIAoFGl jevCSfAZ4HRSbjJIiJKn7SfSdX1aPw4NApjgAZFcaVctvXdmw3vtkh83obtHhbc2za+g LFzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788239249; x=1788844049; h=references:to:cc:in-reply-to:date:subject:mime-version:content-type :message-id:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=2lCkInXnGh5djFjbse+dNknZlvDk1cCqYYS92piCtdw=; b=rPP0aylt99YeP3EtfPRbpLhCV1XrucDD7BsIjo3DtWMld0D0sdiGB9p/13LxnLSyGP IOll7WB87yxLXZsiey0Hw1JivzZYOcBB9HyOO+pUXcL0IYfvtOVs/8u/kJj2cTUYNIYD hu+cUFtmXx9HuPB3/MZCD9kSfZZDwfI2Ry82lfH6rEdP6/p1aFK5pEkUfQMzSuEph+Xw gG+D1Aj0snGpSB9xh+dU+hv6XqeI1oOWqaMIPggnDAqanS5BFaB+MryqNc1BcNoi3wZ/ pNHWZPYSJu7CnImxWHUAWejyB/Ek/VcyEt+2gwvv0wmoOgT4C+lLLVNbdKUTvIgc3AIK FVPQ== X-Gm-Message-State: AFuF++k3EC1gM0vXN0MZl6ZF+JRuFrw5cozDQSHvJqpRhkTwiSiBwoh5 rX/T626I0U9LL7QEWX6qITtbH1ZaPZVs9eRO5c7iXShihd9VuAs5Ll2fhzcetw== X-Gm-Gg: AR+sD10+5OXXahMI+THs5+zlGpfsEBdIEu2XzbD6HZ+H0D+k9I0p4+PRjNPRQlLvymo +ZRSTuJQtTTnTslH9TVeHQqeJfF0ZRLUtz8YTbUeFU74gZIoaHuAsT9FwyA3cYsu1blZTNr5wzt fdnz1oOwQGGrGtxfbhwFymZ2Fi9/XWEpgJJxg+AnNubQP/zgdMV7SOKwbZG65DHfqjmX85jSxLV DPJ2n+wZWAVBbuI8u13Lppqe4Gk7GnMBK37yt18mKfunIOAYgU2mRkpK9G/WbO2/m3xhq7LrXB4 lWQysg9TRTmRtiaaYGlSePTbmDBN9QU6TLXAQGQuawke8m8GB59G5aJHlHlAEDV+RN/FDhQap4c 1yFWJ7LeZMofhvmMNd8g6OicLyFoboCqBAde390k5Kq6L9YEeldr8koHpqY7JxBOByLBdAbT9e6 sP721qHvJjYS4o6ykcd7KbRzzw9HNt5fLTfv5VtUpI25Rr/eowz1b+81+tM5NgnWwjT1NA8BD/Y xrEyvBs4XfRJDdq+cQZsmzM7Xgsp/KO3UTPE/tiPl9LUOM= X-Received: by 2002:a05:600c:4688:b0:499:78b3:7b36 with SMTP id 5b1f17b1804b1-49b91c4fa79mr403753515e9.11.1788239249096; Mon, 31 Aug 2026 22:07:29 -0700 (PDT) Received: from smtpclient.apple (88-188-215-218.subs.proxad.net. [88.188.215.218]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49cdce4a804sm43618475e9.15.2026.08.31.22.07.28 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 31 Aug 2026 22:07:28 -0700 (PDT) From: bertrand HARTWIG Message-Id: Content-Type: multipart/alternative; boundary="Apple-Mail=_0995631E-2713-4452-98AC-57886B50AF72" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.700.51.1.1\)) Subject: Re: How to definitively determine whether a statement is a SELECT statement? Date: Tue, 1 Sep 2026 07:07:17 +0200 In-Reply-To: Cc: Pgsql-admin To: Ron Johnson References: X-Mailer: Apple Mail (2.3864.700.51.1.1) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_0995631E-2713-4452-98AC-57886B50AF72 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hello, You can use this python lib : pglast from pglast import parse_sql from pglast.ast import SelectStmt def is_select_query(sql: str) -> bool: try: statements =3D parse_sql(sql) except Exception: return False # SQL invalide if len(statements) !=3D 1: return False # Refuse plusieurs instructions SQL return isinstance(statements[0].stmt, SelectStmt) print(is_select_query("SELECT * FROM users")) # True print(is_select_query("WITH x AS (SELECT 1) SELECT * FROM x")) # True print(is_select_query("INSERT INTO users(name) VALUES ('Alice')")) # = False print(is_select_query("SELECT 1; DELETE FROM users")) # False Bertrand > Le 31 ao=C3=BBt 2026 =C3=A0 18:06, Ron Johnson = a =C3=A9crit : >=20 > Sometimes, the developers add comments to the top of statements, and = so we see that in pg_stat_activity.query as seen in this example: >=20 > select query > from pg_stat_activity > where pid =3D 1054079; > query =20 > ---------------------------------------- > -- Some comment written by the developer > SELECT blah blah FROM .blah >=20 > I could case-insensitively search pg_stat_activity.query for "SELECT " = but that will fail if there is a SELECT in the CTE or subquery of a = DELETE or UPDATE statement, and writing a parser to strip out all = comments is a bit too much effort for a simple query. >=20 > -- > Death to , and butter sauce. > Don't boil me, I'm still alive. > lobster! --Apple-Mail=_0995631E-2713-4452-98AC-57886B50AF72 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 Hello,

You can use = this python lib : pglast

from pglast import = parse_sql
from pglast.ast import = SelectStmt


def = is_select_query(sql: str) -> bool:
    = try:
        statements =3D = parse_sql(sql)
    except = Exception:
        return False  # = SQL invalide

    if len(statements) = !=3D 1:
        return False  # = Refuse plusieurs instructions SQL

    = return isinstance(statements[0].stmt, = SelectStmt)


print(is_select_query(= "SELECT * FROM users"))          # = True
print(is_select_query("WITH x AS (SELECT 1) SELECT * FROM = x"))  # True
print(is_select_query("INSERT INTO = users(name) VALUES ('Alice')"))  # = False
print(is_select_query("SELECT 1; DELETE FROM users")) =  # = False

Bertrand

Le 31 ao=C3=BBt 2026 =C3=A0 18:06, Ron Johnson = <ronljohnsonjr@gmail.com> a =C3=A9crit :

Sometimes, = the developers add comments to the top of statements, and so we see that = in pg_stat_activity.query as seen in this = example:

select = query
from pg_stat_activity
where pid =3D 1054079;
 query =  
----------------------------------------
-- Some comment written by the developer
SELECT = blah blah FROM .blah

I could = case-insensitively search pg_stat_activity.query for "SELECT " but = that will fail if there is a SELECT in the CTE or subquery of a DELETE = or UPDATE statement, and writing a parser to strip out all comments is a = bit too much effort for a simple query.

--
Death to <Redacted>, and butter sauce.
Don't boil = me, I'm still alive.
<Redacted> = lobster!

= --Apple-Mail=_0995631E-2713-4452-98AC-57886B50AF72--