aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/analyze.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r--src/backend/parser/analyze.c117
1 files changed, 113 insertions, 4 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 3dc0cad8165..ea9cb5fa8c2 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.91 1998/12/14 06:50:32 scrappy Exp $
+ * $Id: analyze.c,v 1.92 1999/01/18 00:09:49 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -26,6 +26,11 @@
#include "parser/parse_node.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
+/***S*I***/
+#include "parser/parse_expr.h"
+#include "catalog/pg_type.h"
+#include "parse.h"
+
#include "utils/builtins.h"
#include "utils/mcxt.h"
@@ -383,8 +388,13 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
* The INSERT INTO ... SELECT ... could have a UNION in child, so
* unionClause may be false
*/
- qry->unionall = stmt->unionall;
- qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
+ qry->unionall = stmt->unionall;
+
+ /***S*I***/
+ /* Just hand through the unionClause and intersectClause.
+ * We will handle it in the function Except_Intersect_Rewrite() */
+ qry->unionClause = stmt->unionClause;
+ qry->intersectClause = stmt->intersectClause;
/*
* If there is a havingQual but there are no aggregates, then there is
@@ -942,7 +952,12 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
* unionClause may be false
*/
qry->unionall = stmt->unionall;
- qry->unionClause = transformUnionClause(stmt->unionClause, qry->targetList);
+
+ /***S*I***/
+ /* Just hand through the unionClause and intersectClause.
+ * We will handle it in the function Except_Intersect_Rewrite() */
+ qry->unionClause = stmt->unionClause;
+ qry->intersectClause = stmt->intersectClause;
/*
* If there is a havingQual but there are no aggregates, then there is
@@ -1012,3 +1027,97 @@ transformCursorStmt(ParseState *pstate, SelectStmt *stmt)
return qry;
}
+
+/***S*I***/
+/* This function steps through the tree
+ * built up by the select_w_o_sort rule
+ * and builds a list of all SelectStmt Nodes found
+ * The built up list is handed back in **select_list.
+ * If one of the SelectStmt Nodes has the 'unionall' flag
+ * set to true *unionall_present hands back 'true' */
+void
+create_select_list(Node *ptr, List **select_list, bool *unionall_present)
+{
+ if(IsA(ptr, SelectStmt)) {
+ *select_list = lappend(*select_list, ptr);
+ if(((SelectStmt *)ptr)->unionall == TRUE) *unionall_present = TRUE;
+ return;
+ }
+
+ /* Recursively call for all arguments. A NOT expr has no lexpr! */
+ if (((A_Expr *)ptr)->lexpr != NULL)
+ create_select_list(((A_Expr *)ptr)->lexpr, select_list, unionall_present);
+ create_select_list(((A_Expr *)ptr)->rexpr, select_list, unionall_present);
+}
+
+/* Changes the A_Expr Nodes to Expr Nodes and exchanges ANDs and ORs.
+ * The reason for the exchange is easy: We implement INTERSECTs and EXCEPTs
+ * by rewriting these queries to semantically equivalent queries that use
+ * IN and NOT IN subselects. To be able to use all three operations
+ * (UNIONs INTERSECTs and EXCEPTs) in one complex query we have to
+ * translate the queries into Disjunctive Normal Form (DNF). Unfortunately
+ * there is no function 'dnfify' but there is a function 'cnfify'
+ * which produces DNF when we exchange ANDs and ORs before calling
+ * 'cnfify' and exchange them back in the result.
+ *
+ * If an EXCEPT or INTERSECT is present *intersect_present
+ * hands back 'true' */
+Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present)
+{
+ Node *result;
+
+ switch(nodeTag(ptr))
+ {
+ case T_A_Expr:
+ {
+ A_Expr *a = (A_Expr *)ptr;
+
+ switch (a->oper)
+ {
+ case AND:
+ {
+ Expr *expr = makeNode(Expr);
+ Node *lexpr = A_Expr_to_Expr(((A_Expr *)ptr)->lexpr, intersect_present);
+ Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
+
+ *intersect_present = TRUE;
+
+ expr->typeOid = BOOLOID;
+ expr->opType = OR_EXPR;
+ expr->args = makeList(lexpr, rexpr, -1);
+ result = (Node *) expr;
+ break;
+ }
+ case OR:
+ {
+ Expr *expr = makeNode(Expr);
+ Node *lexpr = A_Expr_to_Expr(((A_Expr *)ptr)->lexpr, intersect_present);
+ Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
+
+ expr->typeOid = BOOLOID;
+ expr->opType = AND_EXPR;
+ expr->args = makeList(lexpr, rexpr, -1);
+ result = (Node *) expr;
+ break;
+ }
+ case NOT:
+ {
+ Expr *expr = makeNode(Expr);
+ Node *rexpr = A_Expr_to_Expr(((A_Expr *)ptr)->rexpr, intersect_present);
+
+ expr->typeOid = BOOLOID;
+ expr->opType = NOT_EXPR;
+ expr->args = makeList(rexpr, -1);
+ result = (Node *) expr;
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ {
+ result = ptr;
+ }
+ }
+ return result;
+}