This query identifies concurrency risks in user-defined routines by flagging INSERT, UPDATE, or DELETE statements that utilize subqueries without a FOR SHARE locking clause. Failure to acquire a shared lock on source rows allows concurrent transactions to modify or delete them between the subquery's execution and the outer operation, potentially leading to data inconsistencies. Routines utilizing the xmin system column are excluded, operating on the assumption that they implement Optimistic Concurrency Control (version checking) and therefore do not require pessimistic locking.
Notes
The query was improved by ChatGPT 5.2
Type
Problem detection (Each row in the result could represent a flaw in the design)
WITH routines AS (
SELECT
n.nspname AS routine_schema,
p.proname AS routine_name,
pg_get_function_identity_arguments(p.oid) AS parameters,
CASE p.prokind
WHEN 'f' THEN 'FUNCTION'
WHEN 'p' THEN 'PROCEDURE'
WHEN 'w' THEN 'WINDOW FUNCTION'
END AS routine_type,
pg_get_functiondef(p.oid) AS src
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
WHERE p.prokind <> 'a'
AND p.proname NOT IN ('f_assume_you_must_use_files', 'f_check_format_comma_separated_list', 'f_check_password', 'f_default_value_with_no_match')
AND n.nspname NOT IN (
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name <> 'public'
AND schema_owner = 'postgres'
AND schema_name IS NOT NULL
)
AND pg_get_functiondef(p.oid) !~* '\bxmin\b'
),
cte_names AS (
SELECT
r.*,
COALESCE(array_agg(lower(m[1])) FILTER (WHERE m[1] IS NOT NULL), ARRAY[]::text[]) AS ctes
FROM routines r
LEFT JOIN LATERAL regexp_matches(
r.src,
'\b(?:WITH|,)\s*([a-z_][a-z0-9_]*)\s+AS\b',
'gi'
) AS m ON TRUE
GROUP BY r.routine_schema, r.routine_name, r.parameters, r.routine_type, r.src
),
hits AS (
SELECT
c.*,
h[1] AS subselect_text,
lower(h[2]) AS from_name
FROM cte_names c
JOIN LATERAL regexp_matches(
c.src,
'\(\s*(SELECT\b[^)]*\bFROM\s+([a-z_][a-z0-9_]*)(?:\s+[a-z_][a-z0-9_]*)?[^)]*)\)',
'gi'
) AS h ON TRUE
)
SELECT DISTINCT
routine_schema,
routine_name,
parameters,
routine_type,
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(src,'<','<','g'),
'[\r\n]',' ','g'),
'SELECT','SELECT','gi'),
'FOR[[:space:]]+(SHARE|UPDATE|NO[[:space:]]+KEY[[:space:]]+UPDATE|KEY[[:space:]]+SHARE)',
'FOR \1',
'gi'
) AS routine_src
FROM hits
WHERE
-- ära raporteeri, kui subquery loeb CTE nime pealt
from_name <> ALL (ctes)
-- raporteeri, kui subquery sees puudub ridade lukustamine
AND subselect_text !~* '\bFOR\s+(SHARE|UPDATE|NO\s+KEY\s+UPDATE|KEY\s+SHARE)\b'
ORDER BY routine_schema, routine_name, parameters;
Collections
This query belongs to the following collections:
Name
Description
Find problems automatically
Queries, that results point to problems in the database. Each query in the collection produces an initial assessment. However, a human reviewer has the final say as to whether there is a problem or not .
Categories
This query is classified under the following categories:
Name
Description
Concurrency control
Queries of this category provide information about concurrency control.
Does not work in some earlier PostgreSQL version
Queries of this category provide information that was not available in some earlier PostgreSQL version
Transactions
Queries of this catergory provide information about the use of transactions.
User-defined routines
Queries of this category provide information about the user-defined routines