PostgreSQL Source Code  git master
define.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * define.c
4  * Support routines for various kinds of object creation.
5  *
6  *
7  * Portions Copyright (c) 1996-2022, 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 *
50 {
51  if (def->arg == NULL)
52  ereport(ERROR,
53  (errcode(ERRCODE_SYNTAX_ERROR),
54  errmsg("%s requires a parameter",
55  def->defname)));
56  switch (nodeTag(def->arg))
57  {
58  case T_Integer:
59  return psprintf("%ld", (long) intVal(def->arg));
60  case T_Float:
61  return castNode(Float, def->arg)->fval;
62  case T_Boolean:
63  return boolVal(def->arg) ? "true" : "false";
64  case T_String:
65  return strVal(def->arg);
66  case T_TypeName:
67  return TypeNameToString((TypeName *) def->arg);
68  case T_List:
69  return NameListToString((List *) def->arg);
70  case T_A_Star:
71  return pstrdup("*");
72  default:
73  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
74  }
75  return NULL; /* keep compiler quiet */
76 }
77 
78 /*
79  * Extract a numeric value (actually double) from a DefElem.
80  */
81 double
83 {
84  if (def->arg == NULL)
85  ereport(ERROR,
86  (errcode(ERRCODE_SYNTAX_ERROR),
87  errmsg("%s requires a numeric value",
88  def->defname)));
89  switch (nodeTag(def->arg))
90  {
91  case T_Integer:
92  return (double) intVal(def->arg);
93  case T_Float:
94  return floatVal(def->arg);
95  default:
96  ereport(ERROR,
97  (errcode(ERRCODE_SYNTAX_ERROR),
98  errmsg("%s requires a numeric value",
99  def->defname)));
100  }
101  return 0; /* keep compiler quiet */
102 }
103 
104 /*
105  * Extract a boolean value from a DefElem.
106  */
107 bool
109 {
110  /*
111  * If no parameter given, assume "true" is meant.
112  */
113  if (def->arg == NULL)
114  return true;
115 
116  /*
117  * Allow 0, 1, "true", "false", "on", "off"
118  */
119  switch (nodeTag(def->arg))
120  {
121  case T_Integer:
122  switch (intVal(def->arg))
123  {
124  case 0:
125  return false;
126  case 1:
127  return true;
128  default:
129  /* otherwise, error out below */
130  break;
131  }
132  break;
133  default:
134  {
135  char *sval = defGetString(def);
136 
137  /*
138  * The set of strings accepted here should match up with the
139  * grammar's opt_boolean_or_string production.
140  */
141  if (pg_strcasecmp(sval, "true") == 0)
142  return true;
143  if (pg_strcasecmp(sval, "false") == 0)
144  return false;
145  if (pg_strcasecmp(sval, "on") == 0)
146  return true;
147  if (pg_strcasecmp(sval, "off") == 0)
148  return false;
149  }
150  break;
151  }
152  ereport(ERROR,
153  (errcode(ERRCODE_SYNTAX_ERROR),
154  errmsg("%s requires a Boolean value",
155  def->defname)));
156  return false; /* keep compiler quiet */
157 }
158 
159 /*
160  * Extract an int32 value from a DefElem.
161  */
162 int32
164 {
165  if (def->arg == NULL)
166  ereport(ERROR,
167  (errcode(ERRCODE_SYNTAX_ERROR),
168  errmsg("%s requires an integer value",
169  def->defname)));
170  switch (nodeTag(def->arg))
171  {
172  case T_Integer:
173  return (int32) intVal(def->arg);
174  default:
175  ereport(ERROR,
176  (errcode(ERRCODE_SYNTAX_ERROR),
177  errmsg("%s requires an integer value",
178  def->defname)));
179  }
180  return 0; /* keep compiler quiet */
181 }
182 
183 /*
184  * Extract an int64 value from a DefElem.
185  */
186 int64
188 {
189  if (def->arg == NULL)
190  ereport(ERROR,
191  (errcode(ERRCODE_SYNTAX_ERROR),
192  errmsg("%s requires a numeric value",
193  def->defname)));
194  switch (nodeTag(def->arg))
195  {
196  case T_Integer:
197  return (int64) intVal(def->arg);
198  case T_Float:
199 
200  /*
201  * Values too large for int4 will be represented as Float
202  * constants by the lexer. Accept these if they are valid int8
203  * strings.
204  */
206  CStringGetDatum(castNode(Float, def->arg)->fval)));
207  default:
208  ereport(ERROR,
209  (errcode(ERRCODE_SYNTAX_ERROR),
210  errmsg("%s requires a numeric value",
211  def->defname)));
212  }
213  return 0; /* keep compiler quiet */
214 }
215 
216 /*
217  * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
218  */
219 List *
221 {
222  if (def->arg == NULL)
223  ereport(ERROR,
224  (errcode(ERRCODE_SYNTAX_ERROR),
225  errmsg("%s requires a parameter",
226  def->defname)));
227  switch (nodeTag(def->arg))
228  {
229  case T_TypeName:
230  return ((TypeName *) def->arg)->names;
231  case T_List:
232  return (List *) def->arg;
233  case T_String:
234  /* Allow quoted name for backwards compatibility */
235  return list_make1(def->arg);
236  default:
237  ereport(ERROR,
238  (errcode(ERRCODE_SYNTAX_ERROR),
239  errmsg("argument of %s must be a name",
240  def->defname)));
241  }
242  return NIL; /* keep compiler quiet */
243 }
244 
245 /*
246  * Extract a TypeName from a DefElem.
247  *
248  * Note: we do not accept a List arg here, because the parser will only
249  * return a bare List when the name looks like an operator name.
250  */
251 TypeName *
253 {
254  if (def->arg == NULL)
255  ereport(ERROR,
256  (errcode(ERRCODE_SYNTAX_ERROR),
257  errmsg("%s requires a parameter",
258  def->defname)));
259  switch (nodeTag(def->arg))
260  {
261  case T_TypeName:
262  return (TypeName *) def->arg;
263  case T_String:
264  /* Allow quoted typename for backwards compatibility */
266  default:
267  ereport(ERROR,
268  (errcode(ERRCODE_SYNTAX_ERROR),
269  errmsg("argument of %s must be a type name",
270  def->defname)));
271  }
272  return NULL; /* keep compiler quiet */
273 }
274 
275 /*
276  * Extract a type length indicator (either absolute bytes, or
277  * -1 for "variable") from a DefElem.
278  */
279 int
281 {
282  if (def->arg == NULL)
283  ereport(ERROR,
284  (errcode(ERRCODE_SYNTAX_ERROR),
285  errmsg("%s requires a parameter",
286  def->defname)));
287  switch (nodeTag(def->arg))
288  {
289  case T_Integer:
290  return intVal(def->arg);
291  case T_Float:
292  ereport(ERROR,
293  (errcode(ERRCODE_SYNTAX_ERROR),
294  errmsg("%s requires an integer value",
295  def->defname)));
296  break;
297  case T_String:
298  if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
299  return -1; /* variable length */
300  break;
301  case T_TypeName:
302  /* cope if grammar chooses to believe "variable" is a typename */
304  "variable") == 0)
305  return -1; /* variable length */
306  break;
307  case T_List:
308  /* must be an operator name */
309  break;
310  default:
311  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
312  }
313  ereport(ERROR,
314  (errcode(ERRCODE_SYNTAX_ERROR),
315  errmsg("invalid argument for %s: \"%s\"",
316  def->defname, defGetString(def))));
317  return 0; /* keep compiler quiet */
318 }
319 
320 /*
321  * Extract a list of string values (otherwise uninterpreted) from a DefElem.
322  */
323 List *
325 {
326  ListCell *cell;
327 
328  if (def->arg == NULL)
329  ereport(ERROR,
330  (errcode(ERRCODE_SYNTAX_ERROR),
331  errmsg("%s requires a parameter",
332  def->defname)));
333  if (nodeTag(def->arg) != T_List)
334  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
335 
336  foreach(cell, (List *) def->arg)
337  {
338  Node *str = (Node *) lfirst(cell);
339 
340  if (!IsA(str, String))
341  elog(ERROR, "unexpected node type in name list: %d",
342  (int) nodeTag(str));
343  }
344 
345  return (List *) def->arg;
346 }
347 
348 /*
349  * Raise an error about a conflicting DefElem.
350  */
351 void
353 {
354  ereport(ERROR,
355  errcode(ERRCODE_SYNTAX_ERROR),
356  errmsg("conflicting or redundant options"),
357  parser_errposition(pstate, defel->location));
358 }
signed int int32
Definition: c.h:429
int32 defGetInt32(DefElem *def)
Definition: define.c:163
int defGetTypeLength(DefElem *def)
Definition: define.c:280
bool defGetBoolean(DefElem *def)
Definition: define.c:108
List * defGetQualifiedName(DefElem *def)
Definition: define.c:220
char * defGetString(DefElem *def)
Definition: define.c:49
int64 defGetInt64(DefElem *def)
Definition: define.c:187
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:352
double defGetNumeric(DefElem *def)
Definition: define.c:82
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:252
List * defGetStringList(DefElem *def)
Definition: define.c:324
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
Datum int8in(PG_FUNCTION_ARGS)
Definition: int8.c:51
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:457
char * pstrdup(const char *in)
Definition: mcxt.c:1305
char * NameListToString(List *names)
Definition: namespace.c:3148
#define IsA(nodeptr, _type_)
Definition: nodes.h:624
#define nodeTag(nodeptr)
Definition: nodes.h:578
@ T_List
Definition: nodes.h:317
@ T_TypeName
Definition: nodes.h:473
@ T_Float
Definition: nodes.h:309
@ T_String
Definition: nodes.h:311
@ T_Integer
Definition: nodes.h:308
@ T_A_Star
Definition: nodes.h:458
@ T_Boolean
Definition: nodes.h:310
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:480
#define lfirst(lc)
Definition: pg_list.h:169
#define NIL
Definition: pg_list.h:65
#define list_make1(x1)
Definition: pg_list.h:206
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define CStringGetDatum(X)
Definition: postgres.h:622
#define DatumGetInt64(X)
Definition: postgres.h:651
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
char * defname
Definition: parsenodes.h:765
int location
Definition: parsenodes.h:769
Node * arg
Definition: parsenodes.h:766
Definition: value.h:46
Definition: pg_list.h:51
Definition: nodes.h:574
Definition: value.h:58
#define boolVal(v)
Definition: value.h:71
#define intVal(v)
Definition: value.h:69
#define strVal(v)
Definition: value.h:72
#define floatVal(v)
Definition: value.h:70