LCOV - code coverage report
Current view: top level - src/backend/tcop - cmdtag.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 39 42 92.9 %
Date: 2024-11-21 08:14:44 Functions: 7 8 87.5 %
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-2024, 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      737458 : InitializeQueryCompletion(QueryCompletion *qc)
      41             : {
      42      737458 :     qc->commandTag = CMDTAG_UNKNOWN;
      43      737458 :     qc->nprocessed = 0;
      44      737458 : }
      45             : 
      46             : const char *
      47       17276 : GetCommandTagName(CommandTag commandTag)
      48             : {
      49       17276 :     return tag_behavior[commandTag].name;
      50             : }
      51             : 
      52             : const char *
      53     1222076 : GetCommandTagNameAndLen(CommandTag commandTag, Size *len)
      54             : {
      55     1222076 :     *len = (Size) tag_behavior[commandTag].namelen;
      56     1222076 :     return tag_behavior[commandTag].name;
      57             : }
      58             : 
      59             : bool
      60      557072 : command_tag_display_rowcount(CommandTag commandTag)
      61             : {
      62      557072 :     return tag_behavior[commandTag].display_rowcount;
      63             : }
      64             : 
      65             : bool
      66         140 : command_tag_event_trigger_ok(CommandTag commandTag)
      67             : {
      68         140 :     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         434 : GetCommandTagEnum(const char *commandname)
      84             : {
      85             :     const CommandTagBehavior *base,
      86             :                *last,
      87             :                *position;
      88             :     int         result;
      89             : 
      90         434 :     if (commandname == NULL || *commandname == '\0')
      91           0 :         return CMDTAG_UNKNOWN;
      92             : 
      93         434 :     base = tag_behavior;
      94         434 :     last = tag_behavior + lengthof(tag_behavior) - 1;
      95        3176 :     while (last >= base)
      96             :     {
      97        3164 :         position = base + ((last - base) >> 1);
      98        3164 :         result = pg_strcasecmp(commandname, position->name);
      99        3164 :         if (result == 0)
     100         422 :             return (CommandTag) (position - tag_behavior);
     101        2742 :         else if (result < 0)
     102        1000 :             last = position - 1;
     103             :         else
     104        1742 :             base = position + 1;
     105             :     }
     106          12 :     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      557072 : BuildQueryCompletionString(char *buff, const QueryCompletion *qc,
     122             :                            bool nameonly)
     123             : {
     124      557072 :     CommandTag  tag = qc->commandTag;
     125             :     Size        taglen;
     126      557072 :     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      557072 :     memcpy(buff, tagname, taglen);
     134      557072 :     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      557072 :     if (command_tag_display_rowcount(tag) && !nameonly)
     147             :     {
     148      343068 :         if (tag == CMDTAG_INSERT)
     149             :         {
     150       64084 :             *bufp++ = ' ';
     151       64084 :             *bufp++ = '0';
     152             :         }
     153      343068 :         *bufp++ = ' ';
     154      343068 :         bufp += pg_ulltoa_n(qc->nprocessed, bufp);
     155             :     }
     156             : 
     157             :     /* and finally, NUL terminate the string */
     158      557072 :     *bufp = '\0';
     159             : 
     160             :     Assert((bufp - buff) == strlen(buff));
     161             : 
     162      557072 :     return bufp - buff;
     163             : }

Generated by: LCOV version 1.14