summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2022-07-05 08:26:36 +0000
committerPeter Eisentraut2022-07-05 08:26:36 +0000
commit6ffff0fd225432fe2ae4bd5abb7ff6113e255418 (patch)
treef91bd8fc1216b34cace2ac81a5aeab6ec3fb8cb8
parente3dd7c06e62774628e102c3cd47ee46e85519de7 (diff)
Fix pg_prepared_statements.result_types for DML statements
Amendment to 84ad713cf85aeffee5dd39f62d49a1b9e34632da: Not all prepared statements have a result descriptor. As currently coded, this would crash when reading pg_prepared_statements. Make those cases return null for result_types instead. Also add a test case for it.
-rw-r--r--doc/src/sgml/catalogs.sgml2
-rw-r--r--src/backend/commands/prepare.c20
-rw-r--r--src/test/regress/expected/prepare.out7
-rw-r--r--src/test/regress/sql/prepare.sql4
4 files changed, 26 insertions, 7 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index ef7ae7e8fd..4f3f375a84 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -11511,6 +11511,8 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
form of an array of <type>regtype</type>. The OID corresponding
to an element of this array can be obtained by casting the
<type>regtype</type> value to <type>oid</type>.
+ If the prepared statement does not provide a result (e.g., a DML
+ statement), then this field will be null.
</para></entry>
</row>
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index d1deb97fff..2333aae467 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -684,15 +684,10 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
{
TupleDesc result_desc;
- Oid *result_types;
Datum values[8];
bool nulls[8];
result_desc = prep_stmt->plansource->resultDesc;
- result_types = (Oid *) palloc(result_desc->natts * sizeof(Oid));
-
- for (int i = 0; i < result_desc->natts; i++)
- result_types[i] = result_desc->attrs[i].atttypid;
MemSet(nulls, 0, sizeof(nulls));
@@ -701,7 +696,20 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
values[3] = build_regtype_array(prep_stmt->plansource->param_types,
prep_stmt->plansource->num_params);
- values[4] = build_regtype_array(result_types, result_desc->natts);
+ if (result_desc)
+ {
+ Oid *result_types;
+
+ result_types = (Oid *) palloc(result_desc->natts * sizeof(Oid));
+ for (int i = 0; i < result_desc->natts; i++)
+ result_types[i] = result_desc->attrs[i].atttypid;
+ values[4] = build_regtype_array(result_types, result_desc->natts);
+ }
+ else
+ {
+ /* no result descriptor (for example, DML statement) */
+ nulls[4] = true;
+ }
values[5] = BoolGetDatum(prep_stmt->from_sql);
values[6] = Int64GetDatumFast(prep_stmt->plansource->num_generic_plans);
values[7] = Int64GetDatumFast(prep_stmt->plansource->num_custom_plans);
diff --git a/src/test/regress/expected/prepare.out b/src/test/regress/expected/prepare.out
index faf07f620b..5815e17b39 100644
--- a/src/test/regress/expected/prepare.out
+++ b/src/test/regress/expected/prepare.out
@@ -159,6 +159,9 @@ PREPARE q6 AS
SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;
PREPARE q7(unknown) AS
SELECT * FROM road WHERE thepath = $1;
+-- DML statements
+PREPARE q8 AS
+ UPDATE tenk1 SET stringu1 = $2 WHERE unique1 = $1;
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements
ORDER BY name;
name | statement | parameter_types | result_types
@@ -177,7 +180,9 @@ SELECT name, statement, parameter_types, result_types FROM pg_prepared_statement
| SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; | |
q7 | PREPARE q7(unknown) AS +| {path} | {text,path}
| SELECT * FROM road WHERE thepath = $1; | |
-(5 rows)
+ q8 | PREPARE q8 AS +| {integer,name} |
+ | UPDATE tenk1 SET stringu1 = $2 WHERE unique1 = $1; | |
+(6 rows)
-- test DEALLOCATE ALL;
DEALLOCATE ALL;
diff --git a/src/test/regress/sql/prepare.sql b/src/test/regress/sql/prepare.sql
index 55eef91d2a..c6098dc95c 100644
--- a/src/test/regress/sql/prepare.sql
+++ b/src/test/regress/sql/prepare.sql
@@ -71,6 +71,10 @@ PREPARE q6 AS
PREPARE q7(unknown) AS
SELECT * FROM road WHERE thepath = $1;
+-- DML statements
+PREPARE q8 AS
+ UPDATE tenk1 SET stringu1 = $2 WHERE unique1 = $1;
+
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements
ORDER BY name;