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 "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "parser/analyze.h"
#include "parser/parse_coerce.h"
#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_type.h"
#include "rewrite/rewriteHandler.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, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
 
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 714 of file prepare.c.

715 {
716  Datum *tmp_ary;
717  ArrayType *result;
718  int i;
719 
720  tmp_ary = (Datum *) palloc(num_params * sizeof(Datum));
721 
722  for (i = 0; i < num_params; i++)
723  tmp_ary[i] = ObjectIdGetDatum(param_types[i]);
724 
725  /* XXX: this hardcodes assumptions about the regtype type */
726  result = construct_array(tmp_ary, num_params, REGTYPEOID,
727  4, true, TYPALIGN_INT);
728  return PointerGetDatum(result);
729 }
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3319
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1068
uintptr_t Datum
Definition: postgres.h:411
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define PointerGetDatum(X)
Definition: postgres.h:600

References construct_array(), i, ObjectIdGetDatum, palloc(), and PointerGetDatum.

Referenced by pg_prepared_statement().

◆ DeallocateQuery()

void DeallocateQuery ( DeallocateStmt stmt)

Definition at line 505 of file prepare.c.

506 {
507  if (stmt->name)
508  DropPreparedStatement(stmt->name, true);
509  else
511 }
void DropPreparedStatement(const char *stmt_name, bool showError)
Definition: prepare.c:519
void DropAllPreparedStatements(void)
Definition: prepare.c:540

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

Referenced by standard_ProcessUtility().

◆ DropAllPreparedStatements()

void DropAllPreparedStatements ( void  )

Definition at line 540 of file prepare.c.

541 {
542  HASH_SEQ_STATUS seq;
543  PreparedStatement *entry;
544 
545  /* nothing cached */
546  if (!prepared_queries)
547  return;
548 
549  /* walk over cache */
551  while ((entry = hash_seq_search(&seq)) != NULL)
552  {
553  /* Release the plancache entry */
554  DropCachedPlan(entry->plansource);
555 
556  /* Now we can remove the hash table entry */
558  }
559 }
static HTAB * prepared_queries
Definition: prepare.c:47
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
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
@ HASH_REMOVE
Definition: hsearch.h:115
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:498
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 519 of file prepare.c.

520 {
521  PreparedStatement *entry;
522 
523  /* Find the query's hash table entry; raise error if wanted */
524  entry = FetchPreparedStatement(stmt_name, showError);
525 
526  if (entry)
527  {
528  /* Release the plancache entry */
529  DropCachedPlan(entry->plansource);
530 
531  /* Now we can remove the hash table entry */
533  }
534 }
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:434

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 281 of file prepare.c.

283 {
284  Oid *param_types = pstmt->plansource->param_types;
285  int num_params = pstmt->plansource->num_params;
286  int nparams = list_length(params);
287  ParamListInfo paramLI;
288  List *exprstates;
289  ListCell *l;
290  int i;
291 
292  if (nparams != num_params)
293  ereport(ERROR,
294  (errcode(ERRCODE_SYNTAX_ERROR),
295  errmsg("wrong number of parameters for prepared statement \"%s\"",
296  pstmt->stmt_name),
297  errdetail("Expected %d parameters but got %d.",
298  num_params, nparams)));
299 
300  /* Quick exit if no parameters */
301  if (num_params == 0)
302  return NULL;
303 
304  /*
305  * We have to run parse analysis for the expressions. Since the parser is
306  * not cool about scribbling on its input, copy first.
307  */
308  params = copyObject(params);
309 
310  i = 0;
311  foreach(l, params)
312  {
313  Node *expr = lfirst(l);
314  Oid expected_type_id = param_types[i];
315  Oid given_type_id;
316 
317  expr = transformExpr(pstate, expr, EXPR_KIND_EXECUTE_PARAMETER);
318 
319  given_type_id = exprType(expr);
320 
321  expr = coerce_to_target_type(pstate, expr, given_type_id,
322  expected_type_id, -1,
325  -1);
326 
327  if (expr == NULL)
328  ereport(ERROR,
329  (errcode(ERRCODE_DATATYPE_MISMATCH),
330  errmsg("parameter $%d of type %s cannot be coerced to the expected type %s",
331  i + 1,
332  format_type_be(given_type_id),
333  format_type_be(expected_type_id)),
334  errhint("You will need to rewrite or cast the expression."),
335  parser_errposition(pstate, exprLocation(lfirst(l)))));
336 
337  /* Take care of collations in the finished expression. */
338  assign_expr_collations(pstate, expr);
339 
340  lfirst(l) = expr;
341  i++;
342  }
343 
344  /* Prepare the expressions for execution */
345  exprstates = ExecPrepareExprList(params, estate);
346 
347  paramLI = makeParamList(num_params);
348 
349  i = 0;
350  foreach(l, exprstates)
351  {
352  ExprState *n = (ExprState *) lfirst(l);
353  ParamExternData *prm = &paramLI->params[i];
354 
355  prm->ptype = param_types[i];
356  prm->pflags = PARAM_FLAG_CONST;
358  GetPerTupleExprContext(estate),
359  &prm->isnull);
360 
361  i++;
362  }
363 
364  return paramLI;
365 }
int errdetail(const char *fmt,...)
Definition: elog.c:1037
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
List * ExecPrepareExprList(List *nodes, EState *estate)
Definition: execExpr.c:820
#define GetPerTupleExprContext(estate)
Definition: executor.h:537
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:335
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1343
#define copyObject(obj)
Definition: nodes.h:689
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:112
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
@ EXPR_KIND_EXECUTE_PARAMETER
Definition: parse_node.h:75
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
unsigned int Oid
Definition: postgres_ext.h:31
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:494
@ COERCION_ASSIGNMENT
Definition: primnodes.h:473
Definition: pg_list.h:51
Definition: nodes.h:574
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 150 of file prepare.c.

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

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(), 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().

◆ ExplainExecuteQuery()

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

Definition at line 571 of file prepare.c.

574 {
575  PreparedStatement *entry;
576  const char *query_string;
577  CachedPlan *cplan;
578  List *plan_list;
579  ListCell *p;
580  ParamListInfo paramLI = NULL;
581  EState *estate = NULL;
582  instr_time planstart;
583  instr_time planduration;
584  BufferUsage bufusage_start,
585  bufusage;
586 
587  if (es->buffers)
588  bufusage_start = pgBufferUsage;
589  INSTR_TIME_SET_CURRENT(planstart);
590 
591  /* Look it up in the hash table */
592  entry = FetchPreparedStatement(execstmt->name, true);
593 
594  /* Shouldn't find a non-fixed-result cached plan */
595  if (!entry->plansource->fixed_result)
596  elog(ERROR, "EXPLAIN EXECUTE does not support variable-result cached plans");
597 
598  query_string = entry->plansource->query_string;
599 
600  /* Evaluate parameters, if any */
601  if (entry->plansource->num_params)
602  {
603  ParseState *pstate;
604 
605  pstate = make_parsestate(NULL);
606  pstate->p_sourcetext = queryString;
607 
608  /*
609  * Need an EState to evaluate parameters; must not delete it till end
610  * of query, in case parameters are pass-by-reference. Note that the
611  * passed-in "params" could possibly be referenced in the parameter
612  * expressions.
613  */
614  estate = CreateExecutorState();
615  estate->es_param_list_info = params;
616 
617  paramLI = EvaluateParams(pstate, entry, execstmt->params, estate);
618  }
619 
620  /* Replan if needed, and acquire a transient refcount */
621  cplan = GetCachedPlan(entry->plansource, paramLI,
622  CurrentResourceOwner, queryEnv);
623 
624  INSTR_TIME_SET_CURRENT(planduration);
625  INSTR_TIME_SUBTRACT(planduration, planstart);
626 
627  /* calc differences of buffer counters. */
628  if (es->buffers)
629  {
630  memset(&bufusage, 0, sizeof(BufferUsage));
631  BufferUsageAccumDiff(&bufusage, &pgBufferUsage, &bufusage_start);
632  }
633 
634  plan_list = cplan->stmt_list;
635 
636  /* Explain each query */
637  foreach(p, plan_list)
638  {
639  PlannedStmt *pstmt = lfirst_node(PlannedStmt, p);
640 
641  if (pstmt->commandType != CMD_UTILITY)
642  ExplainOnePlan(pstmt, into, es, query_string, paramLI, queryEnv,
643  &planduration, (es->buffers ? &bufusage : NULL));
644  else
645  ExplainOneUtility(pstmt->utilityStmt, into, es, query_string,
646  paramLI, queryEnv);
647 
648  /* No need for CommandCounterIncrement, as ExplainOnePlan did it */
649 
650  /* Separate plans with an appropriate separator */
651  if (lnext(plan_list, p) != NULL)
653  }
654 
655  if (estate)
656  FreeExecutorState(estate);
657 
659 }
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:518
void ExplainSeparatePlans(ExplainState *es)
Definition: explain.c:4909
void ExplainOneUtility(Node *utilityStmt, IntoClause *into, ExplainState *es, const char *queryString, ParamListInfo params, QueryEnvironment *queryEnv)
Definition: explain.c:428
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
#define INSTR_TIME_SUBTRACT(x, y)
Definition: instr_time.h:170
struct timeval instr_time
Definition: instr_time.h:150
BufferUsage pgBufferUsage
Definition: instrument.c:20
void BufferUsageAccumDiff(BufferUsage *dst, const BufferUsage *add, const BufferUsage *sub)
Definition: instrument.c:246
@ CMD_UTILITY
Definition: nodes.h:726
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:43
#define lfirst_node(type, lc)
Definition: pg_list.h:172
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1264
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
bool buffers
Definition: explain.h:44
const char * p_sourcetext
Definition: parse_node.h:182
Node * utilityStmt
Definition: plannodes.h:87

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().

◆ FetchPreparedStatement()

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

Definition at line 434 of file prepare.c.

435 {
436  PreparedStatement *entry;
437 
438  /*
439  * If the hash table hasn't been initialized, it can't be storing
440  * anything, therefore it couldn't possibly store our plan.
441  */
442  if (prepared_queries)
444  stmt_name,
445  HASH_FIND,
446  NULL);
447  else
448  entry = NULL;
449 
450  if (!entry && throwError)
451  ereport(ERROR,
452  (errcode(ERRCODE_UNDEFINED_PSTATEMENT),
453  errmsg("prepared statement \"%s\" does not exist",
454  stmt_name)));
455 
456  return entry;
457 }
@ 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 466 of file prepare.c.

467 {
468  /*
469  * Since we don't allow prepared statements' result tupdescs to change,
470  * there's no need to worry about revalidating the cached plan here.
471  */
473  if (stmt->plansource->resultDesc)
475  else
476  return NULL;
477 }
Assert(fmt[strlen(fmt) - 1] !='\n')
TupleDesc resultDesc
Definition: plancache.h:108
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111

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

Referenced by UtilityTupleDescriptor().

◆ FetchPreparedStatementTargetList()

List* FetchPreparedStatementTargetList ( PreparedStatement stmt)

Definition at line 489 of file prepare.c.

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

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

Referenced by FetchStatementTargetList().

◆ InitQueryHashTable()

static void InitQueryHashTable ( void  )
static

Definition at line 372 of file prepare.c.

373 {
374  HASHCTL hash_ctl;
375 
376  hash_ctl.keysize = NAMEDATALEN;
377  hash_ctl.entrysize = sizeof(PreparedStatement);
378 
379  prepared_queries = hash_create("Prepared Queries",
380  32,
381  &hash_ctl,
383 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
#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 667 of file prepare.c.

668 {
669  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
670 
671  /*
672  * We put all the tuples into a tuplestore in one scan of the hashtable.
673  * This avoids any issue of the hashtable possibly changing between calls.
674  */
675  SetSingleFuncCall(fcinfo, 0);
676 
677  /* hash table might be uninitialized */
678  if (prepared_queries)
679  {
680  HASH_SEQ_STATUS hash_seq;
681  PreparedStatement *prep_stmt;
682 
683  hash_seq_init(&hash_seq, prepared_queries);
684  while ((prep_stmt = hash_seq_search(&hash_seq)) != NULL)
685  {
686  Datum values[7];
687  bool nulls[7];
688 
689  MemSet(nulls, 0, sizeof(nulls));
690 
691  values[0] = CStringGetTextDatum(prep_stmt->stmt_name);
693  values[2] = TimestampTzGetDatum(prep_stmt->prepare_time);
695  prep_stmt->plansource->num_params);
696  values[4] = BoolGetDatum(prep_stmt->from_sql);
699 
700  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
701  values, nulls);
702  }
703  }
704 
705  return (Datum) 0;
706 }
static Datum build_regtype_array(Oid *param_types, int num_params)
Definition: prepare.c:714
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
#define MemSet(start, val, len)
Definition: c.h:1008
void SetSingleFuncCall(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define Int64GetDatumFast(X)
Definition: postgres.h:804
#define BoolGetDatum(X)
Definition: postgres.h:446
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:317
Tuplestorestate * setResult
Definition: execnodes.h:316
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32

References BoolGetDatum, build_regtype_array(), CStringGetTextDatum, PreparedStatement::from_sql, hash_seq_init(), hash_seq_search(), Int64GetDatumFast, MemSet, CachedPlanSource::num_custom_plans, CachedPlanSource::num_generic_plans, CachedPlanSource::num_params, CachedPlanSource::param_types, PreparedStatement::plansource, PreparedStatement::prepare_time, prepared_queries, CachedPlanSource::query_string, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SetSingleFuncCall(), PreparedStatement::stmt_name, TimestampTzGetDatum, tuplestore_putvalues(), and values.

◆ PrepareQuery()

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

Definition at line 59 of file prepare.c.

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

References PrepareStmt::argtypes, CompleteCachedPlan(), CreateCachedPlan(), CreateCommandTag(), CURSOR_OPT_PARALLEL_OK, ereport, errcode(), errmsg(), ERROR, i, lfirst, list_length(), makeNode, PrepareStmt::name, ParseState::p_sourcetext, palloc(), pg_analyze_and_rewrite_varparams(), PrepareStmt::query, RawStmt::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 392 of file prepare.c.

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

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