LCOV - code coverage report
Current view: top level - src/backend/tcop - cmdtag.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 92.9 % 42 39
Test Date: 2026-07-24 19:15:43 Functions: 87.5 % 8 7
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 81.2 % 16 13

             Branch data     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                 :      513300 : InitializeQueryCompletion(QueryCompletion *qc)
      41                 :             : {
      42                 :      513300 :     qc->commandTag = CMDTAG_UNKNOWN;
      43                 :      513300 :     qc->nprocessed = 0;
      44                 :      513300 : }
      45                 :             : 
      46                 :             : const char *
      47                 :       10121 : GetCommandTagName(CommandTag commandTag)
      48                 :             : {
      49                 :       10121 :     return tag_behavior[commandTag].name;
      50                 :             : }
      51                 :             : 
      52                 :             : const char *
      53                 :      859339 : GetCommandTagNameAndLen(CommandTag commandTag, Size *len)
      54                 :             : {
      55                 :      859339 :     *len = (Size) tag_behavior[commandTag].namelen;
      56                 :      859339 :     return tag_behavior[commandTag].name;
      57                 :             : }
      58                 :             : 
      59                 :             : bool
      60                 :      393862 : command_tag_display_rowcount(CommandTag commandTag)
      61                 :             : {
      62                 :      393862 :     return tag_behavior[commandTag].display_rowcount;
      63                 :             : }
      64                 :             : 
      65                 :             : bool
      66                 :          93 : command_tag_event_trigger_ok(CommandTag commandTag)
      67                 :             : {
      68                 :          93 :     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                 :         293 : GetCommandTagEnum(const char *commandname)
      84                 :             : {
      85                 :             :     const CommandTagBehavior *base,
      86                 :             :                *last,
      87                 :             :                *position;
      88                 :             :     int         result;
      89                 :             : 
      90   [ +  -  -  + ]:         293 :     if (commandname == NULL || *commandname == '\0')
      91                 :           0 :         return CMDTAG_UNKNOWN;
      92                 :             : 
      93                 :         293 :     base = tag_behavior;
      94                 :         293 :     last = tag_behavior + lengthof(tag_behavior) - 1;
      95         [ +  + ]:        1874 :     while (last >= base)
      96                 :             :     {
      97                 :        1866 :         position = base + ((last - base) >> 1);
      98                 :        1866 :         result = pg_strcasecmp(commandname, position->name);
      99         [ +  + ]:        1866 :         if (result == 0)
     100                 :         285 :             return (CommandTag) (position - tag_behavior);
     101         [ +  + ]:        1581 :         else if (result < 0)
     102                 :         586 :             last = position - 1;
     103                 :             :         else
     104                 :         995 :             base = position + 1;
     105                 :             :     }
     106                 :           8 :     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                 :      393862 : BuildQueryCompletionString(char *buff, const QueryCompletion *qc,
     122                 :             :                            bool nameonly)
     123                 :             : {
     124                 :      393862 :     CommandTag  tag = qc->commandTag;
     125                 :             :     Size        taglen;
     126                 :      393862 :     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                 :      393862 :     memcpy(buff, tagname, taglen);
     134                 :      393862 :     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   [ +  +  +  - ]:      393862 :     if (command_tag_display_rowcount(tag) && !nameonly)
     147                 :             :     {
     148         [ +  + ]:      234420 :         if (tag == CMDTAG_INSERT)
     149                 :             :         {
     150                 :       39060 :             *bufp++ = ' ';
     151                 :       39060 :             *bufp++ = '0';
     152                 :             :         }
     153                 :      234420 :         *bufp++ = ' ';
     154                 :      234420 :         bufp += pg_ulltoa_n(qc->nprocessed, bufp);
     155                 :             :     }
     156                 :             : 
     157                 :             :     /* and finally, NUL terminate the string */
     158                 :      393862 :     *bufp = '\0';
     159                 :             : 
     160                 :             :     Assert((bufp - buff) == strlen(buff));
     161                 :             : 
     162                 :      393862 :     return bufp - buff;
     163                 :             : }
        

Generated by: LCOV version 2.0-1