diff options
author | Bruce Momjian <bruce@momjian.us> | 2002-07-18 04:41:46 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2002-07-18 04:41:46 +0000 |
commit | 3e22406ec63b60ed50d3d0c593f9e84b5e1d058b (patch) | |
tree | 9cd544d8f473a766e21629227f615bd536d0359d /src/backend/executor/execQual.c | |
parent | 7ea5f1d7f16e9771e90c020db93d7e8a9a3b22f5 (diff) | |
download | postgresql-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.c | 112 |
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)); |