Commit fbd26d69 authored by Tom Lane's avatar Tom Lane

Arrange that no database accesses are attempted during parser() --- this

took some rejiggering of typename and ACL parsing, as well as moving
parse_analyze call out of parser().  Restructure postgres.c processing
so that parse analysis and rewrite are skipped when in abort-transaction
state.  Only COMMIT and ABORT statements will be processed beyond the raw
parser() phase.  This addresses problem of parser failing with database access
errors while in aborted state (see pghackers discussions around 7/28/00).
Also fix some bugs with COMMIT/ABORT statements appearing in the middle of
a single query input string.
Function, operator, and aggregate arguments/results can now use full
TypeName production, in particular foo[] for array types.
DROP OPERATOR and COMMENT ON OPERATOR were broken for unary operators.
Allow CREATE AGGREGATE to accept unquoted numeric constants for initcond.
parent 4837270b
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.48 2000/08/21 20:55:31 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.49 2000/10/07 00:58:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -93,35 +93,34 @@ ProcedureCreate(char *procedureName, ...@@ -93,35 +93,34 @@ ProcedureCreate(char *procedureName,
MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid)); MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid));
foreach(x, argList) foreach(x, argList)
{ {
Value *t = lfirst(x); TypeName *t = (TypeName *) lfirst(x);
char *typnam = TypeNameToInternalName(t);
if (parameterCount >= FUNC_MAX_ARGS) if (parameterCount >= FUNC_MAX_ARGS)
elog(ERROR, "Procedures cannot take more than %d arguments", elog(ERROR, "Procedures cannot take more than %d arguments",
FUNC_MAX_ARGS); FUNC_MAX_ARGS);
if (strcmp(strVal(t), "opaque") == 0) if (strcmp(typnam, "opaque") == 0)
{ {
if (languageObjectId == SQLlanguageId) if (languageObjectId == SQLlanguageId)
elog(ERROR, "ProcedureCreate: sql functions cannot take type \"opaque\""); elog(ERROR, "ProcedureCreate: sql functions cannot take type \"opaque\"");
toid = 0; toid = InvalidOid;
} }
else else
{ {
toid = TypeGet(strVal(t), &defined); toid = TypeGet(typnam, &defined);
if (!OidIsValid(toid)) if (!OidIsValid(toid))
{
elog(ERROR, "ProcedureCreate: arg type '%s' is not defined", elog(ERROR, "ProcedureCreate: arg type '%s' is not defined",
strVal(t)); typnam);
}
if (!defined) if (!defined)
{
elog(NOTICE, "ProcedureCreate: arg type '%s' is only a shell", elog(NOTICE, "ProcedureCreate: arg type '%s' is only a shell",
strVal(t)); typnam);
}
} }
if (t->setof)
elog(ERROR, "ProcedureCreate: functions cannot accept set arguments");
typev[parameterCount++] = toid; typev[parameterCount++] = toid;
} }
...@@ -178,7 +177,7 @@ ProcedureCreate(char *procedureName, ...@@ -178,7 +177,7 @@ ProcedureCreate(char *procedureName,
{ {
if (languageObjectId == SQLlanguageId) if (languageObjectId == SQLlanguageId)
elog(ERROR, "ProcedureCreate: sql functions cannot return type \"opaque\""); elog(ERROR, "ProcedureCreate: sql functions cannot return type \"opaque\"");
typeObjectId = 0; typeObjectId = InvalidOid;
} }
else else
{ {
...@@ -194,11 +193,9 @@ ProcedureCreate(char *procedureName, ...@@ -194,11 +193,9 @@ ProcedureCreate(char *procedureName,
returnTypeName); returnTypeName);
} }
else if (!defined) else if (!defined)
{
elog(NOTICE, "ProcedureCreate: return type '%s' is only a shell", elog(NOTICE, "ProcedureCreate: return type '%s' is only a shell",
returnTypeName); returnTypeName);
} }
}
/* /*
* don't allow functions of complex types that have the same name as * don't allow functions of complex types that have the same name as
...@@ -212,7 +209,6 @@ ProcedureCreate(char *procedureName, ...@@ -212,7 +209,6 @@ ProcedureCreate(char *procedureName,
elog(ERROR, "method %s already an attribute of type %s", elog(ERROR, "method %s already an attribute of type %s",
procedureName, strVal(lfirst(argList))); procedureName, strVal(lfirst(argList)));
/* /*
* If this is a postquel procedure, we parse it here in order to be * If this is a postquel procedure, we parse it here in order to be
* sure that it contains no syntax errors. We should store the plan * sure that it contains no syntax errors. We should store the plan
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "commands/comment.h" #include "commands/comment.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse.h" #include "parser/parse.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "rewrite/rewriteRemove.h" #include "rewrite/rewriteRemove.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
...@@ -46,7 +48,7 @@ static void CommentAttribute(char *relation, char *attrib, char *comment); ...@@ -46,7 +48,7 @@ static void CommentAttribute(char *relation, char *attrib, char *comment);
static void CommentDatabase(char *database, char *comment); static void CommentDatabase(char *database, char *comment);
static void CommentRewrite(char *rule, char *comment); static void CommentRewrite(char *rule, char *comment);
static void CommentType(char *type, char *comment); static void CommentType(char *type, char *comment);
static void CommentAggregate(char *aggregate, char *aggtype, char *comment); static void CommentAggregate(char *aggregate, List *arguments, char *comment);
static void CommentProc(char *function, List *arguments, char *comment); static void CommentProc(char *function, List *arguments, char *comment);
static void CommentOperator(char *opname, List *arguments, char *comment); static void CommentOperator(char *opname, List *arguments, char *comment);
static void CommentTrigger(char *trigger, char *relation, char *comments); static void CommentTrigger(char *trigger, char *relation, char *comments);
...@@ -92,7 +94,7 @@ CommentObject(int objtype, char *objname, char *objproperty, ...@@ -92,7 +94,7 @@ CommentObject(int objtype, char *objname, char *objproperty,
CommentType(objname, comment); CommentType(objname, comment);
break; break;
case (AGGREGATE): case (AGGREGATE):
CommentAggregate(objname, objproperty, comment); CommentAggregate(objname, objlist, comment);
break; break;
case (FUNCTION): case (FUNCTION):
CommentProc(objname, objlist, comment); CommentProc(objname, objlist, comment);
...@@ -544,9 +546,10 @@ CommentType(char *type, char *comment) ...@@ -544,9 +546,10 @@ CommentType(char *type, char *comment)
*/ */
static void static void
CommentAggregate(char *aggregate, char *argument, char *comment) CommentAggregate(char *aggregate, List *arguments, char *comment)
{ {
TypeName *aggtype = (TypeName *) lfirst(arguments);
char *aggtypename = NULL;
HeapTuple aggtuple; HeapTuple aggtuple;
Oid baseoid, Oid baseoid,
oid; oid;
...@@ -554,11 +557,12 @@ CommentAggregate(char *aggregate, char *argument, char *comment) ...@@ -554,11 +557,12 @@ CommentAggregate(char *aggregate, char *argument, char *comment)
/*** First, attempt to determine the base aggregate oid ***/ /*** First, attempt to determine the base aggregate oid ***/
if (argument) if (aggtype)
{ {
baseoid = TypeGet(argument, &defined); aggtypename = TypeNameToInternalName(aggtype);
baseoid = TypeGet(aggtypename, &defined);
if (!OidIsValid(baseoid)) if (!OidIsValid(baseoid))
elog(ERROR, "aggregate type '%s' does not exist", argument); elog(ERROR, "type '%s' does not exist", aggtypename);
} }
else else
baseoid = 0; baseoid = 0;
...@@ -568,10 +572,10 @@ CommentAggregate(char *aggregate, char *argument, char *comment) ...@@ -568,10 +572,10 @@ CommentAggregate(char *aggregate, char *argument, char *comment)
#ifndef NO_SECURITY #ifndef NO_SECURITY
if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid)) if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid))
{ {
if (argument) if (aggtypename)
{ {
elog(ERROR, "you are not permitted to comment on aggregate '%s' %s '%s'", elog(ERROR, "you are not permitted to comment on aggregate '%s' %s '%s'",
aggregate, "with type", argument); aggregate, "with type", aggtypename);
} }
else else
{ {
...@@ -587,10 +591,10 @@ CommentAggregate(char *aggregate, char *argument, char *comment) ...@@ -587,10 +591,10 @@ CommentAggregate(char *aggregate, char *argument, char *comment)
ObjectIdGetDatum(baseoid), 0, 0); ObjectIdGetDatum(baseoid), 0, 0);
if (!HeapTupleIsValid(aggtuple)) if (!HeapTupleIsValid(aggtuple))
{ {
if (argument) if (aggtypename)
{ {
elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'", elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'",
argument, aggregate); aggtypename, aggregate);
} }
else else
elog(ERROR, "aggregate '%s' does not exist", aggregate); elog(ERROR, "aggregate '%s' does not exist", aggregate);
...@@ -622,7 +626,6 @@ CommentProc(char *function, List *arguments, char *comment) ...@@ -622,7 +626,6 @@ CommentProc(char *function, List *arguments, char *comment)
functuple; functuple;
Oid oid, Oid oid,
argoids[FUNC_MAX_ARGS]; argoids[FUNC_MAX_ARGS];
char *argument;
int i, int i,
argcount; argcount;
...@@ -635,18 +638,20 @@ CommentProc(char *function, List *arguments, char *comment) ...@@ -635,18 +638,20 @@ CommentProc(char *function, List *arguments, char *comment)
FUNC_MAX_ARGS); FUNC_MAX_ARGS);
for (i = 0; i < argcount; i++) for (i = 0; i < argcount; i++)
{ {
argument = strVal(lfirst(arguments)); TypeName *t = (TypeName *) lfirst(arguments);
char *typnam = TypeNameToInternalName(t);
arguments = lnext(arguments); arguments = lnext(arguments);
if (strcmp(argument, "opaque") == 0)
argoids[i] = 0; if (strcmp(typnam, "opaque") == 0)
argoids[i] = InvalidOid;
else else
{ {
argtuple = SearchSysCacheTuple(TYPENAME, argtuple = SearchSysCacheTuple(TYPENAME,
PointerGetDatum(argument), PointerGetDatum(typnam),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(argtuple)) if (!HeapTupleIsValid(argtuple))
elog(ERROR, "function argument type '%s' does not exist", elog(ERROR, "CommentProc: type '%s' not found", typnam);
argument);
argoids[i] = argtuple->t_data->t_oid; argoids[i] = argtuple->t_data->t_oid;
} }
} }
...@@ -664,10 +669,9 @@ CommentProc(char *function, List *arguments, char *comment) ...@@ -664,10 +669,9 @@ CommentProc(char *function, List *arguments, char *comment)
functuple = SearchSysCacheTuple(PROCNAME, PointerGetDatum(function), functuple = SearchSysCacheTuple(PROCNAME, PointerGetDatum(function),
Int32GetDatum(argcount), Int32GetDatum(argcount),
PointerGetDatum(argoids), 0); PointerGetDatum(argoids), 0);
if (!HeapTupleIsValid(functuple)) if (!HeapTupleIsValid(functuple))
elog(ERROR, "function '%s' with the supplied %s does not exist", func_error("CommentProc", function, argcount, argoids, NULL);
function, "argument list");
oid = functuple->t_data->t_oid; oid = functuple->t_data->t_oid;
/*** Call CreateComments() to create/drop the comments ***/ /*** Call CreateComments() to create/drop the comments ***/
...@@ -691,23 +695,24 @@ CommentProc(char *function, List *arguments, char *comment) ...@@ -691,23 +695,24 @@ CommentProc(char *function, List *arguments, char *comment)
static void static void
CommentOperator(char *opername, List *arguments, char *comment) CommentOperator(char *opername, List *arguments, char *comment)
{ {
TypeName *typenode1 = (TypeName *) lfirst(arguments);
TypeName *typenode2 = (TypeName *) lsecond(arguments);
char oprtype = 0,
*lefttype = NULL,
*righttype = NULL;
Form_pg_operator data; Form_pg_operator data;
HeapTuple optuple; HeapTuple optuple;
Oid oid, Oid oid,
leftoid = InvalidOid, leftoid = InvalidOid,
rightoid = InvalidOid; rightoid = InvalidOid;
bool defined; bool defined;
char oprtype = 0,
*lefttype = NULL,
*righttype = NULL;
/*** Initialize our left and right argument types ***/ /*** Initialize our left and right argument types ***/
if (lfirst(arguments) != NULL) if (typenode1 != NULL)
lefttype = strVal(lfirst(arguments)); lefttype = TypeNameToInternalName(typenode1);
if (lsecond(arguments) != NULL) if (typenode2 != NULL)
righttype = strVal(lsecond(arguments)); righttype = TypeNameToInternalName(typenode2);
/*** Attempt to fetch the left oid, if specified ***/ /*** Attempt to fetch the left oid, if specified ***/
...@@ -732,9 +737,9 @@ CommentOperator(char *opername, List *arguments, char *comment) ...@@ -732,9 +737,9 @@ CommentOperator(char *opername, List *arguments, char *comment)
if (OidIsValid(leftoid) && (OidIsValid(rightoid))) if (OidIsValid(leftoid) && (OidIsValid(rightoid)))
oprtype = 'b'; oprtype = 'b';
else if (OidIsValid(leftoid)) else if (OidIsValid(leftoid))
oprtype = 'l';
else if (OidIsValid(rightoid))
oprtype = 'r'; oprtype = 'r';
else if (OidIsValid(rightoid))
oprtype = 'l';
else else
elog(ERROR, "operator '%s' is of an illegal type'", opername); elog(ERROR, "operator '%s' is of an illegal type'", opername);
...@@ -769,7 +774,6 @@ CommentOperator(char *opername, List *arguments, char *comment) ...@@ -769,7 +774,6 @@ CommentOperator(char *opername, List *arguments, char *comment)
/*** Call CreateComments() to create/drop the comments ***/ /*** Call CreateComments() to create/drop the comments ***/
CreateComments(oid, comment); CreateComments(oid, comment);
} }
/*------------------------------------------------------------------ /*------------------------------------------------------------------
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.52 2000/09/12 16:48:55 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.53 2000/10/07 00:58:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "commands/comment.h" #include "commands/comment.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/syscache.h" #include "utils/syscache.h"
...@@ -39,8 +40,8 @@ ...@@ -39,8 +40,8 @@
*/ */
void void
RemoveOperator(char *operatorName, /* operator name */ RemoveOperator(char *operatorName, /* operator name */
char *typeName1, /* first type name */ char *typeName1, /* left argument type name */
char *typeName2) /* optional second type name */ char *typeName2) /* right argument type name */
{ {
Relation relation; Relation relation;
HeapTuple tup; HeapTuple tup;
...@@ -53,28 +54,22 @@ RemoveOperator(char *operatorName, /* operator name */ ...@@ -53,28 +54,22 @@ RemoveOperator(char *operatorName, /* operator name */
{ {
typeId1 = TypeGet(typeName1, &defined); typeId1 = TypeGet(typeName1, &defined);
if (!OidIsValid(typeId1)) if (!OidIsValid(typeId1))
{
elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName1); elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName1);
return;
}
} }
if (typeName2) if (typeName2)
{ {
typeId2 = TypeGet(typeName2, &defined); typeId2 = TypeGet(typeName2, &defined);
if (!OidIsValid(typeId2)) if (!OidIsValid(typeId2))
{
elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName2); elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName2);
return;
}
} }
if (OidIsValid(typeId1) && OidIsValid(typeId2)) if (OidIsValid(typeId1) && OidIsValid(typeId2))
oprtype = 'b'; oprtype = 'b';
else if (OidIsValid(typeId1)) else if (OidIsValid(typeId1))
oprtype = 'l';
else
oprtype = 'r'; oprtype = 'r';
else
oprtype = 'l';
relation = heap_openr(OperatorRelationName, RowExclusiveLock); relation = heap_openr(OperatorRelationName, RowExclusiveLock);
...@@ -94,7 +89,6 @@ RemoveOperator(char *operatorName, /* operator name */ ...@@ -94,7 +89,6 @@ RemoveOperator(char *operatorName, /* operator name */
operatorName); operatorName);
#endif #endif
/*** Delete any comments associated with this operator ***/ /*** Delete any comments associated with this operator ***/
DeleteComments(tup->t_data->t_oid); DeleteComments(tup->t_data->t_oid);
...@@ -308,13 +302,12 @@ RemoveType(char *typeName) /* type name to be removed */ ...@@ -308,13 +302,12 @@ RemoveType(char *typeName) /* type name to be removed */
*/ */
void void
RemoveFunction(char *functionName, /* function name to be removed */ RemoveFunction(char *functionName, /* function name to be removed */
int nargs, List *argTypes) /* list of TypeName nodes */
List *argNameList /* list of TypeNames */ )
{ {
int nargs = length(argTypes);
Relation relation; Relation relation;
HeapTuple tup; HeapTuple tup;
Oid argList[FUNC_MAX_ARGS]; Oid argList[FUNC_MAX_ARGS];
char *typename;
int i; int i;
if (nargs > FUNC_MAX_ARGS) if (nargs > FUNC_MAX_ARGS)
...@@ -323,19 +316,20 @@ RemoveFunction(char *functionName, /* function name to be removed */ ...@@ -323,19 +316,20 @@ RemoveFunction(char *functionName, /* function name to be removed */
MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
typename = strVal(lfirst(argNameList)); TypeName *t = (TypeName *) lfirst(argTypes);
argNameList = lnext(argNameList); char *typnam = TypeNameToInternalName(t);
if (strcmp(typename, "opaque") == 0) argTypes = lnext(argTypes);
argList[i] = 0;
if (strcmp(typnam, "opaque") == 0)
argList[i] = InvalidOid;
else else
{ {
tup = SearchSysCacheTuple(TYPENAME, tup = SearchSysCacheTuple(TYPENAME,
PointerGetDatum(typename), PointerGetDatum(typnam),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveFunction: type '%s' not found", typename); elog(ERROR, "RemoveFunction: type '%s' not found", typnam);
argList[i] = tup->t_data->t_oid; argList[i] = tup->t_data->t_oid;
} }
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.124 2000/10/05 19:11:27 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.125 2000/10/07 00:58:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1854,13 +1854,9 @@ _copyChangeACLStmt(ChangeACLStmt *from) ...@@ -1854,13 +1854,9 @@ _copyChangeACLStmt(ChangeACLStmt *from)
{ {
ChangeACLStmt *newnode = makeNode(ChangeACLStmt); ChangeACLStmt *newnode = makeNode(ChangeACLStmt);
if (from->aclitem)
{
newnode->aclitem = (struct AclItem *) palloc(sizeof(struct AclItem));
memcpy(newnode->aclitem, from->aclitem, sizeof(struct AclItem));
}
newnode->modechg = from->modechg;
Node_Copy(from, newnode, relNames); Node_Copy(from, newnode, relNames);
if (from->aclString)
newnode->aclString = pstrdup(from->aclString);
return newnode; return newnode;
} }
...@@ -2033,7 +2029,7 @@ _copyProcedureStmt(ProcedureStmt *from) ...@@ -2033,7 +2029,7 @@ _copyProcedureStmt(ProcedureStmt *from)
ProcedureStmt *newnode = makeNode(ProcedureStmt); ProcedureStmt *newnode = makeNode(ProcedureStmt);
newnode->funcname = pstrdup(from->funcname); newnode->funcname = pstrdup(from->funcname);
Node_Copy(from, newnode, defArgs); Node_Copy(from, newnode, argTypes);
Node_Copy(from, newnode, returnType); Node_Copy(from, newnode, returnType);
Node_Copy(from, newnode, withClause); Node_Copy(from, newnode, withClause);
Node_Copy(from, newnode, as); Node_Copy(from, newnode, as);
...@@ -2048,7 +2044,7 @@ _copyRemoveAggrStmt(RemoveAggrStmt *from) ...@@ -2048,7 +2044,7 @@ _copyRemoveAggrStmt(RemoveAggrStmt *from)
RemoveAggrStmt *newnode = makeNode(RemoveAggrStmt); RemoveAggrStmt *newnode = makeNode(RemoveAggrStmt);
newnode->aggname = pstrdup(from->aggname); newnode->aggname = pstrdup(from->aggname);
newnode->aggtype = pstrdup(from->aggtype); Node_Copy(from, newnode, aggtype);
return newnode; return newnode;
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.75 2000/10/05 19:11:27 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.76 2000/10/07 00:58:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -753,24 +753,10 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b) ...@@ -753,24 +753,10 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
static bool static bool
_equalChangeACLStmt(ChangeACLStmt *a, ChangeACLStmt *b) _equalChangeACLStmt(ChangeACLStmt *a, ChangeACLStmt *b)
{ {
if (a->aclitem && b->aclitem)
{
if (a->aclitem->ai_id != b->aclitem->ai_id)
return false;
if (a->aclitem->ai_idtype != b->aclitem->ai_idtype)
return false;
if (a->aclitem->ai_mode != b->aclitem->ai_mode)
return false;
}
else
{
if (a->aclitem != b->aclitem)
return false; /* one NULL, one not */
}
if (a->modechg != b->modechg)
return false;
if (!equal(a->relNames, b->relNames)) if (!equal(a->relNames, b->relNames))
return false; return false;
if (!equalstr(a->aclString, b->aclString))
return false;
return true; return true;
} }
...@@ -956,7 +942,7 @@ _equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b) ...@@ -956,7 +942,7 @@ _equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b)
{ {
if (!equalstr(a->funcname, b->funcname)) if (!equalstr(a->funcname, b->funcname))
return false; return false;
if (!equal(a->defArgs, b->defArgs)) if (!equal(a->argTypes, b->argTypes))
return false; return false;
if (!equal(a->returnType, b->returnType)) if (!equal(a->returnType, b->returnType))
return false; return false;
...@@ -975,7 +961,7 @@ _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b) ...@@ -975,7 +961,7 @@ _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
{ {
if (!equalstr(a->aggname, b->aggname)) if (!equalstr(a->aggname, b->aggname))
return false; return false;
if (!equalstr(a->aggtype, b->aggtype)) if (!equal(a->aggtype, b->aggtype))
return false; return false;
return true; return true;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: analyze.c,v 1.160 2000/10/05 19:11:33 tgl Exp $ * $Id: analyze.c,v 1.161 2000/10/07 00:58:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -69,25 +69,23 @@ static List *extras_after; ...@@ -69,25 +69,23 @@ static List *extras_after;
/* /*
* parse_analyze - * parse_analyze -
* analyze a list of parse trees and transform them if necessary. * analyze a raw parse tree and transform it to Query form.
*
* Returns a list of transformed parse trees. Optimizable statements are
* all transformed to Query while the rest stays the same.
* *
* The result is a List of Query nodes (we need a list since some commands
* produce multiple Queries). Optimizable statements require considerable
* transformation, while many utility-type statements are simply hung off
* a dummy CMD_UTILITY Query node.
*/ */
List * List *
parse_analyze(List *pl, ParseState *parentParseState) parse_analyze(Node *parseTree, ParseState *parentParseState)
{ {
List *result = NIL; List *result = NIL;
while (pl != NIL)
{
ParseState *pstate = make_parsestate(parentParseState); ParseState *pstate = make_parsestate(parentParseState);
Query *parsetree; Query *query;
extras_before = extras_after = NIL; extras_before = extras_after = NIL;
parsetree = transformStmt(pstate, lfirst(pl)); query = transformStmt(pstate, parseTree);
release_pstate_resources(pstate); release_pstate_resources(pstate);
while (extras_before != NIL) while (extras_before != NIL)
...@@ -98,7 +96,7 @@ parse_analyze(List *pl, ParseState *parentParseState) ...@@ -98,7 +96,7 @@ parse_analyze(List *pl, ParseState *parentParseState)
extras_before = lnext(extras_before); extras_before = lnext(extras_before);
} }
result = lappend(result, parsetree); result = lappend(result, query);
while (extras_after != NIL) while (extras_after != NIL)
{ {
...@@ -109,8 +107,6 @@ parse_analyze(List *pl, ParseState *parentParseState) ...@@ -109,8 +107,6 @@ parse_analyze(List *pl, ParseState *parentParseState)
} }
pfree(pstate); pfree(pstate);
pl = lnext(pl);
}
return result; return result;
} }
...@@ -126,8 +122,7 @@ release_pstate_resources(ParseState *pstate) ...@@ -126,8 +122,7 @@ release_pstate_resources(ParseState *pstate)
/* /*
* transformStmt - * transformStmt -
* transform a Parse tree. If it is an optimizable statement, turn it * transform a Parse tree into a Query tree.
* into a Query tree.
*/ */
static Query * static Query *
transformStmt(ParseState *pstate, Node *parseTree) transformStmt(ParseState *pstate, Node *parseTree)
...@@ -353,7 +348,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) ...@@ -353,7 +348,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had * from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had
* bugs of just that nature...) * bugs of just that nature...)
*/ */
selectList = parse_analyze(makeList1(stmt->selectStmt), pstate); selectList = parse_analyze(stmt->selectStmt, pstate);
Assert(length(selectList) == 1); Assert(length(selectList) == 1);
selectQuery = (Query *) lfirst(selectList); selectQuery = (Query *) lfirst(selectList);
...@@ -1933,7 +1928,7 @@ transformSetOperationTree(ParseState *pstate, Node *node) ...@@ -1933,7 +1928,7 @@ transformSetOperationTree(ParseState *pstate, Node *node)
*/ */
save_rtable = pstate->p_rtable; save_rtable = pstate->p_rtable;
pstate->p_rtable = NIL; pstate->p_rtable = NIL;
selectList = parse_analyze(makeList1(stmt), pstate); selectList = parse_analyze((Node *) stmt, pstate);
pstate->p_rtable = save_rtable; pstate->p_rtable = save_rtable;
Assert(length(selectList) == 1); Assert(length(selectList) == 1);
...@@ -2752,6 +2747,7 @@ makeFromExpr(List *fromlist, Node *quals) ...@@ -2752,6 +2747,7 @@ makeFromExpr(List *fromlist, Node *quals)
static void static void
transformColumnType(ParseState *pstate, ColumnDef *column) transformColumnType(ParseState *pstate, ColumnDef *column)
{ {
TypeName *typename = column->typename;
/* /*
* If the column doesn't have an explicitly specified typmod, check to * If the column doesn't have an explicitly specified typmod, check to
...@@ -2760,18 +2756,33 @@ transformColumnType(ParseState *pstate, ColumnDef *column) ...@@ -2760,18 +2756,33 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
* Note that we deliberately do NOT look at array or set information * Note that we deliberately do NOT look at array or set information
* here; "numeric[]" needs the same default typmod as "numeric". * here; "numeric[]" needs the same default typmod as "numeric".
*/ */
if (column->typename->typmod == -1) if (typename->typmod == -1)
{ {
switch (typeTypeId(typenameType(column->typename->name))) switch (typeTypeId(typenameType(typename->name)))
{ {
case BPCHAROID: case BPCHAROID:
/* "char" -> "char(1)" */ /* "char" -> "char(1)" */
column->typename->typmod = VARHDRSZ + 1; typename->typmod = VARHDRSZ + 1;
break; break;
case NUMERICOID: case NUMERICOID:
column->typename->typmod = VARHDRSZ + typename->typmod = VARHDRSZ +
((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE); ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE);
break; break;
} }
} }
/*
* Is this the name of a complex type? If so, implement
* it as a set.
*
* XXX this is a hangover from ancient Berkeley code that probably
* doesn't work anymore anyway.
*/
if (typeTypeRelid(typenameType(typename->name)) != InvalidOid)
{
/* (Eventually add in here that the set can only
* contain one element.)
*/
typename->setof = true;
}
} }
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.194 2000/10/05 19:11:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.195 2000/10/07 00:58:17 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
extern List *parsetree; /* final parse result is delivered here */ extern List *parsetree; /* final parse result is delivered here */
static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
static bool QueryIsRule = FALSE; static bool QueryIsRule = FALSE;
static Oid *param_type_info; static Oid *param_type_info;
static int pfunc_num_args; static int pfunc_num_args;
...@@ -161,7 +160,7 @@ static void doNegateFloat(Value *v); ...@@ -161,7 +160,7 @@ static void doNegateFloat(Value *v);
%type <str> relation_name, copy_file_name, copy_delimiter, copy_null, def_name, %type <str> relation_name, copy_file_name, copy_delimiter, copy_null, def_name,
database_name, access_method_clause, access_method, attr_name, database_name, access_method_clause, access_method, attr_name,
class, index_name, name, func_name, file_name, aggr_argtype class, index_name, name, func_name, file_name
%type <str> opt_id, %type <str> opt_id,
all_Op, MathOp, opt_name, all_Op, MathOp, opt_name,
...@@ -183,7 +182,7 @@ static void doNegateFloat(Value *v); ...@@ -183,7 +182,7 @@ static void doNegateFloat(Value *v);
def_list, opt_indirection, group_clause, TriggerFuncArgs, def_list, opt_indirection, group_clause, TriggerFuncArgs,
opt_select_limit opt_select_limit
%type <typnam> func_arg, func_return %type <typnam> func_arg, func_return, aggr_argtype
%type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp %type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp
...@@ -1541,7 +1540,7 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptUnder OptCreateAs AS Select ...@@ -1541,7 +1540,7 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptUnder OptCreateAs AS Select
n->istemp = $2; n->istemp = $2;
n->into = $4; n->into = $4;
if ($5 != NIL) if ($5 != NIL)
yyerror("CREATE TABLE/AS SELECT does not support UNDER"); elog(ERROR,"CREATE TABLE/AS SELECT does not support UNDER");
if ($6 != NIL) if ($6 != NIL)
mapTargetColumns($6, n->targetList); mapTargetColumns($6, n->targetList);
$$ = $8; $$ = $8;
...@@ -2009,8 +2008,8 @@ CommentStmt: COMMENT ON comment_type name IS comment_text ...@@ -2009,8 +2008,8 @@ CommentStmt: COMMENT ON comment_type name IS comment_text
CommentStmt *n = makeNode(CommentStmt); CommentStmt *n = makeNode(CommentStmt);
n->objtype = $3; n->objtype = $3;
n->objname = $4; n->objname = $4;
n->objproperty = $5; n->objproperty = NULL;
n->objlist = NULL; n->objlist = makeList1($5);
n->comment = $7; n->comment = $7;
$$ = (Node *) n; $$ = (Node *) n;
} }
...@@ -2309,7 +2308,7 @@ grantee: PUBLIC ...@@ -2309,7 +2308,7 @@ grantee: PUBLIC
opt_with_grant: WITH GRANT OPTION opt_with_grant: WITH GRANT OPTION
{ {
yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges"); elog(ERROR,"WITH GRANT OPTION is not supported. Only relation owners can set privileges");
} }
| /*EMPTY*/ | /*EMPTY*/
; ;
...@@ -2471,7 +2470,7 @@ ProcedureStmt: CREATE FUNCTION func_name func_args ...@@ -2471,7 +2470,7 @@ ProcedureStmt: CREATE FUNCTION func_name func_args
{ {
ProcedureStmt *n = makeNode(ProcedureStmt); ProcedureStmt *n = makeNode(ProcedureStmt);
n->funcname = $3; n->funcname = $3;
n->defArgs = $4; n->argTypes = $4;
n->returnType = (Node *)$6; n->returnType = (Node *)$6;
n->withClause = $11; n->withClause = $11;
n->as = $8; n->as = $8;
...@@ -2488,29 +2487,12 @@ func_args: '(' func_args_list ')' { $$ = $2; } ...@@ -2488,29 +2487,12 @@ func_args: '(' func_args_list ')' { $$ = $2; }
; ;
func_args_list: func_arg func_args_list: func_arg
{ $$ = makeList1(makeString($1->name)); } { $$ = makeList1($1); }
| func_args_list ',' func_arg | func_args_list ',' func_arg
{ $$ = lappend($1, makeString($3->name)); } { $$ = lappend($1, $3); }
; ;
/* Would be nice to use the full Typename production for these fields, func_arg: opt_arg Typename
* but that one sometimes dives into the catalogs looking for valid types.
* Arguments like "opaque" are valid when defining functions,
* so that won't work here. The only thing we give up is array notation,
* which isn't meaningful in this context anyway.
* - thomas 2000-03-25
* The following productions are difficult, since it is difficult to
* distinguish between TokenId and SimpleTypename:
opt_arg TokenId SimpleTypename
{
$$ = $3;
}
| TokenId SimpleTypename
{
$$ = $2;
}
*/
func_arg: opt_arg SimpleTypename
{ {
/* We can catch over-specified arguments here if we want to, /* We can catch over-specified arguments here if we want to,
* but for now better to silently swallow typmod, etc. * but for now better to silently swallow typmod, etc.
...@@ -2518,7 +2500,7 @@ func_arg: opt_arg SimpleTypename ...@@ -2518,7 +2500,7 @@ func_arg: opt_arg SimpleTypename
*/ */
$$ = $2; $$ = $2;
} }
| SimpleTypename | Typename
{ {
$$ = $1; $$ = $1;
} }
...@@ -2546,7 +2528,7 @@ func_as: Sconst ...@@ -2546,7 +2528,7 @@ func_as: Sconst
{ $$ = makeList2(makeString($1), makeString($3)); } { $$ = makeList2(makeString($1), makeString($3)); }
; ;
func_return: SimpleTypename func_return: Typename
{ {
/* We can catch over-specified arguments here if we want to, /* We can catch over-specified arguments here if we want to,
* but for now better to silently swallow typmod, etc. * but for now better to silently swallow typmod, etc.
...@@ -2554,11 +2536,6 @@ func_return: SimpleTypename ...@@ -2554,11 +2536,6 @@ func_return: SimpleTypename
*/ */
$$ = $1; $$ = $1;
} }
| SETOF SimpleTypename
{
$$ = $2;
$$->setof = TRUE;
}
; ;
...@@ -2599,12 +2576,12 @@ RemoveAggrStmt: DROP AGGREGATE name aggr_argtype ...@@ -2599,12 +2576,12 @@ RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
{ {
RemoveAggrStmt *n = makeNode(RemoveAggrStmt); RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
n->aggname = $3; n->aggname = $3;
n->aggtype = $4; n->aggtype = (Node *) $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
aggr_argtype: name { $$ = $1; } aggr_argtype: Typename { $$ = $1; }
| '*' { $$ = NULL; } | '*' { $$ = NULL; }
; ;
...@@ -2628,16 +2605,16 @@ RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')' ...@@ -2628,16 +2605,16 @@ RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
} }
; ;
oper_argtypes: name oper_argtypes: Typename
{ {
elog(ERROR,"parser: argument type missing (use NONE for unary operators)"); elog(ERROR,"parser: argument type missing (use NONE for unary operators)");
} }
| name ',' name | Typename ',' Typename
{ $$ = makeList2(makeString($1), makeString($3)); } { $$ = makeList2($1, $3); }
| NONE ',' name /* left unary */ | NONE ',' Typename /* left unary */
{ $$ = makeList2(NULL, makeString($3)); } { $$ = makeList2(NULL, $3); }
| name ',' NONE /* right unary */ | Typename ',' NONE /* right unary */
{ $$ = makeList2(makeString($1), NULL); } { $$ = makeList2($1, NULL); }
; ;
...@@ -3832,23 +3809,6 @@ Typename: SimpleTypename opt_array_bounds ...@@ -3832,23 +3809,6 @@ Typename: SimpleTypename opt_array_bounds
{ {
$$ = $1; $$ = $1;
$$->arrayBounds = $2; $$->arrayBounds = $2;
/* Is this the name of a complex type? If so, implement
* it as a set.
*/
if (strcmp(saved_relname, $$->name) == 0)
/* This attr is the same type as the relation
* being defined. The classic example: create
* emp(name=text,mgr=emp)
*/
$$->setof = TRUE;
else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
/* (Eventually add in here that the set can only
* contain one element.)
*/
$$->setof = TRUE;
else
$$->setof = FALSE;
} }
| SETOF SimpleTypename | SETOF SimpleTypename
{ {
...@@ -3909,7 +3869,7 @@ Numeric: FLOAT opt_float ...@@ -3909,7 +3869,7 @@ Numeric: FLOAT opt_float
| DECIMAL opt_decimal | DECIMAL opt_decimal
{ {
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
$$->name = xlateSqlType("numeric"); $$->name = xlateSqlType("decimal");
$$->typmod = $2; $$->typmod = $2;
} }
| DEC opt_decimal | DEC opt_decimal
...@@ -5245,7 +5205,6 @@ update_target_el: ColId opt_indirection '=' a_expr ...@@ -5245,7 +5205,6 @@ update_target_el: ColId opt_indirection '=' a_expr
relation_name: SpecialRuleRelation relation_name: SpecialRuleRelation
{ {
$$ = $1; $$ = $1;
StrNCpy(saved_relname, $1, NAMEDATALEN);
} }
| ColId | ColId
{ {
...@@ -5255,7 +5214,6 @@ relation_name: SpecialRuleRelation ...@@ -5255,7 +5214,6 @@ relation_name: SpecialRuleRelation
elog(ERROR,"%s cannot be accessed by users",$1); elog(ERROR,"%s cannot be accessed by users",$1);
else else
$$ = $1; $$ = $1;
StrNCpy(saved_relname, $1, NAMEDATALEN);
} }
; ;
...@@ -5298,7 +5256,7 @@ AexprConst: Iconst ...@@ -5298,7 +5256,7 @@ AexprConst: Iconst
n->val.val.str = $1; n->val.val.str = $1;
$$ = (Node *)n; $$ = (Node *)n;
} }
/* The SimpleTypename rule formerly used Typename, /* This rule formerly used Typename,
* but that causes reduce conflicts with subscripted column names. * but that causes reduce conflicts with subscripted column names.
* Now, separate into ConstTypename and ConstInterval, * Now, separate into ConstTypename and ConstInterval,
* to allow implementing the SQL92 syntax for INTERVAL literals. * to allow implementing the SQL92 syntax for INTERVAL literals.
...@@ -5383,6 +5341,7 @@ ColId: generic { $$ = $1; } ...@@ -5383,6 +5341,7 @@ ColId: generic { $$ = $1; }
| TokenId { $$ = $1; } | TokenId { $$ = $1; }
| INTERVAL { $$ = "interval"; } | INTERVAL { $$ = "interval"; }
| NATIONAL { $$ = "national"; } | NATIONAL { $$ = "national"; }
| NONE { $$ = "none"; }
| PATH_P { $$ = "path"; } | PATH_P { $$ = "path"; }
| SERIAL { $$ = "serial"; } | SERIAL { $$ = "serial"; }
| TIME { $$ = "time"; } | TIME { $$ = "time"; }
...@@ -5595,7 +5554,6 @@ ColLabel: ColId { $$ = $1; } ...@@ -5595,7 +5554,6 @@ ColLabel: ColId { $$ = $1; }
| NATURAL { $$ = "natural"; } | NATURAL { $$ = "natural"; }
| NCHAR { $$ = "nchar"; } | NCHAR { $$ = "nchar"; }
| NEW { $$ = "new"; } | NEW { $$ = "new"; }
| NONE { $$ = "none"; }
| NOT { $$ = "not"; } | NOT { $$ = "not"; }
| NOTNULL { $$ = "notnull"; } | NOTNULL { $$ = "notnull"; }
| NULLIF { $$ = "nullif"; } | NULLIF { $$ = "nullif"; }
...@@ -5851,7 +5809,6 @@ xlateSqlType(char *name) ...@@ -5851,7 +5809,6 @@ xlateSqlType(char *name)
void parser_init(Oid *typev, int nargs) void parser_init(Oid *typev, int nargs)
{ {
saved_relname[0] = '\0';
QueryIsRule = FALSE; QueryIsRule = FALSE;
/* /*
* Keep enough information around to fill out the type of param nodes * Keep enough information around to fill out the type of param nodes
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.69 2000/10/05 19:11:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.70 2000/10/07 00:58:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -375,7 +375,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) ...@@ -375,7 +375,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
save_joinlist = pstate->p_joinlist; save_joinlist = pstate->p_joinlist;
pstate->p_rtable = NIL; pstate->p_rtable = NIL;
pstate->p_joinlist = NIL; pstate->p_joinlist = NIL;
parsetrees = parse_analyze(makeList1(r->subquery), pstate); parsetrees = parse_analyze(r->subquery, pstate);
pstate->p_rtable = save_rtable; pstate->p_rtable = save_rtable;
pstate->p_joinlist = save_joinlist; pstate->p_joinlist = save_joinlist;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.85 2000/10/05 19:11:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.86 2000/10/07 00:58:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -294,8 +294,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) ...@@ -294,8 +294,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
break; break;
} }
pstate->p_hasSubLinks = true; pstate->p_hasSubLinks = true;
qtrees = parse_analyze(makeList1(sublink->subselect), qtrees = parse_analyze(sublink->subselect, pstate);
pstate);
if (length(qtrees) != 1) if (length(qtrees) != 1)
elog(ERROR, "Bad query in subselect"); elog(ERROR, "Bad query in subselect");
qtree = (Query *) lfirst(qtrees); qtree = (Query *) lfirst(qtrees);
...@@ -821,19 +820,21 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) ...@@ -821,19 +820,21 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod)
static Node * static Node *
parser_typecast_constant(Value *expr, TypeName *typename) parser_typecast_constant(Value *expr, TypeName *typename)
{ {
Const *con;
Type tp; Type tp;
Datum datum; Datum datum;
Const *con;
char *const_string = NULL; char *const_string = NULL;
bool string_palloced = false; bool string_palloced = false;
bool isNull = false; bool isNull = false;
tp = typenameType(TypeNameToInternalName(typename));
switch (nodeTag(expr)) switch (nodeTag(expr))
{ {
case T_Integer: case T_Integer:
string_palloced = true;
const_string = DatumGetCString(DirectFunctionCall1(int4out, const_string = DatumGetCString(DirectFunctionCall1(int4out,
Int32GetDatum(expr->val.ival))); Int32GetDatum(expr->val.ival)));
string_palloced = true;
break; break;
case T_Float: case T_Float:
case T_String: case T_String:
...@@ -844,18 +845,8 @@ parser_typecast_constant(Value *expr, TypeName *typename) ...@@ -844,18 +845,8 @@ parser_typecast_constant(Value *expr, TypeName *typename)
break; break;
default: default:
elog(ERROR, "Cannot cast this expression to type '%s'", elog(ERROR, "Cannot cast this expression to type '%s'",
typename->name); typeTypeName(tp));
}
if (typename->arrayBounds != NIL)
{
char type_string[NAMEDATALEN + 2];
sprintf(type_string, "_%s", typename->name);
tp = (Type) typenameType(type_string);
} }
else
tp = (Type) typenameType(typename->name);
if (isNull) if (isNull)
datum = (Datum) NULL; datum = (Datum) NULL;
...@@ -892,15 +883,7 @@ parser_typecast_expression(ParseState *pstate, ...@@ -892,15 +883,7 @@ parser_typecast_expression(ParseState *pstate,
Type tp; Type tp;
Oid targetType; Oid targetType;
if (typename->arrayBounds != NIL) tp = typenameType(TypeNameToInternalName(typename));
{
char type_string[NAMEDATALEN + 2];
sprintf(type_string, "_%s", typename->name);
tp = (Type) typenameType(type_string);
}
else
tp = (Type) typenameType(typename->name);
targetType = typeTypeId(tp); targetType = typeTypeId(tp);
if (inputType == InvalidOid) if (inputType == InvalidOid)
...@@ -925,3 +908,26 @@ parser_typecast_expression(ParseState *pstate, ...@@ -925,3 +908,26 @@ parser_typecast_expression(ParseState *pstate,
return expr; 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)
{
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;
}
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* parser.c * parser.c
* Main entry point/driver for PostgreSQL parser * Main entry point/driver for PostgreSQL grammar
*
* Note that the grammar is not allowed to perform any table access
* (since we need to be able to do basic parsing even while inside an
* aborted transaction). Therefore, the data structures returned by
* the grammar are "raw" parsetrees that still need to be analyzed by
* parse_analyze.
* *
* *
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.46 2000/09/12 21:07:02 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.47 2000/10/07 00:58:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,8 +22,6 @@ ...@@ -16,8 +22,6 @@
#include "postgres.h" #include "postgres.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
#include "parser/analyze.h"
#include "parser/gramparse.h" #include "parser/gramparse.h"
#include "parser/parse.h" #include "parser/parse.h"
#include "parser/parser.h" #include "parser/parser.h"
...@@ -35,19 +39,17 @@ List *parsetree; /* result of parsing is left here */ ...@@ -35,19 +39,17 @@ List *parsetree; /* result of parsing is left here */
static int lookahead_token; /* one-token lookahead */ static int lookahead_token; /* one-token lookahead */
static bool have_lookahead; /* lookahead_token set? */ static bool have_lookahead; /* lookahead_token set? */
#ifdef SETS_FIXED
static void fixupsets();
static void define_sets();
#endif
/* /*
* parser-- returns a list of parse trees * parser
* Given a query in string form, and optionally info about
* parameter types, do lexical and syntactic analysis.
*
* Returns a list of raw (un-analyzed) parse trees.
*/ */
List * List *
parser(char *str, Oid *typev, int nargs) parser(char *str, Oid *typev, int nargs)
{ {
List *queryList;
int yyresult; int yyresult;
parseString = str; parseString = str;
...@@ -67,28 +69,9 @@ parser(char *str, Oid *typev, int nargs) ...@@ -67,28 +69,9 @@ parser(char *str, Oid *typev, int nargs)
clearerr(stdin); clearerr(stdin);
if (yyresult) /* error */ if (yyresult) /* error */
return (List *) NULL; return NIL;
queryList = parse_analyze(parsetree, NULL);
#ifdef SETS_FIXED
/*
* Fixing up sets calls the parser, so it reassigns the global
* variable parsetree. So save the real parsetree.
*/
savetree = parsetree;
foreach(parse, savetree)
{ /* savetree is really a list of parses */
/* find set definitions embedded in query */
fixupsets((Query *) lfirst(parse));
} return parsetree;
return savetree;
#endif
return queryList;
} }
...@@ -135,83 +118,3 @@ yylex(void) ...@@ -135,83 +118,3 @@ yylex(void)
return cur_token; return cur_token;
} }
#ifdef SETS_FIXED
static void
fixupsets(Query *parse)
{
if (parse == NULL)
return;
if (parse->commandType == CMD_UTILITY) /* utility */
return;
if (parse->commandType != CMD_INSERT)
return;
define_sets(parse);
}
/* Recursively find all of the Consts in the parsetree. Some of
* these may represent a set. The value of the Const will be the
* query (a string) which defines the set. Call SetDefine to define
* the set, and store the OID of the new set in the Const instead.
*/
static void
define_sets(Node *clause)
{
Oid setoid;
Type t = typeidType(OIDOID);
Oid typeoid = typeTypeId(t);
Size oidsize = typeLen(t);
bool oidbyval = typeByVal(t);
if (clause == NULL)
return;
else if (IsA(clause, LispList))
{
define_sets(lfirst(clause));
define_sets(lnext(clause));
}
else if (IsA(clause, Const))
{
if (get_constisnull((Const) clause) ||
!get_constisset((Const) clause))
return;
setoid = SetDefine(((Const *) clause)->constvalue,
typeidTypeName(((Const *) clause)->consttype));
set_constvalue((Const) clause, setoid);
set_consttype((Const) clause, typeoid);
set_constlen((Const) clause, oidsize);
set_constypeByVal((Const) clause, oidbyval);
}
else if (IsA(clause, Iter))
define_sets(((Iter *) clause)->iterexpr);
else if (single_node(clause))
return;
else if (or_clause(clause) || and_clause(clause))
{
List *temp;
/* mapcan */
foreach(temp, ((Expr *) clause)->args)
define_sets(lfirst(temp));
}
else if (is_funcclause(clause))
{
List *temp;
/* mapcan */
foreach(temp, ((Expr *) clause)->args)
define_sets(lfirst(temp));
}
else if (IsA(clause, ArrayRef))
define_sets(((ArrayRef *) clause)->refassgnexpr);
else if (not_clause(clause))
define_sets(get_notclausearg(clause));
else if (is_opclause(clause))
{
define_sets(get_leftop(clause));
define_sets(get_rightop(clause));
}
}
#endif
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.49 2000/10/02 04:49:27 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.50 2000/10/07 00:58:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,10 +16,12 @@ ...@@ -16,10 +16,12 @@
#include "postgres.h" #include "postgres.h"
#include "access/heapam.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "catalog/pg_shadow.h" #include "catalog/pg_shadow.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "miscadmin.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/memutils.h" #include "utils/memutils.h"
...@@ -561,7 +563,52 @@ aclcontains(PG_FUNCTION_ARGS) ...@@ -561,7 +563,52 @@ aclcontains(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
} }
/* parser support routines */ /*
* ExecuteChangeACLStmt
* Called to execute the utility command type ChangeACLStmt
*/
void
ExecuteChangeACLStmt(ChangeACLStmt *stmt)
{
AclItem aclitem;
unsigned modechg;
List *i;
/* see comment in pg_type.h */
Assert(ACLITEMSIZE == sizeof(AclItem));
/* Convert string ACL spec into internal form */
aclparse(stmt->aclString, &aclitem, &modechg);
foreach(i, stmt->relNames)
{
char *relname = strVal(lfirst(i));
Relation rel;
rel = heap_openr(relname, AccessExclusiveLock);
if (rel && rel->rd_rel->relkind == RELKIND_INDEX)
elog(ERROR, "\"%s\" is an index relation",
relname);
#ifndef NO_SECURITY
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "you do not own class \"%s\"",
relname);
#endif
ChangeAcl(relname, &aclitem, modechg);
/* close rel, but keep lock until end of xact */
heap_close(rel, NoLock);
}
}
/*
* Parser support routines for ACL-related statements.
*
* XXX CAUTION: these are called from gram.y, which is not allowed to
* do any table accesses. Therefore, it is not kosher to do things
* like trying to translate usernames to user IDs here. Keep it all
* in string form until statement execution time.
*/
/* /*
* aclmakepriv * aclmakepriv
...@@ -569,9 +616,7 @@ aclcontains(PG_FUNCTION_ARGS) ...@@ -569,9 +616,7 @@ aclcontains(PG_FUNCTION_ARGS)
* and a new privilege * and a new privilege
* *
* does not add duplicate privileges * does not add duplicate privileges
*
*/ */
char * char *
aclmakepriv(char *old_privlist, char new_priv) aclmakepriv(char *old_privlist, char new_priv)
{ {
...@@ -619,12 +664,9 @@ aclmakepriv(char *old_privlist, char new_priv) ...@@ -619,12 +664,9 @@ aclmakepriv(char *old_privlist, char new_priv)
* "G" - group * "G" - group
* "U" - user * "U" - user
* *
* concatenates the two strings together with a space in between * Just concatenates the two strings together with a space in between.
* * Per above comments, we can't try to resolve a user or group name here.
* this routine is used in the parser
*
*/ */
char * char *
aclmakeuser(char *user_type, char *user) aclmakeuser(char *user_type, char *user)
{ {
...@@ -635,20 +677,16 @@ aclmakeuser(char *user_type, char *user) ...@@ -635,20 +677,16 @@ aclmakeuser(char *user_type, char *user)
return user_list; return user_list;
} }
/* /*
* makeAclStmt: * makeAclStmt:
* this is a helper routine called by the parser * create a ChangeACLStmt at parse time.
* create a ChangeAclStmt * we take in the privileges, relation_name_list, and grantee
* we take in the privilegs, relation_name_list, and grantee
* as well as a single character '+' or '-' to indicate grant or revoke * as well as a single character '+' or '-' to indicate grant or revoke
* *
* returns a new ChangeACLStmt* * We convert the information to the same external form recognized by
* * aclitemin (see aclparse), and save that string in the ChangeACLStmt.
* this routines works by creating a old-style changle acl string and * Conversion to internal form happens when the statement is executed.
* then calling aclparse;
*/ */
ChangeACLStmt * ChangeACLStmt *
makeAclStmt(char *privileges, List *rel_list, char *grantee, makeAclStmt(char *privileges, List *rel_list, char *grantee,
char grant_or_revoke) char grant_or_revoke)
...@@ -658,11 +696,6 @@ makeAclStmt(char *privileges, List *rel_list, char *grantee, ...@@ -658,11 +696,6 @@ makeAclStmt(char *privileges, List *rel_list, char *grantee,
initStringInfo(&str); initStringInfo(&str);
/* see comment in pg_type.h */
Assert(ACLITEMSIZE == sizeof(AclItem));
n->aclitem = (AclItem *) palloc(sizeof(AclItem));
/* the grantee string is "G <group_name>", "U <user_name>", or "ALL" */ /* the grantee string is "G <group_name>", "U <user_name>", or "ALL" */
if (grantee[0] == 'G') /* group permissions */ if (grantee[0] == 'G') /* group permissions */
{ {
...@@ -683,7 +716,8 @@ makeAclStmt(char *privileges, List *rel_list, char *grantee, ...@@ -683,7 +716,8 @@ makeAclStmt(char *privileges, List *rel_list, char *grantee,
grant_or_revoke, privileges); grant_or_revoke, privileges);
} }
n->relNames = rel_list; n->relNames = rel_list;
aclparse(str.data, n->aclitem, (unsigned *) &n->modechg); n->aclString = pstrdup(str.data);
pfree(str.data); pfree(str.data);
return n; return n;
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: defrem.h,v 1.20 2000/08/24 03:29:09 tgl Exp $ * $Id: defrem.h,v 1.21 2000/10/07 00:58:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,7 +48,7 @@ extern void DefineType(char *name, List *parameters); ...@@ -48,7 +48,7 @@ extern void DefineType(char *name, List *parameters);
/* /*
* prototypes in remove.c * prototypes in remove.c
*/ */
extern void RemoveFunction(char *functionName, int nargs, List *argNameList); extern void RemoveFunction(char *functionName, List *argTypes);
extern void RemoveOperator(char *operatorName, extern void RemoveOperator(char *operatorName,
char *typeName1, char *typeName2); char *typeName1, char *typeName2);
extern void RemoveType(char *typeName); extern void RemoveType(char *typeName);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.115 2000/10/05 19:11:36 tgl Exp $ * $Id: parsenodes.h,v 1.116 2000/10/07 00:58:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -114,9 +114,8 @@ typedef struct AlterTableStmt ...@@ -114,9 +114,8 @@ typedef struct AlterTableStmt
typedef struct ChangeACLStmt typedef struct ChangeACLStmt
{ {
NodeTag type; NodeTag type;
struct AclItem *aclitem;
unsigned modechg;
List *relNames; List *relNames;
char *aclString;
} ChangeACLStmt; } ChangeACLStmt;
/* ---------------------- /* ----------------------
...@@ -488,10 +487,8 @@ typedef struct ProcedureStmt ...@@ -488,10 +487,8 @@ typedef struct ProcedureStmt
{ {
NodeTag type; NodeTag type;
char *funcname; /* name of function to create */ char *funcname; /* name of function to create */
List *defArgs; /* list of definitions a list of strings List *argTypes; /* list of argument types (TypeName nodes) */
* (as Value *) */ Node *returnType; /* the return type (a TypeName node) */
Node *returnType; /* the return type (as a string or a
* TypeName (ie.setof) */
List *withClause; /* a list of DefElem */ List *withClause; /* a list of DefElem */
List *as; /* definition of function body */ List *as; /* definition of function body */
char *language; /* C, SQL, etc */ char *language; /* C, SQL, etc */
...@@ -505,7 +502,7 @@ typedef struct RemoveAggrStmt ...@@ -505,7 +502,7 @@ typedef struct RemoveAggrStmt
{ {
NodeTag type; NodeTag type;
char *aggname; /* aggregate to drop */ char *aggname; /* aggregate to drop */
char *aggtype; /* for this type */ Node *aggtype; /* TypeName for input datatype, or NULL */
} RemoveAggrStmt; } RemoveAggrStmt;
/* ---------------------- /* ----------------------
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: analyze.h,v 1.11 2000/10/05 19:11:38 tgl Exp $ * $Id: analyze.h,v 1.12 2000/10/07 00:58:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
#include "parser/parse_node.h" #include "parser/parse_node.h"
extern List *parse_analyze(List *pl, ParseState *parentParseState); extern List *parse_analyze(Node *parseTree, ParseState *parentParseState);
#endif /* ANALYZE_H */ #endif /* ANALYZE_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_expr.h,v 1.19 2000/06/15 03:32:55 momjian Exp $ * $Id: parse_expr.h,v 1.20 2000/10/07 00:58:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -26,5 +26,6 @@ extern Oid exprType(Node *expr); ...@@ -26,5 +26,6 @@ extern Oid exprType(Node *expr);
extern int32 exprTypmod(Node *expr); extern int32 exprTypmod(Node *expr);
extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod); extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod);
extern void parse_expr_init(void); extern void parse_expr_init(void);
extern char *TypeNameToInternalName(TypeName *typename);
#endif /* PARSE_EXPR_H */ #endif /* PARSE_EXPR_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: tcopprot.h,v 1.34 2000/09/06 14:15:28 petere Exp $ * $Id: tcopprot.h,v 1.35 2000/10/07 00:58:23 tgl Exp $
* *
* OLD COMMENTS * OLD COMMENTS
* This file was created so that other c files could get the two * This file was created so that other c files could get the two
...@@ -35,7 +35,7 @@ extern bool ShowPortNumber; ...@@ -35,7 +35,7 @@ extern bool ShowPortNumber;
extern List *pg_parse_and_rewrite(char *query_string, extern List *pg_parse_and_rewrite(char *query_string,
Oid *typev, int nargs); Oid *typev, int nargs);
extern Plan *pg_plan_query(Query *querytree); extern Plan *pg_plan_query(Query *querytree);
extern void pg_exec_query_dest(char *query_string, extern void pg_exec_query_string(char *query_string,
CommandDest dest, CommandDest dest,
MemoryContext parse_context); MemoryContext parse_context);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: acl.h,v 1.28 2000/10/02 04:49:27 tgl Exp $ * $Id: acl.h,v 1.29 2000/10/07 00:58:23 tgl Exp $
* *
* NOTES * NOTES
* For backward-compatibility purposes we have to allow there * For backward-compatibility purposes we have to allow there
...@@ -167,12 +167,15 @@ extern char *aclcheck_error_strings[]; ...@@ -167,12 +167,15 @@ extern char *aclcheck_error_strings[];
/*#define ACLDEBUG_TRACE*/ /*#define ACLDEBUG_TRACE*/
/* /*
* routines used internally (parser, etc.) * routines used internally
*/ */
extern Acl *acldefault(char *relname, AclId ownerid); extern Acl *acldefault(char *relname, AclId ownerid);
extern Acl *aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg); extern Acl *aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg);
/*
* routines used by the parser
*/
extern char *aclmakepriv(char *old_privlist, char new_priv); extern char *aclmakepriv(char *old_privlist, char new_priv);
extern char *aclmakeuser(char *user_type, char *user); extern char *aclmakeuser(char *user_type, char *user);
extern ChangeACLStmt *makeAclStmt(char *privs, List *rel_list, char *grantee, extern ChangeACLStmt *makeAclStmt(char *privs, List *rel_list, char *grantee,
...@@ -187,6 +190,7 @@ extern Datum aclitemout(PG_FUNCTION_ARGS); ...@@ -187,6 +190,7 @@ extern Datum aclitemout(PG_FUNCTION_ARGS);
extern Datum aclinsert(PG_FUNCTION_ARGS); extern Datum aclinsert(PG_FUNCTION_ARGS);
extern Datum aclremove(PG_FUNCTION_ARGS); extern Datum aclremove(PG_FUNCTION_ARGS);
extern Datum aclcontains(PG_FUNCTION_ARGS); extern Datum aclcontains(PG_FUNCTION_ARGS);
extern void ExecuteChangeACLStmt(ChangeACLStmt *stmt);
/* /*
* prototypes for functions in aclchk.c * prototypes for functions in aclchk.c
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment