Allow most expressions in BETWEEN clause. Allow all expressions if
authorThomas G. Lockhart
Wed, 4 Feb 1998 06:11:48 +0000 (06:11 +0000)
committerThomas G. Lockhart
Wed, 4 Feb 1998 06:11:48 +0000 (06:11 +0000)
 surrounded by parentheses (but not all are meaningful).
Remove unused keywords ACL, APPEND, MERGE.
Requires a "make clean" to recompile all code since keyword numeric
 assignments have changed with keyword removal.

src/backend/parser/gram.y
src/backend/parser/keywords.c

index b3a6f73095b5b321aa71729995f57a9f539733fd..0100081a4a103e558124b812438f7984f79850d9 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.103 1998/02/03 19:26:41 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.104 1998/02/04 06:11:46 thomas Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -188,7 +188,7 @@ Oid param_type(int t); /* used in parse_expr.c */
 %type    columnDef, alter_clause
 %type  def_elem
 %type    def_arg, columnElem, where_clause,
-               a_expr, a_expr_or_null, AexprConst,
+               a_expr, a_expr_or_null, b_expr, AexprConst,
                in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
                having_clause
 %type    row_descriptor, row_list
@@ -269,14 +269,14 @@ Oid   param_type(int t); /* used in parse_expr.c */
 %token TYPE_P
 
 /* Keywords for Postgres support (not in SQL92 reserved words) */
-%token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
-       APPEND, BACKWARD, BEFORE, BINARY, CLUSTER, COPY,
+%token ABORT_TRANS, AFTER, AGGREGATE, ANALYZE,
+       BACKWARD, BEFORE, BINARY, CLUSTER, COPY,
        DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
        FORWARD, FUNCTION, HANDLER,
        INDEX, INHERITS, INSTEAD, ISNULL,
-       LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION, MERGE, MOVE,
+       LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION, MOVE,
        NEW, NONE, NOTHING, NOTNULL, OIDS, OPERATOR, PROCEDURAL,
-       RECIPE, RENAME, REPLACE, RESET, RETURNS, RULE,
+       RECIPE, RENAME, RESET, RETURNS, RULE,
        SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED, 
        VACUUM, VERBOSE, VERSION
 
@@ -3199,6 +3199,14 @@ row_list:  row_list ',' a_expr
                }
        ;
 
+/*
+ * This is the heart of the expression syntax.
+ * Note that the BETWEEN clause looks similar to a boolean expression
+ *  and so we must define b_expr which is almost the same as a_expr
+ *  but without the boolean expressions.
+ * All operations are allowed in a BETWEEN clause if surrounded by parens.
+ */
+
 a_expr:  attr opt_indirection
                {
                    $1->indirection = $2;
@@ -3208,6 +3216,14 @@ a_expr:  attr opt_indirection
                {   $$ = $1;  }
        | AexprConst
                {   $$ = $1;  }
+       | ColId
+               {
+                   /* could be a column name or a relation_name */
+                   Ident *n = makeNode(Ident);
+                   n->name = $1;
+                   n->indirection = NULL;
+                   $$ = (Node *)n;
+               }
        | '-' a_expr %prec UMINUS
                {   $$ = makeA_Expr(OP, "-", NULL, $2); }
        | a_expr '+' a_expr
@@ -3274,14 +3290,6 @@ a_expr:  attr opt_indirection
                {   $$ = makeA_Expr(OP, $1, NULL, $2); }
        | a_expr Op
                {   $$ = makeA_Expr(OP, $2, $1, NULL); }
-       | ColId
-               {
-                   /* could be a column name or a relation_name */
-                   Ident *n = makeNode(Ident);
-                   n->name = $1;
-                   n->indirection = NULL;
-                   $$ = (Node *)n;
-               }
        | name '(' '*' ')'
                {
                    /* cheap hack for aggregate (eg. count) */
@@ -3508,13 +3516,13 @@ a_expr:  attr opt_indirection
                    n->typename->name = xlateSqlType("bool");
                    $$ = makeA_Expr(OP, "=", $1,(Node *)n);
                }
-       | a_expr BETWEEN AexprConst AND AexprConst
+       | a_expr BETWEEN b_expr AND b_expr
                {
                    $$ = makeA_Expr(AND, NULL,
                        makeA_Expr(OP, ">=", $1, $3),
                        makeA_Expr(OP, "<=", $1, $5));
                }
-       | a_expr NOT BETWEEN AexprConst AND AexprConst
+       | a_expr NOT BETWEEN b_expr AND b_expr
                {
                    $$ = makeA_Expr(OR, NULL,
                        makeA_Expr(OP, "<", $1, $4),
@@ -3796,6 +3804,233 @@ a_expr:  attr opt_indirection
                {   $$ = makeA_Expr(NOT, NULL, NULL, $2); }
        ;
 
+/*
+ * b_expr is a subset of the complete expression syntax
+ *  defined by a_expr. b_expr is used in BETWEEN clauses
+ *  to eliminate parser ambiguities stemming from the AND keyword.
+ */
+
+b_expr:  attr opt_indirection
+               {
+                   $1->indirection = $2;
+                   $$ = (Node *)$1;
+               }
+       | AexprConst
+               {   $$ = $1;  }
+       | ColId
+               {
+                   /* could be a column name or a relation_name */
+                   Ident *n = makeNode(Ident);
+                   n->name = $1;
+                   n->indirection = NULL;
+                   $$ = (Node *)n;
+               }
+       | '-' b_expr %prec UMINUS
+               {   $$ = makeA_Expr(OP, "-", NULL, $2); }
+       | b_expr '+' b_expr
+               {   $$ = makeA_Expr(OP, "+", $1, $3); }
+       | b_expr '-' b_expr
+               {   $$ = makeA_Expr(OP, "-", $1, $3); }
+       | b_expr '/' b_expr
+               {   $$ = makeA_Expr(OP, "/", $1, $3); }
+       | b_expr '*' b_expr
+               {   $$ = makeA_Expr(OP, "*", $1, $3); }
+       | ':' b_expr
+               {   $$ = makeA_Expr(OP, ":", NULL, $2); }
+       | ';' b_expr
+               {   $$ = makeA_Expr(OP, ";", NULL, $2); }
+       | '|' b_expr
+               {   $$ = makeA_Expr(OP, "|", NULL, $2); }
+       | b_expr TYPECAST Typename
+               {
+                   $$ = (Node *)$1;
+                   /* AexprConst can be either A_Const or ParamNo */
+                   if (nodeTag($1) == T_A_Const) {
+                       ((A_Const *)$1)->typename = $3;
+                   } else if (nodeTag($1) == T_Param) {
+                       ((ParamNo *)$1)->typename = $3;
+                   /* otherwise, try to transform to a function call */
+                   } else {
+                       FuncCall *n = makeNode(FuncCall);
+                       n->funcname = $3->name;
+                       n->args = lcons($1,NIL);
+                       $$ = (Node *)n;
+                   }
+               }
+       | CAST b_expr AS Typename
+               {
+                   $$ = (Node *)$2;
+                   /* AexprConst can be either A_Const or ParamNo */
+                   if (nodeTag($2) == T_A_Const) {
+                       ((A_Const *)$2)->typename = $4;
+                   } else if (nodeTag($2) == T_Param) {
+                       ((ParamNo *)$2)->typename = $4;
+                   /* otherwise, try to transform to a function call */
+                   } else {
+                       FuncCall *n = makeNode(FuncCall);
+                       n->funcname = $4->name;
+                       n->args = lcons($2,NIL);
+                       $$ = (Node *)n;
+                   }
+               }
+       | '(' a_expr ')'
+               {   $$ = $2; }
+       | b_expr Op b_expr
+               {   $$ = makeIndexable($2,$1,$3);   }
+       | Op b_expr
+               {   $$ = makeA_Expr(OP, $1, NULL, $2); }
+       | b_expr Op
+               {   $$ = makeA_Expr(OP, $2, $1, NULL); }
+       | name '(' ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = $1;
+                   n->args = NIL;
+                   $$ = (Node *)n;
+               }
+       | name '(' expr_list ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = $1;
+                   n->args = $3;
+                   $$ = (Node *)n;
+               }
+       | CURRENT_DATE
+               {
+                   A_Const *n = makeNode(A_Const);
+                   TypeName *t = makeNode(TypeName);
+
+                   n->val.type = T_String;
+                   n->val.val.str = "now";
+                   n->typename = t;
+
+                   t->name = xlateSqlType("date");
+                   t->setof = FALSE;
+
+                   $$ = (Node *)n;
+               }
+       | CURRENT_TIME
+               {
+                   A_Const *n = makeNode(A_Const);
+                   TypeName *t = makeNode(TypeName);
+
+                   n->val.type = T_String;
+                   n->val.val.str = "now";
+                   n->typename = t;
+
+                   t->name = xlateSqlType("time");
+                   t->setof = FALSE;
+
+                   $$ = (Node *)n;
+               }
+       | CURRENT_TIME '(' Iconst ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   A_Const *s = makeNode(A_Const);
+                   TypeName *t = makeNode(TypeName);
+
+                   n->funcname = xlateSqlType("time");
+                   n->args = lcons(s, NIL);
+
+                   s->val.type = T_String;
+                   s->val.val.str = "now";
+                   s->typename = t;
+
+                   t->name = xlateSqlType("time");
+                   t->setof = FALSE;
+
+                   if ($3 != 0)
+                       elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
+
+                   $$ = (Node *)n;
+               }
+       | CURRENT_TIMESTAMP
+               {
+                   A_Const *n = makeNode(A_Const);
+                   TypeName *t = makeNode(TypeName);
+
+                   n->val.type = T_String;
+                   n->val.val.str = "now";
+                   n->typename = t;
+
+                   t->name = xlateSqlType("timestamp");
+                   t->setof = FALSE;
+
+                   $$ = (Node *)n;
+               }
+       | CURRENT_TIMESTAMP '(' Iconst ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   A_Const *s = makeNode(A_Const);
+                   TypeName *t = makeNode(TypeName);
+
+                   n->funcname = xlateSqlType("timestamp");
+                   n->args = lcons(s, NIL);
+
+                   s->val.type = T_String;
+                   s->val.val.str = "now";
+                   s->typename = t;
+
+                   t->name = xlateSqlType("timestamp");
+                   t->setof = FALSE;
+
+                   if ($3 != 0)
+                       elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
+
+                   $$ = (Node *)n;
+               }
+       | CURRENT_USER
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = "getpgusername";
+                   n->args = NIL;
+                   $$ = (Node *)n;
+               }
+       | POSITION '(' position_list ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = "strpos";
+                   n->args = $3;
+                   $$ = (Node *)n;
+               }
+       | SUBSTRING '(' substr_list ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = "substr";
+                   n->args = $3;
+                   $$ = (Node *)n;
+               }
+       /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
+       | TRIM '(' BOTH trim_list ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = "btrim";
+                   n->args = $4;
+                   $$ = (Node *)n;
+               }
+       | TRIM '(' LEADING trim_list ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = "ltrim";
+                   n->args = $4;
+                   $$ = (Node *)n;
+               }
+       | TRIM '(' TRAILING trim_list ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = "rtrim";
+                   n->args = $4;
+                   $$ = (Node *)n;
+               }
+       | TRIM '(' trim_list ')'
+               {
+                   FuncCall *n = makeNode(FuncCall);
+                   n->funcname = "btrim";
+                   n->args = $3;
+                   $$ = (Node *)n;
+               }
+       ;
+
 opt_indirection:  '[' a_expr ']' opt_indirection
                {
                    A_Indices *ai = makeNode(A_Indices);
index 2c556f2a8e931ff90a94f07cfe4a42eb09ee0622..6567b015c092bb22c878e31c715f78acd6d6185e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.33 1998/02/03 16:04:05 thomas Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.34 1998/02/04 06:11:48 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,6 @@
 static ScanKeyword ScanKeywords[] = {
    /* name                 value           */
    {"abort", ABORT_TRANS},
-   {"acl", ACL},
    {"action", ACTION},
    {"add", ADD},
    {"after", AFTER},
@@ -40,7 +39,6 @@ static ScanKeyword ScanKeywords[] = {
    {"analyze", ANALYZE},
    {"and", AND},
    {"any", ANY},
-   {"append", APPEND},
    {"archive", ARCHIVE},
    {"as", AS},
    {"asc", ASC},
@@ -128,7 +126,6 @@ static ScanKeyword ScanKeywords[] = {
    {"location", LOCATION},
    {"lock", LOCK_P},
    {"match", MATCH},
-   {"merge", MERGE},
    {"minute", MINUTE_P},
    {"month", MONTH_P},
    {"move", MOVE},
@@ -165,7 +162,6 @@ static ScanKeyword ScanKeywords[] = {
    {"recipe", RECIPE},
    {"references", REFERENCES},
    {"rename", RENAME},
-   {"replace", REPLACE},
    {"reset", RESET},
    {"returns", RETURNS},
    {"revoke", REVOKE},