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

  • 相关阅读:
    TCP的发送系列 — 发送缓存的管理(二)
    TCP的发送系列 — 发送缓存的管理(一)
    TCP的发送系列 — tcp_sendmsg()的实现(二)
    TCP的发送系列 — tcp_sendmsg()的实现(一)
    YTU 2618: B 求类中数据成员的最大值-类模板
    YTU 2617: B C++时间类的运算符重载
    YTU 2616: A代码完善--简易二元运算
    YTU 2615: AB编程题--世界杯小组赛
    YTU 2614: A代码完善--系统日期
    YTU 2611: A代码完善--向量的运算
  • 原文地址:https://www.cnblogs.com/gaojian/p/3092073.html
Copyright © 2020-2023  润新知