mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
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
This commit is contained in:
@ -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,
|
||||
@ -1188,6 +1193,104 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* 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
|
||||
*
|
||||
@ -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));
|
||||
|
Reference in New Issue
Block a user