1 /*-------------------------------------------------------------------------
4 * Prepareable SQL statements via PREPARE, EXECUTE and DEALLOCATE
6 * This module also implements storage of prepared statements that are
7 * accessed via the extended FE/BE query protocol.
10 * Copyright (c) 2002-2008, PostgreSQL Global Development Group
15 *-------------------------------------------------------------------------
19 #include "access/xact.h"
20 #include "catalog/pg_type.h"
21 #include "commands/explain.h"
22 #include "commands/prepare.h"
23 #include "miscadmin.h"
24 #include "nodes/nodeFuncs.h"
25 #include "parser/analyze.h"
26 #include "parser/parse_coerce.h"
27 #include "parser/parse_expr.h"
28 #include "parser/parse_type.h"
29 #include "rewrite/rewriteHandler.h"
30 #include "tcop/pquery.h"
31 #include "tcop/tcopprot.h"
32 #include "tcop/utility.h"
33 #include "utils/builtins.h"
34 #include "utils/memutils.h"
35 #include "utils/snapmgr.h"
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.
44 static HTAB
*prepared_queries
= NULL
;
46 static void InitQueryHashTable(void);
47 static ParamListInfo
EvaluateParams(PreparedStatement
*pstmt
, List
*params
,
48 const char *queryString
, EState
*estate
);
49 static Datum
build_regtype_array(Oid
*param_types
, int num_params
);
52 * Implements the 'PREPARE' utility statement.
55 PrepareQuery(PrepareStmt
*stmt
, const char *queryString
)
65 * Disallow empty-string statement name (conflicts with protocol-level
68 if (!stmt
->name
|| stmt
->name
[0] == '\0')
70 (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION
),
71 errmsg("invalid statement name: must not be empty")));
73 /* Transform list of TypeNames to array of type OIDs */
74 nargs
= list_length(stmt
->argtypes
);
82 * typenameTypeId wants a ParseState to carry the source query string.
83 * Is it worth refactoring its API to avoid this?
85 pstate
= make_parsestate(NULL
);
86 pstate
->p_sourcetext
= queryString
;
88 argtypes
= (Oid
*) palloc(nargs
* sizeof(Oid
));
91 foreach(l
, stmt
->argtypes
)
93 TypeName
*tn
= lfirst(l
);
94 Oid toid
= typenameTypeId(pstate
, tn
, NULL
);
101 * Analyze the statement using these parameter types (any parameters
102 * passed in from above us will not be visible to it), allowing
103 * information about unknown parameters to be deduced from context.
105 * Because parse analysis scribbles on the raw querytree, we must make a
106 * copy to ensure we have a pristine raw tree to cache. FIXME someday.
108 query
= parse_analyze_varparams((Node
*) copyObject(stmt
->query
),
113 * Check that all parameter types were determined.
115 for (i
= 0; i
< nargs
; i
++)
117 Oid argtype
= argtypes
[i
];
119 if (argtype
== InvalidOid
|| argtype
== UNKNOWNOID
)
121 (errcode(ERRCODE_INDETERMINATE_DATATYPE
),
122 errmsg("could not determine data type of parameter $%d",
127 * grammar only allows OptimizableStmt, so this check should be redundant
129 switch (query
->commandType
)
139 (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION
),
140 errmsg("utility statements cannot be prepared")));
144 /* Rewrite the query. The result could be 0, 1, or many queries. */
145 query_list
= QueryRewrite(query
);
147 /* Generate plans for queries. Snapshot is already set. */
148 plan_list
= pg_plan_queries(query_list
, 0, NULL
, false);
153 StorePreparedStatement(stmt
->name
,
156 CreateCommandTag((Node
*) query
),
159 0, /* default cursor options */
165 * Implements the 'EXECUTE' utility statement.
167 * Note: this is one of very few places in the code that needs to deal with
168 * two query strings at once. The passed-in queryString is that of the
169 * EXECUTE, which we might need for error reporting while processing the
170 * parameter expressions. The query_string that we copy from the plan
171 * source is that of the original PREPARE.
174 ExecuteQuery(ExecuteStmt
*stmt
, const char *queryString
,
175 ParamListInfo params
,
176 DestReceiver
*dest
, char *completionTag
)
178 PreparedStatement
*entry
;
181 ParamListInfo paramLI
= NULL
;
182 EState
*estate
= NULL
;
186 /* Look it up in the hash table */
187 entry
= FetchPreparedStatement(stmt
->name
, true);
189 /* Shouldn't have a non-fully-planned plancache entry */
190 if (!entry
->plansource
->fully_planned
)
191 elog(ERROR
, "EXECUTE does not support unplanned prepared statements");
192 /* Shouldn't get any non-fixed-result cached plan, either */
193 if (!entry
->plansource
->fixed_result
)
194 elog(ERROR
, "EXECUTE does not support variable-result cached plans");
196 /* Evaluate parameters, if any */
197 if (entry
->plansource
->num_params
> 0)
200 * Need an EState to evaluate parameters; must not delete it till end
201 * of query, in case parameters are pass-by-reference.
203 estate
= CreateExecutorState();
204 estate
->es_param_list_info
= params
;
205 paramLI
= EvaluateParams(entry
, stmt
->params
,
206 queryString
, estate
);
209 /* Create a new portal to run the query in */
210 portal
= CreateNewPortal();
211 /* Don't display the portal in pg_cursors, it is for internal use only */
212 portal
->visible
= false;
214 /* Copy the plan's saved query string into the portal's memory */
215 query_string
= MemoryContextStrdup(PortalGetHeapMemory(portal
),
216 entry
->plansource
->query_string
);
219 * For CREATE TABLE / AS EXECUTE, we must make a copy of the stored query
220 * so that we can modify its destination (yech, but this has always been
221 * ugly). For regular EXECUTE we can just use the cached query, since the
222 * executor is read-only.
226 MemoryContext oldContext
;
229 /* Replan if needed, and increment plan refcount transiently */
230 cplan
= RevalidateCachedPlan(entry
->plansource
, true);
232 /* Copy plan into portal's context, and modify */
233 oldContext
= MemoryContextSwitchTo(PortalGetHeapMemory(portal
));
235 plan_list
= copyObject(cplan
->stmt_list
);
237 if (list_length(plan_list
) != 1)
239 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
240 errmsg("prepared statement is not a SELECT")));
241 pstmt
= (PlannedStmt
*) linitial(plan_list
);
242 if (!IsA(pstmt
, PlannedStmt
) ||
243 pstmt
->commandType
!= CMD_SELECT
||
244 pstmt
->utilityStmt
!= NULL
)
246 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
247 errmsg("prepared statement is not a SELECT")));
248 pstmt
->intoClause
= copyObject(stmt
->into
);
250 MemoryContextSwitchTo(oldContext
);
252 /* We no longer need the cached plan refcount ... */
253 ReleaseCachedPlan(cplan
, true);
254 /* ... and we don't want the portal to depend on it, either */
259 /* Replan if needed, and increment plan refcount for portal */
260 cplan
= RevalidateCachedPlan(entry
->plansource
, false);
261 plan_list
= cplan
->stmt_list
;
264 PortalDefineQuery(portal
,
267 entry
->plansource
->commandTag
,
272 * Run the portal to completion.
274 PortalStart(portal
, paramLI
, GetActiveSnapshot());
276 (void) PortalRun(portal
, FETCH_ALL
, false, dest
, dest
, completionTag
);
278 PortalDrop(portal
, false);
281 FreeExecutorState(estate
);
283 /* No need to pfree other memory, MemoryContext will be reset */
287 * EvaluateParams: evaluate a list of parameters.
289 * pstmt: statement we are getting parameters for.
290 * params: list of given parameter expressions (raw parser output!)
291 * queryString: source text for error messages.
292 * estate: executor state to use.
294 * Returns a filled-in ParamListInfo -- this can later be passed to
295 * CreateQueryDesc(), which allows the executor to make use of the parameters
296 * during query execution.
299 EvaluateParams(PreparedStatement
*pstmt
, List
*params
,
300 const char *queryString
, EState
*estate
)
302 Oid
*param_types
= pstmt
->plansource
->param_types
;
303 int num_params
= pstmt
->plansource
->num_params
;
304 int nparams
= list_length(params
);
306 ParamListInfo paramLI
;
311 if (nparams
!= num_params
)
313 (errcode(ERRCODE_SYNTAX_ERROR
),
314 errmsg("wrong number of parameters for prepared statement \"%s\"",
316 errdetail("Expected %d parameters but got %d.",
317 num_params
, nparams
)));
319 /* Quick exit if no parameters */
324 * We have to run parse analysis for the expressions. Since the parser is
325 * not cool about scribbling on its input, copy first.
327 params
= (List
*) copyObject(params
);
329 pstate
= make_parsestate(NULL
);
330 pstate
->p_sourcetext
= queryString
;
335 Node
*expr
= lfirst(l
);
336 Oid expected_type_id
= param_types
[i
];
339 expr
= transformExpr(pstate
, expr
);
341 /* Cannot contain subselects or aggregates */
342 if (pstate
->p_hasSubLinks
)
344 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
345 errmsg("cannot use subquery in EXECUTE parameter")));
346 if (pstate
->p_hasAggs
)
348 (errcode(ERRCODE_GROUPING_ERROR
),
349 errmsg("cannot use aggregate function in EXECUTE parameter")));
351 given_type_id
= exprType(expr
);
353 expr
= coerce_to_target_type(pstate
, expr
, given_type_id
,
354 expected_type_id
, -1,
356 COERCE_IMPLICIT_CAST
,
361 (errcode(ERRCODE_DATATYPE_MISMATCH
),
362 errmsg("parameter $%d of type %s cannot be coerced to the expected type %s",
364 format_type_be(given_type_id
),
365 format_type_be(expected_type_id
)),
366 errhint("You will need to rewrite or cast the expression.")));
372 /* Prepare the expressions for execution */
373 exprstates
= (List
*) ExecPrepareExpr((Expr
*) params
, estate
);
375 /* sizeof(ParamListInfoData) includes the first array element */
376 paramLI
= (ParamListInfo
)
377 palloc(sizeof(ParamListInfoData
) +
378 (num_params
- 1) *sizeof(ParamExternData
));
379 paramLI
->numParams
= num_params
;
382 foreach(l
, exprstates
)
384 ExprState
*n
= lfirst(l
);
385 ParamExternData
*prm
= ¶mLI
->params
[i
];
387 prm
->ptype
= param_types
[i
];
389 prm
->value
= ExecEvalExprSwitchContext(n
,
390 GetPerTupleExprContext(estate
),
402 * Initialize query hash table upon first use.
405 InitQueryHashTable(void)
409 MemSet(&hash_ctl
, 0, sizeof(hash_ctl
));
411 hash_ctl
.keysize
= NAMEDATALEN
;
412 hash_ctl
.entrysize
= sizeof(PreparedStatement
);
414 prepared_queries
= hash_create("Prepared Queries",
421 * Store all the data pertaining to a query in the hash table using
422 * the specified key. All the given data is copied into either the hashtable
423 * entry or the underlying plancache entry, so the caller can dispose of its
426 * Exception: commandTag is presumed to be a pointer to a constant string,
427 * or possibly NULL, so it need not be copied. Note that commandTag should
428 * be NULL only if the original query (before rewriting) was empty.
431 StorePreparedStatement(const char *stmt_name
,
432 Node
*raw_parse_tree
,
433 const char *query_string
,
434 const char *commandTag
,
441 PreparedStatement
*entry
;
442 CachedPlanSource
*plansource
;
445 /* Initialize the hash table, if necessary */
446 if (!prepared_queries
)
447 InitQueryHashTable();
449 /* Check for pre-existing entry of same name */
450 hash_search(prepared_queries
, stmt_name
, HASH_FIND
, &found
);
454 (errcode(ERRCODE_DUPLICATE_PSTATEMENT
),
455 errmsg("prepared statement \"%s\" already exists",
458 /* Create a plancache entry */
459 plansource
= CreateCachedPlan(raw_parse_tree
,
469 /* Now we can add entry to hash table */
470 entry
= (PreparedStatement
*) hash_search(prepared_queries
,
475 /* Shouldn't get a duplicate entry */
477 elog(ERROR
, "duplicate prepared statement \"%s\"",
480 /* Fill in the hash table entry */
481 entry
->plansource
= plansource
;
482 entry
->from_sql
= from_sql
;
483 entry
->prepare_time
= GetCurrentStatementStartTimestamp();
487 * Lookup an existing query in the hash table. If the query does not
488 * actually exist, throw ereport(ERROR) or return NULL per second parameter.
490 * Note: this does not force the referenced plancache entry to be valid,
491 * since not all callers care.
494 FetchPreparedStatement(const char *stmt_name
, bool throwError
)
496 PreparedStatement
*entry
;
499 * If the hash table hasn't been initialized, it can't be storing
500 * anything, therefore it couldn't possibly store our plan.
502 if (prepared_queries
)
503 entry
= (PreparedStatement
*) hash_search(prepared_queries
,
510 if (!entry
&& throwError
)
512 (errcode(ERRCODE_UNDEFINED_PSTATEMENT
),
513 errmsg("prepared statement \"%s\" does not exist",
520 * Given a prepared statement, determine the result tupledesc it will
521 * produce. Returns NULL if the execution will not return tuples.
523 * Note: the result is created or copied into current memory context.
526 FetchPreparedStatementResultDesc(PreparedStatement
*stmt
)
529 * Since we don't allow prepared statements' result tupdescs to change,
530 * there's no need for a revalidate call here.
532 Assert(stmt
->plansource
->fixed_result
);
533 if (stmt
->plansource
->resultDesc
)
534 return CreateTupleDescCopy(stmt
->plansource
->resultDesc
);
540 * Given a prepared statement that returns tuples, extract the query
541 * targetlist. Returns NIL if the statement doesn't have a determinable
544 * Note: this is pretty ugly, but since it's only used in corner cases like
545 * Describe Statement on an EXECUTE command, we don't worry too much about
549 FetchPreparedStatementTargetList(PreparedStatement
*stmt
)
554 /* No point in looking if it doesn't return tuples */
555 if (stmt
->plansource
->resultDesc
== NULL
)
558 /* Make sure the plan is up to date */
559 cplan
= RevalidateCachedPlan(stmt
->plansource
, true);
561 /* Get the primary statement and find out what it returns */
562 tlist
= FetchStatementTargetList(PortalListGetPrimaryStmt(cplan
->stmt_list
));
564 /* Copy into caller's context so we can release the plancache entry */
565 tlist
= (List
*) copyObject(tlist
);
567 ReleaseCachedPlan(cplan
, true);
573 * Implements the 'DEALLOCATE' utility statement: deletes the
574 * specified plan from storage.
577 DeallocateQuery(DeallocateStmt
*stmt
)
580 DropPreparedStatement(stmt
->name
, true);
582 DropAllPreparedStatements();
586 * Internal version of DEALLOCATE
588 * If showError is false, dropping a nonexistent statement is a no-op.
591 DropPreparedStatement(const char *stmt_name
, bool showError
)
593 PreparedStatement
*entry
;
595 /* Find the query's hash table entry; raise error if wanted */
596 entry
= FetchPreparedStatement(stmt_name
, showError
);
600 /* Release the plancache entry */
601 DropCachedPlan(entry
->plansource
);
603 /* Now we can remove the hash table entry */
604 hash_search(prepared_queries
, entry
->stmt_name
, HASH_REMOVE
, NULL
);
609 * Drop all cached statements.
612 DropAllPreparedStatements(void)
615 PreparedStatement
*entry
;
618 if (!prepared_queries
)
621 /* walk over cache */
622 hash_seq_init(&seq
, prepared_queries
);
623 while ((entry
= hash_seq_search(&seq
)) != NULL
)
625 /* Release the plancache entry */
626 DropCachedPlan(entry
->plansource
);
628 /* Now we can remove the hash table entry */
629 hash_search(prepared_queries
, entry
->stmt_name
, HASH_REMOVE
, NULL
);
634 * Implements the 'EXPLAIN EXECUTE' utility statement.
637 ExplainExecuteQuery(ExecuteStmt
*execstmt
, ExplainStmt
*stmt
,
638 const char *queryString
,
639 ParamListInfo params
, TupOutputState
*tstate
)
641 PreparedStatement
*entry
;
645 ParamListInfo paramLI
= NULL
;
646 EState
*estate
= NULL
;
648 /* Look it up in the hash table */
649 entry
= FetchPreparedStatement(execstmt
->name
, true);
651 /* Shouldn't have a non-fully-planned plancache entry */
652 if (!entry
->plansource
->fully_planned
)
653 elog(ERROR
, "EXPLAIN EXECUTE does not support unplanned prepared statements");
654 /* Shouldn't get any non-fixed-result cached plan, either */
655 if (!entry
->plansource
->fixed_result
)
656 elog(ERROR
, "EXPLAIN EXECUTE does not support variable-result cached plans");
658 /* Replan if needed, and acquire a transient refcount */
659 cplan
= RevalidateCachedPlan(entry
->plansource
, true);
661 plan_list
= cplan
->stmt_list
;
663 /* Evaluate parameters, if any */
664 if (entry
->plansource
->num_params
)
667 * Need an EState to evaluate parameters; must not delete it till end
668 * of query, in case parameters are pass-by-reference.
670 estate
= CreateExecutorState();
671 estate
->es_param_list_info
= params
;
672 paramLI
= EvaluateParams(entry
, execstmt
->params
,
673 queryString
, estate
);
676 /* Explain each query */
677 foreach(p
, plan_list
)
679 PlannedStmt
*pstmt
= (PlannedStmt
*) lfirst(p
);
682 is_last_query
= (lnext(p
) == NULL
);
684 if (IsA(pstmt
, PlannedStmt
))
688 if (pstmt
->commandType
!= CMD_SELECT
||
689 pstmt
->utilityStmt
!= NULL
)
691 (errcode(ERRCODE_WRONG_OBJECT_TYPE
),
692 errmsg("prepared statement is not a SELECT")));
694 /* Copy the stmt so we can modify it */
695 pstmt
= copyObject(pstmt
);
697 pstmt
->intoClause
= execstmt
->into
;
700 ExplainOnePlan(pstmt
, paramLI
, stmt
, tstate
);
704 ExplainOneUtility((Node
*) pstmt
, stmt
, queryString
,
708 /* No need for CommandCounterIncrement, as ExplainOnePlan did it */
710 /* put a blank line between plans */
712 do_text_output_oneline(tstate
, "");
716 FreeExecutorState(estate
);
718 ReleaseCachedPlan(cplan
, true);
722 * This set returning function reads all the prepared statements and
723 * returns a set of (name, statement, prepare_time, param_types, from_sql).
726 pg_prepared_statement(PG_FUNCTION_ARGS
)
728 ReturnSetInfo
*rsinfo
= (ReturnSetInfo
*) fcinfo
->resultinfo
;
730 Tuplestorestate
*tupstore
;
731 MemoryContext per_query_ctx
;
732 MemoryContext oldcontext
;
734 /* check to see if caller supports us returning a tuplestore */
735 if (rsinfo
== NULL
|| !IsA(rsinfo
, ReturnSetInfo
))
737 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
738 errmsg("set-valued function called in context that cannot accept a set")));
739 if (!(rsinfo
->allowedModes
& SFRM_Materialize
))
741 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
742 errmsg("materialize mode required, but it is not " \
743 "allowed in this context")));
745 /* need to build tuplestore in query context */
746 per_query_ctx
= rsinfo
->econtext
->ecxt_per_query_memory
;
747 oldcontext
= MemoryContextSwitchTo(per_query_ctx
);
750 * build tupdesc for result tuples. This must match the definition of the
751 * pg_prepared_statements view in system_views.sql
753 tupdesc
= CreateTemplateTupleDesc(5, false);
754 TupleDescInitEntry(tupdesc
, (AttrNumber
) 1, "name",
756 TupleDescInitEntry(tupdesc
, (AttrNumber
) 2, "statement",
758 TupleDescInitEntry(tupdesc
, (AttrNumber
) 3, "prepare_time",
759 TIMESTAMPTZOID
, -1, 0);
760 TupleDescInitEntry(tupdesc
, (AttrNumber
) 4, "parameter_types",
761 REGTYPEARRAYOID
, -1, 0);
762 TupleDescInitEntry(tupdesc
, (AttrNumber
) 5, "from_sql",
766 * We put all the tuples into a tuplestore in one scan of the hashtable.
767 * This avoids any issue of the hashtable possibly changing between calls.
769 tupstore
= tuplestore_begin_heap(true, false, work_mem
);
771 /* hash table might be uninitialized */
772 if (prepared_queries
)
774 HASH_SEQ_STATUS hash_seq
;
775 PreparedStatement
*prep_stmt
;
777 hash_seq_init(&hash_seq
, prepared_queries
);
778 while ((prep_stmt
= hash_seq_search(&hash_seq
)) != NULL
)
783 /* generate junk in short-term context */
784 MemoryContextSwitchTo(oldcontext
);
786 MemSet(nulls
, 0, sizeof(nulls
));
788 values
[0] = CStringGetTextDatum(prep_stmt
->stmt_name
);
789 values
[1] = CStringGetTextDatum(prep_stmt
->plansource
->query_string
);
790 values
[2] = TimestampTzGetDatum(prep_stmt
->prepare_time
);
791 values
[3] = build_regtype_array(prep_stmt
->plansource
->param_types
,
792 prep_stmt
->plansource
->num_params
);
793 values
[4] = BoolGetDatum(prep_stmt
->from_sql
);
795 /* switch to appropriate context while storing the tuple */
796 MemoryContextSwitchTo(per_query_ctx
);
797 tuplestore_putvalues(tupstore
, tupdesc
, values
, nulls
);
801 /* clean up and return the tuplestore */
802 tuplestore_donestoring(tupstore
);
804 MemoryContextSwitchTo(oldcontext
);
806 rsinfo
->returnMode
= SFRM_Materialize
;
807 rsinfo
->setResult
= tupstore
;
808 rsinfo
->setDesc
= tupdesc
;
814 * This utility function takes a C array of Oids, and returns a Datum
815 * pointing to a one-dimensional Postgres array of regtypes. An empty
816 * array is returned as a zero-element array, not NULL.
819 build_regtype_array(Oid
*param_types
, int num_params
)
825 tmp_ary
= (Datum
*) palloc(num_params
* sizeof(Datum
));
827 for (i
= 0; i
< num_params
; i
++)
828 tmp_ary
[i
] = ObjectIdGetDatum(param_types
[i
]);
830 /* XXX: this hardcodes assumptions about the regtype type */
831 result
= construct_array(tmp_ary
, num_params
, REGTYPEOID
, 4, true, 'i');
832 return PointerGetDatum(result
);