diff options
Diffstat (limited to 'src/backend/parser')
-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 |
5 files changed, 125 insertions, 248 deletions
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 |