Add result_types column to pg_prepared_statements view
Containing the types of the columns returned by the prepared statement. Prompted by question from IRC user mlvzk. Author: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> Discussion: https://www.postgresql.org/message-id/flat/871qwpo7te.fsf@wibble.ilmari.org
This commit is contained in:
parent
eb64ceac7e
commit
84ad713cf8
|
@ -11502,6 +11502,18 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
|
||||||
</para></entry>
|
</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry role="catalog_table_entry"><para role="column_definition">
|
||||||
|
<structfield>result_types</structfield> <type>regtype[]</type>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The types of the columns returned by the prepared statement in the
|
||||||
|
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>.
|
||||||
|
</para></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry role="catalog_table_entry"><para role="column_definition">
|
<entry role="catalog_table_entry"><para role="column_definition">
|
||||||
<structfield>from_sql</structfield> <type>bool</type>
|
<structfield>from_sql</structfield> <type>bool</type>
|
||||||
|
|
|
@ -683,8 +683,16 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
|
||||||
hash_seq_init(&hash_seq, prepared_queries);
|
hash_seq_init(&hash_seq, prepared_queries);
|
||||||
while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
|
while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
|
||||||
{
|
{
|
||||||
Datum values[7];
|
TupleDesc result_desc;
|
||||||
bool nulls[7];
|
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));
|
MemSet(nulls, 0, sizeof(nulls));
|
||||||
|
|
||||||
|
@ -693,9 +701,10 @@ 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] = BoolGetDatum(prep_stmt->from_sql);
|
values[4] = build_regtype_array(result_types, result_desc->natts);
|
||||||
values[5] = Int64GetDatumFast(prep_stmt->plansource->num_generic_plans);
|
values[5] = BoolGetDatum(prep_stmt->from_sql);
|
||||||
values[6] = Int64GetDatumFast(prep_stmt->plansource->num_custom_plans);
|
values[6] = Int64GetDatumFast(prep_stmt->plansource->num_generic_plans);
|
||||||
|
values[7] = Int64GetDatumFast(prep_stmt->plansource->num_custom_plans);
|
||||||
|
|
||||||
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
|
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
|
||||||
values, nulls);
|
values, nulls);
|
||||||
|
|
|
@ -53,6 +53,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 202205191
|
#define CATALOG_VERSION_NO 202207051
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8025,9 +8025,9 @@
|
||||||
proname => 'pg_prepared_statement', prorows => '1000', proretset => 't',
|
proname => 'pg_prepared_statement', prorows => '1000', proretset => 't',
|
||||||
provolatile => 's', proparallel => 'r', prorettype => 'record',
|
provolatile => 's', proparallel => 'r', prorettype => 'record',
|
||||||
proargtypes => '',
|
proargtypes => '',
|
||||||
proallargtypes => '{text,text,timestamptz,_regtype,bool,int8,int8}',
|
proallargtypes => '{text,text,timestamptz,_regtype,_regtype,bool,int8,int8}',
|
||||||
proargmodes => '{o,o,o,o,o,o,o}',
|
proargmodes => '{o,o,o,o,o,o,o,o}',
|
||||||
proargnames => '{name,statement,prepare_time,parameter_types,from_sql,generic_plans,custom_plans}',
|
proargnames => '{name,statement,prepare_time,parameter_types,result_types,from_sql,generic_plans,custom_plans}',
|
||||||
prosrc => 'pg_prepared_statement' },
|
prosrc => 'pg_prepared_statement' },
|
||||||
{ oid => '2511', descr => 'get the open cursors for this session',
|
{ oid => '2511', descr => 'get the open cursors for this session',
|
||||||
proname => 'pg_cursor', prorows => '1000', proretset => 't',
|
proname => 'pg_cursor', prorows => '1000', proretset => 't',
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
-- Regression tests for prepareable statements. We query the content
|
-- Regression tests for prepareable statements. We query the content
|
||||||
-- of the pg_prepared_statements view as prepared statements are
|
-- of the pg_prepared_statements view as prepared statements are
|
||||||
-- created and removed.
|
-- created and removed.
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
name | statement | parameter_types
|
name | statement | parameter_types | result_types
|
||||||
------+-----------+-----------------
|
------+-----------+-----------------+--------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
PREPARE q1 AS SELECT 1 AS a;
|
PREPARE q1 AS SELECT 1 AS a;
|
||||||
|
@ -13,10 +13,10 @@ EXECUTE q1;
|
||||||
1
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
name | statement | parameter_types
|
name | statement | parameter_types | result_types
|
||||||
------+------------------------------+-----------------
|
------+------------------------------+-----------------+--------------
|
||||||
q1 | PREPARE q1 AS SELECT 1 AS a; | {}
|
q1 | PREPARE q1 AS SELECT 1 AS a; | {} | {integer}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- should fail
|
-- should fail
|
||||||
|
@ -32,26 +32,26 @@ EXECUTE q1;
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
PREPARE q2 AS SELECT 2 AS b;
|
PREPARE q2 AS SELECT 2 AS b;
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
name | statement | parameter_types
|
name | statement | parameter_types | result_types
|
||||||
------+------------------------------+-----------------
|
------+------------------------------+-----------------+--------------
|
||||||
q1 | PREPARE q1 AS SELECT 2; | {}
|
q1 | PREPARE q1 AS SELECT 2; | {} | {integer}
|
||||||
q2 | PREPARE q2 AS SELECT 2 AS b; | {}
|
q2 | PREPARE q2 AS SELECT 2 AS b; | {} | {integer}
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
-- sql92 syntax
|
-- sql92 syntax
|
||||||
DEALLOCATE PREPARE q1;
|
DEALLOCATE PREPARE q1;
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
name | statement | parameter_types
|
name | statement | parameter_types | result_types
|
||||||
------+------------------------------+-----------------
|
------+------------------------------+-----------------+--------------
|
||||||
q2 | PREPARE q2 AS SELECT 2 AS b; | {}
|
q2 | PREPARE q2 AS SELECT 2 AS b; | {} | {integer}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
DEALLOCATE PREPARE q2;
|
DEALLOCATE PREPARE q2;
|
||||||
-- the view should return the empty set again
|
-- the view should return the empty set again
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
name | statement | parameter_types
|
name | statement | parameter_types | result_types
|
||||||
------+-----------+-----------------
|
------+-----------+-----------------+--------------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- parameterized queries
|
-- parameterized queries
|
||||||
|
@ -159,24 +159,24 @@ 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;
|
||||||
SELECT name, statement, parameter_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
|
name | statement | parameter_types | result_types
|
||||||
------+------------------------------------------------------------------+----------------------------------------------------
|
------+------------------------------------------------------------------+----------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------
|
||||||
q2 | PREPARE q2(text) AS +| {text}
|
q2 | PREPARE q2(text) AS +| {text} | {name,boolean,boolean}
|
||||||
| SELECT datname, datistemplate, datallowconn +|
|
| SELECT datname, datistemplate, datallowconn +| |
|
||||||
| FROM pg_database WHERE datname = $1; |
|
| FROM pg_database WHERE datname = $1; | |
|
||||||
q3 | PREPARE q3(text, int, float, boolean, smallint) AS +| {text,integer,"double precision",boolean,smallint}
|
q3 | PREPARE q3(text, int, float, boolean, smallint) AS +| {text,integer,"double precision",boolean,smallint} | {integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,name,name,name}
|
||||||
| SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR+|
|
| SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR+| |
|
||||||
| ten = $3::bigint OR true = $4 OR odd = $5::int) +|
|
| ten = $3::bigint OR true = $4 OR odd = $5::int) +| |
|
||||||
| ORDER BY unique1; |
|
| ORDER BY unique1; | |
|
||||||
q5 | PREPARE q5(int, text) AS +| {integer,text}
|
q5 | PREPARE q5(int, text) AS +| {integer,text} | {integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,name,name,name}
|
||||||
| SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 +|
|
| SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 +| |
|
||||||
| ORDER BY unique1; |
|
| ORDER BY unique1; | |
|
||||||
q6 | PREPARE q6 AS +| {integer,name}
|
q6 | PREPARE q6 AS +| {integer,name} | {integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,integer,name,name,name}
|
||||||
| SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; |
|
| SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2; | |
|
||||||
q7 | PREPARE q7(unknown) AS +| {path}
|
q7 | PREPARE q7(unknown) AS +| {path} | {text,path}
|
||||||
| SELECT * FROM road WHERE thepath = $1; |
|
| SELECT * FROM road WHERE thepath = $1; | |
|
||||||
(5 rows)
|
(5 rows)
|
||||||
|
|
||||||
-- test DEALLOCATE ALL;
|
-- test DEALLOCATE ALL;
|
||||||
|
|
|
@ -1423,10 +1423,11 @@ pg_prepared_statements| SELECT p.name,
|
||||||
p.statement,
|
p.statement,
|
||||||
p.prepare_time,
|
p.prepare_time,
|
||||||
p.parameter_types,
|
p.parameter_types,
|
||||||
|
p.result_types,
|
||||||
p.from_sql,
|
p.from_sql,
|
||||||
p.generic_plans,
|
p.generic_plans,
|
||||||
p.custom_plans
|
p.custom_plans
|
||||||
FROM pg_prepared_statement() p(name, statement, prepare_time, parameter_types, from_sql, generic_plans, custom_plans);
|
FROM pg_prepared_statement() p(name, statement, prepare_time, parameter_types, result_types, from_sql, generic_plans, custom_plans);
|
||||||
pg_prepared_xacts| SELECT p.transaction,
|
pg_prepared_xacts| SELECT p.transaction,
|
||||||
p.gid,
|
p.gid,
|
||||||
p.prepared,
|
p.prepared,
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
-- of the pg_prepared_statements view as prepared statements are
|
-- of the pg_prepared_statements view as prepared statements are
|
||||||
-- created and removed.
|
-- created and removed.
|
||||||
|
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
|
|
||||||
PREPARE q1 AS SELECT 1 AS a;
|
PREPARE q1 AS SELECT 1 AS a;
|
||||||
EXECUTE q1;
|
EXECUTE q1;
|
||||||
|
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
|
|
||||||
-- should fail
|
-- should fail
|
||||||
PREPARE q1 AS SELECT 2;
|
PREPARE q1 AS SELECT 2;
|
||||||
|
@ -18,16 +18,16 @@ PREPARE q1 AS SELECT 2;
|
||||||
EXECUTE q1;
|
EXECUTE q1;
|
||||||
|
|
||||||
PREPARE q2 AS SELECT 2 AS b;
|
PREPARE q2 AS SELECT 2 AS b;
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
|
|
||||||
-- sql92 syntax
|
-- sql92 syntax
|
||||||
DEALLOCATE PREPARE q1;
|
DEALLOCATE PREPARE q1;
|
||||||
|
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
|
|
||||||
DEALLOCATE PREPARE q2;
|
DEALLOCATE PREPARE q2;
|
||||||
-- the view should return the empty set again
|
-- the view should return the empty set again
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements;
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements;
|
||||||
|
|
||||||
-- parameterized queries
|
-- parameterized queries
|
||||||
PREPARE q2(text) AS
|
PREPARE q2(text) AS
|
||||||
|
@ -71,7 +71,7 @@ PREPARE q6 AS
|
||||||
PREPARE q7(unknown) AS
|
PREPARE q7(unknown) AS
|
||||||
SELECT * FROM road WHERE thepath = $1;
|
SELECT * FROM road WHERE thepath = $1;
|
||||||
|
|
||||||
SELECT name, statement, parameter_types FROM pg_prepared_statements
|
SELECT name, statement, parameter_types, result_types FROM pg_prepared_statements
|
||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
-- test DEALLOCATE ALL;
|
-- test DEALLOCATE ALL;
|
||||||
|
|
Loading…
Reference in New Issue