mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
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.
This commit is contained in:
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -188,7 +188,7 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||||||
%type <node> columnDef, alter_clause
|
%type <node> columnDef, alter_clause
|
||||||
%type <defelt> def_elem
|
%type <defelt> def_elem
|
||||||
%type <node> def_arg, columnElem, where_clause,
|
%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,
|
in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
|
||||||
having_clause
|
having_clause
|
||||||
%type <list> row_descriptor, row_list
|
%type <list> row_descriptor, row_list
|
||||||
@ -269,14 +269,14 @@ Oid param_type(int t); /* used in parse_expr.c */
|
|||||||
%token TYPE_P
|
%token TYPE_P
|
||||||
|
|
||||||
/* Keywords for Postgres support (not in SQL92 reserved words) */
|
/* Keywords for Postgres support (not in SQL92 reserved words) */
|
||||||
%token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
|
%token ABORT_TRANS, AFTER, AGGREGATE, ANALYZE,
|
||||||
APPEND, BACKWARD, BEFORE, BINARY, CLUSTER, COPY,
|
BACKWARD, BEFORE, BINARY, CLUSTER, COPY,
|
||||||
DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
|
DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
|
||||||
FORWARD, FUNCTION, HANDLER,
|
FORWARD, FUNCTION, HANDLER,
|
||||||
INDEX, INHERITS, INSTEAD, ISNULL,
|
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,
|
NEW, NONE, NOTHING, NOTNULL, OIDS, OPERATOR, PROCEDURAL,
|
||||||
RECIPE, RENAME, REPLACE, RESET, RETURNS, RULE,
|
RECIPE, RENAME, RESET, RETURNS, RULE,
|
||||||
SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED,
|
SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED,
|
||||||
VACUUM, VERBOSE, VERSION
|
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
|
a_expr: attr opt_indirection
|
||||||
{
|
{
|
||||||
$1->indirection = $2;
|
$1->indirection = $2;
|
||||||
@ -3208,6 +3216,14 @@ a_expr: attr opt_indirection
|
|||||||
{ $$ = $1; }
|
{ $$ = $1; }
|
||||||
| AexprConst
|
| AexprConst
|
||||||
{ $$ = $1; }
|
{ $$ = $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
|
| '-' a_expr %prec UMINUS
|
||||||
{ $$ = makeA_Expr(OP, "-", NULL, $2); }
|
{ $$ = makeA_Expr(OP, "-", NULL, $2); }
|
||||||
| a_expr '+' a_expr
|
| a_expr '+' a_expr
|
||||||
@ -3274,14 +3290,6 @@ a_expr: attr opt_indirection
|
|||||||
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
|
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
|
||||||
| a_expr Op
|
| a_expr Op
|
||||||
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
|
{ $$ = 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 '(' '*' ')'
|
| name '(' '*' ')'
|
||||||
{
|
{
|
||||||
/* cheap hack for aggregate (eg. count) */
|
/* cheap hack for aggregate (eg. count) */
|
||||||
@ -3508,13 +3516,13 @@ a_expr: attr opt_indirection
|
|||||||
n->typename->name = xlateSqlType("bool");
|
n->typename->name = xlateSqlType("bool");
|
||||||
$$ = makeA_Expr(OP, "=", $1,(Node *)n);
|
$$ = 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(AND, NULL,
|
||||||
makeA_Expr(OP, ">=", $1, $3),
|
makeA_Expr(OP, ">=", $1, $3),
|
||||||
makeA_Expr(OP, "<=", $1, $5));
|
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(OR, NULL,
|
||||||
makeA_Expr(OP, "<", $1, $4),
|
makeA_Expr(OP, "<", $1, $4),
|
||||||
@ -3796,6 +3804,233 @@ a_expr: attr opt_indirection
|
|||||||
{ $$ = makeA_Expr(NOT, NULL, NULL, $2); }
|
{ $$ = 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
|
opt_indirection: '[' a_expr ']' opt_indirection
|
||||||
{
|
{
|
||||||
A_Indices *ai = makeNode(A_Indices);
|
A_Indices *ai = makeNode(A_Indices);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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[] = {
|
static ScanKeyword ScanKeywords[] = {
|
||||||
/* name value */
|
/* name value */
|
||||||
{"abort", ABORT_TRANS},
|
{"abort", ABORT_TRANS},
|
||||||
{"acl", ACL},
|
|
||||||
{"action", ACTION},
|
{"action", ACTION},
|
||||||
{"add", ADD},
|
{"add", ADD},
|
||||||
{"after", AFTER},
|
{"after", AFTER},
|
||||||
@ -40,7 +39,6 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"analyze", ANALYZE},
|
{"analyze", ANALYZE},
|
||||||
{"and", AND},
|
{"and", AND},
|
||||||
{"any", ANY},
|
{"any", ANY},
|
||||||
{"append", APPEND},
|
|
||||||
{"archive", ARCHIVE},
|
{"archive", ARCHIVE},
|
||||||
{"as", AS},
|
{"as", AS},
|
||||||
{"asc", ASC},
|
{"asc", ASC},
|
||||||
@ -128,7 +126,6 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"location", LOCATION},
|
{"location", LOCATION},
|
||||||
{"lock", LOCK_P},
|
{"lock", LOCK_P},
|
||||||
{"match", MATCH},
|
{"match", MATCH},
|
||||||
{"merge", MERGE},
|
|
||||||
{"minute", MINUTE_P},
|
{"minute", MINUTE_P},
|
||||||
{"month", MONTH_P},
|
{"month", MONTH_P},
|
||||||
{"move", MOVE},
|
{"move", MOVE},
|
||||||
@ -165,7 +162,6 @@ static ScanKeyword ScanKeywords[] = {
|
|||||||
{"recipe", RECIPE},
|
{"recipe", RECIPE},
|
||||||
{"references", REFERENCES},
|
{"references", REFERENCES},
|
||||||
{"rename", RENAME},
|
{"rename", RENAME},
|
||||||
{"replace", REPLACE},
|
|
||||||
{"reset", RESET},
|
{"reset", RESET},
|
||||||
{"returns", RETURNS},
|
{"returns", RETURNS},
|
||||||
{"revoke", REVOKE},
|
{"revoke", REVOKE},
|
||||||
|
Reference in New Issue
Block a user