]> granicus.if.org Git - postgresql/blob - src/backend/commands/define.c
30a175c659e84241a195a70d0e9ec2848e02c3ad
[postgresql] / src / backend / commands / define.c
1 /*-------------------------------------------------------------------------
2  *
3  * define.c
4  *
5  *        These routines execute some of the CREATE statements.  In an earlier
6  *        version of Postgres, these were "define" statements.
7  *
8  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
9  * Portions Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.64 2001/10/28 06:25:42 momjian Exp $
14  *
15  * DESCRIPTION
16  *        The "DefineFoo" routines take the parse tree and pick out the
17  *        appropriate arguments/flags, passing the results to the
18  *        corresponding "FooDefine" routines (in src/catalog) that do
19  *        the actual catalog-munging.  These routines also verify permission
20  *        of the user to execute the command.
21  *
22  * NOTES
23  *        These things must be defined and committed in the following order:
24  *              "create function":
25  *                              input/output, recv/send procedures
26  *              "create type":
27  *                              type
28  *              "create operator":
29  *                              operators
30  *
31  *              Most of the parse-tree manipulation routines are defined in
32  *              commands/manip.c.
33  *
34  *-------------------------------------------------------------------------
35  */
36 #include "postgres.h"
37
38 #include <ctype.h>
39 #include <math.h>
40
41 #include "access/heapam.h"
42 #include "catalog/catname.h"
43 #include "catalog/pg_aggregate.h"
44 #include "catalog/pg_language.h"
45 #include "catalog/pg_operator.h"
46 #include "catalog/pg_proc.h"
47 #include "catalog/pg_type.h"
48 #include "commands/defrem.h"
49 #include "fmgr.h"
50 #include "miscadmin.h"
51 #include "optimizer/cost.h"
52 #include "parser/parse_expr.h"
53 #include "utils/builtins.h"
54 #include "utils/syscache.h"
55
56 static char *defGetString(DefElem *def);
57 static double defGetNumeric(DefElem *def);
58 static int      defGetTypeLength(DefElem *def);
59
60 #define DEFAULT_TYPDELIM                ','
61
62
63 static void
64 case_translate_language_name(const char *input, char *output)
65 {
66 /*
67  *      Translate the input language name to lower case, except if it's "C",
68  * translate to upper case.
69  */
70         int                     i;
71
72         for (i = 0; i < NAMEDATALEN - 1 && input[i]; ++i)
73                 output[i] = tolower((unsigned char) input[i]);
74
75         output[i] = '\0';
76
77         if (strcmp(output, "c") == 0)
78                 output[0] = 'C';
79 }
80
81
82
83 static void
84 compute_return_type(TypeName *returnType,
85                                         char **prorettype_p, bool *returnsSet_p)
86 {
87 /*
88  *       Examine the "returns" clause returnType of the CREATE FUNCTION statement
89  *       and return information about it as *prorettype_p and *returnsSet.
90  */
91         *prorettype_p = TypeNameToInternalName(returnType);
92         *returnsSet_p = returnType->setof;
93 }
94
95
96 static void
97 compute_full_attributes(List *parameters,
98                                                 int32 *byte_pct_p, int32 *perbyte_cpu_p,
99                                                 int32 *percall_cpu_p, int32 *outin_ratio_p,
100                                                 bool *canCache_p, bool *isStrict_p)
101 {
102 /*-------------
103  *       Interpret the parameters *parameters and return their contents as
104  *       *byte_pct_p, etc.
105  *
106  *      These parameters supply optional information about a function.
107  *      All have defaults if not specified.
108  *
109  *      Note: currently, only two of these parameters actually do anything:
110  *
111  *       * canCache means the optimizer's constant-folder is allowed to
112  *         pre-evaluate the function when all its inputs are constants.
113  *
114  *       * isStrict means the function should not be called when any NULL
115  *         inputs are present; instead a NULL result value should be assumed.
116  *
117  *      The other four parameters are not used anywhere.        They used to be
118  *      used in the "expensive functions" optimizer, but that's been dead code
119  *      for a long time.
120  *
121  *      Since canCache and isStrict are useful for any function, we now allow
122  *      attributes to be supplied for all functions regardless of language.
123  *------------
124  */
125         List       *pl;
126
127         /* the defaults */
128         *byte_pct_p = BYTE_PCT;
129         *perbyte_cpu_p = PERBYTE_CPU;
130         *percall_cpu_p = PERCALL_CPU;
131         *outin_ratio_p = OUTIN_RATIO;
132         *canCache_p = false;
133         *isStrict_p = false;
134
135         foreach(pl, parameters)
136         {
137                 DefElem    *param = (DefElem *) lfirst(pl);
138
139                 if (strcasecmp(param->defname, "iscachable") == 0)
140                         *canCache_p = true;
141                 else if (strcasecmp(param->defname, "isstrict") == 0)
142                         *isStrict_p = true;
143                 else if (strcasecmp(param->defname, "trusted") == 0)
144                 {
145                         /*
146                          * we don't have untrusted functions any more. The 4.2
147                          * implementation is lousy anyway so I took it out. -ay 10/94
148                          */
149                         elog(ERROR, "untrusted function has been decommissioned.");
150                 }
151                 else if (strcasecmp(param->defname, "byte_pct") == 0)
152                         *byte_pct_p = (int) defGetNumeric(param);
153                 else if (strcasecmp(param->defname, "perbyte_cpu") == 0)
154                         *perbyte_cpu_p = (int) defGetNumeric(param);
155                 else if (strcasecmp(param->defname, "percall_cpu") == 0)
156                         *percall_cpu_p = (int) defGetNumeric(param);
157                 else if (strcasecmp(param->defname, "outin_ratio") == 0)
158                         *outin_ratio_p = (int) defGetNumeric(param);
159                 else
160                         elog(NOTICE, "Unrecognized function attribute '%s' ignored",
161                                  param->defname);
162         }
163 }
164
165
166 /*
167  * For a dynamically linked C language object, the form of the clause is
168  *
169  *         AS <object file name> [, <link symbol name> ]
170  *
171  * In all other cases
172  *
173  *         AS <object reference, or sql code>
174  *
175  */
176
177 static void
178 interpret_AS_clause(const char *languageName, const List *as,
179                                         char **prosrc_str_p, char **probin_str_p)
180 {
181         Assert(as != NIL);
182
183         if (strcmp(languageName, "C") == 0)
184         {
185                 /*
186                  * For "C" language, store the file name in probin and, when
187                  * given, the link symbol name in prosrc.
188                  */
189                 *probin_str_p = strVal(lfirst(as));
190                 if (lnext(as) == NULL)
191                         *prosrc_str_p = "-";
192                 else
193                         *prosrc_str_p = strVal(lsecond(as));
194         }
195         else
196         {
197                 /* Everything else wants the given string in prosrc. */
198                 *prosrc_str_p = strVal(lfirst(as));
199                 *probin_str_p = "-";
200
201                 if (lnext(as) != NIL)
202                         elog(ERROR, "CREATE FUNCTION: only one AS item needed for %s language",
203                                  languageName);
204         }
205 }
206
207
208
209 /*
210  * CreateFunction
211  *       Execute a CREATE FUNCTION utility statement.
212  */
213 void
214 CreateFunction(ProcedureStmt *stmt)
215 {
216         char       *probin_str;
217
218         /* pathname of executable file that executes this function, if any */
219
220         char       *prosrc_str;
221
222         /* SQL that executes this function, if any */
223
224         char       *prorettype;
225
226         /* Type of return value (or member of set of values) from function */
227
228         char            languageName[NAMEDATALEN];
229
230         /*
231          * name of language of function, with case adjusted: "C", "internal",
232          * "sql", etc.
233          */
234
235         bool            returnsSet;
236
237         /* The function returns a set of values, as opposed to a singleton. */
238
239         /*
240          * The following are optional user-supplied attributes of the
241          * function.
242          */
243         int32           byte_pct,
244                                 perbyte_cpu,
245                                 percall_cpu,
246                                 outin_ratio;
247         bool            canCache,
248                                 isStrict;
249
250         /* Convert language name to canonical case */
251         case_translate_language_name(stmt->language, languageName);
252
253         /*
254          * Apply appropriate security checks depending on language.
255          */
256         if (strcmp(languageName, "C") == 0 ||
257                 strcmp(languageName, "internal") == 0)
258         {
259                 if (!superuser())
260                         elog(ERROR,
261                                  "Only users with Postgres superuser privilege are "
262                            "permitted to create a function in the '%s' language.\n\t"
263                                  "Others may use the 'sql' language "
264                                  "or the created procedural languages.",
265                                  languageName);
266         }
267         else if (strcmp(languageName, "sql") == 0)
268         {
269                 /* No security check needed for SQL functions */
270         }
271         else
272         {
273                 HeapTuple       languageTuple;
274                 Form_pg_language languageStruct;
275
276                 /* Lookup the language in the system cache */
277                 languageTuple = SearchSysCache(LANGNAME,
278                                                                            PointerGetDatum(languageName),
279                                                                            0, 0, 0);
280                 if (!HeapTupleIsValid(languageTuple))
281                         elog(ERROR,
282                                  "Unrecognized language specified in a CREATE FUNCTION: "
283                                  "'%s'.\n\tPre-installed languages are SQL, C, and "
284                                  "internal.\n\tAdditional languages may be installed "
285                                  "using 'createlang'.",
286                                  languageName);
287
288                 /* Check that this language is a PL */
289                 languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
290                 if (!languageStruct->lanispl)
291                         elog(ERROR,
292                                  "Language '%s' isn't defined as PL", languageName);
293
294                 /*
295                  * Functions in untrusted procedural languages are restricted to
296                  * be defined by postgres superusers only
297                  */
298                 if (!languageStruct->lanpltrusted && !superuser())
299                         elog(ERROR, "Only users with Postgres superuser privilege "
300                                  "are permitted to create a function in the '%s' "
301                                  "language.",
302                                  languageName);
303
304                 ReleaseSysCache(languageTuple);
305         }
306
307         /*
308          * Convert remaining parameters of CREATE to form wanted by
309          * ProcedureCreate.
310          */
311         Assert(IsA(stmt->returnType, TypeName));
312         compute_return_type((TypeName *) stmt->returnType,
313                                                 &prorettype, &returnsSet);
314
315         compute_full_attributes(stmt->withClause,
316                                                         &byte_pct, &perbyte_cpu, &percall_cpu,
317                                                         &outin_ratio, &canCache, &isStrict);
318
319         interpret_AS_clause(languageName, stmt->as, &prosrc_str, &probin_str);
320
321         /*
322          * And now that we have all the parameters, and know we're permitted
323          * to do so, go ahead and create the function.
324          */
325         ProcedureCreate(stmt->funcname,
326                                         stmt->replace,
327                                         returnsSet,
328                                         prorettype,
329                                         languageName,
330                                         prosrc_str, /* converted to text later */
331                                         probin_str, /* converted to text later */
332                                         true,           /* (obsolete "trusted") */
333                                         canCache,
334                                         isStrict,
335                                         byte_pct,
336                                         perbyte_cpu,
337                                         percall_cpu,
338                                         outin_ratio,
339                                         stmt->argTypes);
340 }
341
342
343
344 /* --------------------------------
345  * DefineOperator
346  *
347  *              this function extracts all the information from the
348  *              parameter list generated by the parser and then has
349  *              OperatorCreate() do all the actual work.
350  *
351  * 'parameters' is a list of DefElem
352  * --------------------------------
353  */
354 void
355 DefineOperator(char *oprName,
356                            List *parameters)
357 {
358         uint16          precedence = 0; /* operator precedence */
359         bool            canHash = false;        /* operator hashes */
360         bool            isLeftAssociative = true;               /* operator is left
361                                                                                                  * associative */
362         char       *functionName = NULL;        /* function for operator */
363         char       *typeName1 = NULL;           /* first type name */
364         char       *typeName2 = NULL;           /* second type name */
365         char       *commutatorName = NULL;      /* optional commutator operator
366                                                                                  * name */
367         char       *negatorName = NULL;         /* optional negator operator name */
368         char       *restrictionName = NULL; /* optional restrict. sel.
369                                                                                  * procedure */
370         char       *joinName = NULL;    /* optional join sel. procedure name */
371         char       *sortName1 = NULL;           /* optional first sort operator */
372         char       *sortName2 = NULL;           /* optional second sort operator */
373         List       *pl;
374
375         /*
376          * loop over the definition list and extract the information we need.
377          */
378         foreach(pl, parameters)
379         {
380                 DefElem    *defel = (DefElem *) lfirst(pl);
381
382                 if (strcasecmp(defel->defname, "leftarg") == 0)
383                 {
384                         typeName1 = defGetString(defel);
385                         if (IsA(defel->arg, TypeName) &&
386                                 ((TypeName *) defel->arg)->setof)
387                                 elog(ERROR, "setof type not implemented for leftarg");
388                 }
389                 else if (strcasecmp(defel->defname, "rightarg") == 0)
390                 {
391                         typeName2 = defGetString(defel);
392                         if (IsA(defel->arg, TypeName) &&
393                                 ((TypeName *) defel->arg)->setof)
394                                 elog(ERROR, "setof type not implemented for rightarg");
395                 }
396                 else if (strcasecmp(defel->defname, "procedure") == 0)
397                         functionName = defGetString(defel);
398                 else if (strcasecmp(defel->defname, "precedence") == 0)
399                 {
400                         /* NOT IMPLEMENTED (never worked in v4.2) */
401                         elog(NOTICE, "CREATE OPERATOR: precedence not implemented");
402                 }
403                 else if (strcasecmp(defel->defname, "associativity") == 0)
404                 {
405                         /* NOT IMPLEMENTED (never worked in v4.2) */
406                         elog(NOTICE, "CREATE OPERATOR: associativity not implemented");
407                 }
408                 else if (strcasecmp(defel->defname, "commutator") == 0)
409                         commutatorName = defGetString(defel);
410                 else if (strcasecmp(defel->defname, "negator") == 0)
411                         negatorName = defGetString(defel);
412                 else if (strcasecmp(defel->defname, "restrict") == 0)
413                         restrictionName = defGetString(defel);
414                 else if (strcasecmp(defel->defname, "join") == 0)
415                         joinName = defGetString(defel);
416                 else if (strcasecmp(defel->defname, "hashes") == 0)
417                         canHash = TRUE;
418                 else if (strcasecmp(defel->defname, "sort1") == 0)
419                 {
420                         /* ----------------
421                          * XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... )
422                          * XXX is undocumented in the reference manual source as of
423                          * 89/8/22.
424                          * ----------------
425                          */
426                         sortName1 = defGetString(defel);
427                 }
428                 else if (strcasecmp(defel->defname, "sort2") == 0)
429                         sortName2 = defGetString(defel);
430                 else
431                 {
432                         elog(NOTICE, "DefineOperator: attribute \"%s\" not recognized",
433                                  defel->defname);
434                 }
435         }
436
437         /*
438          * make sure we have our required definitions
439          */
440         if (functionName == NULL)
441                 elog(ERROR, "Define: \"procedure\" unspecified");
442
443         /*
444          * now have OperatorCreate do all the work..
445          */
446         OperatorCreate(oprName,         /* operator name */
447                                    typeName1,   /* first type name */
448                                    typeName2,   /* second type name */
449                                    functionName,        /* function for operator */
450                                    precedence,  /* operator precedence */
451                                    isLeftAssociative,   /* operator is left associative */
452                                    commutatorName,              /* optional commutator operator
453                                                                                  * name */
454                                    negatorName, /* optional negator operator name */
455                                    restrictionName,             /* optional restrict. sel.
456                                                                                  * procedure */
457                                    joinName,    /* optional join sel. procedure name */
458                                    canHash,             /* operator hashes */
459                                    sortName1,   /* optional first sort operator */
460                                    sortName2);  /* optional second sort operator */
461
462 }
463
464 /* -------------------
465  *      DefineAggregate
466  * ------------------
467  */
468 void
469 DefineAggregate(char *aggName, List *parameters)
470 {
471         char       *transfuncName = NULL;
472         char       *finalfuncName = NULL;
473         char       *baseType = NULL;
474         char       *transType = NULL;
475         char       *initval = NULL;
476         List       *pl;
477
478         foreach(pl, parameters)
479         {
480                 DefElem    *defel = (DefElem *) lfirst(pl);
481
482                 /*
483                  * sfunc1, stype1, and initcond1 are accepted as obsolete
484                  * spellings for sfunc, stype, initcond.
485                  */
486                 if (strcasecmp(defel->defname, "sfunc") == 0)
487                         transfuncName = defGetString(defel);
488                 else if (strcasecmp(defel->defname, "sfunc1") == 0)
489                         transfuncName = defGetString(defel);
490                 else if (strcasecmp(defel->defname, "finalfunc") == 0)
491                         finalfuncName = defGetString(defel);
492                 else if (strcasecmp(defel->defname, "basetype") == 0)
493                         baseType = defGetString(defel);
494                 else if (strcasecmp(defel->defname, "stype") == 0)
495                         transType = defGetString(defel);
496                 else if (strcasecmp(defel->defname, "stype1") == 0)
497                         transType = defGetString(defel);
498                 else if (strcasecmp(defel->defname, "initcond") == 0)
499                         initval = defGetString(defel);
500                 else if (strcasecmp(defel->defname, "initcond1") == 0)
501                         initval = defGetString(defel);
502                 else
503                         elog(NOTICE, "DefineAggregate: attribute \"%s\" not recognized",
504                                  defel->defname);
505         }
506
507         /*
508          * make sure we have our required definitions
509          */
510         if (baseType == NULL)
511                 elog(ERROR, "Define: \"basetype\" unspecified");
512         if (transType == NULL)
513                 elog(ERROR, "Define: \"stype\" unspecified");
514         if (transfuncName == NULL)
515                 elog(ERROR, "Define: \"sfunc\" unspecified");
516
517         /*
518          * Most of the argument-checking is done inside of AggregateCreate
519          */
520         AggregateCreate(aggName,        /* aggregate name */
521                                         transfuncName,          /* step function name */
522                                         finalfuncName,          /* final function name */
523                                         baseType,       /* type of data being aggregated */
524                                         transType,      /* transition data type */
525                                         initval);       /* initial condition */
526 }
527
528 /*
529  * DefineType
530  *              Registers a new type.
531  */
532 void
533 DefineType(char *typeName, List *parameters)
534 {
535         int16           internalLength = -1;    /* int2 */
536         int16           externalLength = -1;    /* int2 */
537         char       *elemName = NULL;
538         char       *inputName = NULL;
539         char       *outputName = NULL;
540         char       *sendName = NULL;
541         char       *receiveName = NULL;
542         char       *defaultValue = NULL;
543         bool            byValue = false;
544         char            delimiter = DEFAULT_TYPDELIM;
545         char       *shadow_type;
546         List       *pl;
547         char            alignment = 'i';        /* default alignment */
548         char            storage = 'p';  /* default TOAST storage method */
549
550         /*
551          * Type names must be one character shorter than other names, allowing
552          * room to create the corresponding array type name with prepended
553          * "_".
554          */
555         if (strlen(typeName) > (NAMEDATALEN - 2))
556                 elog(ERROR, "DefineType: type names must be %d characters or less",
557                          NAMEDATALEN - 2);
558
559         foreach(pl, parameters)
560         {
561                 DefElem    *defel = (DefElem *) lfirst(pl);
562
563                 if (strcasecmp(defel->defname, "internallength") == 0)
564                         internalLength = defGetTypeLength(defel);
565                 else if (strcasecmp(defel->defname, "externallength") == 0)
566                         externalLength = defGetTypeLength(defel);
567                 else if (strcasecmp(defel->defname, "input") == 0)
568                         inputName = defGetString(defel);
569                 else if (strcasecmp(defel->defname, "output") == 0)
570                         outputName = defGetString(defel);
571                 else if (strcasecmp(defel->defname, "send") == 0)
572                         sendName = defGetString(defel);
573                 else if (strcasecmp(defel->defname, "delimiter") == 0)
574                 {
575                         char       *p = defGetString(defel);
576
577                         delimiter = p[0];
578                 }
579                 else if (strcasecmp(defel->defname, "receive") == 0)
580                         receiveName = defGetString(defel);
581                 else if (strcasecmp(defel->defname, "element") == 0)
582                         elemName = defGetString(defel);
583                 else if (strcasecmp(defel->defname, "default") == 0)
584                         defaultValue = defGetString(defel);
585                 else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
586                         byValue = true;
587                 else if (strcasecmp(defel->defname, "alignment") == 0)
588                 {
589                         char       *a = defGetString(defel);
590
591                         /*
592                          * Note: if argument was an unquoted identifier, parser will
593                          * have applied xlateSqlType() to it, so be prepared to
594                          * recognize translated type names as well as the nominal
595                          * form.
596                          */
597                         if (strcasecmp(a, "double") == 0)
598                                 alignment = 'd';
599                         else if (strcasecmp(a, "float8") == 0)
600                                 alignment = 'd';
601                         else if (strcasecmp(a, "int4") == 0)
602                                 alignment = 'i';
603                         else if (strcasecmp(a, "int2") == 0)
604                                 alignment = 's';
605                         else if (strcasecmp(a, "char") == 0)
606                                 alignment = 'c';
607                         else if (strcasecmp(a, "bpchar") == 0)
608                                 alignment = 'c';
609                         else
610                                 elog(ERROR, "DefineType: \"%s\" alignment not recognized",
611                                          a);
612                 }
613                 else if (strcasecmp(defel->defname, "storage") == 0)
614                 {
615                         char       *a = defGetString(defel);
616
617                         if (strcasecmp(a, "plain") == 0)
618                                 storage = 'p';
619                         else if (strcasecmp(a, "external") == 0)
620                                 storage = 'e';
621                         else if (strcasecmp(a, "extended") == 0)
622                                 storage = 'x';
623                         else if (strcasecmp(a, "main") == 0)
624                                 storage = 'm';
625                         else
626                                 elog(ERROR, "DefineType: \"%s\" storage not recognized",
627                                          a);
628                 }
629                 else
630                 {
631                         elog(NOTICE, "DefineType: attribute \"%s\" not recognized",
632                                  defel->defname);
633                 }
634         }
635
636         /*
637          * make sure we have our required definitions
638          */
639         if (inputName == NULL)
640                 elog(ERROR, "Define: \"input\" unspecified");
641         if (outputName == NULL)
642                 elog(ERROR, "Define: \"output\" unspecified");
643
644         /*
645          * now have TypeCreate do all the real work.
646          */
647         TypeCreate(typeName,            /* type name */
648                            InvalidOid,          /* preassigned type oid (not done here) */
649                            InvalidOid,          /* relation oid (n/a here) */
650                            internalLength,      /* internal size */
651                            externalLength,      /* external size */
652                            'b',                         /* type-type (base type) */
653                            delimiter,           /* array element delimiter */
654                            inputName,           /* input procedure */
655                            outputName,          /* output procedure */
656                            receiveName,         /* receive procedure */
657                            sendName,            /* send procedure */
658                            elemName,            /* element type name */
659                            defaultValue,        /* default type value */
660                            byValue,                     /* passed by value */
661                            alignment,           /* required alignment */
662                            storage);            /* TOAST strategy */
663
664         /*
665          * When we create a base type (as opposed to a complex type) we need
666          * to have an array entry for it in pg_type as well.
667          */
668         shadow_type = makeArrayTypeName(typeName);
669
670         /* alignment must be 'i' or 'd' for arrays */
671         alignment = (alignment == 'd') ? 'd' : 'i';
672
673         TypeCreate(shadow_type,         /* type name */
674                            InvalidOid,          /* preassigned type oid (not done here) */
675                            InvalidOid,          /* relation oid (n/a here) */
676                            -1,                          /* internal size */
677                            -1,                          /* external size */
678                            'b',                         /* type-type (base type) */
679                            DEFAULT_TYPDELIM,    /* array element delimiter */
680                            "array_in",          /* input procedure */
681                            "array_out",         /* output procedure */
682                            "array_in",          /* receive procedure */
683                            "array_out",         /* send procedure */
684                            typeName,            /* element type name */
685                            NULL,                        /* never a default type value */
686                            false,                       /* never passed by value */
687                            alignment,           /* see above */
688                            'x');                        /* ARRAY is always toastable */
689
690         pfree(shadow_type);
691 }
692
693 static char *
694 defGetString(DefElem *def)
695 {
696         if (def->arg == NULL)
697                 elog(ERROR, "Define: \"%s\" requires a parameter",
698                          def->defname);
699         switch (nodeTag(def->arg))
700         {
701                 case T_Integer:
702                         {
703                                 char       *str = palloc(32);
704
705                                 snprintf(str, 32, "%ld", (long) intVal(def->arg));
706                                 return str;
707                         }
708                 case T_Float:
709
710                         /*
711                          * T_Float values are kept in string form, so this type cheat
712                          * works (and doesn't risk losing precision)
713                          */
714                         return strVal(def->arg);
715                 case T_String:
716                         return strVal(def->arg);
717                 case T_TypeName:
718                         return TypeNameToInternalName((TypeName *) def->arg);
719                 default:
720                         elog(ERROR, "Define: cannot interpret argument of \"%s\"",
721                                  def->defname);
722         }
723         return NULL;                            /* keep compiler quiet */
724 }
725
726 static double
727 defGetNumeric(DefElem *def)
728 {
729         if (def->arg == NULL)
730                 elog(ERROR, "Define: \"%s\" requires a numeric value",
731                          def->defname);
732         switch (nodeTag(def->arg))
733         {
734                 case T_Integer:
735                         return (double) intVal(def->arg);
736                 case T_Float:
737                         return floatVal(def->arg);
738                 default:
739                         elog(ERROR, "Define: \"%s\" requires a numeric value",
740                                  def->defname);
741         }
742         return 0;                                       /* keep compiler quiet */
743 }
744
745 static int
746 defGetTypeLength(DefElem *def)
747 {
748         if (def->arg == NULL)
749                 elog(ERROR, "Define: \"%s\" requires a parameter",
750                          def->defname);
751         switch (nodeTag(def->arg))
752         {
753                 case T_Integer:
754                         return intVal(def->arg);
755                 case T_Float:
756                         elog(ERROR, "Define: \"%s\" requires an integral value",
757                                  def->defname);
758                         break;
759                 case T_String:
760                         if (strcasecmp(strVal(def->arg), "variable") == 0)
761                                 return -1;              /* variable length */
762                         break;
763                 case T_TypeName:
764                         /* cope if grammar chooses to believe "variable" is a typename */
765                         if (strcasecmp(TypeNameToInternalName((TypeName *) def->arg),
766                                                    "variable") == 0)
767                                 return -1;              /* variable length */
768                         break;
769                 default:
770                         elog(ERROR, "Define: cannot interpret argument of \"%s\"",
771                                  def->defname);
772         }
773         elog(ERROR, "Define: invalid argument for \"%s\"",
774                  def->defname);
775         return 0;                                       /* keep compiler quiet */
776 }