]> granicus.if.org Git - postgresql/blob - src/backend/tcop/pquery.c
pgindent run. Make it all clean.
[postgresql] / src / backend / tcop / pquery.c
1 /*-------------------------------------------------------------------------
2  *
3  * pquery.c
4  *        POSTGRES process query command code
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.43 2001/03/22 03:59:48 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15
16 #include "postgres.h"
17
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"
24
25
26 static char *CreateOperationTag(int operationType);
27
28
29 /* ----------------------------------------------------------------
30  *              CreateQueryDesc
31  * ----------------------------------------------------------------
32  */
33 QueryDesc  *
34 CreateQueryDesc(Query *parsetree,
35                                 Plan *plantree,
36                                 CommandDest dest)
37 {
38         QueryDesc  *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
39
40         qd->operation = parsetree->commandType;         /* operation */
41         qd->parsetree = parsetree;      /* parse tree */
42         qd->plantree = plantree;        /* plan */
43         qd->dest = dest;                        /* output dest */
44         return qd;
45 }
46
47 /* ----------------------------------------------------------------
48  *              CreateExecutorState
49  *
50  *              Note: this may someday take parameters -cim 9/18/89
51  * ----------------------------------------------------------------
52  */
53 EState *
54 CreateExecutorState(void)
55 {
56         EState     *state;
57
58         /* ----------------
59          *      create a new executor state
60          * ----------------
61          */
62         state = makeNode(EState);
63
64         /* ----------------
65          *      initialize the Executor State structure
66          * ----------------
67          */
68         state->es_direction = ForwardScanDirection;
69         state->es_range_table = NIL;
70
71         state->es_result_relations = NULL;
72         state->es_num_result_relations = 0;
73         state->es_result_relation_info = NULL;
74
75         state->es_junkFilter = NULL;
76
77         state->es_into_relation_descriptor = NULL;
78
79         state->es_param_list_info = NULL;
80         state->es_param_exec_vals = NULL;
81
82         state->es_tupleTable = NULL;
83
84         state->es_query_cxt = CurrentMemoryContext;
85
86         state->es_per_tuple_exprcontext = NULL;
87
88         /* ----------------
89          *      return the executor state structure
90          * ----------------
91          */
92         return state;
93 }
94
95 /* ----------------------------------------------------------------
96  *              CreateOperationTag
97  *
98  *              utility to get a string representation of the
99  *              query operation.
100  * ----------------------------------------------------------------
101  */
102 static char *
103 CreateOperationTag(int operationType)
104 {
105         char       *tag;
106
107         switch (operationType)
108         {
109                 case CMD_SELECT:
110                         tag = "SELECT";
111                         break;
112                 case CMD_INSERT:
113                         tag = "INSERT";
114                         break;
115                 case CMD_DELETE:
116                         tag = "DELETE";
117                         break;
118                 case CMD_UPDATE:
119                         tag = "UPDATE";
120                         break;
121                 default:
122                         elog(DEBUG, "CreateOperationTag: unknown operation type %d",
123                                  operationType);
124                         tag = "???";
125                         break;
126         }
127
128         return tag;
129 }
130
131 /* ----------------
132  *              PreparePortal
133  * ----------------
134  */
135 Portal
136 PreparePortal(char *portalName)
137 {
138         Portal          portal;
139
140         /* ----------------
141          *       Check for already-in-use portal name.
142          * ----------------
143          */
144         portal = GetPortalByName(portalName);
145         if (PortalIsValid(portal))
146         {
147
148                 /*
149                  * XXX Should we raise an error rather than closing the old
150                  * portal?
151                  */
152                 elog(NOTICE, "Closing pre-existing portal \"%s\"",
153                          portalName);
154                 PortalDrop(&portal);
155         }
156
157         /* ----------------
158          *       Create the new portal.
159          * ----------------
160          */
161         portal = CreatePortal(portalName);
162
163         return portal;
164 }
165
166
167 /* ----------------------------------------------------------------
168  *              ProcessQuery
169  *
170  *              Execute a plan, the non-parallel version
171  * ----------------------------------------------------------------
172  */
173 void
174 ProcessQuery(Query *parsetree,
175                          Plan *plan,
176                          CommandDest dest)
177 {
178         int                     operation = parsetree->commandType;
179         char       *tag;
180         bool            isRetrieveIntoPortal;
181         bool            isRetrieveIntoRelation;
182         char       *intoName = NULL;
183         Portal          portal = NULL;
184         MemoryContext oldContext = NULL;
185         QueryDesc  *queryDesc;
186         EState     *state;
187         TupleDesc       attinfo;
188
189         set_ps_display(tag = CreateOperationTag(operation));
190
191         /* ----------------
192          *      initialize portal/into relation status
193          * ----------------
194          */
195         isRetrieveIntoPortal = false;
196         isRetrieveIntoRelation = false;
197
198         if (operation == CMD_SELECT)
199         {
200                 if (parsetree->isPortal)
201                 {
202                         isRetrieveIntoPortal = true;
203                         intoName = parsetree->into;
204                         if (parsetree->isBinary)
205                         {
206
207                                 /*
208                                  * For internal format portals, we change Remote
209                                  * (externalized form) to RemoteInternal (internalized
210                                  * form)
211                                  */
212                                 dest = RemoteInternal;
213                         }
214                 }
215                 else if (parsetree->into != NULL)
216                 {
217                         /* select into table */
218                         isRetrieveIntoRelation = true;
219                 }
220         }
221
222         /* ----------------
223          *      If retrieving into a portal, set up the portal and copy
224          *      the parsetree and plan into its memory context.
225          * ----------------
226          */
227         if (isRetrieveIntoPortal)
228         {
229                 portal = PreparePortal(intoName);
230                 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
231                 parsetree = copyObject(parsetree);
232                 plan = copyObject(plan);
233
234                 /*
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
237                  * context.
238                  */
239         }
240
241         /* ----------------
242          *      Now we can create the QueryDesc object.
243          * ----------------
244          */
245         queryDesc = CreateQueryDesc(parsetree, plan, dest);
246
247         /* ----------------
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.
253          * ----------------
254          */
255         if (isRetrieveIntoRelation)
256                 queryDesc->dest = None;
257
258         /* ----------------
259          *      create a default executor state.
260          * ----------------
261          */
262         state = CreateExecutorState();
263
264         /* ----------------
265          *      call ExecStart to prepare the plan for execution
266          * ----------------
267          */
268         attinfo = ExecutorStart(queryDesc, state);
269
270         /* ----------------
271          *       report the query's result type information
272          *       back to the front end or to whatever destination
273          *       we're dealing with.
274          * ----------------
275          */
276         BeginCommand(NULL,
277                                  operation,
278                                  attinfo,
279                                  isRetrieveIntoRelation,
280                                  isRetrieveIntoPortal,
281                                  tag,
282                                  dest);
283
284         /* ----------------
285          *      If retrieve into portal, stop now; we do not run the plan
286          *      until a FETCH command is received.
287          * ----------------
288          */
289         if (isRetrieveIntoPortal)
290         {
291                 PortalSetQuery(portal,
292                                            queryDesc,
293                                            attinfo,
294                                            state,
295                                            PortalCleanup);
296
297                 /* Now we can return to caller's memory context. */
298                 MemoryContextSwitchTo(oldContext);
299
300                 EndCommand(tag, dest);
301
302                 return;
303         }
304
305         /* ----------------
306          *       Now we get to the important call to ExecutorRun() where we
307          *       actually run the plan..
308          * ----------------
309          */
310         ExecutorRun(queryDesc, state, EXEC_RUN, 0L);
311
312         /* save infos for EndCommand */
313         UpdateCommandInfo(operation, state->es_lastoid, state->es_processed);
314
315         /* ----------------
316          *       Now, we close down all the scans and free allocated resources.
317          * ----------------
318          */
319         ExecutorEnd(queryDesc, state);
320
321         /* ----------------
322          *      Notify the destination of end of processing.
323          * ----------------
324          */
325         EndCommand(tag, dest);
326 }