Age Owner Branch data TLA 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 *
5999 tgl@sss.pgh.pa.us 35 :CBC 31432 : defGetString(DefElem *def)
36 : : {
37 [ - + ]: 31432 : if (def->arg == NULL)
8084 tgl@sss.pgh.pa.us 38 [ # # ]:UBC 0 : ereport(ERROR,
39 : : (errcode(ERRCODE_SYNTAX_ERROR),
40 : : errmsg("%s requires a parameter",
41 : : def->defname)));
5999 tgl@sss.pgh.pa.us 42 [ + + + + :CBC 31432 : switch (nodeTag(def->arg))
+ - - - ]
43 : : {
9100 44 : 537 : case T_Integer:
4261 peter_e@gmx.net 45 : 537 : return psprintf("%ld", (long) intVal(def->arg));
9100 tgl@sss.pgh.pa.us 46 : 56 : case T_Float:
1331 peter@eisentraut.org 47 : 56 : return castNode(Float, def->arg)->fval;
48 : 290 : case T_Boolean:
49 [ + + ]: 290 : return boolVal(def->arg) ? "true" : "false";
9100 tgl@sss.pgh.pa.us 50 : 27745 : case T_String:
5999 51 : 27745 : return strVal(def->arg);
9100 52 : 2804 : case T_TypeName:
5999 53 : 2804 : return TypeNameToString((TypeName *) def->arg);
8428 tgl@sss.pgh.pa.us 54 :UBC 0 : case T_List:
5999 55 : 0 : return NameListToString((List *) def->arg);
5829 56 : 0 : case T_A_Star:
57 : 0 : return pstrdup("*");
9100 58 : 0 : default:
5999 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
9471 tgl@sss.pgh.pa.us 68 :CBC 2480 : defGetNumeric(DefElem *def)
69 : : {
70 [ - + ]: 2480 : if (def->arg == NULL)
8084 tgl@sss.pgh.pa.us 71 [ # # ]:UBC 0 : ereport(ERROR,
72 : : (errcode(ERRCODE_SYNTAX_ERROR),
73 : : errmsg("%s requires a numeric value",
74 : : def->defname)));
9471 tgl@sss.pgh.pa.us 75 [ + + - ]:CBC 2480 : switch (nodeTag(def->arg))
76 : : {
77 : 2470 : case T_Integer:
78 : 2470 : return (double) intVal(def->arg);
79 : 10 : case T_Float:
80 : 10 : return floatVal(def->arg);
9471 tgl@sss.pgh.pa.us 81 :UBC 0 : default:
8084 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
5999 tgl@sss.pgh.pa.us 94 :CBC 20774 : defGetBoolean(DefElem *def)
95 : : {
96 : : /*
97 : : * If no parameter value given, assume "true" is meant.
98 : : */
99 [ + + ]: 20774 : if (def->arg == NULL)
7785 100 : 10562 : return true;
101 : :
102 : : /*
103 : : * Allow 0, 1, "true", "false", "on", "off"
104 : : */
5999 105 [ + + ]: 10212 : switch (nodeTag(def->arg))
106 : : {
7006 bruce@momjian.us 107 : 235 : case T_Integer:
5999 tgl@sss.pgh.pa.us 108 [ + + + ]: 235 : switch (intVal(def->arg))
109 : : {
7005 110 : 203 : case 0:
111 : 203 : return false;
112 : 29 : case 1:
113 : 29 : return true;
114 : 3 : default:
115 : : /* otherwise, error out below */
116 : 3 : break;
117 : : }
7006 bruce@momjian.us 118 : 3 : break;
119 : 9977 : default:
120 : : {
5999 tgl@sss.pgh.pa.us 121 : 9977 : 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 : : */
7005 127 [ + + ]: 9977 : if (pg_strcasecmp(sval, "true") == 0)
128 : 833 : return true;
129 [ + + ]: 9144 : if (pg_strcasecmp(sval, "false") == 0)
130 : 728 : return false;
5886 131 [ + + ]: 8416 : if (pg_strcasecmp(sval, "on") == 0)
132 : 150 : return true;
133 [ + + ]: 8266 : if (pg_strcasecmp(sval, "off") == 0)
134 : 8254 : return false;
135 : : }
7006 bruce@momjian.us 136 : 12 : break;
137 : : }
7785 tgl@sss.pgh.pa.us 138 [ + - ]: 15 : 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
4312 149 : 939 : defGetInt32(DefElem *def)
150 : : {
151 [ - + ]: 939 : if (def->arg == NULL)
4312 tgl@sss.pgh.pa.us 152 [ # # ]:UBC 0 : ereport(ERROR,
153 : : (errcode(ERRCODE_SYNTAX_ERROR),
154 : : errmsg("%s requires an integer value",
155 : : def->defname)));
4312 tgl@sss.pgh.pa.us 156 [ + + ]:CBC 939 : switch (nodeTag(def->arg))
157 : : {
158 : 936 : case T_Integer:
159 : 936 : return (int32) intVal(def->arg);
4312 tgl@sss.pgh.pa.us 160 :GBC 3 : default:
161 [ + - ]: 3 : 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
8508 tgl@sss.pgh.pa.us 173 :CBC 429 : defGetInt64(DefElem *def)
174 : : {
175 [ - + ]: 429 : if (def->arg == NULL)
8084 tgl@sss.pgh.pa.us 176 [ # # ]:UBC 0 : ereport(ERROR,
177 : : (errcode(ERRCODE_SYNTAX_ERROR),
178 : : errmsg("%s requires a numeric value",
179 : : def->defname)));
8508 tgl@sss.pgh.pa.us 180 [ + + - ]:CBC 429 : switch (nodeTag(def->arg))
181 : : {
182 : 397 : case T_Integer:
183 : 397 : return (int64) intVal(def->arg);
184 : 32 : 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 : 32 : return DatumGetInt64(DirectFunctionCall1(int8in,
192 : : CStringGetDatum(castNode(Float, def->arg)->fval)));
8508 tgl@sss.pgh.pa.us 193 :UBC 0 : default:
8084 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
1037 tgl@sss.pgh.pa.us 206 :CBC 129 : defGetObjectId(DefElem *def)
207 : : {
208 [ - + ]: 129 : if (def->arg == NULL)
1037 tgl@sss.pgh.pa.us 209 [ # # ]:UBC 0 : ereport(ERROR,
210 : : (errcode(ERRCODE_SYNTAX_ERROR),
211 : : errmsg("%s requires a numeric value",
212 : : def->defname)));
1037 tgl@sss.pgh.pa.us 213 [ + - - ]:CBC 129 : switch (nodeTag(def->arg))
214 : : {
215 : 129 : case T_Integer:
216 : 129 : return (Oid) intVal(def->arg);
1037 tgl@sss.pgh.pa.us 217 :UBC 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 *
8551 tgl@sss.pgh.pa.us 239 :CBC 8092 : defGetQualifiedName(DefElem *def)
240 : : {
241 [ - + ]: 8092 : if (def->arg == NULL)
8084 tgl@sss.pgh.pa.us 242 [ # # ]:UBC 0 : ereport(ERROR,
243 : : (errcode(ERRCODE_SYNTAX_ERROR),
244 : : errmsg("%s requires a parameter",
245 : : def->defname)));
8551 tgl@sss.pgh.pa.us 246 [ + + + - ]:CBC 8092 : switch (nodeTag(def->arg))
247 : : {
248 : 5081 : case T_TypeName:
249 : 8092 : return ((TypeName *) def->arg)->names;
8428 250 : 1332 : case T_List:
251 : 1332 : return (List *) def->arg;
8551 252 : 1679 : case T_String:
253 : : /* Allow quoted name for backwards compatibility */
7773 neilc@samurai.com 254 : 1679 : return list_make1(def->arg);
8551 tgl@sss.pgh.pa.us 255 :UBC 0 : default:
8084 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 *
8562 tgl@sss.pgh.pa.us 271 :CBC 3059 : defGetTypeName(DefElem *def)
272 : : {
273 [ - + ]: 3059 : if (def->arg == NULL)
8084 tgl@sss.pgh.pa.us 274 [ # # ]:UBC 0 : ereport(ERROR,
275 : : (errcode(ERRCODE_SYNTAX_ERROR),
276 : : errmsg("%s requires a parameter",
277 : : def->defname)));
8562 tgl@sss.pgh.pa.us 278 [ + + - ]:CBC 3059 : switch (nodeTag(def->arg))
279 : : {
280 : 3056 : case T_TypeName:
281 : 3059 : return (TypeName *) def->arg;
282 : 3 : case T_String:
283 : : /* Allow quoted typename for backwards compatibility */
7116 284 : 3 : return makeTypeNameFromNameList(list_make1(def->arg));
8562 tgl@sss.pgh.pa.us 285 :UBC 0 : default:
8084 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
10225 bruce@momjian.us 299 :CBC 78 : defGetTypeLength(DefElem *def)
300 : : {
9100 tgl@sss.pgh.pa.us 301 [ - + ]: 78 : if (def->arg == NULL)
8084 tgl@sss.pgh.pa.us 302 [ # # ]:UBC 0 : ereport(ERROR,
303 : : (errcode(ERRCODE_SYNTAX_ERROR),
304 : : errmsg("%s requires a parameter",
305 : : def->defname)));
9100 tgl@sss.pgh.pa.us 306 [ + - - + :CBC 78 : switch (nodeTag(def->arg))
- - ]
307 : : {
308 : 60 : case T_Integer:
309 : 60 : return intVal(def->arg);
9100 tgl@sss.pgh.pa.us 310 :UBC 0 : case T_Float:
8084 311 [ # # ]: 0 : ereport(ERROR,
312 : : (errcode(ERRCODE_SYNTAX_ERROR),
313 : : errmsg("%s requires an integer value",
314 : : def->defname)));
315 : : break;
9100 316 : 0 : case T_String:
7792 317 [ # # ]: 0 : if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
9100 318 : 0 : return -1; /* variable length */
319 : 0 : break;
9100 tgl@sss.pgh.pa.us 320 :CBC 18 : case T_TypeName:
321 : : /* cope if grammar chooses to believe "variable" is a typename */
7792 322 [ + - ]: 18 : if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
323 : : "variable") == 0)
9100 324 : 18 : return -1; /* variable length */
9100 tgl@sss.pgh.pa.us 325 :UBC 0 : break;
8428 326 : 0 : case T_List:
327 : : /* must be an operator name */
328 : 0 : break;
9100 329 : 0 : default:
8084 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 *
3152 peter_e@gmx.net 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 : :
3034 bruce@momjian.us 355 [ # # # # : 0 : foreach(cell, (List *) def->arg)
# # ]
356 : : {
3152 peter_e@gmx.net 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
1514 dean.a.rasheed@gmail 371 :CBC 78 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
372 : : {
373 [ + - ]: 78 : ereport(ERROR,
374 : : errcode(ERRCODE_SYNTAX_ERROR),
375 : : errmsg("conflicting or redundant options"),
376 : : parser_errposition(pstate, defel->location));
377 : : }
|