Обсуждение: BETWEEN SYMMETRIC

Поиск
Список
Период
Сортировка

BETWEEN SYMMETRIC

От
"Christopher Kings-Lynne"
Дата:
Hi,

Based on recent discussion, I went thru and got together the work I'd done
on the BETWEEN node.  It's not as far along as I thought.  I ran into a few
hurdles:

* ExecEvalBetweenExpr is probably beyond my powers - I've done my best and
marked my hopelessness with '@@' symbols.  I don't know how to actually
evaluate the node properly, I don't know how to check that all the 3 types
are coercible to the same type and I don't know how to make it take rowvars
(sic?)instead of scalars, as per spec.

Copy and Equal are done, I think.

Out I've guessed at how to do it based on other examples, but I need
feedback.  Read I haven't done at all cos I don't quite understand when/why
it's used or how to do it.

The grammar has been updated to use the new BetweenExpr node, with new
syntax options.

The new keywords have been added in the relevant places, and they are
reserved.

nodes.h and parsenodes.h are aware of the new node.

I have added a full regression test that I used in my old gram.y only
implementation, that didn't use a new node - it will be helpful!

Where do we go from here?

Chris


Re: BETWEEN SYMMETRIC

От
Rod Taylor
Дата:
Kinda like the blind leading the blind, but:

I'm assuming you will need to do something similar to what you did in
the previous version in gram.y.  That is, create an expression node with
the appropriate equations and pass that through ExecEvalExpr().

You can probably return the true or false from ExecEvalExpr directly for
the between case, and simply invert for the not null case.  Don't forget
about the NULL.

See ExecEvalNull, ExecEvalBool, ExecEvalAnd, ExecEvalOr tests for
example calls.


On Thu, 2002-06-27 at 06:31, Christopher Kings-Lynne wrote:
> Hi,
> 
> Based on recent discussion, I went thru and got together the work I'd done
> on the BETWEEN node.  It's not as far along as I thought.  I ran into a few
> hurdles:
> 
> * ExecEvalBetweenExpr is probably beyond my powers - I've done my best and
> marked my hopelessness with '@@' symbols.  I don't know how to actually
> evaluate the node properly, I don't know how to check that all the 3 types
> are coercible to the same type and I don't know how to make it take rowvars
> (sic?)instead of scalars, as per spec.
> 
> Copy and Equal are done, I think.
> 
> Out I've guessed at how to do it based on other examples, but I need
> feedback.  Read I haven't done at all cos I don't quite understand when/why
> it's used or how to do it.
> 
> The grammar has been updated to use the new BetweenExpr node, with new
> syntax options.
> 
> The new keywords have been added in the relevant places, and they are
> reserved.
> 
> nodes.h and parsenodes.h are aware of the new node.
> 
> I have added a full regression test that I used in my old gram.y only
> implementation, that didn't use a new node - it will be helpful!
> 
> Where do we go from here?
> 
> Chris
> 
> ----
> 

> ? GNUmakefile
> ? between.diff.txt
> ? config.log
> ? config.status
> ? contrib/spi/.deps
> ? src/Makefile.global
> ? src/backend/postgres
> ? src/backend/access/common/.deps
> ? src/backend/access/gist/.deps
> ? src/backend/access/hash/.deps
> ? src/backend/access/heap/.deps
> ? src/backend/access/index/.deps
> ? src/backend/access/nbtree/.deps
> ? src/backend/access/rtree/.deps
> ? src/backend/access/transam/.deps
> ? src/backend/bootstrap/.deps
> ? src/backend/catalog/.deps
> ? src/backend/catalog/postgres.bki
> ? src/backend/catalog/postgres.description
> ? src/backend/commands/.deps
> ? src/backend/commands/tablecmds.c.mystuff
> ? src/backend/executor/.deps
> ? src/backend/lib/.deps
> ? src/backend/libpq/.deps
> ? src/backend/main/.deps
> ? src/backend/nodes/.deps
> ? src/backend/optimizer/geqo/.deps
> ? src/backend/optimizer/path/.deps
> ? src/backend/optimizer/plan/.deps
> ? src/backend/optimizer/prep/.deps
> ? src/backend/optimizer/util/.deps
> ? src/backend/parser/.deps
> ? src/backend/port/.deps
> ? src/backend/postmaster/.deps
> ? src/backend/regex/.deps
> ? src/backend/rewrite/.deps
> ? src/backend/storage/buffer/.deps
> ? src/backend/storage/file/.deps
> ? src/backend/storage/freespace/.deps
> ? src/backend/storage/ipc/.deps
> ? src/backend/storage/large_object/.deps
> ? src/backend/storage/lmgr/.deps
> ? src/backend/storage/page/.deps
> ? src/backend/storage/smgr/.deps
> ? src/backend/tcop/.deps
> ? src/backend/utils/.deps
> ? src/backend/utils/adt/.deps
> ? src/backend/utils/cache/.deps
> ? src/backend/utils/error/.deps
> ? src/backend/utils/fmgr/.deps
> ? src/backend/utils/hash/.deps
> ? src/backend/utils/init/.deps
> ? src/backend/utils/mb/.deps
> ? src/backend/utils/misc/.deps
> ? src/backend/utils/mmgr/.deps
> ? src/backend/utils/sort/.deps
> ? src/backend/utils/time/.deps
> ? src/bin/initdb/initdb
> ? src/bin/initlocation/initlocation
> ? src/bin/ipcclean/ipcclean
> ? src/bin/pg_config/pg_config
> ? src/bin/pg_ctl/pg_ctl
> ? src/bin/pg_dump/.deps
> ? src/bin/pg_dump/pg_dump
> ? src/bin/pg_dump/pg_dumpall
> ? src/bin/pg_dump/pg_restore
> ? src/bin/pg_encoding/.deps
> ? src/bin/pg_encoding/pg_encoding
> ? src/bin/pg_id/.deps
> ? src/bin/pg_id/pg_id
> ? src/bin/psql/.deps
> ? src/bin/psql/psql
> ? src/bin/scripts/createlang
> ? src/include/pg_config.h
> ? src/include/stamp-h
> ? src/interfaces/ecpg/lib/.deps
> ? src/interfaces/ecpg/lib/libecpg.so.3
> ? src/interfaces/ecpg/preproc/.deps
> ? src/interfaces/ecpg/preproc/ecpg
> ? src/interfaces/libpgeasy/.deps
> ? src/interfaces/libpgeasy/libpgeasy.so.2
> ? src/interfaces/libpq/.deps
> ? src/interfaces/libpq/libpq.so.2
> ? src/interfaces/libpq++/.deps
> ? src/interfaces/libpq++/libpq++.so.4
> ? src/pl/plpgsql/src/.deps
> ? src/pl/plpgsql/src/libplpgsql.so.1
> ? src/test/regress/.deps
> ? src/test/regress/log
> ? src/test/regress/pg_regress
> ? src/test/regress/regression.diffs
> ? src/test/regress/regression.out
> ? src/test/regress/results
> ? src/test/regress/tmp_check
> ? src/test/regress/expected/constraints.out
> ? src/test/regress/expected/copy.out
> ? src/test/regress/expected/create_function_1.out
> ? src/test/regress/expected/create_function_2.out
> ? src/test/regress/expected/misc.out
> ? src/test/regress/sql/constraints.sql
> ? src/test/regress/sql/copy.sql
> ? src/test/regress/sql/create_function_1.sql
> ? src/test/regress/sql/create_function_2.sql
> ? src/test/regress/sql/misc.sql
> Index: src/backend/executor/execQual.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/executor/execQual.c,v
> retrieving revision 1.94
> diff -c -r1.94 execQual.c
> *** src/backend/executor/execQual.c    2002/06/20 20:29:27    1.94
> --- src/backend/executor/execQual.c    2002/06/27 10:27:30
> ***************
> *** 60,65 ****
> --- 60,67 ----
>   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,
> ***************
> *** 1110,1115 ****
> --- 1112,1182 ----
>   }
>   
>   /* ----------------------------------------------------------------
> +  *        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;
> + 
> +     /* Evaluate subexpressons and test for NULL parameters */
> +     expr_result = ExecEvalExpr(btest->expr, econtext, isNull, isDone);
> +     if (*isNull) {
> +         *isNull = true;
> +         return (Datum) 0;
> +     }
> +     lexpr_result = ExecEvalExpr(btest->lexpr, econtext, isNull, isDone);
> +     if (*isNull) {
> +         *isNull = true;
> +         return (Datum) 0;
> +     }
> +     rexpr_result = ExecEvalExpr(btest->rexpr, econtext, isNull, isDone);
> +     if (*isNull) {
> +         *isNull = true;
> +         return (Datum) 0;
> +     }
> + 
> +     /* Make sure return value is what we think it is */
> +     *isNull = false;
> + 
> +     /* Now, depending on the symmetry, evaluate the
> +        BETWEEN expression */
> + 
> +     if (btest->symmetric)
> +     {
> +         /* @@ This is pseudocode - how do I copare the results? @@ */
> +         if ((expr_result >= lexpr_result &&
> +             expr_result <= rexpr_result) ||
> +             (expr_result >= rexpr_result &&
> +             expr_result <= lexpr_result))
> +         {
> +             return BoolGetDatum(true);
> +         }
> +         else
> +             return BoolGetDatum(false);
> +     }
> +     else {
> +         if (expr_result >= lexpr_result &&
> +             expr_result <= rexpr_result)
> +         {
> +             return BoolGetDatum(true);
> +         }
> +         else
> +             return BoolGetDatum(false);
> +     }
> + }
> + 
> + /* ----------------------------------------------------------------
>    *        ExecEvalNullTest
>    *
>    *        Evaluate a NullTest node.
> ***************
> *** 1397,1402 ****
> --- 1464,1475 ----
>                                       econtext,
>                                       isNull,
>                                       isDone);
> +             break;
> +         case T_BetweenExpr:
> +             retDatum = ExecEvalBetweenExpr((BetweenExpr *) expression,
> +                                         econtext,
> +                                         isNull,
> +                                         isDone);
>               break;
>           case T_NullTest:
>               retDatum = ExecEvalNullTest((NullTest *) expression,
> Index: src/backend/nodes/copyfuncs.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
> retrieving revision 1.191
> diff -c -r1.191 copyfuncs.c
> *** src/backend/nodes/copyfuncs.c    2002/06/20 20:29:29    1.191
> --- src/backend/nodes/copyfuncs.c    2002/06/27 10:27:31
> ***************
> *** 1000,1005 ****
> --- 1000,1025 ----
>   }
>   
>   /* ----------------
> +  *         _copyBetweenExpr
> +  * ----------------
> +  */
> + static BetweenExpr *
> + _copyBetweenExpr(BetweenExpr *from)
> + {
> +     BetweenExpr *newnode = makeNode(BetweenExpr);
> + 
> +     /*
> +      * copy remainder of node
> +      */
> +     Node_Copy(from, newnode, expr);
> +     newnode->symmetric = from->symmetric;
> +     Node_Copy(from, newnode, lexpr);
> +     Node_Copy(from, newnode, rexpr);
> + 
> +     return newnode;
> + }
> + 
> + /* ----------------
>    *        _copyCaseWhen
>    * ----------------
>    */
> ***************
> *** 3043,3048 ****
> --- 3063,3071 ----
>               break;
>           case T_CaseExpr:
>               retval = _copyCaseExpr(from);
> +             break;
> +         case T_BetweenExpr:
> +             retval = _copyBetweenExpr(from);
>               break;
>           case T_CaseWhen:
>               retval = _copyCaseWhen(from);
> Index: src/backend/nodes/equalfuncs.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
> retrieving revision 1.138
> diff -c -r1.138 equalfuncs.c
> *** src/backend/nodes/equalfuncs.c    2002/06/20 20:29:29    1.138
> --- src/backend/nodes/equalfuncs.c    2002/06/27 10:27:31
> ***************
> *** 1752,1757 ****
> --- 1752,1772 ----
>   }
>   
>   static bool
> + _equalBetweenExpr(BetweenExpr *a, BetweenExpr *b)
> + {
> +       if (!equal(a->expr, b->expr))
> +               return false;
> +       if (a->symmetric != b->symmetric)
> +               return false;
> +       if (!equal(a->lexpr, b->lexpr))
> +               return false;
> +       if (!equal(a->rexpr, b->rexpr))
> +               return false;
> + 
> +       return true;
> + }
> + 
> + static bool
>   _equalCaseWhen(CaseWhen *a, CaseWhen *b)
>   {
>       if (!equal(a->expr, b->expr))
> ***************
> *** 2198,2203 ****
> --- 2213,2221 ----
>               break;
>           case T_CaseExpr:
>               retval = _equalCaseExpr(a, b);
> +             break;
> +         case T_BetweenExpr:
> +             retval = _equalBetweenExpr(a, b);
>               break;
>           case T_CaseWhen:
>               retval = _equalCaseWhen(a, b);
> Index: src/backend/nodes/outfuncs.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/nodes/outfuncs.c,v
> retrieving revision 1.160
> diff -c -r1.160 outfuncs.c
> *** src/backend/nodes/outfuncs.c    2002/06/20 20:29:29    1.160
> --- src/backend/nodes/outfuncs.c    2002/06/27 10:27:32
> ***************
> *** 1466,1471 ****
> --- 1466,1494 ----
>       _outNode(str, node->defresult);
>   }
>   
> + /*
> +  *     BetweenExpr
> +  */
> + static void
> + _outBetweenExpr(StringInfo str, BetweenExpr *node)
> + {
> +     appendStringInfo(str, " :expr ");
> +     _outNode(str, node->expr);
> + 
> +     appendStringInfo(str, " BETWEEN ");
> +     if (node->symmetric)
> +         appendStringInfo(str, "SYMMETRIC ");
> +     /* We don't write out ASYMMETRIC, as it's the default */
> + 
> +     appendStringInfo(str, " :lexpr ");
> +     _outNode(str, node->lexpr);
> + 
> +     appendStringInfo(str, " AND ");
> + 
> +     appendStringInfo(str, " :rexpr ");
> +     _outNode(str, node->rexpr);
> + }
> + 
>   static void
>   _outCaseWhen(StringInfo str, CaseWhen *node)
>   {
> ***************
> *** 1759,1764 ****
> --- 1782,1790 ----
>                   break;
>               case T_CaseExpr:
>                   _outCaseExpr(str, obj);
> +                 break;
> +             case T_BetweenExpr:
> +                 _outBetweenExpr(str, obj);
>                   break;
>               case T_CaseWhen:
>                   _outCaseWhen(str, obj);
> Index: src/backend/parser/gram.y
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
> retrieving revision 2.334
> diff -c -r2.334 gram.y
> *** src/backend/parser/gram.y    2002/06/22 02:04:45    2.334
> --- src/backend/parser/gram.y    2002/06/27 10:27:35
> ***************
> *** 234,240 ****
>   
>   %type <list>    extract_list, overlay_list, position_list
>   %type <list>    substr_list, trim_list
> ! %type <ival>    opt_interval
>   %type <node>    overlay_placing, substr_from, substr_for
>   
>   %type <boolean> opt_instead, opt_cursor
> --- 234,240 ----
>   
>   %type <list>    extract_list, overlay_list, position_list
>   %type <list>    substr_list, trim_list
> ! %type <ival>    opt_interval, opt_symmetry
>   %type <node>    overlay_placing, substr_from, substr_for
>   
>   %type <boolean> opt_instead, opt_cursor
> ***************
> *** 321,327 ****
>   /* 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,
>   
>       BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BIGINT, BINARY, BIT, BOTH,
>       BOOLEAN, BY,
> --- 321,327 ----
>   /* 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, ASYMMETRIC, AT, AUTHORIZATION,
>   
>       BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BIGINT, BINARY, BIT, BOTH,
>       BOOLEAN, BY,
> ***************
> *** 380,386 ****
>       SERIALIZABLE, SESSION, SESSION_USER, SET, SETOF, SHARE,
>       SHOW, SIMILAR, SIMPLE, SMALLINT, SOME, STABLE, START, STATEMENT,
>       STATISTICS, STDIN, STDOUT, STORAGE, STRICT, SUBSTRING,
> !     SYSID,
>   
>       TABLE, TEMP, TEMPLATE, TEMPORARY, THEN, TIME, TIMESTAMP,
>       TO, TOAST, TRAILING, TRANSACTION, TRIGGER, TRIM, TRUE_P,
> --- 380,386 ----
>       SERIALIZABLE, SESSION, SESSION_USER, SET, SETOF, SHARE,
>       SHOW, SIMILAR, SIMPLE, SMALLINT, SOME, STABLE, START, STATEMENT,
>       STATISTICS, STDIN, STDOUT, STORAGE, STRICT, SUBSTRING,
> !     SYMMETRIC, SYSID,
>   
>       TABLE, TEMP, TEMPLATE, TEMPORARY, THEN, TIME, TIMESTAMP,
>       TO, TOAST, TRAILING, TRANSACTION, TRIGGER, TRIM, TRUE_P,
> ***************
> *** 5433,5449 ****
>                       b->booltesttype = IS_NOT_UNKNOWN;
>                       $$ = (Node *)b;
>                   }
> !             | a_expr BETWEEN b_expr AND b_expr            %prec BETWEEN
>                   {
> !                     $$ = (Node *) makeA_Expr(AND, NIL,
> !                         (Node *) makeSimpleA_Expr(OP, ">=", $1, $3),
> !                         (Node *) makeSimpleA_Expr(OP, "<=", $1, $5));
> !                 }
> !             | a_expr NOT BETWEEN b_expr AND b_expr        %prec BETWEEN
> !                 {
> !                     $$ = (Node *) makeA_Expr(OR, NIL,
> !                         (Node *) makeSimpleA_Expr(OP, "<", $1, $4),
> !                         (Node *) makeSimpleA_Expr(OP, ">", $1, $6));
>                   }
>               | a_expr IN_P in_expr
>                   {
> --- 5433,5446 ----
>                       b->booltesttype = IS_NOT_UNKNOWN;
>                       $$ = (Node *)b;
>                   }
> !             | a_expr BETWEEN opt_symmetry b_expr AND b_expr            %prec BETWEEN
>                   {
> !                     BetweenExpr *n = makeNode(BetweenExpr);
> !                     n->expr = $1;
> !                     n->symmetric = $3;
> !                     n->lexpr = $4;
> !                     n->rexpr = $6;
> !                     $$ = (Node *)n;
>                   }
>               | a_expr IN_P in_expr
>                   {
> ***************
> *** 5519,5524 ****
> --- 5516,5526 ----
>                   { $$ = $1; }
>           ;
>   
> + opt_symmetry:     SYMMETRIC                { $$ = TRUE; }
> +         | ASYMMETRIC                { $$ = FALSE; }
> +         | /* EMPTY */                { $$ = FALSE; /* default */ }
> +         ;
> + 
>   /*
>    * Restricted expressions
>    *
> ***************
> *** 6844,6849 ****
> --- 6846,6852 ----
>               | ANY
>               | AS
>               | ASC
> +             | ASYMMETRIC
>               | BOTH
>               | CASE
>               | CAST
> ***************
> *** 6868,6882 ****
>               | FOR
>               | FOREIGN
>               | FROM
> !             | GRANT
> !             | GROUP_P
> !             | HAVING
> !             | INITIALLY
> !             | INTERSECT
> !             | INTO
> !             | LEADING
> !             | LIMIT
> !             | LOCALTIME
>               | LOCALTIMESTAMP
>               | NEW
>               | NOT
> --- 6871,6885 ----
>               | FOR
>               | FOREIGN
>               | FROM
> !             | GRANT 
> !             | GROUP_P 
> !             | HAVING 
> !             | INITIALLY 
> !             | INTERSECT 
> !             | INTO 
> !             | LEADING 
> !             | LIMIT 
> !             | LOCALTIME 
>               | LOCALTIMESTAMP
>               | NEW
>               | NOT
> ***************
> *** 6894,6899 ****
> --- 6897,6903 ----
>               | SELECT
>               | SESSION_USER
>               | SOME
> +             | SYMMETRIC
>               | TABLE
>               | THEN
>               | TO
> Index: src/backend/parser/keywords.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v
> retrieving revision 1.117
> diff -c -r1.117 keywords.c
> *** src/backend/parser/keywords.c    2002/06/22 02:04:45    1.117
> --- src/backend/parser/keywords.c    2002/06/27 10:27:35
> ***************
> *** 45,50 ****
> --- 45,51 ----
>       {"asc", ASC},
>       {"assertion", ASSERTION},
>       {"assignment", ASSIGNMENT},
> +     {"asymmetric", ASYMMETRIC},
>       {"at", AT},
>       {"authorization", AUTHORIZATION},
>       {"backward", BACKWARD},
> ***************
> *** 271,276 ****
> --- 272,278 ----
>       {"storage", STORAGE},
>       {"strict", STRICT},
>       {"substring", SUBSTRING},
> +     {"symmetric", SYMMETRIC},
>       {"sysid", SYSID},
>       {"table", TABLE},
>       {"temp", TEMP},
> Index: src/include/nodes/nodes.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v
> retrieving revision 1.109
> diff -c -r1.109 nodes.h
> *** src/include/nodes/nodes.h    2002/06/20 20:29:51    1.109
> --- src/include/nodes/nodes.h    2002/06/27 10:27:36
> ***************
> *** 225,230 ****
> --- 225,231 ----
>       T_GroupClause,
>       T_NullTest,
>       T_BooleanTest,
> +     T_BetweenExpr,
>       T_CaseExpr,
>       T_CaseWhen,
>       T_FkConstraint,
> Index: src/include/nodes/parsenodes.h
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
> retrieving revision 1.182
> diff -c -r1.182 parsenodes.h
> *** src/include/nodes/parsenodes.h    2002/06/20 20:29:51    1.182
> --- src/include/nodes/parsenodes.h    2002/06/27 10:27:37
> ***************
> *** 174,179 ****
> --- 174,192 ----
>   } A_Const;
>   
>   /*
> +  * BetweenExpr - an SQL99 BETWEEN expression
> +  */
> + 
> + typedef struct BetweenExpr
> + {
> +     NodeTag        type;
> +     Node        *expr;            /* Expression to check */
> +     int        symmetric;        /* True if SYMMETRIC, false if ASYMMETRIC */
> +     Node        *lexpr;            /* First bound */
> +     Node        *rexpr;            /* Second bound */
> + } BetweenExpr;
> + 
> + /*
>    * TypeCast - a CAST expression
>    *
>    * NOTE: for mostly historical reasons, A_Const parsenodes contain
> Index: src/test/regress/expected/select.out
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/select.out,v
> retrieving revision 1.10
> diff -c -r1.10 select.out
> *** src/test/regress/expected/select.out    2001/07/16 05:07:00    1.10
> --- src/test/regress/expected/select.out    2002/06/27 10:27:38
> ***************
> *** 430,432 ****
> --- 430,579 ----
>    mary    |   8
>   (58 rows)
>   
> + -- 
> + -- Test between syntax
> + --
> + SELECT 2 BETWEEN 1 AND 3;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT 2 BETWEEN 3 AND 1;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT 2 BETWEEN ASYMMETRIC 1 AND 3;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT 2 BETWEEN ASYMMETRIC 3 AND 1;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT 2 BETWEEN SYMMETRIC 1 AND 3;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT 2 BETWEEN SYMMETRIC 3 AND 1;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT 2 NOT BETWEEN 1 AND 3;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT 2 NOT BETWEEN 3 AND 1;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT 2 NOT BETWEEN ASYMMETRIC 1 AND 3;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT 2 NOT BETWEEN ASYMMETRIC 3 AND 1;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT 2 NOT BETWEEN SYMMETRIC 1 AND 3;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT 2 NOT BETWEEN SYMMETRIC 3 AND 1;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT -4 BETWEEN -1 AND -3;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT -4 BETWEEN -3 AND -1;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT -4 BETWEEN ASYMMETRIC -1 AND -3;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT -4 BETWEEN ASYMMETRIC -3 AND -1;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT -4 BETWEEN SYMMETRIC -1 AND -3;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT -4 BETWEEN SYMMETRIC -3 AND -1;
> +  ?column? 
> + ----------
> +  f
> + (1 row)
> + 
> + SELECT -4 NOT BETWEEN -1 AND -3;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT -4 NOT BETWEEN -3 AND -1;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT -4 NOT BETWEEN ASYMMETRIC -1 AND -3;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT -4 NOT BETWEEN ASYMMETRIC -3 AND -1;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT -4 NOT BETWEEN SYMMETRIC -1 AND -3;
> +  ?column? 
> + ----------
> +  t
> + (1 row)
> + 
> + SELECT -4 NOT BETWEEN SYMMETRIC -3 AND -1;
> +  ?column? 
> + ----------
> +  t
> +  (1 row)
> + 
> Index: src/test/regress/sql/select.sql
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/select.sql,v
> retrieving revision 1.6
> diff -c -r1.6 select.sql
> *** src/test/regress/sql/select.sql    2001/07/16 05:07:00    1.6
> --- src/test/regress/sql/select.sql    2002/06/27 10:27:39
> ***************
> *** 103,105 ****
> --- 103,133 ----
>   --
>   SELECT p.name, p.age FROM person* p ORDER BY age using >, name;
>   
> + -- 
> + -- Test between syntax
> + --
> + SELECT 2 BETWEEN 1 AND 3;
> + SELECT 2 BETWEEN 3 AND 1;
> + SELECT 2 BETWEEN ASYMMETRIC 1 AND 3;
> + SELECT 2 BETWEEN ASYMMETRIC 3 AND 1;
> + SELECT 2 BETWEEN SYMMETRIC 1 AND 3;
> + SELECT 2 BETWEEN SYMMETRIC 3 AND 1;
> + SELECT 2 NOT BETWEEN 1 AND 3;
> + SELECT 2 NOT BETWEEN 3 AND 1;
> + SELECT 2 NOT BETWEEN ASYMMETRIC 1 AND 3;
> + SELECT 2 NOT BETWEEN ASYMMETRIC 3 AND 1;
> + SELECT 2 NOT BETWEEN SYMMETRIC 1 AND 3;
> + SELECT 2 NOT BETWEEN SYMMETRIC 3 AND 1;
> + SELECT -4 BETWEEN -1 AND -3;
> + SELECT -4 BETWEEN -3 AND -1;
> + SELECT -4 BETWEEN ASYMMETRIC -1 AND -3;
> + SELECT -4 BETWEEN ASYMMETRIC -3 AND -1;
> + SELECT -4 BETWEEN SYMMETRIC -1 AND -3;
> + SELECT -4 BETWEEN SYMMETRIC -3 AND -1;
> + SELECT -4 NOT BETWEEN -1 AND -3;
> + SELECT -4 NOT BETWEEN -3 AND -1;
> + SELECT -4 NOT BETWEEN ASYMMETRIC -1 AND -3;
> + SELECT -4 NOT BETWEEN ASYMMETRIC -3 AND -1;
> + SELECT -4 NOT BETWEEN SYMMETRIC -1 AND -3;
> + SELECT -4 NOT BETWEEN SYMMETRIC -3 AND -1;
> + 
> ----
> 

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly