1 /*-------------------------------------------------------------------------
4 * POSTGRES process query command code
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.46 2001/10/25 05:49:43 momjian Exp $
13 *-------------------------------------------------------------------------
18 #include "commands/command.h"
19 #include "executor/execdefs.h"
20 #include "executor/executor.h"
21 #include "tcop/pquery.h"
22 #include "utils/memutils.h"
23 #include "utils/ps_status.h"
26 static char *CreateOperationTag(int operationType);
29 /* ----------------------------------------------------------------
31 * ----------------------------------------------------------------
34 CreateQueryDesc(Query *parsetree,
38 QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
40 qd->operation = parsetree->commandType; /* operation */
41 qd->parsetree = parsetree; /* parse tree */
42 qd->plantree = plantree; /* plan */
43 qd->dest = dest; /* output dest */
47 /* ----------------------------------------------------------------
50 * Note: this may someday take parameters -cim 9/18/89
51 * ----------------------------------------------------------------
54 CreateExecutorState(void)
59 * create a new executor state
61 state = makeNode(EState);
64 * initialize the Executor State structure
66 state->es_direction = ForwardScanDirection;
67 state->es_range_table = NIL;
69 state->es_result_relations = NULL;
70 state->es_num_result_relations = 0;
71 state->es_result_relation_info = NULL;
73 state->es_junkFilter = NULL;
75 state->es_into_relation_descriptor = NULL;
77 state->es_param_list_info = NULL;
78 state->es_param_exec_vals = NULL;
80 state->es_tupleTable = NULL;
82 state->es_query_cxt = CurrentMemoryContext;
84 state->es_per_tuple_exprcontext = NULL;
87 * return the executor state structure
92 /* ----------------------------------------------------------------
95 * utility to get a string representation of the
97 * ----------------------------------------------------------------
100 CreateOperationTag(int operationType)
104 switch (operationType)
119 elog(DEBUG, "CreateOperationTag: unknown operation type %d",
133 PreparePortal(char *portalName)
138 * Check for already-in-use portal name.
140 portal = GetPortalByName(portalName);
141 if (PortalIsValid(portal))
144 * XXX Should we raise an error rather than closing the old
147 elog(NOTICE, "Closing pre-existing portal \"%s\"",
153 * Create the new portal.
155 portal = CreatePortal(portalName);
161 /* ----------------------------------------------------------------
164 * Execute a plan, the non-parallel version
165 * ----------------------------------------------------------------
168 ProcessQuery(Query *parsetree,
172 int operation = parsetree->commandType;
174 bool isRetrieveIntoPortal;
175 bool isRetrieveIntoRelation;
176 char *intoName = NULL;
177 Portal portal = NULL;
178 MemoryContext oldContext = NULL;
179 QueryDesc *queryDesc;
183 set_ps_display(tag = CreateOperationTag(operation));
186 * initialize portal/into relation status
188 isRetrieveIntoPortal = false;
189 isRetrieveIntoRelation = false;
191 if (operation == CMD_SELECT)
193 if (parsetree->isPortal)
195 isRetrieveIntoPortal = true;
196 intoName = parsetree->into;
197 if (parsetree->isBinary)
200 * For internal format portals, we change Remote
201 * (externalized form) to RemoteInternal (internalized
204 dest = RemoteInternal;
207 else if (parsetree->into != NULL)
209 /* select into table */
210 isRetrieveIntoRelation = true;
215 * If retrieving into a portal, set up the portal and copy the
216 * parsetree and plan into its memory context.
218 if (isRetrieveIntoPortal)
220 portal = PreparePortal(intoName);
221 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
222 parsetree = copyObject(parsetree);
223 plan = copyObject(plan);
226 * We stay in portal's memory context for now, so that query desc,
227 * EState, and plan startup info are also allocated in the portal
233 * Now we can create the QueryDesc object.
235 queryDesc = CreateQueryDesc(parsetree, plan, dest);
238 * When performing a retrieve into, we override the normal
239 * communication destination during the processing of the the query.
240 * This only affects the tuple-output function - the correct
241 * destination will still see BeginCommand() and EndCommand()
244 if (isRetrieveIntoRelation)
245 queryDesc->dest = None;
248 * create a default executor state.
250 state = CreateExecutorState();
253 * call ExecStart to prepare the plan for execution
255 attinfo = ExecutorStart(queryDesc, state);
258 * report the query's result type information back to the front end or
259 * to whatever destination we're dealing with.
264 isRetrieveIntoRelation,
265 isRetrieveIntoPortal,
270 * If retrieve into portal, stop now; we do not run the plan until a
271 * FETCH command is received.
273 if (isRetrieveIntoPortal)
275 PortalSetQuery(portal,
281 /* Now we can return to caller's memory context. */
282 MemoryContextSwitchTo(oldContext);
284 EndCommand(tag, dest);
290 * Now we get to the important call to ExecutorRun() where we actually
293 ExecutorRun(queryDesc, state, EXEC_RUN, 0L);
295 /* save infos for EndCommand */
296 UpdateCommandInfo(operation, state->es_lastoid, state->es_processed);
299 * Now, we close down all the scans and free allocated resources.
301 ExecutorEnd(queryDesc, state);
304 * Notify the destination of end of processing.
306 EndCommand(tag, dest);