1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-25 20:23:07 +03:00

pg_type has a typnamespace column; system now supports creating types

in different namespaces.  Also, cleanup work on relation namespace
support: drop, alter, rename commands work for tables in non-default
namespaces.
This commit is contained in:
Tom Lane
2002-03-29 19:06:29 +00:00
parent 7c1ff35410
commit d5e99ab4d6
68 changed files with 2074 additions and 2266 deletions

View File

@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.223 2002/03/26 19:15:56 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.224 2002/03/29 19:06:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -108,11 +108,7 @@ static void transformIndexConstraints(ParseState *pstate,
CreateStmtContext *cxt);
static void transformFKConstraints(ParseState *pstate,
CreateStmtContext *cxt);
static Node *transformTypeRefs(ParseState *pstate, Node *stmt);
static void applyColumnNames(List *dst, List *src);
static void transformTypeRefsList(ParseState *pstate, List *l);
static void transformTypeRef(ParseState *pstate, TypeName *tn);
static List *getSetColTypes(ParseState *pstate, Node *node);
static void transformForUpdate(Query *qry, List *forUpdate);
static void transformConstraintAttrs(List *constraintList);
@@ -309,18 +305,6 @@ transformStmt(ParseState *pstate, Node *parseTree,
(SelectStmt *) parseTree);
break;
/*
* Convert use of %TYPE in statements where it is permitted.
*/
case T_ProcedureStmt:
case T_CommentStmt:
case T_RemoveFuncStmt:
case T_DefineStmt:
result = makeNode(Query);
result->commandType = CMD_UTILITY;
result->utilityStmt = transformTypeRefs(pstate, parseTree);
break;
default:
/*
@@ -792,17 +776,24 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
/* Check for SERIAL pseudo-types */
is_serial = false;
if (strcmp(column->typename->name, "serial") == 0 ||
strcmp(column->typename->name, "serial4") == 0)
if (length(column->typename->names) == 1)
{
is_serial = true;
column->typename->name = pstrdup("int4");
}
else if (strcmp(column->typename->name, "bigserial") == 0 ||
strcmp(column->typename->name, "serial8") == 0)
{
is_serial = true;
column->typename->name = pstrdup("int8");
char *typname = strVal(lfirst(column->typename->names));
if (strcmp(typname, "serial") == 0 ||
strcmp(typname, "serial4") == 0)
{
is_serial = true;
column->typename->names = NIL;
column->typename->typeid = INT4OID;
}
else if (strcmp(typname, "bigserial") == 0 ||
strcmp(typname, "serial8") == 0)
{
is_serial = true;
column->typename->names = NIL;
column->typename->typeid = INT8OID;
}
}
/* Do necessary work on the column type declaration */
@@ -2634,110 +2625,6 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
return qry;
}
/*
* Transform uses of %TYPE in a statement.
*/
static Node *
transformTypeRefs(ParseState *pstate, Node *stmt)
{
switch (nodeTag(stmt))
{
case T_ProcedureStmt:
{
ProcedureStmt *ps = (ProcedureStmt *) stmt;
transformTypeRefsList(pstate, ps->argTypes);
transformTypeRef(pstate, (TypeName *) ps->returnType);
transformTypeRefsList(pstate, ps->withClause);
}
break;
case T_CommentStmt:
{
CommentStmt *cs = (CommentStmt *) stmt;
transformTypeRefsList(pstate, cs->objlist);
}
break;
case T_RemoveFuncStmt:
{
RemoveFuncStmt *rs = (RemoveFuncStmt *) stmt;
transformTypeRefsList(pstate, rs->args);
}
break;
case T_DefineStmt:
{
DefineStmt *ds = (DefineStmt *) stmt;
List *ele;
foreach(ele, ds->definition)
{
DefElem *de = (DefElem *) lfirst(ele);
if (de->arg != NULL
&& IsA(de->arg, TypeName))
transformTypeRef(pstate, (TypeName *) de->arg);
}
}
break;
default:
elog(ERROR, "Unsupported type %d in transformTypeRefs",
nodeTag(stmt));
break;
}
return stmt;
}
/*
* Transform uses of %TYPE in a list.
*/
static void
transformTypeRefsList(ParseState *pstate, List *l)
{
List *ele;
foreach(ele, l)
{
Node *elem = lfirst(ele);
if (elem && IsA(elem, TypeName))
transformTypeRef(pstate, (TypeName *) elem);
}
}
/*
* Transform a TypeName to not use %TYPE.
*/
static void
transformTypeRef(ParseState *pstate, TypeName *tn)
{
ColumnRef *cref;
Node *n;
Var *v;
char *tyn;
if (tn->attrname == NULL)
return;
/* XXX this needs work; can't type name be qualified? */
cref = makeNode(ColumnRef);
cref->fields = makeList2(makeString(tn->name), makeString(tn->attrname));
cref->indirection = NIL;
n = transformExpr(pstate, (Node *) cref);
if (!IsA(n, Var))
elog(ERROR, "unsupported expression in %%TYPE");
v = (Var *) n;
tyn = typeidTypeName(v->vartype);
elog(NOTICE, "%s.%s%%TYPE converted to %s", tn->name, tn->attrname, tyn);
tn->name = tyn;
tn->typmod = v->vartypmod;
tn->attrname = NULL;
}
/* exported so planner can check again after rewriting, query pullup, etc */
void
CheckSelectForUpdate(Query *qry)
@@ -3059,15 +2946,7 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
ColumnDef *col = lfirst(cols);
if (strcmp(col->colname, colname) == 0)
{
char *buff = TypeNameToInternalName(col->typename);
result = typenameTypeId(buff);
if (!OidIsValid(result))
elog(ERROR, "Unable to lookup type %s",
col->typename->name);
return result;
}
return typenameTypeId(col->typename);
}
/* Perhaps it's a system column name */
sysatt = SystemAttributeByName(colname, cxt->hasoids);
@@ -3092,7 +2971,6 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
if (strcmp(name, colname) == 0)
{
result = rel->rd_att->attrs[count]->atttypid;
heap_close(rel, NoLock);
return result;
}
@@ -3111,7 +2989,6 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
if (HeapTupleIsValid(atttuple))
{
result = ((Form_pg_attribute) GETSTRUCT(atttuple))->atttypid;
ReleaseSysCache(atttuple);
return result;
}
@@ -3233,7 +3110,7 @@ static void
transformColumnType(ParseState *pstate, ColumnDef *column)
{
TypeName *typename = column->typename;
Type ctype = typenameType(typename->name);
Type ctype = typenameType(typename);
/*
* Is this the name of a complex type? If so, implement it as a set.

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.296 2002/03/22 02:56:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.297 2002/03/29 19:06:10 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -53,6 +53,7 @@
#include "access/htup.h"
#include "catalog/index.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/params.h"
#include "nodes/parsenodes.h"
#include "parser/gramparse.h"
@@ -122,8 +123,6 @@ static void doNegateFloat(Value *v);
ResTarget *target;
PrivTarget *privtarget;
DefineStmt *dstmt;
RuleStmt *rstmt;
InsertStmt *istmt;
}
@@ -175,7 +174,8 @@ static void doNegateFloat(Value *v);
%type <str> relation_name, copy_file_name, copy_delimiter, copy_null,
database_name, access_method_clause, access_method, attr_name,
class, index_name, name, func_name, file_name
class, index_name, name, function_name, file_name,
func_name, handler_name
%type <range> qualified_name, OptConstrFromTable
@@ -200,8 +200,8 @@ static void doNegateFloat(Value *v);
opt_column_list, columnList, opt_name_list,
sort_clause, sortby_list, index_params, index_list, name_list,
from_clause, from_list, opt_array_bounds, qualified_name_list,
expr_list, attrs, opt_attrs, target_list, update_target_list,
insert_column_list,
any_name, any_name_list, expr_list, dotted_name, attrs,
target_list, update_target_list, insert_column_list,
def_list, opt_indirection, group_clause, TriggerFuncArgs,
select_limit, opt_select_limit
@@ -411,10 +411,10 @@ static void doNegateFloat(Value *v);
/* Unary Operators */
%left AT ZONE /* sets precedence for AT TIME ZONE */
%right UMINUS
%left '.'
%left '[' ']'
%left '(' ')'
%left TYPECAST
%left '.'
%%
/*
@@ -1812,7 +1812,7 @@ IntegerOnly: Iconst
*****************************************************************************/
CreatePLangStmt: CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
HANDLER func_name opt_lancompiler
HANDLER handler_name opt_lancompiler
{
CreatePLangStmt *n = makeNode(CreatePLangStmt);
n->plname = $5;
@@ -1827,6 +1827,16 @@ opt_trusted: TRUSTED { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
/* This ought to be just func_name, but that causes reduce/reduce conflicts
* (CREATE LANGUAGE is the only place where func_name isn't followed by '(').
* Work around by using name and dotted_name separately.
*/
handler_name: name
{ $$ = $1; }
| dotted_name
{ $$ = strVal(lfirst($1)); /* XXX changing soon */ }
;
opt_lancompiler: LANCOMPILER Sconst { $$ = $2; }
| /*EMPTY*/ { $$ = ""; }
;
@@ -1853,7 +1863,7 @@ opt_procedural: PROCEDURAL { $$ = TRUE; }
CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
qualified_name TriggerForSpec EXECUTE PROCEDURE
name '(' TriggerFuncArgs ')'
func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $3;
@@ -1877,7 +1887,8 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
| CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
qualified_name OptConstrFromTable
ConstraintAttributeSpec
FOR EACH ROW EXECUTE PROCEDURE name '(' TriggerFuncArgs ')'
FOR EACH ROW EXECUTE PROCEDURE
func_name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $4;
@@ -2043,7 +2054,7 @@ DefineStmt: CREATE AGGREGATE func_name definition
{
DefineStmt *n = makeNode(DefineStmt);
n->defType = AGGREGATE;
n->defname = $3;
n->defnames = makeList1(makeString($3)); /* XXX */
n->definition = $4;
$$ = (Node *)n;
}
@@ -2051,15 +2062,15 @@ DefineStmt: CREATE AGGREGATE func_name definition
{
DefineStmt *n = makeNode(DefineStmt);
n->defType = OPERATOR;
n->defname = $3;
n->defnames = makeList1(makeString($3)); /* XXX */
n->definition = $4;
$$ = (Node *)n;
}
| CREATE TYPE_P name definition
| CREATE TYPE_P any_name definition
{
DefineStmt *n = makeNode(DefineStmt);
n->defType = TYPE_P;
n->defname = $3;
n->defnames = $3;
n->definition = $4;
$$ = (Node *)n;
}
@@ -2102,10 +2113,7 @@ def_arg: func_return { $$ = (Node *)$1; }
*
*****************************************************************************/
/* DropStmt needs to use qualified_name_list as many of the objects
* are relations or other schema objects (names can be schema-qualified) */
DropStmt: DROP drop_type qualified_name_list opt_drop_behavior
DropStmt: DROP drop_type any_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
@@ -2124,6 +2132,18 @@ drop_type: TABLE { $$ = DROP_TABLE; }
| DOMAIN_P { $$ = DROP_DOMAIN; }
;
any_name_list: any_name
{ $$ = makeList1($1); }
| any_name_list ',' any_name
{ $$ = lappend($1, $3); }
;
any_name: ColId
{ $$ = makeList1(makeString($1)); }
| dotted_name
{ $$ = $1; }
;
/*****************************************************************************
*
* QUERY:
@@ -2192,7 +2212,7 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
n->comment = $10;
$$ = (Node *) n;
}
| COMMENT ON AGGREGATE name '(' aggr_argtype ')' IS comment_text
| COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = AGGREGATE;
@@ -2203,18 +2223,6 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
n->comment = $9;
$$ = (Node *) n;
}
| COMMENT ON AGGREGATE name aggr_argtype IS comment_text
{
/* Obsolete syntax, but must support for awhile */
CommentStmt *n = makeNode(CommentStmt);
n->objtype = AGGREGATE;
n->objschema = NULL;
n->objname = $4;
n->objproperty = NULL;
n->objlist = makeList1($5);
n->comment = $7;
$$ = (Node *) n;
}
| COMMENT ON FUNCTION func_name func_args IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
@@ -2691,9 +2699,9 @@ ProcedureStmt: CREATE opt_or_replace FUNCTION func_name func_args
{
ProcedureStmt *n = makeNode(ProcedureStmt);
n->replace = $2;
n->funcname = $4;
n->funcname = makeList1(makeString($4)); /* XXX */
n->argTypes = $5;
n->returnType = (Node *) $7;
n->returnType = $7;
n->withClause = $12;
n->as = $9;
n->language = $11;
@@ -2765,19 +2773,19 @@ func_return: func_type
;
/*
* We would like to make the second production here be ColId '.' ColId etc,
* We would like to make the second production here be ColId attrs etc,
* but that causes reduce/reduce conflicts. type_name is next best choice.
*/
func_type: Typename
{
$$ = $1;
}
| type_name '.' ColId '%' TYPE_P
| type_name attrs '%' TYPE_P
{
$$ = makeNode(TypeName);
$$->name = $1;
$$->names = lcons(makeString($1), $2);
$$->pct_type = true;
$$->typmod = -1;
$$->attrname = $3;
}
;
@@ -2804,15 +2812,7 @@ RemoveAggrStmt: DROP AGGREGATE func_name '(' aggr_argtype ')'
{
RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
n->aggname = $3;
n->aggtype = (Node *) $5;
$$ = (Node *)n;
}
| DROP AGGREGATE func_name aggr_argtype
{
/* Obsolete syntax, but must support for awhile */
RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
n->aggname = $3;
n->aggtype = (Node *) $4;
n->aggtype = $5;
$$ = (Node *)n;
}
;
@@ -3293,7 +3293,7 @@ DropdbStmt: DROP DATABASE database_name
*
*****************************************************************************/
CreateDomainStmt: CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
CreateDomainStmt: CREATE DOMAIN_P any_name opt_as Typename ColQualList opt_collate
{
CreateDomainStmt *n = makeNode(CreateDomainStmt);
n->domainname = $3;
@@ -4237,6 +4237,14 @@ opt_array_bounds: opt_array_bounds '[' ']'
{ $$ = NIL; }
;
/*
* XXX ideally, the production for a qualified typename should be ColId attrs
* (there's no obvious reason why the first name should need to be restricted)
* and should be an alternative of GenericType (so that it can be used to
* specify a type for a literal in AExprConst). However doing either causes
* reduce/reduce conflicts that I haven't been able to find a workaround
* for. FIXME later.
*/
SimpleTypename: ConstTypename
| ConstInterval opt_interval
{
@@ -4249,6 +4257,12 @@ SimpleTypename: ConstTypename
$$ = $1;
$$->typmod = ((($5 & 0x7FFF) << 16) | $3);
}
| type_name attrs
{
$$ = makeNode(TypeName);
$$->names = lcons(makeString($1), $2);
$$->typmod = -1;
}
;
ConstTypename: GenericType
@@ -4260,9 +4274,7 @@ ConstTypename: GenericType
GenericType: type_name
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType($1);
$$->typmod = -1;
$$ = makeTypeName(xlateSqlType($1));
}
;
@@ -4273,32 +4285,25 @@ GenericType: type_name
*/
Numeric: FLOAT opt_float
{
$$ = makeNode(TypeName);
$$->name = $2; /* already xlated */
$$->typmod = -1;
$$ = makeTypeName($2); /* already xlated */
}
| DOUBLE PRECISION
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("float8");
$$->typmod = -1;
$$ = makeTypeName(xlateSqlType("float8"));
}
| DECIMAL opt_decimal
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("decimal");
$$ = makeTypeName(xlateSqlType("decimal"));
$$->typmod = $2;
}
| DEC opt_decimal
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("decimal");
$$ = makeTypeName(xlateSqlType("decimal"));
$$->typmod = $2;
}
| NUMERIC opt_numeric
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("numeric");
$$ = makeTypeName(xlateSqlType("numeric"));
$$->typmod = $2;
}
;
@@ -4379,8 +4384,7 @@ opt_decimal: '(' Iconst ',' Iconst ')'
*/
Bit: bit '(' Iconst ')'
{
$$ = makeNode(TypeName);
$$->name = $1;
$$ = makeTypeName($1);
if ($3 < 1)
elog(ERROR,"length for type '%s' must be at least 1",
$1);
@@ -4391,8 +4395,7 @@ Bit: bit '(' Iconst ')'
}
| bit
{
$$ = makeNode(TypeName);
$$->name = $1;
$$ = makeTypeName($1);
/* bit defaults to bit(1), varbit to no limit */
if (strcmp($1, "bit") == 0)
$$->typmod = 1;
@@ -4418,8 +4421,19 @@ bit: BIT opt_varying
*/
Character: character '(' Iconst ')' opt_charset
{
$$ = makeNode(TypeName);
$$->name = $1;
if (($5 != NULL) && (strcmp($5, "sql_text") != 0))
{
char *type;
type = palloc(strlen($1) + 1 + strlen($5) + 1);
strcpy(type, $1);
strcat(type, "_");
strcat(type, $5);
$1 = xlateSqlType(type);
}
$$ = makeTypeName($1);
if ($3 < 1)
elog(ERROR,"length for type '%s' must be at least 1",
$1);
@@ -4433,36 +4447,27 @@ Character: character '(' Iconst ')' opt_charset
* truncate where necessary)
*/
$$->typmod = VARHDRSZ + $3;
if (($5 != NULL) && (strcmp($5, "sql_text") != 0)) {
char *type;
type = palloc(strlen($$->name) + 1 + strlen($5) + 1);
strcpy(type, $$->name);
strcat(type, "_");
strcat(type, $5);
$$->name = xlateSqlType(type);
};
}
| character opt_charset
{
$$ = makeNode(TypeName);
$$->name = $1;
if (($2 != NULL) && (strcmp($2, "sql_text") != 0))
{
char *type;
type = palloc(strlen($1) + 1 + strlen($2) + 1);
strcpy(type, $1);
strcat(type, "_");
strcat(type, $2);
$1 = xlateSqlType(type);
}
$$ = makeTypeName($1);
/* char defaults to char(1), varchar to no limit */
if (strcmp($1, "bpchar") == 0)
$$->typmod = VARHDRSZ + 1;
else
$$->typmod = -1;
if (($2 != NULL) && (strcmp($2, "sql_text") != 0)) {
char *type;
type = palloc(strlen($$->name) + 1 + strlen($2) + 1);
strcpy(type, $$->name);
strcat(type, "_");
strcat(type, $2);
$$->name = xlateSqlType(type);
};
}
;
@@ -4488,11 +4493,10 @@ opt_collate: COLLATE ColId { $$ = $2; }
ConstDatetime: TIMESTAMP '(' Iconst ')' opt_timezone_x
{
$$ = makeNode(TypeName);
if ($5)
$$->name = xlateSqlType("timestamptz");
$$ = makeTypeName(xlateSqlType("timestamptz"));
else
$$->name = xlateSqlType("timestamp");
$$ = makeTypeName(xlateSqlType("timestamp"));
/* XXX the timezone field seems to be unused
* - thomas 2001-09-06
*/
@@ -4504,11 +4508,10 @@ ConstDatetime: TIMESTAMP '(' Iconst ')' opt_timezone_x
}
| TIMESTAMP opt_timezone_x
{
$$ = makeNode(TypeName);
if ($2)
$$->name = xlateSqlType("timestamptz");
$$ = makeTypeName(xlateSqlType("timestamptz"));
else
$$->name = xlateSqlType("timestamp");
$$ = makeTypeName(xlateSqlType("timestamp"));
/* XXX the timezone field seems to be unused
* - thomas 2001-09-06
*/
@@ -4524,11 +4527,10 @@ ConstDatetime: TIMESTAMP '(' Iconst ')' opt_timezone_x
}
| TIME '(' Iconst ')' opt_timezone
{
$$ = makeNode(TypeName);
if ($5)
$$->name = xlateSqlType("timetz");
$$ = makeTypeName(xlateSqlType("timetz"));
else
$$->name = xlateSqlType("time");
$$ = makeTypeName(xlateSqlType("time"));
if (($3 < 0) || ($3 > 13))
elog(ERROR,"TIME(%d)%s precision must be between %d and %d",
$3, ($5 ? " WITH TIME ZONE": ""), 0, 13);
@@ -4536,11 +4538,10 @@ ConstDatetime: TIMESTAMP '(' Iconst ')' opt_timezone_x
}
| TIME opt_timezone
{
$$ = makeNode(TypeName);
if ($2)
$$->name = xlateSqlType("timetz");
$$ = makeTypeName(xlateSqlType("timetz"));
else
$$->name = xlateSqlType("time");
$$ = makeTypeName(xlateSqlType("time"));
/* SQL99 specified a default precision of zero.
* See comments for timestamp above on why we will
* leave this unspecified for now. - thomas 2001-12-07
@@ -4551,9 +4552,7 @@ ConstDatetime: TIMESTAMP '(' Iconst ')' opt_timezone_x
ConstInterval: INTERVAL
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("interval");
$$->typmod = -1;
$$ = makeTypeName(xlateSqlType("interval"));
}
;
@@ -5161,7 +5160,7 @@ c_expr: columnref
| CURRENT_DATE opt_empty_parentheses
{
/*
* Translate as "date('now'::text)".
* Translate as "'now'::text::date".
*
* We cannot use "'now'::date" because coerce_type() will
* immediately reduce that to a constant representing
@@ -5174,43 +5173,30 @@ c_expr: columnref
* of type-input conversion functions...
*/
A_Const *s = makeNode(A_Const);
TypeName *t = makeNode(TypeName);
TypeName *d = makeNode(TypeName);
TypeName *d;
s->val.type = T_String;
s->val.val.str = "now";
s->typename = t;
s->typename = makeTypeName(xlateSqlType("text"));
t->name = xlateSqlType("text");
t->setof = FALSE;
t->typmod = -1;
d->name = xlateSqlType("date");
d->setof = FALSE;
d->typmod = -1;
d = makeTypeName(xlateSqlType("date"));
$$ = (Node *)makeTypeCast((Node *)s, d);
}
| CURRENT_TIME opt_empty_parentheses
{
/*
* Translate as "timetz('now'::text)".
* Translate as "'now'::text::timetz".
* See comments for CURRENT_DATE.
*/
A_Const *s = makeNode(A_Const);
TypeName *t = makeNode(TypeName);
TypeName *d = makeNode(TypeName);
TypeName *d;
s->val.type = T_String;
s->val.val.str = "now";
s->typename = t;
s->typename = makeTypeName(xlateSqlType("text"));
t->name = xlateSqlType("text");
t->setof = FALSE;
t->typmod = -1;
d->name = xlateSqlType("timetz");
d->setof = FALSE;
d = makeTypeName(xlateSqlType("timetz"));
/* SQL99 mandates a default precision of zero for TIME
* fields in schemas. However, for CURRENT_TIME
* let's preserve the microsecond precision we
@@ -5223,23 +5209,17 @@ c_expr: columnref
| CURRENT_TIME '(' Iconst ')'
{
/*
* Translate as "timetz('now'::text)".
* Translate as "'now'::text::timetz(n)".
* See comments for CURRENT_DATE.
*/
A_Const *s = makeNode(A_Const);
TypeName *t = makeNode(TypeName);
TypeName *d = makeNode(TypeName);
TypeName *d;
s->val.type = T_String;
s->val.val.str = "now";
s->typename = t;
s->typename = makeTypeName(xlateSqlType("text"));
t->name = xlateSqlType("text");
t->setof = FALSE;
t->typmod = -1;
d->name = xlateSqlType("timetz");
d->setof = FALSE;
d = makeTypeName(xlateSqlType("timetz"));
if (($3 < 0) || ($3 > 13))
elog(ERROR,"CURRENT_TIME(%d) precision must be between %d and %d",
$3, 0, 13);
@@ -5250,23 +5230,17 @@ c_expr: columnref
| CURRENT_TIMESTAMP opt_empty_parentheses
{
/*
* Translate as "timestamptz('now'::text)".
* Translate as "'now'::text::timestamptz".
* See comments for CURRENT_DATE.
*/
A_Const *s = makeNode(A_Const);
TypeName *t = makeNode(TypeName);
TypeName *d = makeNode(TypeName);
TypeName *d;
s->val.type = T_String;
s->val.val.str = "now";
s->typename = t;
s->typename = makeTypeName(xlateSqlType("text"));
t->name = xlateSqlType("text");
t->setof = FALSE;
t->typmod = -1;
d->name = xlateSqlType("timestamptz");
d->setof = FALSE;
d = makeTypeName(xlateSqlType("timestamptz"));
/* SQL99 mandates a default precision of 6 for timestamp.
* Also, that is about as precise as we will get since
* we are using a microsecond time interface.
@@ -5279,23 +5253,17 @@ c_expr: columnref
| CURRENT_TIMESTAMP '(' Iconst ')'
{
/*
* Translate as "timestamptz('now'::text)".
* Translate as "'now'::text::timestamptz(n)".
* See comments for CURRENT_DATE.
*/
A_Const *s = makeNode(A_Const);
TypeName *t = makeNode(TypeName);
TypeName *d = makeNode(TypeName);
TypeName *d;
s->val.type = T_String;
s->val.val.str = "now";
s->typename = t;
s->typename = makeTypeName(xlateSqlType("text"));
t->name = xlateSqlType("text");
t->setof = FALSE;
t->typmod = -1;
d->name = xlateSqlType("timestamptz");
d->setof = FALSE;
d = makeTypeName(xlateSqlType("timestamptz"));
if (($3 < 0) || ($3 > 13))
elog(ERROR,"CURRENT_TIMESTAMP(%d) precision must be between %d and %d",
$3, 0, 13);
@@ -5645,24 +5613,24 @@ columnref: relation_name opt_indirection
$$->fields = makeList1(makeString($1));
$$->indirection = $2;
}
| relation_name attrs opt_indirection
| dotted_name opt_indirection
{
$$ = makeNode(ColumnRef);
$$->fields = lcons(makeString($1), $2);
$$->indirection = $3;
$$->fields = $1;
$$->indirection = $2;
}
;
attrs: opt_attrs '.' attr_name
{ $$ = lappend($1, makeString($3)); }
| opt_attrs '.' '*'
{ $$ = lappend($1, makeString("*")); }
dotted_name: relation_name attrs
{ $$ = lcons(makeString($1), $2); }
;
opt_attrs: /*EMPTY*/
{ $$ = NIL; }
| opt_attrs '.' attr_name
{ $$ = lappend($1, makeString($3)); }
attrs: '.' attr_name
{ $$ = makeList1(makeString($2)); }
| '.' '*'
{ $$ = makeList1(makeString("*")); }
| '.' attr_name attrs
{ $$ = lcons(makeString($2), $3); }
;
opt_empty_parentheses: '(' ')' { $$ = TRUE; }
@@ -5742,11 +5710,11 @@ relation_name: SpecialRuleRelation
$$ = $1;
}
;
qualified_name_list: qualified_name
{ $$ = makeList1($1); }
{ $$ = makeList1($1); }
| qualified_name_list ',' qualified_name
{ $$ = lappend($1, $3); }
{ $$ = lappend($1, $3); }
;
qualified_name: ColId
@@ -5787,6 +5755,21 @@ class: ColId { $$ = $1; };
index_name: ColId { $$ = $1; };
file_name: Sconst { $$ = $1; };
/* func_name will soon return a List ... but not yet */
/*
func_name: function_name
{ $$ = makeList1(makeString($1)); }
| dotted_name
{ $$ = $1; }
;
*/
func_name: function_name
{ $$ = $1; }
| dotted_name
{ $$ = strVal(lfirst($1)); }
;
/* Constants
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
*/
@@ -5867,9 +5850,7 @@ AexprConst: Iconst
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = "t";
n->typename = makeNode(TypeName);
n->typename->name = xlateSqlType("bool");
n->typename->typmod = -1;
n->typename = makeTypeName(xlateSqlType("bool"));
$$ = (Node *)n;
}
| FALSE_P
@@ -5877,9 +5858,7 @@ AexprConst: Iconst
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = "f";
n->typename = makeNode(TypeName);
n->typename->name = xlateSqlType("bool");
n->typename->typmod = -1;
n->typename = makeTypeName(xlateSqlType("bool"));
$$ = (Node *)n;
}
| NULL_P
@@ -5920,7 +5899,7 @@ type_name: IDENT { $$ = $1; }
/* Function identifier --- names that can be function names.
*/
func_name: IDENT { $$ = xlateSqlFunc($1); }
function_name: IDENT { $$ = xlateSqlFunc($1); }
| unreserved_keyword { $$ = xlateSqlFunc($1); }
| func_name_keyword { $$ = xlateSqlFunc($1); }
;
@@ -6304,6 +6283,7 @@ static Node *
makeStringConst(char *str, TypeName *typename)
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = str;
n->typename = typename;
@@ -6315,12 +6295,10 @@ static Node *
makeFloatConst(char *str)
{
A_Const *n = makeNode(A_Const);
TypeName *t = makeNode(TypeName);
n->val.type = T_Float;
n->val.val.str = str;
t->name = xlateSqlType("float");
t->typmod = -1;
n->typename = t;
n->typename = makeTypeName(xlateSqlType("float"));
return (Node *)n;
}
@@ -6435,7 +6413,6 @@ makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg)
return (Node *) n;
}
/* xlateSqlFunc()
* Convert alternate function names to internal Postgres functions.
*

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.111 2002/03/21 16:01:03 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.112 2002/03/29 19:06:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1103,7 +1103,7 @@ parser_typecast_constant(Value *expr, TypeName *typename)
bool string_palloced = false;
bool isNull = false;
tp = typenameType(TypeNameToInternalName(typename));
tp = typenameType(typename);
switch (nodeTag(expr))
{
@@ -1161,7 +1161,7 @@ parser_typecast_expression(ParseState *pstate,
Oid inputType = exprType(expr);
Oid targetType;
targetType = typenameTypeId(TypeNameToInternalName(typename));
targetType = typenameTypeId(typename);
if (inputType == InvalidOid)
return expr; /* do nothing if NULL input */
@@ -1185,27 +1185,3 @@ parser_typecast_expression(ParseState *pstate,
return expr;
}
/*
* Given a TypeName node as returned by the grammar, generate the internal
* name of the corresponding type. Note this does NOT check if the type
* exists or not.
*/
char *
TypeNameToInternalName(TypeName *typename)
{
Assert(typename->attrname == NULL);
if (typename->arrayBounds != NIL)
{
/*
* By convention, the name of an array type is the name of its
* element type with "_" prepended.
*/
char *arrayname = palloc(strlen(typename->name) + 2);
sprintf(arrayname, "_%s", typename->name);
return arrayname;
}
else
return typename->name;
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.120 2002/03/22 02:56:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.121 2002/03/29 19:06:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#include "catalog/indexing.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "nodes/makefuncs.h"
#include "parser/parse_agg.h"
@@ -969,9 +970,14 @@ func_get_detail(char *funcname,
{
Oid targetType;
targetType = GetSysCacheOid(TYPENAME,
/* XXX WRONG: need to search searchpath for name; but little
* point in fixing before we revise this code for qualified
* funcnames too.
*/
targetType = GetSysCacheOid(TYPENAMENSP,
PointerGetDatum(funcname),
0, 0, 0);
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
0, 0);
if (OidIsValid(targetType) &&
!ISCOMPLEX(targetType))
{
@@ -1222,13 +1228,11 @@ find_inheritors(Oid relid, Oid **supervec)
{
/* return the type id, rather than the relation id */
Relation rd;
Oid trelid;
relid = lfirsti(elt);
rd = heap_open(relid, NoLock);
trelid = typenameTypeId(RelationGetRelationName(rd));
*relidvec++ = rd->rd_rel->reltype;
heap_close(rd, NoLock);
*relidvec++ = trelid;
}
}
else
@@ -1473,7 +1477,9 @@ ParseComplexProjection(ParseState *pstate,
* argument types
*/
void
func_error(char *caller, char *funcname, int nargs, Oid *argtypes, char *msg)
func_error(const char *caller, const char *funcname,
int nargs, const Oid *argtypes,
const char *msg)
{
char p[(NAMEDATALEN + 2) * FUNC_MAX_ARGS],
*ptr;
@@ -1488,9 +1494,9 @@ func_error(char *caller, char *funcname, int nargs, Oid *argtypes, char *msg)
*ptr++ = ',';
*ptr++ = ' ';
}
if (argtypes[i] != 0)
if (OidIsValid(argtypes[i]))
{
strcpy(ptr, typeidTypeName(argtypes[i]));
strncpy(ptr, typeidTypeName(argtypes[i]), NAMEDATALEN);
*(ptr + NAMEDATALEN) = '\0';
}
else

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.79 2002/03/22 02:56:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.80 2002/03/29 19:06:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -525,8 +525,15 @@ FigureColnameInternal(Node *node, char **name)
case T_A_Const:
if (((A_Const *) node)->typename != NULL)
{
*name = ((A_Const *) node)->typename->name;
return 1;
List *names = ((A_Const *) node)->typename->names;
if (names != NIL)
{
while (lnext(names) != NIL)
names = lnext(names);
*name = strVal(lfirst(names));
return 1;
}
}
break;
case T_TypeCast:
@@ -536,8 +543,15 @@ FigureColnameInternal(Node *node, char **name)
{
if (((TypeCast *) node)->typename != NULL)
{
*name = ((TypeCast *) node)->typename->name;
return 1;
List *names = ((TypeCast *) node)->typename->names;
if (names != NIL)
{
while (lnext(names) != NIL)
names = lnext(names);
*name = strVal(lfirst(names));
return 1;
}
}
}
break;

View File

@@ -8,20 +8,250 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.37 2001/10/25 05:49:40 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.38 2002/03/29 19:06:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "catalog/namespace.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/parsenodes.h"
#include "parser/parser.h"
#include "parser/parse_expr.h"
#include "parser/parse_type.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
/*
* LookupTypeName
* Given a TypeName object, get the OID of the referenced type.
* Returns InvalidOid if no such type can be found.
*
* NB: even if the returned OID is not InvalidOid, the type might be
* just a shell. Caller should check typisdefined before using the type.
*/
Oid
LookupTypeName(const TypeName *typename)
{
Oid restype;
/* Easy if it's an internally generated TypeName */
if (typename->names == NIL)
return typename->typeid;
if (typename->pct_type)
{
/* Handle %TYPE reference to type of an existing field */
RangeVar *rel = makeRangeVar(NULL, NULL);
char *field = NULL;
Oid relid;
AttrNumber attnum;
/* deconstruct the name list */
switch (length(typename->names))
{
case 1:
elog(ERROR, "Improper %%TYPE reference (too few dotted names)");
break;
case 2:
rel->relname = strVal(lfirst(typename->names));
field = strVal(lsecond(typename->names));
break;
case 3:
rel->schemaname = strVal(lfirst(typename->names));
rel->relname = strVal(lsecond(typename->names));
field = strVal(lfirst(lnext(lnext(typename->names))));
break;
case 4:
rel->catalogname = strVal(lfirst(typename->names));
rel->schemaname = strVal(lsecond(typename->names));
rel->relname = strVal(lfirst(lnext(lnext(typename->names))));
field = strVal(lfirst(lnext(lnext(lnext(typename->names)))));
break;
default:
elog(ERROR, "Improper %%TYPE reference (too many dotted names)");
break;
}
/* look up the field */
relid = RangeVarGetRelid(rel, false);
attnum = get_attnum(relid, field);
if (attnum == InvalidAttrNumber)
elog(ERROR, "'%s' is not an attribute of class '%s'",
field, rel->relname);
restype = get_atttype(relid, attnum);
/* this construct should never have an array indicator */
Assert(typename->arrayBounds == NIL);
/* emit nuisance warning */
elog(NOTICE, "%s converted to %s",
TypeNameToString(typename), typeidTypeName(restype));
}
else
{
/* Normal reference to a type name */
char *catalogname;
char *schemaname = NULL;
char *typname = NULL;
/* deconstruct the name list */
switch (length(typename->names))
{
case 1:
typname = strVal(lfirst(typename->names));
break;
case 2:
schemaname = strVal(lfirst(typename->names));
typname = strVal(lsecond(typename->names));
break;
case 3:
catalogname = strVal(lfirst(typename->names));
schemaname = strVal(lsecond(typename->names));
typname = strVal(lfirst(lnext(lnext(typename->names))));
/*
* We check the catalog name and then ignore it.
*/
if (strcmp(catalogname, DatabaseName) != 0)
elog(ERROR, "Cross-database references are not implemented");
break;
default:
elog(ERROR, "Improper type name (too many dotted names)");
break;
}
/* If an array reference, look up the array type instead */
if (typename->arrayBounds != NIL)
typname = makeArrayTypeName(typname);
if (schemaname)
{
Oid namespaceId;
namespaceId = GetSysCacheOid(NAMESPACENAME,
CStringGetDatum(schemaname),
0, 0, 0);
if (!OidIsValid(namespaceId))
elog(ERROR, "Namespace \"%s\" does not exist",
schemaname);
restype = GetSysCacheOid(TYPENAMENSP,
PointerGetDatum(typname),
ObjectIdGetDatum(namespaceId),
0, 0);
}
else
{
/* XXX wrong, should use namespace search */
restype = GetSysCacheOid(TYPENAMENSP,
PointerGetDatum(typname),
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
0, 0);
}
}
return restype;
}
/*
* TypeNameToString
* Produce a string representing the name of a TypeName.
*
* NB: this must work on TypeNames that do not describe any actual type;
* it is mostly used for reporting lookup errors.
*/
char *
TypeNameToString(const TypeName *typename)
{
StringInfoData string;
initStringInfo(&string);
if (typename->names != NIL)
{
/* Emit possibly-qualified name as-is */
List *l;
foreach(l, typename->names)
{
if (l != typename->names)
appendStringInfoChar(&string, '.');
appendStringInfo(&string, "%s", strVal(lfirst(l)));
}
}
else
{
/* Look up internally-specified type */
appendStringInfo(&string, "%s", typeidTypeName(typename->typeid));
}
/*
* Add decoration as needed, but only for fields considered by
* LookupTypeName
*/
if (typename->pct_type)
appendStringInfo(&string, "%%TYPE");
if (typename->arrayBounds != NIL)
appendStringInfo(&string, "[]");
return string.data;
}
/*
* typenameTypeId - given a TypeName, return the type's OID
*
* This is equivalent to LookupTypeName, except that this will report
* a suitable error message if the type cannot be found or is not defined.
*/
Oid
typenameTypeId(const TypeName *typename)
{
Oid typoid;
typoid = LookupTypeName(typename);
if (!OidIsValid(typoid))
elog(ERROR, "Type \"%s\" does not exist",
TypeNameToString(typename));
if (!get_typisdefined(typoid))
elog(ERROR, "Type \"%s\" is only a shell",
TypeNameToString(typename));
return typoid;
}
/*
* typenameType - given a TypeName, return a Type structure
*
* This is equivalent to typenameTypeId + syscache fetch of Type tuple.
* NB: caller must ReleaseSysCache the type tuple when done with it.
*/
Type
typenameType(const TypeName *typename)
{
Oid typoid;
HeapTuple tup;
typoid = LookupTypeName(typename);
if (!OidIsValid(typoid))
elog(ERROR, "Type \"%s\" does not exist",
TypeNameToString(typename));
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typoid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "Type \"%s\" does not exist",
TypeNameToString(typename));
if (! ((Form_pg_type) GETSTRUCT(tup))->typisdefined)
elog(ERROR, "Type \"%s\" is only a shell",
TypeNameToString(typename));
return (Type) tup;
}
/* check to see if a type id is valid,
* returns true if it is. By using this call before calling
* typeidType or typeidTypeName, more meaningful error messages
@@ -51,24 +281,6 @@ typeidType(Oid id)
return (Type) tup;
}
/* return a Type structure, given type name */
/* NB: caller must ReleaseSysCache the type tuple when done with it */
Type
typenameType(char *s)
{
HeapTuple tup;
if (s == NULL)
elog(ERROR, "typenameType: Null typename");
tup = SearchSysCache(TYPENAME,
PointerGetDatum(s),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "Unable to locate type name '%s' in catalog", s);
return (Type) tup;
}
/* given type (as type struct), return the type OID */
Oid
typeTypeId(Type tp)
@@ -207,6 +419,7 @@ typeidOutfunc(Oid type_id)
#endif
/* return a type name, given a typeid */
/* nb: type name is NOT unique; use this only for error messages */
char *
typeidTypeName(Oid id)
{
@@ -251,18 +464,6 @@ typeidTypeRelid(Oid type_id)
return result;
}
/* given a type name, return the type's typeid */
Oid
typenameTypeId(char *s)
{
Type typ = typenameType(s);
Oid result;
result = typ->t_data->t_oid;
ReleaseSysCache(typ);
return result;
}
/*
* Given a string that is supposed to be a SQL-compatible type declaration,
* such as "int4" or "integer" or "character varying(32)", parse
@@ -327,7 +528,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
!IsA(typename, TypeName))
elog(ERROR, "Invalid type name '%s'", str);
*type_id = typenameTypeId(TypeNameToInternalName(typename));
*type_id = typenameTypeId(typename);
*typmod = typename->typmod;
pfree(buf);