aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y39
-rw-r--r--src/backend/parser/keywords.c4
-rw-r--r--src/backend/parser/parse_expr.c89
3 files changed, 112 insertions, 20 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 33b534f8eff..f2220aa00b9 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 907a26baee6..cfdea14962d 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -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},
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index d93aeb55b5d..1ae340b670e 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -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));