PostgreSQL Source Code  git master
prepare.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * prepare.c
4  * Prepareable SQL statements via PREPARE, EXECUTE and DEALLOCATE
5  *
6  * This module also implements storage of prepared statements that are
7  * accessed via the extended FE/BE query protocol.
8  *
9  *
10  * Copyright (c) 2002-2024, PostgreSQL Global Development Group
11  *
12  * IDENTIFICATION
13  * src/backend/commands/prepare.c
14  *
15  *-------------------------------------------------------------------------
16  */
17 #include "postgres.h"
18 
19 #include <limits.h>
20 
21 #include "access/xact.h"
22 #include "catalog/pg_type.h"
23 #include "commands/createas.h"
24 #include "commands/prepare.h"
25 #include "funcapi.h"
26 #include "nodes/nodeFuncs.h"
27 #include "parser/parse_coerce.h"
28 #include "parser/parse_collate.h"
29 #include "parser/parse_expr.h"
30 #include "parser/parse_type.h"
31 #include "tcop/pquery.h"
32 #include "tcop/utility.h"
33 #include "utils/builtins.h"
34 #include "utils/snapmgr.h"
35 #include "utils/timestamp.h"
36 
37 
38 /*
39  * The hash table in which prepared queries are stored. This is
40  * per-backend: query plans are not shared between backends.
41  * The keys for this hash table are the arguments to PREPARE and EXECUTE
42  * (statement names); the entries are PreparedStatement structs.
43  */
44 static HTAB *prepared_queries = NULL;
45 
46 static void InitQueryHashTable(void);
48  PreparedStatement *pstmt, List *params,
49  EState *estate);
50 static Datum build_regtype_array(Oid *param_types, int num_params);
51 
52 /*
53  * Implements the 'PREPARE' utility statement.
54  */
55 void
57  int stmt_location, int stmt_len)
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')
70  ereport(ERROR,
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 }
137 
138 /*
139  * ExecuteQuery --- implement the 'EXECUTE' utility statement.
140  *
141  * This code also supports CREATE TABLE ... AS EXECUTE. That case is
142  * indicated by passing a non-null intoClause. The DestReceiver is already
143  * set up correctly for CREATE TABLE AS, but we still have to make a few
144  * other adjustments here.
145  */
146 void
148  ExecuteStmt *stmt, IntoClause *intoClause,
149  ParamListInfo params,
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)
225  ereport(ERROR,
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)
230  ereport(ERROR,
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, true, 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 }
264 
265 /*
266  * EvaluateParams: evaluate a list of parameters.
267  *
268  * pstate: parse state
269  * pstmt: statement we are getting parameters for.
270  * params: list of given parameter expressions (raw parser output!)
271  * estate: executor state to use.
272  *
273  * Returns a filled-in ParamListInfo -- this can later be passed to
274  * CreateQueryDesc(), which allows the executor to make use of the parameters
275  * during query execution.
276  */
277 static ParamListInfo
279  EState *estate)
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)
290  ereport(ERROR,
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)
325  ereport(ERROR,
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."),
332  parser_errposition(pstate, exprLocation(lfirst(l)))));
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];
353  prm->pflags = PARAM_FLAG_CONST;
355  GetPerTupleExprContext(estate),
356  &prm->isnull);
357 
358  i++;
359  }
360 
361  return paramLI;
362 }
363 
364 
365 /*
366  * Initialize query hash table upon first use.
367  */
368 static void
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 }
381 
382 /*
383  * Store all the data pertaining to a query in the hash table using
384  * the specified key. The passed CachedPlanSource should be "unsaved"
385  * in case we get an error here; we'll save it once we've created the hash
386  * table entry.
387  */
388 void
389 StorePreparedStatement(const char *stmt_name,
390  CachedPlanSource *plansource,
391  bool from_sql)
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,
404  HASH_ENTER,
405  &found);
406 
407  /* Shouldn't get a duplicate entry */
408  if (found)
409  ereport(ERROR,
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 }
422 
423 /*
424  * Lookup an existing query in the hash table. If the query does not
425  * actually exist, throw ereport(ERROR) or return NULL per second parameter.
426  *
427  * Note: this does not force the referenced plancache entry to be valid,
428  * since not all callers care.
429  */
431 FetchPreparedStatement(const char *stmt_name, bool throwError)
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  */
439  if (prepared_queries)
441  stmt_name,
442  HASH_FIND,
443  NULL);
444  else
445  entry = NULL;
446 
447  if (!entry && throwError)
448  ereport(ERROR,
449  (errcode(ERRCODE_UNDEFINED_PSTATEMENT),
450  errmsg("prepared statement \"%s\" does not exist",
451  stmt_name)));
452 
453  return entry;
454 }
455 
456 /*
457  * Given a prepared statement, determine the result tupledesc it will
458  * produce. Returns NULL if the execution will not return tuples.
459  *
460  * Note: the result is created or copied into current memory context.
461  */
462 TupleDesc
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 }
475 
476 /*
477  * Given a prepared statement that returns tuples, extract the query
478  * targetlist. Returns NIL if the statement doesn't have a determinable
479  * targetlist.
480  *
481  * Note: this is pretty ugly, but since it's only used in corner cases like
482  * Describe Statement on an EXECUTE command, we don't worry too much about
483  * efficiency.
484  */
485 List *
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 }
496 
497 /*
498  * Implements the 'DEALLOCATE' utility statement: deletes the
499  * specified plan from storage.
500  */
501 void
503 {
504  if (stmt->name)
505  DropPreparedStatement(stmt->name, true);
506  else
508 }
509 
510 /*
511  * Internal version of DEALLOCATE
512  *
513  * If showError is false, dropping a nonexistent statement is a no-op.
514  */
515 void
516 DropPreparedStatement(const char *stmt_name, bool showError)
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 */
526  DropCachedPlan(entry->plansource);
527 
528  /* Now we can remove the hash table entry */
530  }
531 }
532 
533 /*
534  * Drop all cached statements.
535  */
536 void
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 */
551  DropCachedPlan(entry->plansource);
552 
553  /* Now we can remove the hash table entry */
555  }
556 }
557 
558 /*
559  * Implements the 'EXPLAIN EXECUTE' utility statement.
560  *
561  * "into" is NULL unless we are doing EXPLAIN CREATE TABLE AS EXECUTE,
562  * in which case executing the query should result in creating that table.
563  *
564  * Note: the passed-in queryString is that of the EXPLAIN EXECUTE,
565  * not the original PREPARE; we get the latter string from the plancache.
566  */
567 void
569  const char *queryString, ParamListInfo params,
570  QueryEnvironment *queryEnv)
571 {
572  PreparedStatement *entry;
573  const char *query_string;
574  CachedPlan *cplan;
575  List *plan_list;
576  ListCell *p;
577  ParamListInfo paramLI = NULL;
578  EState *estate = NULL;
579  instr_time planstart;
580  instr_time planduration;
581  BufferUsage bufusage_start,
582  bufusage;
583  MemoryContextCounters mem_counters;
584  MemoryContext planner_ctx = NULL;
585  MemoryContext saved_ctx = NULL;
586 
587  if (es->memory)
588  {
589  /* See ExplainOneQuery about this */
592  "explain analyze planner context",
594  saved_ctx = MemoryContextSwitchTo(planner_ctx);
595  }
596 
597  if (es->buffers)
598  bufusage_start = pgBufferUsage;
599  INSTR_TIME_SET_CURRENT(planstart);
600 
601  /* Look it up in the hash table */
602  entry = FetchPreparedStatement(execstmt->name, true);
603 
604  /* Shouldn't find a non-fixed-result cached plan */
605  if (!entry->plansource->fixed_result)
606  elog(ERROR, "EXPLAIN EXECUTE does not support variable-result cached plans");
607 
608  query_string = entry->plansource->query_string;
609 
610  /* Evaluate parameters, if any */
611  if (entry->plansource->num_params)
612  {
613  ParseState *pstate;
614 
615  pstate = make_parsestate(NULL);
616  pstate->p_sourcetext = queryString;
617 
618  /*
619  * Need an EState to evaluate parameters; must not delete it till end
620  * of query, in case parameters are pass-by-reference. Note that the
621  * passed-in "params" could possibly be referenced in the parameter
622  * expressions.
623  */
624  estate = CreateExecutorState();
625  estate->es_param_list_info = params;
626 
627  paramLI = EvaluateParams(pstate, entry, execstmt->params, estate);
628  }
629 
630  /* Replan if needed, and acquire a transient refcount */
631  cplan = GetCachedPlan(entry->plansource, paramLI,
632  CurrentResourceOwner, queryEnv);
633 
634  INSTR_TIME_SET_CURRENT(planduration);
635  INSTR_TIME_SUBTRACT(planduration, planstart);
636 
637  if (es->memory)
638  {
639  MemoryContextSwitchTo(saved_ctx);
640  MemoryContextMemConsumed(planner_ctx, &mem_counters);
641  }
642 
643  /* calc differences of buffer counters. */
644  if (es->buffers)
645  {
646  memset(&bufusage, 0, sizeof(BufferUsage));
647  BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
648  }
649 
650  plan_list = cplan->stmt_list;
651 
652  /* Explain each query */
653  foreach(p, plan_list)
654  {
655  PlannedStmt *pstmt = lfirst_node(PlannedStmt, p);
656 
657  if (pstmt->commandType != CMD_UTILITY)
658  ExplainOnePlan(pstmt, into, es, query_string, paramLI, queryEnv,
659  &planduration, (es->buffers ? &bufusage : NULL),
660  es->memory ? &mem_counters : NULL);
661  else
662  ExplainOneUtility(pstmt->utilityStmt, into, es, query_string,
663  paramLI, queryEnv);
664 
665  /* No need for CommandCounterIncrement, as ExplainOnePlan did it */
666 
667  /* Separate plans with an appropriate separator */
668  if (lnext(plan_list, p) != NULL)
670  }
671 
672  if (estate)
673  FreeExecutorState(estate);
674 
676 }
677 
678 /*
679  * This set returning function reads all the prepared statements and
680  * returns a set of (name, statement, prepare_time, param_types, from_sql,
681  * generic_plans, custom_plans).
682  */
683 Datum
685 {
686  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
687 
688  /*
689  * We put all the tuples into a tuplestore in one scan of the hashtable.
690  * This avoids any issue of the hashtable possibly changing between calls.
691  */
692  InitMaterializedSRF(fcinfo, 0);
693 
694  /* hash table might be uninitialized */
695  if (prepared_queries)
696  {
697  HASH_SEQ_STATUS hash_seq;
698  PreparedStatement *prep_stmt;
699 
700  hash_seq_init(&hash_seq, prepared_queries);
701  while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
702  {
703  TupleDesc result_desc;
704  Datum values[8];
705  bool nulls[8] = {0};
706 
707  result_desc = prep_stmt->plansource->resultDesc;
708 
709  values[0] = CStringGetTextDatum(prep_stmt->stmt_name);
711  values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
713  prep_stmt->plansource->num_params);
714  if (result_desc)
715  {
716  Oid *result_types;
717 
718  result_types = palloc_array(Oid, result_desc->natts);
719  for (int i = 0; i < result_desc->natts; i++)
720  result_types[i] = result_desc->attrs[i].atttypid;
721  values[4] = build_regtype_array(result_types, result_desc->natts);
722  }
723  else
724  {
725  /* no result descriptor (for example, DML statement) */
726  nulls[4] = true;
727  }
728  values[5] = BoolGetDatum(prep_stmt->from_sql);
731 
732  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
733  values, nulls);
734  }
735  }
736 
737  return (Datum) 0;
738 }
739 
740 /*
741  * This utility function takes a C array of Oids, and returns a Datum
742  * pointing to a one-dimensional Postgres array of regtypes. An empty
743  * array is returned as a zero-element array, not NULL.
744  */
745 static Datum
746 build_regtype_array(Oid *param_types, int num_params)
747 {
748  Datum *tmp_ary;
749  ArrayType *result;
750  int i;
751 
752  tmp_ary = palloc_array(Datum, num_params);
753 
754  for (i = 0; i < num_params; i++)
755  tmp_ary[i] = ObjectIdGetDatum(param_types[i]);
756 
757  result = construct_array_builtin(tmp_ary, num_params, REGTYPEOID);
758  return PointerGetDatum(result);
759 }
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3374
static HTAB * prepared_queries
Definition: prepare.c:44
void DropPreparedStatement(const char *stmt_name, bool showError)
Definition: prepare.c:516
void PrepareQuery(ParseState *pstate, PrepareStmt *stmt, int stmt_location, int stmt_len)
Definition: prepare.c:56
static void InitQueryHashTable(void)
Definition: prepare.c:369
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:431
TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt)
Definition: prepare.c:463
Datum pg_prepared_statement(PG_FUNCTION_ARGS)
Definition: prepare.c:684
static ParamListInfo EvaluateParams(ParseState *pstate, PreparedStatement *pstmt, List *params, EState *estate)
Definition: prepare.c:278
void StorePreparedStatement(const char *stmt_name, CachedPlanSource *plansource, bool from_sql)
Definition: prepare.c:389
static Datum build_regtype_array(Oid *param_types, int num_params)
Definition: prepare.c:746
void ExecuteQuery(ParseState *pstate, ExecuteStmt *stmt, IntoClause *intoClause, ParamListInfo params, DestReceiver *dest, QueryCompletion *qc)
Definition: prepare.c:147
void ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: prepare.c:568
void DropAllPreparedStatements(void)
Definition: prepare.c:537
List * FetchPreparedStatementTargetList(PreparedStatement *stmt)
Definition: prepare.c:486
void DeallocateQuery(DeallocateStmt *stmt)
Definition: prepare.c:502
static Datum values[MAXATTR]
Definition: bootstrap.c:152
#define CStringGetTextDatum(s)
Definition: builtins.h:97
int GetIntoRelEFlags(IntoClause *intoClause)
Definition: createas.c:370
int64 TimestampTz
Definition: timestamp.h:39
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1395
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition: execExpr.c:806
EState * CreateExecutorState(void)
Definition: execUtils.c:88
void FreeExecutorState(EState *estate)
Definition: execUtils.c:189
#define GetPerTupleExprContext(estate)
Definition: executor.h:550
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:348
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:568
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:5076
void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:478
#define palloc_array(type, count)
Definition: fe_memutils.h:64
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define HASH_STRINGS
Definition: hsearch.h:96
@ HASH_FIND
Definition: hsearch.h:113
@ HASH_REMOVE
Definition: hsearch.h:115
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_ELEM
Definition: hsearch.h:95
#define stmt
Definition: indent_codes.h:59
#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
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
Definition: mcxt.c:774
MemoryContext CurrentMemoryContext
Definition: mcxt.c:131
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1670
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1320
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:223
@ CMD_UTILITY
Definition: nodes.h:260
@ CMD_SELECT
Definition: nodes.h:255
#define makeNode(_type_)
Definition: nodes.h:155
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
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:111
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:39
@ EXPR_KIND_EXECUTE_PARAMETER
Definition: parse_node.h:76
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
#define FETCH_ALL
Definition: parsenodes.h:3179
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3144
#define NAMEDATALEN
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:526
List * CachedPlanGetTargetList(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:1640
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:482
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
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1168
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1291
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
List * pg_analyze_and_rewrite_varparams(RawStmt *parsetree, const char *query_string, Oid **paramTypes, int *numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:710
#define Int64GetDatumFast(X)
Definition: postgres.h:554
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition: pquery.c:433
bool PortalRun(Portal portal, long count, bool isTopLevel, bool run_once, DestReceiver *dest, DestReceiver *altdest, QueryCompletion *qc)
Definition: pquery.c:684
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:692
@ COERCION_ASSIGNMENT
Definition: primnodes.h:671
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:770
CommandTag commandTag
Definition: plancache.h:101
const char * query_string
Definition: plancache.h:100
TupleDesc resultDesc
Definition: plancache.h:108
int64 num_custom_plans
Definition: plancache.h:133
int64 num_generic_plans
Definition: plancache.h:134
List * stmt_list
Definition: plancache.h:150
ParamListInfo es_param_list_info
Definition: execnodes.h:659
List * params
Definition: parsenodes.h:3902
char * name
Definition: parsenodes.h:3901
bool memory
Definition: explain.h:48
bool buffers
Definition: explain.h:44
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
Definition: dynahash.c:220
bool skipData
Definition: primnodes.h:156
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
const char * p_sourcetext
Definition: parse_node.h:193
CmdType commandType
Definition: plannodes.h:52
Node * utilityStmt
Definition: plannodes.h:95
MemoryContext portalContext
Definition: portal.h:120
bool visible
Definition: portal.h:205
char stmt_name[NAMEDATALEN]
Definition: prepare.h:30
TimestampTz prepare_time
Definition: prepare.h:33
CachedPlanSource * plansource
Definition: prepare.h:31
int stmt_len
Definition: parsenodes.h:1875
Node * stmt
Definition: parsenodes.h:1873
int stmt_location
Definition: parsenodes.h:1874
TupleDesc setDesc
Definition: execnodes.h:340
Tuplestorestate * setResult
Definition: execnodes.h:339
FormData_pg_attribute attrs[FLEXIBLE_ARRAY_MEMBER]
Definition: tupdesc.h:87
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:750
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2359
static Datum TimestampTzGetDatum(TimestampTz X)
Definition: timestamp.h:52
TimestampTz GetCurrentStatementStartTimestamp(void)
Definition: xact.c:865