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:
@ -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>
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user