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