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-2003, PostgreSQL Global Development Group
13 * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.25 2004/01/07 18:56:25 neilc Exp $
15 *-------------------------------------------------------------------------
19 #include "commands/explain.h"
20 #include "commands/prepare.h"
21 #include "executor/executor.h"
22 #include "utils/guc.h"
23 #include "optimizer/planner.h"
24 #include "rewrite/rewriteHandler.h"
25 #include "tcop/pquery.h"
26 #include "tcop/tcopprot.h"
27 #include "tcop/utility.h"
28 #include "utils/hsearch.h"
29 #include "utils/memutils.h"
33 * The hash table in which prepared queries are stored. This is
34 * per-backend: query plans are not shared between backends.
35 * The keys for this hash table are the arguments to PREPARE and EXECUTE
36 * (statement names); the entries are PreparedStatement structs.
38 static HTAB *prepared_queries = NULL;
40 static void InitQueryHashTable(void);
41 static ParamListInfo EvaluateParams(EState *estate,
42 List *params, List *argtypes);
45 * Implements the 'PREPARE' utility statement.
48 PrepareQuery(PrepareStmt *stmt)
50 const char *commandTag;
55 * Disallow empty-string statement name (conflicts with protocol-level
58 if (!stmt->name || stmt->name[0] == '\0')
60 (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION),
61 errmsg("invalid statement name: must not be empty")));
63 switch (stmt->query->commandType)
66 commandTag = "SELECT";
69 commandTag = "INSERT";
72 commandTag = "UPDATE";
75 commandTag = "DELETE";
79 (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION),
80 errmsg("utility statements cannot be prepared")));
81 commandTag = NULL; /* keep compiler quiet */
86 * Parse analysis is already done, but we must still rewrite and plan
90 /* Rewrite the query. The result could be 0, 1, or many queries. */
91 query_list = QueryRewrite(stmt->query);
93 /* Generate plans for queries. Snapshot is already set. */
94 plan_list = pg_plan_queries(query_list, false);
96 /* Save the results. */
97 StorePreparedStatement(stmt->name,
98 NULL, /* text form not available */
106 * Implements the 'EXECUTE' utility statement.
109 ExecuteQuery(ExecuteStmt *stmt, DestReceiver *dest)
111 PreparedStatement *entry;
115 MemoryContext qcontext;
116 ParamListInfo paramLI = NULL;
117 EState *estate = NULL;
120 /* Look it up in the hash table */
121 entry = FetchPreparedStatement(stmt->name, true);
123 query_string = entry->query_string;
124 query_list = entry->query_list;
125 plan_list = entry->plan_list;
126 qcontext = entry->context;
128 Assert(length(query_list) == length(plan_list));
130 /* Evaluate parameters, if any */
131 if (entry->argtype_list != NIL)
134 * Need an EState to evaluate parameters; must not delete it till
135 * end of query, in case parameters are pass-by-reference.
137 estate = CreateExecutorState();
138 paramLI = EvaluateParams(estate, stmt->params, entry->argtype_list);
142 * Create a new portal to run the query in
144 portal = CreateNewPortal();
147 * For CREATE TABLE / AS EXECUTE, make a copy of the stored query so
148 * that we can modify its destination (yech, but this has always been
149 * ugly). For regular EXECUTE we can just use the stored query where
150 * it sits, since the executor is read-only.
154 MemoryContext oldContext;
157 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
160 query_string = pstrdup(query_string);
161 query_list = copyObject(query_list);
162 plan_list = copyObject(plan_list);
163 qcontext = PortalGetHeapMemory(portal);
165 if (length(query_list) != 1)
167 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
168 errmsg("prepared statement is not a SELECT")));
169 query = (Query *) lfirst(query_list);
170 if (query->commandType != CMD_SELECT)
172 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
173 errmsg("prepared statement is not a SELECT")));
174 query->into = copyObject(stmt->into);
176 MemoryContextSwitchTo(oldContext);
179 PortalDefineQuery(portal,
187 * Run the portal to completion.
189 PortalStart(portal, paramLI);
191 (void) PortalRun(portal, FETCH_ALL, dest, dest, NULL);
193 PortalDrop(portal, false);
196 FreeExecutorState(estate);
198 /* No need to pfree other memory, MemoryContext will be reset */
202 * Evaluates a list of parameters, using the given executor state. It
203 * requires a list of the parameter values themselves, and a list of
204 * their types. It returns a filled-in ParamListInfo -- this can later
205 * be passed to CreateQueryDesc(), which allows the executor to make use
206 * of the parameters during query execution.
209 EvaluateParams(EState *estate, List *params, List *argtypes)
211 int nargs = length(argtypes);
212 ParamListInfo paramLI;
217 /* Parser should have caught this error, but check for safety */
218 if (length(params) != nargs)
219 elog(ERROR, "wrong number of arguments");
221 exprstates = (List *) ExecPrepareExpr((Expr *) params, estate);
223 paramLI = (ParamListInfo)
224 palloc0((nargs + 1) * sizeof(ParamListInfoData));
226 foreach(l, exprstates)
228 ExprState *n = lfirst(l);
231 paramLI[i].value = ExecEvalExprSwitchContext(n,
232 GetPerTupleExprContext(estate),
235 paramLI[i].kind = PARAM_NUM;
236 paramLI[i].id = i + 1;
237 paramLI[i].isnull = isNull;
242 paramLI[i].kind = PARAM_INVALID;
249 * Initialize query hash table upon first use.
252 InitQueryHashTable(void)
256 MemSet(&hash_ctl, 0, sizeof(hash_ctl));
258 hash_ctl.keysize = NAMEDATALEN;
259 hash_ctl.entrysize = sizeof(PreparedStatement);
261 prepared_queries = hash_create("Prepared Queries",
266 if (!prepared_queries)
267 elog(ERROR, "could not create hash table");
271 * Store all the data pertaining to a query in the hash table using
272 * the specified key. A copy of the data is made in a memory context belonging
273 * to the hash entry, so the caller can dispose of their copy.
275 * Exception: commandTag is presumed to be a pointer to a constant string,
276 * or possibly NULL, so it need not be copied. Note that commandTag should
277 * be NULL only if the original query (before rewriting) was empty.
280 StorePreparedStatement(const char *stmt_name,
281 const char *query_string,
282 const char *commandTag,
287 PreparedStatement *entry;
288 MemoryContext oldcxt,
291 char key[NAMEDATALEN];
294 /* Initialize the hash table, if necessary */
295 if (!prepared_queries)
296 InitQueryHashTable();
298 /* Check for pre-existing entry of same name */
299 /* See notes in FetchPreparedStatement */
300 MemSet(key, 0, sizeof(key));
301 strncpy(key, stmt_name, sizeof(key));
303 hash_search(prepared_queries, key, HASH_FIND, &found);
307 (errcode(ERRCODE_DUPLICATE_PSTATEMENT),
308 errmsg("prepared statement \"%s\" already exists",
311 /* Make a permanent memory context for the hashtable entry */
312 entrycxt = AllocSetContextCreate(TopMemoryContext,
314 ALLOCSET_SMALL_MINSIZE,
315 ALLOCSET_SMALL_INITSIZE,
316 ALLOCSET_SMALL_MAXSIZE);
318 oldcxt = MemoryContextSwitchTo(entrycxt);
321 * We need to copy the data so that it is stored in the correct memory
322 * context. Do this before making hashtable entry, so that an
323 * out-of-memory failure only wastes memory and doesn't leave us with
324 * an incomplete (ie corrupt) hashtable entry.
326 qstring = query_string ? pstrdup(query_string) : NULL;
327 query_list = (List *) copyObject(query_list);
328 plan_list = (List *) copyObject(plan_list);
329 argtype_list = listCopy(argtype_list);
331 /* Now we can add entry to hash table */
332 entry = (PreparedStatement *) hash_search(prepared_queries,
337 /* Shouldn't get a failure, nor a duplicate entry */
339 elog(ERROR, "could not store prepared statement \"%s\"",
342 /* Fill in the hash table entry with copied data */
343 entry->query_string = qstring;
344 entry->commandTag = commandTag;
345 entry->query_list = query_list;
346 entry->plan_list = plan_list;
347 entry->argtype_list = argtype_list;
348 entry->context = entrycxt;
350 MemoryContextSwitchTo(oldcxt);
354 * Lookup an existing query in the hash table. If the query does not
355 * actually exist, throw ereport(ERROR) or return NULL per second parameter.
358 FetchPreparedStatement(const char *stmt_name, bool throwError)
360 char key[NAMEDATALEN];
361 PreparedStatement *entry;
364 * If the hash table hasn't been initialized, it can't be storing
365 * anything, therefore it couldn't possibly store our plan.
367 if (prepared_queries)
370 * We can't just use the statement name as supplied by the user:
371 * the hash package is picky enough that it needs to be
372 * NULL-padded out to the appropriate length to work correctly.
374 MemSet(key, 0, sizeof(key));
375 strncpy(key, stmt_name, sizeof(key));
377 entry = (PreparedStatement *) hash_search(prepared_queries,
385 if (!entry && throwError)
387 (errcode(ERRCODE_UNDEFINED_PSTATEMENT),
388 errmsg("prepared statement \"%s\" does not exist",
395 * Look up a prepared statement given the name (giving error if not found).
396 * If found, return the list of argument type OIDs.
399 FetchPreparedStatementParams(const char *stmt_name)
401 PreparedStatement *entry;
403 entry = FetchPreparedStatement(stmt_name, true);
405 return entry->argtype_list;
409 * Given a prepared statement, determine the result tupledesc it will
410 * produce. Returns NULL if the execution will not return tuples.
412 * Note: the result is created or copied into current memory context.
415 FetchPreparedStatementResultDesc(PreparedStatement *stmt)
419 switch (ChoosePortalStrategy(stmt->query_list))
421 case PORTAL_ONE_SELECT:
422 query = (Query *) lfirst(stmt->query_list);
423 return ExecCleanTypeFromTL(query->targetList, false);
425 case PORTAL_UTIL_SELECT:
426 query = (Query *) lfirst(stmt->query_list);
427 return UtilityTupleDescriptor(query->utilityStmt);
429 case PORTAL_MULTI_QUERY:
430 /* will not return tuples */
437 * Implements the 'DEALLOCATE' utility statement: deletes the
438 * specified plan from storage.
441 DeallocateQuery(DeallocateStmt *stmt)
443 DropPreparedStatement(stmt->name, true);
447 * Internal version of DEALLOCATE
449 * If showError is false, dropping a nonexistent statement is a no-op.
452 DropPreparedStatement(const char *stmt_name, bool showError)
454 PreparedStatement *entry;
456 /* Find the query's hash table entry; raise error if wanted */
457 entry = FetchPreparedStatement(stmt_name, showError);
461 /* Drop any open portals that depend on this prepared statement */
462 Assert(MemoryContextIsValid(entry->context));
463 DropDependentPortals(entry->context);
465 /* Flush the context holding the subsidiary data */
466 MemoryContextDelete(entry->context);
468 /* Now we can remove the hash table entry */
469 hash_search(prepared_queries, entry->stmt_name, HASH_REMOVE, NULL);
474 * Implements the 'EXPLAIN EXECUTE' utility statement.
477 ExplainExecuteQuery(ExplainStmt *stmt, TupOutputState *tstate)
479 ExecuteStmt *execstmt = (ExecuteStmt *) stmt->query->utilityStmt;
480 PreparedStatement *entry;
484 ParamListInfo paramLI = NULL;
485 EState *estate = NULL;
487 /* explain.c should only call me for EXECUTE stmt */
488 Assert(execstmt && IsA(execstmt, ExecuteStmt));
490 /* Look it up in the hash table */
491 entry = FetchPreparedStatement(execstmt->name, true);
493 query_list = entry->query_list;
494 plan_list = entry->plan_list;
496 Assert(length(query_list) == length(plan_list));
498 /* Evaluate parameters, if any */
499 if (entry->argtype_list != NIL)
502 * Need an EState to evaluate parameters; must not delete it till
503 * end of query, in case parameters are pass-by-reference.
505 estate = CreateExecutorState();
506 paramLI = EvaluateParams(estate, execstmt->params,
507 entry->argtype_list);
510 /* Explain each query */
511 foreach(l, query_list)
513 Query *query = (Query *) lfirst(l);
514 Plan *plan = (Plan *) lfirst(plan_list);
517 plan_list = lnext(plan_list);
518 is_last_query = (plan_list == NIL);
520 if (query->commandType == CMD_UTILITY)
522 if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
523 do_text_output_oneline(tstate, "NOTIFY");
525 do_text_output_oneline(tstate, "UTILITY");
533 if (query->commandType != CMD_SELECT)
535 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
536 errmsg("prepared statement is not a SELECT")));
538 /* Copy the query so we can modify it */
539 query = copyObject(query);
541 query->into = execstmt->into;
544 /* Create a QueryDesc requesting no output */
545 qdesc = CreateQueryDesc(query, plan, None_Receiver,
546 paramLI, stmt->analyze);
548 ExplainOnePlan(qdesc, stmt, tstate);
551 /* No need for CommandCounterIncrement, as ExplainOnePlan did it */
553 /* put a blank line between plans */
555 do_text_output_oneline(tstate, "");
559 FreeExecutorState(estate);