PostgreSQL在何处处理 sql查询之二

在exec_simple_query中,代码如下:

  1 /*
  2  * exec_simple_query
  3  *
  4  * Execute a "simple Query" protocol message.
  5  */
  6 static void
  7 exec_simple_query(const char *query_string)
  8 {
  9     CommandDest dest = whereToSendOutput;
 10     MemoryContext oldcontext;
 11     List       *parsetree_list;
 12     ListCell   *parsetree_item;
 13 
 14 
 15     bool        save_log_statement_stats = log_statement_stats;
 16     bool        was_logged = false;
 17     bool        isTopLevel;
 18     char        msec_str[32];
 19 
 20 
 21     /*
 22      * Report query to various monitoring facilities.
 23      */
 24     debug_query_string = query_string;
 25 
 26     pgstat_report_activity(STATE_RUNNING, query_string);
 27 
 28     TRACE_POSTGRESQL_QUERY_START(query_string);
 29 
 30     /*
 31      * We use save_log_statement_stats so ShowUsage doesn't report incorrect
 32      * results because ResetUsage wasn't called.
 33      */
 34     if (save_log_statement_stats)
 35         ResetUsage();
 36 
 37     /*
 38      * Start up a transaction command.    All queries generated by the
 39      * query_string will be in this same command block, *unless* we find a
 40      * BEGIN/COMMIT/ABORT statement; we have to force a new xact command after
 41      * one of those, else bad things will happen in xact.c. (Note that this
 42      * will normally change current memory context.)
 43      */
 44     start_xact_command();
 45 
 46     /*
 47      * Zap any pre-existing unnamed statement.    (While not strictly necessary,
 48      * it seems best to define simple-Query mode as if it used the unnamed
 49      * statement and portal; this ensures we recover any storage used by prior
 50      * unnamed operations.)
 51      */
 52     drop_unnamed_stmt();
 53 
 54     /*
 55      * Switch to appropriate context for constructing parsetrees.
 56      */
 57     oldcontext = MemoryContextSwitchTo(MessageContext);
 58 
 59     /*
 60      * Do basic parsing of the query or queries (this should be safe even if
 61      * we are in aborted transaction state!)
 62      */
 63     parsetree_list = pg_parse_query(query_string);
 64 
 65     /* Log immediately if dictated by log_statement */
 66     if (check_log_statement(parsetree_list))
 67     {
 68         ereport(LOG,
 69                 (errmsg("statement: %s", query_string),
 70                  errhidestmt(true),
 71                  errdetail_execute(parsetree_list)));
 72         was_logged = true;
 73     }
 74 
 75     /*
 76      * Switch back to transaction context to enter the loop.
 77      */
 78     MemoryContextSwitchTo(oldcontext);
 79 
 80     /*
 81      * We'll tell PortalRun it's a top-level command iff there's exactly one
 82      * raw parsetree.  If more than one, it's effectively a transaction block
 83      * and we want PreventTransactionChain to reject unsafe commands. (Note:
 84      * we're assuming that query rewrite cannot add commands that are
 85      * significant to PreventTransactionChain.)
 86      */
 87     isTopLevel = (list_length(parsetree_list) == 1);
 88 
 89     /*
 90      * Run through the raw parsetree(s) and process each one.
 91      */
 92     foreach(parsetree_item, parsetree_list)
 93     {
 94         Node       *parsetree = (Node *) lfirst(parsetree_item);
 95 
 96         bool        snapshot_set = false;
 97         const char *commandTag;
 98         char        completionTag[COMPLETION_TAG_BUFSIZE];
 99         List       *querytree_list,
100                    *plantree_list;
101         Portal        portal;
102         DestReceiver *receiver;
103         int16        format;
104 
105         /*
106          * Get the command name for use in status display (it also becomes the
107          * default completion tag, down inside PortalRun).    Set ps_status and
108          * do any special start-of-SQL-command processing needed by the
109          * destination.
110          */
111         commandTag = CreateCommandTag(parsetree);
112 
113         //fprintf(stderr,"commandTag is :%s\n",commandTag);
114 
115         set_ps_display(commandTag, false);
116 
117         BeginCommand(commandTag, dest);
118 
119         //fprintf(stderr,"BeginCommand finished.\n");
120 
121         /*
122          * If we are in an aborted transaction, reject all commands except
123          * COMMIT/ABORT.  It is important that this test occur before we try
124          * to do parse analysis, rewrite, or planning, since all those phases
125          * try to do database accesses, which may fail in abort state. (It
126          * might be safe to allow some additional utility commands in this
127          * state, but not many...)
128          */
129         if (IsAbortedTransactionBlockState() &&
130             !IsTransactionExitStmt(parsetree))
131             ereport(ERROR,
132                     (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
133                      errmsg("current transaction is aborted, "
134                           "commands ignored until end of transaction block"),
135                      errdetail_abort()));
136 
137         /* Make sure we are in a transaction command */
138         start_xact_command();
139 
140         /* If we got a cancel signal in parsing or prior command, quit */
141         CHECK_FOR_INTERRUPTS();
142 
143         /*
144          * Set up a snapshot if parse analysis/planning will need one.
145          */
146         if (analyze_requires_snapshot(parsetree))
147         {
148             PushActiveSnapshot(GetTransactionSnapshot());
149             snapshot_set = true;
150         }
151 
152         /*
153          * OK to analyze, rewrite, and plan this query.
154          *
155          * Switch to appropriate context for constructing querytrees (again,
156          * these must outlive the execution context).
157          */
158         oldcontext = MemoryContextSwitchTo(MessageContext);
159 
160         querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
161                                                 NULL, 0);
162 
163         plantree_list = pg_plan_queries(querytree_list, 0, NULL);
164 
165         /* If we got a cancel signal in analysis or planning, quit */
166         CHECK_FOR_INTERRUPTS();
167 
168         /*
169          * Create unnamed portal to run the query or queries in. If there
170          * already is one, silently drop it.
171          */
172         portal = CreatePortal("", true, true);
173         /* Don't display the portal in pg_cursors */
174         portal->visible = false;
175 
176         /*
177          * We don't have to copy anything into the portal, because everything
178          * we are passing here is in MessageContext, which will outlive the
179          * portal anyway.
180          */
181         PortalDefineQuery(portal,
182                           NULL,
183                           query_string,
184                           commandTag,
185                           plantree_list,
186                           NULL);
187 
188         /*
189          * Start the portal.
190          *
191          * If we took a snapshot for parsing/planning, the portal may be able
192          * to reuse it for the execution phase.  Currently, this will only
193          * happen in PORTAL_ONE_SELECT mode.  But even if PortalStart doesn't
194          * end up being able to do this, keeping the parse/plan snapshot
195          * around until after we start the portal doesn't cost much.
196          */
197         PortalStart(portal, NULL, 0, snapshot_set);
198 
199         /* Done with the snapshot used for parsing/planning */
200         if (snapshot_set)
201             PopActiveSnapshot();
202 
203         /*
204          * Select the appropriate output format: text unless we are doing a
205          * FETCH from a binary cursor.    (Pretty grotty to have to do this here
206          * --- but it avoids grottiness in other places.  Ah, the joys of
207          * backward compatibility...)
208          */
209         format = 0;                /* TEXT is default */
210         if (IsA(parsetree, FetchStmt))
211         {
212             FetchStmt  *stmt = (FetchStmt *) parsetree;
213 
214             if (!stmt->ismove)
215             {
216                 Portal        fportal = GetPortalByName(stmt->portalname);
217 
218                 if (PortalIsValid(fportal) &&
219                     (fportal->cursorOptions & CURSOR_OPT_BINARY))
220                     format = 1; /* BINARY */
221             }
222         }
223         PortalSetResultFormat(portal, 1, &format);
224 
225         /*
226          * Now we can create the destination receiver object.
227          */
228         receiver = CreateDestReceiver(dest);
229         if (dest == DestRemote)
230             SetRemoteDestReceiverParams(receiver, portal);
231 
232         /*
233          * Switch back to transaction context for execution.
234          */
235         MemoryContextSwitchTo(oldcontext);
236 
237         /*
238          * Run the portal to completion, and then drop it (and the receiver).
239          */
240         (void) PortalRun(portal,
241                          FETCH_ALL,
242                          isTopLevel,
243                          receiver,
244                          receiver,
245                          completionTag);
246 
247         (*receiver->rDestroy) (receiver);
248 
249         PortalDrop(portal, false);
250 
251         if (IsA(parsetree, TransactionStmt))
252         {
253             /*
254              * If this was a transaction control statement, commit it. We will
255              * start a new xact command for the next command (if any).
256              */
257             finish_xact_command();
258         }
259         else if (lnext(parsetree_item) == NULL)
260         {
261             /*
262              * If this is the last parsetree of the query string, close down
263              * transaction statement before reporting command-complete.  This
264              * is so that any end-of-transaction errors are reported before
265              * the command-complete message is issued, to avoid confusing
266              * clients who will expect either a command-complete message or an
267              * error, not one and then the other.  But for compatibility with
268              * historical Postgres behavior, we do not force a transaction
269              * boundary between queries appearing in a single query string.
270              */
271             finish_xact_command();
272         }
273         else
274         {
275             /*
276              * We need a CommandCounterIncrement after every query, except
277              * those that start or end a transaction block.
278              */
279             CommandCounterIncrement();
280         }
281 
282         /*
283          * Tell client that we're done with this query.  Note we emit exactly
284          * one EndCommand report for each raw parsetree, thus one for each SQL
285          * command the client sent, regardless of rewriting. (But a command
286          * aborted by error will not send an EndCommand report at all.)
287          */
288         EndCommand(completionTag, dest);
289     }                            /* end loop over parsetrees */
290 
291 
292 
293 
294     /*
295      * Close down transaction statement, if one is open.
296      */
297     finish_xact_command();
298 
299     /*
300      * If there were no parsetrees, return EmptyQueryResponse message.
301      */
302     if (!parsetree_list)
303         NullCommand(dest);
304 
305     /*
306      * Emit duration logging if appropriate.
307      */
308     switch (check_log_duration(msec_str, was_logged))
309     {
310         case 1:
311             ereport(LOG,
312                     (errmsg("duration: %s ms", msec_str),
313                      errhidestmt(true)));
314             break;
315         case 2:
316             ereport(LOG,
317                     (errmsg("duration: %s ms  statement: %s",
318                             msec_str, query_string),
319                      errhidestmt(true),
320                      errdetail_execute(parsetree_list)));
321             break;
322     }
323 
324     if (save_log_statement_stats)
325         ShowUsage("QUERY STATISTICS");
326 
327     TRACE_POSTGRESQL_QUERY_DONE(query_string);
328 
329     debug_query_string = NULL;
334 
335 }

其中,从 portal = CreatePortal("", true, true); 这一句开始,就是准备要执行了。

原文地址:https://www.cnblogs.com/gaojian/p/3092073.html