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.43 2001/03/22 03:59:48 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
62 state = makeNode(EState);
65 * initialize the Executor State structure
68 state->es_direction = ForwardScanDirection;
69 state->es_range_table = NIL;
71 state->es_result_relations = NULL;
72 state->es_num_result_relations = 0;
73 state->es_result_relation_info = NULL;
75 state->es_junkFilter = NULL;
77 state->es_into_relation_descriptor = NULL;
79 state->es_param_list_info = NULL;
80 state->es_param_exec_vals = NULL;
82 state->es_tupleTable = NULL;
84 state->es_query_cxt = CurrentMemoryContext;
86 state->es_per_tuple_exprcontext = NULL;
89 * return the executor state structure
95 /* ----------------------------------------------------------------
98 * utility to get a string representation of the
100 * ----------------------------------------------------------------
103 CreateOperationTag(int operationType)
107 switch (operationType)
122 elog(DEBUG, "CreateOperationTag: unknown operation type %d",
136 PreparePortal(char *portalName)
141 * Check for already-in-use portal name.
144 portal = GetPortalByName(portalName);
145 if (PortalIsValid(portal))
149 * XXX Should we raise an error rather than closing the old
152 elog(NOTICE, "Closing pre-existing portal \"%s\"",
158 * Create the new portal.
161 portal = CreatePortal(portalName);
167 /* ----------------------------------------------------------------
170 * Execute a plan, the non-parallel version
171 * ----------------------------------------------------------------
174 ProcessQuery(Query *parsetree,
178 int operation = parsetree->commandType;
180 bool isRetrieveIntoPortal;
181 bool isRetrieveIntoRelation;
182 char *intoName = NULL;
183 Portal portal = NULL;
184 MemoryContext oldContext = NULL;
185 QueryDesc *queryDesc;
189 set_ps_display(tag = CreateOperationTag(operation));
192 * initialize portal/into relation status
195 isRetrieveIntoPortal = false;
196 isRetrieveIntoRelation = false;
198 if (operation == CMD_SELECT)
200 if (parsetree->isPortal)
202 isRetrieveIntoPortal = true;
203 intoName = parsetree->into;
204 if (parsetree->isBinary)
208 * For internal format portals, we change Remote
209 * (externalized form) to RemoteInternal (internalized
212 dest = RemoteInternal;
215 else if (parsetree->into != NULL)
217 /* select into table */
218 isRetrieveIntoRelation = true;
223 * If retrieving into a portal, set up the portal and copy
224 * the parsetree and plan into its memory context.
227 if (isRetrieveIntoPortal)
229 portal = PreparePortal(intoName);
230 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
231 parsetree = copyObject(parsetree);
232 plan = copyObject(plan);
235 * We stay in portal's memory context for now, so that query desc,
236 * EState, and plan startup info are also allocated in the portal
242 * Now we can create the QueryDesc object.
245 queryDesc = CreateQueryDesc(parsetree, plan, dest);
248 * When performing a retrieve into, we override the normal
249 * communication destination during the processing of the
250 * the query. This only affects the tuple-output function
251 * - the correct destination will still see BeginCommand()
252 * and EndCommand() messages.
255 if (isRetrieveIntoRelation)
256 queryDesc->dest = None;
259 * create a default executor state.
262 state = CreateExecutorState();
265 * call ExecStart to prepare the plan for execution
268 attinfo = ExecutorStart(queryDesc, state);
271 * report the query's result type information
272 * back to the front end or to whatever destination
273 * we're dealing with.
279 isRetrieveIntoRelation,
280 isRetrieveIntoPortal,
285 * If retrieve into portal, stop now; we do not run the plan
286 * until a FETCH command is received.
289 if (isRetrieveIntoPortal)
291 PortalSetQuery(portal,
297 /* Now we can return to caller's memory context. */
298 MemoryContextSwitchTo(oldContext);
300 EndCommand(tag, dest);
306 * Now we get to the important call to ExecutorRun() where we
307 * actually run the plan..
310 ExecutorRun(queryDesc, state, EXEC_RUN, 0L);
312 /* save infos for EndCommand */
313 UpdateCommandInfo(operation, state->es_lastoid, state->es_processed);
316 * Now, we close down all the scans and free allocated resources.
319 ExecutorEnd(queryDesc, state);
322 * Notify the destination of end of processing.
325 EndCommand(tag, dest);