Force a checkpoint in CREATE DATABASE before starting to copy the files,
[PostgreSQL.git] / src / backend / commands / portalcmds.c
blob9047cbcdece8a99272eb7cae4b4d4b2bc20feed1
1 /*-------------------------------------------------------------------------
3 * portalcmds.c
4 * Utility commands affecting portals (that is, SQL cursor commands)
6 * Note: see also tcop/pquery.c, which implements portal operations for
7 * the FE/BE protocol. This module uses pquery.c for some operations.
8 * And both modules depend on utils/mmgr/portalmem.c, which controls
9 * storage management for portals (but doesn't run any queries in them).
12 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
16 * IDENTIFICATION
17 * $PostgreSQL$
19 *-------------------------------------------------------------------------
22 #include "postgres.h"
24 #include <limits.h>
26 #include "access/xact.h"
27 #include "commands/portalcmds.h"
28 #include "executor/executor.h"
29 #include "tcop/pquery.h"
30 #include "utils/memutils.h"
31 #include "utils/snapmgr.h"
35 * PerformCursorOpen
36 * Execute SQL DECLARE CURSOR command.
38 * The query has already been through parse analysis, rewriting, and planning.
39 * When it gets here, it looks like a SELECT PlannedStmt, except that the
40 * utilityStmt field is set.
42 void
43 PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params,
44 const char *queryString, bool isTopLevel)
46 DeclareCursorStmt *cstmt = (DeclareCursorStmt *) stmt->utilityStmt;
47 Portal portal;
48 MemoryContext oldContext;
50 if (cstmt == NULL || !IsA(cstmt, DeclareCursorStmt))
51 elog(ERROR, "PerformCursorOpen called for non-cursor query");
54 * Disallow empty-string cursor name (conflicts with protocol-level
55 * unnamed portal).
57 if (!cstmt->portalname || cstmt->portalname[0] == '\0')
58 ereport(ERROR,
59 (errcode(ERRCODE_INVALID_CURSOR_NAME),
60 errmsg("invalid cursor name: must not be empty")));
63 * If this is a non-holdable cursor, we require that this statement has
64 * been executed inside a transaction block (or else, it would have no
65 * user-visible effect).
67 if (!(cstmt->options & CURSOR_OPT_HOLD))
68 RequireTransactionChain(isTopLevel, "DECLARE CURSOR");
71 * Create a portal and copy the plan and queryString into its memory.
73 portal = CreatePortal(cstmt->portalname, false, false);
75 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
77 stmt = copyObject(stmt);
78 stmt->utilityStmt = NULL; /* make it look like plain SELECT */
80 queryString = pstrdup(queryString);
82 PortalDefineQuery(portal,
83 NULL,
84 queryString,
85 "SELECT", /* cursor's query is always a SELECT */
86 list_make1(stmt),
87 NULL);
89 /*----------
90 * Also copy the outer portal's parameter list into the inner portal's
91 * memory context. We want to pass down the parameter values in case we
92 * had a command like
93 * DECLARE c CURSOR FOR SELECT ... WHERE foo = $1
94 * This will have been parsed using the outer parameter set and the
95 * parameter value needs to be preserved for use when the cursor is
96 * executed.
97 *----------
99 params = copyParamList(params);
101 MemoryContextSwitchTo(oldContext);
104 * Set up options for portal.
106 * If the user didn't specify a SCROLL type, allow or disallow scrolling
107 * based on whether it would require any additional runtime overhead to do
108 * so. Also, we disallow scrolling for FOR UPDATE cursors.
110 portal->cursorOptions = cstmt->options;
111 if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
113 if (stmt->rowMarks == NIL &&
114 ExecSupportsBackwardScan(stmt->planTree))
115 portal->cursorOptions |= CURSOR_OPT_SCROLL;
116 else
117 portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
121 * Start execution, inserting parameters if any.
123 PortalStart(portal, params, GetActiveSnapshot());
125 Assert(portal->strategy == PORTAL_ONE_SELECT);
128 * We're done; the query won't actually be run until PerformPortalFetch is
129 * called.
134 * PerformPortalFetch
135 * Execute SQL FETCH or MOVE command.
137 * stmt: parsetree node for command
138 * dest: where to send results
139 * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
140 * in which to store a command completion status string.
142 * completionTag may be NULL if caller doesn't want a status string.
144 void
145 PerformPortalFetch(FetchStmt *stmt,
146 DestReceiver *dest,
147 char *completionTag)
149 Portal portal;
150 long nprocessed;
153 * Disallow empty-string cursor name (conflicts with protocol-level
154 * unnamed portal).
156 if (!stmt->portalname || stmt->portalname[0] == '\0')
157 ereport(ERROR,
158 (errcode(ERRCODE_INVALID_CURSOR_NAME),
159 errmsg("invalid cursor name: must not be empty")));
161 /* get the portal from the portal name */
162 portal = GetPortalByName(stmt->portalname);
163 if (!PortalIsValid(portal))
165 ereport(ERROR,
166 (errcode(ERRCODE_UNDEFINED_CURSOR),
167 errmsg("cursor \"%s\" does not exist", stmt->portalname)));
168 return; /* keep compiler happy */
171 /* Adjust dest if needed. MOVE wants destination DestNone */
172 if (stmt->ismove)
173 dest = None_Receiver;
175 /* Do it */
176 nprocessed = PortalRunFetch(portal,
177 stmt->direction,
178 stmt->howMany,
179 dest);
181 /* Return command status if wanted */
182 if (completionTag)
183 snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s %ld",
184 stmt->ismove ? "MOVE" : "FETCH",
185 nprocessed);
189 * PerformPortalClose
190 * Close a cursor.
192 void
193 PerformPortalClose(const char *name)
195 Portal portal;
197 /* NULL means CLOSE ALL */
198 if (name == NULL)
200 PortalHashTableDeleteAll();
201 return;
205 * Disallow empty-string cursor name (conflicts with protocol-level
206 * unnamed portal).
208 if (name[0] == '\0')
209 ereport(ERROR,
210 (errcode(ERRCODE_INVALID_CURSOR_NAME),
211 errmsg("invalid cursor name: must not be empty")));
214 * get the portal from the portal name
216 portal = GetPortalByName(name);
217 if (!PortalIsValid(portal))
219 ereport(ERROR,
220 (errcode(ERRCODE_UNDEFINED_CURSOR),
221 errmsg("cursor \"%s\" does not exist", name)));
222 return; /* keep compiler happy */
226 * Note: PortalCleanup is called as a side-effect
228 PortalDrop(portal, false);
232 * PortalCleanup
234 * Clean up a portal when it's dropped. This is the standard cleanup hook
235 * for portals.
237 void
238 PortalCleanup(Portal portal)
240 QueryDesc *queryDesc;
243 * sanity checks
245 AssertArg(PortalIsValid(portal));
246 AssertArg(portal->cleanup == PortalCleanup);
249 * Shut down executor, if still running. We skip this during error abort,
250 * since other mechanisms will take care of releasing executor resources,
251 * and we can't be sure that ExecutorEnd itself wouldn't fail.
253 queryDesc = PortalGetQueryDesc(portal);
254 if (queryDesc)
256 portal->queryDesc = NULL;
257 if (portal->status != PORTAL_FAILED)
259 ResourceOwner saveResourceOwner;
261 /* We must make the portal's resource owner current */
262 saveResourceOwner = CurrentResourceOwner;
263 PG_TRY();
265 CurrentResourceOwner = portal->resowner;
266 /* we do not need AfterTriggerEndQuery() here */
267 ExecutorEnd(queryDesc);
268 FreeQueryDesc(queryDesc);
270 PG_CATCH();
272 /* Ensure CurrentResourceOwner is restored on error */
273 CurrentResourceOwner = saveResourceOwner;
274 PG_RE_THROW();
276 PG_END_TRY();
277 CurrentResourceOwner = saveResourceOwner;
283 * PersistHoldablePortal
285 * Prepare the specified Portal for access outside of the current
286 * transaction. When this function returns, all future accesses to the
287 * portal must be done via the Tuplestore (not by invoking the
288 * executor).
290 void
291 PersistHoldablePortal(Portal portal)
293 QueryDesc *queryDesc = PortalGetQueryDesc(portal);
294 Portal saveActivePortal;
295 ResourceOwner saveResourceOwner;
296 MemoryContext savePortalContext;
297 MemoryContext oldcxt;
300 * If we're preserving a holdable portal, we had better be inside the
301 * transaction that originally created it.
303 Assert(portal->createSubid != InvalidSubTransactionId);
304 Assert(queryDesc != NULL);
307 * Caller must have created the tuplestore already.
309 Assert(portal->holdContext != NULL);
310 Assert(portal->holdStore != NULL);
313 * Before closing down the executor, we must copy the tupdesc into
314 * long-term memory, since it was created in executor memory.
316 oldcxt = MemoryContextSwitchTo(portal->holdContext);
318 portal->tupDesc = CreateTupleDescCopy(portal->tupDesc);
320 MemoryContextSwitchTo(oldcxt);
323 * Check for improper portal use, and mark portal active.
325 if (portal->status != PORTAL_READY)
326 ereport(ERROR,
327 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
328 errmsg("portal \"%s\" cannot be run", portal->name)));
329 portal->status = PORTAL_ACTIVE;
332 * Set up global portal context pointers.
334 saveActivePortal = ActivePortal;
335 saveResourceOwner = CurrentResourceOwner;
336 savePortalContext = PortalContext;
337 PG_TRY();
339 ActivePortal = portal;
340 CurrentResourceOwner = portal->resowner;
341 PortalContext = PortalGetHeapMemory(portal);
343 MemoryContextSwitchTo(PortalContext);
345 PushActiveSnapshot(queryDesc->snapshot);
348 * Rewind the executor: we need to store the entire result set in the
349 * tuplestore, so that subsequent backward FETCHs can be processed.
351 ExecutorRewind(queryDesc);
353 /* Change the destination to output to the tuplestore */
354 queryDesc->dest = CreateDestReceiver(DestTuplestore, portal);
356 /* Fetch the result set into the tuplestore */
357 ExecutorRun(queryDesc, ForwardScanDirection, 0L);
359 (*queryDesc->dest->rDestroy) (queryDesc->dest);
360 queryDesc->dest = NULL;
363 * Now shut down the inner executor.
365 portal->queryDesc = NULL; /* prevent double shutdown */
366 /* we do not need AfterTriggerEndQuery() here */
367 ExecutorEnd(queryDesc);
368 FreeQueryDesc(queryDesc);
371 * Set the position in the result set: ideally, this could be
372 * implemented by just skipping straight to the tuple # that we need
373 * to be at, but the tuplestore API doesn't support that. So we start
374 * at the beginning of the tuplestore and iterate through it until we
375 * reach where we need to be. FIXME someday? (Fortunately, the
376 * typical case is that we're supposed to be at or near the start of
377 * the result set, so this isn't as bad as it sounds.)
379 MemoryContextSwitchTo(portal->holdContext);
381 if (portal->atEnd)
383 /* we can handle this case even if posOverflow */
384 while (tuplestore_advance(portal->holdStore, true))
385 /* continue */ ;
387 else
389 long store_pos;
391 if (portal->posOverflow) /* oops, cannot trust portalPos */
392 ereport(ERROR,
393 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
394 errmsg("could not reposition held cursor")));
396 tuplestore_rescan(portal->holdStore);
398 for (store_pos = 0; store_pos < portal->portalPos; store_pos++)
400 if (!tuplestore_advance(portal->holdStore, true))
401 elog(ERROR, "unexpected end of tuple stream");
405 PG_CATCH();
407 /* Uncaught error while executing portal: mark it dead */
408 portal->status = PORTAL_FAILED;
410 /* Restore global vars and propagate error */
411 ActivePortal = saveActivePortal;
412 CurrentResourceOwner = saveResourceOwner;
413 PortalContext = savePortalContext;
415 PG_RE_THROW();
417 PG_END_TRY();
419 MemoryContextSwitchTo(oldcxt);
421 /* Mark portal not active */
422 portal->status = PORTAL_READY;
424 ActivePortal = saveActivePortal;
425 CurrentResourceOwner = saveResourceOwner;
426 PortalContext = savePortalContext;
428 PopActiveSnapshot();
431 * We can now release any subsidiary memory of the portal's heap context;
432 * we'll never use it again. The executor already dropped its context,
433 * but this will clean up anything that glommed onto the portal's heap via
434 * PortalContext.
436 MemoryContextDeleteChildren(PortalGetHeapMemory(portal));