Logo Search packages:      
Sourcecode: postgresql-8.4 version File versions

define.c

/*-------------------------------------------------------------------------
 *
 * define.c
 *      Support routines for various kinds of object creation.
 *
 *
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *      $PostgreSQL$
 *
 * DESCRIPTION
 *      The "DefineFoo" routines take the parse tree and pick out the
 *      appropriate arguments/flags, passing the results to the
 *      corresponding "FooDefine" routines (in src/catalog) that do
 *      the actual catalog-munging.  These routines also verify permission
 *      of the user to execute the command.
 *
 * NOTES
 *      These things must be defined and committed in the following order:
 *          "create function":
 *                      input/output, recv/send procedures
 *          "create type":
 *                      type
 *          "create operator":
 *                      operators
 *
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include <ctype.h>
#include <math.h>

#include "catalog/namespace.h"
#include "commands/defrem.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "parser/scansup.h"
#include "utils/int8.h"


/*
 * Translate the input language name to lower case, and truncate if needed.
 *
 * Returns a palloc'd string
 */
char *
case_translate_language_name(const char *input)
{
      return downcase_truncate_identifier(input, strlen(input), false);
}


/*
 * Extract a string value (otherwise uninterpreted) from a DefElem.
 */
char *
defGetString(DefElem *def)
{
      if (def->arg == NULL)
            ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("%s requires a parameter",
                                    def->defname)));
      switch (nodeTag(def->arg))
      {
            case T_Integer:
                  {
                        char     *str = palloc(32);

                        snprintf(str, 32, "%ld", (long) intVal(def->arg));
                        return str;
                  }
            case T_Float:

                  /*
                   * T_Float values are kept in string form, so this type cheat
                   * works (and doesn't risk losing precision)
                   */
                  return strVal(def->arg);
            case T_String:
                  return strVal(def->arg);
            case T_TypeName:
                  return TypeNameToString((TypeName *) def->arg);
            case T_List:
                  return NameListToString((List *) def->arg);
            default:
                  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
      }
      return NULL;                        /* keep compiler quiet */
}

/*
 * Extract a numeric value (actually double) from a DefElem.
 */
double
defGetNumeric(DefElem *def)
{
      if (def->arg == NULL)
            ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("%s requires a numeric value",
                                    def->defname)));
      switch (nodeTag(def->arg))
      {
            case T_Integer:
                  return (double) intVal(def->arg);
            case T_Float:
                  return floatVal(def->arg);
            default:
                  ereport(ERROR,
                              (errcode(ERRCODE_SYNTAX_ERROR),
                               errmsg("%s requires a numeric value",
                                          def->defname)));
      }
      return 0;                           /* keep compiler quiet */
}

/*
 * Extract a boolean value from a DefElem.
 */
bool
defGetBoolean(DefElem *def)
{
      /*
       * If no parameter given, assume "true" is meant.
       */
      if (def->arg == NULL)
            return true;

      /*
       * Allow 0, 1, "true", "false"
       */
      switch (nodeTag(def->arg))
      {
            case T_Integer:
                  switch (intVal(def->arg))
                  {
                        case 0:
                              return false;
                        case 1:
                              return true;
                        default:
                              /* otherwise, error out below */
                              break;
                  }
                  break;
            default:
                  {
                        char     *sval = defGetString(def);

                        if (pg_strcasecmp(sval, "true") == 0)
                              return true;
                        if (pg_strcasecmp(sval, "false") == 0)
                              return false;

                  }
                  break;
      }
      ereport(ERROR,
                  (errcode(ERRCODE_SYNTAX_ERROR),
                   errmsg("%s requires a Boolean value",
                              def->defname)));
      return false;                       /* keep compiler quiet */
}

/*
 * Extract an int64 value from a DefElem.
 */
int64
defGetInt64(DefElem *def)
{
      if (def->arg == NULL)
            ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("%s requires a numeric value",
                                    def->defname)));
      switch (nodeTag(def->arg))
      {
            case T_Integer:
                  return (int64) intVal(def->arg);
            case T_Float:

                  /*
                   * Values too large for int4 will be represented as Float
                   * constants by the lexer.    Accept these if they are valid int8
                   * strings.
                   */
                  return DatumGetInt64(DirectFunctionCall1(int8in,
                                                             CStringGetDatum(strVal(def->arg))));
            default:
                  ereport(ERROR,
                              (errcode(ERRCODE_SYNTAX_ERROR),
                               errmsg("%s requires a numeric value",
                                          def->defname)));
      }
      return 0;                           /* keep compiler quiet */
}

/*
 * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
 */
List *
defGetQualifiedName(DefElem *def)
{
      if (def->arg == NULL)
            ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("%s requires a parameter",
                                    def->defname)));
      switch (nodeTag(def->arg))
      {
            case T_TypeName:
                  return ((TypeName *) def->arg)->names;
            case T_List:
                  return (List *) def->arg;
            case T_String:
                  /* Allow quoted name for backwards compatibility */
                  return list_make1(def->arg);
            default:
                  ereport(ERROR,
                              (errcode(ERRCODE_SYNTAX_ERROR),
                               errmsg("argument of %s must be a name",
                                          def->defname)));
      }
      return NIL;                         /* keep compiler quiet */
}

/*
 * Extract a TypeName from a DefElem.
 *
 * Note: we do not accept a List arg here, because the parser will only
 * return a bare List when the name looks like an operator name.
 */
TypeName *
defGetTypeName(DefElem *def)
{
      if (def->arg == NULL)
            ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("%s requires a parameter",
                                    def->defname)));
      switch (nodeTag(def->arg))
      {
            case T_TypeName:
                  return (TypeName *) def->arg;
            case T_String:
                  /* Allow quoted typename for backwards compatibility */
                  return makeTypeNameFromNameList(list_make1(def->arg));
            default:
                  ereport(ERROR,
                              (errcode(ERRCODE_SYNTAX_ERROR),
                               errmsg("argument of %s must be a type name",
                                          def->defname)));
      }
      return NULL;                        /* keep compiler quiet */
}

/*
 * Extract a type length indicator (either absolute bytes, or
 * -1 for "variable") from a DefElem.
 */
int
defGetTypeLength(DefElem *def)
{
      if (def->arg == NULL)
            ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("%s requires a parameter",
                                    def->defname)));
      switch (nodeTag(def->arg))
      {
            case T_Integer:
                  return intVal(def->arg);
            case T_Float:
                  ereport(ERROR,
                              (errcode(ERRCODE_SYNTAX_ERROR),
                               errmsg("%s requires an integer value",
                                          def->defname)));
                  break;
            case T_String:
                  if (pg_strcasecmp(strVal(def->arg), "variable") == 0)
                        return -1;        /* variable length */
                  break;
            case T_TypeName:
                  /* cope if grammar chooses to believe "variable" is a typename */
                  if (pg_strcasecmp(TypeNameToString((TypeName *) def->arg),
                                            "variable") == 0)
                        return -1;        /* variable length */
                  break;
            case T_List:
                  /* must be an operator name */
                  break;
            default:
                  elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
      }
      ereport(ERROR,
                  (errcode(ERRCODE_SYNTAX_ERROR),
                   errmsg("invalid argument for %s: \"%s\"",
                              def->defname, defGetString(def))));
      return 0;                           /* keep compiler quiet */
}

/*
 * Create a DefElem setting "oids" to the specified value.
 */
DefElem *
defWithOids(bool value)
{
      return makeDefElem("oids", (Node *) makeInteger(value));
}

Generated by  Doxygen 1.6.0   Back to index