LCOV - code coverage report
Current view: top level - src/backend/tcop - cmdtag.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 92.9 % 42 39
Test Date: 2026-02-17 17:20:33 Functions: 87.5 % 8 7
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * cmdtag.c
       4              :  *    Data and routines for commandtag names and enumeration.
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  * IDENTIFICATION
      10              :  *    src/backend/tcop/cmdtag.c
      11              :  *
      12              :  *-------------------------------------------------------------------------
      13              :  */
      14              : #include "postgres.h"
      15              : 
      16              : #include "tcop/cmdtag.h"
      17              : #include "utils/builtins.h"
      18              : 
      19              : 
      20              : typedef struct CommandTagBehavior
      21              : {
      22              :     const char *name;           /* tag name, e.g. "SELECT" */
      23              :     const uint8 namelen;        /* set to strlen(name) */
      24              :     const bool  event_trigger_ok;
      25              :     const bool  table_rewrite_ok;
      26              :     const bool  display_rowcount;   /* should the number of rows affected be
      27              :                                      * shown in the command completion string */
      28              : } CommandTagBehavior;
      29              : 
      30              : #define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt) \
      31              :     { name, (uint8) (sizeof(name) - 1), evtrgok, rwrok, rowcnt },
      32              : 
      33              : static const CommandTagBehavior tag_behavior[] = {
      34              : #include "tcop/cmdtaglist.h"
      35              : };
      36              : 
      37              : #undef PG_CMDTAG
      38              : 
      39              : void
      40       424391 : InitializeQueryCompletion(QueryCompletion *qc)
      41              : {
      42       424391 :     qc->commandTag = CMDTAG_UNKNOWN;
      43       424391 :     qc->nprocessed = 0;
      44       424391 : }
      45              : 
      46              : const char *
      47         9407 : GetCommandTagName(CommandTag commandTag)
      48              : {
      49         9407 :     return tag_behavior[commandTag].name;
      50              : }
      51              : 
      52              : const char *
      53       703878 : GetCommandTagNameAndLen(CommandTag commandTag, Size *len)
      54              : {
      55       703878 :     *len = (Size) tag_behavior[commandTag].namelen;
      56       703878 :     return tag_behavior[commandTag].name;
      57              : }
      58              : 
      59              : bool
      60       320563 : command_tag_display_rowcount(CommandTag commandTag)
      61              : {
      62       320563 :     return tag_behavior[commandTag].display_rowcount;
      63              : }
      64              : 
      65              : bool
      66           70 : command_tag_event_trigger_ok(CommandTag commandTag)
      67              : {
      68           70 :     return tag_behavior[commandTag].event_trigger_ok;
      69              : }
      70              : 
      71              : bool
      72            0 : command_tag_table_rewrite_ok(CommandTag commandTag)
      73              : {
      74            0 :     return tag_behavior[commandTag].table_rewrite_ok;
      75              : }
      76              : 
      77              : /*
      78              :  * Search CommandTag by name
      79              :  *
      80              :  * Returns CommandTag, or CMDTAG_UNKNOWN if not recognized
      81              :  */
      82              : CommandTag
      83          220 : GetCommandTagEnum(const char *commandname)
      84              : {
      85              :     const CommandTagBehavior *base,
      86              :                *last,
      87              :                *position;
      88              :     int         result;
      89              : 
      90          220 :     if (commandname == NULL || *commandname == '\0')
      91            0 :         return CMDTAG_UNKNOWN;
      92              : 
      93          220 :     base = tag_behavior;
      94          220 :     last = tag_behavior + lengthof(tag_behavior) - 1;
      95         1570 :     while (last >= base)
      96              :     {
      97         1564 :         position = base + ((last - base) >> 1);
      98         1564 :         result = pg_strcasecmp(commandname, position->name);
      99         1564 :         if (result == 0)
     100          214 :             return (CommandTag) (position - tag_behavior);
     101         1350 :         else if (result < 0)
     102          503 :             last = position - 1;
     103              :         else
     104          847 :             base = position + 1;
     105              :     }
     106            6 :     return CMDTAG_UNKNOWN;
     107              : }
     108              : 
     109              : /*
     110              :  * BuildQueryCompletionString
     111              :  *      Build a string containing the command tag name with the
     112              :  *      QueryCompletion's nprocessed for command tags with display_rowcount
     113              :  *      set.  Returns the strlen of the constructed string.
     114              :  *
     115              :  * The caller must ensure that buff is at least COMPLETION_TAG_BUFSIZE bytes.
     116              :  *
     117              :  * If nameonly is true, then the constructed string will contain only the tag
     118              :  * name.
     119              :  */
     120              : Size
     121       320563 : BuildQueryCompletionString(char *buff, const QueryCompletion *qc,
     122              :                            bool nameonly)
     123              : {
     124       320563 :     CommandTag  tag = qc->commandTag;
     125              :     Size        taglen;
     126       320563 :     const char *tagname = GetCommandTagNameAndLen(tag, &taglen);
     127              :     char       *bufp;
     128              : 
     129              :     /*
     130              :      * We assume the tagname is plain ASCII and therefore requires no encoding
     131              :      * conversion.
     132              :      */
     133       320563 :     memcpy(buff, tagname, taglen);
     134       320563 :     bufp = buff + taglen;
     135              : 
     136              :     /* ensure that the tagname isn't long enough to overrun the buffer */
     137              :     Assert(taglen <= COMPLETION_TAG_BUFSIZE - MAXINT8LEN - 4);
     138              : 
     139              :     /*
     140              :      * In PostgreSQL versions 11 and earlier, it was possible to create a
     141              :      * table WITH OIDS.  When inserting into such a table, INSERT used to
     142              :      * include the Oid of the inserted record in the completion tag.  To
     143              :      * maintain compatibility in the wire protocol, we now write a "0" (for
     144              :      * InvalidOid) in the location where we once wrote the new record's Oid.
     145              :      */
     146       320563 :     if (command_tag_display_rowcount(tag) && !nameonly)
     147              :     {
     148       193323 :         if (tag == CMDTAG_INSERT)
     149              :         {
     150        33392 :             *bufp++ = ' ';
     151        33392 :             *bufp++ = '0';
     152              :         }
     153       193323 :         *bufp++ = ' ';
     154       193323 :         bufp += pg_ulltoa_n(qc->nprocessed, bufp);
     155              :     }
     156              : 
     157              :     /* and finally, NUL terminate the string */
     158       320563 :     *bufp = '\0';
     159              : 
     160              :     Assert((bufp - buff) == strlen(buff));
     161              : 
     162       320563 :     return bufp - buff;
     163              : }
        

Generated by: LCOV version 2.0-1