aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2002-07-18 04:41:46 +0000
committerBruce Momjian <bruce@momjian.us>2002-07-18 04:41:46 +0000
commit3e22406ec63b60ed50d3d0c593f9e84b5e1d058b (patch)
tree9cd544d8f473a766e21629227f615bd536d0359d /src/backend/executor/execQual.c
parent7ea5f1d7f16e9771e90c020db93d7e8a9a3b22f5 (diff)
downloadpostgresql-3e22406ec63b60ed50d3d0c593f9e84b5e1d058b.tar.gz
postgresql-3e22406ec63b60ed50d3d0c593f9e84b5e1d058b.zip
Finished the Between patch Christopher started.
Implements between (symmetric / asymmetric) as a node. Executes the left or right expression once, makes a Const out of the resulting Datum and executes the >=, <= portions out of the Const sets. Of course, the parser does a fair amount of preparatory work for this to happen. Rod Taylor
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c112
1 files changed, 110 insertions, 2 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 6bb2b5fa942..4246b44dac0 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.97 2002/07/06 20:16:35 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.98 2002/07/18 04:41:44 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,6 +38,9 @@
#include "executor/execdebug.h"
#include "executor/functions.h"
#include "executor/nodeSubplan.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse.h"
+#include "parser/parse_expr.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fcache.h"
@@ -62,6 +65,8 @@ static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalBetweenExpr(BetweenExpr *btest, ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext,
@@ -1189,6 +1194,104 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
}
/* ----------------------------------------------------------------
+ * ExecEvalBetweenExpr
+ *
+ * Evaluate a BetweenExpr node. Result is
+ * a boolean. If any of the three expression
+ * parameters are NULL, result is NULL.
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalBetweenExpr(BetweenExpr *btest,
+ ExprContext *econtext,
+ bool *isNull,
+ ExprDoneCond *isDone)
+{
+ Datum expr_result;
+ Datum lexpr_result;
+ Datum rexpr_result;
+ bool result = FALSE;
+ Node *expr_const;
+ Node *lexpr_const;
+ Node *rexpr_const;
+
+ /* Evaluate subexpressons and Auto-return if we find a NULL */
+ expr_result = ExecEvalExpr(btest->expr, econtext, isNull, isDone);
+ if (*isNull)
+ return (Datum) 0;
+
+ lexpr_result = ExecEvalExpr(btest->lexpr, econtext, isNull, isDone);
+ if (*isNull)
+ return (Datum) 0;
+
+ rexpr_result = ExecEvalExpr(btest->rexpr, econtext, isNull, isDone);
+ if (*isNull)
+ return (Datum) 0;
+
+ /*
+ * Make a Constant out of our newly found Datums
+ * Types were coerced during transformExpr to be common
+ */
+ expr_const = (Node *) makeConst(btest->typeId, btest->typeLen,
+ expr_result, false,
+ btest->typeByVal, false, true);
+
+ lexpr_const = (Node *) makeConst(btest->typeId, btest->typeLen,
+ lexpr_result, false,
+ btest->typeByVal, false, true);
+
+ rexpr_const = (Node *) makeConst(btest->typeId, btest->typeLen,
+ rexpr_result, false,
+ btest->typeByVal, false, true);
+
+ /*
+ * Test the between case which for the straight forward method.
+ * expr >= lexpr and expr <= rexpr
+ *
+ * Of course, can't use makeA_Expr here without requiring another
+ * transform, so we've already prepared a gthan and lthan operator
+ * set in the parsing stage.
+ */
+ btest->gthan->args = makeList2(expr_const, lexpr_const);
+ if (DatumGetBool(ExecEvalExpr((Node *) btest->gthan,
+ econtext,
+ isNull, isDone)))
+ {
+ btest->lthan->args = makeList2(expr_const, rexpr_const);
+ result = DatumGetBool(ExecEvalExpr((Node *) btest->lthan,
+ econtext,
+ isNull, isDone));
+ }
+
+ /*
+ * If this is a symmetric BETWEEN, we win a second try with the operators
+ * reversed. (a >= min(b,c) and a <= max(b,c))
+ */
+ if (!result && btest->symmetric)
+ {
+ btest->gthan->args = makeList2(expr_const, rexpr_const);
+ if (DatumGetBool(ExecEvalExpr((Node *) btest->gthan,
+ econtext,
+ isNull, isDone)))
+ {
+ btest->lthan->args = makeList2(expr_const, lexpr_const);
+ result = DatumGetBool(ExecEvalExpr((Node *) btest->lthan,
+ econtext,
+ isNull, isDone));
+ }
+ }
+
+ /* Apply NOT as necessary */
+ if (btest->not)
+ result = !result;
+
+ /* We're not returning a null */
+ *isNull = false;
+
+ return (BoolGetDatum(result));
+}
+
+/* ----------------------------------------------------------------
* ExecEvalNullTest
*
* Evaluate a NullTest node.
@@ -1524,6 +1627,12 @@ ExecEvalExpr(Node *expression,
isNull,
isDone);
break;
+ case T_BetweenExpr:
+ retDatum = ExecEvalBetweenExpr((BetweenExpr *) expression,
+ econtext,
+ isNull,
+ isDone);
+ break;
case T_NullTest:
retDatum = ExecEvalNullTest((NullTest *) expression,
econtext,
@@ -1536,7 +1645,6 @@ ExecEvalExpr(Node *expression,
isNull,
isDone);
break;
-
default:
elog(ERROR, "ExecEvalExpr: unknown expression type %d",
nodeTag(expression));