diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/analyze.c | 7 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 387 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 47 |
3 files changed, 84 insertions, 357 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index b83e1372962..4ad72439b36 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.c,v 1.123 1999/11/07 23:08:10 momjian Exp $ + * $Id: analyze.c,v 1.124 1999/11/15 02:00:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -231,11 +231,11 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt) /* fix where clause */ qry->qual = transformWhereClause(pstate, stmt->whereClause, NULL); - qry->hasSubLinks = pstate->p_hasSubLinks; qry->rtable = pstate->p_rtable; qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL); + qry->hasSubLinks = pstate->p_hasSubLinks; qry->hasAggs = pstate->p_hasAggs; if (pstate->p_hasAggs) parseCheckAggregates(pstate, qry); @@ -423,6 +423,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) if (stmt->forUpdate != NULL) transformForUpdate(qry, stmt->forUpdate); + /* in case of subselects in default clauses... */ + qry->hasSubLinks = pstate->p_hasSubLinks; + return (Query *) qry; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index ba16de5e443..9aa9f93cd15 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.113 1999/10/29 23:52:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.114 1999/11/15 02:00:10 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -53,11 +53,12 @@ #include "mb/pg_wchar.h" #endif +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; -extern List *parsetree; /* @@ -75,8 +76,6 @@ static void mapTargetColumns(List *source, List *target); static void param_type_init(Oid *typev, int nargs); static Node *doNegate(Node *n); -Oid param_type(int t); /* used in parse_expr.c */ - /* old versions of flex define this as a macro */ #if defined(yywrap) #undef yywrap @@ -178,7 +177,7 @@ Oid param_type(int t); /* used in parse_expr.c */ %type <boolean> TriggerForOpt, TriggerForType, OptTemp, OptTempType, OptTempScope %type <list> for_update_clause, update_list -%type <boolean> opt_union +%type <boolean> opt_all %type <boolean> opt_table %type <boolean> opt_trans @@ -1097,11 +1096,18 @@ OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; } | /*EMPTY*/ { $$ = NIL; } ; -CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SubSelect +/* + * Note: CREATE TABLE ... AS SELECT ... is just another spelling for + * SELECT ... INTO. + */ + +CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SelectStmt { SelectStmt *n = (SelectStmt *)$7; if ($5 != NIL) mapTargetColumns($5, n->targetList); + if (n->into != NULL) + elog(ERROR,"CREATE TABLE/AS SELECT may not specify INTO"); n->istemp = $2; n->into = $4; $$ = (Node *)n; @@ -2861,7 +2867,7 @@ select_clause: '(' select_clause ')' $$ = (Node *)makeA_Expr(AND,NULL,$1, makeA_Expr(NOT,NULL,NULL,$3)); } - | select_clause UNION opt_union select_clause + | select_clause UNION opt_all select_clause { if (IsA($4, SelectStmt)) { @@ -2919,7 +2925,7 @@ opt_table: TABLE { $$ = TRUE; } | /*EMPTY*/ { $$ = FALSE; } ; -opt_union: ALL { $$ = TRUE; } +opt_all: ALL { $$ = TRUE; } | /*EMPTY*/ { $$ = FALSE; } ; @@ -3590,16 +3596,13 @@ a_expr_or_null: a_expr * Define row_descriptor to allow yacc to break the reduce/reduce conflict * with singleton expressions. * Eliminated lots of code by defining row_op and sub_type clauses. - * However, can not consolidate EXPR_LINK case with others subselects - * due to shift/reduce conflict with the non-subselect clause (the parser - * would have to look ahead more than one token to resolve the conflict). * - thomas 1998-05-09 */ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { SubLink *n = makeNode(SubLink); n->lefthand = $2; - n->oper = lcons("=",NIL); + n->oper = lcons("=", NIL); n->useor = false; n->subLinkType = ANY_SUBLINK; n->subselect = $6; @@ -3609,7 +3612,7 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { SubLink *n = makeNode(SubLink); n->lefthand = $2; - n->oper = lcons("<>",NIL); + n->oper = lcons("<>", NIL); n->useor = true; n->subLinkType = ALL_SUBLINK; n->subselect = $7; @@ -3637,7 +3640,7 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' n->useor = true; else n->useor = false; - n->subLinkType = EXPR_SUBLINK; + n->subLinkType = MULTIEXPR_SUBLINK; n->subselect = $6; $$ = (Node *)n; } @@ -3933,16 +3936,6 @@ a_expr: attr n->args = NIL; $$ = (Node *)n; } - | EXISTS '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = NIL; - n->useor = false; - n->oper = NIL; - n->subLinkType = EXISTS_SUBLINK; - n->subselect = $3; - $$ = (Node *)n; - } | EXTRACT '(' extract_list ')' { FuncCall *n = makeNode(FuncCall); @@ -4065,7 +4058,7 @@ a_expr: attr { SubLink *n = (SubLink *)$4; n->lefthand = lcons($1, NIL); - n->oper = lcons("=",NIL); + n->oper = lcons("=", NIL); n->useor = false; n->subLinkType = ANY_SUBLINK; $$ = (Node *)n; @@ -4092,7 +4085,7 @@ a_expr: attr { SubLink *n = (SubLink *)$5; n->lefthand = lcons($1, NIL); - n->oper = lcons("<>",NIL); + n->oper = lcons("<>", NIL); n->useor = false; n->subLinkType = ALL_SUBLINK; $$ = (Node *)n; @@ -4112,334 +4105,34 @@ a_expr: attr $$ = n; } } - | a_expr Op '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons($2,NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '+' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("+",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '-' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("-",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '*' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("*",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '/' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("/",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '%' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("%",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '^' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("^",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '|' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("|",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '<' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("<",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '>' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons(">",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr '=' '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("=",NIL); - n->useor = false; - n->subLinkType = EXPR_SUBLINK; - n->subselect = $4; - $$ = (Node *)n; - } - | a_expr Op ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons($2,NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '+' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("+",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '-' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("-",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '*' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("*",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '/' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("/",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '%' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("%",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '^' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("^",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '|' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("|",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '<' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("<",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '>' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons(">",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '=' ANY '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1,NIL); - n->oper = lcons("=",NIL); - n->useor = false; - n->subLinkType = ANY_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr Op ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons($2,NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '+' ALL '(' SubSelect ')' + | a_expr row_op sub_type '(' SubSelect ')' { SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("+",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; + n->lefthand = lcons($1, NIL); + n->oper = lcons($2, NIL); + n->useor = false; /* doesn't matter since only one col */ + n->subLinkType = $3; n->subselect = $5; $$ = (Node *)n; } - | a_expr '-' ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("-",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '*' ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("*",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '/' ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("/",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '%' ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("%",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '^' ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("^",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '|' ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("|",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '<' ALL '(' SubSelect ')' - { - SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("<",NIL); - n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; - $$ = (Node *)n; - } - | a_expr '>' ALL '(' SubSelect ')' + | EXISTS '(' SubSelect ')' { SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons(">",NIL); + n->lefthand = NIL; + n->oper = NIL; n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; + n->subLinkType = EXISTS_SUBLINK; + n->subselect = $3; $$ = (Node *)n; } - | a_expr '=' ALL '(' SubSelect ')' + | '(' SubSelect ')' { SubLink *n = makeNode(SubLink); - n->lefthand = lcons($1, NULL); - n->oper = lcons("=",NIL); + n->lefthand = NIL; + n->oper = NIL; n->useor = false; - n->subLinkType = ALL_SUBLINK; - n->subselect = $5; + n->subLinkType = EXPR_SUBLINK; + n->subselect = $2; $$ = (Node *)n; } | a_expr AND a_expr @@ -4702,6 +4395,16 @@ b_expr: attr n->args = $3; $$ = (Node *)n; } + | '(' SubSelect ')' + { + SubLink *n = makeNode(SubLink); + n->lefthand = NIL; + n->oper = NIL; + n->useor = false; + n->subLinkType = EXPR_SUBLINK; + n->subselect = $2; + $$ = (Node *)n; + } ; opt_indirection: '[' a_expr ']' opt_indirection @@ -5345,8 +5048,6 @@ mapTargetColumns(List *src, List *dst) src = lnext(src); dst = lnext(dst); } - - return; } /* mapTargetColumns() */ diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index ee9d3077283..76e5f91f1a8 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.58 1999/09/13 04:14:56 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.59 1999/11/15 02:00:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -220,8 +220,30 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) sublink->lefthand = NIL; sublink->oper = NIL; } + else if (sublink->subLinkType == EXPR_SUBLINK) + { + List *tlist = qtree->targetList; + + /* Make sure the subselect delivers a single column + * (ignoring resjunk targets). + */ + if (tlist == NIL || + ((TargetEntry *) lfirst(tlist))->resdom->resjunk) + elog(ERROR, "parser: subselect must have a field"); + while ((tlist = lnext(tlist)) != NIL) + { + if (! ((TargetEntry *) lfirst(tlist))->resdom->resjunk) + elog(ERROR, "parser: subselect must have only one field"); + } + /* EXPR needs no lefthand or combining operator. + * These fields should be NIL already, but make sure. + */ + sublink->lefthand = NIL; + sublink->oper = NIL; + } else { + /* ALL, ANY, or MULTIEXPR: generate operator list */ char *op = lfirst(sublink->oper); List *left_list = sublink->lefthand; List *right_list = qtree->targetList; @@ -231,9 +253,10 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) lfirst(elist) = transformExpr(pstate, lfirst(elist), precedence); - if (length(left_list) > 1 && + /* Combining operators other than =/<> is dubious... */ + if (length(left_list) != 1 && strcmp(op, "=") != 0 && strcmp(op, "<>") != 0) - elog(ERROR, "parser: '%s' is not relational operator", + elog(ERROR, "parser: '%s' is not usable for row comparison", op); sublink->oper = NIL; @@ -266,8 +289,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) FALSE); opform = (Form_pg_operator) GETSTRUCT(optup); - if (opform->oprresult != BOOLOID && - sublink->subLinkType != EXPR_SUBLINK) + if (opform->oprresult != BOOLOID) elog(ERROR, "parser: '%s' must return 'bool' to be used with quantified predicate subquery", op); newop = makeOper(oprid(optup),/* opno */ @@ -589,13 +611,14 @@ exprType(Node *expr) if (sublink->subLinkType == EXPR_SUBLINK) { - /* return the result type of the combining operator; - * should only be one... - */ - Oper *op = (Oper *) lfirst(sublink->oper); - - Assert(IsA(op, Oper)); - type = op->opresulttype; + /* get the type of the subselect's first target column */ + Query *qtree = (Query *) sublink->subselect; + TargetEntry *tent; + + if (! qtree || ! IsA(qtree, Query)) + elog(ERROR, "exprType: can't get type for untransformed sublink"); + tent = (TargetEntry *) lfirst(qtree->targetList); + type = tent->resdom->restype; } else { |