Commit c1dcd59c authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Allow most expressions in BETWEEN clause. Allow all expressions if

 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.
parent bced35f1
......@@ -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 <node> columnDef, alter_clause
%type <defelt> def_elem
%type <node> 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 <list> 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);
......
......@@ -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},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment