PostgreSQL Source Code  git master
prepare.h File Reference
Include dependency graph for prepare.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PreparedStatement
 

Functions

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 DeallocateQuery (DeallocateStmt *stmt)
 
void ExplainExecuteQuery (ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
void StorePreparedStatement (const char *stmt_name, CachedPlanSource *plansource, bool from_sql)
 
PreparedStatementFetchPreparedStatement (const char *stmt_name, bool throwError)
 
void DropPreparedStatement (const char *stmt_name, bool showError)
 
TupleDesc FetchPreparedStatementResultDesc (PreparedStatement *stmt)
 
ListFetchPreparedStatementTargetList (PreparedStatement *stmt)
 
void DropAllPreparedStatements (void)
 

Function Documentation

◆ DeallocateQuery()

void DeallocateQuery ( DeallocateStmt stmt)

Definition at line 538 of file prepare.c.

References DropAllPreparedStatements(), DropPreparedStatement(), and DeallocateStmt::name.

Referenced by standard_ProcessUtility().

539 {
540  if (stmt->name)
541  DropPreparedStatement(stmt->name, true);
542  else
544 }
void DropAllPreparedStatements(void)
Definition: prepare.c:573
void DropPreparedStatement(const char *stmt_name, bool showError)
Definition: prepare.c:552

◆ DropAllPreparedStatements()

void DropAllPreparedStatements ( void  )

Definition at line 573 of file prepare.c.

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

Referenced by DeallocateQuery(), and DiscardAll().

574 {
575  HASH_SEQ_STATUS seq;
576  PreparedStatement *entry;
577 
578  /* nothing cached */
579  if (!prepared_queries)
580  return;
581 
582  /* walk over cache */
584  while ((entry = hash_seq_search(&seq)) != NULL)
585  {
586  /* Release the plancache entry */
587  DropCachedPlan(entry->plansource);
588 
589  /* Now we can remove the hash table entry */
591  }
592 }
CachedPlanSource * plansource
Definition: prepare.h:31
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * prepared_queries
Definition: prepare.c:46
char stmt_name[NAMEDATALEN]
Definition: prepare.h:30
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:498

◆ DropPreparedStatement()

void DropPreparedStatement ( const char *  stmt_name,
bool  showError 
)

Definition at line 552 of file prepare.c.

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

Referenced by DeallocateQuery(), and PostgresMain().

553 {
554  PreparedStatement *entry;
555 
556  /* Find the query's hash table entry; raise error if wanted */
557  entry = FetchPreparedStatement(stmt_name, showError);
558 
559  if (entry)
560  {
561  /* Release the plancache entry */
562  DropCachedPlan(entry->plansource);
563 
564  /* Now we can remove the hash table entry */
566  }
567 }
CachedPlanSource * plansource
Definition: prepare.h:31
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * prepared_queries
Definition: prepare.c:46
char stmt_name[NAMEDATALEN]
Definition: prepare.h:30
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:498
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:467

◆ ExecuteQuery()

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

Definition at line 187 of file prepare.c.

References CMD_SELECT, CachedPlanSource::commandTag, PlannedStmt::commandType, CreateExecutorState(), CreateNewPortal(), 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(), ExecuteStmt::name, CachedPlanSource::num_params, ExecuteStmt::params, PreparedStatement::plansource, PortalData::portalContext, PortalDefineQuery(), PortalDrop(), PortalRun(), PortalStart(), CachedPlanSource::query_string, IntoClause::skipData, CachedPlan::stmt_list, and PortalData::visible.

Referenced by ExecCreateTableAs(), and standard_ProcessUtility().

191 {
192  PreparedStatement *entry;
193  CachedPlan *cplan;
194  List *plan_list;
195  ParamListInfo paramLI = NULL;
196  EState *estate = NULL;
197  Portal portal;
198  char *query_string;
199  int eflags;
200  long count;
201 
202  /* Look it up in the hash table */
203  entry = FetchPreparedStatement(stmt->name, true);
204 
205  /* Shouldn't find a non-fixed-result cached plan */
206  if (!entry->plansource->fixed_result)
207  elog(ERROR, "EXECUTE does not support variable-result cached plans");
208 
209  /* Evaluate parameters, if any */
210  if (entry->plansource->num_params > 0)
211  {
212  /*
213  * Need an EState to evaluate parameters; must not delete it till end
214  * of query, in case parameters are pass-by-reference. Note that the
215  * passed-in "params" could possibly be referenced in the parameter
216  * expressions.
217  */
218  estate = CreateExecutorState();
219  estate->es_param_list_info = params;
220  paramLI = EvaluateParams(pstate, entry, stmt->params, estate);
221  }
222 
223  /* Create a new portal to run the query in */
224  portal = CreateNewPortal();
225  /* Don't display the portal in pg_cursors, it is for internal use only */
226  portal->visible = false;
227 
228  /* Copy the plan's saved query string into the portal's memory */
229  query_string = MemoryContextStrdup(portal->portalContext,
230  entry->plansource->query_string);
231 
232  /* Replan if needed, and increment plan refcount for portal */
233  cplan = GetCachedPlan(entry->plansource, paramLI, NULL, NULL);
234  plan_list = cplan->stmt_list;
235 
236  /*
237  * For CREATE TABLE ... AS EXECUTE, we must verify that the prepared
238  * statement is one that produces tuples. Currently we insist that it be
239  * a plain old SELECT. In future we might consider supporting other
240  * things such as INSERT ... RETURNING, but there are a couple of issues
241  * to be settled first, notably how WITH NO DATA should be handled in such
242  * a case (do we really want to suppress execution?) and how to pass down
243  * the OID-determining eflags (PortalStart won't handle them in such a
244  * case, and for that matter it's not clear the executor will either).
245  *
246  * For CREATE TABLE ... AS EXECUTE, we also have to ensure that the proper
247  * eflags and fetch count are passed to PortalStart/PortalRun.
248  */
249  if (intoClause)
250  {
251  PlannedStmt *pstmt;
252 
253  if (list_length(plan_list) != 1)
254  ereport(ERROR,
255  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
256  errmsg("prepared statement is not a SELECT")));
257  pstmt = linitial_node(PlannedStmt, plan_list);
258  if (pstmt->commandType != CMD_SELECT)
259  ereport(ERROR,
260  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
261  errmsg("prepared statement is not a SELECT")));
262 
263  /* Set appropriate eflags */
264  eflags = GetIntoRelEFlags(intoClause);
265 
266  /* And tell PortalRun whether to run to completion or not */
267  if (intoClause->skipData)
268  count = 0;
269  else
270  count = FETCH_ALL;
271  }
272  else
273  {
274  /* Plain old EXECUTE */
275  eflags = 0;
276  count = FETCH_ALL;
277  }
278 
279  PortalDefineQuery(portal,
280  NULL,
281  query_string,
282  entry->plansource->commandTag,
283  plan_list,
284  cplan);
285 
286  /*
287  * Run the portal as appropriate.
288  */
289  PortalStart(portal, paramLI, eflags, GetActiveSnapshot());
290 
291  (void) PortalRun(portal, count, false, true, dest, dest, qc);
292 
293  PortalDrop(portal, false);
294 
295  if (estate)
296  FreeExecutorState(estate);
297 
298  /* No need to pfree other memory, MemoryContext will be reset */
299 }
Portal CreateNewPortal(void)
Definition: portalmem.c:234
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition: pquery.c:430
bool visible
Definition: portal.h:196
CachedPlanSource * plansource
Definition: prepare.h:31
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
static ParamListInfo EvaluateParams(ParseState *pstate, PreparedStatement *pstmt, List *params, EState *estate)
Definition: prepare.c:314
int errcode(int sqlerrcode)
Definition: elog.c:704
bool skipData
Definition: primnodes.h:119
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan)
Definition: portalmem.c:281
#define linitial_node(type, l)
Definition: pg_list.h:177
MemoryContext portalContext
Definition: portal.h:120
bool PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
Definition: pquery.c:672
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:381
#define ERROR
Definition: elog.h:45
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1141
EState * CreateExecutorState(void)
Definition: execUtils.c:90
CmdType commandType
Definition: plannodes.h:46
#define ereport(elevel,...)
Definition: elog.h:155
const char * query_string
Definition: plancache.h:100
CommandTag commandTag
Definition: plancache.h:101
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:915
void PortalDrop(Portal portal, bool isTopCommit)
Definition: portalmem.c:467
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1174
#define elog(elevel,...)
Definition: elog.h:228
char * name
Definition: parsenodes.h:3470
ParamListInfo es_param_list_info
Definition: execnodes.h:566
List * params
Definition: parsenodes.h:3471
List * stmt_list
Definition: plancache.h:150
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:467
Definition: pg_list.h:50
#define FETCH_ALL
Definition: parsenodes.h:2794

◆ ExplainExecuteQuery()

void ExplainExecuteQuery ( ExecuteStmt execstmt,
IntoClause into,
ExplainState es,
const char *  queryString,
ParamListInfo  params,
QueryEnvironment queryEnv 
)

Definition at line 604 of file prepare.c.

References ExplainState::buffers, BufferUsageAccumDiff(), CMD_UTILITY, PlannedStmt::commandType, CreateExecutorState(), 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, lfirst_node, lnext(), make_parsestate(), ExecuteStmt::name, CachedPlanSource::num_params, ParseState::p_sourcetext, ExecuteStmt::params, pgBufferUsage, PreparedStatement::plansource, CachedPlanSource::query_string, ReleaseCachedPlan(), CachedPlan::stmt_list, and PlannedStmt::utilityStmt.

Referenced by ExplainOneUtility().

607 {
608  PreparedStatement *entry;
609  const char *query_string;
610  CachedPlan *cplan;
611  List *plan_list;
612  ListCell *p;
613  ParamListInfo paramLI = NULL;
614  EState *estate = NULL;
615  instr_time planstart;
616  instr_time planduration;
617  BufferUsage bufusage_start,
618  bufusage;
619 
620  if (es->buffers)
621  bufusage_start = pgBufferUsage;
622  INSTR_TIME_SET_CURRENT(planstart);
623 
624  /* Look it up in the hash table */
625  entry = FetchPreparedStatement(execstmt->name, true);
626 
627  /* Shouldn't find a non-fixed-result cached plan */
628  if (!entry->plansource->fixed_result)
629  elog(ERROR, "EXPLAIN EXECUTE does not support variable-result cached plans");
630 
631  query_string = entry->plansource->query_string;
632 
633  /* Evaluate parameters, if any */
634  if (entry->plansource->num_params)
635  {
636  ParseState *pstate;
637 
638  pstate = make_parsestate(NULL);
639  pstate->p_sourcetext = queryString;
640 
641  /*
642  * Need an EState to evaluate parameters; must not delete it till end
643  * of query, in case parameters are pass-by-reference. Note that the
644  * passed-in "params" could possibly be referenced in the parameter
645  * expressions.
646  */
647  estate = CreateExecutorState();
648  estate->es_param_list_info = params;
649 
650  paramLI = EvaluateParams(pstate, entry, execstmt->params, estate);
651  }
652 
653  /* Replan if needed, and acquire a transient refcount */
654  cplan = GetCachedPlan(entry->plansource, paramLI,
655  CurrentResourceOwner, queryEnv);
656 
657  INSTR_TIME_SET_CURRENT(planduration);
658  INSTR_TIME_SUBTRACT(planduration, planstart);
659 
660  /* calc differences of buffer counters. */
661  if (es->buffers)
662  {
663  memset(&bufusage, 0, sizeof(BufferUsage));
664  BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
665  }
666 
667  plan_list = cplan->stmt_list;
668 
669  /* Explain each query */
670  foreach(p, plan_list)
671  {
672  PlannedStmt *pstmt = lfirst_node(PlannedStmt, p);
673 
674  if (pstmt->commandType != CMD_UTILITY)
675  ExplainOnePlan(pstmt, into, es, query_string, paramLI, queryEnv,
676  &planduration, (es->buffers ? &bufusage : NULL));
677  else
678  ExplainOneUtility(pstmt->utilityStmt, into, es, query_string,
679  paramLI, queryEnv);
680 
681  /* No need for CommandCounterIncrement, as ExplainOnePlan did it */
682 
683  /* Separate plans with an appropriate separator */
684  if (lnext(plan_list, p) != NULL)
686  }
687 
688  if (estate)
689  FreeExecutorState(estate);
690 
692 }
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:4622
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
CachedPlanSource * plansource
Definition: prepare.h:31
ResourceOwner CurrentResourceOwner
Definition: resowner.c:144
struct timeval instr_time
Definition: instr_time.h:150
static ParamListInfo EvaluateParams(ParseState *pstate, PreparedStatement *pstmt, List *params, EState *estate)
Definition: prepare.c:314
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1264
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
Definition: instrument.c:225
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
void FreeExecutorState(EState *estate)
Definition: execUtils.c:186
#define ERROR
Definition: elog.h:45
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:170
#define lfirst_node(type, lc)
Definition: pg_list.h:172
Node * utilityStmt
Definition: plannodes.h:86
const char * p_sourcetext
Definition: parse_node.h:180
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1141
EState * CreateExecutorState(void)
Definition: execUtils.c:90
CmdType commandType
Definition: plannodes.h:46
void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv, const instr_time *planduration, const BufferUsage *bufusage)
Definition: explain.c:512
const char * query_string
Definition: plancache.h:100
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
#define elog(elevel,...)
Definition: elog.h:228
char * name
Definition: parsenodes.h:3470
bool buffers
Definition: explain.h:44
ParamListInfo es_param_list_info
Definition: execnodes.h:566
List * params
Definition: parsenodes.h:3471
List * stmt_list
Definition: plancache.h:150
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:467
Definition: pg_list.h:50
void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:421
BufferUsage pgBufferUsage
Definition: instrument.c:20

◆ FetchPreparedStatement()

PreparedStatement* FetchPreparedStatement ( const char *  stmt_name,
bool  throwError 
)

Definition at line 467 of file prepare.c.

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

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

468 {
469  PreparedStatement *entry;
470 
471  /*
472  * If the hash table hasn't been initialized, it can't be storing
473  * anything, therefore it couldn't possibly store our plan.
474  */
475  if (prepared_queries)
477  stmt_name,
478  HASH_FIND,
479  NULL);
480  else
481  entry = NULL;
482 
483  if (!entry && throwError)
484  ereport(ERROR,
485  (errcode(ERRCODE_UNDEFINED_PSTATEMENT),
486  errmsg("prepared statement \"%s\" does not exist",
487  stmt_name)));
488 
489  return entry;
490 }
int errcode(int sqlerrcode)
Definition: elog.c:704
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * prepared_queries
Definition: prepare.c:46
#define ERROR
Definition: elog.h:45
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:915

◆ FetchPreparedStatementResultDesc()

TupleDesc FetchPreparedStatementResultDesc ( PreparedStatement stmt)

Definition at line 499 of file prepare.c.

References Assert, CreateTupleDescCopy(), CachedPlanSource::fixed_result, PreparedStatement::plansource, and CachedPlanSource::resultDesc.

Referenced by UtilityTupleDescriptor().

500 {
501  /*
502  * Since we don't allow prepared statements' result tupdescs to change,
503  * there's no need to worry about revalidating the cached plan here.
504  */
506  if (stmt->plansource->resultDesc)
508  else
509  return NULL;
510 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
CachedPlanSource * plansource
Definition: prepare.h:31
TupleDesc resultDesc
Definition: plancache.h:108
#define Assert(condition)
Definition: c.h:804

◆ FetchPreparedStatementTargetList()

List* FetchPreparedStatementTargetList ( PreparedStatement stmt)

Definition at line 522 of file prepare.c.

References CachedPlanGetTargetList(), copyObject, and PreparedStatement::plansource.

Referenced by FetchStatementTargetList().

523 {
524  List *tlist;
525 
526  /* Get the plan's primary targetlist */
527  tlist = CachedPlanGetTargetList(stmt->plansource, NULL);
528 
529  /* Copy into caller's context in case plan gets invalidated */
530  return copyObject(tlist);
531 }
CachedPlanSource * plansource
Definition: prepare.h:31
List * CachedPlanGetTargetList(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:1611
#define copyObject(obj)
Definition: nodes.h:646
Definition: pg_list.h:50

◆ PrepareQuery()

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

Definition at line 58 of file prepare.c.

References PrepareStmt::argtypes, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, Query::commandType, CompleteCachedPlan(), copyObject, CreateCachedPlan(), CreateCommandTag(), CURSOR_OPT_PARALLEL_OK, ereport, errcode(), errmsg(), ERROR, i, InvalidOid, lfirst, list_length(), makeNode, PrepareStmt::name, ParseState::p_sourcetext, palloc(), parse_analyze_varparams(), PrepareStmt::query, QueryRewrite(), RawStmt::stmt, RawStmt::stmt_len, RawStmt::stmt_location, StorePreparedStatement(), and typenameTypeId().

Referenced by standard_ProcessUtility().

60 {
61  RawStmt *rawstmt;
62  CachedPlanSource *plansource;
63  Oid *argtypes = NULL;
64  int nargs;
65  Query *query;
66  List *query_list;
67  int i;
68 
69  /*
70  * Disallow empty-string statement name (conflicts with protocol-level
71  * unnamed statement).
72  */
73  if (!stmt->name || stmt->name[0] == '\0')
74  ereport(ERROR,
75  (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION),
76  errmsg("invalid statement name: must not be empty")));
77 
78  /*
79  * Need to wrap the contained statement in a RawStmt node to pass it to
80  * parse analysis.
81  *
82  * Because parse analysis scribbles on the raw querytree, we must make a
83  * copy to ensure we don't modify the passed-in tree. FIXME someday.
84  */
85  rawstmt = makeNode(RawStmt);
86  rawstmt->stmt = (Node *) copyObject(stmt->query);
87  rawstmt->stmt_location = stmt_location;
88  rawstmt->stmt_len = stmt_len;
89 
90  /*
91  * Create the CachedPlanSource before we do parse analysis, since it needs
92  * to see the unmodified raw parse tree.
93  */
94  plansource = CreateCachedPlan(rawstmt, pstate->p_sourcetext,
95  CreateCommandTag(stmt->query));
96 
97  /* Transform list of TypeNames to array of type OIDs */
98  nargs = list_length(stmt->argtypes);
99 
100  if (nargs)
101  {
102  ListCell *l;
103 
104  argtypes = (Oid *) palloc(nargs * sizeof(Oid));
105  i = 0;
106 
107  foreach(l, stmt->argtypes)
108  {
109  TypeName *tn = lfirst(l);
110  Oid toid = typenameTypeId(pstate, tn);
111 
112  argtypes[i++] = toid;
113  }
114  }
115 
116  /*
117  * Analyze the statement using these parameter types (any parameters
118  * passed in from above us will not be visible to it), allowing
119  * information about unknown parameters to be deduced from context.
120  */
121  query = parse_analyze_varparams(rawstmt, pstate->p_sourcetext,
122  &argtypes, &nargs);
123 
124  /*
125  * Check that all parameter types were determined.
126  */
127  for (i = 0; i < nargs; i++)
128  {
129  Oid argtype = argtypes[i];
130 
131  if (argtype == InvalidOid || argtype == UNKNOWNOID)
132  ereport(ERROR,
133  (errcode(ERRCODE_INDETERMINATE_DATATYPE),
134  errmsg("could not determine data type of parameter $%d",
135  i + 1)));
136  }
137 
138  /*
139  * grammar only allows PreparableStmt, so this check should be redundant
140  */
141  switch (query->commandType)
142  {
143  case CMD_SELECT:
144  case CMD_INSERT:
145  case CMD_UPDATE:
146  case CMD_DELETE:
147  /* OK */
148  break;
149  default:
150  ereport(ERROR,
151  (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION),
152  errmsg("utility statements cannot be prepared")));
153  break;
154  }
155 
156  /* Rewrite the query. The result could be 0, 1, or many queries. */
157  query_list = QueryRewrite(query);
158 
159  /* Finish filling in the CachedPlanSource */
160  CompleteCachedPlan(plansource,
161  query_list,
162  NULL,
163  argtypes,
164  nargs,
165  NULL,
166  NULL,
167  CURSOR_OPT_PARALLEL_OK, /* allow parallel mode */
168  true); /* fixed result */
169 
170  /*
171  * Save the results.
172  */
174  plansource,
175  true);
176 }
List * QueryRewrite(Query *parsetree)
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:164
Definition: nodes.h:530
int errcode(int sqlerrcode)
Definition: elog.c:704
Query * parse_analyze_varparams(RawStmt *parseTree, const char *sourceText, Oid **paramTypes, int *numParams)
Definition: analyze.c:138
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:45
Node * stmt
Definition: parsenodes.h:1539
const char * p_sourcetext
Definition: parse_node.h:180
int stmt_len
Definition: parsenodes.h:1541
int stmt_location
Definition: parsenodes.h:1540
void StorePreparedStatement(const char *stmt_name, CachedPlanSource *plansource, bool from_sql)
Definition: prepare.c:425
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:155
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:578
char * name
Definition: parsenodes.h:3456
#define lfirst(lc)
Definition: pg_list.h:169
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2251
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:338
Node * query
Definition: parsenodes.h:3458
static int list_length(const List *l)
Definition: pg_list.h:149
List * argtypes
Definition: parsenodes.h:3457
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2759
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
#define copyObject(obj)
Definition: nodes.h:646
Definition: pg_list.h:50
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291

◆ StorePreparedStatement()

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

Definition at line 425 of file prepare.c.

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

Referenced by exec_parse_message(), and PrepareQuery().

428 {
429  PreparedStatement *entry;
431  bool found;
432 
433  /* Initialize the hash table, if necessary */
434  if (!prepared_queries)
436 
437  /* Add entry to hash table */
439  stmt_name,
440  HASH_ENTER,
441  &found);
442 
443  /* Shouldn't get a duplicate entry */
444  if (found)
445  ereport(ERROR,
446  (errcode(ERRCODE_DUPLICATE_PSTATEMENT),
447  errmsg("prepared statement \"%s\" already exists",
448  stmt_name)));
449 
450  /* Fill in the hash table entry */
451  entry->plansource = plansource;
452  entry->from_sql = from_sql;
453  entry->prepare_time = cur_ts;
454 
455  /* Now it's safe to move the CachedPlanSource to permanent memory */
456  SaveCachedPlan(plansource);
457 }
static void InitQueryHashTable(void)
Definition: prepare.c:405
CachedPlanSource * plansource
Definition: prepare.h:31
int64 TimestampTz
Definition: timestamp.h:39
int errcode(int sqlerrcode)
Definition: elog.c:704
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
static HTAB * prepared_queries
Definition: prepare.c:46
#define ERROR
Definition: elog.h:45
#define ereport(elevel,...)
Definition: elog.h:155
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:454
TimestampTz prepare_time
Definition: prepare.h:33
int errmsg(const char *fmt,...)
Definition: elog.c:915
TimestampTz GetCurrentStatementStartTimestamp(void)
Definition: xact.c:807