PostgreSQL Source Code git master
define.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * define.c
4 * Support routines for various kinds of object creation.
5 *
6 *
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 *
11 * IDENTIFICATION
12 * src/backend/commands/define.c
13 *
14 * DESCRIPTION
15 * Support routines for dealing with DefElem nodes.
16 *
17 *
18 *-------------------------------------------------------------------------
19 */
20#include "postgres.h"
21
22#include <ctype.h>
23#include <math.h>
24
25#include "catalog/namespace.h"
26#include "commands/defrem.h"
27#include "nodes/makefuncs.h"
28#include "parser/parse_type.h"
29#include "utils/fmgrprotos.h"
30
31/*
32 * Extract a string value (otherwise uninterpreted) from a DefElem.
33 */
34char *
36{
37 if (def->arg == NULL)
39 (errcode(ERRCODE_SYNTAX_ERROR),
40 errmsg("%s requires a parameter",
41 def->defname)));
42 switch (nodeTag(def->arg))
43 {
44 case T_Integer:
45 return psprintf("%ld", (long) intVal(def->arg));
46 case T_Float:
47 return castNode(Float, def->arg)->fval;
48 case T_Boolean:
49 return boolVal(def->arg) ? "true" : "false";
50 case T_String:
51 return strVal(def->arg);
52 case T_TypeName:
53 return TypeNameToString((TypeName *) def->arg);
54 case T_List:
55 return NameListToString((List *) def->arg);
56 case T_A_Star:
57 return pstrdup("*");
58 default:
59 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
60 }
61 return NULL; /* keep compiler quiet */
62}
63
64/*
65 * Extract a numeric value (actually double) from a DefElem.
66 */
67double
69{
70 if (def->arg == NULL)
72 (errcode(ERRCODE_SYNTAX_ERROR),
73 errmsg("%s requires a numeric value",
74 def->defname)));
75 switch (nodeTag(def->arg))
76 {
77 case T_Integer:
78 return (double) intVal(def->arg);
79 case T_Float:
80 return floatVal(def->arg);
81 default:
83 (errcode(ERRCODE_SYNTAX_ERROR),
84 errmsg("%s requires a numeric value",
85 def->defname)));
86 }
87 return 0; /* keep compiler quiet */
88}
89
90/*
91 * Extract a boolean value from a DefElem.
92 */
93bool
95{
96 /*
97 * If no parameter value given, assume "true" is meant.
98 */
99 if (def->arg == NULL)
100 return true;
101
102 /*
103 * Allow 0, 1, "true", "false", "on", "off"
104 */
105 switch (nodeTag(def->arg))
106 {
107 case T_Integer:
108 switch (intVal(def->arg))
109 {
110 case 0:
111 return false;
112 case 1:
113 return true;
114 default:
115 /* otherwise, error out below */
116 break;
117 }
118 break;
119 default:
120 {
121 char *sval = defGetString(def);
122
123 /*
124 * The set of strings accepted here should match up with the
125 * grammar's opt_boolean_or_string production.
126 */
127 if (pg_strcasecmp(sval, "true") == 0)
128 return true;
129 if (pg_strcasecmp(sval, "false") == 0)
130 return false;
131 if (pg_strcasecmp(sval, "on") == 0)
132 return true;
133 if (pg_strcasecmp(sval, "off") == 0)
134 return false;
135 }
136 break;
137 }
139 (errcode(ERRCODE_SYNTAX_ERROR),
140 errmsg("%s requires a Boolean value",
141 def->defname)));
142 return false; /* keep compiler quiet */
143}
144
145/*
146 * Extract an int32 value from a DefElem.
147 */
148int32
150{
151 if (def->arg == NULL)
153 (errcode(ERRCODE_SYNTAX_ERROR),
154 errmsg("%s requires an integer value",
155 def->defname)));
156 switch (nodeTag(def->arg))
157 {
158 case T_Integer:
159 return (int32) intVal(def->arg);
160 default:
162 (errcode(ERRCODE_SYNTAX_ERROR),
163 errmsg("%s requires an integer value",
164 def->defname)));
165 }
166 return 0; /* keep compiler quiet */
167}
168
169/*
170 * Extract an int64 value from a DefElem.
171 */
172int64
174{
175 if (def->arg == NULL)
177 (errcode(ERRCODE_SYNTAX_ERROR),
178 errmsg("%s requires a numeric value",
179 def->defname)));
180 switch (nodeTag(def->arg))
181 {
182 case T_Integer:
183 return (int64) intVal(def->arg);
184 case T_Float:
185
186 /*
187 * Values too large for int4 will be represented as Float
188 * constants by the lexer. Accept these if they are valid int8
189 * strings.
190 */
192 CStringGetDatum(castNode(Float, def->arg)->fval)));
193 default:
195 (errcode(ERRCODE_SYNTAX_ERROR),
196 errmsg("%s requires a numeric value",
197 def->defname)));
198 }
199 return 0; /* keep compiler quiet */
200}
201
202/*
203 * Extract an OID value from a DefElem.
204 */
205Oid
207{
208 if (def->arg == NULL)
210 (errcode(ERRCODE_SYNTAX_ERROR),
211 errmsg("%s requires a numeric value",
212 def->defname)));
213 switch (nodeTag(def->arg))
214 {
215 case T_Integer:
216 return (Oid) intVal(def->arg);
217 case T_Float:
218
219 /*
220 * Values too large for int4 will be represented as Float
221 * constants by the lexer. Accept these if they are valid OID
222 * strings.
223 */
225 CStringGetDatum(castNode(Float, def->arg)->fval)));
226 default:
228 (errcode(ERRCODE_SYNTAX_ERROR),
229 errmsg("%s requires a numeric value",
230 def->defname)));
231 }
232 return 0; /* keep compiler quiet */
233}
234
235/*
236 * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
237 */
238List *
240{
241 if (def->arg == NULL)
243 (errcode(ERRCODE_SYNTAX_ERROR),
244 errmsg("%s requires a parameter",
245 def->defname)));
246 switch (nodeTag(def->arg))
247 {
248 case T_TypeName:
249 return ((TypeName *) def->arg)->names;
250 case T_List:
251 return (List *) def->arg;
252 case T_String:
253 /* Allow quoted name for backwards compatibility */
254 return list_make1(def->arg);
255 default:
257 (errcode(ERRCODE_SYNTAX_ERROR),
258 errmsg("argument of %s must be a name",
259 def->defname)));
260 }
261 return NIL; /* keep compiler quiet */
262}
263
264/*
265 * Extract a TypeName from a DefElem.
266 *
267 * Note: we do not accept a List arg here, because the parser will only
268 * return a bare List when the name looks like an operator name.
269 */
270TypeName *
272{
273 if (def->arg == NULL)
275 (errcode(ERRCODE_SYNTAX_ERROR),
276 errmsg("%s requires a parameter",
277 def->defname)));
278 switch (nodeTag(def->arg))
279 {
280 case T_TypeName:
281 return (TypeName *) def->arg;
282 case T_String:
283 /* Allow quoted typename for backwards compatibility */
285 default:
287 (errcode(ERRCODE_SYNTAX_ERROR),
288 errmsg("argument of %s must be a type name",
289 def->defname)));
290 }
291 return NULL; /* keep compiler quiet */
292}
293
294/*
295 * Extract a type length indicator (either absolute bytes, or
296 * -1 for "variable") from a DefElem.
297 */
298int
300{
301 if (def->arg == NULL)
303 (errcode(ERRCODE_SYNTAX_ERROR),
304 errmsg("%s requires a parameter",
305 def->defname)));
306 switch (nodeTag(def->arg))
307 {
308 case T_Integer:
309 return intVal(def->arg);
310 case T_Float:
312 (errcode(ERRCODE_SYNTAX_ERROR),
313 errmsg("%s requires an integer value",
314 def->defname)));
315 break;
316 case T_String:
317 if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
318 return -1; /* variable length */
319 break;
320 case T_TypeName:
321 /* cope if grammar chooses to believe "variable" is a typename */
323 "variable") == 0)
324 return -1; /* variable length */
325 break;
326 case T_List:
327 /* must be an operator name */
328 break;
329 default:
330 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
331 }
333 (errcode(ERRCODE_SYNTAX_ERROR),
334 errmsg("invalid argument for %s: \"%s\"",
335 def->defname, defGetString(def))));
336 return 0; /* keep compiler quiet */
337}
338
339/*
340 * Extract a list of string values (otherwise uninterpreted) from a DefElem.
341 */
342List *
344{
345 ListCell *cell;
346
347 if (def->arg == NULL)
349 (errcode(ERRCODE_SYNTAX_ERROR),
350 errmsg("%s requires a parameter",
351 def->defname)));
352 if (nodeTag(def->arg) != T_List)
353 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
354
355 foreach(cell, (List *) def->arg)
356 {
357 Node *str = (Node *) lfirst(cell);
358
359 if (!IsA(str, String))
360 elog(ERROR, "unexpected node type in name list: %d",
361 (int) nodeTag(str));
362 }
363
364 return (List *) def->arg;
365}
366
367/*
368 * Raise an error about a conflicting DefElem.
369 */
370void
372{
374 errcode(ERRCODE_SYNTAX_ERROR),
375 errmsg("conflicting or redundant options"),
376 parser_errposition(pstate, defel->location));
377}
int64_t int64
Definition: c.h:485
int32_t int32
Definition: c.h:484
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:271
int32 defGetInt32(DefElem *def)
Definition: define.c:149
int defGetTypeLength(DefElem *def)
Definition: define.c:299
char * defGetString(DefElem *def)
Definition: define.c:35
bool defGetBoolean(DefElem *def)
Definition: define.c:94
List * defGetQualifiedName(DefElem *def)
Definition: define.c:239
int64 defGetInt64(DefElem *def)
Definition: define.c:173
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:371
Oid defGetObjectId(DefElem *def)
Definition: define.c:206
double defGetNumeric(DefElem *def)
Definition: define.c:68
List * defGetStringList(DefElem *def)
Definition: define.c:343
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
const char * str
Datum int8in(PG_FUNCTION_ARGS)
Definition: int8.c:50
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:484
char * pstrdup(const char *in)
Definition: mcxt.c:1696
char * NameListToString(const List *names)
Definition: namespace.c:3594
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
Datum oidin(PG_FUNCTION_ARGS)
Definition: oid.c:37
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:478
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:390
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:247
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
unsigned int Oid
Definition: postgres_ext.h:32
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
char * defname
Definition: parsenodes.h:826
ParseLoc location
Definition: parsenodes.h:830
Node * arg
Definition: parsenodes.h:827
Definition: value.h:48
Definition: pg_list.h:54
Definition: nodes.h:129
Definition: value.h:64
#define boolVal(v)
Definition: value.h:81
#define intVal(v)
Definition: value.h:79
#define strVal(v)
Definition: value.h:82
#define floatVal(v)
Definition: value.h:80