v2-0000-cover-letter.patch
application/octet-stream
Filename: v2-0000-cover-letter.patch
Type: application/octet-stream
Part: 5
From b0cdce84f7825651a6bda1a371bcc2458311545f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Pasternak?= <michal.dtz@gmail.com>
Date: Tue, 7 Jul 2026 15:09:36 +0200
Subject: [PATCH v2 0/5] Schema-qualifiable operator syntax for
implicit-operator constructs (was: Schema-qualify the equality
operator when deparsing NULLIF/IS DISTINCT FROM)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Several SQL constructs resolve an operator by unqualified name at parse
time and provide no place in their syntax to write a schema-qualified
operator name: IS [NOT] DISTINCT FROM, NULLIF, simple CASE, row
comparisons, and ANY/ALL subquery comparisons -- the classes Tom
cataloged in 10492.1531515255@sss.pgh.pa.us -- plus JOIN USING /
NATURAL JOIN. When such a construct ends up bound to an operator that
is not reachable through the search_path in effect at reload time
(typically pg_dump's restricted search_path), the dumped definition
either fails to restore or, worse, silently reparses with a different
operator.
This series gives each construct an optional OPERATOR() decoration,
one construct per patch. The parser always accepts the decoration;
ruleutils.c emits it only when reparsing the undecorated form would
not resolve the very same operator OID(s). Post-analysis expression
trees and executor nodes are untouched.
0001: a IS [NOT] DISTINCT OPERATOR(s.=) FROM b and
NULLIF(a, b USING OPERATOR(s.=))
0002: JOIN ... USING (a, b) OPERATOR (s.=, s.=), one operator per
USING column; NATURAL JOIN deparses via the same path
0003: ROW(a, b) OPERATOR(s.<, s.<) ROW(c, d), generalizing the
existing single-name decoration to a per-column list
0004: (a, b) OPERATOR(op1, op2) ANY (SELECT ...), likewise for
ANY/ALL and row-op-subquery sublinks; fixes today's silent
operator swap when a multi-column IN is dumped and reloaded
0005: CASE x WHEN y USING OPERATOR(s.=) THEN ..., per WHEN arm
The whole series weighs in at 22 files changed, 2366 insertions(+),
90 deletions(-), of which about 1530 lines are regression tests and
expected output and about 165 lines are documentation.
Michał Pasternak (5):
Allow schema-qualifying the operator in IS DISTINCT FROM/NULLIF
Allow schema-qualifying the operators of JOIN USING
Allow per-column operator lists in row comparisons
Allow per-column operator lists in ANY/ALL subquery comparisons
Allow schema-qualifying the comparison operator of a simple CASE
contrib/hstore/expected/hstore.out | 88 ++
contrib/hstore/sql/hstore.sql | 43 +
doc/src/sgml/func/func-comparison.sgml | 23 +-
doc/src/sgml/func/func-comparisons.sgml | 19 +
doc/src/sgml/func/func-conditional.sgml | 39 +-
doc/src/sgml/func/func-subquery.sgml | 40 +
doc/src/sgml/queries.sgml | 12 +
doc/src/sgml/ref/select.sgml | 18 +-
doc/src/sgml/syntax.sgml | 20 +
src/backend/commands/define.c | 5 +
src/backend/parser/gram.y | 103 +-
src/backend/parser/parse_clause.c | 55 +-
src/backend/parser/parse_expr.c | 134 ++-
src/backend/parser/parse_oper.c | 22 +
src/backend/utils/adt/ruleutils.c | 380 +++++++-
src/include/catalog/catversion.h | 2 +-
src/include/nodes/parsenodes.h | 9 +-
src/include/nodes/primnodes.h | 25 +-
src/include/parser/parse_oper.h | 20 +
.../regress/expected/operator_qualify.out | 893 ++++++++++++++++++
src/test/regress/parallel_schedule | 5 +-
src/test/regress/sql/operator_qualify.sql | 501 ++++++++++
22 files changed, 2366 insertions(+), 90 deletions(-)
create mode 100644 src/test/regress/expected/operator_qualify.out
create mode 100644 src/test/regress/sql/operator_qualify.sql
--
2.54.0