LCOV - code coverage report
Current view: top level - src/backend/tcop - cmdtag.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 98.1 % 52 51
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 75.0 % 20 15

             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                 :       63669 : InitializeQueryCompletion(QueryCompletion *qc)
      41                 :             : {
      42                 :       63669 :         qc->commandTag = CMDTAG_UNKNOWN;
      43                 :       63669 :         qc->nprocessed = 0;
      44                 :       63669 : }
      45                 :             : 
      46                 :             : const char *
      47                 :         111 : GetCommandTagName(CommandTag commandTag)
      48                 :             : {
      49                 :         111 :         return tag_behavior[commandTag].name;
      50                 :             : }
      51                 :             : 
      52                 :             : const char *
      53                 :      110121 : GetCommandTagNameAndLen(CommandTag commandTag, Size *len)
      54                 :             : {
      55                 :      110121 :         *len = (Size) tag_behavior[commandTag].namelen;
      56                 :      110121 :         return tag_behavior[commandTag].name;
      57                 :             : }
      58                 :             : 
      59                 :             : bool
      60                 :       51360 : command_tag_display_rowcount(CommandTag commandTag)
      61                 :             : {
      62                 :       51360 :         return tag_behavior[commandTag].display_rowcount;
      63                 :             : }
      64                 :             : 
      65                 :             : bool
      66                 :       16413 : command_tag_event_trigger_ok(CommandTag commandTag)
      67                 :             : {
      68                 :       16413 :         return tag_behavior[commandTag].event_trigger_ok;
      69                 :             : }
      70                 :             : 
      71                 :             : bool
      72                 :          22 : command_tag_table_rewrite_ok(CommandTag commandTag)
      73                 :             : {
      74                 :          22 :         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                 :          73 : GetCommandTagEnum(const char *commandname)
      84                 :             : {
      85                 :          73 :         const CommandTagBehavior *base,
      86                 :             :                            *last,
      87                 :             :                            *position;
      88                 :          73 :         int                     result;
      89                 :             : 
      90   [ +  -  -  + ]:          73 :         if (commandname == NULL || *commandname == '\0')
      91                 :           0 :                 return CMDTAG_UNKNOWN;
      92                 :             : 
      93                 :          73 :         base = tag_behavior;
      94                 :          73 :         last = tag_behavior + lengthof(tag_behavior) - 1;
      95         [ +  + ]:         521 :         while (last >= base)
      96                 :             :         {
      97                 :         519 :                 position = base + ((last - base) >> 1);
      98                 :         519 :                 result = pg_strcasecmp(commandname, position->name);
      99         [ +  + ]:         519 :                 if (result == 0)
     100                 :          71 :                         return (CommandTag) (position - tag_behavior);
     101         [ +  + ]:         448 :                 else if (result < 0)
     102                 :         167 :                         last = position - 1;
     103                 :             :                 else
     104                 :         281 :                         base = position + 1;
     105                 :             :         }
     106                 :           2 :         return CMDTAG_UNKNOWN;
     107                 :          73 : }
     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                 :       51360 : BuildQueryCompletionString(char *buff, const QueryCompletion *qc,
     122                 :             :                                                    bool nameonly)
     123                 :             : {
     124                 :       51360 :         CommandTag      tag = qc->commandTag;
     125                 :       51360 :         Size            taglen;
     126                 :       51360 :         const char *tagname = GetCommandTagNameAndLen(tag, &taglen);
     127                 :       51360 :         char       *bufp;
     128                 :             : 
     129                 :             :         /*
     130                 :             :          * We assume the tagname is plain ASCII and therefore requires no encoding
     131                 :             :          * conversion.
     132                 :             :          */
     133                 :       51360 :         memcpy(buff, tagname, taglen);
     134                 :       51360 :         bufp = buff + taglen;
     135                 :             : 
     136                 :             :         /* ensure that the tagname isn't long enough to overrun the buffer */
     137         [ +  - ]:       51360 :         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   [ +  +  -  + ]:       51360 :         if (command_tag_display_rowcount(tag) && !nameonly)
     147                 :             :         {
     148         [ +  + ]:       29326 :                 if (tag == CMDTAG_INSERT)
     149                 :             :                 {
     150                 :        4474 :                         *bufp++ = ' ';
     151                 :        4474 :                         *bufp++ = '0';
     152                 :        4474 :                 }
     153                 :       29326 :                 *bufp++ = ' ';
     154                 :       29326 :                 bufp += pg_ulltoa_n(qc->nprocessed, bufp);
     155                 :       29326 :         }
     156                 :             : 
     157                 :             :         /* and finally, NUL terminate the string */
     158                 :       51360 :         *bufp = '\0';
     159                 :             : 
     160         [ +  - ]:       51360 :         Assert((bufp - buff) == strlen(buff));
     161                 :             : 
     162                 :      102720 :         return bufp - buff;
     163                 :       51360 : }
        

Generated by: LCOV version 2.3.2-1