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 *
6189 tgl@sss.pgh.pa.us 34 :CBC 32967 : defGetString(DefElem *def)
35 : : {
36 [ - + ]: 32967 : if (def->arg == NULL)
8274 tgl@sss.pgh.pa.us 37 [ # # ]:UBC 0 : ereport(ERROR,
38 : : (errcode(ERRCODE_SYNTAX_ERROR),
39 : : errmsg("%s requires a parameter",
40 : : def->defname)));
6189 tgl@sss.pgh.pa.us 41 [ + + + + :CBC 32967 : switch (nodeTag(def->arg))
+ - - - ]
42 : : {
9290 43 : 555 : case T_Integer:
96 peter@eisentraut.org 44 :GNC 555 : return psprintf("%d", intVal(def->arg));
9290 tgl@sss.pgh.pa.us 45 :CBC 58 : case T_Float:
1521 peter@eisentraut.org 46 : 58 : return castNode(Float, def->arg)->fval;
47 : 293 : case T_Boolean:
48 [ + + ]: 293 : return boolVal(def->arg) ? "true" : "false";
9290 tgl@sss.pgh.pa.us 49 : 29098 : case T_String:
6189 50 : 29098 : return strVal(def->arg);
9290 51 : 2963 : case T_TypeName:
6189 52 : 2963 : return TypeNameToString((TypeName *) def->arg);
8618 tgl@sss.pgh.pa.us 53 :UBC 0 : case T_List:
6189 54 : 0 : return NameListToString((List *) def->arg);
6019 55 : 0 : case T_A_Star:
56 : 0 : return pstrdup("*");
9290 57 : 0 : default:
6189 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
9661 tgl@sss.pgh.pa.us 67 :CBC 2041 : defGetNumeric(DefElem *def)
68 : : {
69 [ - + ]: 2041 : if (def->arg == NULL)
8274 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)));
9661 tgl@sss.pgh.pa.us 74 [ + + - ]:CBC 2041 : switch (nodeTag(def->arg))
75 : : {
76 : 2031 : case T_Integer:
77 : 2031 : return (double) intVal(def->arg);
78 : 10 : case T_Float:
79 : 10 : return floatVal(def->arg);
9661 tgl@sss.pgh.pa.us 80 :UBC 0 : default:
8274 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
6189 tgl@sss.pgh.pa.us 93 :CBC 22451 : defGetBoolean(DefElem *def)
94 : : {
95 : : /*
96 : : * If no parameter value given, assume "true" is meant.
97 : : */
98 [ + + ]: 22451 : if (def->arg == NULL)
7975 99 : 11543 : return true;
100 : :
101 : : /*
102 : : * Allow 0, 1, "true", "false", "on", "off"
103 : : */
6189 104 [ + + ]: 10908 : switch (nodeTag(def->arg))
105 : : {
7196 bruce@momjian.us 106 : 245 : case T_Integer:
6189 tgl@sss.pgh.pa.us 107 [ + + + ]: 245 : switch (intVal(def->arg))
108 : : {
7195 109 : 213 : case 0:
110 : 213 : return false;
111 : 29 : case 1:
112 : 29 : return true;
113 : 3 : default:
114 : : /* otherwise, error out below */
115 : 3 : break;
116 : : }
7196 bruce@momjian.us 117 : 3 : break;
118 : 10663 : default:
119 : : {
6189 tgl@sss.pgh.pa.us 120 : 10663 : 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 : : */
7195 126 [ + + ]: 10663 : if (pg_strcasecmp(sval, "true") == 0)
127 : 855 : return true;
128 [ + + ]: 9808 : if (pg_strcasecmp(sval, "false") == 0)
129 : 749 : return false;
6076 130 [ + + ]: 9059 : if (pg_strcasecmp(sval, "on") == 0)
131 : 150 : return true;
132 [ + + ]: 8909 : if (pg_strcasecmp(sval, "off") == 0)
133 : 8897 : return false;
134 : : }
7196 bruce@momjian.us 135 : 12 : break;
136 : : }
7975 tgl@sss.pgh.pa.us 137 [ + - ]: 15 : 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
4502 148 : 1124 : defGetInt32(DefElem *def)
149 : : {
150 [ + + ]: 1124 : if (def->arg == NULL)
4502 tgl@sss.pgh.pa.us 151 [ + - ]:GBC 3 : ereport(ERROR,
152 : : (errcode(ERRCODE_SYNTAX_ERROR),
153 : : errmsg("%s requires an integer value",
154 : : def->defname)));
4502 tgl@sss.pgh.pa.us 155 [ + + ]:CBC 1121 : switch (nodeTag(def->arg))
156 : : {
157 : 1118 : case T_Integer:
158 : 1118 : return (int32) intVal(def->arg);
4502 tgl@sss.pgh.pa.us 159 :GBC 3 : default:
160 [ + - ]: 3 : 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
8698 tgl@sss.pgh.pa.us 172 :CBC 441 : defGetInt64(DefElem *def)
173 : : {
174 [ - + ]: 441 : if (def->arg == NULL)
8274 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)));
8698 tgl@sss.pgh.pa.us 179 [ + + - ]:CBC 441 : switch (nodeTag(def->arg))
180 : : {
181 : 409 : case T_Integer:
182 : 409 : return (int64) intVal(def->arg);
183 : 32 : 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 : 32 : return DatumGetInt64(DirectFunctionCall1(int8in,
191 : : CStringGetDatum(castNode(Float, def->arg)->fval)));
8698 tgl@sss.pgh.pa.us 192 :UBC 0 : default:
8274 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
1227 tgl@sss.pgh.pa.us 205 :CBC 133 : defGetObjectId(DefElem *def)
206 : : {
207 [ - + ]: 133 : if (def->arg == NULL)
1227 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)));
1227 tgl@sss.pgh.pa.us 212 [ + - - ]:CBC 133 : switch (nodeTag(def->arg))
213 : : {
214 : 133 : case T_Integer:
215 : 133 : return (Oid) intVal(def->arg);
1227 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 *
8741 tgl@sss.pgh.pa.us 238 :CBC 8431 : defGetQualifiedName(DefElem *def)
239 : : {
240 [ - + ]: 8431 : if (def->arg == NULL)
8274 tgl@sss.pgh.pa.us 241 [ # # ]:UBC 0 : ereport(ERROR,
242 : : (errcode(ERRCODE_SYNTAX_ERROR),
243 : : errmsg("%s requires a parameter",
244 : : def->defname)));
8741 tgl@sss.pgh.pa.us 245 [ + + + - ]:CBC 8431 : switch (nodeTag(def->arg))
246 : : {
247 : 5236 : case T_TypeName:
248 : 8431 : return ((TypeName *) def->arg)->names;
8618 249 : 1389 : case T_List:
250 : 1389 : return (List *) def->arg;
8741 251 : 1806 : case T_String:
252 : : /* Allow quoted name for backwards compatibility */
7963 neilc@samurai.com 253 : 1806 : return list_make1(def->arg);
8741 tgl@sss.pgh.pa.us 254 :UBC 0 : default:
8274 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 *
8752 tgl@sss.pgh.pa.us 270 :CBC 3119 : defGetTypeName(DefElem *def)
271 : : {
272 [ - + ]: 3119 : if (def->arg == NULL)
8274 tgl@sss.pgh.pa.us 273 [ # # ]:UBC 0 : ereport(ERROR,
274 : : (errcode(ERRCODE_SYNTAX_ERROR),
275 : : errmsg("%s requires a parameter",
276 : : def->defname)));
8752 tgl@sss.pgh.pa.us 277 [ + + - ]:CBC 3119 : switch (nodeTag(def->arg))
278 : : {
279 : 3116 : case T_TypeName:
280 : 3119 : return (TypeName *) def->arg;
281 : 3 : case T_String:
282 : : /* Allow quoted typename for backwards compatibility */
7306 283 : 3 : return makeTypeNameFromNameList(list_make1(def->arg));
8752 tgl@sss.pgh.pa.us 284 :UBC 0 : default:
8274 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
10415 bruce@momjian.us 298 :CBC 78 : defGetTypeLength(DefElem *def)
299 : : {
9290 tgl@sss.pgh.pa.us 300 [ - + ]: 78 : if (def->arg == NULL)
8274 tgl@sss.pgh.pa.us 301 [ # # ]:UBC 0 : ereport(ERROR,
302 : : (errcode(ERRCODE_SYNTAX_ERROR),
303 : : errmsg("%s requires a parameter",
304 : : def->defname)));
9290 tgl@sss.pgh.pa.us 305 [ + - - + :CBC 78 : switch (nodeTag(def->arg))
- - ]
306 : : {
307 : 60 : case T_Integer:
308 : 60 : return intVal(def->arg);
9290 tgl@sss.pgh.pa.us 309 :UBC 0 : case T_Float:
8274 310 [ # # ]: 0 : ereport(ERROR,
311 : : (errcode(ERRCODE_SYNTAX_ERROR),
312 : : errmsg("%s requires an integer value",
313 : : def->defname)));
314 : : break;
9290 315 : 0 : case T_String:
7982 316 [ # # ]: 0 : if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
9290 317 : 0 : return -1; /* variable length */
318 : 0 : break;
9290 tgl@sss.pgh.pa.us 319 :CBC 18 : case T_TypeName:
320 : : /* cope if grammar chooses to believe "variable" is a typename */
7982 321 [ + - ]: 18 : if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
322 : : "variable") == 0)
9290 323 : 18 : return -1; /* variable length */
9290 tgl@sss.pgh.pa.us 324 :UBC 0 : break;
8618 325 : 0 : case T_List:
326 : : /* must be an operator name */
327 : 0 : break;
9290 328 : 0 : default:
8274 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 *
3342 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)));
65 fujii@postgresql.org 351 [ # # ]:UNC 0 : if (!IsA(def->arg, List))
3342 peter_e@gmx.net 352 [ # # ]:UBC 0 : elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
353 : :
3224 bruce@momjian.us 354 [ # # # # : 0 : foreach(cell, (List *) def->arg)
# # ]
355 : : {
3342 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
1704 dean.a.rasheed@gmail 370 :CBC 84 : errorConflictingDefElem(DefElem *defel, ParseState *pstate)
371 : : {
372 [ + - ]: 84 : ereport(ERROR,
373 : : errcode(ERRCODE_SYNTAX_ERROR),
374 : : errmsg("conflicting or redundant options"),
375 : : parser_errposition(pstate, defel->location));
376 : : }
|