mirror of
https://github.com/postgres/postgres.git
synced 2025-08-22 21:53:06 +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:
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.342 2002/07/18 02:02:30 ishii Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.343 2002/07/18 04:41:45 momjian Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -235,7 +235,7 @@ static void doNegateFloat(Value *v);
|
||||
|
||||
%type <list> extract_list, overlay_list, position_list
|
||||
%type <list> substr_list, trim_list
|
||||
%type <ival> opt_interval
|
||||
%type <ival> opt_interval, opt_symmetry
|
||||
%type <node> overlay_placing, substr_from, substr_for
|
||||
|
||||
%type <boolean> opt_instead, opt_cursor
|
||||
@@ -320,7 +320,7 @@ static void doNegateFloat(Value *v);
|
||||
/* ordinary key words in alphabetical order */
|
||||
%token <keyword> ABORT_TRANS, ABSOLUTE, ACCESS, ACTION, ADD, AFTER,
|
||||
AGGREGATE, ALL, ALTER, ANALYSE, ANALYZE, AND, ANY, AS, ASC,
|
||||
ASSERTION, ASSIGNMENT, AT, AUTHORIZATION,
|
||||
ASSERTION, ASSIGNMENT, ASYMMETRIC, AT, AUTHORIZATION,
|
||||
|
||||
BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BIGINT, BINARY, BIT, BOTH,
|
||||
BOOLEAN, BY,
|
||||
@@ -379,7 +379,7 @@ static void doNegateFloat(Value *v);
|
||||
SERIALIZABLE, SESSION, SESSION_USER, SET, SETOF, SHARE,
|
||||
SHOW, SIMILAR, SIMPLE, SMALLINT, SOME, STABLE, START, STATEMENT,
|
||||
STATISTICS, STDIN, STDOUT, STORAGE, STRICT, SUBSTRING,
|
||||
SYSID,
|
||||
SYMMETRIC, SYSID,
|
||||
|
||||
TABLE, TEMP, TEMPLATE, TEMPORARY, THEN, TIME, TIMESTAMP,
|
||||
TO, TOAST, TRAILING, TRANSACTION, TREAT, TRIGGER, TRIM, TRUE_P,
|
||||
@@ -5500,17 +5500,25 @@ a_expr: c_expr { $$ = $1; }
|
||||
}
|
||||
| a_expr IS DISTINCT FROM a_expr %prec DISTINCT
|
||||
{ $$ = (Node *) makeSimpleA_Expr(DISTINCT, "=", $1, $5); }
|
||||
| a_expr BETWEEN b_expr AND b_expr %prec BETWEEN
|
||||
| a_expr BETWEEN opt_symmetry b_expr AND b_expr %prec BETWEEN
|
||||
{
|
||||
$$ = (Node *) makeA_Expr(AND, NIL,
|
||||
(Node *) makeSimpleA_Expr(OP, ">=", $1, $3),
|
||||
(Node *) makeSimpleA_Expr(OP, "<=", $1, $5));
|
||||
BetweenExpr *n = makeNode(BetweenExpr);
|
||||
n->expr = $1;
|
||||
n->symmetric = $3;
|
||||
n->lexpr = $4;
|
||||
n->rexpr = $6;
|
||||
n->not = false;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| a_expr NOT BETWEEN b_expr AND b_expr %prec BETWEEN
|
||||
| a_expr NOT BETWEEN opt_symmetry b_expr AND b_expr %prec BETWEEN
|
||||
{
|
||||
$$ = (Node *) makeA_Expr(OR, NIL,
|
||||
(Node *) makeSimpleA_Expr(OP, "<", $1, $4),
|
||||
(Node *) makeSimpleA_Expr(OP, ">", $1, $6));
|
||||
BetweenExpr *n = makeNode(BetweenExpr);
|
||||
n->expr = $1;
|
||||
n->symmetric = $4;
|
||||
n->lexpr = $5;
|
||||
n->rexpr = $7;
|
||||
n->not = true;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| a_expr IN_P in_expr
|
||||
{
|
||||
@@ -5582,6 +5590,11 @@ a_expr: c_expr { $$ = $1; }
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
opt_symmetry: SYMMETRIC { $$ = TRUE; }
|
||||
| ASYMMETRIC { $$ = FALSE; }
|
||||
| /* EMPTY */ { $$ = FALSE; }
|
||||
;
|
||||
|
||||
/*
|
||||
* Restricted expressions
|
||||
*
|
||||
@@ -6919,6 +6932,7 @@ reserved_keyword:
|
||||
| ANY
|
||||
| AS
|
||||
| ASC
|
||||
| ASYMMETRIC
|
||||
| BOTH
|
||||
| CASE
|
||||
| CAST
|
||||
@@ -6969,6 +6983,7 @@ reserved_keyword:
|
||||
| SELECT
|
||||
| SESSION_USER
|
||||
| SOME
|
||||
| SYMMETRIC
|
||||
| TABLE
|
||||
| THEN
|
||||
| TO
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.119 2002/07/11 07:39:26 ishii Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.120 2002/07/18 04:41:45 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -45,6 +45,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"asc", ASC},
|
||||
{"assertion", ASSERTION},
|
||||
{"assignment", ASSIGNMENT},
|
||||
{"asymmetric", ASYMMETRIC},
|
||||
{"at", AT},
|
||||
{"authorization", AUTHORIZATION},
|
||||
{"backward", BACKWARD},
|
||||
@@ -272,6 +273,7 @@ static const ScanKeyword ScanKeywords[] = {
|
||||
{"storage", STORAGE},
|
||||
{"strict", STRICT},
|
||||
{"substring", SUBSTRING},
|
||||
{"symmetric", SYMMETRIC},
|
||||
{"sysid", SYSID},
|
||||
{"table", TABLE},
|
||||
{"temp", TEMP},
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.121 2002/07/06 20:16:36 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.122 2002/07/18 04:41:45 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -69,11 +69,8 @@ parse_expr_init(void)
|
||||
* here.
|
||||
*
|
||||
* NOTE: there are various cases in which this routine will get applied to
|
||||
* an already-transformed expression. Some examples:
|
||||
* 1. At least one construct (BETWEEN/AND) puts the same nodes
|
||||
* into two branches of the parse tree; hence, some nodes
|
||||
* are transformed twice.
|
||||
* 2. Another way it can happen is that coercion of an operator or
|
||||
* an already-transformed expression. An examples:
|
||||
* - Another way it can happen is that coercion of an operator or
|
||||
* function argument to the required type (via coerce_type())
|
||||
* can apply transformExpr to an already-transformed subexpression.
|
||||
* An example here is "SELECT count(*) + 1.0 FROM table".
|
||||
@@ -588,6 +585,82 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
result = expr;
|
||||
break;
|
||||
}
|
||||
case T_BetweenExpr:
|
||||
{
|
||||
BetweenExpr *b = (BetweenExpr *) expr;
|
||||
List *typeIds = NIL;
|
||||
HeapTuple tup;
|
||||
Form_pg_operator opform;
|
||||
|
||||
/* Transform the expressions */
|
||||
b->expr = transformExpr(pstate, b->expr);
|
||||
b->lexpr = transformExpr(pstate, b->lexpr);
|
||||
b->rexpr = transformExpr(pstate, b->rexpr);
|
||||
|
||||
/* Find coercion type for all 3 entities */
|
||||
typeIds = lappendi(typeIds, exprType(b->expr));
|
||||
typeIds = lappendi(typeIds, exprType(b->lexpr));
|
||||
typeIds = lappendi(typeIds, exprType(b->rexpr));
|
||||
b->typeId = select_common_type(typeIds, "TransformExpr");
|
||||
|
||||
/* Additional type information */
|
||||
b->typeLen = get_typlen(b->typeId);
|
||||
b->typeByVal = get_typbyval(b->typeId);
|
||||
|
||||
/* Coerce the three expressions to the type */
|
||||
b->expr = coerce_to_common_type(pstate, b->expr,
|
||||
b->typeId,
|
||||
"TransformExpr");
|
||||
|
||||
b->lexpr = coerce_to_common_type(pstate, b->lexpr,
|
||||
b->typeId,
|
||||
"TransformExpr");
|
||||
|
||||
b->rexpr = coerce_to_common_type(pstate, b->rexpr,
|
||||
b->typeId,
|
||||
"TransformExpr");
|
||||
|
||||
/* Build the >= operator */
|
||||
tup = oper(makeList1(makeString(">=")),
|
||||
b->typeId, b->typeId, false);
|
||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||
|
||||
/* Triple check our types */
|
||||
if (b->typeId != opform->oprright || b->typeId != opform->oprleft)
|
||||
elog(ERROR, "transformExpr: Unable to find appropriate"
|
||||
" operator for between operation");
|
||||
|
||||
b->gthan = makeNode(Expr);
|
||||
b->gthan->typeOid = opform->oprresult;
|
||||
b->gthan->opType = OP_EXPR;
|
||||
b->gthan->oper = (Node *) makeOper(oprid(tup), /* opno */
|
||||
oprfuncid(tup), /* opid */
|
||||
opform->oprresult, /* opresulttype */
|
||||
get_func_retset(opform->oprcode));/* opretset */
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
/* Build the equation for <= operator */
|
||||
tup = oper(makeList1(makeString("<=")),
|
||||
b->typeId, b->typeId, false);
|
||||
opform = (Form_pg_operator) GETSTRUCT(tup);
|
||||
|
||||
/* Triple check the types */
|
||||
if (b->typeId != opform->oprright || b->typeId != opform->oprleft)
|
||||
elog(ERROR, "transformExpr: Unable to find appropriate"
|
||||
" operator for between operation");
|
||||
|
||||
b->lthan = makeNode(Expr);
|
||||
b->lthan->typeOid = opform->oprresult;
|
||||
b->lthan->opType = OP_EXPR;
|
||||
b->lthan->oper = (Node *) makeOper(oprid(tup), /* opno */
|
||||
oprfuncid(tup), /* opid */
|
||||
opform->oprresult, /* opresulttype */
|
||||
get_func_retset(opform->oprcode));/* opretset */
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
result = expr;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Quietly accept node types that may be presented when we are
|
||||
@@ -609,7 +682,6 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
result = (Node *) expr;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* should not reach here */
|
||||
elog(ERROR, "transformExpr: does not know how to transform node %d"
|
||||
@@ -890,6 +962,9 @@ exprType(Node *expr)
|
||||
case T_BooleanTest:
|
||||
type = BOOLOID;
|
||||
break;
|
||||
case T_BetweenExpr:
|
||||
type = BOOLOID;
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "exprType: Do not know how to get type for %d node",
|
||||
nodeTag(expr));
|
||||
|
Reference in New Issue
Block a user