Branch data 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 : 4217 : defGetString(DefElem *def)
35 : : {
36 [ + - ]: 4217 : if (def->arg == NULL)
37 [ # # # # ]: 0 : ereport(ERROR,
38 : : (errcode(ERRCODE_SYNTAX_ERROR),
39 : : errmsg("%s requires a parameter",
40 : : def->defname)));
41 [ + + + + : 4217 : switch (nodeTag(def->arg))
+ - - - ]
42 : : {
43 : : case T_Integer:
44 : 156 : return psprintf("%d", intVal(def->arg));
45 : : case T_Float:
46 : 14 : return castNode(Float, def->arg)->fval;
47 : : case T_Boolean:
48 : 73 : return boolVal(def->arg) ? "true" : "false";
49 : : case T_String:
50 : 3744 : return strVal(def->arg);
51 : : case T_TypeName:
52 : 230 : return TypeNameToString((TypeName *) def->arg);
53 : : case T_List:
54 : 0 : return NameListToString((List *) def->arg);
55 : : case T_A_Star:
56 : 0 : return pstrdup("*");
57 : : default:
58 [ # # # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
59 : 0 : }
60 : 0 : return NULL; /* keep compiler quiet */
61 : 4217 : }
62 : :
63 : : /*
64 : : * Extract a numeric value (actually double) from a DefElem.
65 : : */
66 : : double
67 : 56 : defGetNumeric(DefElem *def)
68 : : {
69 [ + - ]: 56 : if (def->arg == NULL)
70 [ # # # # ]: 0 : ereport(ERROR,
71 : : (errcode(ERRCODE_SYNTAX_ERROR),
72 : : errmsg("%s requires a numeric value",
73 : : def->defname)));
74 [ + + - ]: 56 : switch (nodeTag(def->arg))
75 : : {
76 : : case T_Integer:
77 : 53 : return (double) intVal(def->arg);
78 : : case T_Float:
79 : 3 : return floatVal(def->arg);
80 : : default:
81 [ # # # # ]: 0 : ereport(ERROR,
82 : : (errcode(ERRCODE_SYNTAX_ERROR),
83 : : errmsg("%s requires a numeric value",
84 : : def->defname)));
85 : 0 : }
86 : 0 : return 0; /* keep compiler quiet */
87 : 56 : }
88 : :
89 : : /*
90 : : * Extract a boolean value from a DefElem.
91 : : */
92 : : bool
93 : 4173 : defGetBoolean(DefElem *def)
94 : : {
95 : : /*
96 : : * If no parameter value given, assume "true" is meant.
97 : : */
98 [ + + ]: 4173 : if (def->arg == NULL)
99 : 1258 : return true;
100 : :
101 : : /*
102 : : * Allow 0, 1, "true", "false", "on", "off"
103 : : */
104 [ + + ]: 2915 : switch (nodeTag(def->arg))
105 : : {
106 : : case T_Integer:
107 [ + + + ]: 20 : switch (intVal(def->arg))
108 : : {
109 : : case 0:
110 : 10 : return false;
111 : : case 1:
112 : 9 : return true;
113 : : default:
114 : : /* otherwise, error out below */
115 : 1 : break;
116 : : }
117 : 1 : break;
118 : : default:
119 : : {
120 : 2895 : 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 [ + + ]: 2895 : if (pg_strcasecmp(sval, "true") == 0)
127 : 46 : return true;
128 [ + + ]: 2849 : if (pg_strcasecmp(sval, "false") == 0)
129 : 80 : return false;
130 [ + + ]: 2769 : if (pg_strcasecmp(sval, "on") == 0)
131 : 32 : return true;
132 [ + + ]: 2737 : if (pg_strcasecmp(sval, "off") == 0)
133 : 2733 : return false;
134 [ - + + ]: 2895 : }
135 : 4 : break;
136 : : }
137 [ - + + - ]: 5 : ereport(ERROR,
138 : : (errcode(ERRCODE_SYNTAX_ERROR),
139 : : errmsg("%s requires a Boolean value",
140 : : def->defname)));
141 : 0 : return false; /* keep compiler quiet */
142 : 4168 : }
143 : :
144 : : /*
145 : : * Extract an int32 value from a DefElem.
146 : : */
147 : : int32
148 : 384 : defGetInt32(DefElem *def)
149 : : {
150 [ + + ]: 384 : if (def->arg == NULL)
151 [ + - + - ]: 1 : ereport(ERROR,
152 : : (errcode(ERRCODE_SYNTAX_ERROR),
153 : : errmsg("%s requires an integer value",
154 : : def->defname)));
155 [ + + ]: 383 : switch (nodeTag(def->arg))
156 : : {
157 : : case T_Integer:
158 : 382 : return (int32) intVal(def->arg);
159 : : default:
160 [ + - + - ]: 1 : ereport(ERROR,
161 : : (errcode(ERRCODE_SYNTAX_ERROR),
162 : : errmsg("%s requires an integer value",
163 : : def->defname)));
164 : 0 : }
165 : 0 : return 0; /* keep compiler quiet */
166 : 382 : }
167 : :
168 : : /*
169 : : * Extract an int64 value from a DefElem.
170 : : */
171 : : int64
172 : 73 : defGetInt64(DefElem *def)
173 : : {
174 [ + - ]: 73 : if (def->arg == NULL)
175 [ # # # # ]: 0 : ereport(ERROR,
176 : : (errcode(ERRCODE_SYNTAX_ERROR),
177 : : errmsg("%s requires a numeric value",
178 : : def->defname)));
179 [ + + - ]: 73 : switch (nodeTag(def->arg))
180 : : {
181 : : case T_Integer:
182 : 63 : return (int64) intVal(def->arg);
183 : : 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 : 10 : return DatumGetInt64(DirectFunctionCall1(int8in,
191 : : CStringGetDatum(castNode(Float, def->arg)->fval)));
192 : : default:
193 [ # # # # ]: 0 : ereport(ERROR,
194 : : (errcode(ERRCODE_SYNTAX_ERROR),
195 : : errmsg("%s requires a numeric value",
196 : : def->defname)));
197 : 0 : }
198 : 0 : return 0; /* keep compiler quiet */
199 : 73 : }
200 : :
201 : : /*
202 : : * Extract an OID value from a DefElem.
203 : : */
204 : : Oid
205 : 2 : defGetObjectId(DefElem *def)
206 : : {
207 [ + - ]: 2 : if (def->arg == NULL)
208 [ # # # # ]: 0 : ereport(ERROR,
209 : : (errcode(ERRCODE_SYNTAX_ERROR),
210 : : errmsg("%s requires a numeric value",
211 : : def->defname)));
212 [ + - - ]: 2 : switch (nodeTag(def->arg))
213 : : {
214 : : case T_Integer:
215 : 2 : return (Oid) intVal(def->arg);
216 : : 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 : : default:
226 [ # # # # ]: 0 : ereport(ERROR,
227 : : (errcode(ERRCODE_SYNTAX_ERROR),
228 : : errmsg("%s requires a numeric value",
229 : : def->defname)));
230 : 0 : }
231 : 0 : return 0; /* keep compiler quiet */
232 : 2 : }
233 : :
234 : : /*
235 : : * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
236 : : */
237 : : List *
238 : 695 : defGetQualifiedName(DefElem *def)
239 : : {
240 [ + - ]: 695 : if (def->arg == NULL)
241 [ # # # # ]: 0 : ereport(ERROR,
242 : : (errcode(ERRCODE_SYNTAX_ERROR),
243 : : errmsg("%s requires a parameter",
244 : : def->defname)));
245 [ + + + - ]: 695 : switch (nodeTag(def->arg))
246 : : {
247 : : case T_TypeName:
248 : 438 : return ((TypeName *) def->arg)->names;
249 : : case T_List:
250 : 222 : return (List *) def->arg;
251 : : case T_String:
252 : : /* Allow quoted name for backwards compatibility */
253 : 35 : return list_make1(def->arg);
254 : : default:
255 [ # # # # ]: 0 : ereport(ERROR,
256 : : (errcode(ERRCODE_SYNTAX_ERROR),
257 : : errmsg("argument of %s must be a name",
258 : : def->defname)));
259 : 0 : }
260 : 0 : return NIL; /* keep compiler quiet */
261 : 695 : }
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 : 525 : defGetTypeName(DefElem *def)
271 : : {
272 [ + - ]: 525 : if (def->arg == NULL)
273 [ # # # # ]: 0 : ereport(ERROR,
274 : : (errcode(ERRCODE_SYNTAX_ERROR),
275 : : errmsg("%s requires a parameter",
276 : : def->defname)));
277 [ + + - ]: 525 : switch (nodeTag(def->arg))
278 : : {
279 : : case T_TypeName:
280 : 524 : return (TypeName *) def->arg;
281 : : case T_String:
282 : : /* Allow quoted typename for backwards compatibility */
283 : 1 : return makeTypeNameFromNameList(list_make1(def->arg));
284 : : default:
285 [ # # # # ]: 0 : ereport(ERROR,
286 : : (errcode(ERRCODE_SYNTAX_ERROR),
287 : : errmsg("argument of %s must be a type name",
288 : : def->defname)));
289 : 0 : }
290 : 0 : return NULL; /* keep compiler quiet */
291 : 525 : }
292 : :
293 : : /*
294 : : * Extract a type length indicator (either absolute bytes, or
295 : : * -1 for "variable") from a DefElem.
296 : : */
297 : : int
298 : 6 : defGetTypeLength(DefElem *def)
299 : : {
300 [ + - ]: 6 : if (def->arg == NULL)
301 [ # # # # ]: 0 : ereport(ERROR,
302 : : (errcode(ERRCODE_SYNTAX_ERROR),
303 : : errmsg("%s requires a parameter",
304 : : def->defname)));
305 [ + - + - : 6 : switch (nodeTag(def->arg))
- - ]
306 : : {
307 : : case T_Integer:
308 : 4 : return intVal(def->arg);
309 : : case T_Float:
310 [ # # # # ]: 0 : ereport(ERROR,
311 : : (errcode(ERRCODE_SYNTAX_ERROR),
312 : : errmsg("%s requires an integer value",
313 : : def->defname)));
314 : 0 : break;
315 : : case T_String:
316 [ # # ]: 0 : if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
317 : 0 : return -1; /* variable length */
318 : 0 : break;
319 : : case T_TypeName:
320 : : /* cope if grammar chooses to believe "variable" is a typename */
321 : 2 : if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
322 [ + - ]: 2 : "variable") == 0)
323 : 2 : return -1; /* variable length */
324 : 0 : break;
325 : : case T_List:
326 : : /* must be an operator name */
327 : : break;
328 : : default:
329 [ # # # # ]: 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
330 : 0 : }
331 [ # # # # ]: 0 : ereport(ERROR,
332 : : (errcode(ERRCODE_SYNTAX_ERROR),
333 : : errmsg("invalid argument for %s: \"%s\"",
334 : : def->defname, defGetString(def))));
335 : 0 : return 0; /* keep compiler quiet */
336 : 6 : }
337 : :
338 : : /*
339 : : * Extract a list of string values (otherwise uninterpreted) from a DefElem.
340 : : */
341 : : List *
342 : 0 : defGetStringList(DefElem *def)
343 : : {
344 : 0 : 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 : 0 : }
362 : :
363 : 0 : return (List *) def->arg;
364 : 0 : }
365 : :
366 : : /*
367 : : * Raise an error about a conflicting DefElem.
368 : : */
369 : : void
370 : 26 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
371 : : {
372 [ + - + - ]: 26 : ereport(ERROR,
373 : : errcode(ERRCODE_SYNTAX_ERROR),
374 : : errmsg("conflicting or redundant options"),
375 : : parser_errposition(pstate, defel->location));
376 : 0 : }
|