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); 这一句开始,就是准备要执行了。