在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/archive/2013/05/22/3092073.html

PostgreSQL在何处处理 sql查询之二相关推荐

  1. PostgreSQL在何处处理 sql查询之二十二

    接前面. 回到程序调用关系上来: estimate_rel_size -> RelationGetNumberOfBlocks->RelationGetNumberOfBlocksINFo ...

  2. PostgreSQL在何处处理 sql查询之二十一

    接前面: 回到mdopen上来,看看是谁调用了 mdopen,又获得了什么. /** mdnblocks() -- Get the number of blocks stored in a relat ...

  3. PostgreSQL在何处处理 sql查询之五十二

    开始 /** Ready to do the primary planning.*/final_rel = make_one_rel(root, joinlist); 展开: /** make_one ...

  4. PostgreSQL在何处处理 sql查询之十二

    接前面,对 subquery_planner,进行进一步的分析: /*--------------------* subquery_planner* Invokes the planner on a ...

  5. PostgreSQL在何处处理 sql查询之六十二

    对 RelOptInfo * make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) 函数进行研究: 看看 inner ...

  6. PostgreSQL在何处处理 sql查询之五十一

    继续分析 query_planner: /** query_planner* Generate a path (that is, a simplified plan) for a basic quer ...

  7. PostgreSQL在何处处理 sql查询之四十七

    再次上溯: /*--------------------* subquery_planner* Invokes the planner on a subquery. We recurse to her ...

  8. PostgreSQL在何处处理 sql查询

    如果我开一个psql窗口,来输入sql文,它在数据库的何处被解析?在何处被"真正"处理? postgres.c 的 int PostgresMain(int argc, char ...

  9. PostgreSQL在何处处理 sql查询之五十四

    接前面,从 cheapeast_path 的角度,关注 query_planner 函数,对其进行简化: void query_planner(PlannerInfo *root, List *tli ...

最新文章

  1. 面试高频——JUC并发工具包快速上手(超详细总结)
  2. python标准异常
  3. 提高Excel中VBA效率的四种方法
  4. python 柱状图-【python】【数据分析】3D柱状图就是这么好看
  5. PHP $_REQUEST获取表单提交的代码
  6. 小余学调度:调度指令票系列讲解1(持续更新中ing)
  7. kafka 0.9 java开发_kafka 0.9 java producer and consumer demo
  8. 【电设控制与图像训练题】【激光打靶】【openmv测试代码以及效果】
  9. python对非it上班族有用吗_非专业人士学Python有用吗?
  10. delphi idtcpclient 发送十六进制00_91413足球推荐分析 法甲 04:00 南特 VS 巴黎圣日尔曼...
  11. python 配置文件对比_Python3实现配置文件差异对比脚本
  12. LR录制脚本后,中文显示的是乱码,怎么解决?
  13. composer killed while updating or install
  14. ubuntu第三方源导致软件无法安装的问题
  15. HttpPrinter-网页打印控件
  16. 【区间选点问题】 N个闭区间,最少需要多少个点,让每个闭区间都有一个点
  17. 【Unity】用Lerp()实现类杀戮尖塔手牌变化
  18. uiautomator2+adb shell input tap 实现微博自动取消关注
  19. 疫情大考,文旅央企华侨城出台有力措施保障游客安全
  20. 哈工大计算机网络week4学习总结

热门文章

  1. MYSQL常用操作速查
  2. 前端ajax传递json格式参数,后端springboot接收
  3. 电脑开机提示计算机无法启动不了,电脑无法启动并出现“System Halted”如何解决?...
  4. 查看php项目tp版本,tp5.1如何查看版本号
  5. vue3中setup()函数的使用一
  6. centos 删除crontab_Centos7:利用crontab定时执行任务
  7. tensorflow sigmoid 如何计算训练数据的正确率_“来自蒙娜丽莎的凝视”— 结合 TensorFlow.js 和深度学习实现...
  8. extmail如何登陆mysql_rhel5.4下postfix+mysql+extmail中mysql密码怎么设置?
  9. php载入内存的是本地代码吗,常量和静态变量会先载入内存后在进行执行php代码...
  10. 算法导论 练习9.3-8两个有序数组的中位数