PostgreSQL Source Code git master
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/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/snapmgr.h"
#include "utils/timestamp.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 744 of file prepare.c.

745{
746 Datum *tmp_ary;
747 ArrayType *result;
748 int i;
749
750 tmp_ary = palloc_array(Datum, num_params);
751
752 for (i = 0; i < num_params; i++)
753 tmp_ary[i] = ObjectIdGetDatum(param_types[i]);
754
755 result = construct_array_builtin(tmp_ary, num_params, REGTYPEOID);
756 return PointerGetDatum(result);
757}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
#define palloc_array(type, count)
Definition: fe_memutils.h:76
int i
Definition: isn.c:72
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252

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

Referenced by pg_prepared_statement().

◆ DeallocateQuery()

void DeallocateQuery ( DeallocateStmt stmt)

Definition at line 502 of file prepare.c.

503{
504 if (stmt->name)
505 DropPreparedStatement(stmt->name, true);
506 else
508}
void DropPreparedStatement(const char *stmt_name, bool showError)
Definition: prepare.c:516
void DropAllPreparedStatements(void)
Definition: prepare.c:537
#define stmt
Definition: indent_codes.h:59

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

Referenced by standard_ProcessUtility().

◆ DropAllPreparedStatements()

void DropAllPreparedStatements ( void  )

Definition at line 537 of file prepare.c.

538{
539 HASH_SEQ_STATUS seq;
540 PreparedStatement *entry;
541
542 /* nothing cached */
543 if (!prepared_queries)
544 return;
545
546 /* walk over cache */
548 while ((entry = hash_seq_search(&seq)) != NULL)
549 {
550 /* Release the plancache entry */
552
553 /* Now we can remove the hash table entry */
555 }
556}
static HTAB * prepared_queries
Definition: prepare.c:44
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1420
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
@ HASH_REMOVE
Definition: hsearch.h:115
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:526
char stmt_name[NAMEDATALEN]
Definition: prepare.h:30
CachedPlanSource * plansource
Definition: prepare.h:31

References DropCachedPlan(), 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 516 of file prepare.c.

517{
518 PreparedStatement *entry;
519
520 /* Find the query's hash table entry; raise error if wanted */
521 entry = FetchPreparedStatement(stmt_name, showError);
522
523 if (entry)
524 {
525 /* Release the plancache entry */
527
528 /* Now we can remove the hash table entry */
530 }
531}
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:431

References DropCachedPlan(), 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 278 of file prepare.c.

280{
281 Oid *param_types = pstmt->plansource->param_types;
282 int num_params = pstmt->plansource->num_params;
283 int nparams = list_length(params);
284 ParamListInfo paramLI;
285 List *exprstates;
286 ListCell *l;
287 int i;
288
289 if (nparams != num_params)
291 (errcode(ERRCODE_SYNTAX_ERROR),
292 errmsg("wrong number of parameters for prepared statement \"%s\"",
293 pstmt->stmt_name),
294 errdetail("Expected %d parameters but got %d.",
295 num_params, nparams)));
296
297 /* Quick exit if no parameters */
298 if (num_params == 0)
299 return NULL;
300
301 /*
302 * We have to run parse analysis for the expressions. Since the parser is
303 * not cool about scribbling on its input, copy first.
304 */
305 params = copyObject(params);
306
307 i = 0;
308 foreach(l, params)
309 {
310 Node *expr = lfirst(l);
311 Oid expected_type_id = param_types[i];
312 Oid given_type_id;
313
314 expr = transformExpr(pstate, expr, EXPR_KIND_EXECUTE_PARAMETER);
315
316 given_type_id = exprType(expr);
317
318 expr = coerce_to_target_type(pstate, expr, given_type_id,
319 expected_type_id, -1,
322 -1);
323
324 if (expr == NULL)
326 (errcode(ERRCODE_DATATYPE_MISMATCH),
327 errmsg("parameter $%d of type %s cannot be coerced to the expected type %s",
328 i + 1,
329 format_type_be(given_type_id),
330 format_type_be(expected_type_id)),
331 errhint("You will need to rewrite or cast the expression."),
333
334 /* Take care of collations in the finished expression. */
335 assign_expr_collations(pstate, expr);
336
337 lfirst(l) = expr;
338 i++;
339 }
340
341 /* Prepare the expressions for execution */
342 exprstates = ExecPrepareExprList(params, estate);
343
344 paramLI = makeParamList(num_params);
345
346 i = 0;
347 foreach(l, exprstates)
348 {
349 ExprState *n = (ExprState *) lfirst(l);
350 ParamExternData *prm = &paramLI->params[i];
351
352 prm->ptype = param_types[i];
356 &prm->isnull);
357
358 i++;
359 }
360
361 return paramLI;
362}
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition: execExpr.c:817
#define GetPerTupleExprContext(estate)
Definition: executor.h:563
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:361
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1380
#define copyObject(obj)
Definition: nodes.h:224
ParamListInfo makeParamList(int numParams)
Definition: params.c:44
#define PARAM_FLAG_CONST
Definition: params.h:88
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
void assign_expr_collations(ParseState *pstate, Node *expr)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:118
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
Definition: postgres_ext.h:31
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:736
@ COERCION_ASSIGNMENT
Definition: primnodes.h:715
Definition: pg_list.h:54
Definition: nodes.h:129
bool isnull
Definition: params.h:93
uint16 pflags
Definition: params.h:94
Datum value
Definition: params.h:92
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:125

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(), format_type_be(), GetPerTupleExprContext, i, ParamExternData::isnull, lfirst, list_length(), makeParamList(), CachedPlanSource::num_params, PARAM_FLAG_CONST, CachedPlanSource::param_types, ParamListInfoData::params, parser_errposition(), ParamExternData::pflags, PreparedStatement::plansource, ParamExternData::ptype, PreparedStatement::stmt_name, transformExpr(), and ParamExternData::value.

Referenced by ExecuteQuery(), and ExplainExecuteQuery().

◆ ExecuteQuery()

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

Definition at line 147 of file prepare.c.

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

References CMD_SELECT, CachedPlanSource::commandTag, PlannedStmt::commandType, CreateExecutorState(), CreateNewPortal(), generate_unaccent_rules::dest, elog, ereport, errcode(), errmsg(), ERROR, EState::es_param_list_info, EvaluateParams(), 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 568 of file prepare.c.

570{
571 PreparedStatement *entry;
572 const char *query_string;
573 CachedPlan *cplan;
574 List *plan_list;
575 ListCell *p;
576 ParamListInfo paramLI = NULL;
577 EState *estate = NULL;
578 instr_time planstart;
579 instr_time planduration;
580 BufferUsage bufusage_start,
581 bufusage;
582 MemoryContextCounters mem_counters;
583 MemoryContext planner_ctx = NULL;
584 MemoryContext saved_ctx = NULL;
585
586 if (es->memory)
587 {
588 /* See ExplainOneQuery about this */
591 "explain analyze planner context",
593 saved_ctx = MemoryContextSwitchTo(planner_ctx);
594 }
595
596 if (es->buffers)
597 bufusage_start = pgBufferUsage;
598 INSTR_TIME_SET_CURRENT(planstart);
599
600 /* Look it up in the hash table */
601 entry = FetchPreparedStatement(execstmt->name, true);
602
603 /* Shouldn't find a non-fixed-result cached plan */
604 if (!entry->plansource->fixed_result)
605 elog(ERROR, "EXPLAIN EXECUTE does not support variable-result cached plans");
606
607 query_string = entry->plansource->query_string;
608
609 /* Evaluate parameters, if any */
610 if (entry->plansource->num_params)
611 {
612 ParseState *pstate_params;
613
614 pstate_params = make_parsestate(NULL);
615 pstate_params->p_sourcetext = pstate->p_sourcetext;
616
617 /*
618 * Need an EState to evaluate parameters; must not delete it till end
619 * of query, in case parameters are pass-by-reference. Note that the
620 * passed-in "params" could possibly be referenced in the parameter
621 * expressions.
622 */
623 estate = CreateExecutorState();
624 estate->es_param_list_info = params;
625
626 paramLI = EvaluateParams(pstate_params, entry, execstmt->params, estate);
627 }
628
629 /* Replan if needed, and acquire a transient refcount */
630 cplan = GetCachedPlan(entry->plansource, paramLI,
632
633 INSTR_TIME_SET_CURRENT(planduration);
634 INSTR_TIME_SUBTRACT(planduration, planstart);
635
636 if (es->memory)
637 {
638 MemoryContextSwitchTo(saved_ctx);
639 MemoryContextMemConsumed(planner_ctx, &mem_counters);
640 }
641
642 /* calc differences of buffer counters. */
643 if (es->buffers)
644 {
645 memset(&bufusage, 0, sizeof(BufferUsage));
646 BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
647 }
648
649 plan_list = cplan->stmt_list;
650
651 /* Explain each query */
652 foreach(p, plan_list)
653 {
655
656 if (pstmt->commandType != CMD_UTILITY)
657 ExplainOnePlan(pstmt, into, es, query_string, paramLI, pstate->p_queryEnv,
658 &planduration, (es->buffers ? &bufusage : NULL),
659 es->memory ? &mem_counters : NULL);
660 else
661 ExplainOneUtility(pstmt->utilityStmt, into, es, pstate, paramLI);
662
663 /* No need for CommandCounterIncrement, as ExplainOnePlan did it */
664
665 /* Separate plans with an appropriate separator */
666 if (lnext(plan_list, p) != NULL)
668 }
669
670 if (estate)
671 FreeExecutorState(estate);
672
674}
#define Assert(condition)
Definition: c.h:812
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:644
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:5510
void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, ParseState *pstate, ParamListInfo params)
Definition: explain.c:540
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:181
BufferUsage pgBufferUsage
Definition: instrument.c:20
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
Definition: instrument.c:248
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
Definition: mcxt.c:786
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
@ CMD_UTILITY
Definition: nodes.h:270
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:1291
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
List * params
Definition: parsenodes.h:4079
char * name
Definition: parsenodes.h:4078
bool memory
Definition: explain.h:55
bool buffers
Definition: explain.h:51
QueryEnvironment * p_queryEnv
Definition: parse_node.h:239
const char * p_sourcetext
Definition: parse_node.h:209
Node * utilityStmt
Definition: plannodes.h:95

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(), FetchPreparedStatement(), CachedPlanSource::fixed_result, FreeExecutorState(), GetCachedPlan(), INSTR_TIME_SET_CURRENT, INSTR_TIME_SUBTRACT, IsA, lfirst_node, lnext(), make_parsestate(), ExplainState::memory, MemoryContextMemConsumed(), MemoryContextSwitchTo(), ExecuteStmt::name, CachedPlanSource::num_params, ParseState::p_queryEnv, ParseState::p_sourcetext, ExecuteStmt::params, 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 431 of file prepare.c.

432{
433 PreparedStatement *entry;
434
435 /*
436 * If the hash table hasn't been initialized, it can't be storing
437 * anything, therefore it couldn't possibly store our plan.
438 */
441 stmt_name,
442 HASH_FIND,
443 NULL);
444 else
445 entry = NULL;
446
447 if (!entry && throwError)
449 (errcode(ERRCODE_UNDEFINED_PSTATEMENT),
450 errmsg("prepared statement \"%s\" does not exist",
451 stmt_name)));
452
453 return entry;
454}
@ HASH_FIND
Definition: hsearch.h:113

References ereport, errcode(), errmsg(), ERROR, 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 463 of file prepare.c.

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

References Assert, CreateTupleDescCopy(), and stmt.

Referenced by UtilityTupleDescriptor().

◆ FetchPreparedStatementTargetList()

List * FetchPreparedStatementTargetList ( PreparedStatement stmt)

Definition at line 486 of file prepare.c.

487{
488 List *tlist;
489
490 /* Get the plan's primary targetlist */
491 tlist = CachedPlanGetTargetList(stmt->plansource, NULL);
492
493 /* Copy into caller's context in case plan gets invalidated */
494 return copyObject(tlist);
495}
List * CachedPlanGetTargetList(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:1640

References CachedPlanGetTargetList(), copyObject, and stmt.

Referenced by FetchStatementTargetList().

◆ InitQueryHashTable()

static void InitQueryHashTable ( void  )
static

Definition at line 369 of file prepare.c.

370{
371 HASHCTL hash_ctl;
372
373 hash_ctl.keysize = NAMEDATALEN;
374 hash_ctl.entrysize = sizeof(PreparedStatement);
375
376 prepared_queries = hash_create("Prepared Queries",
377 32,
378 &hash_ctl,
380}
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define HASH_STRINGS
Definition: hsearch.h:96
#define HASH_ELEM
Definition: hsearch.h:95
#define NAMEDATALEN
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References HASHCTL::entrysize, 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 682 of file prepare.c.

683{
684 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
685
686 /*
687 * We put all the tuples into a tuplestore in one scan of the hashtable.
688 * This avoids any issue of the hashtable possibly changing between calls.
689 */
690 InitMaterializedSRF(fcinfo, 0);
691
692 /* hash table might be uninitialized */
694 {
695 HASH_SEQ_STATUS hash_seq;
696 PreparedStatement *prep_stmt;
697
699 while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
700 {
701 TupleDesc result_desc;
702 Datum values[8];
703 bool nulls[8] = {0};
704
705 result_desc = prep_stmt->plansource->resultDesc;
706
707 values[0] = CStringGetTextDatum(prep_stmt->stmt_name);
709 values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
711 prep_stmt->plansource->num_params);
712 if (result_desc)
713 {
714 Oid *result_types;
715
716 result_types = palloc_array(Oid, result_desc->natts);
717 for (int i = 0; i < result_desc->natts; i++)
718 result_types[i] = TupleDescAttr(result_desc, i)->atttypid;
719 values[4] = build_regtype_array(result_types, result_desc->natts);
720 }
721 else
722 {
723 /* no result descriptor (for example, DML statement) */
724 nulls[4] = true;
725 }
726 values[5] = BoolGetDatum(prep_stmt->from_sql);
729
730 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
731 values, nulls);
732 }
733 }
734
735 return (Datum) 0;
736}
static Datum build_regtype_array(Oid *param_types, int num_params)
Definition: prepare.c:744
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define Int64GetDatumFast(X)
Definition: postgres.h:554
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
TupleDesc resultDesc
Definition: plancache.h:108
int64 num_custom_plans
Definition: plancache.h:133
int64 num_generic_plans
Definition: plancache.h:134
TimestampTz prepare_time
Definition: prepare.h:33
TupleDesc setDesc
Definition: execnodes.h:343
Tuplestorestate * setResult
Definition: execnodes.h:342
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:153
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784
static Datum TimestampTzGetDatum(TimestampTz X)
Definition: timestamp.h:52

References BoolGetDatum(), build_regtype_array(), CStringGetTextDatum, PreparedStatement::from_sql, hash_seq_init(), hash_seq_search(), i, InitMaterializedSRF(), Int64GetDatumFast, TupleDescData::natts, CachedPlanSource::num_custom_plans, CachedPlanSource::num_generic_plans, CachedPlanSource::num_params, palloc_array, CachedPlanSource::param_types, PreparedStatement::plansource, PreparedStatement::prepare_time, prepared_queries, CachedPlanSource::query_string, CachedPlanSource::resultDesc, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, PreparedStatement::stmt_name, TimestampTzGetDatum(), TupleDescAttr(), tuplestore_putvalues(), and values.

◆ PrepareQuery()

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

Definition at line 56 of file prepare.c.

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

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

Referenced by standard_ProcessUtility().

◆ StorePreparedStatement()

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

Definition at line 389 of file prepare.c.

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

References ereport, errcode(), errmsg(), ERROR, 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