1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* define.c
|
2002-04-15 07:22:04 +02:00
|
|
|
* Support routines for various kinds of object creation.
|
1996-10-31 10:08:10 +01:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2003-08-04 04:40:20 +02:00
|
|
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2003-11-29 20:52:15 +01:00
|
|
|
* $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.85 2003/11/29 19:51:47 pgsql Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* DESCRIPTION
|
1997-09-07 07:04:48 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-07 07:04:48 +02:00
|
|
|
* These things must be defined and committed in the following order:
|
|
|
|
* "create function":
|
|
|
|
* input/output, recv/send procedures
|
|
|
|
* "create type":
|
|
|
|
* type
|
|
|
|
* "create operator":
|
|
|
|
* operators
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
2001-06-13 23:44:41 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#include <ctype.h>
|
1996-11-06 09:21:43 +01:00
|
|
|
#include <math.h>
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2002-08-10 21:01:53 +02:00
|
|
|
#include "catalog/namespace.h"
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "commands/defrem.h"
|
2002-03-29 20:06:29 +01:00
|
|
|
#include "parser/parse_type.h"
|
2002-05-22 23:40:55 +02:00
|
|
|
#include "utils/int8.h"
|
1996-10-31 10:08:10 +01:00
|
|
|
|
|
|
|
|
2002-02-19 00:11:58 +01:00
|
|
|
/*
|
|
|
|
* Translate the input language name to lower case.
|
2002-04-15 07:22:04 +02:00
|
|
|
*
|
2002-09-21 20:39:26 +02:00
|
|
|
* Output buffer must be NAMEDATALEN long.
|
2002-02-19 00:11:58 +01:00
|
|
|
*/
|
2002-04-15 07:22:04 +02:00
|
|
|
void
|
1997-09-07 07:04:48 +02:00
|
|
|
case_translate_language_name(const char *input, char *output)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1996-10-31 10:08:10 +01:00
|
|
|
|
2003-08-04 02:43:34 +02:00
|
|
|
MemSet(output, 0, NAMEDATALEN); /* ensure result Name is
|
|
|
|
* zero-filled */
|
2002-09-21 20:39:26 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
for (i = 0; i < NAMEDATALEN - 1 && input[i]; ++i)
|
2000-12-03 21:45:40 +01:00
|
|
|
output[i] = tolower((unsigned char) input[i]);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-10-31 10:08:10 +01:00
|
|
|
|
|
|
|
|
2001-06-21 20:25:54 +02:00
|
|
|
/*
|
2002-04-15 07:22:04 +02:00
|
|
|
* Extract a string value (otherwise uninterpreted) from a DefElem.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2002-04-15 07:22:04 +02:00
|
|
|
char *
|
1997-09-08 23:56:23 +02:00
|
|
|
defGetString(DefElem *def)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-10-07 02:58:23 +02:00
|
|
|
if (def->arg == NULL)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a parameter",
|
|
|
|
def->defname)));
|
2000-10-07 02:58:23 +02:00
|
|
|
switch (nodeTag(def->arg))
|
|
|
|
{
|
|
|
|
case T_Integer:
|
2001-03-22 05:01:46 +01:00
|
|
|
{
|
|
|
|
char *str = palloc(32);
|
2000-04-07 15:40:45 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
snprintf(str, 32, "%ld", (long) intVal(def->arg));
|
|
|
|
return str;
|
|
|
|
}
|
2000-10-07 02:58:23 +02:00
|
|
|
case T_Float:
|
2001-03-22 05:01:46 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* T_Float values are kept in string form, so this type cheat
|
2000-10-07 02:58:23 +02:00
|
|
|
* works (and doesn't risk losing precision)
|
|
|
|
*/
|
|
|
|
return strVal(def->arg);
|
|
|
|
case T_String:
|
|
|
|
return strVal(def->arg);
|
|
|
|
case T_TypeName:
|
2002-03-29 20:06:29 +01:00
|
|
|
return TypeNameToString((TypeName *) def->arg);
|
2002-08-10 21:01:53 +02:00
|
|
|
case T_List:
|
|
|
|
return NameListToString((List *) def->arg);
|
2000-10-07 02:58:23 +02:00
|
|
|
default:
|
2003-07-20 23:56:35 +02:00
|
|
|
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
|
2000-10-07 02:58:23 +02:00
|
|
|
}
|
|
|
|
return NULL; /* keep compiler quiet */
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2002-04-15 07:22:04 +02:00
|
|
|
/*
|
|
|
|
* Extract a numeric value (actually double) from a DefElem.
|
|
|
|
*/
|
|
|
|
double
|
1999-10-02 23:33:33 +02:00
|
|
|
defGetNumeric(DefElem *def)
|
|
|
|
{
|
|
|
|
if (def->arg == NULL)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a numeric value",
|
|
|
|
def->defname)));
|
1999-10-02 23:33:33 +02:00
|
|
|
switch (nodeTag(def->arg))
|
|
|
|
{
|
|
|
|
case T_Integer:
|
|
|
|
return (double) intVal(def->arg);
|
|
|
|
case T_Float:
|
|
|
|
return floatVal(def->arg);
|
|
|
|
default:
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a numeric value",
|
|
|
|
def->defname)));
|
1999-10-02 23:33:33 +02:00
|
|
|
}
|
|
|
|
return 0; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
2002-05-22 23:40:55 +02:00
|
|
|
/*
|
|
|
|
* Extract an int64 value from a DefElem.
|
|
|
|
*/
|
|
|
|
int64
|
|
|
|
defGetInt64(DefElem *def)
|
|
|
|
{
|
|
|
|
if (def->arg == NULL)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a numeric value",
|
|
|
|
def->defname)));
|
2002-05-22 23:40:55 +02:00
|
|
|
switch (nodeTag(def->arg))
|
|
|
|
{
|
|
|
|
case T_Integer:
|
|
|
|
return (int64) intVal(def->arg);
|
|
|
|
case T_Float:
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2002-05-22 23:40:55 +02:00
|
|
|
/*
|
|
|
|
* Values too large for int4 will be represented as Float
|
2002-09-04 22:31:48 +02:00
|
|
|
* constants by the lexer. Accept these if they are valid
|
|
|
|
* int8 strings.
|
2002-05-22 23:40:55 +02:00
|
|
|
*/
|
|
|
|
return DatumGetInt64(DirectFunctionCall1(int8in,
|
|
|
|
CStringGetDatum(strVal(def->arg))));
|
|
|
|
default:
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a numeric value",
|
|
|
|
def->defname)));
|
2002-05-22 23:40:55 +02:00
|
|
|
}
|
|
|
|
return 0; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
2002-04-15 07:22:04 +02:00
|
|
|
/*
|
|
|
|
* Extract a possibly-qualified name (as a List of Strings) from a DefElem.
|
|
|
|
*/
|
|
|
|
List *
|
2002-04-09 22:35:55 +02:00
|
|
|
defGetQualifiedName(DefElem *def)
|
|
|
|
{
|
|
|
|
if (def->arg == NULL)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a parameter",
|
|
|
|
def->defname)));
|
2002-04-09 22:35:55 +02:00
|
|
|
switch (nodeTag(def->arg))
|
|
|
|
{
|
|
|
|
case T_TypeName:
|
|
|
|
return ((TypeName *) def->arg)->names;
|
2002-08-10 21:01:53 +02:00
|
|
|
case T_List:
|
|
|
|
return (List *) def->arg;
|
2002-04-09 22:35:55 +02:00
|
|
|
case T_String:
|
|
|
|
/* Allow quoted name for backwards compatibility */
|
|
|
|
return makeList1(def->arg);
|
|
|
|
default:
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("argument of %s must be a name",
|
|
|
|
def->defname)));
|
2002-04-09 22:35:55 +02:00
|
|
|
}
|
|
|
|
return NIL; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
2002-04-15 07:22:04 +02:00
|
|
|
/*
|
|
|
|
* Extract a TypeName from a DefElem.
|
2002-08-10 21:01:53 +02:00
|
|
|
*
|
|
|
|
* 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.
|
2002-04-15 07:22:04 +02:00
|
|
|
*/
|
|
|
|
TypeName *
|
2002-03-29 20:06:29 +01:00
|
|
|
defGetTypeName(DefElem *def)
|
|
|
|
{
|
|
|
|
if (def->arg == NULL)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a parameter",
|
|
|
|
def->defname)));
|
2002-03-29 20:06:29 +01:00
|
|
|
switch (nodeTag(def->arg))
|
|
|
|
{
|
|
|
|
case T_TypeName:
|
|
|
|
return (TypeName *) def->arg;
|
|
|
|
case T_String:
|
2002-09-04 22:31:48 +02:00
|
|
|
{
|
|
|
|
/* Allow quoted typename for backwards compatibility */
|
|
|
|
TypeName *n = makeNode(TypeName);
|
|
|
|
|
|
|
|
n->names = makeList1(def->arg);
|
|
|
|
n->typmod = -1;
|
|
|
|
return n;
|
|
|
|
}
|
2002-03-29 20:06:29 +01:00
|
|
|
default:
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("argument of %s must be a type name",
|
|
|
|
def->defname)));
|
2002-03-29 20:06:29 +01:00
|
|
|
}
|
|
|
|
return NULL; /* keep compiler quiet */
|
|
|
|
}
|
|
|
|
|
2002-04-15 07:22:04 +02:00
|
|
|
/*
|
|
|
|
* Extract a type length indicator (either absolute bytes, or
|
|
|
|
* -1 for "variable") from a DefElem.
|
|
|
|
*/
|
|
|
|
int
|
1997-09-08 23:56:23 +02:00
|
|
|
defGetTypeLength(DefElem *def)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-10-07 02:58:23 +02:00
|
|
|
if (def->arg == NULL)
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires a parameter",
|
|
|
|
def->defname)));
|
2000-10-07 02:58:23 +02:00
|
|
|
switch (nodeTag(def->arg))
|
|
|
|
{
|
|
|
|
case T_Integer:
|
|
|
|
return intVal(def->arg);
|
|
|
|
case T_Float:
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("%s requires an integer value",
|
|
|
|
def->defname)));
|
2000-10-07 02:58:23 +02:00
|
|
|
break;
|
|
|
|
case T_String:
|
|
|
|
if (strcasecmp(strVal(def->arg), "variable") == 0)
|
|
|
|
return -1; /* variable length */
|
|
|
|
break;
|
|
|
|
case T_TypeName:
|
|
|
|
/* cope if grammar chooses to believe "variable" is a typename */
|
2002-03-29 20:06:29 +01:00
|
|
|
if (strcasecmp(TypeNameToString((TypeName *) def->arg),
|
2000-10-07 02:58:23 +02:00
|
|
|
"variable") == 0)
|
|
|
|
return -1; /* variable length */
|
|
|
|
break;
|
2002-08-10 21:01:53 +02:00
|
|
|
case T_List:
|
|
|
|
/* must be an operator name */
|
|
|
|
break;
|
2000-10-07 02:58:23 +02:00
|
|
|
default:
|
2003-07-20 23:56:35 +02:00
|
|
|
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
|
2000-10-07 02:58:23 +02:00
|
|
|
}
|
2003-07-20 23:56:35 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
|
|
|
errmsg("invalid argument for %s: \"%s\"",
|
|
|
|
def->defname, defGetString(def))));
|
2000-10-07 02:58:23 +02:00
|
|
|
return 0; /* keep compiler quiet */
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|