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-2025, 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
20typedef 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
39void
41{
42 qc->commandTag = CMDTAG_UNKNOWN;
43 qc->nprocessed = 0;
44}
45
46const char *
48{
49 return tag_behavior[commandTag].name;
50}
51
52const char *
54{
55 *len = (Size) tag_behavior[commandTag].namelen;
56 return tag_behavior[commandTag].name;
57}
58
59bool
61{
62 return tag_behavior[commandTag].display_rowcount;
63}
64
65bool
67{
68 return tag_behavior[commandTag].event_trigger_ok;
69}
70
71bool
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 */
83GetCommandTagEnum(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;
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 */
120Size
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 */
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
uint8_t uint8
Definition: c.h:486
#define Assert(condition)
Definition: c.h:815
#define lengthof(array)
Definition: c.h:745
size_t Size
Definition: c.h:562
const char * GetCommandTagNameAndLen(CommandTag commandTag, Size *len)
Definition: cmdtag.c:53
void InitializeQueryCompletion(QueryCompletion *qc)
Definition: cmdtag.c:40
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:47
struct CommandTagBehavior CommandTagBehavior
static const CommandTagBehavior tag_behavior[]
Definition: cmdtag.c:33
CommandTag GetCommandTagEnum(const char *commandname)
Definition: cmdtag.c:83
bool command_tag_event_trigger_ok(CommandTag commandTag)
Definition: cmdtag.c:66
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
#define COMPLETION_TAG_BUFSIZE
Definition: cmdtag.h:17
CommandTag
Definition: cmdtag.h:23
int pg_ulltoa_n(uint64 value, char *a)
Definition: numutils.c:1140
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:32
CommandTag commandTag
Definition: cmdtag.h:31