From 588867bd7b5f7cf9d3a7f373064a5a9474b992fe Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Mon, 19 Jan 1998 05:06:41 +0000 Subject: [PATCH] Create SubLink nodes in parser for Vadim. --- src/backend/parser/analyze.c | 6 +- src/backend/parser/gram.y | 98 +++++++++++++++++++++++-------- src/backend/parser/keywords.c | 3 +- src/backend/parser/parse_clause.c | 4 +- src/backend/parser/parse_expr.c | 39 +++++++++++- src/backend/parser/parse_node.c | 7 ++- src/backend/parser/parser.c | 4 +- src/include/nodes/primnodes.h | 5 +- src/include/parser/analyze.h | 4 +- src/include/parser/parse_node.h | 6 +- 10 files changed, 133 insertions(+), 43 deletions(-) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 45c5d1406b..5fc0bb1ac3 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.65 1998/01/15 18:59:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.66 1998/01/19 05:06:13 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -53,7 +53,7 @@ List *extras = NIL; * */ QueryTreeList * -parse_analyze(List *pl) +parse_analyze(List *pl, ParseState *parentParseState) { QueryTreeList *result; ParseState *pstate; @@ -65,7 +65,7 @@ parse_analyze(List *pl) while (pl != NIL) { - pstate = make_parsestate(); + pstate = make_parsestate(parentParseState); result->qtrees[i++] = transformStmt(pstate, lfirst(pl)); if (extras != NIL) { diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 0f43799d38..244c834568 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 1.93 1998/01/17 05:01:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.94 1998/01/19 05:06:15 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -48,7 +48,7 @@ static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */ static bool QueryIsRule = FALSE; -static Node *saved_In_Expr; +static List *saved_In_Expr = NIL; static Oid *param_type_info; static int pfunc_num_args; extern List *parsetree; @@ -242,7 +242,7 @@ Oid param_type(int t); /* used in parse_expr.c */ */ /* Keywords (in SQL92 reserved words) */ -%token ACTION, ADD, ALL, ALTER, AND, AS, ASC, +%token ACTION, ADD, ALL, ALTER, AND, ANY AS, ASC, BEGIN_TRANS, BETWEEN, BOTH, BY, CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT, CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME, @@ -2871,7 +2871,9 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { SubLink *n = makeNode(SubLink); n->lefthand = $2; - n->subLinkType = IN_SUBLINK; + n->oper = lcons("=",NIL); + n->useor = false; + n->subLinkType = ANY_SUBLINK; n->subselect = $6; $$ = (Node *)n; } @@ -2879,7 +2881,29 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { SubLink *n = makeNode(SubLink); n->lefthand = $2; - n->subLinkType = NOTIN_SUBLINK; + n->oper = lcons("<>",NIL); + n->useor = true; + n->subLinkType = ALL_SUBLINK; + n->subselect = $7; + $$ = (Node *)n; + } + | '(' row_descriptor ')' Op ANY '(' SubSelect ')' + { + SubLink *n = makeNode(SubLink); + n->lefthand = $2; + n->oper = lcons($4,NIL); + n->useor = false; + n->subLinkType = ANY_SUBLINK; + n->subselect = $7; + $$ = (Node *)n; + } + | '(' row_descriptor ')' Op ALL '(' SubSelect ')' + { + SubLink *n = makeNode(SubLink); + n->lefthand = $2; + n->oper = lcons($4,NIL); + n->useor = false; + n->subLinkType = ALL_SUBLINK; n->subselect = $7; $$ = (Node *)n; } @@ -2887,8 +2911,12 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { SubLink *n = makeNode(SubLink); n->lefthand = $2; - n->subLinkType = OPER_SUBLINK; n->oper = lcons($4, NIL); + if (strcmp($4,"<>") == 0) + n->useor = true; + else + n->useor = false; + n->subLinkType = EXPR_SUBLINK; n->subselect = $6; $$ = (Node *)n; } @@ -3114,17 +3142,13 @@ a_expr: attr opt_indirection n->args = NIL; $$ = (Node *)n; } - /* We probably need to define an "exists" node, - * since the optimizer could choose to find only one match. - * Perhaps the first implementation could just check for - * count(*) > 0? - thomas 1997-07-19 - */ | EXISTS '(' SubSelect ')' { SubLink *n = makeNode(SubLink); n->lefthand = NIL; - n->subLinkType = EXISTS_SUBLINK; + n->useor = false; n->oper = NIL; + n->subLinkType = EXISTS_SUBLINK; n->subselect = $3; $$ = (Node *)n; } @@ -3239,26 +3263,52 @@ a_expr: attr opt_indirection makeA_Expr(OP, "<", $1, $4), makeA_Expr(OP, ">", $1, $6)); } - | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')' + | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')' { saved_In_Expr = lnext(saved_In_Expr); } { if (nodeTag($5) == T_SubLink) { - ((SubLink *)$5)->lefthand = lcons($1, NIL); - ((SubLink *)$5)->subLinkType = IN_SUBLINK; - $$ = (Node *)$5; + SubLink *n = (SubLink *)$5; + n->lefthand = lcons($1, NIL); + n->oper = lcons("=",NIL); + n->useor = false; + n->subLinkType = ANY_SUBLINK; + $$ = (Node *)n; } else $$ = $5; } - | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')' + | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')' { saved_In_Expr = lnext(saved_In_Expr); } { if (nodeTag($6) == T_SubLink) { - ((SubLink *)$6)->lefthand = lcons($1, NIL); - ((SubLink *)$6)->subLinkType = NOTIN_SUBLINK; - $$ = (Node *)$6; + SubLink *n = (SubLink *)$6; + n->lefthand = lcons($1, NIL); + n->oper = lcons("<>",NIL); + n->useor = false; + n->subLinkType = ALL_SUBLINK; + $$ = (Node *)n; } else $$ = $6; } + | 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 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 AND a_expr { $$ = makeA_Expr(AND, NULL, $1, $3); } | a_expr OR a_expr @@ -3480,10 +3530,10 @@ in_expr: SubSelect ; in_expr_nodes: AexprConst - { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); } + { $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); } | in_expr_nodes ',' AexprConst { $$ = makeA_Expr(OR, NULL, $1, - makeA_Expr(OP, "=", saved_In_Expr, $3)); + makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3)); } ; @@ -3498,10 +3548,10 @@ not_in_expr: SubSelect ; not_in_expr_nodes: AexprConst - { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); } + { $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); } | not_in_expr_nodes ',' AexprConst { $$ = makeA_Expr(AND, NULL, $1, - makeA_Expr(OP, "<>", saved_In_Expr, $3)); + makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3)); } ; diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index 45c450f7d0..3049689aa1 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.29 1998/01/05 03:32:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.30 1998/01/19 05:06:16 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -39,6 +39,7 @@ static ScanKeyword ScanKeywords[] = { {"alter", ALTER}, {"analyze", ANALYZE}, {"and", AND}, + {"any", ANY}, {"append", APPEND}, {"archive", ARCHIVE}, {"as", AS}, diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 7b09518d4f..71aaf24423 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.8 1998/01/06 23:58:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.9 1998/01/19 05:06:17 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -387,7 +387,7 @@ transformUnionClause(List *unionClause, List *targetlist) if (unionClause) { - qlist = parse_analyze(unionClause); + qlist = parse_analyze(unionClause, NULL); for (i=0; i < qlist->len; i++) union_list = lappend(union_list, qlist->qtrees[i]); diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 00efc044dc..b1bf7d3a95 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.7 1998/01/16 23:20:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.8 1998/01/19 05:06:18 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,7 @@ #include "nodes/params.h" #include "nodes/relation.h" #include "parse.h" +#include "parser/analyze.h" #include "parser/gramparse.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" @@ -249,6 +250,42 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) precedence); break; } + case T_SubLink: + { + SubLink *sublink = (SubLink *) expr; + QueryTreeList *qtree; + Query *subselect; + + qtree = parse_analyze(lcons(sublink->subselect,NIL), pstate); + + Assert(qtree->len == 1); + + sublink->subselect = (Node *) subselect = qtree->qtrees[0]; + + if (length(sublink->lefthand) != + length(subselect->targetList)) + elog(ERROR,"Subselect has too many or too few fields."); + + if (sublink->subLinkType != EXISTS_SUBLINK) + { + char *op = lfirst(sublink->oper); + List *left_expr = sublink->lefthand; + List *right_expr = subselect->targetList; + List *elist; + + foreach(elist, left_expr) + { + Node *lexpr = transformExpr(pstate, lfirst(elist), precedence); + Node *rexpr = lfirst(right_expr); + Expr *op_expr; + + op_expr = make_op(op, lexpr, rexpr); + sublink->oper = lappend(sublink->oper, op_expr->oper); + right_expr = lnext(right_expr); + } + } + break; + } default: /* should not reach here */ elog(ERROR, "transformExpr: does not know how to transform node %d", diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index 15a47993a7..03bc54d531 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.7 1998/01/17 04:53:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.8 1998/01/19 05:06:19 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -42,7 +42,7 @@ static Node *make_operand(char *opname, */ ParseState * -make_parsestate(void) +make_parsestate(ParseState *parentParseState) { ParseState *pstate; @@ -50,7 +50,8 @@ make_parsestate(void) MemSet(pstate, 0, sizeof(ParseState)); pstate->p_last_resno = 1; - + pstate->parentParseState = parentParseState; + return (pstate); } diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c index d7e2344823..0a7a8d5800 100644 --- a/src/backend/parser/parser.c +++ b/src/backend/parser/parser.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.31 1997/12/22 05:42:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.32 1998/01/19 05:06:20 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -61,7 +61,7 @@ parser(char *str, Oid *typev, int nargs) if (yyresult) /* error */ return ((QueryTreeList *) NULL); - queryList = parse_analyze(parsetree); + queryList = parse_analyze(parsetree, NULL); #ifdef SETS_FIXED diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 3da2c433cb..531e5e9052 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.13 1998/01/17 04:53:42 momjian Exp $ + * $Id: primnodes.h,v 1.14 1998/01/19 05:06:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -281,8 +281,7 @@ typedef struct Aggreg */ typedef enum SubLinkType { - EXISTS_SUBLINK, ALL_SUBLINK, ANY_SUBLINK, EXPR_SUBLINK, - IN_SUBLINK, NOTIN_SUBLINK, OPER_SUBLINK + EXISTS_SUBLINK, ALL_SUBLINK, ANY_SUBLINK, EXPR_SUBLINK } SubLinkType; diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index b88d80f346..85191a60c1 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.h,v 1.2 1997/11/26 01:13:56 momjian Exp $ + * $Id: analyze.h,v 1.3 1998/01/19 05:06:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -14,6 +14,6 @@ #include -extern QueryTreeList *parse_analyze(List *pl); +extern QueryTreeList *parse_analyze(List *pl, ParseState *parentParseState); #endif /* ANALYZE_H */ diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index a0915574a1..f09c7d0f86 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: parse_node.h,v 1.5 1998/01/17 04:53:46 momjian Exp $ + * $Id: parse_node.h,v 1.6 1998/01/19 05:06:41 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -28,9 +28,11 @@ typedef struct QueryTreeList /* state information used during parse analysis */ typedef struct ParseState { + struct ParseState; int p_last_resno; List *p_rtable; List *p_insert_columns; + struct ParseState *parentParseState; bool p_hasAggs; bool p_hasSubLinks; bool p_is_insert; @@ -41,7 +43,7 @@ typedef struct ParseState RangeTblEntry *p_target_rangetblentry; } ParseState; -extern ParseState *make_parsestate(void); +extern ParseState *make_parsestate(ParseState *parentParseState); extern Expr *make_op(char *opname, Node *ltree, Node *rtree); extern Var *make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id); extern ArrayRef *make_array_ref(Node *expr,