PostgreSQL Source Code git master
Loading...
Searching...
No Matches
prepare.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/createas.h"
#include "commands/explain.h"
#include "commands/explain_format.h"
#include "commands/explain_state.h"
#include "commands/prepare.h"
#include "funcapi.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_type.h"
#include "tcop/pquery.h"
#include "tcop/utility.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
#include "utils/tuplestore.h"
Include dependency graph for prepare.c:

Go to the source code of this file.

Functions

static void InitQueryHashTable (void)
 
static ParamListInfo EvaluateParams (ParseState *pstate, PreparedStatement *pstmt, List *params, EState *estate)
 
static Datum build_regtype_array (Oid *param_types, int num_params)
 
void PrepareQuery (ParseState *pstate, PrepareStmt *stmt, int stmt_location, int stmt_len)
 
void ExecuteQuery (ParseState *pstate, ExecuteStmt *stmt, IntoClause *intoClause, ParamListInfo params, DestReceiver *dest, QueryCompletion *qc)
 
void StorePreparedStatement (const char *stmt_name, CachedPlanSource *plansource, bool from_sql)
 
PreparedStatementFetchPreparedStatement (const char *stmt_name, bool throwError)
 
TupleDesc FetchPreparedStatementResultDesc (PreparedStatement *stmt)
 
ListFetchPreparedStatementTargetList (PreparedStatement *stmt)
 
void DeallocateQuery (DeallocateStmt *stmt)
 
void DropPreparedStatement (const char *stmt_name, bool showError)
 
void DropAllPreparedStatements (void)
 
void ExplainExecuteQuery (ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
 
Datum pg_prepared_statement (PG_FUNCTION_ARGS)
 

Variables

static HTABprepared_queries = NULL
 

Function Documentation

◆ build_regtype_array()

static Datum build_regtype_array ( Oid param_types,
int  num_params 
)
static

Definition at line 749 of file prepare.c.

750{
751 Datum *tmp_ary;
752 ArrayType *result;
753 int i;
754
755 tmp_ary = palloc_array(Datum, num_params);
756
757 for (i = 0; i < num_params; i++)
758 tmp_ary[i] = ObjectIdGetDatum(param_types[i]);
759
760 result = construct_array_builtin(tmp_ary, num_params, REGTYPEOID);
761 return PointerGetDatum(result);
762}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
#define palloc_array(type, count)
Definition fe_memutils.h:76
int i
Definition isn.c:77
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static int fb(int x)

References construct_array_builtin(), fb(), i, ObjectIdGetDatum(), palloc_array, and PointerGetDatum().

Referenced by pg_prepared_statement().

◆ DeallocateQuery()

void DeallocateQuery ( DeallocateStmt stmt)

Definition at line 507 of file prepare.c.

508{
509 if (stmt->name)
510 DropPreparedStatement(stmt->name, true);
511 else
513}
void DropPreparedStatement(const char *stmt_name, bool showError)
Definition prepare.c:521
void DropAllPreparedStatements(void)
Definition prepare.c:542
#define stmt

References DropAllPreparedStatements(), DropPreparedStatement(), and stmt.

Referenced by standard_ProcessUtility().

◆ DropAllPreparedStatements()

void DropAllPreparedStatements ( void  )

Definition at line 542 of file prepare.c.

543{
545 PreparedStatement *entry;
546
547 /* nothing cached */
548 if (!prepared_queries)
549 return;
550
551 /* walk over cache */
553 while ((entry = hash_seq_search(&seq)) != NULL)
554 {
555 /* Release the plancache entry */
557
558 /* Now we can remove the hash table entry */
560 }
561}
static HTAB * prepared_queries
Definition prepare.c:49
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
@ HASH_REMOVE
Definition hsearch.h:115
void DropCachedPlan(CachedPlanSource *plansource)
Definition plancache.c:591
char stmt_name[NAMEDATALEN]
Definition prepare.h:31
CachedPlanSource * plansource
Definition prepare.h:32

References DropCachedPlan(), fb(), HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), PreparedStatement::plansource, prepared_queries, and PreparedStatement::stmt_name.

Referenced by DeallocateQuery(), and DiscardAll().

◆ DropPreparedStatement()

void DropPreparedStatement ( const char stmt_name,
bool  showError 
)

Definition at line 521 of file prepare.c.

522{
523 PreparedStatement *entry;
524
525 /* Find the query's hash table entry; raise error if wanted */
526 entry = FetchPreparedStatement(stmt_name, showError);
527
528 if (entry)
529 {
530 /* Release the plancache entry */
532
533 /* Now we can remove the hash table entry */
535 }
536}
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition prepare.c:436

References DropCachedPlan(), fb(), FetchPreparedStatement(), HASH_REMOVE, hash_search(), PreparedStatement::plansource, prepared_queries, and PreparedStatement::stmt_name.

Referenced by DeallocateQuery(), and PostgresMain().

◆ EvaluateParams()

static ParamListInfo EvaluateParams ( ParseState pstate,
PreparedStatement pstmt,
List params,
EState estate 
)
static

Definition at line 283 of file prepare.c.

285{
286 Oid *param_types = pstmt->plansource->param_types;
287 int num_params = pstmt->plansource->num_params;
288 int nparams = list_length(params);
289 ParamListInfo paramLI;
290 List *exprstates;
291 ListCell *l;
292 int i;
293
294 if (nparams != num_params)
297 errmsg("wrong number of parameters for prepared statement \"%s\"",
298 pstmt->stmt_name),
299 errdetail("Expected %d parameters but got %d.",
300 num_params, nparams)));
301
302 /* Quick exit if no parameters */
303 if (num_params == 0)
304 return NULL;
305
306 /*
307 * We have to run parse analysis for the expressions. Since the parser is
308 * not cool about scribbling on its input, copy first.
309 */
310 params = copyObject(params);
311
312 i = 0;
313 foreach(l, params)
314 {
315 Node *expr = lfirst(l);
316 Oid expected_type_id = param_types[i];
318
319 expr = transformExpr(pstate, expr, EXPR_KIND_EXECUTE_PARAMETER);
320
321 given_type_id = exprType(expr);
322
323 expr = coerce_to_target_type(pstate, expr, given_type_id,
327 -1);
328
329 if (expr == NULL)
332 errmsg("parameter $%d of type %s cannot be coerced to the expected type %s",
333 i + 1,
336 errhint("You will need to rewrite or cast the expression."),
338
339 /* Take care of collations in the finished expression. */
340 assign_expr_collations(pstate, expr);
341
342 lfirst(l) = expr;
343 i++;
344 }
345
346 /* Prepare the expressions for execution */
347 exprstates = ExecPrepareExprList(params, estate);
348
349 paramLI = makeParamList(num_params);
350
351 i = 0;
352 foreach(l, exprstates)
353 {
354 ExprState *n = (ExprState *) lfirst(l);
355 ParamExternData *prm = &paramLI->params[i];
356
357 prm->ptype = param_types[i];
358 prm->pflags = PARAM_FLAG_CONST;
361 &prm->isnull);
362
363 i++;
364 }
365
366 return paramLI;
367}
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition execExpr.c:872
#define GetPerTupleExprContext(estate)
Definition executor.h:660
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition executor.h:439
char * format_type_be(Oid type_oid)
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int exprLocation(const Node *expr)
Definition nodeFuncs.c:1392
#define copyObject(obj)
Definition nodes.h:232
static char * errmsg
ParamListInfo makeParamList(int numParams)
Definition params.c:44
#define PARAM_FLAG_CONST
Definition params.h:87
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition parse_expr.c:121
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
@ EXPR_KIND_EXECUTE_PARAMETER
Definition parse_node.h:76
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
unsigned int Oid
@ COERCE_IMPLICIT_CAST
Definition primnodes.h:769
@ COERCION_ASSIGNMENT
Definition primnodes.h:748
Definition pg_list.h:54
Definition nodes.h:135
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition params.h:124

References assign_expr_collations(), COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, copyObject, ereport, errcode(), errdetail(), errhint(), errmsg, ERROR, ExecEvalExprSwitchContext(), ExecPrepareExprList(), EXPR_KIND_EXECUTE_PARAMETER, exprLocation(), exprType(), fb(), format_type_be(), GetPerTupleExprContext, i, lfirst, list_length(), makeParamList(), CachedPlanSource::num_params, PARAM_FLAG_CONST, CachedPlanSource::param_types, ParamListInfoData::params, parser_errposition(), PreparedStatement::plansource, ParamExternData::ptype, PreparedStatement::stmt_name, and transformExpr().

Referenced by ExecuteQuery(), and ExplainExecuteQuery().

◆ ExecuteQuery()

void ExecuteQuery ( ParseState pstate,
ExecuteStmt stmt,
IntoClause intoClause,
ParamListInfo  params,
DestReceiver dest,
QueryCompletion qc 
)

Definition at line 152 of file prepare.c.

156{
157 PreparedStatement *entry;
158 CachedPlan *cplan;
160 ParamListInfo paramLI = NULL;
161 EState *estate = NULL;
162 Portal portal;
163 char *query_string;
164 int eflags;
165 long count;
166
167 /* Look it up in the hash table */
168 entry = FetchPreparedStatement(stmt->name, true);
169
170 /* Shouldn't find a non-fixed-result cached plan */
171 if (!entry->plansource->fixed_result)
172 elog(ERROR, "EXECUTE does not support variable-result cached plans");
173
174 /* Evaluate parameters, if any */
175 if (entry->plansource->num_params > 0)
176 {
177 /*
178 * Need an EState to evaluate parameters; must not delete it till end
179 * of query, in case parameters are pass-by-reference. Note that the
180 * passed-in "params" could possibly be referenced in the parameter
181 * expressions.
182 */
183 estate = CreateExecutorState();
184 estate->es_param_list_info = params;
185 paramLI = EvaluateParams(pstate, entry, stmt->params, estate);
186 }
187
188 /* Create a new portal to run the query in */
189 portal = CreateNewPortal();
190 /* Don't display the portal in pg_cursors, it is for internal use only */
191 portal->visible = false;
192
193 /* Copy the plan's saved query string into the portal's memory */
194 query_string = MemoryContextStrdup(portal->portalContext,
195 entry->plansource->query_string);
196
197 /* Replan if needed, and increment plan refcount for portal */
198 cplan = GetCachedPlan(entry->plansource, paramLI, NULL, NULL);
199 plan_list = cplan->stmt_list;
200
201 /*
202 * DO NOT add any logic that could possibly throw an error between
203 * GetCachedPlan and PortalDefineQuery, or you'll leak the plan refcount.
204 */
205 PortalDefineQuery(portal,
206 NULL,
207 query_string,
208 entry->plansource->commandTag,
209 plan_list,
210 cplan);
211
212 /*
213 * For CREATE TABLE ... AS EXECUTE, we must verify that the prepared
214 * statement is one that produces tuples. Currently we insist that it be
215 * a plain old SELECT. In future we might consider supporting other
216 * things such as INSERT ... RETURNING, but there are a couple of issues
217 * to be settled first, notably how WITH NO DATA should be handled in such
218 * a case (do we really want to suppress execution?) and how to pass down
219 * the OID-determining eflags (PortalStart won't handle them in such a
220 * case, and for that matter it's not clear the executor will either).
221 *
222 * For CREATE TABLE ... AS EXECUTE, we also have to ensure that the proper
223 * eflags and fetch count are passed to PortalStart/PortalRun.
224 */
225 if (intoClause)
226 {
227 PlannedStmt *pstmt;
228
229 if (list_length(plan_list) != 1)
232 errmsg("prepared statement is not a SELECT")));
234 if (pstmt->commandType != CMD_SELECT)
237 errmsg("prepared statement is not a SELECT")));
238
239 /* Set appropriate eflags */
240 eflags = GetIntoRelEFlags(intoClause);
241
242 /* And tell PortalRun whether to run to completion or not */
243 if (intoClause->skipData)
244 count = 0;
245 else
246 count = FETCH_ALL;
247 }
248 else
249 {
250 /* Plain old EXECUTE */
251 eflags = 0;
252 count = FETCH_ALL;
253 }
254
255 /*
256 * Run the portal as appropriate.
257 */
258 PortalStart(portal, paramLI, eflags, GetActiveSnapshot());
259
260 (void) PortalRun(portal, count, false, dest, dest, qc);
261
262 PortalDrop(portal, false);
263
264 if (estate)
265 FreeExecutorState(estate);
266
267 /* No need to pfree other memory, MemoryContext will be reset */
268}
static ParamListInfo EvaluateParams(ParseState *pstate, PreparedStatement *pstmt, List *params, EState *estate)
Definition prepare.c:283
int GetIntoRelEFlags(IntoClause *intoClause)
Definition createas.c:375
#define elog(elevel,...)
Definition elog.h:226
void FreeExecutorState(EState *estate)
Definition execUtils.c:197
EState * CreateExecutorState(void)
Definition execUtils.c:90
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1768
@ CMD_SELECT
Definition nodes.h:275
#define FETCH_ALL
#define linitial_node(type, l)
Definition pg_list.h:181
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition plancache.c:1297
Portal CreateNewPortal(void)
Definition portalmem.c:237
void PortalDrop(Portal portal, bool isTopCommit)
Definition portalmem.c:469
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan)
Definition portalmem.c:284
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition pquery.c:429
bool PortalRun(Portal portal, long count, bool isTopLevel, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
Definition pquery.c:680
Snapshot GetActiveSnapshot(void)
Definition snapmgr.c:800
CommandTag commandTag
Definition plancache.h:111
const char * query_string
Definition plancache.h:110
List * stmt_list
Definition plancache.h:162
ParamListInfo es_param_list_info
Definition execnodes.h:716
bool skipData
Definition primnodes.h:172
CmdType commandType
Definition plannodes.h:66
MemoryContext portalContext
Definition portal.h:120
bool visible
Definition portal.h:204

References CMD_SELECT, CachedPlanSource::commandTag, PlannedStmt::commandType, CreateExecutorState(), CreateNewPortal(), elog, ereport, errcode(), errmsg, ERROR, EState::es_param_list_info, EvaluateParams(), fb(), FETCH_ALL, FetchPreparedStatement(), CachedPlanSource::fixed_result, FreeExecutorState(), GetActiveSnapshot(), GetCachedPlan(), GetIntoRelEFlags(), linitial_node, list_length(), MemoryContextStrdup(), CachedPlanSource::num_params, PreparedStatement::plansource, PortalData::portalContext, PortalDefineQuery(), PortalDrop(), PortalRun(), PortalStart(), CachedPlanSource::query_string, IntoClause::skipData, stmt, CachedPlan::stmt_list, and PortalData::visible.

Referenced by ExecCreateTableAs(), and standard_ProcessUtility().

◆ ExplainExecuteQuery()

void ExplainExecuteQuery ( ExecuteStmt execstmt,
IntoClause into,
ExplainState es,
ParseState pstate,
ParamListInfo  params 
)

Definition at line 573 of file prepare.c.

575{
576 PreparedStatement *entry;
577 const char *query_string;
578 CachedPlan *cplan;
580 ListCell *p;
581 ParamListInfo paramLI = NULL;
582 EState *estate = NULL;
585 BufferUsage bufusage_start,
586 bufusage;
590
591 if (es->memory)
592 {
593 /* See ExplainOneQuery about this */
596 "explain analyze planner context",
599 }
600
601 if (es->buffers)
602 bufusage_start = pgBufferUsage;
604
605 /* Look it up in the hash table */
606 entry = FetchPreparedStatement(execstmt->name, true);
607
608 /* Shouldn't find a non-fixed-result cached plan */
609 if (!entry->plansource->fixed_result)
610 elog(ERROR, "EXPLAIN EXECUTE does not support variable-result cached plans");
611
612 query_string = entry->plansource->query_string;
613
614 /* Evaluate parameters, if any */
615 if (entry->plansource->num_params)
616 {
618
620 pstate_params->p_sourcetext = pstate->p_sourcetext;
621
622 /*
623 * Need an EState to evaluate parameters; must not delete it till end
624 * of query, in case parameters are pass-by-reference. Note that the
625 * passed-in "params" could possibly be referenced in the parameter
626 * expressions.
627 */
628 estate = CreateExecutorState();
629 estate->es_param_list_info = params;
630
631 paramLI = EvaluateParams(pstate_params, entry, execstmt->params, estate);
632 }
633
634 /* Replan if needed, and acquire a transient refcount */
635 cplan = GetCachedPlan(entry->plansource, paramLI,
637
640
641 if (es->memory)
642 {
645 }
646
647 /* calc differences of buffer counters. */
648 if (es->buffers)
649 {
650 memset(&bufusage, 0, sizeof(BufferUsage));
651 BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
652 }
653
654 plan_list = cplan->stmt_list;
655
656 /* Explain each query */
657 foreach(p, plan_list)
658 {
660
661 if (pstmt->commandType != CMD_UTILITY)
662 ExplainOnePlan(pstmt, into, es, query_string, paramLI, pstate->p_queryEnv,
663 &planduration, (es->buffers ? &bufusage : NULL),
664 es->memory ? &mem_counters : NULL);
665 else
666 ExplainOneUtility(pstmt->utilityStmt, into, es, pstate, paramLI);
667
668 /* No need for CommandCounterIncrement, as ExplainOnePlan did it */
669
670 /* Separate plans with an appropriate separator */
671 if (lnext(plan_list, p) != NULL)
673 }
674
675 if (estate)
676 FreeExecutorState(estate);
677
679}
#define Assert(condition)
Definition c.h:945
void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage, const MemoryContextCounters *mem_counters)
Definition explain.c:497
void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
Definition explain.c:393
void ExplainSeparatePlans(ExplainState *es)
#define INSTR_TIME_SET_CURRENT(t)
Definition instr_time.h:122
#define INSTR_TIME_SUBTRACT(x, y)
Definition instr_time.h:177
BufferUsage pgBufferUsage
Definition instrument.c:20
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
Definition instrument.c:249
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
Definition mcxt.c:835
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define IsA(nodeptr, _type_)
Definition nodes.h:164
@ CMD_UTILITY
Definition nodes.h:280
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
ParseState * make_parsestate(ParseState *parentParseState)
Definition parse_node.c:39
#define lfirst_node(type, lc)
Definition pg_list.h:176
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:343
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition plancache.c:1428
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
QueryEnvironment * p_queryEnv
Definition parse_node.h:237
const char * p_sourcetext
Definition parse_node.h:210
Node * utilityStmt
Definition plannodes.h:151

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, ExplainState::buffers, BufferUsageAccumDiff(), CMD_UTILITY, PlannedStmt::commandType, CreateExecutorState(), CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, EState::es_param_list_info, EvaluateParams(), ExplainOnePlan(), ExplainOneUtility(), ExplainSeparatePlans(), fb(), FetchPreparedStatement(), CachedPlanSource::fixed_result, FreeExecutorState(), GetCachedPlan(), INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, IsA, lfirst_node, lnext(), make_parsestate(), ExplainState::memory, MemoryContextMemConsumed(), MemoryContextSwitchTo(), CachedPlanSource::num_params, ParseState::p_queryEnv, ParseState::p_sourcetext, pgBufferUsage, PreparedStatement::plansource, CachedPlanSource::query_string, ReleaseCachedPlan(), CachedPlan::stmt_list, and PlannedStmt::utilityStmt.

Referenced by ExplainOneUtility().

◆ FetchPreparedStatement()

PreparedStatement * FetchPreparedStatement ( const char stmt_name,
bool  throwError 
)

Definition at line 436 of file prepare.c.

437{
438 PreparedStatement *entry;
439
440 /*
441 * If the hash table hasn't been initialized, it can't be storing
442 * anything, therefore it couldn't possibly store our plan.
443 */
446 stmt_name,
447 HASH_FIND,
448 NULL);
449 else
450 entry = NULL;
451
452 if (!entry && throwError)
455 errmsg("prepared statement \"%s\" does not exist",
456 stmt_name)));
457
458 return entry;
459}
@ HASH_FIND
Definition hsearch.h:113

References ereport, errcode(), errmsg, ERROR, fb(), HASH_FIND, hash_search(), and prepared_queries.

Referenced by DropPreparedStatement(), errdetail_execute(), exec_bind_message(), exec_describe_statement_message(), ExecuteQuery(), ExplainExecuteQuery(), FetchStatementTargetList(), GetCommandLogLevel(), UtilityReturnsTuples(), and UtilityTupleDescriptor().

◆ FetchPreparedStatementResultDesc()

TupleDesc FetchPreparedStatementResultDesc ( PreparedStatement stmt)

Definition at line 468 of file prepare.c.

469{
470 /*
471 * Since we don't allow prepared statements' result tupdescs to change,
472 * there's no need to worry about revalidating the cached plan here.
473 */
474 Assert(stmt->plansource->fixed_result);
475 if (stmt->plansource->resultDesc)
476 return CreateTupleDescCopy(stmt->plansource->resultDesc);
477 else
478 return NULL;
479}
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition tupdesc.c:242

References Assert, CreateTupleDescCopy(), fb(), and stmt.

Referenced by UtilityTupleDescriptor().

◆ FetchPreparedStatementTargetList()

List * FetchPreparedStatementTargetList ( PreparedStatement stmt)

Definition at line 491 of file prepare.c.

492{
493 List *tlist;
494
495 /* Get the plan's primary targetlist */
496 tlist = CachedPlanGetTargetList(stmt->plansource, NULL);
497
498 /* Copy into caller's context in case plan gets invalidated */
499 return copyObject(tlist);
500}
List * CachedPlanGetTargetList(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition plancache.c:1779

References CachedPlanGetTargetList(), copyObject, fb(), and stmt.

Referenced by FetchStatementTargetList().

◆ InitQueryHashTable()

static void InitQueryHashTable ( void  )
static

Definition at line 374 of file prepare.c.

375{
377
379 hash_ctl.entrysize = sizeof(PreparedStatement);
380
381 prepared_queries = hash_create("Prepared Queries",
382 32,
383 &hash_ctl,
385}
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:358
#define HASH_STRINGS
Definition hsearch.h:96
#define HASH_ELEM
Definition hsearch.h:95
#define NAMEDATALEN
Size keysize
Definition hsearch.h:75

References fb(), hash_create(), HASH_ELEM, HASH_STRINGS, HASHCTL::keysize, NAMEDATALEN, and prepared_queries.

Referenced by StorePreparedStatement().

◆ pg_prepared_statement()

Datum pg_prepared_statement ( PG_FUNCTION_ARGS  )

Definition at line 687 of file prepare.c.

688{
689 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
690
691 /*
692 * We put all the tuples into a tuplestore in one scan of the hashtable.
693 * This avoids any issue of the hashtable possibly changing between calls.
694 */
695 InitMaterializedSRF(fcinfo, 0);
696
697 /* hash table might be uninitialized */
699 {
702
704 while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
705 {
707 Datum values[8];
708 bool nulls[8] = {0};
709
710 result_desc = prep_stmt->plansource->resultDesc;
711
712 values[0] = CStringGetTextDatum(prep_stmt->stmt_name);
713 values[1] = CStringGetTextDatum(prep_stmt->plansource->query_string);
714 values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
715 values[3] = build_regtype_array(prep_stmt->plansource->param_types,
716 prep_stmt->plansource->num_params);
717 if (result_desc)
718 {
720
722 for (int i = 0; i < result_desc->natts; i++)
725 }
726 else
727 {
728 /* no result descriptor (for example, DML statement) */
729 nulls[4] = true;
730 }
731 values[5] = BoolGetDatum(prep_stmt->from_sql);
732 values[6] = Int64GetDatumFast(prep_stmt->plansource->num_generic_plans);
733 values[7] = Int64GetDatumFast(prep_stmt->plansource->num_custom_plans);
734
735 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
736 values, nulls);
737 }
738 }
739
740 return (Datum) 0;
741}
static Datum build_regtype_array(Oid *param_types, int num_params)
Definition prepare.c:749
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition funcapi.c:76
#define Int64GetDatumFast(X)
Definition postgres.h:525
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
static Datum TimestampTzGetDatum(TimestampTz X)
Definition timestamp.h:52

References BoolGetDatum(), build_regtype_array(), CStringGetTextDatum, fb(), hash_seq_init(), hash_seq_search(), i, InitMaterializedSRF(), Int64GetDatumFast, palloc_array, prepared_queries, TimestampTzGetDatum(), TupleDescAttr(), tuplestore_putvalues(), and values.

◆ PrepareQuery()

void PrepareQuery ( ParseState pstate,
PrepareStmt stmt,
int  stmt_location,
int  stmt_len 
)

Definition at line 61 of file prepare.c.

63{
65 CachedPlanSource *plansource;
66 Oid *argtypes = NULL;
67 int nargs;
68 List *query_list;
69
70 /*
71 * Disallow empty-string statement name (conflicts with protocol-level
72 * unnamed statement).
73 */
74 if (!stmt->name || stmt->name[0] == '\0')
77 errmsg("invalid statement name: must not be empty")));
78
79 /*
80 * Need to wrap the contained statement in a RawStmt node to pass it to
81 * parse analysis.
82 */
84 rawstmt->stmt = stmt->query;
85 rawstmt->stmt_location = stmt_location;
86 rawstmt->stmt_len = stmt_len;
87
88 /*
89 * Create the CachedPlanSource before we do parse analysis, since it needs
90 * to see the unmodified raw parse tree.
91 */
92 plansource = CreateCachedPlan(rawstmt, pstate->p_sourcetext,
93 CreateCommandTag(stmt->query));
94
95 /* Transform list of TypeNames to array of type OIDs */
96 nargs = list_length(stmt->argtypes);
97
98 if (nargs)
99 {
100 int i;
101 ListCell *l;
102
103 argtypes = palloc_array(Oid, nargs);
104 i = 0;
105
106 foreach(l, stmt->argtypes)
107 {
108 TypeName *tn = lfirst(l);
109 Oid toid = typenameTypeId(pstate, tn);
110
111 argtypes[i++] = toid;
112 }
113 }
114
115 /*
116 * Analyze the statement using these parameter types (any parameters
117 * passed in from above us will not be visible to it), allowing
118 * information about unknown parameters to be deduced from context.
119 * Rewrite the query. The result could be 0, 1, or many queries.
120 */
122 &argtypes, &nargs, NULL);
123
124 /* Finish filling in the CachedPlanSource */
125 CompleteCachedPlan(plansource,
126 query_list,
127 NULL,
128 argtypes,
129 nargs,
130 NULL,
131 NULL,
132 CURSOR_OPT_PARALLEL_OK, /* allow parallel mode */
133 true); /* fixed result */
134
135 /*
136 * Save the results.
137 */
139 plansource,
140 true);
141}
void StorePreparedStatement(const char *stmt_name, CachedPlanSource *plansource, bool from_sql)
Definition prepare.c:394
#define makeNode(_type_)
Definition nodes.h:161
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition parse_type.c:291
#define CURSOR_OPT_PARALLEL_OK
CachedPlanSource * CreateCachedPlan(const RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition plancache.c:185
void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
Definition plancache.c:393
List * pg_analyze_and_rewrite_varparams(RawStmt *parsetree, const char *query_string, Oid **paramTypes, int *numParams, QueryEnvironment *queryEnv)
Definition postgres.c:709
CommandTag CreateCommandTag(Node *parsetree)
Definition utility.c:2384

References CompleteCachedPlan(), CreateCachedPlan(), CreateCommandTag(), CURSOR_OPT_PARALLEL_OK, ereport, errcode(), errmsg, ERROR, fb(), i, lfirst, list_length(), makeNode, ParseState::p_sourcetext, palloc_array, pg_analyze_and_rewrite_varparams(), stmt, StorePreparedStatement(), and typenameTypeId().

Referenced by standard_ProcessUtility().

◆ StorePreparedStatement()

void StorePreparedStatement ( const char stmt_name,
CachedPlanSource plansource,
bool  from_sql 
)

Definition at line 394 of file prepare.c.

397{
398 PreparedStatement *entry;
400 bool found;
401
402 /* Initialize the hash table, if necessary */
403 if (!prepared_queries)
405
406 /* Add entry to hash table */
408 stmt_name,
410 &found);
411
412 /* Shouldn't get a duplicate entry */
413 if (found)
416 errmsg("prepared statement \"%s\" already exists",
417 stmt_name)));
418
419 /* Fill in the hash table entry */
420 entry->plansource = plansource;
421 entry->from_sql = from_sql;
422 entry->prepare_time = cur_ts;
423
424 /* Now it's safe to move the CachedPlanSource to permanent memory */
425 SaveCachedPlan(plansource);
426}
static void InitQueryHashTable(void)
Definition prepare.c:374
int64 TimestampTz
Definition timestamp.h:39
@ HASH_ENTER
Definition hsearch.h:114
void SaveCachedPlan(CachedPlanSource *plansource)
Definition plancache.c:547
TimestampTz prepare_time
Definition prepare.h:34
TimestampTz GetCurrentStatementStartTimestamp(void)
Definition xact.c:881

References ereport, errcode(), errmsg, ERROR, fb(), PreparedStatement::from_sql, GetCurrentStatementStartTimestamp(), HASH_ENTER, hash_search(), InitQueryHashTable(), PreparedStatement::plansource, PreparedStatement::prepare_time, prepared_queries, and SaveCachedPlan().

Referenced by exec_parse_message(), and PrepareQuery().

Variable Documentation

◆ prepared_queries