PostgreSQL Source Code  git master
cmdtag.c
Go to the documentation of this file.
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 */
29 
30 #define PG_CMDTAG(tag, name, evtrgok, rwrok, rowcnt) \
31  { name, (uint8) (sizeof(name) - 1), evtrgok, rwrok, rowcnt },
32 
34 #include "tcop/cmdtaglist.h"
35 };
36 
37 #undef PG_CMDTAG
38 
39 void
41 {
42  qc->commandTag = CMDTAG_UNKNOWN;
43  qc->nprocessed = 0;
44 }
45 
46 const char *
48 {
49  return tag_behavior[commandTag].name;
50 }
51 
52 const char *
54 {
55  *len = (Size) tag_behavior[commandTag].namelen;
56  return tag_behavior[commandTag].name;
57 }
58 
59 bool
61 {
62  return tag_behavior[commandTag].display_rowcount;
63 }
64 
65 bool
67 {
68  return tag_behavior[commandTag].event_trigger_ok;
69 }
70 
71 bool
73 {
74  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  */
83 GetCommandTagEnum(const char *commandname)
84 {
85  const CommandTagBehavior *base,
86  *last,
87  *position;
88  int result;
89 
90  if (commandname == NULL || *commandname == '\0')
91  return CMDTAG_UNKNOWN;
92 
93  base = tag_behavior;
94  last = tag_behavior + lengthof(tag_behavior) - 1;
95  while (last >= base)
96  {
97  position = base + ((last - base) >> 1);
98  result = pg_strcasecmp(commandname, position->name);
99  if (result == 0)
100  return (CommandTag) (position - tag_behavior);
101  else if (result < 0)
102  last = position - 1;
103  else
104  base = position + 1;
105  }
106  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
122  bool nameonly)
123 {
124  CommandTag tag = qc->commandTag;
125  Size taglen;
126  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  memcpy(buff, tagname, taglen);
134  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  if (command_tag_display_rowcount(tag) && !nameonly)
147  {
148  if (tag == CMDTAG_INSERT)
149  {
150  *bufp++ = ' ';
151  *bufp++ = '0';
152  }
153  *bufp++ = ' ';
154  bufp += pg_ulltoa_n(qc->nprocessed, bufp);
155  }
156 
157  /* and finally, NUL terminate the string */
158  *bufp = '\0';
159 
160  Assert((bufp - buff) == strlen(buff));
161 
162  return bufp - buff;
163 }
#define MAXINT8LEN
Definition: builtins.h:22
#define Assert(condition)
Definition: c.h:858
#define lengthof(array)
Definition: c.h:788
unsigned char uint8
Definition: c.h:504
size_t Size
Definition: c.h:605
void InitializeQueryCompletion(QueryCompletion *qc)
Definition: cmdtag.c:40
struct CommandTagBehavior CommandTagBehavior
const char * GetCommandTagNameAndLen(CommandTag commandTag, Size *len)
Definition: cmdtag.c:53
CommandTag GetCommandTagEnum(const char *commandname)
Definition: cmdtag.c:83
bool command_tag_event_trigger_ok(CommandTag commandTag)
Definition: cmdtag.c:66
static const CommandTagBehavior tag_behavior[COMMAND_TAG_NEXTTAG]
Definition: cmdtag.c:33
bool command_tag_table_rewrite_ok(CommandTag commandTag)
Definition: cmdtag.c:72
bool command_tag_display_rowcount(CommandTag commandTag)
Definition: cmdtag.c:60
Size BuildQueryCompletionString(char *buff, const QueryCompletion *qc, bool nameonly)
Definition: cmdtag.c:121
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:47
#define COMPLETION_TAG_BUFSIZE
Definition: cmdtag.h:17
CommandTag
Definition: cmdtag.h:23
@ COMMAND_TAG_NEXTTAG
Definition: cmdtag.h:25
int pg_ulltoa_n(uint64 value, char *a)
Definition: numutils.c:1142
const void size_t len
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
const bool table_rewrite_ok
Definition: cmdtag.c:25
const uint8 namelen
Definition: cmdtag.c:23
const bool event_trigger_ok
Definition: cmdtag.c:24
const bool display_rowcount
Definition: cmdtag.c:26
const char * name
Definition: cmdtag.c:22
uint64 nprocessed
Definition: cmdtag.h:33
CommandTag commandTag
Definition: cmdtag.h:32