PostgreSQL在何处处理 sql查询之二

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介:

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







本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2013/05/22/3092073.html,如需转载请自行联系原作者

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
19天前
|
SQL NoSQL Java
Java使用sql查询mongodb
通过使用 MongoDB Connector for BI 和 JDBC,开发者可以在 Java 中使用 SQL 语法查询 MongoDB 数据库。这种方法对于熟悉 SQL 的团队非常有帮助,能够快速实现对 MongoDB 数据的操作。同时,也需要注意到这种方法的性能和功能限制,根据具体应用场景进行选择和优化。
64 9
|
1月前
|
SQL 存储 人工智能
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
Vanna 是一个开源的 Python RAG(Retrieval-Augmented Generation)框架,能够基于大型语言模型(LLMs)为数据库生成精确的 SQL 查询。Vanna 支持多种 LLMs、向量数据库和 SQL 数据库,提供高准确性查询,同时确保数据库内容安全私密,不外泄。
148 7
Vanna:开源 AI 检索生成框架,自动生成精确的 SQL 查询
|
2月前
|
SQL Java
使用java在未知表字段情况下通过sql查询信息
使用java在未知表字段情况下通过sql查询信息
43 8
|
2月前
|
SQL 安全 PHP
PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全
本文深入探讨了PHP开发中防止SQL注入的方法,包括使用参数化查询、对用户输入进行过滤和验证、使用安全的框架和库等,旨在帮助开发者有效应对SQL注入这一常见安全威胁,保障应用安全。
72 4
|
2月前
|
SQL 监控 关系型数据库
SQL语句当前及历史信息查询-performance schema的使用
本文介绍了如何使用MySQL的Performance Schema来获取SQL语句的当前和历史执行信息。Performance Schema默认在MySQL 8.0中启用,可以通过查询相关表来获取详细的SQL执行信息,包括当前执行的SQL、历史执行记录和统计汇总信息,从而快速定位和解决性能瓶颈。
|
2月前
|
SQL 存储 缓存
如何优化SQL查询性能?
【10月更文挑战第28天】如何优化SQL查询性能?
197 10
|
2月前
|
SQL 关系型数据库 MySQL
|
2月前
|
SQL 关系型数据库 数据库
PostgreSQL性能飙升的秘密:这几个调优技巧让你的数据库查询速度翻倍!
【10月更文挑战第25天】本文介绍了几种有效提升 PostgreSQL 数据库查询效率的方法,包括索引优化、查询优化、配置优化和硬件优化。通过合理设计索引、编写高效 SQL 查询、调整配置参数和选择合适硬件,可以显著提高数据库性能。
523 1
|
3月前
|
SQL 数据库 开发者
功能发布-自定义SQL查询
本期主要为大家介绍ClkLog九月上线的新功能-自定义SQL查询。
|
2月前
|
SQL 关系型数据库 MySQL
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
39 0