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-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 : */
34 : char *
35 58958 : defGetString(DefElem *def)
36 : {
37 58958 : if (def->arg == NULL)
38 0 : ereport(ERROR,
39 : (errcode(ERRCODE_SYNTAX_ERROR),
40 : errmsg("%s requires a parameter",
41 : def->defname)));
42 58958 : switch (nodeTag(def->arg))
43 : {
44 1060 : case T_Integer:
45 1060 : return psprintf("%ld", (long) intVal(def->arg));
46 106 : case T_Float:
47 106 : return castNode(Float, def->arg)->fval;
48 560 : case T_Boolean:
49 560 : return boolVal(def->arg) ? "true" : "false";
50 52200 : case T_String:
51 52200 : return strVal(def->arg);
52 5032 : case T_TypeName:
53 5032 : return TypeNameToString((TypeName *) def->arg);
54 0 : case T_List:
55 0 : return NameListToString((List *) def->arg);
56 0 : case T_A_Star:
57 0 : return pstrdup("*");
58 0 : default:
59 0 : 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 : */
67 : double
68 4448 : defGetNumeric(DefElem *def)
69 : {
70 4448 : if (def->arg == NULL)
71 0 : ereport(ERROR,
72 : (errcode(ERRCODE_SYNTAX_ERROR),
73 : errmsg("%s requires a numeric value",
74 : def->defname)));
75 4448 : switch (nodeTag(def->arg))
76 : {
77 4428 : case T_Integer:
78 4428 : return (double) intVal(def->arg);
79 20 : case T_Float:
80 20 : return floatVal(def->arg);
81 0 : default:
82 0 : ereport(ERROR,
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 : */
93 : bool
94 34356 : defGetBoolean(DefElem *def)
95 : {
96 : /*
97 : * If no parameter value given, assume "true" is meant.
98 : */
99 34356 : if (def->arg == NULL)
100 15396 : return true;
101 :
102 : /*
103 : * Allow 0, 1, "true", "false", "on", "off"
104 : */
105 18960 : switch (nodeTag(def->arg))
106 : {
107 470 : case T_Integer:
108 470 : switch (intVal(def->arg))
109 : {
110 400 : case 0:
111 400 : return false;
112 64 : case 1:
113 64 : return true;
114 6 : default:
115 : /* otherwise, error out below */
116 6 : break;
117 : }
118 6 : break;
119 18490 : default:
120 : {
121 18490 : 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 18490 : if (pg_strcasecmp(sval, "true") == 0)
128 1612 : return true;
129 16878 : if (pg_strcasecmp(sval, "false") == 0)
130 1380 : return false;
131 15498 : if (pg_strcasecmp(sval, "on") == 0)
132 284 : return true;
133 15214 : if (pg_strcasecmp(sval, "off") == 0)
134 15190 : return false;
135 : }
136 24 : break;
137 : }
138 30 : ereport(ERROR,
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 : */
148 : int32
149 1800 : defGetInt32(DefElem *def)
150 : {
151 1800 : if (def->arg == NULL)
152 0 : ereport(ERROR,
153 : (errcode(ERRCODE_SYNTAX_ERROR),
154 : errmsg("%s requires an integer value",
155 : def->defname)));
156 1800 : switch (nodeTag(def->arg))
157 : {
158 1800 : case T_Integer:
159 1800 : return (int32) intVal(def->arg);
160 0 : default:
161 0 : ereport(ERROR,
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 : */
172 : int64
173 806 : defGetInt64(DefElem *def)
174 : {
175 806 : if (def->arg == NULL)
176 0 : ereport(ERROR,
177 : (errcode(ERRCODE_SYNTAX_ERROR),
178 : errmsg("%s requires a numeric value",
179 : def->defname)));
180 806 : switch (nodeTag(def->arg))
181 : {
182 742 : case T_Integer:
183 742 : return (int64) intVal(def->arg);
184 64 : 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 : */
191 64 : return DatumGetInt64(DirectFunctionCall1(int8in,
192 : CStringGetDatum(castNode(Float, def->arg)->fval)));
193 0 : default:
194 0 : ereport(ERROR,
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 : */
205 : Oid
206 202 : defGetObjectId(DefElem *def)
207 : {
208 202 : if (def->arg == NULL)
209 0 : ereport(ERROR,
210 : (errcode(ERRCODE_SYNTAX_ERROR),
211 : errmsg("%s requires a numeric value",
212 : def->defname)));
213 202 : switch (nodeTag(def->arg))
214 : {
215 202 : case T_Integer:
216 202 : return (Oid) intVal(def->arg);
217 0 : 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 : */
224 0 : return DatumGetObjectId(DirectFunctionCall1(oidin,
225 : CStringGetDatum(castNode(Float, def->arg)->fval)));
226 0 : default:
227 0 : ereport(ERROR,
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 : */
238 : List *
239 15198 : defGetQualifiedName(DefElem *def)
240 : {
241 15198 : if (def->arg == NULL)
242 0 : ereport(ERROR,
243 : (errcode(ERRCODE_SYNTAX_ERROR),
244 : errmsg("%s requires a parameter",
245 : def->defname)));
246 15198 : switch (nodeTag(def->arg))
247 : {
248 9648 : case T_TypeName:
249 15198 : return ((TypeName *) def->arg)->names;
250 2616 : case T_List:
251 2616 : return (List *) def->arg;
252 2934 : case T_String:
253 : /* Allow quoted name for backwards compatibility */
254 2934 : return list_make1(def->arg);
255 0 : default:
256 0 : ereport(ERROR,
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 : */
270 : TypeName *
271 5948 : defGetTypeName(DefElem *def)
272 : {
273 5948 : if (def->arg == NULL)
274 0 : ereport(ERROR,
275 : (errcode(ERRCODE_SYNTAX_ERROR),
276 : errmsg("%s requires a parameter",
277 : def->defname)));
278 5948 : switch (nodeTag(def->arg))
279 : {
280 5942 : case T_TypeName:
281 5948 : return (TypeName *) def->arg;
282 6 : case T_String:
283 : /* Allow quoted typename for backwards compatibility */
284 6 : return makeTypeNameFromNameList(list_make1(def->arg));
285 0 : default:
286 0 : ereport(ERROR,
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 : */
298 : int
299 130 : defGetTypeLength(DefElem *def)
300 : {
301 130 : if (def->arg == NULL)
302 0 : ereport(ERROR,
303 : (errcode(ERRCODE_SYNTAX_ERROR),
304 : errmsg("%s requires a parameter",
305 : def->defname)));
306 130 : switch (nodeTag(def->arg))
307 : {
308 100 : case T_Integer:
309 100 : return intVal(def->arg);
310 0 : case T_Float:
311 0 : ereport(ERROR,
312 : (errcode(ERRCODE_SYNTAX_ERROR),
313 : errmsg("%s requires an integer value",
314 : def->defname)));
315 : break;
316 0 : case T_String:
317 0 : if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
318 0 : return -1; /* variable length */
319 0 : break;
320 30 : case T_TypeName:
321 : /* cope if grammar chooses to believe "variable" is a typename */
322 30 : if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
323 : "variable") == 0)
324 30 : return -1; /* variable length */
325 0 : break;
326 0 : case T_List:
327 : /* must be an operator name */
328 0 : break;
329 0 : default:
330 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
331 : }
332 0 : ereport(ERROR,
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 : */
342 : List *
343 0 : defGetStringList(DefElem *def)
344 : {
345 : ListCell *cell;
346 :
347 0 : if (def->arg == NULL)
348 0 : ereport(ERROR,
349 : (errcode(ERRCODE_SYNTAX_ERROR),
350 : errmsg("%s requires a parameter",
351 : def->defname)));
352 0 : if (nodeTag(def->arg) != T_List)
353 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
354 :
355 0 : foreach(cell, (List *) def->arg)
356 : {
357 0 : Node *str = (Node *) lfirst(cell);
358 :
359 0 : if (!IsA(str, String))
360 0 : elog(ERROR, "unexpected node type in name list: %d",
361 : (int) nodeTag(str));
362 : }
363 :
364 0 : return (List *) def->arg;
365 : }
366 :
367 : /*
368 : * Raise an error about a conflicting DefElem.
369 : */
370 : void
371 156 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
372 : {
373 156 : ereport(ERROR,
374 : errcode(ERRCODE_SYNTAX_ERROR),
375 : errmsg("conflicting or redundant options"),
376 : parser_errposition(pstate, defel->location));
377 : }
|