From 1b1a9d08bafeeb02f0bca2b7595677779f17a189 Mon Sep 17 00:00:00 2001 From: Ilya Staroverov Date: Mon, 26 Oct 2026 12:40:42 +0300 Subject: [PATCH v1 01/11] pg_stat_statements: Add tests for more query patterns These tests show that some queries that differ in more than their constants are merged into a single entry, as what makes them different is not part of the query ID: - the names in XMLELEMENT, XMLATTRIBUTES, XMLFOREST and XMLPI, and DOCUMENT or CONTENT in XMLPARSE and XMLSERIALIZE; - the column types, defaults, NOT NULL and FOR ORDINALITY of XMLTABLE, its namespaces, and the names of its columns without PATH; - ROLLUP, CUBE and GROUPING SETS; - the SEARCH and CYCLE clauses of recursive CTEs; - the column definition lists of functions in FROM; - VARIADIC in calls of functions taking VARIADIC "any"; - the fields of a composite column assigned by INSERT or UPDATE; - the composite type that ROW() constructors are cast to, and the operators of row comparisons; - OVERRIDING in INSERT and MERGE. So are queries that differ in the WHITESPACE option of XMLPARSE, in VERSION NO VALUE and the STANDALONE option of XMLROOT, or in the type modifier of XMLSERIALIZE. The SQL/XML tests go into a new file, xml.sql, with an alternate output for builds without libxml, as in the main regression test suite. Author: Ilya Staroverov --- contrib/pg_stat_statements/Makefile | 1 + contrib/pg_stat_statements/expected/dml.out | 67 +++ .../pg_stat_statements/expected/select.out | 380 ++++++++++++++ contrib/pg_stat_statements/expected/xml.out | 485 ++++++++++++++++++ contrib/pg_stat_statements/expected/xml_1.out | 445 ++++++++++++++++ contrib/pg_stat_statements/meson.build | 1 + contrib/pg_stat_statements/sql/dml.sql | 31 ++ contrib/pg_stat_statements/sql/select.sql | 93 ++++ contrib/pg_stat_statements/sql/xml.sql | 144 ++++++ 9 files changed, 1647 insertions(+) create mode 100644 contrib/pg_stat_statements/expected/xml.out create mode 100644 contrib/pg_stat_statements/expected/xml_1.out create mode 100644 contrib/pg_stat_statements/sql/xml.sql diff --git a/contrib/pg_stat_statements/Makefile b/contrib/pg_stat_statements/Makefile index 2fe2a077ad..01ff05ea07 100644 --- a/contrib/pg_stat_statements/Makefile +++ b/contrib/pg_stat_statements/Makefile @@ -37,6 +37,7 @@ REGRESS = \ plancache \ squashing \ sqljson \ + xml \ cleanup \ oldextversions diff --git a/contrib/pg_stat_statements/expected/dml.out b/contrib/pg_stat_statements/expected/dml.out index 347cb8699e..b310a97b25 100644 --- a/contrib/pg_stat_statements/expected/dml.out +++ b/contrib/pg_stat_statements/expected/dml.out @@ -139,6 +139,73 @@ SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t (10 rows) +-- OVERRIDING +CREATE TEMP TABLE pgss_identity_tab (a int GENERATED BY DEFAULT AS IDENTITY, b int); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +INSERT INTO pgss_identity_tab VALUES (100, 1); +-- with OVERRIDING USER VALUE, a gets the next identity value +INSERT INTO pgss_identity_tab OVERRIDING USER VALUE VALUES (100, 1); +INSERT INTO pgss_identity_tab OVERRIDING SYSTEM VALUE VALUES (100, 1); +MERGE INTO pgss_identity_tab USING (SELECT 1 AS b) s ON false + WHEN NOT MATCHED THEN INSERT VALUES (100, s.b); +MERGE INTO pgss_identity_tab USING (SELECT 1 AS b) s ON false + WHEN NOT MATCHED THEN INSERT OVERRIDING USER VALUE VALUES (100, s.b); +MERGE INTO pgss_identity_tab USING (SELECT 1 AS b) s ON false + WHEN NOT MATCHED THEN INSERT OVERRIDING SYSTEM VALUE VALUES (100, s.b); +SELECT a, b FROM pgss_identity_tab ORDER BY a; + a | b +-----+--- + 1 | 1 + 2 | 1 + 100 | 1 + 100 | 1 + 100 | 1 + 100 | 1 +(6 rows) + +DROP TABLE pgss_identity_tab; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | rows | query +-------+------+------------------------------------------------------------- + 3 | 3 | INSERT INTO pgss_identity_tab VALUES ($1, $2) + 3 | 3 | MERGE INTO pgss_identity_tab USING (SELECT $1 AS b) s ON $2+ + | | WHEN NOT MATCHED THEN INSERT VALUES ($3, s.b) + 1 | 6 | SELECT a, b FROM pgss_identity_tab ORDER BY a + 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(4 rows) + +-- assignments to fields of a composite column +CREATE TYPE pgss_point AS (x int, y int); +CREATE TEMP TABLE pgss_fieldstore_tab (c pgss_point); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +INSERT INTO pgss_fieldstore_tab (c.x) VALUES (1); +INSERT INTO pgss_fieldstore_tab (c.y) VALUES (2); +INSERT INTO pgss_fieldstore_tab (c.x, c.y) VALUES (3, 4); +UPDATE pgss_fieldstore_tab SET c.x = 5; +UPDATE pgss_fieldstore_tab SET c.y = 6; +UPDATE pgss_fieldstore_tab SET c.x = 7, c.y = 8; +DROP TABLE pgss_fieldstore_tab; +DROP TYPE pgss_point; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | rows | query +-------+------+------------------------------------------------------------ + 2 | 2 | INSERT INTO pgss_fieldstore_tab (c.x) VALUES ($1) + 1 | 1 | INSERT INTO pgss_fieldstore_tab (c.x, c.y) VALUES ($1, $2) + 1 | 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 2 | 6 | UPDATE pgss_fieldstore_tab SET c.x = $1 + 1 | 3 | UPDATE pgss_fieldstore_tab SET c.x = $1, c.y = $2 +(5 rows) + -- check that [temp] table relation extensions are tracked as writes CREATE TABLE pgss_extend_tab (a int, b text); CREATE TEMP TABLE pgss_extend_temp_tab (a int, b text); diff --git a/contrib/pg_stat_statements/expected/select.out b/contrib/pg_stat_statements/expected/select.out index a069119c79..5961c894e9 100644 --- a/contrib/pg_stat_statements/expected/select.out +++ b/contrib/pg_stat_statements/expected/select.out @@ -889,3 +889,383 @@ SELECT pg_stat_statements_reset() IS NOT NULL AS t; t (1 row) +-- ROLLUP, CUBE and GROUPING SETS +CREATE TEMP TABLE pgss_empty_tab (a int, b int); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY ROLLUP (a, b); + a | b | count +---+---+------- + | | 0 +(1 row) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY CUBE (a, b); + a | b | count +---+---+------- + | | 0 +(1 row) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY GROUPING SETS (a, b); + a | b | count +---+---+------- +(0 rows) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY ROLLUP ((a, b)); + a | b | count +---+---+------- + | | 0 +(1 row) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY CUBE ((a, b)); + a | b | count +---+---+------- + | | 0 +(1 row) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY a, ROLLUP (b); + a | b | count +---+---+------- +(0 rows) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY a, CUBE (b); + a | b | count +---+---+------- +(0 rows) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY GROUPING SETS (ROLLUP (a), CUBE (b)); + a | b | count +---+---+------- + | | 0 + | | 0 +(2 rows) + +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY GROUPING SETS (CUBE (a), ROLLUP (b)); + a | b | count +---+---+------- + | | 0 + | | 0 +(2 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | query +-------+----------------------------------------------------------------------------------------- + 2 | SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY GROUPING SETS (ROLLUP (a), CUBE (b)) + 2 | SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY ROLLUP ((a, b)) + 3 | SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY ROLLUP (a, b) + 2 | SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY a, ROLLUP (b) + 0 | SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C" + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(6 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- WITH RECURSIVE ... SEARCH and CYCLE +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SELECT * FROM t; + a | b +---+--- +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a SET seq SELECT * FROM t; + a | b | seq +---+---+----- +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH BREADTH FIRST BY a SET seq SELECT * FROM t; + a | b | seq +---+---+----- +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY b SET seq SELECT * FROM t; + a | b | seq +---+---+----- +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a, b SET seq SELECT * FROM t; + a | b | seq +---+---+----- +(0 rows) + +-- only the name of the sequence column differs +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a SET ord SELECT * FROM t; + a | b | ord +---+---+----- +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET is_cycle USING path SELECT * FROM t; + a | b | is_cycle | path +---+---+----------+------ +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE b SET is_cycle USING path SELECT * FROM t; + a | b | is_cycle | path +---+---+----------+------ +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a, b SET is_cycle USING path SELECT * FROM t; + a | b | is_cycle | path +---+---+----------+------ +(0 rows) + +-- TO true DEFAULT false is the default +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET is_cycle TO true DEFAULT false USING path SELECT * FROM t; + a | b | is_cycle | path +---+---+----------+------ +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET is_cycle TO 'Y' DEFAULT 'N' USING path SELECT * FROM t; + a | b | is_cycle | path +---+---+----------+------ +(0 rows) + +-- only the names of the mark and path columns differ +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET c USING p SELECT * FROM t; + a | b | c | p +---+---+---+--- +(0 rows) + +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a SET seq CYCLE a SET is_cycle USING path SELECT * FROM t; + a | b | seq | is_cycle | path +---+---+-----+----------+------ +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | query +-------+----------------------------------------------------------------------------------------- + 0 | SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C" + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 6 | WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + $1, b FROM t)+ + | CYCLE a SET is_cycle USING path SELECT * FROM t + 1 | WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + $1, b FROM t)+ + | SEARCH DEPTH FIRST BY a SET seq CYCLE a SET is_cycle USING path SELECT * FROM t + 5 | WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + $1, b FROM t)+ + | SEARCH DEPTH FIRST BY a SET seq SELECT * FROM t + 1 | WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + $1, b FROM t)+ + | SELECT * FROM t +(6 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- column definition lists +SELECT * FROM json_to_record('{"a": 1}') AS t(a int); + a +--- + 1 +(1 row) + +-- only the constant differs +SELECT * FROM json_to_record('{"a": 2}') AS t(a int); + a +--- + 2 +(1 row) + +SELECT * FROM json_to_record('{"a": 1}') AS t(a text); + a +--- + 1 +(1 row) + +SELECT * FROM json_to_record('{"a": 1}') AS t(a varchar(3)); + a +--- + 1 +(1 row) + +SELECT * FROM json_to_record('{"a": 1}') AS t(a varchar(4)); + a +--- + 1 +(1 row) + +SELECT * FROM json_to_record('{"a": 1}') AS t(a text COLLATE "C"); + a +--- + 1 +(1 row) + +-- the column names are the keys to look up +SELECT * FROM json_to_record('{"a": 1}') AS t(b int); + b +--- + +(1 row) + +SELECT * FROM json_to_record('{"a": 1}') AS t(a int, b int); + a | b +---+--- + 1 | +(1 row) + +SELECT * FROM ROWS FROM (json_to_record('{"a": 1}') AS (a int), + json_to_record('{"b": 1}') AS (b int)) AS t; + a | b +---+--- + 1 | 1 +(1 row) + +SELECT * FROM ROWS FROM (json_to_record('{"a": 1}') AS (a int), + json_to_record('{"b": 1}') AS (b text)) AS t; + a | b +---+--- + 1 | 1 +(1 row) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | query +-------+------------------------------------------------------------------------ + 2 | SELECT * FROM ROWS FROM (json_to_record($1) AS (a int), + + | json_to_record($2) AS (b int)) AS t + 7 | SELECT * FROM json_to_record($1) AS t(a int) + 1 | SELECT * FROM json_to_record($1) AS t(a int, b int) + 0 | SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C" + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- VARIADIC +SELECT format('%s', VARIADIC ARRAY['a', 'b']); + format +-------- + a +(1 row) + +SELECT format('%s', ARRAY['a', 'b']); + format +-------- + {a,b} +(1 row) + +SELECT concat(VARIADIC ARRAY['a', 'b']); + concat +-------- + ab +(1 row) + +SELECT concat(ARRAY['a', 'b']); + concat +-------- + {a,b} +(1 row) + +-- VARIADIC is the same as separate arguments, except for VARIADIC "any" +SELECT jsonb_extract_path('{}', a::text, b::text) FROM pgss_empty_tab; + jsonb_extract_path +-------------------- +(0 rows) + +SELECT jsonb_extract_path('{}', VARIADIC ARRAY[a::text, b::text]) + FROM pgss_empty_tab; + jsonb_extract_path +-------------------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | query +-------+------------------------------------------------------------------------ + 0 | SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C" + 2 | SELECT concat(VARIADIC ARRAY[$1 /*, ... */]) + 2 | SELECT format($1, VARIADIC ARRAY[$2 /*, ... */]) + 2 | SELECT jsonb_extract_path($1, a::text, b::text) FROM pgss_empty_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +-- row constructors and row comparisons +CREATE TYPE pgss_pair1 AS (x int, y int); +CREATE TYPE pgss_pair2 AS (p int, q int); +SELECT (ROW(1, 2)::pgss_pair1).*; + x | y +---+--- + 1 | 2 +(1 row) + +SELECT (ROW(1, 2)::pgss_pair2).*; + p | q +---+--- + 1 | 2 +(1 row) + +SELECT ROW(1, 2); + row +------- + (1,2) +(1 row) + +SELECT ROW(1, 2)::pgss_pair1; + row +------- + (1,2) +(1 row) + +SELECT ROW(s, t) < ROW('b', 'b') FROM (VALUES ('a', 'a')) AS v(s, t); + ?column? +---------- + t +(1 row) + +SELECT ROW(s, t) ~<~ ROW('b', 'b') FROM (VALUES ('a', 'a')) AS v(s, t); + ?column? +---------- + t +(1 row) + +SELECT ROW(s, t) <= ROW('b', 'b') FROM (VALUES ('a', 'a')) AS v(s, t); + ?column? +---------- + t +(1 row) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + calls | query +-------+------------------------------------------------------------------------ + 2 | SELECT (ROW($1, $2)::pgss_pair1).* + 2 | SELECT ROW($1, $2) + 2 | SELECT ROW(s, t) < ROW($1, $2) FROM (VALUES ($3, $4)) AS v(s, t) + 1 | SELECT ROW(s, t) <= ROW($1, $2) FROM (VALUES ($3, $4)) AS v(s, t) + 0 | SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C" + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(6 rows) + +DROP TYPE pgss_pair1, pgss_pair2; +DROP TABLE pgss_empty_tab; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + diff --git a/contrib/pg_stat_statements/expected/xml.out b/contrib/pg_stat_statements/expected/xml.out new file mode 100644 index 0000000000..6c4c34b2c5 --- /dev/null +++ b/contrib/pg_stat_statements/expected/xml.out @@ -0,0 +1,485 @@ +-- +-- SQL/XML +-- +SET pg_stat_statements.track_utility = FALSE; +CREATE TABLE pgss_xml_tab (x xml, t text); +-- +-- SQL/XML functions +-- +-- XMLELEMENT, XMLATTRIBUTES, XMLFOREST and XMLPI names +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLELEMENT(NAME foo) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +SELECT XMLELEMENT(NAME bar) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +SELECT XMLELEMENT(NAME foo, t) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a)) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS b)) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +-- the attribute name defaults to the column name +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t)) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS t)) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a), t) FROM pgss_xml_tab; + xmlelement +------------ +(0 rows) + +SELECT XMLFOREST(t AS a) FROM pgss_xml_tab; + xmlforest +----------- +(0 rows) + +SELECT XMLFOREST(t AS b) FROM pgss_xml_tab; + xmlforest +----------- +(0 rows) + +-- the element name defaults to the column name +SELECT XMLFOREST(t) FROM pgss_xml_tab; + xmlforest +----------- +(0 rows) + +SELECT XMLFOREST(t AS t) FROM pgss_xml_tab; + xmlforest +----------- +(0 rows) + +SELECT XMLFOREST(t AS a, x AS b) FROM pgss_xml_tab; + xmlforest +----------- +(0 rows) + +SELECT XMLPI(NAME foo) FROM pgss_xml_tab; + xmlpi +------- +(0 rows) + +SELECT XMLPI(NAME bar) FROM pgss_xml_tab; + xmlpi +------- +(0 rows) + +SELECT XMLPI(NAME foo, t) FROM pgss_xml_tab; + xmlpi +------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+------------------------------------------------------------------------- + 2 | SELECT XMLELEMENT(NAME foo) FROM pgss_xml_tab + 4 | SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a)) FROM pgss_xml_tab + 1 | SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a), t) FROM pgss_xml_tab + 1 | SELECT XMLELEMENT(NAME foo, t) FROM pgss_xml_tab + 4 | SELECT XMLFOREST(t AS a) FROM pgss_xml_tab + 1 | SELECT XMLFOREST(t AS a, x AS b) FROM pgss_xml_tab + 2 | SELECT XMLPI(NAME foo) FROM pgss_xml_tab + 1 | SELECT XMLPI(NAME foo, t) FROM pgss_xml_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(9 rows) + +-- XMLPARSE and XMLSERIALIZE +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLPARSE(DOCUMENT t) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +SELECT XMLPARSE(CONTENT t) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +-- STRIP WHITESPACE is the default +SELECT XMLPARSE(CONTENT t STRIP WHITESPACE) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +SELECT XMLPARSE(CONTENT t PRESERVE WHITESPACE) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +SELECT XMLSERIALIZE(DOCUMENT x AS text) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS text) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +-- NO INDENT is the default +SELECT XMLSERIALIZE(CONTENT x AS text NO INDENT) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS text INDENT) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS varchar(10)) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS varchar(20)) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+----------------------------------------------------------------- + 4 | SELECT XMLPARSE(DOCUMENT t) FROM pgss_xml_tab + 1 | SELECT XMLSERIALIZE(CONTENT x AS text INDENT) FROM pgss_xml_tab + 2 | SELECT XMLSERIALIZE(CONTENT x AS varchar(10)) FROM pgss_xml_tab + 3 | SELECT XMLSERIALIZE(DOCUMENT x AS text) FROM pgss_xml_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +-- XMLROOT +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLROOT(x, VERSION '1.0') FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.1') FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION NO VALUE) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.0', STANDALONE YES) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.0', STANDALONE NO) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.0', STANDALONE NO VALUE) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 6 | SELECT XMLROOT(x, VERSION $1) FROM pgss_xml_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- XMLCONCAT, IS DOCUMENT and XMLEXISTS +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLCONCAT(x, x) FROM pgss_xml_tab; + xmlconcat +----------- +(0 rows) + +SELECT XMLCONCAT(x, x, x) FROM pgss_xml_tab; + xmlconcat +----------- +(0 rows) + +SELECT x IS DOCUMENT FROM pgss_xml_tab; + ?column? +---------- +(0 rows) + +SELECT x IS NOT DOCUMENT FROM pgss_xml_tab; + ?column? +---------- +(0 rows) + +SELECT XMLEXISTS('/r' PASSING x) FROM pgss_xml_tab; + xmlexists +----------- +(0 rows) + +-- BY REF and BY VALUE are noise words +SELECT XMLEXISTS('/r' PASSING BY REF x) FROM pgss_xml_tab; + xmlexists +----------- +(0 rows) + +SELECT XMLEXISTS('/r' PASSING BY VALUE x BY VALUE) FROM pgss_xml_tab; + xmlexists +----------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 1 | SELECT XMLCONCAT(x, x) FROM pgss_xml_tab + 1 | SELECT XMLCONCAT(x, x, x) FROM pgss_xml_tab + 3 | SELECT XMLEXISTS($1 PASSING x) FROM pgss_xml_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 1 | SELECT x IS DOCUMENT FROM pgss_xml_tab + 1 | SELECT x IS NOT DOCUMENT FROM pgss_xml_tab +(6 rows) + +-- +-- XMLTABLE +-- +-- column types, defaults and NOT NULL +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a text PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a varchar(3) PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a varchar(4) PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 1) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 2) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' NOT NULL) xt; + x | t | a +---+---+--- +(0 rows) + +-- NULL is the default +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' NULL) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 1 NOT NULL) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 9 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2) xt + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- FOR ORDINALITY, column names and paths +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a', b int PATH 'b') xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a FOR ORDINALITY, b int PATH 'b') xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a', b FOR ORDINALITY) xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS o FOR ORDINALITY, a int) xt; + x | t | o | a +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int, o FOR ORDINALITY) xt; + x | t | a | o +---+---+---+--- +(0 rows) + +-- only the column names and the paths differ +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS c int PATH 'c', d int PATH 'd') xt; + x | t | c | d +---+---+---+--- +(0 rows) + +-- without PATH, the path is the column name +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int, b int) xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS c int, d int) xt; + x | t | c | d +---+---+---+--- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+--------------------------------------------------------------------- + 1 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a FOR ORDINALITY, b int PATH $2) xt + 1 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2, b FOR ORDINALITY) xt + 2 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2, b int PATH $3) xt + 4 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS o FOR ORDINALITY, a int) xt + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +-- XMLNAMESPACES and PASSING +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://x' AS n), '/n:r' + PASSING x COLUMNS a int PATH 'n:a') xt; + x | t | a +---+---+--- +(0 rows) + +-- only the namespace, its name and the paths differ +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://y' AS m), '/m:r' + PASSING x COLUMNS a int PATH 'm:a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://x' AS n, 'http://y' AS m), '/n:r' + PASSING x COLUMNS a int PATH 'm:a') xt; + x | t | a +---+---+--- +(0 rows) + +-- BY REF and BY VALUE are noise words +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING BY REF x COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING BY VALUE x BY VALUE COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 6 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2) xt + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +DROP TABLE pgss_xml_tab; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + diff --git a/contrib/pg_stat_statements/expected/xml_1.out b/contrib/pg_stat_statements/expected/xml_1.out new file mode 100644 index 0000000000..86152a84c8 --- /dev/null +++ b/contrib/pg_stat_statements/expected/xml_1.out @@ -0,0 +1,445 @@ +-- +-- SQL/XML +-- +SET pg_stat_statements.track_utility = FALSE; +CREATE TABLE pgss_xml_tab (x xml, t text); +-- +-- SQL/XML functions +-- +-- XMLELEMENT, XMLATTRIBUTES, XMLFOREST and XMLPI names +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLELEMENT(NAME foo) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLELEMENT(NAME bar) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLELEMENT(NAME foo, t) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a)) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS b)) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +-- the attribute name defaults to the column name +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t)) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS t)) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a), t) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLFOREST(t AS a) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLFOREST(t AS b) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +-- the element name defaults to the column name +SELECT XMLFOREST(t) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLFOREST(t AS t) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLFOREST(t AS a, x AS b) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLPI(NAME foo) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLPI(NAME bar) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT XMLPI(NAME foo, t) FROM pgss_xml_tab; +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(1 row) + +-- XMLPARSE and XMLSERIALIZE +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLPARSE(DOCUMENT t) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +SELECT XMLPARSE(CONTENT t) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +-- STRIP WHITESPACE is the default +SELECT XMLPARSE(CONTENT t STRIP WHITESPACE) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +SELECT XMLPARSE(CONTENT t PRESERVE WHITESPACE) FROM pgss_xml_tab; + xmlparse +---------- +(0 rows) + +SELECT XMLSERIALIZE(DOCUMENT x AS text) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS text) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +-- NO INDENT is the default +SELECT XMLSERIALIZE(CONTENT x AS text NO INDENT) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS text INDENT) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS varchar(10)) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT XMLSERIALIZE(CONTENT x AS varchar(20)) FROM pgss_xml_tab; + xmlserialize +-------------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+----------------------------------------------------------------- + 4 | SELECT XMLPARSE(DOCUMENT t) FROM pgss_xml_tab + 1 | SELECT XMLSERIALIZE(CONTENT x AS text INDENT) FROM pgss_xml_tab + 2 | SELECT XMLSERIALIZE(CONTENT x AS varchar(10)) FROM pgss_xml_tab + 3 | SELECT XMLSERIALIZE(DOCUMENT x AS text) FROM pgss_xml_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +-- XMLROOT +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLROOT(x, VERSION '1.0') FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.1') FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION NO VALUE) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.0', STANDALONE YES) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.0', STANDALONE NO) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT XMLROOT(x, VERSION '1.0', STANDALONE NO VALUE) FROM pgss_xml_tab; + xmlroot +--------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 6 | SELECT XMLROOT(x, VERSION $1) FROM pgss_xml_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- XMLCONCAT, IS DOCUMENT and XMLEXISTS +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT XMLCONCAT(x, x) FROM pgss_xml_tab; + xmlconcat +----------- +(0 rows) + +SELECT XMLCONCAT(x, x, x) FROM pgss_xml_tab; + xmlconcat +----------- +(0 rows) + +SELECT x IS DOCUMENT FROM pgss_xml_tab; + ?column? +---------- +(0 rows) + +SELECT x IS NOT DOCUMENT FROM pgss_xml_tab; + ?column? +---------- +(0 rows) + +SELECT XMLEXISTS('/r' PASSING x) FROM pgss_xml_tab; + xmlexists +----------- +(0 rows) + +-- BY REF and BY VALUE are noise words +SELECT XMLEXISTS('/r' PASSING BY REF x) FROM pgss_xml_tab; + xmlexists +----------- +(0 rows) + +SELECT XMLEXISTS('/r' PASSING BY VALUE x BY VALUE) FROM pgss_xml_tab; + xmlexists +----------- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 1 | SELECT XMLCONCAT(x, x) FROM pgss_xml_tab + 1 | SELECT XMLCONCAT(x, x, x) FROM pgss_xml_tab + 3 | SELECT XMLEXISTS($1 PASSING x) FROM pgss_xml_tab + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t + 1 | SELECT x IS DOCUMENT FROM pgss_xml_tab + 1 | SELECT x IS NOT DOCUMENT FROM pgss_xml_tab +(6 rows) + +-- +-- XMLTABLE +-- +-- column types, defaults and NOT NULL +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a text PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a varchar(3) PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a varchar(4) PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 1) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 2) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' NOT NULL) xt; + x | t | a +---+---+--- +(0 rows) + +-- NULL is the default +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' NULL) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 1 NOT NULL) xt; + x | t | a +---+---+--- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 9 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2) xt + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +-- FOR ORDINALITY, column names and paths +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a', b int PATH 'b') xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a FOR ORDINALITY, b int PATH 'b') xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a', b FOR ORDINALITY) xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS o FOR ORDINALITY, a int) xt; + x | t | o | a +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int, o FOR ORDINALITY) xt; + x | t | a | o +---+---+---+--- +(0 rows) + +-- only the column names and the paths differ +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS c int PATH 'c', d int PATH 'd') xt; + x | t | c | d +---+---+---+--- +(0 rows) + +-- without PATH, the path is the column name +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int, b int) xt; + x | t | a | b +---+---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS c int, d int) xt; + x | t | c | d +---+---+---+--- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+--------------------------------------------------------------------- + 1 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a FOR ORDINALITY, b int PATH $2) xt + 1 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2, b FOR ORDINALITY) xt + 2 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2, b int PATH $3) xt + 4 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS o FOR ORDINALITY, a int) xt + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(5 rows) + +-- XMLNAMESPACES and PASSING +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://x' AS n), '/n:r' + PASSING x COLUMNS a int PATH 'n:a') xt; + x | t | a +---+---+--- +(0 rows) + +-- only the namespace, its name and the paths differ +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://y' AS m), '/m:r' + PASSING x COLUMNS a int PATH 'm:a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://x' AS n, 'http://y' AS m), '/n:r' + PASSING x COLUMNS a int PATH 'm:a') xt; + x | t | a +---+---+--- +(0 rows) + +-- BY REF and BY VALUE are noise words +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING BY REF x COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING BY VALUE x BY VALUE COLUMNS a int PATH 'a') xt; + x | t | a +---+---+--- +(0 rows) + +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + calls | query +-------+---------------------------------------------------- + 6 | SELECT * FROM pgss_xml_tab, + + | XMLTABLE($1 PASSING x COLUMNS a int PATH $2) xt + 1 | SELECT pg_stat_statements_reset() IS NOT NULL AS t +(2 rows) + +DROP TABLE pgss_xml_tab; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + t +--- + t +(1 row) + diff --git a/contrib/pg_stat_statements/meson.build b/contrib/pg_stat_statements/meson.build index a2f957836a..923f08f670 100644 --- a/contrib/pg_stat_statements/meson.build +++ b/contrib/pg_stat_statements/meson.build @@ -59,6 +59,7 @@ tests += { 'plancache', 'squashing', 'sqljson', + 'xml', 'cleanup', 'oldextversions', ], diff --git a/contrib/pg_stat_statements/sql/dml.sql b/contrib/pg_stat_statements/sql/dml.sql index 9986b0a22d..5d64e238af 100644 --- a/contrib/pg_stat_statements/sql/dml.sql +++ b/contrib/pg_stat_statements/sql/dml.sql @@ -74,6 +74,37 @@ DROP TABLE pgss_dml_tab; SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +-- OVERRIDING +CREATE TEMP TABLE pgss_identity_tab (a int GENERATED BY DEFAULT AS IDENTITY, b int); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +INSERT INTO pgss_identity_tab VALUES (100, 1); +-- with OVERRIDING USER VALUE, a gets the next identity value +INSERT INTO pgss_identity_tab OVERRIDING USER VALUE VALUES (100, 1); +INSERT INTO pgss_identity_tab OVERRIDING SYSTEM VALUE VALUES (100, 1); +MERGE INTO pgss_identity_tab USING (SELECT 1 AS b) s ON false + WHEN NOT MATCHED THEN INSERT VALUES (100, s.b); +MERGE INTO pgss_identity_tab USING (SELECT 1 AS b) s ON false + WHEN NOT MATCHED THEN INSERT OVERRIDING USER VALUE VALUES (100, s.b); +MERGE INTO pgss_identity_tab USING (SELECT 1 AS b) s ON false + WHEN NOT MATCHED THEN INSERT OVERRIDING SYSTEM VALUE VALUES (100, s.b); +SELECT a, b FROM pgss_identity_tab ORDER BY a; +DROP TABLE pgss_identity_tab; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + +-- assignments to fields of a composite column +CREATE TYPE pgss_point AS (x int, y int); +CREATE TEMP TABLE pgss_fieldstore_tab (c pgss_point); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +INSERT INTO pgss_fieldstore_tab (c.x) VALUES (1); +INSERT INTO pgss_fieldstore_tab (c.y) VALUES (2); +INSERT INTO pgss_fieldstore_tab (c.x, c.y) VALUES (3, 4); +UPDATE pgss_fieldstore_tab SET c.x = 5; +UPDATE pgss_fieldstore_tab SET c.y = 6; +UPDATE pgss_fieldstore_tab SET c.x = 7, c.y = 8; +DROP TABLE pgss_fieldstore_tab; +DROP TYPE pgss_point; +SELECT calls, rows, query FROM pg_stat_statements ORDER BY query COLLATE "C"; + -- check that [temp] table relation extensions are tracked as writes CREATE TABLE pgss_extend_tab (a int, b text); CREATE TEMP TABLE pgss_extend_temp_tab (a int, b text); diff --git a/contrib/pg_stat_statements/sql/select.sql b/contrib/pg_stat_statements/sql/select.sql index a10d618c03..b8d2d457d7 100644 --- a/contrib/pg_stat_statements/sql/select.sql +++ b/contrib/pg_stat_statements/sql/select.sql @@ -269,3 +269,96 @@ DROP SCHEMA pgss_schema_1 CASCADE; DROP SCHEMA pgss_schema_2 CASCADE; DROP TABLE tab_search_same, tab_search_diff_1, tab_search_diff_2; SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- ROLLUP, CUBE and GROUPING SETS +CREATE TEMP TABLE pgss_empty_tab (a int, b int); +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY ROLLUP (a, b); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY CUBE (a, b); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY GROUPING SETS (a, b); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY ROLLUP ((a, b)); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY CUBE ((a, b)); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY a, ROLLUP (b); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY a, CUBE (b); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY GROUPING SETS (ROLLUP (a), CUBE (b)); +SELECT a, b, COUNT(*) FROM pgss_empty_tab GROUP BY GROUPING SETS (CUBE (a), ROLLUP (b)); +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- WITH RECURSIVE ... SEARCH and CYCLE +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a SET seq SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH BREADTH FIRST BY a SET seq SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY b SET seq SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a, b SET seq SELECT * FROM t; +-- only the name of the sequence column differs +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a SET ord SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET is_cycle USING path SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE b SET is_cycle USING path SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a, b SET is_cycle USING path SELECT * FROM t; +-- TO true DEFAULT false is the default +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET is_cycle TO true DEFAULT false USING path SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET is_cycle TO 'Y' DEFAULT 'N' USING path SELECT * FROM t; +-- only the names of the mark and path columns differ +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + CYCLE a SET c USING p SELECT * FROM t; +WITH RECURSIVE t AS (SELECT a, b FROM pgss_empty_tab UNION ALL SELECT a + 1, b FROM t) + SEARCH DEPTH FIRST BY a SET seq CYCLE a SET is_cycle USING path SELECT * FROM t; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- column definition lists +SELECT * FROM json_to_record('{"a": 1}') AS t(a int); +-- only the constant differs +SELECT * FROM json_to_record('{"a": 2}') AS t(a int); +SELECT * FROM json_to_record('{"a": 1}') AS t(a text); +SELECT * FROM json_to_record('{"a": 1}') AS t(a varchar(3)); +SELECT * FROM json_to_record('{"a": 1}') AS t(a varchar(4)); +SELECT * FROM json_to_record('{"a": 1}') AS t(a text COLLATE "C"); +-- the column names are the keys to look up +SELECT * FROM json_to_record('{"a": 1}') AS t(b int); +SELECT * FROM json_to_record('{"a": 1}') AS t(a int, b int); +SELECT * FROM ROWS FROM (json_to_record('{"a": 1}') AS (a int), + json_to_record('{"b": 1}') AS (b int)) AS t; +SELECT * FROM ROWS FROM (json_to_record('{"a": 1}') AS (a int), + json_to_record('{"b": 1}') AS (b text)) AS t; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- VARIADIC +SELECT format('%s', VARIADIC ARRAY['a', 'b']); +SELECT format('%s', ARRAY['a', 'b']); +SELECT concat(VARIADIC ARRAY['a', 'b']); +SELECT concat(ARRAY['a', 'b']); +-- VARIADIC is the same as separate arguments, except for VARIADIC "any" +SELECT jsonb_extract_path('{}', a::text, b::text) FROM pgss_empty_tab; +SELECT jsonb_extract_path('{}', VARIADIC ARRAY[a::text, b::text]) + FROM pgss_empty_tab; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; + +-- row constructors and row comparisons +CREATE TYPE pgss_pair1 AS (x int, y int); +CREATE TYPE pgss_pair2 AS (p int, q int); +SELECT (ROW(1, 2)::pgss_pair1).*; +SELECT (ROW(1, 2)::pgss_pair2).*; +SELECT ROW(1, 2); +SELECT ROW(1, 2)::pgss_pair1; +SELECT ROW(s, t) < ROW('b', 'b') FROM (VALUES ('a', 'a')) AS v(s, t); +SELECT ROW(s, t) ~<~ ROW('b', 'b') FROM (VALUES ('a', 'a')) AS v(s, t); +SELECT ROW(s, t) <= ROW('b', 'b') FROM (VALUES ('a', 'a')) AS v(s, t); +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C"; +DROP TYPE pgss_pair1, pgss_pair2; +DROP TABLE pgss_empty_tab; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; diff --git a/contrib/pg_stat_statements/sql/xml.sql b/contrib/pg_stat_statements/sql/xml.sql new file mode 100644 index 0000000000..8eaa665e24 --- /dev/null +++ b/contrib/pg_stat_statements/sql/xml.sql @@ -0,0 +1,144 @@ +-- +-- SQL/XML +-- + +SET pg_stat_statements.track_utility = FALSE; + +CREATE TABLE pgss_xml_tab (x xml, t text); + +-- +-- SQL/XML functions +-- + +-- XMLELEMENT, XMLATTRIBUTES, XMLFOREST and XMLPI names +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT XMLELEMENT(NAME foo) FROM pgss_xml_tab; +SELECT XMLELEMENT(NAME bar) FROM pgss_xml_tab; +SELECT XMLELEMENT(NAME foo, t) FROM pgss_xml_tab; +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a)) FROM pgss_xml_tab; +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS b)) FROM pgss_xml_tab; +-- the attribute name defaults to the column name +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t)) FROM pgss_xml_tab; +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS t)) FROM pgss_xml_tab; +SELECT XMLELEMENT(NAME foo, XMLATTRIBUTES(t AS a), t) FROM pgss_xml_tab; +SELECT XMLFOREST(t AS a) FROM pgss_xml_tab; +SELECT XMLFOREST(t AS b) FROM pgss_xml_tab; +-- the element name defaults to the column name +SELECT XMLFOREST(t) FROM pgss_xml_tab; +SELECT XMLFOREST(t AS t) FROM pgss_xml_tab; +SELECT XMLFOREST(t AS a, x AS b) FROM pgss_xml_tab; +SELECT XMLPI(NAME foo) FROM pgss_xml_tab; +SELECT XMLPI(NAME bar) FROM pgss_xml_tab; +SELECT XMLPI(NAME foo, t) FROM pgss_xml_tab; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + +-- XMLPARSE and XMLSERIALIZE +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT XMLPARSE(DOCUMENT t) FROM pgss_xml_tab; +SELECT XMLPARSE(CONTENT t) FROM pgss_xml_tab; +-- STRIP WHITESPACE is the default +SELECT XMLPARSE(CONTENT t STRIP WHITESPACE) FROM pgss_xml_tab; +SELECT XMLPARSE(CONTENT t PRESERVE WHITESPACE) FROM pgss_xml_tab; +SELECT XMLSERIALIZE(DOCUMENT x AS text) FROM pgss_xml_tab; +SELECT XMLSERIALIZE(CONTENT x AS text) FROM pgss_xml_tab; +-- NO INDENT is the default +SELECT XMLSERIALIZE(CONTENT x AS text NO INDENT) FROM pgss_xml_tab; +SELECT XMLSERIALIZE(CONTENT x AS text INDENT) FROM pgss_xml_tab; +SELECT XMLSERIALIZE(CONTENT x AS varchar(10)) FROM pgss_xml_tab; +SELECT XMLSERIALIZE(CONTENT x AS varchar(20)) FROM pgss_xml_tab; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + +-- XMLROOT +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT XMLROOT(x, VERSION '1.0') FROM pgss_xml_tab; +SELECT XMLROOT(x, VERSION '1.1') FROM pgss_xml_tab; +SELECT XMLROOT(x, VERSION NO VALUE) FROM pgss_xml_tab; +SELECT XMLROOT(x, VERSION '1.0', STANDALONE YES) FROM pgss_xml_tab; +SELECT XMLROOT(x, VERSION '1.0', STANDALONE NO) FROM pgss_xml_tab; +SELECT XMLROOT(x, VERSION '1.0', STANDALONE NO VALUE) FROM pgss_xml_tab; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + +-- XMLCONCAT, IS DOCUMENT and XMLEXISTS +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT XMLCONCAT(x, x) FROM pgss_xml_tab; +SELECT XMLCONCAT(x, x, x) FROM pgss_xml_tab; +SELECT x IS DOCUMENT FROM pgss_xml_tab; +SELECT x IS NOT DOCUMENT FROM pgss_xml_tab; +SELECT XMLEXISTS('/r' PASSING x) FROM pgss_xml_tab; +-- BY REF and BY VALUE are noise words +SELECT XMLEXISTS('/r' PASSING BY REF x) FROM pgss_xml_tab; +SELECT XMLEXISTS('/r' PASSING BY VALUE x BY VALUE) FROM pgss_xml_tab; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + +-- +-- XMLTABLE +-- + +-- column types, defaults and NOT NULL +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a text PATH 'a') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a varchar(3) PATH 'a') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a varchar(4) PATH 'a') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 1) xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 2) xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' NOT NULL) xt; +-- NULL is the default +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' NULL) xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a' DEFAULT 1 NOT NULL) xt; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + +-- FOR ORDINALITY, column names and paths +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a', b int PATH 'b') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a FOR ORDINALITY, b int PATH 'b') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a', b FOR ORDINALITY) xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS o FOR ORDINALITY, a int) xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int, o FOR ORDINALITY) xt; +-- only the column names and the paths differ +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS c int PATH 'c', d int PATH 'd') xt; +-- without PATH, the path is the column name +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int, b int) xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS c int, d int) xt; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + +-- XMLNAMESPACES and PASSING +SELECT pg_stat_statements_reset() IS NOT NULL AS t; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING x COLUMNS a int PATH 'a') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://x' AS n), '/n:r' + PASSING x COLUMNS a int PATH 'n:a') xt; +-- only the namespace, its name and the paths differ +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://y' AS m), '/m:r' + PASSING x COLUMNS a int PATH 'm:a') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE(XMLNAMESPACES('http://x' AS n, 'http://y' AS m), '/n:r' + PASSING x COLUMNS a int PATH 'm:a') xt; +-- BY REF and BY VALUE are noise words +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING BY REF x COLUMNS a int PATH 'a') xt; +SELECT * FROM pgss_xml_tab, + XMLTABLE('/r' PASSING BY VALUE x BY VALUE COLUMNS a int PATH 'a') xt; +SELECT calls, query FROM pg_stat_statements ORDER BY query COLLATE "C", calls; + +DROP TABLE pgss_xml_tab; +SELECT pg_stat_statements_reset() IS NOT NULL AS t; base-commit: 022a80fe6c1d82f7777bd52f9d3e5f9952533109 -- 2.43.0