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-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 *
6240 tgl@sss.pgh.pa.us 34 :CBC 38558 : defGetString(DefElem *def)
35 : : {
36 [ - + ]: 38558 : if (def->arg == NULL)
8325 tgl@sss.pgh.pa.us 37 [ # # ]:UBC 0 : ereport(ERROR,
38 : : (errcode(ERRCODE_SYNTAX_ERROR),
39 : : errmsg("%s requires a parameter",
40 : : def->defname)));
6240 tgl@sss.pgh.pa.us 41 [ + + + + :CBC 38558 : switch (nodeTag(def->arg))
+ - - - ]
42 : : {
9341 43 : 737 : case T_Integer:
147 peter@eisentraut.org 44 :GNC 737 : return psprintf("%d", intVal(def->arg));
9341 tgl@sss.pgh.pa.us 45 :CBC 72 : case T_Float:
1572 peter@eisentraut.org 46 : 72 : return castNode(Float, def->arg)->fval;
47 : 372 : case T_Boolean:
48 [ + + ]: 372 : return boolVal(def->arg) ? "true" : "false";
9341 tgl@sss.pgh.pa.us 49 : 33940 : case T_String:
6240 50 : 33940 : return strVal(def->arg);
9341 51 : 3437 : case T_TypeName:
6240 52 : 3437 : return TypeNameToString((TypeName *) def->arg);
8669 tgl@sss.pgh.pa.us 53 :UBC 0 : case T_List:
6240 54 : 0 : return NameListToString((List *) def->arg);
6070 55 : 0 : case T_A_Star:
56 : 0 : return pstrdup("*");
9341 57 : 0 : default:
6240 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
9712 tgl@sss.pgh.pa.us 67 :CBC 2242 : defGetNumeric(DefElem *def)
68 : : {
69 [ - + ]: 2242 : if (def->arg == NULL)
8325 tgl@sss.pgh.pa.us 70 [ # # ]:UBC 0 : ereport(ERROR,
71 : : (errcode(ERRCODE_SYNTAX_ERROR),
72 : : errmsg("%s requires a numeric value",
73 : : def->defname)));
9712 tgl@sss.pgh.pa.us 74 [ + + - ]:CBC 2242 : switch (nodeTag(def->arg))
75 : : {
76 : 2224 : case T_Integer:
77 : 2224 : return (double) intVal(def->arg);
78 : 18 : case T_Float:
79 : 18 : return floatVal(def->arg);
9712 tgl@sss.pgh.pa.us 80 :UBC 0 : default:
8325 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
6240 tgl@sss.pgh.pa.us 93 :CBC 28136 : defGetBoolean(DefElem *def)
94 : : {
95 : : /*
96 : : * If no parameter value given, assume "true" is meant.
97 : : */
98 [ + + ]: 28136 : if (def->arg == NULL)
8026 99 : 14031 : return true;
100 : :
101 : : /*
102 : : * Allow 0, 1, "true", "false", "on", "off"
103 : : */
6240 104 [ + + ]: 14105 : switch (nodeTag(def->arg))
105 : : {
7247 bruce@momjian.us 106 : 274 : case T_Integer:
6240 tgl@sss.pgh.pa.us 107 [ + + + ]: 274 : switch (intVal(def->arg))
108 : : {
7246 109 : 232 : case 0:
110 : 232 : return false;
111 : 38 : case 1:
112 : 38 : return true;
113 : 4 : default:
114 : : /* otherwise, error out below */
115 : 4 : break;
116 : : }
7247 bruce@momjian.us 117 : 4 : break;
118 : 13831 : default:
119 : : {
6240 tgl@sss.pgh.pa.us 120 : 13831 : 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 : : */
7246 126 [ + + ]: 13831 : if (pg_strcasecmp(sval, "true") == 0)
127 : 955 : return true;
128 [ + + ]: 12876 : if (pg_strcasecmp(sval, "false") == 0)
129 : 883 : return false;
6127 130 [ + + ]: 11993 : if (pg_strcasecmp(sval, "on") == 0)
131 : 191 : return true;
132 [ + + ]: 11802 : if (pg_strcasecmp(sval, "off") == 0)
133 : 11786 : return false;
134 : : }
7247 bruce@momjian.us 135 : 16 : break;
136 : : }
8026 tgl@sss.pgh.pa.us 137 [ + - ]: 20 : 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
4553 148 : 145714 : defGetInt32(DefElem *def)
149 : : {
150 [ + + ]: 145714 : if (def->arg == NULL)
4553 tgl@sss.pgh.pa.us 151 [ + - ]:GBC 4 : ereport(ERROR,
152 : : (errcode(ERRCODE_SYNTAX_ERROR),
153 : : errmsg("%s requires an integer value",
154 : : def->defname)));
4553 tgl@sss.pgh.pa.us 155 [ + + ]:CBC 145710 : switch (nodeTag(def->arg))
156 : : {
157 : 145706 : case T_Integer:
158 : 145706 : return (int32) intVal(def->arg);
4553 tgl@sss.pgh.pa.us 159 :GBC 4 : default:
160 [ + - ]: 4 : 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
8749 tgl@sss.pgh.pa.us 172 :CBC 521 : defGetInt64(DefElem *def)
173 : : {
174 [ - + ]: 521 : if (def->arg == NULL)
8325 tgl@sss.pgh.pa.us 175 [ # # ]:UBC 0 : ereport(ERROR,
176 : : (errcode(ERRCODE_SYNTAX_ERROR),
177 : : errmsg("%s requires a numeric value",
178 : : def->defname)));
8749 tgl@sss.pgh.pa.us 179 [ + + - ]:CBC 521 : switch (nodeTag(def->arg))
180 : : {
181 : 479 : case T_Integer:
182 : 479 : return (int64) intVal(def->arg);
183 : 42 : 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 : 42 : return DatumGetInt64(DirectFunctionCall1(int8in,
191 : : CStringGetDatum(castNode(Float, def->arg)->fval)));
8749 tgl@sss.pgh.pa.us 192 :UBC 0 : default:
8325 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
1278 tgl@sss.pgh.pa.us 205 :CBC 147 : defGetObjectId(DefElem *def)
206 : : {
207 [ - + ]: 147 : if (def->arg == NULL)
1278 tgl@sss.pgh.pa.us 208 [ # # ]:UBC 0 : ereport(ERROR,
209 : : (errcode(ERRCODE_SYNTAX_ERROR),
210 : : errmsg("%s requires a numeric value",
211 : : def->defname)));
1278 tgl@sss.pgh.pa.us 212 [ + - - ]:CBC 147 : switch (nodeTag(def->arg))
213 : : {
214 : 147 : case T_Integer:
215 : 147 : return (Oid) intVal(def->arg);
1278 tgl@sss.pgh.pa.us 216 :UBC 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 *
8792 tgl@sss.pgh.pa.us 238 :CBC 9513 : defGetQualifiedName(DefElem *def)
239 : : {
240 [ - + ]: 9513 : if (def->arg == NULL)
8325 tgl@sss.pgh.pa.us 241 [ # # ]:UBC 0 : ereport(ERROR,
242 : : (errcode(ERRCODE_SYNTAX_ERROR),
243 : : errmsg("%s requires a parameter",
244 : : def->defname)));
8792 tgl@sss.pgh.pa.us 245 [ + + + - ]:CBC 9513 : switch (nodeTag(def->arg))
246 : : {
247 : 5894 : case T_TypeName:
248 : 5894 : return ((TypeName *) def->arg)->names;
8669 249 : 1623 : case T_List:
250 : 1623 : return (List *) def->arg;
8792 251 : 1996 : case T_String:
252 : : /* Allow quoted name for backwards compatibility */
8014 neilc@samurai.com 253 : 1996 : return list_make1(def->arg);
8792 tgl@sss.pgh.pa.us 254 :UBC 0 : default:
8325 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 *
8803 tgl@sss.pgh.pa.us 270 :CBC 3692 : defGetTypeName(DefElem *def)
271 : : {
272 [ - + ]: 3692 : if (def->arg == NULL)
8325 tgl@sss.pgh.pa.us 273 [ # # ]:UBC 0 : ereport(ERROR,
274 : : (errcode(ERRCODE_SYNTAX_ERROR),
275 : : errmsg("%s requires a parameter",
276 : : def->defname)));
8803 tgl@sss.pgh.pa.us 277 [ + + - ]:CBC 3692 : switch (nodeTag(def->arg))
278 : : {
279 : 3688 : case T_TypeName:
280 : 3688 : return (TypeName *) def->arg;
281 : 4 : case T_String:
282 : : /* Allow quoted typename for backwards compatibility */
7357 283 : 4 : return makeTypeNameFromNameList(list_make1(def->arg));
8803 tgl@sss.pgh.pa.us 284 :UBC 0 : default:
8325 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
10466 bruce@momjian.us 298 :CBC 84 : defGetTypeLength(DefElem *def)
299 : : {
9341 tgl@sss.pgh.pa.us 300 [ - + ]: 84 : if (def->arg == NULL)
8325 tgl@sss.pgh.pa.us 301 [ # # ]:UBC 0 : ereport(ERROR,
302 : : (errcode(ERRCODE_SYNTAX_ERROR),
303 : : errmsg("%s requires a parameter",
304 : : def->defname)));
9341 tgl@sss.pgh.pa.us 305 [ + - - + :CBC 84 : switch (nodeTag(def->arg))
- - ]
306 : : {
307 : 64 : case T_Integer:
308 : 64 : return intVal(def->arg);
9341 tgl@sss.pgh.pa.us 309 :UBC 0 : case T_Float:
8325 310 [ # # ]: 0 : ereport(ERROR,
311 : : (errcode(ERRCODE_SYNTAX_ERROR),
312 : : errmsg("%s requires an integer value",
313 : : def->defname)));
314 : : break;
9341 315 : 0 : case T_String:
8033 316 [ # # ]: 0 : if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
9341 317 : 0 : return -1; /* variable length */
318 : 0 : break;
9341 tgl@sss.pgh.pa.us 319 :CBC 20 : case T_TypeName:
320 : : /* cope if grammar chooses to believe "variable" is a typename */
8033 321 [ + - ]: 20 : if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
322 : : "variable") == 0)
9341 323 : 20 : return -1; /* variable length */
9341 tgl@sss.pgh.pa.us 324 :UBC 0 : break;
8669 325 : 0 : case T_List:
326 : : /* must be an operator name */
327 : 0 : break;
9341 328 : 0 : default:
8325 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 *
3393 peter_e@gmx.net 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)));
116 fujii@postgresql.org 351 [ # # ]:UNC 0 : if (!IsA(def->arg, List))
3393 peter_e@gmx.net 352 [ # # ]:UBC 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
353 : :
3275 bruce@momjian.us 354 [ # # # # : 0 : foreach(cell, (List *) def->arg)
# # ]
355 : : {
3393 peter_e@gmx.net 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
1755 dean.a.rasheed@gmail 370 :CBC 111 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
371 : : {
372 [ + - ]: 111 : ereport(ERROR,
373 : : errcode(ERRCODE_SYNTAX_ERROR),
374 : : errmsg("conflicting or redundant options"),
375 : : parser_errposition(pstate, defel->location));
376 : : }
|