/Users/deen/code/yugabyte-db/src/postgres/src/backend/commands/define.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * define.c |
4 | | * Support routines for various kinds of object creation. |
5 | | * |
6 | | * |
7 | | * Portions Copyright (c) 1996-2018, 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 | | * The "DefineFoo" routines take the parse tree and pick out the |
16 | | * appropriate arguments/flags, passing the results to the |
17 | | * corresponding "FooDefine" routines (in src/catalog) that do |
18 | | * the actual catalog-munging. These routines also verify permission |
19 | | * of the user to execute the command. |
20 | | * |
21 | | * NOTES |
22 | | * These things must be defined and committed in the following order: |
23 | | * "create function": |
24 | | * input/output, recv/send procedures |
25 | | * "create type": |
26 | | * type |
27 | | * "create operator": |
28 | | * operators |
29 | | * |
30 | | * |
31 | | *------------------------------------------------------------------------- |
32 | | */ |
33 | | #include "postgres.h" |
34 | | |
35 | | #include <ctype.h> |
36 | | #include <math.h> |
37 | | |
38 | | #include "catalog/namespace.h" |
39 | | #include "commands/defrem.h" |
40 | | #include "nodes/makefuncs.h" |
41 | | #include "parser/parse_type.h" |
42 | | #include "parser/scansup.h" |
43 | | #include "utils/builtins.h" |
44 | | |
45 | | /* |
46 | | * Extract a string value (otherwise uninterpreted) from a DefElem. |
47 | | */ |
48 | | char * |
49 | | defGetString(DefElem *def) |
50 | 6.10k | { |
51 | 6.10k | if (def->arg == NULL) |
52 | 6.10k | ereport(ERROR, |
53 | 6.10k | (errcode(ERRCODE_SYNTAX_ERROR), |
54 | 6.10k | errmsg("%s requires a parameter", |
55 | 6.10k | def->defname))); |
56 | 6.10k | switch (nodeTag(def->arg)) |
57 | 6.10k | { |
58 | 14 | case T_Integer: |
59 | 14 | return psprintf("%ld", (long) intVal(def->arg)); |
60 | 0 | case T_Float: |
61 | | |
62 | | /* |
63 | | * T_Float values are kept in string form, so this type cheat |
64 | | * works (and doesn't risk losing precision) |
65 | | */ |
66 | 0 | return strVal(def->arg); |
67 | 6.07k | case T_String: |
68 | 6.07k | return strVal(def->arg); |
69 | 16 | case T_TypeName: |
70 | 16 | return TypeNameToString((TypeName *) def->arg); |
71 | 0 | case T_List: |
72 | 0 | return NameListToString((List *) def->arg); |
73 | 0 | case T_A_Star: |
74 | 0 | return pstrdup("*"); |
75 | 0 | default: |
76 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg)); |
77 | 6.10k | } |
78 | 0 | return NULL; /* keep compiler quiet */ |
79 | 6.10k | } |
80 | | |
81 | | /* |
82 | | * Extract a numeric value (actually double) from a DefElem. |
83 | | */ |
84 | | double |
85 | | defGetNumeric(DefElem *def) |
86 | 1 | { |
87 | 1 | if (def->arg == NULL) |
88 | 1 | ereport(ERROR, |
89 | 1 | (errcode(ERRCODE_SYNTAX_ERROR), |
90 | 1 | errmsg("%s requires a numeric value", |
91 | 1 | def->defname))); |
92 | 1 | switch (nodeTag(def->arg)) |
93 | 1 | { |
94 | 0 | case T_Integer: |
95 | 0 | return (double) intVal(def->arg); |
96 | 1 | case T_Float: |
97 | 1 | return floatVal(def->arg); |
98 | 0 | default: |
99 | 0 | ereport(ERROR, |
100 | 1 | (errcode(ERRCODE_SYNTAX_ERROR), |
101 | 1 | errmsg("%s requires a numeric value", |
102 | 1 | def->defname))); |
103 | 1 | } |
104 | 0 | return 0; /* keep compiler quiet */ |
105 | 1 | } |
106 | | |
107 | | /* |
108 | | * Extract a boolean value from a DefElem. |
109 | | */ |
110 | | bool |
111 | | defGetBoolean(DefElem *def) |
112 | 880 | { |
113 | | /* |
114 | | * If no parameter given, assume "true" is meant. |
115 | | */ |
116 | 880 | if (def->arg == NULL) |
117 | 195 | return true; |
118 | | |
119 | | /* |
120 | | * Allow 0, 1, "true", "false", "on", "off" |
121 | | */ |
122 | 685 | switch (nodeTag(def->arg)) |
123 | 685 | { |
124 | 3 | case T_Integer: |
125 | 3 | switch (intVal(def->arg)) |
126 | 3 | { |
127 | 0 | case 0: |
128 | 0 | return false; |
129 | 3 | case 1: |
130 | 3 | return true; |
131 | 0 | default: |
132 | | /* otherwise, error out below */ |
133 | 0 | break; |
134 | 0 | } |
135 | 0 | break; |
136 | 682 | default: |
137 | 682 | { |
138 | 682 | char *sval = defGetString(def); |
139 | | |
140 | | /* |
141 | | * The set of strings accepted here should match up with the |
142 | | * grammar's opt_boolean production. |
143 | | */ |
144 | 682 | if (pg_strcasecmp(sval, "true") == 0) |
145 | 417 | return true; |
146 | 265 | if (pg_strcasecmp(sval, "false") == 0) |
147 | 24 | return false; |
148 | 241 | if (pg_strcasecmp(sval, "on") == 0) |
149 | 0 | return true; |
150 | 241 | if (pg_strcasecmp(sval, "off") == 0) |
151 | 241 | return false; |
152 | 0 | } |
153 | 0 | break; |
154 | 0 | } |
155 | 0 | ereport(ERROR, |
156 | 0 | (errcode(ERRCODE_SYNTAX_ERROR), |
157 | 0 | errmsg("%s requires a Boolean value", |
158 | 0 | def->defname))); |
159 | 0 | return false; /* keep compiler quiet */ |
160 | 0 | } |
161 | | |
162 | | /* |
163 | | * Extract an int32 value from a DefElem. |
164 | | */ |
165 | | int32 |
166 | | defGetInt32(DefElem *def) |
167 | 32 | { |
168 | 32 | if (def->arg == NULL) |
169 | 32 | ereport(ERROR, |
170 | 32 | (errcode(ERRCODE_SYNTAX_ERROR), |
171 | 32 | errmsg("%s requires an integer value", |
172 | 32 | def->defname))); |
173 | 32 | switch (nodeTag(def->arg)) |
174 | 32 | { |
175 | 32 | case T_Integer: |
176 | 32 | return (int32) intVal(def->arg); |
177 | 0 | default: |
178 | 0 | ereport(ERROR, |
179 | 32 | (errcode(ERRCODE_SYNTAX_ERROR), |
180 | 32 | errmsg("%s requires an integer value", |
181 | 32 | def->defname))); |
182 | 32 | } |
183 | 0 | return 0; /* keep compiler quiet */ |
184 | 32 | } |
185 | | |
186 | | /* |
187 | | * Extract an int64 value from a DefElem. |
188 | | */ |
189 | | int64 |
190 | | defGetInt64(DefElem *def) |
191 | 4 | { |
192 | 4 | if (def->arg == NULL) |
193 | 4 | ereport(ERROR, |
194 | 4 | (errcode(ERRCODE_SYNTAX_ERROR), |
195 | 4 | errmsg("%s requires a numeric value", |
196 | 4 | def->defname))); |
197 | 4 | switch (nodeTag(def->arg)) |
198 | 4 | { |
199 | 4 | case T_Integer: |
200 | 4 | return (int64) intVal(def->arg); |
201 | 0 | case T_Float: |
202 | | |
203 | | /* |
204 | | * Values too large for int4 will be represented as Float |
205 | | * constants by the lexer. Accept these if they are valid int8 |
206 | | * strings. |
207 | | */ |
208 | 0 | return DatumGetInt64(DirectFunctionCall1(int8in, |
209 | 0 | CStringGetDatum(strVal(def->arg)))); |
210 | 0 | default: |
211 | 0 | ereport(ERROR, |
212 | 4 | (errcode(ERRCODE_SYNTAX_ERROR), |
213 | 4 | errmsg("%s requires a numeric value", |
214 | 4 | def->defname))); |
215 | 4 | } |
216 | 0 | return 0; /* keep compiler quiet */ |
217 | 4 | } |
218 | | |
219 | | /* |
220 | | * Extract a possibly-qualified name (as a List of Strings) from a DefElem. |
221 | | */ |
222 | | List * |
223 | | defGetQualifiedName(DefElem *def) |
224 | 1.45k | { |
225 | 1.45k | if (def->arg == NULL) |
226 | 1.45k | ereport(ERROR, |
227 | 1.45k | (errcode(ERRCODE_SYNTAX_ERROR), |
228 | 1.45k | errmsg("%s requires a parameter", |
229 | 1.45k | def->defname))); |
230 | 1.45k | switch (nodeTag(def->arg)) |
231 | 1.45k | { |
232 | 981 | case T_TypeName: |
233 | 981 | return ((TypeName *) def->arg)->names; |
234 | 395 | case T_List: |
235 | 395 | return (List *) def->arg; |
236 | 81 | case T_String: |
237 | | /* Allow quoted name for backwards compatibility */ |
238 | 81 | return list_make1(def->arg); |
239 | 0 | default: |
240 | 0 | ereport(ERROR, |
241 | 1.45k | (errcode(ERRCODE_SYNTAX_ERROR), |
242 | 1.45k | errmsg("argument of %s must be a name", |
243 | 1.45k | def->defname))); |
244 | 1.45k | } |
245 | 0 | return NIL; /* keep compiler quiet */ |
246 | 1.45k | } |
247 | | |
248 | | /* |
249 | | * Extract a TypeName from a DefElem. |
250 | | * |
251 | | * Note: we do not accept a List arg here, because the parser will only |
252 | | * return a bare List when the name looks like an operator name. |
253 | | */ |
254 | | TypeName * |
255 | | defGetTypeName(DefElem *def) |
256 | 632 | { |
257 | 632 | if (def->arg == NULL) |
258 | 632 | ereport(ERROR, |
259 | 632 | (errcode(ERRCODE_SYNTAX_ERROR), |
260 | 632 | errmsg("%s requires a parameter", |
261 | 632 | def->defname))); |
262 | 632 | switch (nodeTag(def->arg)) |
263 | 632 | { |
264 | 631 | case T_TypeName: |
265 | 631 | return (TypeName *) def->arg; |
266 | 1 | case T_String: |
267 | | /* Allow quoted typename for backwards compatibility */ |
268 | 1 | return makeTypeNameFromNameList(list_make1(def->arg)); |
269 | 0 | default: |
270 | 0 | ereport(ERROR, |
271 | 632 | (errcode(ERRCODE_SYNTAX_ERROR), |
272 | 632 | errmsg("argument of %s must be a type name", |
273 | 632 | def->defname))); |
274 | 632 | } |
275 | 0 | return NULL; /* keep compiler quiet */ |
276 | 632 | } |
277 | | |
278 | | /* |
279 | | * Extract a type length indicator (either absolute bytes, or |
280 | | * -1 for "variable") from a DefElem. |
281 | | */ |
282 | | int |
283 | | defGetTypeLength(DefElem *def) |
284 | 18 | { |
285 | 18 | if (def->arg == NULL) |
286 | 18 | ereport(ERROR, |
287 | 18 | (errcode(ERRCODE_SYNTAX_ERROR), |
288 | 18 | errmsg("%s requires a parameter", |
289 | 18 | def->defname))); |
290 | 18 | switch (nodeTag(def->arg)) |
291 | 18 | { |
292 | 13 | case T_Integer: |
293 | 13 | return intVal(def->arg); |
294 | 0 | case T_Float: |
295 | 0 | ereport(ERROR, |
296 | 0 | (errcode(ERRCODE_SYNTAX_ERROR), |
297 | 0 | errmsg("%s requires an integer value", |
298 | 0 | def->defname))); |
299 | 0 | break; |
300 | 0 | case T_String: |
301 | 0 | if (pg_strcasecmp(strVal(def->arg), "variable") == 0) |
302 | 0 | return -1; /* variable length */ |
303 | 0 | break; |
304 | 5 | case T_TypeName: |
305 | | /* cope if grammar chooses to believe "variable" is a typename */ |
306 | 5 | if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg), |
307 | 5 | "variable") == 0) |
308 | 5 | return -1; /* variable length */ |
309 | 0 | break; |
310 | 0 | case T_List: |
311 | | /* must be an operator name */ |
312 | 0 | break; |
313 | 0 | default: |
314 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg)); |
315 | 18 | } |
316 | 0 | ereport(ERROR, |
317 | 0 | (errcode(ERRCODE_SYNTAX_ERROR), |
318 | 0 | errmsg("invalid argument for %s: \"%s\"", |
319 | 0 | def->defname, defGetString(def)))); |
320 | 0 | return 0; /* keep compiler quiet */ |
321 | 0 | } |
322 | | |
323 | | /* |
324 | | * Extract a list of string values (otherwise uninterpreted) from a DefElem. |
325 | | */ |
326 | | List * |
327 | | defGetStringList(DefElem *def) |
328 | 0 | { |
329 | 0 | ListCell *cell; |
330 | |
|
331 | 0 | if (def->arg == NULL) |
332 | 0 | ereport(ERROR, |
333 | 0 | (errcode(ERRCODE_SYNTAX_ERROR), |
334 | 0 | errmsg("%s requires a parameter", |
335 | 0 | def->defname))); |
336 | 0 | if (nodeTag(def->arg) != T_List) |
337 | 0 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg)); |
338 | |
|
339 | 0 | foreach(cell, (List *) def->arg) |
340 | 0 | { |
341 | 0 | Node *str = (Node *) lfirst(cell); |
342 | |
|
343 | 0 | if (!IsA(str, String)) |
344 | 0 | elog(ERROR, "unexpected node type in name list: %d", |
345 | 0 | (int) nodeTag(str)); |
346 | 0 | } |
347 | |
|
348 | 0 | return (List *) def->arg; |
349 | 0 | } |