diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/pg_proc.c | 28 | ||||
-rw-r--r-- | src/backend/commands/comment.c | 68 | ||||
-rw-r--r-- | src/backend/commands/define.c | 226 | ||||
-rw-r--r-- | src/backend/commands/remove.c | 38 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 14 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 24 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 91 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 95 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 4 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 56 | ||||
-rw-r--r-- | src/backend/parser/parser.c | 127 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 491 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 132 | ||||
-rw-r--r-- | src/backend/utils/adt/acl.c | 84 | ||||
-rw-r--r-- | src/include/commands/defrem.h | 4 | ||||
-rw-r--r-- | src/include/nodes/parsenodes.h | 13 | ||||
-rw-r--r-- | src/include/parser/analyze.h | 4 | ||||
-rw-r--r-- | src/include/parser/parse_expr.h | 3 | ||||
-rw-r--r-- | src/include/tcop/tcopprot.h | 8 | ||||
-rw-r--r-- | src/include/utils/acl.h | 8 |
20 files changed, 768 insertions, 750 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 98d0cdca0c4..26861047b24 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * 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, MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid)); foreach(x, argList) { - Value *t = lfirst(x); + TypeName *t = (TypeName *) lfirst(x); + char *typnam = TypeNameToInternalName(t); if (parameterCount >= FUNC_MAX_ARGS) elog(ERROR, "Procedures cannot take more than %d arguments", FUNC_MAX_ARGS); - if (strcmp(strVal(t), "opaque") == 0) + if (strcmp(typnam, "opaque") == 0) { if (languageObjectId == SQLlanguageId) elog(ERROR, "ProcedureCreate: sql functions cannot take type \"opaque\""); - toid = 0; + toid = InvalidOid; } else { - toid = TypeGet(strVal(t), &defined); + toid = TypeGet(typnam, &defined); if (!OidIsValid(toid)) - { elog(ERROR, "ProcedureCreate: arg type '%s' is not defined", - strVal(t)); - } - + typnam); if (!defined) - { 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; } @@ -178,7 +177,7 @@ ProcedureCreate(char *procedureName, { if (languageObjectId == SQLlanguageId) elog(ERROR, "ProcedureCreate: sql functions cannot return type \"opaque\""); - typeObjectId = 0; + typeObjectId = InvalidOid; } else { @@ -194,10 +193,8 @@ ProcedureCreate(char *procedureName, returnTypeName); } else if (!defined) - { elog(NOTICE, "ProcedureCreate: return type '%s' is only a shell", returnTypeName); - } } /* @@ -212,7 +209,6 @@ ProcedureCreate(char *procedureName, elog(ERROR, "method %s already an attribute of type %s", procedureName, strVal(lfirst(argList))); - /* * 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 diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 51832bc2c7b..e7b13a80788 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -25,6 +25,8 @@ #include "commands/comment.h" #include "miscadmin.h" #include "parser/parse.h" +#include "parser/parse_expr.h" +#include "parser/parse_func.h" #include "rewrite/rewriteRemove.h" #include "utils/acl.h" #include "utils/fmgroids.h" @@ -46,7 +48,7 @@ static void CommentAttribute(char *relation, char *attrib, char *comment); static void CommentDatabase(char *database, char *comment); static void CommentRewrite(char *rule, 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 CommentOperator(char *opname, List *arguments, char *comment); static void CommentTrigger(char *trigger, char *relation, char *comments); @@ -92,7 +94,7 @@ CommentObject(int objtype, char *objname, char *objproperty, CommentType(objname, comment); break; case (AGGREGATE): - CommentAggregate(objname, objproperty, comment); + CommentAggregate(objname, objlist, comment); break; case (FUNCTION): CommentProc(objname, objlist, comment); @@ -544,9 +546,10 @@ CommentType(char *type, char *comment) */ 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; Oid baseoid, oid; @@ -554,11 +557,12 @@ CommentAggregate(char *aggregate, char *argument, char *comment) /*** 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)) - elog(ERROR, "aggregate type '%s' does not exist", argument); + elog(ERROR, "type '%s' does not exist", aggtypename); } else baseoid = 0; @@ -568,10 +572,10 @@ CommentAggregate(char *aggregate, char *argument, char *comment) #ifndef NO_SECURITY if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid)) { - if (argument) + if (aggtypename) { elog(ERROR, "you are not permitted to comment on aggregate '%s' %s '%s'", - aggregate, "with type", argument); + aggregate, "with type", aggtypename); } else { @@ -587,10 +591,10 @@ CommentAggregate(char *aggregate, char *argument, char *comment) ObjectIdGetDatum(baseoid), 0, 0); if (!HeapTupleIsValid(aggtuple)) { - if (argument) + if (aggtypename) { elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'", - argument, aggregate); + aggtypename, aggregate); } else elog(ERROR, "aggregate '%s' does not exist", aggregate); @@ -622,7 +626,6 @@ CommentProc(char *function, List *arguments, char *comment) functuple; Oid oid, argoids[FUNC_MAX_ARGS]; - char *argument; int i, argcount; @@ -635,18 +638,20 @@ CommentProc(char *function, List *arguments, char *comment) FUNC_MAX_ARGS); for (i = 0; i < argcount; i++) { - argument = strVal(lfirst(arguments)); + TypeName *t = (TypeName *) lfirst(arguments); + char *typnam = TypeNameToInternalName(t); + arguments = lnext(arguments); - if (strcmp(argument, "opaque") == 0) - argoids[i] = 0; + + if (strcmp(typnam, "opaque") == 0) + argoids[i] = InvalidOid; else { argtuple = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(argument), + PointerGetDatum(typnam), 0, 0, 0); if (!HeapTupleIsValid(argtuple)) - elog(ERROR, "function argument type '%s' does not exist", - argument); + elog(ERROR, "CommentProc: type '%s' not found", typnam); argoids[i] = argtuple->t_data->t_oid; } } @@ -664,10 +669,9 @@ CommentProc(char *function, List *arguments, char *comment) functuple = SearchSysCacheTuple(PROCNAME, PointerGetDatum(function), Int32GetDatum(argcount), PointerGetDatum(argoids), 0); - if (!HeapTupleIsValid(functuple)) - elog(ERROR, "function '%s' with the supplied %s does not exist", - function, "argument list"); + func_error("CommentProc", function, argcount, argoids, NULL); + oid = functuple->t_data->t_oid; /*** Call CreateComments() to create/drop the comments ***/ @@ -691,23 +695,24 @@ CommentProc(char *function, List *arguments, char *comment) static void 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; HeapTuple optuple; Oid oid, leftoid = InvalidOid, rightoid = InvalidOid; bool defined; - char oprtype = 0, - *lefttype = NULL, - *righttype = NULL; /*** Initialize our left and right argument types ***/ - if (lfirst(arguments) != NULL) - lefttype = strVal(lfirst(arguments)); - if (lsecond(arguments) != NULL) - righttype = strVal(lsecond(arguments)); + if (typenode1 != NULL) + lefttype = TypeNameToInternalName(typenode1); + if (typenode2 != NULL) + righttype = TypeNameToInternalName(typenode2); /*** Attempt to fetch the left oid, if specified ***/ @@ -732,9 +737,9 @@ CommentOperator(char *opername, List *arguments, char *comment) if (OidIsValid(leftoid) && (OidIsValid(rightoid))) oprtype = 'b'; else if (OidIsValid(leftoid)) - oprtype = 'l'; - else if (OidIsValid(rightoid)) oprtype = 'r'; + else if (OidIsValid(rightoid)) + oprtype = 'l'; else elog(ERROR, "operator '%s' is of an illegal type'", opername); @@ -769,7 +774,6 @@ CommentOperator(char *opername, List *arguments, char *comment) /*** Call CreateComments() to create/drop the comments ***/ CreateComments(oid, comment); - } /*------------------------------------------------------------------ diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index cf31e5edb1f..a33d155db9f 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.46 2000/07/22 03:34:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.47 2000/10/07 00:58:16 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -49,6 +49,7 @@ #include "commands/defrem.h" #include "fmgr.h" #include "optimizer/cost.h" +#include "parser/parse_expr.h" #include "tcop/dest.h" #include "utils/builtins.h" #include "utils/syscache.h" @@ -83,27 +84,15 @@ case_translate_language_name(const char *input, char *output) static void -compute_return_type(const Node *returnType, +compute_return_type(TypeName *returnType, char **prorettype_p, bool *returnsSet_p) { /*--------------------------------------------------------------------------- Examine the "returns" clause returnType of the CREATE FUNCTION statement - and return information about it as **prorettype_p and **returnsSet. + and return information about it as *prorettype_p and *returnsSet. ----------------------------------------------------------------------------*/ - if (nodeTag(returnType) == T_TypeName) - { - /* a set of values */ - TypeName *setType = (TypeName *) returnType; - - *prorettype_p = setType->name; - *returnsSet_p = setType->setof; - } - else - { - /* singleton */ - *prorettype_p = strVal(returnType); - *returnsSet_p = false; - } + *prorettype_p = TypeNameToInternalName(returnType); + *returnsSet_p = returnType->setof; } @@ -214,7 +203,7 @@ interpret_AS_clause(const char *languageName, const List *as, *prosrc_str_p = strVal(lfirst(as)); *probin_str_p = "-"; - if (lnext(as) != NULL) + if (lnext(as) != NIL) elog(ERROR, "CREATE FUNCTION: only one AS item needed for %s language", languageName); } @@ -231,27 +220,23 @@ void CreateFunction(ProcedureStmt *stmt, CommandDest dest) { char *probin_str; - /* pathname of executable file that executes this function, if any */ - char *prosrc_str; + char *prosrc_str; /* SQL that executes this function, if any */ - char *prorettype; + char *prorettype; /* Type of return value (or member of set of values) from function */ - char languageName[NAMEDATALEN]; + char languageName[NAMEDATALEN]; /* * name of language of function, with case adjusted: "C", "newC", * "internal", "newinternal", "sql", etc. */ bool returnsSet; - /* The function returns a set of values, as opposed to a singleton. */ - bool lanisPL = false; - /* * The following are optional user-supplied attributes of the * function. @@ -263,8 +248,12 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) bool canCache, isStrict; + /* Convert language name to canonical case */ case_translate_language_name(stmt->language, languageName); + /* + * Apply appropriate security checks depending on language. + */ if (strcmp(languageName, "C") == 0 || strcmp(languageName, "newC") == 0 || strcmp(languageName, "internal") == 0 || @@ -301,7 +290,7 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) /* Check that this language is a PL */ languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); - if (!(languageStruct->lanispl)) + if (!languageStruct->lanispl) elog(ERROR, "Language '%s' isn't defined as PL", languageName); @@ -316,11 +305,15 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) "language.", languageName); } - - lanisPL = true; } - compute_return_type(stmt->returnType, &prorettype, &returnsSet); + /* + * Convert remaining parameters of CREATE to form wanted by + * ProcedureCreate. + */ + Assert(IsA(stmt->returnType, TypeName)); + compute_return_type((TypeName *) stmt->returnType, + &prorettype, &returnsSet); compute_full_attributes(stmt->withClause, &byte_pct, &perbyte_cpu, &percall_cpu, @@ -345,7 +338,7 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) perbyte_cpu, percall_cpu, outin_ratio, - stmt->defArgs, + stmt->argTypes, dest); } @@ -389,49 +382,43 @@ DefineOperator(char *oprName, { DefElem *defel = (DefElem *) lfirst(pl); - if (!strcasecmp(defel->defname, "leftarg")) + if (strcasecmp(defel->defname, "leftarg") == 0) { - if ((nodeTag(defel->arg) == T_TypeName) - && (((TypeName *) defel->arg)->setof)) - elog(ERROR, "setof type not implemented for leftarg"); - typeName1 = defGetString(defel); - if (typeName1 == NULL) - elog(ERROR, "type for leftarg is malformed."); + if (IsA(defel->arg, TypeName) + && ((TypeName *) defel->arg)->setof) + elog(ERROR, "setof type not implemented for leftarg"); } - else if (!strcasecmp(defel->defname, "rightarg")) + else if (strcasecmp(defel->defname, "rightarg") == 0) { - if ((nodeTag(defel->arg) == T_TypeName) - && (((TypeName *) defel->arg)->setof)) - elog(ERROR, "setof type not implemented for rightarg"); - typeName2 = defGetString(defel); - if (typeName2 == NULL) - elog(ERROR, "type for rightarg is malformed."); + if (IsA(defel->arg, TypeName) + && ((TypeName *) defel->arg)->setof) + elog(ERROR, "setof type not implemented for rightarg"); } - else if (!strcasecmp(defel->defname, "procedure")) + else if (strcasecmp(defel->defname, "procedure") == 0) functionName = defGetString(defel); - else if (!strcasecmp(defel->defname, "precedence")) + else if (strcasecmp(defel->defname, "precedence") == 0) { /* NOT IMPLEMENTED (never worked in v4.2) */ elog(NOTICE, "CREATE OPERATOR: precedence not implemented"); } - else if (!strcasecmp(defel->defname, "associativity")) + else if (strcasecmp(defel->defname, "associativity") == 0) { /* NOT IMPLEMENTED (never worked in v4.2) */ elog(NOTICE, "CREATE OPERATOR: associativity not implemented"); } - else if (!strcasecmp(defel->defname, "commutator")) + else if (strcasecmp(defel->defname, "commutator") == 0) commutatorName = defGetString(defel); - else if (!strcasecmp(defel->defname, "negator")) + else if (strcasecmp(defel->defname, "negator") == 0) negatorName = defGetString(defel); - else if (!strcasecmp(defel->defname, "restrict")) + else if (strcasecmp(defel->defname, "restrict") == 0) restrictionName = defGetString(defel); - else if (!strcasecmp(defel->defname, "join")) + else if (strcasecmp(defel->defname, "join") == 0) joinName = defGetString(defel); - else if (!strcasecmp(defel->defname, "hashes")) + else if (strcasecmp(defel->defname, "hashes") == 0) canHash = TRUE; - else if (!strcasecmp(defel->defname, "sort1")) + else if (strcasecmp(defel->defname, "sort1") == 0) { /* ---------------- * XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... ) @@ -441,7 +428,7 @@ DefineOperator(char *oprName, */ sortName1 = defGetString(defel); } - else if (!strcasecmp(defel->defname, "sort2")) + else if (strcasecmp(defel->defname, "sort2") == 0) sortName2 = defGetString(defel); else { @@ -562,72 +549,73 @@ DefineType(char *typeName, List *parameters) char delimiter = DEFAULT_TYPDELIM; char *shadow_type; List *pl; - char alignment = 'i';/* default alignment */ - char storage = 'p'; /* default storage in TOAST */ + char alignment = 'i'; /* default alignment */ + char storage = 'p'; /* default storage in TOAST */ /* - * Type names can only be 15 characters long, so that the shadow type - * can be created using the 16th character as necessary. + * Type names must be one character shorter than other names, + * allowing room to create the corresponding array type name with + * prepended "_". */ - if (strlen(typeName) >= (NAMEDATALEN - 1)) + if (strlen(typeName) > (NAMEDATALEN - 2)) { elog(ERROR, "DefineType: type names must be %d characters or less", - NAMEDATALEN - 1); + NAMEDATALEN - 2); } foreach(pl, parameters) { DefElem *defel = (DefElem *) lfirst(pl); - if (!strcasecmp(defel->defname, "internallength")) + if (strcasecmp(defel->defname, "internallength") == 0) internalLength = defGetTypeLength(defel); - else if (!strcasecmp(defel->defname, "externallength")) + else if (strcasecmp(defel->defname, "externallength") == 0) externalLength = defGetTypeLength(defel); - else if (!strcasecmp(defel->defname, "input")) + else if (strcasecmp(defel->defname, "input") == 0) inputName = defGetString(defel); - else if (!strcasecmp(defel->defname, "output")) + else if (strcasecmp(defel->defname, "output") == 0) outputName = defGetString(defel); - else if (!strcasecmp(defel->defname, "send")) + else if (strcasecmp(defel->defname, "send") == 0) sendName = defGetString(defel); - else if (!strcasecmp(defel->defname, "delimiter")) + else if (strcasecmp(defel->defname, "delimiter") == 0) { char *p = defGetString(defel); delimiter = p[0]; } - else if (!strcasecmp(defel->defname, "receive")) + else if (strcasecmp(defel->defname, "receive") == 0) receiveName = defGetString(defel); - else if (!strcasecmp(defel->defname, "element")) + else if (strcasecmp(defel->defname, "element") == 0) elemName = defGetString(defel); - else if (!strcasecmp(defel->defname, "default")) + else if (strcasecmp(defel->defname, "default") == 0) defaultValue = defGetString(defel); - else if (!strcasecmp(defel->defname, "passedbyvalue")) + else if (strcasecmp(defel->defname, "passedbyvalue") == 0) byValue = true; - else if (!strcasecmp(defel->defname, "alignment")) + else if (strcasecmp(defel->defname, "alignment") == 0) { char *a = defGetString(defel); - if (!strcasecmp(a, "double")) + if (strcasecmp(a, "double") == 0) alignment = 'd'; - else if (!strcasecmp(a, "int4")) + else if (strcasecmp(a, "int4") == 0) alignment = 'i'; else { - elog(ERROR, "DefineType: \"%s\" alignment not recognized", + elog(ERROR, "DefineType: \"%s\" alignment not recognized", a); } } - else if (!strcasecmp(defel->defname, "storage")) + else if (strcasecmp(defel->defname, "storage") == 0) { char *a = defGetString(defel); - if (!strcasecmp(a, "plain")) + if (strcasecmp(a, "plain") == 0) storage = 'p'; - else if (!strcasecmp(a, "external")) + else if (strcasecmp(a, "external") == 0) storage = 'e'; - else if (!strcasecmp(a, "extended")) + else if (strcasecmp(a, "extended") == 0) storage = 'x'; - else if (!strcasecmp(a, "main")) + else if (strcasecmp(a, "main") == 0) storage = 'm'; else { @@ -674,8 +662,8 @@ DefineType(char *typeName, List *parameters) storage); /* TOAST strategy */ /* ---------------- - * When we create a true type (as opposed to a complex type) - * we need to have an shadow array entry for it in pg_type as well. + * When we create a base type (as opposed to a complex type) + * we need to have an array entry for it in pg_type as well. * ---------------- */ shadow_type = makeArrayTypeName(typeName); @@ -702,19 +690,32 @@ DefineType(char *typeName, List *parameters) static char * defGetString(DefElem *def) { - char *string; - - if (nodeTag(def->arg) == T_String) - string = strVal(def->arg); - else if (nodeTag(def->arg) == T_TypeName) - string = ((TypeName *) def->arg)->name; - else - string = NULL; -#if 0 - elog(ERROR, "Define: \"%s\" = what?", def->defname); -#endif + if (def->arg == NULL) + elog(ERROR, "Define: \"%s\" requires a parameter", + def->defname); + switch (nodeTag(def->arg)) + { + case T_Integer: + { + char *str = palloc(32); - return string; + snprintf(str, 32, "%ld", (long) intVal(def->arg)); + return str; + } + case T_Float: + /* T_Float values are kept in string form, so this type cheat + * works (and doesn't risk losing precision) + */ + return strVal(def->arg); + case T_String: + return strVal(def->arg); + case T_TypeName: + return TypeNameToInternalName((TypeName *) def->arg); + default: + elog(ERROR, "Define: cannot interpret argument of \"%s\"", + def->defname); + } + return NULL; /* keep compiler quiet */ } static double @@ -739,15 +740,32 @@ defGetNumeric(DefElem *def) static int defGetTypeLength(DefElem *def) { - if (nodeTag(def->arg) == T_Integer) - return intVal(def->arg); - else if (nodeTag(def->arg) == T_String && - !strcasecmp(strVal(def->arg), "variable")) - return -1; /* variable length */ - else if (nodeTag(def->arg) == T_TypeName && - !strcasecmp(((TypeName *)(def->arg))->name, "variable")) - return -1; - - elog(ERROR, "Define: \"%s\" = what?", def->defname); - return -1; + if (def->arg == NULL) + elog(ERROR, "Define: \"%s\" requires a parameter", + def->defname); + switch (nodeTag(def->arg)) + { + case T_Integer: + return intVal(def->arg); + case T_Float: + elog(ERROR, "Define: \"%s\" requires an integral value", + def->defname); + break; + case T_String: + if (strcasecmp(strVal(def->arg), "variable") == 0) + return -1; /* variable length */ + break; + case T_TypeName: + /* cope if grammar chooses to believe "variable" is a typename */ + if (strcasecmp(TypeNameToInternalName((TypeName *) def->arg), + "variable") == 0) + return -1; /* variable length */ + break; + default: + elog(ERROR, "Define: cannot interpret argument of \"%s\"", + def->defname); + } + elog(ERROR, "Define: invalid argument for \"%s\"", + def->defname); + return 0; /* keep compiler quiet */ } diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index c5b7968e5fd..6da32297f61 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -8,7 +8,7 @@ * * * 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 @@ #include "commands/comment.h" #include "commands/defrem.h" #include "miscadmin.h" +#include "parser/parse_expr.h" #include "parser/parse_func.h" #include "utils/acl.h" #include "utils/syscache.h" @@ -39,8 +40,8 @@ */ void RemoveOperator(char *operatorName, /* operator name */ - char *typeName1, /* first type name */ - char *typeName2) /* optional second type name */ + char *typeName1, /* left argument type name */ + char *typeName2) /* right argument type name */ { Relation relation; HeapTuple tup; @@ -53,28 +54,22 @@ RemoveOperator(char *operatorName, /* operator name */ { typeId1 = TypeGet(typeName1, &defined); if (!OidIsValid(typeId1)) - { elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName1); - return; - } } if (typeName2) { typeId2 = TypeGet(typeName2, &defined); if (!OidIsValid(typeId2)) - { elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName2); - return; - } } if (OidIsValid(typeId1) && OidIsValid(typeId2)) oprtype = 'b'; else if (OidIsValid(typeId1)) - oprtype = 'l'; - else oprtype = 'r'; + else + oprtype = 'l'; relation = heap_openr(OperatorRelationName, RowExclusiveLock); @@ -94,7 +89,6 @@ RemoveOperator(char *operatorName, /* operator name */ operatorName); #endif - /*** Delete any comments associated with this operator ***/ DeleteComments(tup->t_data->t_oid); @@ -308,13 +302,12 @@ RemoveType(char *typeName) /* type name to be removed */ */ void RemoveFunction(char *functionName, /* function name to be removed */ - int nargs, - List *argNameList /* list of TypeNames */ ) + List *argTypes) /* list of TypeName nodes */ { + int nargs = length(argTypes); Relation relation; HeapTuple tup; Oid argList[FUNC_MAX_ARGS]; - char *typename; int i; if (nargs > FUNC_MAX_ARGS) @@ -323,19 +316,20 @@ RemoveFunction(char *functionName, /* function name to be removed */ MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); for (i = 0; i < nargs; i++) { - typename = strVal(lfirst(argNameList)); - argNameList = lnext(argNameList); + TypeName *t = (TypeName *) lfirst(argTypes); + char *typnam = TypeNameToInternalName(t); - if (strcmp(typename, "opaque") == 0) - argList[i] = 0; + argTypes = lnext(argTypes); + + if (strcmp(typnam, "opaque") == 0) + argList[i] = InvalidOid; else { tup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(typename), + PointerGetDatum(typnam), 0, 0, 0); - 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; } } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 1a0f4623978..e768d0bd796 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * 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) { 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); + if (from->aclString) + newnode->aclString = pstrdup(from->aclString); return newnode; } @@ -2033,7 +2029,7 @@ _copyProcedureStmt(ProcedureStmt *from) ProcedureStmt *newnode = makeNode(ProcedureStmt); newnode->funcname = pstrdup(from->funcname); - Node_Copy(from, newnode, defArgs); + Node_Copy(from, newnode, argTypes); Node_Copy(from, newnode, returnType); Node_Copy(from, newnode, withClause); Node_Copy(from, newnode, as); @@ -2048,7 +2044,7 @@ _copyRemoveAggrStmt(RemoveAggrStmt *from) RemoveAggrStmt *newnode = makeNode(RemoveAggrStmt); newnode->aggname = pstrdup(from->aggname); - newnode->aggtype = pstrdup(from->aggtype); + Node_Copy(from, newnode, aggtype); return newnode; } diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index ab8779cb375..d5b2ff4607e 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * 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) static bool _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)) return false; + if (!equalstr(a->aclString, b->aclString)) + return false; return true; } @@ -956,7 +942,7 @@ _equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b) { if (!equalstr(a->funcname, b->funcname)) return false; - if (!equal(a->defArgs, b->defArgs)) + if (!equal(a->argTypes, b->argTypes)) return false; if (!equal(a->returnType, b->returnType)) return false; @@ -975,7 +961,7 @@ _equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b) { if (!equalstr(a->aggname, b->aggname)) return false; - if (!equalstr(a->aggtype, b->aggtype)) + if (!equal(a->aggtype, b->aggtype)) return false; return true; diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index ffedca05ed9..ae1f027e47c 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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,49 +69,45 @@ static List *extras_after; /* * parse_analyze - - * analyze a list of parse trees and transform them if necessary. - * - * Returns a list of transformed parse trees. Optimizable statements are - * all transformed to Query while the rest stays the same. + * analyze a raw parse tree and transform it to Query form. * + * 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 * -parse_analyze(List *pl, ParseState *parentParseState) +parse_analyze(Node *parseTree, ParseState *parentParseState) { List *result = NIL; + ParseState *pstate = make_parsestate(parentParseState); + Query *query; - while (pl != NIL) - { - ParseState *pstate = make_parsestate(parentParseState); - Query *parsetree; + extras_before = extras_after = NIL; - extras_before = extras_after = NIL; + query = transformStmt(pstate, parseTree); + release_pstate_resources(pstate); - parsetree = transformStmt(pstate, lfirst(pl)); + while (extras_before != NIL) + { + result = lappend(result, + transformStmt(pstate, lfirst(extras_before))); release_pstate_resources(pstate); + extras_before = lnext(extras_before); + } - while (extras_before != NIL) - { - result = lappend(result, - transformStmt(pstate, lfirst(extras_before))); - release_pstate_resources(pstate); - extras_before = lnext(extras_before); - } - - result = lappend(result, parsetree); + result = lappend(result, query); - while (extras_after != NIL) - { - result = lappend(result, - transformStmt(pstate, lfirst(extras_after))); - release_pstate_resources(pstate); - extras_after = lnext(extras_after); - } - - pfree(pstate); - pl = lnext(pl); + while (extras_after != NIL) + { + result = lappend(result, + transformStmt(pstate, lfirst(extras_after))); + release_pstate_resources(pstate); + extras_after = lnext(extras_after); } + pfree(pstate); + return result; } @@ -126,8 +122,7 @@ release_pstate_resources(ParseState *pstate) /* * transformStmt - - * transform a Parse tree. If it is an optimizable statement, turn it - * into a Query tree. + * transform a Parse tree into a Query tree. */ static Query * transformStmt(ParseState *pstate, Node *parseTree) @@ -353,7 +348,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) * from a stand-alone SELECT. (Indeed, Postgres up through 6.5 had * bugs of just that nature...) */ - selectList = parse_analyze(makeList1(stmt->selectStmt), pstate); + selectList = parse_analyze(stmt->selectStmt, pstate); Assert(length(selectList) == 1); selectQuery = (Query *) lfirst(selectList); @@ -1933,7 +1928,7 @@ transformSetOperationTree(ParseState *pstate, Node *node) */ save_rtable = pstate->p_rtable; pstate->p_rtable = NIL; - selectList = parse_analyze(makeList1(stmt), pstate); + selectList = parse_analyze((Node *) stmt, pstate); pstate->p_rtable = save_rtable; Assert(length(selectList) == 1); @@ -2752,6 +2747,7 @@ makeFromExpr(List *fromlist, Node *quals) static void transformColumnType(ParseState *pstate, ColumnDef *column) { + TypeName *typename = column->typename; /* * If the column doesn't have an explicitly specified typmod, check to @@ -2760,18 +2756,33 @@ transformColumnType(ParseState *pstate, ColumnDef *column) * Note that we deliberately do NOT look at array or set information * 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)" */ - column->typename->typmod = VARHDRSZ + 1; + typename->typmod = VARHDRSZ + 1; break; case NUMERICOID: - column->typename->typmod = VARHDRSZ + + typename->typmod = VARHDRSZ + ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE); 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; + } } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index f13b942abd8..a596bd6aba1 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * 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 * AUTHOR DATE MAJOR EVENT @@ -59,7 +59,6 @@ extern List *parsetree; /* final parse result is delivered here */ -static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */ static bool QueryIsRule = FALSE; static Oid *param_type_info; static int pfunc_num_args; @@ -161,7 +160,7 @@ static void doNegateFloat(Value *v); %type <str> relation_name, copy_file_name, copy_delimiter, copy_null, def_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, all_Op, MathOp, opt_name, @@ -183,7 +182,7 @@ static void doNegateFloat(Value *v); def_list, opt_indirection, group_clause, TriggerFuncArgs, opt_select_limit -%type <typnam> func_arg, func_return +%type <typnam> func_arg, func_return, aggr_argtype %type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp @@ -1541,7 +1540,7 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptUnder OptCreateAs AS Select n->istemp = $2; n->into = $4; 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) mapTargetColumns($6, n->targetList); $$ = $8; @@ -2009,8 +2008,8 @@ CommentStmt: COMMENT ON comment_type name IS comment_text CommentStmt *n = makeNode(CommentStmt); n->objtype = $3; n->objname = $4; - n->objproperty = $5; - n->objlist = NULL; + n->objproperty = NULL; + n->objlist = makeList1($5); n->comment = $7; $$ = (Node *) n; } @@ -2309,7 +2308,7 @@ grantee: PUBLIC 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*/ ; @@ -2471,7 +2470,7 @@ ProcedureStmt: CREATE FUNCTION func_name func_args { ProcedureStmt *n = makeNode(ProcedureStmt); n->funcname = $3; - n->defArgs = $4; + n->argTypes = $4; n->returnType = (Node *)$6; n->withClause = $11; n->as = $8; @@ -2488,29 +2487,12 @@ func_args: '(' func_args_list ')' { $$ = $2; } ; func_args_list: func_arg - { $$ = makeList1(makeString($1->name)); } + { $$ = makeList1($1); } | 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, - * 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 +func_arg: opt_arg Typename { /* We can catch over-specified arguments here if we want to, * but for now better to silently swallow typmod, etc. @@ -2518,7 +2500,7 @@ func_arg: opt_arg SimpleTypename */ $$ = $2; } - | SimpleTypename + | Typename { $$ = $1; } @@ -2546,7 +2528,7 @@ func_as: Sconst { $$ = makeList2(makeString($1), makeString($3)); } ; -func_return: SimpleTypename +func_return: Typename { /* We can catch over-specified arguments here if we want to, * but for now better to silently swallow typmod, etc. @@ -2554,11 +2536,6 @@ func_return: SimpleTypename */ $$ = $1; } - | SETOF SimpleTypename - { - $$ = $2; - $$->setof = TRUE; - } ; @@ -2599,12 +2576,12 @@ RemoveAggrStmt: DROP AGGREGATE name aggr_argtype { RemoveAggrStmt *n = makeNode(RemoveAggrStmt); n->aggname = $3; - n->aggtype = $4; + n->aggtype = (Node *) $4; $$ = (Node *)n; } ; -aggr_argtype: name { $$ = $1; } +aggr_argtype: Typename { $$ = $1; } | '*' { $$ = NULL; } ; @@ -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)"); } - | name ',' name - { $$ = makeList2(makeString($1), makeString($3)); } - | NONE ',' name /* left unary */ - { $$ = makeList2(NULL, makeString($3)); } - | name ',' NONE /* right unary */ - { $$ = makeList2(makeString($1), NULL); } + | Typename ',' Typename + { $$ = makeList2($1, $3); } + | NONE ',' Typename /* left unary */ + { $$ = makeList2(NULL, $3); } + | Typename ',' NONE /* right unary */ + { $$ = makeList2($1, NULL); } ; @@ -3832,23 +3809,6 @@ Typename: SimpleTypename opt_array_bounds { $$ = $1; $$->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 { @@ -3909,7 +3869,7 @@ Numeric: FLOAT opt_float | DECIMAL opt_decimal { $$ = makeNode(TypeName); - $$->name = xlateSqlType("numeric"); + $$->name = xlateSqlType("decimal"); $$->typmod = $2; } | DEC opt_decimal @@ -5245,17 +5205,15 @@ update_target_el: ColId opt_indirection '=' a_expr relation_name: SpecialRuleRelation { $$ = $1; - StrNCpy(saved_relname, $1, NAMEDATALEN); } | ColId { /* disallow refs to variable system tables */ if (strcmp(LogRelationName, $1) == 0 - || strcmp(VariableRelationName, $1) == 0) + || strcmp(VariableRelationName, $1) == 0) elog(ERROR,"%s cannot be accessed by users",$1); else $$ = $1; - StrNCpy(saved_relname, $1, NAMEDATALEN); } ; @@ -5298,7 +5256,7 @@ AexprConst: Iconst n->val.val.str = $1; $$ = (Node *)n; } - /* The SimpleTypename rule formerly used Typename, + /* This rule formerly used Typename, * but that causes reduce conflicts with subscripted column names. * Now, separate into ConstTypename and ConstInterval, * to allow implementing the SQL92 syntax for INTERVAL literals. @@ -5383,6 +5341,7 @@ ColId: generic { $$ = $1; } | TokenId { $$ = $1; } | INTERVAL { $$ = "interval"; } | NATIONAL { $$ = "national"; } + | NONE { $$ = "none"; } | PATH_P { $$ = "path"; } | SERIAL { $$ = "serial"; } | TIME { $$ = "time"; } @@ -5595,7 +5554,6 @@ ColLabel: ColId { $$ = $1; } | NATURAL { $$ = "natural"; } | NCHAR { $$ = "nchar"; } | NEW { $$ = "new"; } - | NONE { $$ = "none"; } | NOT { $$ = "not"; } | NOTNULL { $$ = "notnull"; } | NULLIF { $$ = "nullif"; } @@ -5851,7 +5809,6 @@ xlateSqlType(char *name) void parser_init(Oid *typev, int nargs) { - saved_relname[0] = '\0'; QueryIsRule = FALSE; /* * Keep enough information around to fill out the type of param nodes diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 20233ed1950..38dc3ea0976 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * 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) save_joinlist = pstate->p_joinlist; pstate->p_rtable = 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_joinlist = save_joinlist; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 7b647124d1f..94ccaa5f69f 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * 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) break; } pstate->p_hasSubLinks = true; - qtrees = parse_analyze(makeList1(sublink->subselect), - pstate); + qtrees = parse_analyze(sublink->subselect, pstate); if (length(qtrees) != 1) elog(ERROR, "Bad query in subselect"); qtree = (Query *) lfirst(qtrees); @@ -821,19 +820,21 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) static Node * parser_typecast_constant(Value *expr, TypeName *typename) { - Const *con; Type tp; Datum datum; + Const *con; char *const_string = NULL; bool string_palloced = false; bool isNull = false; + tp = typenameType(TypeNameToInternalName(typename)); + switch (nodeTag(expr)) { case T_Integer: - string_palloced = true; const_string = DatumGetCString(DirectFunctionCall1(int4out, Int32GetDatum(expr->val.ival))); + string_palloced = true; break; case T_Float: case T_String: @@ -844,19 +845,9 @@ parser_typecast_constant(Value *expr, TypeName *typename) break; default: 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) datum = (Datum) NULL; else @@ -892,15 +883,7 @@ parser_typecast_expression(ParseState *pstate, Type tp; Oid targetType; - 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); + tp = typenameType(TypeNameToInternalName(typename)); targetType = typeTypeId(tp); if (inputType == InvalidOid) @@ -925,3 +908,26 @@ 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) +{ + 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; +} diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c index 4a6c825498a..84b27549d36 100644 --- a/src/backend/parser/parser.c +++ b/src/backend/parser/parser.c @@ -1,14 +1,20 @@ /*------------------------------------------------------------------------- * * 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) 1994, Regents of the University of California * * 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 @@ #include "postgres.h" #include "nodes/parsenodes.h" -#include "nodes/pg_list.h" -#include "parser/analyze.h" #include "parser/gramparse.h" #include "parser/parse.h" #include "parser/parser.h" @@ -35,19 +39,17 @@ List *parsetree; /* result of parsing is left here */ static int lookahead_token; /* one-token lookahead */ 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 * parser(char *str, Oid *typev, int nargs) { - List *queryList; int yyresult; parseString = str; @@ -67,28 +69,9 @@ parser(char *str, Oid *typev, int nargs) clearerr(stdin); if (yyresult) /* error */ - return (List *) NULL; - - queryList = parse_analyze(parsetree, NULL); + return NIL; -#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 savetree; -#endif - - return queryList; + return parsetree; } @@ -135,83 +118,3 @@ yylex(void) 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 diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index bddad9e4f6e..3eaa3a1562d 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.177 2000/10/03 03:11:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.178 2000/10/07 00:58:18 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -47,6 +47,8 @@ #include "nodes/print.h" #include "optimizer/cost.h" #include "optimizer/planner.h" +#include "parser/analyze.h" +#include "parser/parse.h" #include "parser/parser.h" #include "rewrite/rewriteHandler.h" #include "tcop/fastpath.h" @@ -90,8 +92,6 @@ extern char ControlFilePath[]; static bool dontExecute = false; -static bool IsEmptyQuery = false; - /* note: these declarations had better match tcopprot.h */ DLLIMPORT sigjmp_buf Warn_restart; @@ -129,6 +129,10 @@ int XfuncMode = 0; static int InteractiveBackend(StringInfo inBuf); static int SocketBackend(StringInfo inBuf); static int ReadCommand(StringInfo inBuf); +static List *pg_parse_query(char *query_string, Oid *typev, int nargs); +static List *pg_analyze_and_rewrite(Node *parsetree); +static void start_xact_command(void); +static void finish_xact_command(void); static void SigHupHandler(SIGNAL_ARGS); static void FloatExceptionHandler(SIGNAL_ARGS); static void quickdie(SIGNAL_ARGS); @@ -341,46 +345,120 @@ ReadCommand(StringInfo inBuf) * * A list of Query nodes is returned, since the string might contain * multiple queries and/or the rewriter might expand one query to several. + * + * NOTE: this routine is no longer used for processing interactive queries, + * but it is still needed for parsing of SQL function bodies. */ List * pg_parse_and_rewrite(char *query_string, /* string to execute */ Oid *typev, /* parameter types */ int nargs) /* number of parameters */ { + List *raw_parsetree_list; List *querytree_list; - List *querytree_list_item; - Query *querytree; - List *new_list; + List *list_item; + + /* ---------------- + * (1) parse the request string into a list of raw parse trees. + * ---------------- + */ + raw_parsetree_list = pg_parse_query(query_string, typev, nargs); + + /* ---------------- + * (2) Do parse analysis and rule rewrite. + * ---------------- + */ + querytree_list = NIL; + foreach(list_item, raw_parsetree_list) + { + Node *parsetree = (Node *) lfirst(list_item); + + querytree_list = nconc(querytree_list, + pg_analyze_and_rewrite(parsetree)); + } + + return querytree_list; +} + +/* + * Do raw parsing (only). + * + * A list of parsetrees is returned, since there might be multiple + * commands in the given string. + * + * NOTE: for interactive queries, it is important to keep this routine + * separate from the analysis & rewrite stages. Analysis and rewriting + * cannot be done in an aborted transaction, since they require access to + * database tables. So, we rely on the raw parser to determine whether + * we've seen a COMMIT or ABORT command; when we are in abort state, other + * commands are not processed any further than the raw parse stage. + */ +static List * +pg_parse_query(char *query_string, Oid *typev, int nargs) +{ + List *raw_parsetree_list; if (Debug_print_query) elog(DEBUG, "query: %s", query_string); + if (Show_parser_stats) + ResetUsage(); + + raw_parsetree_list = parser(query_string, typev, nargs); + + if (Show_parser_stats) + { + fprintf(StatFp, "PARSER STATISTICS\n"); + ShowUsage(); + } + + return raw_parsetree_list; +} + +/* + * Given a raw parsetree (gram.y output), perform parse analysis and + * rule rewriting. + * + * A list of Query nodes is returned, since either the analyzer or the + * rewriter might expand one query to several. + * + * NOTE: for reasons mentioned above, this must be separate from raw parsing. + */ +static List * +pg_analyze_and_rewrite(Node *parsetree) +{ + List *querytree_list; + List *list_item; + Query *querytree; + List *new_list; + /* ---------------- - * (1) parse the request string into a list of parse trees + * (1) Perform parse analysis. * ---------------- */ if (Show_parser_stats) ResetUsage(); - querytree_list = parser(query_string, typev, nargs); + querytree_list = parse_analyze(parsetree, NULL); if (Show_parser_stats) { - fprintf(StatFp, "PARSER STATISTICS\n"); + fprintf(StatFp, "PARSE ANALYSIS STATISTICS\n"); ShowUsage(); + ResetUsage(); } /* ---------------- - * (2) rewrite the queries, as necessary + * (2) Rewrite the queries, as necessary * * rewritten queries are collected in new_list. Note there may be * more or fewer than in the original list. * ---------------- */ new_list = NIL; - foreach(querytree_list_item, querytree_list) + foreach(list_item, querytree_list) { - querytree = (Query *) lfirst(querytree_list_item); + querytree = (Query *) lfirst(list_item); if (Debug_print_parse) { @@ -409,19 +487,18 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */ querytree_list = new_list; + if (Show_parser_stats) + { + fprintf(StatFp, "REWRITER STATISTICS\n"); + ShowUsage(); + } + #ifdef COPY_PARSE_PLAN_TREES - /* Optional debugging check: pass parsetree output through copyObject() */ - /* - * Note: we run this test after rewrite, not before, because copyObject() - * does not handle most kinds of nodes that are used only in raw parse - * trees. The present (bizarre) implementation of UNION/INTERSECT/EXCEPT - * doesn't run analysis of the second and later subqueries until rewrite, - * so we'd get false failures on these queries if we did it beforehand. - */ + /* Optional debugging check: pass querytree output through copyObject() */ new_list = (List *) copyObject(querytree_list); /* This checks both copyObject() and the equal() routines... */ if (! equal(new_list, querytree_list)) - elog(NOTICE, "pg_parse_and_rewrite: copyObject failed on parse tree"); + elog(NOTICE, "pg_analyze_and_rewrite: copyObject failed on parse tree"); else querytree_list = new_list; #endif @@ -431,9 +508,9 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */ if (Debug_pretty_print) { elog(DEBUG, "rewritten parse tree:"); - foreach(querytree_list_item, querytree_list) + foreach(list_item, querytree_list) { - querytree = (Query *) lfirst(querytree_list_item); + querytree = (Query *) lfirst(list_item); nodeDisplay(querytree); printf("\n"); } @@ -441,10 +518,9 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */ else { elog(DEBUG, "rewritten parse tree:"); - - foreach(querytree_list_item, querytree_list) + foreach(list_item, querytree_list) { - querytree = (Query *) lfirst(querytree_list_item); + querytree = (Query *) lfirst(list_item); elog(DEBUG, "%s", nodeToString(querytree)); } } @@ -514,7 +590,7 @@ pg_plan_query(Query *querytree) /* ---------------------------------------------------------------- - * pg_exec_query_dest() + * pg_exec_query_string() * * Takes a querystring, runs the parser/utilities or * parser/planner/executor over it as necessary. @@ -545,21 +621,31 @@ pg_plan_query(Query *querytree) */ void -pg_exec_query_dest(char *query_string, /* string to execute */ - CommandDest dest, /* where results should go */ - MemoryContext parse_context) /* context for parsetrees */ +pg_exec_query_string(char *query_string, /* string to execute */ + CommandDest dest, /* where results should go */ + MemoryContext parse_context) /* context for parsetrees */ { + bool xact_started; MemoryContext oldcontext; - List *querytree_list, - *querytree_item; + List *parsetree_list, + *parsetree_item; /* - * If you called this routine with parse_context = CurrentMemoryContext, - * you blew it. They *must* be different, else the context reset - * at the bottom of the loop will destroy the querytree list. - * (We really ought to check that parse_context isn't a child of - * CurrentMemoryContext either, but that would take more cycles than - * it's likely to be worth.) + * Start up a transaction command. All queries generated by the + * query_string will be in this same command block, *unless* we find + * a BEGIN/COMMIT/ABORT statement; we have to force a new xact command + * after one of those, else bad things will happen in xact.c. + * (Note that this will possibly change execution memory context.) + */ + start_xact_command(); + xact_started = true; + + /* + * parse_context *must* be different from the execution memory context, + * else the context reset at the bottom of the loop will destroy the + * parsetree list. (We really ought to check that parse_context isn't a + * child of CurrentMemoryContext either, but that would take more cycles + * than it's likely to be worth.) */ Assert(parse_context != CurrentMemoryContext); @@ -569,48 +655,57 @@ pg_exec_query_dest(char *query_string, /* string to execute */ oldcontext = MemoryContextSwitchTo(parse_context); /* - * Parse and rewrite the query or queries. + * Do basic parsing of the query or queries (this should be safe + * even if we are in aborted transaction state!) */ - querytree_list = pg_parse_and_rewrite(query_string, NULL, 0); + parsetree_list = pg_parse_query(query_string, NULL, 0); /* - * Switch back to execution context for planning and execution. + * Switch back to execution context to enter the loop. */ MemoryContextSwitchTo(oldcontext); /* - * Run through the query or queries and execute each one. + * Run through the parsetree(s) and process each one. */ - foreach(querytree_item, querytree_list) + foreach(parsetree_item, parsetree_list) { - Query *querytree = (Query *) lfirst(querytree_item); + Node *parsetree = (Node *) lfirst(parsetree_item); + bool isTransactionStmt; + List *querytree_list, + *querytree_item; - /* if we got a cancel signal in parsing or prior command, quit */ - if (QueryCancel) - CancelQuery(); + /* Transaction control statements need some special handling */ + isTransactionStmt = IsA(parsetree, TransactionStmt); - if (querytree->commandType == CMD_UTILITY) + /* + * If we are in an aborted transaction, ignore all commands except + * COMMIT/ABORT. It is important that this test occur before we + * try to do parse analysis, rewrite, or planning, since all those + * phases try to do database accesses, which may fail in abort state. + * (It might be safe to allow some additional utility commands in + * this state, but not many...) + */ + if (IsAbortedTransactionBlockState()) { - /* ---------------- - * process utility functions (create, destroy, etc..) - * - * Note: we do not check for the transaction aborted state - * because that is done in ProcessUtility. - * ---------------- - */ - if (Debug_print_query) - elog(DEBUG, "ProcessUtility: %s", query_string); - else if (DebugLvl > 1) - elog(DEBUG, "ProcessUtility"); + bool allowit = false; - ProcessUtility(querytree->utilityStmt, dest); - } - else - { - Plan *plan; + if (isTransactionStmt) + { + TransactionStmt *stmt = (TransactionStmt *) parsetree; + + switch (stmt->command) + { + case COMMIT: + case ROLLBACK: + allowit = true; + break; + default: + break; + } + } - /* If aborted transaction, skip planning and execution */ - if (IsAbortedTransactionBlockState()) + if (! allowit) { /* ---------------- * the EndCommand() stuff is to tell the frontend @@ -631,58 +726,180 @@ pg_exec_query_dest(char *query_string, /* string to execute */ */ continue; } + } - plan = pg_plan_query(querytree); + /* Make sure we are in a transaction command */ + if (! xact_started) + { + start_xact_command(); + xact_started = true; + } - /* if we got a cancel signal whilst planning, quit */ - if (QueryCancel) - CancelQuery(); + /* If we got a cancel signal in parsing or prior command, quit */ + if (QueryCancel) + CancelQuery(); + + /* + * OK to analyze and rewrite this query. + * + * Switch to appropriate context for constructing querytrees + * (again, these must outlive the execution context). + */ + oldcontext = MemoryContextSwitchTo(parse_context); - /* Initialize snapshot state for query */ - SetQuerySnapshot(); + querytree_list = pg_analyze_and_rewrite(parsetree); - /* - * execute the plan - */ - if (Show_executor_stats) - ResetUsage(); + /* + * Switch back to execution context for planning and execution. + */ + MemoryContextSwitchTo(oldcontext); + + /* + * Inner loop handles the individual queries generated from a + * single parsetree by analysis and rewrite. + */ + foreach(querytree_item, querytree_list) + { + Query *querytree = (Query *) lfirst(querytree_item); - if (dontExecute) + /* Make sure we are in a transaction command */ + if (! xact_started) { - /* don't execute it, just show the query plan */ - print_plan(plan, querytree); + start_xact_command(); + xact_started = true; + } + + /* If we got a cancel signal in analysis or prior command, quit */ + if (QueryCancel) + CancelQuery(); + + if (querytree->commandType == CMD_UTILITY) + { + /* ---------------- + * process utility functions (create, destroy, etc..) + * ---------------- + */ + if (Debug_print_query) + elog(DEBUG, "ProcessUtility: %s", query_string); + else if (DebugLvl > 1) + elog(DEBUG, "ProcessUtility"); + + ProcessUtility(querytree->utilityStmt, dest); } else { - if (DebugLvl > 1) - elog(DEBUG, "ProcessQuery"); - ProcessQuery(querytree, plan, dest); + /* ---------------- + * process a plannable query. + * ---------------- + */ + Plan *plan; + + plan = pg_plan_query(querytree); + + /* if we got a cancel signal whilst planning, quit */ + if (QueryCancel) + CancelQuery(); + + /* Initialize snapshot state for query */ + SetQuerySnapshot(); + + /* + * execute the plan + */ + if (Show_executor_stats) + ResetUsage(); + + if (dontExecute) + { + /* don't execute it, just show the query plan */ + print_plan(plan, querytree); + } + else + { + if (DebugLvl > 1) + elog(DEBUG, "ProcessQuery"); + ProcessQuery(querytree, plan, dest); + } + + if (Show_executor_stats) + { + fprintf(stderr, "EXECUTOR STATISTICS\n"); + ShowUsage(); + } } - if (Show_executor_stats) + /* + * In a query block, we want to increment the command counter + * between queries so that the effects of early queries are + * visible to subsequent ones. In particular we'd better + * do so before checking constraints. + */ + if (!isTransactionStmt) + CommandCounterIncrement(); + + /* + * Invoke IMMEDIATE constraint triggers + */ + DeferredTriggerEndQuery(); + + /* + * Clear the execution context to recover temporary + * memory used by the query. NOTE: if query string contains + * BEGIN/COMMIT transaction commands, execution context may + * now be different from what we were originally passed; + * so be careful to clear current context not "oldcontext". + */ + Assert(parse_context != CurrentMemoryContext); + + MemoryContextResetAndDeleteChildren(CurrentMemoryContext); + + /* + * If this was a transaction control statement, commit it + * and arrange to start a new xact command for the next + * command (if any). + */ + if (isTransactionStmt) { - fprintf(stderr, "EXECUTOR STATISTICS\n"); - ShowUsage(); + finish_xact_command(); + xact_started = false; } - } - /* - * In a query block, we want to increment the command counter - * between queries so that the effects of early queries are - * visible to subsequent ones. - */ - CommandCounterIncrement(); - /* - * Also, clear the execution context to recover temporary - * memory used by the query. NOTE: if query string contains - * BEGIN/COMMIT transaction commands, execution context may - * now be different from what we were originally passed; - * so be careful to clear current context not "oldcontext". - */ - MemoryContextResetAndDeleteChildren(CurrentMemoryContext); - } + } /* end loop over queries generated from a parsetree */ + } /* end loop over parsetrees */ + + /* + * Close down transaction statement, if one is open. + */ + if (xact_started) + finish_xact_command(); } +/* + * Convenience routines for starting/committing a single command. + */ +static void +start_xact_command(void) +{ + if (DebugLvl >= 1) + elog(DEBUG, "StartTransactionCommand"); + StartTransactionCommand(); +} + +static void +finish_xact_command(void) +{ + if (DebugLvl >= 1) + elog(DEBUG, "CommitTransactionCommand"); + set_ps_display("commit"); /* XXX probably the wrong place to do this */ + CommitTransactionCommand(); +#ifdef SHOW_MEMORY_STATS + /* print mem stats at each commit for leak tracking */ + if (ShowStats) + MemoryContextStats(TopMemoryContext); +#endif +} + + /* -------------------------------- * signal handler routines used in PostgresMain() * @@ -1397,7 +1614,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.177 $ $Date: 2000/10/03 03:11:19 $\n"); + puts("$Revision: 1.178 $ $Date: 2000/10/07 00:58:18 $\n"); } /* @@ -1524,22 +1741,20 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha { /* ---------------- * 'F' indicates a fastpath call. - * XXX HandleFunctionRequest * ---------------- */ case 'F': - IsEmptyQuery = false; - /* start an xact for this function invocation */ - if (DebugLvl >= 1) - elog(DEBUG, "StartTransactionCommand"); - StartTransactionCommand(); + start_xact_command(); if (HandleFunctionRequest() == EOF) { /* lost frontend connection during F message input */ goto normalexit; } + + /* commit the function-invocation transaction */ + finish_xact_command(); break; /* ---------------- @@ -1551,35 +1766,28 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha { /* ---------------- * if there is nothing in the input buffer, don't bother - * trying to parse and execute anything.. + * trying to parse and execute anything; just send + * back a quick NullCommand response. * ---------------- */ - IsEmptyQuery = true; + if (IsUnderPostmaster) + NullCommand(Remote); } else { /* ---------------- * otherwise, process the input string. + * + * Note: transaction command start/end is now done + * within pg_exec_query_string(), not here. * ---------------- */ - IsEmptyQuery = false; if (Show_query_stats) ResetUsage(); - /* start an xact for this query */ - if (DebugLvl >= 1) - elog(DEBUG, "StartTransactionCommand"); - StartTransactionCommand(); - - pg_exec_query_dest(parser_input->data, - whereToSendOutput, - QueryContext); - - /* - * Invoke IMMEDIATE constraint triggers - * - */ - DeferredTriggerEndQuery(); + pg_exec_query_string(parser_input->data, + whereToSendOutput, + QueryContext); if (Show_query_stats) { @@ -1603,39 +1811,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha elog(ERROR, "unknown frontend message was received"); } - /* ---------------- - * (6) commit the current transaction - * - * Note: if we had an empty input buffer, then we didn't - * call pg_exec_query_dest, so we don't bother to commit - * this transaction. - * ---------------- - */ - if (!IsEmptyQuery) - { - if (DebugLvl >= 1) - elog(DEBUG, "CommitTransactionCommand"); - set_ps_display("commit"); - CommitTransactionCommand(); -#ifdef SHOW_MEMORY_STATS - /* print global-context stats at each commit for leak tracking */ - if (ShowStats) - MemoryContextStats(TopMemoryContext); -#endif - } - else - { - if (IsUnderPostmaster) - NullCommand(Remote); - } - #ifdef MEMORY_CONTEXT_CHECKING /* - * Check all memory after each backend loop + * Check all memory after each backend loop. This is a rather + * weird place to do it, perhaps. */ MemoryContextCheck(TopMemoryContext); #endif - } /* end of main loop */ + } /* end of input-reading loop */ normalexit: ExitAfterAbort = true; /* ensure we will exit if elog during abort */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 9edb092e62d..9b52e9b66cd 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.94 2000/09/12 05:09:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.95 2000/10/07 00:58:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,6 +37,7 @@ #include "commands/view.h" #include "miscadmin.h" #include "parser/parse.h" +#include "parser/parse_expr.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteRemove.h" #include "tcop/utility.h" @@ -46,24 +47,6 @@ /* ---------------- - * CHECK_IF_ABORTED() is used to avoid doing unnecessary - * processing within an aborted transaction block. - * ---------------- - */ - /* we have to use IF because of the 'break' */ -#define CHECK_IF_ABORTED() \ -if (1) \ -{ \ - if (IsAbortedTransactionBlockState()) \ - { \ - elog(NOTICE, "current transaction is aborted, " \ - "queries ignored until end of transaction block"); \ - commandTag = "*ABORT STATE*"; \ - break; \ - } \ -} else - -/* ---------------- * general utility function invoker * ---------------- */ @@ -90,7 +73,6 @@ ProcessUtility(Node *parsetree, { case BEGIN_TRANS: set_ps_display(commandTag = "BEGIN"); - CHECK_IF_ABORTED(); BeginTransactionBlock(); break; @@ -116,7 +98,6 @@ ProcessUtility(Node *parsetree, ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree; set_ps_display(commandTag = "CLOSE"); - CHECK_IF_ABORTED(); PerformPortalClose(stmt->portalname, dest); } @@ -130,7 +111,6 @@ ProcessUtility(Node *parsetree, int count; set_ps_display(commandTag = (stmt->ismove) ? "MOVE" : "FETCH"); - CHECK_IF_ABORTED(); SetQuerySnapshot(); @@ -153,7 +133,6 @@ ProcessUtility(Node *parsetree, */ case T_CreateStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION); @@ -174,7 +153,6 @@ ProcessUtility(Node *parsetree, List *arg; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); /* check as much as we can before we start dropping ... */ foreach(arg, args) @@ -216,7 +194,6 @@ ProcessUtility(Node *parsetree, Relation rel; set_ps_display(commandTag = "TRUNCATE"); - CHECK_IF_ABORTED(); relname = ((TruncateStmt *) parsetree)->relName; if (!allowSystemTableMods && IsSystemRelationName(relname)) @@ -243,27 +220,23 @@ ProcessUtility(Node *parsetree, case T_CommentStmt: { - CommentStmt *statement; statement = ((CommentStmt *) parsetree); set_ps_display(commandTag = "COMMENT"); - CHECK_IF_ABORTED(); + CommentObject(statement->objtype, statement->objname, statement->objproperty, statement->objlist, statement->comment); } break; - - case T_CopyStmt: { CopyStmt *stmt = (CopyStmt *) parsetree; set_ps_display(commandTag = "COPY"); - CHECK_IF_ABORTED(); if (stmt->direction != FROM) SetQuerySnapshot(); @@ -292,7 +265,6 @@ ProcessUtility(Node *parsetree, RenameStmt *stmt = (RenameStmt *) parsetree; set_ps_display(commandTag = "ALTER"); - CHECK_IF_ABORTED(); relname = stmt->relname; if (!allowSystemTableMods && IsSystemRelationName(relname)) @@ -345,7 +317,6 @@ ProcessUtility(Node *parsetree, AlterTableStmt *stmt = (AlterTableStmt *) parsetree; set_ps_display(commandTag = "ALTER"); - CHECK_IF_ABORTED(); /* * Some or all of these functions are recursive to cover @@ -385,34 +356,10 @@ ProcessUtility(Node *parsetree, case T_ChangeACLStmt: { ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree; - List *i; - AclItem *aip; - unsigned modechg; set_ps_display(commandTag = "CHANGE"); - CHECK_IF_ABORTED(); - - aip = stmt->aclitem; - modechg = stmt->modechg; - foreach(i, stmt->relNames) - { - Relation rel; - - relname = strVal(lfirst(i)); - rel = heap_openr(relname, AccessExclusiveLock); - if (rel && rel->rd_rel->relkind == RELKIND_INDEX) - elog(ERROR, "\"%s\" is an index relation", - relname); - /* close rel, but keep lock until end of xact */ - heap_close(rel, NoLock); -#ifndef NO_SECURITY - if (!pg_ownercheck(GetUserId(), relname, RELNAME)) - elog(ERROR, "you do not own class \"%s\"", - relname); -#endif - ChangeAcl(relname, aip, modechg); - } + ExecuteChangeACLStmt(stmt); } break; @@ -426,7 +373,6 @@ ProcessUtility(Node *parsetree, DefineStmt *stmt = (DefineStmt *) parsetree; set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); switch (stmt->defType) { @@ -450,14 +396,14 @@ ProcessUtility(Node *parsetree, ViewStmt *stmt = (ViewStmt *) parsetree; set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + DefineView(stmt->viewname, stmt->query); /* retrieve parsetree */ } break; case T_ProcedureStmt: /* CREATE FUNCTION */ set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + CreateFunction((ProcedureStmt *) parsetree, dest); /* everything */ break; @@ -466,7 +412,7 @@ ProcessUtility(Node *parsetree, IndexStmt *stmt = (IndexStmt *) parsetree; set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + DefineIndex(stmt->relname, /* relation name */ stmt->idxname, /* index name */ stmt->accessMethod, /* am name */ @@ -491,14 +437,13 @@ ProcessUtility(Node *parsetree, elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]); #endif set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); + DefineQueryRewrite(stmt); } break; case T_CreateSeqStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); DefineSequence((CreateSeqStmt *) parsetree); break; @@ -508,7 +453,6 @@ ProcessUtility(Node *parsetree, ExtendStmt *stmt = (ExtendStmt *) parsetree; set_ps_display(commandTag = "EXTEND"); - CHECK_IF_ABORTED(); ExtendIndex(stmt->idxname, /* index name */ (Expr *) stmt->whereClause, /* where */ @@ -521,7 +465,6 @@ ProcessUtility(Node *parsetree, RemoveStmt *stmt = (RemoveStmt *) parsetree; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); switch (stmt->removeType) { @@ -581,10 +524,14 @@ ProcessUtility(Node *parsetree, case T_RemoveAggrStmt: { RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree; + char *typename = (char *) NULL; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); - RemoveAggregate(stmt->aggname, stmt->aggtype); + + if (stmt->aggtype != NULL) + typename = TypeNameToInternalName((TypeName *) stmt->aggtype); + + RemoveAggregate(stmt->aggname, typename); } break; @@ -593,27 +540,27 @@ ProcessUtility(Node *parsetree, RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); - RemoveFunction(stmt->funcname, - length(stmt->args), - stmt->args); + + RemoveFunction(stmt->funcname, stmt->args); } break; case T_RemoveOperStmt: { RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree; - char *type1 = (char *) NULL; - char *type2 = (char *) NULL; + TypeName *typenode1 = (TypeName *) lfirst(stmt->args); + TypeName *typenode2 = (TypeName *) lsecond(stmt->args); + char *typename1 = (char *) NULL; + char *typename2 = (char *) NULL; set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); - if (lfirst(stmt->args) != NULL) - type1 = strVal(lfirst(stmt->args)); - if (lsecond(stmt->args) != NULL) - type2 = strVal(lsecond(stmt->args)); - RemoveOperator(stmt->opname, type1, type2); + if (typenode1 != NULL) + typename1 = TypeNameToInternalName(typenode1); + if (typenode2 != NULL) + typename2 = TypeNameToInternalName(typenode2); + + RemoveOperator(stmt->opname, typename1, typename2); } break; @@ -626,7 +573,7 @@ ProcessUtility(Node *parsetree, CreatedbStmt *stmt = (CreatedbStmt *) parsetree; set_ps_display(commandTag = "CREATE DATABASE"); - CHECK_IF_ABORTED(); + createdb(stmt->dbname, stmt->dbpath, stmt->encoding); } break; @@ -636,7 +583,7 @@ ProcessUtility(Node *parsetree, DropdbStmt *stmt = (DropdbStmt *) parsetree; set_ps_display(commandTag = "DROP DATABASE"); - CHECK_IF_ABORTED(); + dropdb(stmt->dbname); } break; @@ -647,7 +594,6 @@ ProcessUtility(Node *parsetree, NotifyStmt *stmt = (NotifyStmt *) parsetree; set_ps_display(commandTag = "NOTIFY"); - CHECK_IF_ABORTED(); Async_Notify(stmt->relname); } @@ -658,7 +604,6 @@ ProcessUtility(Node *parsetree, ListenStmt *stmt = (ListenStmt *) parsetree; set_ps_display(commandTag = "LISTEN"); - CHECK_IF_ABORTED(); Async_Listen(stmt->relname, MyProcPid); } @@ -669,7 +614,6 @@ ProcessUtility(Node *parsetree, UnlistenStmt *stmt = (UnlistenStmt *) parsetree; set_ps_display(commandTag = "UNLISTEN"); - CHECK_IF_ABORTED(); Async_Unlisten(stmt->relname, MyProcPid); } @@ -684,7 +628,6 @@ ProcessUtility(Node *parsetree, LoadStmt *stmt = (LoadStmt *) parsetree; set_ps_display(commandTag = "LOAD"); - CHECK_IF_ABORTED(); closeAllVfds(); /* probably not necessary... */ load_file(stmt->filename); @@ -696,7 +639,6 @@ ProcessUtility(Node *parsetree, ClusterStmt *stmt = (ClusterStmt *) parsetree; set_ps_display(commandTag = "CLUSTER"); - CHECK_IF_ABORTED(); cluster(stmt->relname, stmt->indexname); } @@ -704,7 +646,7 @@ ProcessUtility(Node *parsetree, case T_VacuumStmt: set_ps_display(commandTag = "VACUUM"); - CHECK_IF_ABORTED(); + vacuum(((VacuumStmt *) parsetree)->vacrel, ((VacuumStmt *) parsetree)->verbose, ((VacuumStmt *) parsetree)->analyze, @@ -716,7 +658,6 @@ ProcessUtility(Node *parsetree, ExplainStmt *stmt = (ExplainStmt *) parsetree; set_ps_display(commandTag = "EXPLAIN"); - CHECK_IF_ABORTED(); ExplainQuery(stmt->query, stmt->verbose, dest); } @@ -732,7 +673,7 @@ ProcessUtility(Node *parsetree, RecipeStmt *stmt = (RecipeStmt *) parsetree; set_ps_display(commandTag = "EXECUTE RECIPE"); - CHECK_IF_ABORTED(); + beginRecipe(stmt); } break; @@ -773,14 +714,12 @@ ProcessUtility(Node *parsetree, */ case T_CreateTrigStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); CreateTrigger((CreateTrigStmt *) parsetree); break; case T_DropTrigStmt: set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); DropTrigger((DropTrigStmt *) parsetree); break; @@ -790,14 +729,12 @@ ProcessUtility(Node *parsetree, */ case T_CreatePLangStmt: set_ps_display(commandTag = "CREATE"); - CHECK_IF_ABORTED(); CreateProceduralLanguage((CreatePLangStmt *) parsetree); break; case T_DropPLangStmt: set_ps_display(commandTag = "DROP"); - CHECK_IF_ABORTED(); DropProceduralLanguage((DropPLangStmt *) parsetree); break; @@ -808,56 +745,48 @@ ProcessUtility(Node *parsetree, */ case T_CreateUserStmt: set_ps_display(commandTag = "CREATE USER"); - CHECK_IF_ABORTED(); CreateUser((CreateUserStmt *) parsetree); break; case T_AlterUserStmt: set_ps_display(commandTag = "ALTER USER"); - CHECK_IF_ABORTED(); AlterUser((AlterUserStmt *) parsetree); break; case T_DropUserStmt: set_ps_display(commandTag = "DROP USER"); - CHECK_IF_ABORTED(); DropUser((DropUserStmt *) parsetree); break; case T_LockStmt: set_ps_display(commandTag = "LOCK TABLE"); - CHECK_IF_ABORTED(); LockTableCommand((LockStmt *) parsetree); break; case T_ConstraintsSetStmt: set_ps_display(commandTag = "SET CONSTRAINTS"); - CHECK_IF_ABORTED(); DeferredTriggerSetState((ConstraintsSetStmt *) parsetree); break; case T_CreateGroupStmt: set_ps_display(commandTag = "CREATE GROUP"); - CHECK_IF_ABORTED(); CreateGroup((CreateGroupStmt *) parsetree); break; case T_AlterGroupStmt: set_ps_display(commandTag = "ALTER GROUP"); - CHECK_IF_ABORTED(); AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP"); break; case T_DropGroupStmt: set_ps_display(commandTag = "DROP GROUP"); - CHECK_IF_ABORTED(); DropGroup((DropGroupStmt *) parsetree); break; @@ -867,7 +796,6 @@ ProcessUtility(Node *parsetree, ReindexStmt *stmt = (ReindexStmt *) parsetree; set_ps_display(commandTag = "REINDEX"); - CHECK_IF_ABORTED(); switch (stmt->reindexType) { diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 3d43a45cd1e..401ed1a9375 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * 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 @@ #include "postgres.h" +#include "access/heapam.h" #include "catalog/catalog.h" #include "catalog/pg_shadow.h" #include "catalog/pg_type.h" #include "lib/stringinfo.h" +#include "miscadmin.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/memutils.h" @@ -561,7 +563,52 @@ aclcontains(PG_FUNCTION_ARGS) 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 @@ -569,9 +616,7 @@ aclcontains(PG_FUNCTION_ARGS) * and a new privilege * * does not add duplicate privileges - * */ - char * aclmakepriv(char *old_privlist, char new_priv) { @@ -619,12 +664,9 @@ aclmakepriv(char *old_privlist, char new_priv) * "G" - group * "U" - user * - * concatenates the two strings together with a space in between - * - * this routine is used in the parser - * + * 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. */ - char * aclmakeuser(char *user_type, char *user) { @@ -635,20 +677,16 @@ aclmakeuser(char *user_type, char *user) return user_list; } - /* * makeAclStmt: - * this is a helper routine called by the parser - * create a ChangeAclStmt - * we take in the privilegs, relation_name_list, and grantee - * as well as a single character '+' or '-' to indicate grant or revoke + * create a ChangeACLStmt at parse time. + * we take in the privileges, relation_name_list, and grantee + * as well as a single character '+' or '-' to indicate grant or revoke * - * returns a new ChangeACLStmt* - * - * this routines works by creating a old-style changle acl string and - * then calling aclparse; + * We convert the information to the same external form recognized by + * aclitemin (see aclparse), and save that string in the ChangeACLStmt. + * Conversion to internal form happens when the statement is executed. */ - ChangeACLStmt * makeAclStmt(char *privileges, List *rel_list, char *grantee, char grant_or_revoke) @@ -658,11 +696,6 @@ makeAclStmt(char *privileges, List *rel_list, char *grantee, 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" */ if (grantee[0] == 'G') /* group permissions */ { @@ -683,7 +716,8 @@ makeAclStmt(char *privileges, List *rel_list, char *grantee, grant_or_revoke, privileges); } n->relNames = rel_list; - aclparse(str.data, n->aclitem, (unsigned *) &n->modechg); + n->aclString = pstrdup(str.data); + pfree(str.data); return n; } diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 2a7a4bdcfa8..dce401d7d9b 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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); /* * 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, char *typeName1, char *typeName2); extern void RemoveType(char *typeName); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 41309426e8b..b50990fe299 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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 typedef struct ChangeACLStmt { NodeTag type; - struct AclItem *aclitem; - unsigned modechg; List *relNames; + char *aclString; } ChangeACLStmt; /* ---------------------- @@ -488,10 +487,8 @@ typedef struct ProcedureStmt { NodeTag type; char *funcname; /* name of function to create */ - List *defArgs; /* list of definitions a list of strings - * (as Value *) */ - Node *returnType; /* the return type (as a string or a - * TypeName (ie.setof) */ + List *argTypes; /* list of argument types (TypeName nodes) */ + Node *returnType; /* the return type (a TypeName node) */ List *withClause; /* a list of DefElem */ List *as; /* definition of function body */ char *language; /* C, SQL, etc */ @@ -505,7 +502,7 @@ typedef struct RemoveAggrStmt { NodeTag type; char *aggname; /* aggregate to drop */ - char *aggtype; /* for this type */ + Node *aggtype; /* TypeName for input datatype, or NULL */ } RemoveAggrStmt; /* ---------------------- diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index afd8a34fb3e..9d60e0f64c8 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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 @@ #include "parser/parse_node.h" -extern List *parse_analyze(List *pl, ParseState *parentParseState); +extern List *parse_analyze(Node *parseTree, ParseState *parentParseState); #endif /* ANALYZE_H */ diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h index 7f1b5d5122d..410a24bc455 100644 --- a/src/include/parser/parse_expr.h +++ b/src/include/parser/parse_expr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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); extern int32 exprTypmod(Node *expr); extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod); extern void parse_expr_init(void); +extern char *TypeNameToInternalName(TypeName *typename); #endif /* PARSE_EXPR_H */ diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 562efca25cc..062a5818407 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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 * This file was created so that other c files could get the two @@ -35,9 +35,9 @@ extern bool ShowPortNumber; extern List *pg_parse_and_rewrite(char *query_string, Oid *typev, int nargs); extern Plan *pg_plan_query(Query *querytree); -extern void pg_exec_query_dest(char *query_string, - CommandDest dest, - MemoryContext parse_context); +extern void pg_exec_query_string(char *query_string, + CommandDest dest, + MemoryContext parse_context); #endif /* BOOTSTRAP_INCLUDE */ diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 4add4202fcb..8836bd1733e 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * 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 * For backward-compatibility purposes we have to allow there @@ -167,12 +167,15 @@ extern char *aclcheck_error_strings[]; /*#define ACLDEBUG_TRACE*/ /* - * routines used internally (parser, etc.) + * routines used internally */ extern Acl *acldefault(char *relname, AclId ownerid); 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 *aclmakeuser(char *user_type, char *user); extern ChangeACLStmt *makeAclStmt(char *privs, List *rel_list, char *grantee, @@ -187,6 +190,7 @@ extern Datum aclitemout(PG_FUNCTION_ARGS); extern Datum aclinsert(PG_FUNCTION_ARGS); extern Datum aclremove(PG_FUNCTION_ARGS); extern Datum aclcontains(PG_FUNCTION_ARGS); +extern void ExecuteChangeACLStmt(ChangeACLStmt *stmt); /* * prototypes for functions in aclchk.c |