Skip to content

Commit 3e22406

Browse files
committed
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
1 parent 7ea5f1d commit 3e22406

File tree

15 files changed

+619
-35
lines changed

15 files changed

+619
-35
lines changed

src/backend/executor/execQual.c

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.97 2002/07/06 20:16:35 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.98 2002/07/18 04:41:44 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -38,6 +38,9 @@
3838
#include "executor/execdebug.h"
3939
#include "executor/functions.h"
4040
#include "executor/nodeSubplan.h"
41+
#include "nodes/makefuncs.h"
42+
#include "parser/parse.h"
43+
#include "parser/parse_expr.h"
4144
#include "utils/array.h"
4245
#include "utils/builtins.h"
4346
#include "utils/fcache.h"
@@ -62,6 +65,8 @@ static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
6265
static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
6366
static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
6467
bool *isNull, ExprDoneCond *isDone);
68+
static Datum ExecEvalBetweenExpr(BetweenExpr *btest, ExprContext *econtext,
69+
bool *isNull, ExprDoneCond *isDone);
6570
static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
6671
bool *isNull, ExprDoneCond *isDone);
6772
static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext,
@@ -1188,6 +1193,104 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
11881193
return (Datum) 0;
11891194
}
11901195

1196+
/* ----------------------------------------------------------------
1197+
* ExecEvalBetweenExpr
1198+
*
1199+
* Evaluate a BetweenExpr node. Result is
1200+
* a boolean. If any of the three expression
1201+
* parameters are NULL, result is NULL.
1202+
* ----------------------------------------------------------------
1203+
*/
1204+
static Datum
1205+
ExecEvalBetweenExpr(BetweenExpr *btest,
1206+
ExprContext *econtext,
1207+
bool *isNull,
1208+
ExprDoneCond *isDone)
1209+
{
1210+
Datum expr_result;
1211+
Datum lexpr_result;
1212+
Datum rexpr_result;
1213+
bool result = FALSE;
1214+
Node *expr_const;
1215+
Node *lexpr_const;
1216+
Node *rexpr_const;
1217+
1218+
/* Evaluate subexpressons and Auto-return if we find a NULL */
1219+
expr_result = ExecEvalExpr(btest->expr, econtext, isNull, isDone);
1220+
if (*isNull)
1221+
return (Datum) 0;
1222+
1223+
lexpr_result = ExecEvalExpr(btest->lexpr, econtext, isNull, isDone);
1224+
if (*isNull)
1225+
return (Datum) 0;
1226+
1227+
rexpr_result = ExecEvalExpr(btest->rexpr, econtext, isNull, isDone);
1228+
if (*isNull)
1229+
return (Datum) 0;
1230+
1231+
/*
1232+
* Make a Constant out of our newly found Datums
1233+
* Types were coerced during transformExpr to be common
1234+
*/
1235+
expr_const = (Node *) makeConst(btest->typeId, btest->typeLen,
1236+
expr_result, false,
1237+
btest->typeByVal, false, true);
1238+
1239+
lexpr_const = (Node *) makeConst(btest->typeId, btest->typeLen,
1240+
lexpr_result, false,
1241+
btest->typeByVal, false, true);
1242+
1243+
rexpr_const = (Node *) makeConst(btest->typeId, btest->typeLen,
1244+
rexpr_result, false,
1245+
btest->typeByVal, false, true);
1246+
1247+
/*
1248+
* Test the between case which for the straight forward method.
1249+
* expr >= lexpr and expr <= rexpr
1250+
*
1251+
* Of course, can't use makeA_Expr here without requiring another
1252+
* transform, so we've already prepared a gthan and lthan operator
1253+
* set in the parsing stage.
1254+
*/
1255+
btest->gthan->args = makeList2(expr_const, lexpr_const);
1256+
if (DatumGetBool(ExecEvalExpr((Node *) btest->gthan,
1257+
econtext,
1258+
isNull, isDone)))
1259+
{
1260+
btest->lthan->args = makeList2(expr_const, rexpr_const);
1261+
result = DatumGetBool(ExecEvalExpr((Node *) btest->lthan,
1262+
econtext,
1263+
isNull, isDone));
1264+
}
1265+
1266+
/*
1267+
* If this is a symmetric BETWEEN, we win a second try with the operators
1268+
* reversed. (a >= min(b,c) and a <= max(b,c))
1269+
*/
1270+
if (!result && btest->symmetric)
1271+
{
1272+
btest->gthan->args = makeList2(expr_const, rexpr_const);
1273+
if (DatumGetBool(ExecEvalExpr((Node *) btest->gthan,
1274+
econtext,
1275+
isNull, isDone)))
1276+
{
1277+
btest->lthan->args = makeList2(expr_const, lexpr_const);
1278+
result = DatumGetBool(ExecEvalExpr((Node *) btest->lthan,
1279+
econtext,
1280+
isNull, isDone));
1281+
}
1282+
}
1283+
1284+
/* Apply NOT as necessary */
1285+
if (btest->not)
1286+
result = !result;
1287+
1288+
/* We're not returning a null */
1289+
*isNull = false;
1290+
1291+
return (BoolGetDatum(result));
1292+
}
1293+
11911294
/* ----------------------------------------------------------------
11921295
* ExecEvalNullTest
11931296
*
@@ -1524,6 +1627,12 @@ ExecEvalExpr(Node *expression,
15241627
isNull,
15251628
isDone);
15261629
break;
1630+
case T_BetweenExpr:
1631+
retDatum = ExecEvalBetweenExpr((BetweenExpr *) expression,
1632+
econtext,
1633+
isNull,
1634+
isDone);
1635+
break;
15271636
case T_NullTest:
15281637
retDatum = ExecEvalNullTest((NullTest *) expression,
15291638
econtext,
@@ -1536,7 +1645,6 @@ ExecEvalExpr(Node *expression,
15361645
isNull,
15371646
isDone);
15381647
break;
1539-
15401648
default:
15411649
elog(ERROR, "ExecEvalExpr: unknown expression type %d",
15421650
nodeTag(expression));

src/backend/nodes/copyfuncs.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.194 2002/07/16 22:12:19 tgl Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.195 2002/07/18 04:41:44 momjian Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -999,6 +999,32 @@ _copyCaseExpr(CaseExpr *from)
999999
return newnode;
10001000
}
10011001

1002+
/* ----------------
1003+
* _copyBetweenExpr
1004+
* ----------------
1005+
*/
1006+
static BetweenExpr *
1007+
_copyBetweenExpr(BetweenExpr *from)
1008+
{
1009+
BetweenExpr *newnode = makeNode(BetweenExpr);
1010+
1011+
/*
1012+
* copy remainder of node
1013+
*/
1014+
Node_Copy(from, newnode, expr);
1015+
Node_Copy(from, newnode, lexpr);
1016+
Node_Copy(from, newnode, rexpr);
1017+
Node_Copy(from, newnode, lthan);
1018+
Node_Copy(from, newnode, gthan);
1019+
newnode->symmetric = from->symmetric;
1020+
newnode->not = from->not;
1021+
newnode->typeId = from->typeId;
1022+
newnode->typeLen = from->typeLen;
1023+
newnode->typeByVal = from->typeByVal;
1024+
1025+
return newnode;
1026+
}
1027+
10021028
/* ----------------
10031029
* _copyCaseWhen
10041030
* ----------------
@@ -3052,6 +3078,9 @@ copyObject(void *from)
30523078
case T_CaseExpr:
30533079
retval = _copyCaseExpr(from);
30543080
break;
3081+
case T_BetweenExpr:
3082+
retval = _copyBetweenExpr(from);
3083+
break;
30553084
case T_CaseWhen:
30563085
retval = _copyCaseWhen(from);
30573086
break;

src/backend/nodes/equalfuncs.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* Portions Copyright (c) 1994, Regents of the University of California
2121
*
2222
* IDENTIFICATION
23-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.141 2002/07/16 22:12:19 tgl Exp $
23+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.142 2002/07/18 04:41:44 momjian Exp $
2424
*
2525
*-------------------------------------------------------------------------
2626
*/
@@ -1769,6 +1769,33 @@ _equalCaseExpr(CaseExpr *a, CaseExpr *b)
17691769
return true;
17701770
}
17711771

1772+
static bool
1773+
_equalBetweenExpr(BetweenExpr *a, BetweenExpr *b)
1774+
{
1775+
if (!equal(a->expr, b->expr))
1776+
return false;
1777+
if (!equal(a->lexpr, b->lexpr))
1778+
return false;
1779+
if (!equal(a->rexpr, b->rexpr))
1780+
return false;
1781+
if (!equal(a->lthan, b->lthan))
1782+
return false;
1783+
if (!equal(a->gthan, b->gthan))
1784+
return false;
1785+
if (a->symmetric != b->symmetric)
1786+
return false;
1787+
if (a->not != b->not)
1788+
return false;
1789+
if (a->typeId != b->typeId)
1790+
return false;
1791+
if (a->typeLen != b->typeLen)
1792+
return false;
1793+
if (a->typeByVal != b->typeByVal)
1794+
return false;
1795+
1796+
return true;
1797+
}
1798+
17721799
static bool
17731800
_equalCaseWhen(CaseWhen *a, CaseWhen *b)
17741801
{
@@ -2217,6 +2244,9 @@ equal(void *a, void *b)
22172244
case T_CaseExpr:
22182245
retval = _equalCaseExpr(a, b);
22192246
break;
2247+
case T_BetweenExpr:
2248+
retval = _equalBetweenExpr(a, b);
2249+
break;
22202250
case T_CaseWhen:
22212251
retval = _equalCaseWhen(a, b);
22222252
break;

src/backend/nodes/outfuncs.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
66
* Portions Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.163 2002/07/16 22:12:19 tgl Exp $
8+
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.164 2002/07/18 04:41:44 momjian Exp $
99
*
1010
* NOTES
1111
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -1483,6 +1483,38 @@ _outCaseWhen(StringInfo str, CaseWhen *node)
14831483
_outNode(str, node->result);
14841484
}
14851485

1486+
/*
1487+
* BetweenExpr
1488+
*/
1489+
static void
1490+
_outBetweenExpr(StringInfo str, BetweenExpr *node)
1491+
{
1492+
appendStringInfo(str, " BETWEENEXPR :expr ");
1493+
_outNode(str, node->expr);
1494+
1495+
appendStringInfo(str, " :not %s",
1496+
booltostr(node->not));
1497+
1498+
appendStringInfo(str, " :symmetric %s",
1499+
booltostr(node->symmetric));
1500+
1501+
appendStringInfo(str, " :lexpr ");
1502+
_outNode(str, node->lexpr);
1503+
1504+
appendStringInfo(str, " :rexpr ");
1505+
_outNode(str, node->rexpr);
1506+
1507+
appendStringInfo(str, " :gthan ");
1508+
_outNode(str, node->gthan);
1509+
1510+
appendStringInfo(str, " :lthan ");
1511+
_outNode(str, node->lthan);
1512+
1513+
appendStringInfo(str, " :typeid %u :typelen %d :typebyval %s",
1514+
node->typeId, node->typeLen,
1515+
booltostr(node->typeByVal));
1516+
}
1517+
14861518
/*
14871519
* NullTest
14881520
*/
@@ -1767,6 +1799,9 @@ _outNode(StringInfo str, void *obj)
17671799
case T_CaseExpr:
17681800
_outCaseExpr(str, obj);
17691801
break;
1802+
case T_BetweenExpr:
1803+
_outBetweenExpr(str, obj);
1804+
break;
17701805
case T_CaseWhen:
17711806
_outCaseWhen(str, obj);
17721807
break;

src/backend/nodes/readfuncs.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.124 2002/07/04 15:23:54 thomas Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.125 2002/07/18 04:41:45 momjian Exp $
1212
*
1313
* NOTES
1414
* Most of the read functions for plan nodes are tested. (In fact, they
@@ -881,6 +881,53 @@ _readCaseWhen(void)
881881
return local_node;
882882
}
883883

884+
static BetweenExpr *
885+
_readBetweenExpr(void)
886+
{
887+
BetweenExpr *local_node;
888+
char *token;
889+
int length;
890+
891+
local_node = makeNode(BetweenExpr);
892+
893+
token = pg_strtok(&length); /* eat :expr */
894+
local_node->expr = nodeRead(true);
895+
896+
token = pg_strtok(&length); /* eat :not */
897+
token = pg_strtok(&length); /* get not */
898+
local_node->not = strtobool(token);
899+
900+
token = pg_strtok(&length); /* eat :symmetric */
901+
token = pg_strtok(&length); /* get symmetric */
902+
local_node->symmetric = strtobool(token);
903+
904+
token = pg_strtok(&length); /* eat :lexpr */
905+
local_node->lexpr = nodeRead(true);
906+
907+
token = pg_strtok(&length); /* eat :rexpr */
908+
local_node->rexpr = nodeRead(true);
909+
910+
token = pg_strtok(&length); /* eat :gthan */
911+
local_node->gthan = nodeRead(true);
912+
913+
token = pg_strtok(&length); /* eat :lthan */
914+
local_node->lthan = nodeRead(true);
915+
916+
token = pg_strtok(&length); /* eat :typeid */
917+
token = pg_strtok(&length); /* get typeid */
918+
local_node->typeId = atooid(token);
919+
920+
token = pg_strtok(&length); /* eat :typelen */
921+
token = pg_strtok(&length); /* get typelen */
922+
local_node->typeLen = atoui(token);
923+
924+
token = pg_strtok(&length); /* eat :typebyval */
925+
token = pg_strtok(&length); /* get typebyval */
926+
local_node->typeByVal = strtobool(token);
927+
928+
return local_node;
929+
}
930+
884931
/* ----------------
885932
* _readNullTest
886933
*
@@ -2132,6 +2179,8 @@ parsePlanString(void)
21322179
return_value = _readNullTest();
21332180
else if (length == 11 && strncmp(token, "BOOLEANTEST", length) == 0)
21342181
return_value = _readBooleanTest();
2182+
else if (length == 11 && strncmp(token, "BETWEENEXPR", length) == 0)
2183+
return_value = _readBetweenExpr();
21352184
else
21362185
elog(ERROR, "badly formatted planstring \"%.10s\"...", token);
21372186

0 commit comments

Comments
 (0)