1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Fix pg_prepared_statements.result_types for DML statements

Amendment to 84ad713cf8: 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.
This commit is contained in:
Peter Eisentraut
2022-07-05 10:26:36 +02:00
parent e3dd7c06e6
commit 6ffff0fd22
4 changed files with 26 additions and 7 deletions

View File

@ -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 form of an array of <type>regtype</type>. The OID corresponding
to an element of this array can be obtained by casting the to an element of this array can be obtained by casting the
<type>regtype</type> value to <type>oid</type>. <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> </para></entry>
</row> </row>

View File

@ -684,15 +684,10 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL) while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
{ {
TupleDesc result_desc; TupleDesc result_desc;
Oid *result_types;
Datum values[8]; Datum values[8];
bool nulls[8]; bool nulls[8];
result_desc = prep_stmt->plansource->resultDesc; 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)); MemSet(nulls, 0, sizeof(nulls));
@ -701,7 +696,20 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
values[2] = TimestampTzGetDatum(prep_stmt->prepare_time); values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
values[3] = build_regtype_array(prep_stmt->plansource->param_types, values[3] = build_regtype_array(prep_stmt->plansource->param_types,
prep_stmt->plansource->num_params); 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[5] = BoolGetDatum(prep_stmt->from_sql);
values[6] = Int64GetDatumFast(prep_stmt->plansource->num_generic_plans); values[6] = Int64GetDatumFast(prep_stmt->plansource->num_generic_plans);
values[7] = Int64GetDatumFast(prep_stmt->plansource->num_custom_plans); values[7] = Int64GetDatumFast(prep_stmt->plansource->num_custom_plans);

View File

@ -159,6 +159,9 @@ PREPARE q6 AS
SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;
PREPARE q7(unknown) AS PREPARE q7(unknown) AS
SELECT * FROM road WHERE thepath = $1; 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 SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements
ORDER BY name; ORDER BY name;
name | statement | parameter_types | result_types 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; | | | SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; | |
q7 | PREPARE q7(unknown) AS +| {path} | {text,path} q7 | PREPARE q7(unknown) AS +| {path} | {text,path}
| SELECT * FROM road WHERE thepath = $1; | | | 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; -- test DEALLOCATE ALL;
DEALLOCATE ALL; DEALLOCATE ALL;

View File

@ -71,6 +71,10 @@ PREPARE q6 AS
PREPARE q7(unknown) AS PREPARE q7(unknown) AS
SELECT * FROM road WHERE thepath = $1; 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 SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements
ORDER BY name; ORDER BY name;