From 338fd36df48a178fdda18bf8cc83ba84554ea2f8 Mon Sep 17 00:00:00 2001 From: Fujii Masao Date: Wed, 21 Oct 2026 11:14:03 +0900 Subject: [PATCH v2 3/3] Mark xpath and quote_ident as STABLE xpath calls float8out to format numeric results, so its output can depend on extra_float_digits GUC. quote_ident calls quote_identifier, whose output depends on quote_all_identifiers GUC. Mark both xpath overloads and quote_ident STABLE instead of IMMUTABLE to reflect their dependence on session settings. This prevents them from being used in expressions that require immutability, such as expression indexes, generated columns, and partition keys. Do not backpatch, since this changes catalog entries and can break existing schemas that rely on these functions being immutable. Author: Fujii Masao Discussion: https://postgr.es/m/871538.1792513085@sss.pgh.pa.us --- src/backend/catalog/system_functions.sql | 2 +- src/include/catalog/pg_proc.dat | 10 +++++----- src/test/regress/expected/xml.out | 2 -- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql index c3c0a6e84ed..de026a1a30c 100644 --- a/src/backend/catalog/system_functions.sql +++ b/src/backend/catalog/system_functions.sql @@ -243,7 +243,7 @@ RETURN $2 + $1; CREATE OR REPLACE FUNCTION xpath(text, xml) RETURNS xml[] LANGUAGE sql - IMMUTABLE PARALLEL SAFE STRICT COST 1 + STABLE PARALLEL SAFE STRICT COST 1 RETURN xpath($1, $2, '{}'::text[]); CREATE OR REPLACE FUNCTION xpath_exists(text, xml) diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 1f21a8eb6d4..59ad6da9edd 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -4846,8 +4846,8 @@ proargtypes => 'interval text', prosrc => 'interval_to_char' }, { oid => '1282', descr => 'quote an identifier for usage in a querystring', - proname => 'quote_ident', prorettype => 'text', proargtypes => 'text', - prosrc => 'quote_ident' }, + proname => 'quote_ident', provolatile => 's', prorettype => 'text', + proargtypes => 'text', prosrc => 'quote_ident' }, { oid => '1283', descr => 'quote a literal for usage in a querystring', proname => 'quote_literal', prorettype => 'text', proargtypes => 'text', prosrc => 'quote_literal' }, @@ -9443,10 +9443,10 @@ { oid => '2931', descr => 'evaluate XPath expression, with namespaces support', - proname => 'xpath', prorettype => '_xml', proargtypes => 'text xml _text', - prosrc => 'xpath' }, + proname => 'xpath', provolatile => 's', prorettype => '_xml', + proargtypes => 'text xml _text', prosrc => 'xpath' }, { oid => '2932', descr => 'evaluate XPath expression', - proname => 'xpath', prolang => 'sql', prorettype => '_xml', + proname => 'xpath', prolang => 'sql', provolatile => 's', prorettype => '_xml', proargtypes => 'text xml', prosrc => 'see system_functions.sql' }, { oid => '2614', descr => 'test XML value against XPath expression', diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index 6998745ee03..fbcc54448be 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -907,7 +907,6 @@ SELECT xpath(NULL, NULL) IS NULL FROM xmltest; SELECT xpath('', ''); ERROR: empty XPath expression -CONTEXT: SQL function "xpath" statement 1 SELECT xpath('//text()', 'number one'); xpath ---------------- @@ -1277,7 +1276,6 @@ ERROR: could not parse XML document DETAIL: line 1: Namespace prefix nosuchprefix on tag is not defined ^ -CONTEXT: SQL function "xpath" statement 1 -- XPath deprecates relative namespaces, but they're not supposed to -- throw an error, only a warning. SELECT xpath('/*', ''); -- 2.56.0