]> granicus.if.org Git - postgresql/blob - src/backend/tcop/pquery.c
pgindent run on all C files. Java run to follow. initdb/regression
[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.46 2001/10/25 05:49:43 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         state = makeNode(EState);
62
63         /*
64          * initialize the Executor State structure
65          */
66         state->es_direction = ForwardScanDirection;
67         state->es_range_table = NIL;
68
69         state->es_result_relations = NULL;
70         state->es_num_result_relations = 0;
71         state->es_result_relation_info = NULL;
72
73         state->es_junkFilter = NULL;
74
75         state->es_into_relation_descriptor = NULL;
76
77         state->es_param_list_info = NULL;
78         state->es_param_exec_vals = NULL;
79
80         state->es_tupleTable = NULL;
81
82         state->es_query_cxt = CurrentMemoryContext;
83
84         state->es_per_tuple_exprcontext = NULL;
85
86         /*
87          * return the executor state structure
88          */
89         return state;
90 }
91
92 /* ----------------------------------------------------------------
93  *              CreateOperationTag
94  *
95  *              utility to get a string representation of the
96  *              query operation.
97  * ----------------------------------------------------------------
98  */
99 static char *
100 CreateOperationTag(int operationType)
101 {
102         char       *tag;
103
104         switch (operationType)
105         {
106                 case CMD_SELECT:
107                         tag = "SELECT";
108                         break;
109                 case CMD_INSERT:
110                         tag = "INSERT";
111                         break;
112                 case CMD_DELETE:
113                         tag = "DELETE";
114                         break;
115                 case CMD_UPDATE:
116                         tag = "UPDATE";
117                         break;
118                 default:
119                         elog(DEBUG, "CreateOperationTag: unknown operation type %d",
120                                  operationType);
121                         tag = "???";
122                         break;
123         }
124
125         return tag;
126 }
127
128 /* ----------------
129  *              PreparePortal
130  * ----------------
131  */
132 Portal
133 PreparePortal(char *portalName)
134 {
135         Portal          portal;
136
137         /*
138          * Check for already-in-use portal name.
139          */
140         portal = GetPortalByName(portalName);
141         if (PortalIsValid(portal))
142         {
143                 /*
144                  * XXX Should we raise an error rather than closing the old
145                  * portal?
146                  */
147                 elog(NOTICE, "Closing pre-existing portal \"%s\"",
148                          portalName);
149                 PortalDrop(portal);
150         }
151
152         /*
153          * Create the new portal.
154          */
155         portal = CreatePortal(portalName);
156
157         return portal;
158 }
159
160
161 /* ----------------------------------------------------------------
162  *              ProcessQuery
163  *
164  *              Execute a plan, the non-parallel version
165  * ----------------------------------------------------------------
166  */
167 void
168 ProcessQuery(Query *parsetree,
169                          Plan *plan,
170                          CommandDest dest)
171 {
172         int                     operation = parsetree->commandType;
173         char       *tag;
174         bool            isRetrieveIntoPortal;
175         bool            isRetrieveIntoRelation;
176         char       *intoName = NULL;
177         Portal          portal = NULL;
178         MemoryContext oldContext = NULL;
179         QueryDesc  *queryDesc;
180         EState     *state;
181         TupleDesc       attinfo;
182
183         set_ps_display(tag = CreateOperationTag(operation));
184
185         /*
186          * initialize portal/into relation status
187          */
188         isRetrieveIntoPortal = false;
189         isRetrieveIntoRelation = false;
190
191         if (operation == CMD_SELECT)
192         {
193                 if (parsetree->isPortal)
194                 {
195                         isRetrieveIntoPortal = true;
196                         intoName = parsetree->into;
197                         if (parsetree->isBinary)
198                         {
199                                 /*
200                                  * For internal format portals, we change Remote
201                                  * (externalized form) to RemoteInternal (internalized
202                                  * form)
203                                  */
204                                 dest = RemoteInternal;
205                         }
206                 }
207                 else if (parsetree->into != NULL)
208                 {
209                         /* select into table */
210                         isRetrieveIntoRelation = true;
211                 }
212         }
213
214         /*
215          * If retrieving into a portal, set up the portal and copy the
216          * parsetree and plan into its memory context.
217          */
218         if (isRetrieveIntoPortal)
219         {
220                 portal = PreparePortal(intoName);
221                 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
222                 parsetree = copyObject(parsetree);
223                 plan = copyObject(plan);
224
225                 /*
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
228                  * context.
229                  */
230         }
231
232         /*
233          * Now we can create the QueryDesc object.
234          */
235         queryDesc = CreateQueryDesc(parsetree, plan, dest);
236
237         /*
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()
242          * messages.
243          */
244         if (isRetrieveIntoRelation)
245                 queryDesc->dest = None;
246
247         /*
248          * create a default executor state.
249          */
250         state = CreateExecutorState();
251
252         /*
253          * call ExecStart to prepare the plan for execution
254          */
255         attinfo = ExecutorStart(queryDesc, state);
256
257         /*
258          * report the query's result type information back to the front end or
259          * to whatever destination we're dealing with.
260          */
261         BeginCommand(NULL,
262                                  operation,
263                                  attinfo,
264                                  isRetrieveIntoRelation,
265                                  isRetrieveIntoPortal,
266                                  tag,
267                                  dest);
268
269         /*
270          * If retrieve into portal, stop now; we do not run the plan until a
271          * FETCH command is received.
272          */
273         if (isRetrieveIntoPortal)
274         {
275                 PortalSetQuery(portal,
276                                            queryDesc,
277                                            attinfo,
278                                            state,
279                                            PortalCleanup);
280
281                 /* Now we can return to caller's memory context. */
282                 MemoryContextSwitchTo(oldContext);
283
284                 EndCommand(tag, dest);
285
286                 return;
287         }
288
289         /*
290          * Now we get to the important call to ExecutorRun() where we actually
291          * run the plan..
292          */
293         ExecutorRun(queryDesc, state, EXEC_RUN, 0L);
294
295         /* save infos for EndCommand */
296         UpdateCommandInfo(operation, state->es_lastoid, state->es_processed);
297
298         /*
299          * Now, we close down all the scans and free allocated resources.
300          */
301         ExecutorEnd(queryDesc, state);
302
303         /*
304          * Notify the destination of end of processing.
305          */
306         EndCommand(tag, dest);
307 }