1010 *
1111 *
1212 * IDENTIFICATION
13- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.103 1998/02/03 19:26:41 momjian Exp $
13+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.104 1998/02/04 06:11:46 thomas Exp $
1414 *
1515 * HISTORY
1616 * AUTHORDATEMAJOR EVENT
@@ -188,7 +188,7 @@ Oidparam_type(int t); /* used in parse_expr.c */
188188%type <node>columnDef, alter_clause
189189%type <defelt>def_elem
190190%type <node>def_arg, columnElem, where_clause,
191- a_expr, a_expr_or_null, AexprConst,
191+ a_expr, a_expr_or_null,b_expr, AexprConst,
192192in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
193193having_clause
194194%type <list>row_descriptor, row_list
@@ -269,14 +269,14 @@ Oidparam_type(int t); /* used in parse_expr.c */
269269%tokenTYPE_P
270270
271271/* Keywords for Postgres support (not in SQL92 reserved words) */
272- %tokenABORT_TRANS,ACL, AFTER, AGGREGATE, ANALYZE,
273- APPEND, BACKWARD, BEFORE, BINARY, CLUSTER, COPY,
272+ %tokenABORT_TRANS, AFTER, AGGREGATE, ANALYZE,
273+ BACKWARD, BEFORE, BINARY, CLUSTER, COPY,
274274DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
275275FORWARD, FUNCTION, HANDLER,
276276INDEX, INHERITS, INSTEAD, ISNULL,
277- LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION,MERGE, MOVE,
277+ LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION, MOVE,
278278NEW, NONE, NOTHING, NOTNULL, OIDS, OPERATOR, PROCEDURAL,
279- RECIPE, RENAME,REPLACE, RESET, RETURNS, RULE,
279+ RECIPE, RENAME, RESET, RETURNS, RULE,
280280SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED,
281281VACUUM, VERBOSE, VERSION
282282
@@ -3199,6 +3199,14 @@ row_list: row_list ',' a_expr
31993199}
32003200;
32013201
3202+ /*
3203+ * This is the heart of the expression syntax.
3204+ * Note that the BETWEEN clause looks similar to a boolean expression
3205+ * and so we must define b_expr which is almost the same as a_expr
3206+ * but without the boolean expressions.
3207+ * All operations are allowed in a BETWEEN clause if surrounded by parens.
3208+ */
3209+
32023210a_expr: attr opt_indirection
32033211{
32043212$1->indirection = $2;
@@ -3208,6 +3216,14 @@ a_expr: attr opt_indirection
32083216{$$ = $1; }
32093217| AexprConst
32103218{$$ = $1; }
3219+ | ColId
3220+ {
3221+ /* could be a column name or a relation_name */
3222+ Ident *n = makeNode(Ident);
3223+ n->name = $1;
3224+ n->indirection = NULL;
3225+ $$ = (Node *)n;
3226+ }
32113227| '-' a_expr %prec UMINUS
32123228{$$ = makeA_Expr(OP, "-", NULL, $2); }
32133229| a_expr '+' a_expr
@@ -3274,14 +3290,6 @@ a_expr: attr opt_indirection
32743290{$$ = makeA_Expr(OP, $1, NULL, $2); }
32753291| a_expr Op
32763292{$$ = makeA_Expr(OP, $2, $1, NULL); }
3277- | ColId
3278- {
3279- /* could be a column name or a relation_name */
3280- Ident *n = makeNode(Ident);
3281- n->name = $1;
3282- n->indirection = NULL;
3283- $$ = (Node *)n;
3284- }
32853293| name '(' '*' ')'
32863294{
32873295/* cheap hack for aggregate (eg. count) */
@@ -3508,13 +3516,13 @@ a_expr: attr opt_indirection
35083516n->typename->name = xlateSqlType("bool");
35093517$$ = makeA_Expr(OP, "=", $1,(Node *)n);
35103518}
3511- | a_expr BETWEENAexprConst ANDAexprConst
3519+ | a_expr BETWEENb_expr ANDb_expr
35123520{
35133521$$ = makeA_Expr(AND, NULL,
35143522makeA_Expr(OP, ">=", $1, $3),
35153523makeA_Expr(OP, "<=", $1, $5));
35163524}
3517- | a_expr NOT BETWEENAexprConst ANDAexprConst
3525+ | a_expr NOT BETWEENb_expr ANDb_expr
35183526{
35193527$$ = makeA_Expr(OR, NULL,
35203528makeA_Expr(OP, "<", $1, $4),
@@ -3796,6 +3804,233 @@ a_expr: attr opt_indirection
37963804{$$ = makeA_Expr(NOT, NULL, NULL, $2); }
37973805;
37983806
3807+ /*
3808+ * b_expr is a subset of the complete expression syntax
3809+ * defined by a_expr. b_expr is used in BETWEEN clauses
3810+ * to eliminate parser ambiguities stemming from the AND keyword.
3811+ */
3812+
3813+ b_expr: attr opt_indirection
3814+ {
3815+ $1->indirection = $2;
3816+ $$ = (Node *)$1;
3817+ }
3818+ | AexprConst
3819+ {$$ = $1; }
3820+ | ColId
3821+ {
3822+ /* could be a column name or a relation_name */
3823+ Ident *n = makeNode(Ident);
3824+ n->name = $1;
3825+ n->indirection = NULL;
3826+ $$ = (Node *)n;
3827+ }
3828+ | '-' b_expr %prec UMINUS
3829+ {$$ = makeA_Expr(OP, "-", NULL, $2); }
3830+ | b_expr '+' b_expr
3831+ {$$ = makeA_Expr(OP, "+", $1, $3); }
3832+ | b_expr '-' b_expr
3833+ {$$ = makeA_Expr(OP, "-", $1, $3); }
3834+ | b_expr '/' b_expr
3835+ {$$ = makeA_Expr(OP, "/", $1, $3); }
3836+ | b_expr '*' b_expr
3837+ {$$ = makeA_Expr(OP, "*", $1, $3); }
3838+ | ':' b_expr
3839+ {$$ = makeA_Expr(OP, ":", NULL, $2); }
3840+ | ';' b_expr
3841+ {$$ = makeA_Expr(OP, ";", NULL, $2); }
3842+ | '|' b_expr
3843+ {$$ = makeA_Expr(OP, "|", NULL, $2); }
3844+ | b_expr TYPECAST Typename
3845+ {
3846+ $$ = (Node *)$1;
3847+ /* AexprConst can be either A_Const or ParamNo */
3848+ if (nodeTag($1) == T_A_Const) {
3849+ ((A_Const *)$1)->typename = $3;
3850+ } else if (nodeTag($1) == T_Param) {
3851+ ((ParamNo *)$1)->typename = $3;
3852+ /* otherwise, try to transform to a function call */
3853+ } else {
3854+ FuncCall *n = makeNode(FuncCall);
3855+ n->funcname = $3->name;
3856+ n->args = lcons($1,NIL);
3857+ $$ = (Node *)n;
3858+ }
3859+ }
3860+ | CAST b_expr AS Typename
3861+ {
3862+ $$ = (Node *)$2;
3863+ /* AexprConst can be either A_Const or ParamNo */
3864+ if (nodeTag($2) == T_A_Const) {
3865+ ((A_Const *)$2)->typename = $4;
3866+ } else if (nodeTag($2) == T_Param) {
3867+ ((ParamNo *)$2)->typename = $4;
3868+ /* otherwise, try to transform to a function call */
3869+ } else {
3870+ FuncCall *n = makeNode(FuncCall);
3871+ n->funcname = $4->name;
3872+ n->args = lcons($2,NIL);
3873+ $$ = (Node *)n;
3874+ }
3875+ }
3876+ | '(' a_expr ')'
3877+ {$$ = $2; }
3878+ | b_expr Op b_expr
3879+ {$$ = makeIndexable($2,$1,$3);}
3880+ | Op b_expr
3881+ {$$ = makeA_Expr(OP, $1, NULL, $2); }
3882+ | b_expr Op
3883+ {$$ = makeA_Expr(OP, $2, $1, NULL); }
3884+ | name '(' ')'
3885+ {
3886+ FuncCall *n = makeNode(FuncCall);
3887+ n->funcname = $1;
3888+ n->args = NIL;
3889+ $$ = (Node *)n;
3890+ }
3891+ | name '(' expr_list ')'
3892+ {
3893+ FuncCall *n = makeNode(FuncCall);
3894+ n->funcname = $1;
3895+ n->args = $3;
3896+ $$ = (Node *)n;
3897+ }
3898+ | CURRENT_DATE
3899+ {
3900+ A_Const *n = makeNode(A_Const);
3901+ TypeName *t = makeNode(TypeName);
3902+
3903+ n->val.type = T_String;
3904+ n->val.val.str = "now";
3905+ n->typename = t;
3906+
3907+ t->name = xlateSqlType("date");
3908+ t->setof = FALSE;
3909+
3910+ $$ = (Node *)n;
3911+ }
3912+ | CURRENT_TIME
3913+ {
3914+ A_Const *n = makeNode(A_Const);
3915+ TypeName *t = makeNode(TypeName);
3916+
3917+ n->val.type = T_String;
3918+ n->val.val.str = "now";
3919+ n->typename = t;
3920+
3921+ t->name = xlateSqlType("time");
3922+ t->setof = FALSE;
3923+
3924+ $$ = (Node *)n;
3925+ }
3926+ | CURRENT_TIME '(' Iconst ')'
3927+ {
3928+ FuncCall *n = makeNode(FuncCall);
3929+ A_Const *s = makeNode(A_Const);
3930+ TypeName *t = makeNode(TypeName);
3931+
3932+ n->funcname = xlateSqlType("time");
3933+ n->args = lcons(s, NIL);
3934+
3935+ s->val.type = T_String;
3936+ s->val.val.str = "now";
3937+ s->typename = t;
3938+
3939+ t->name = xlateSqlType("time");
3940+ t->setof = FALSE;
3941+
3942+ if ($3 != 0)
3943+ elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
3944+
3945+ $$ = (Node *)n;
3946+ }
3947+ | CURRENT_TIMESTAMP
3948+ {
3949+ A_Const *n = makeNode(A_Const);
3950+ TypeName *t = makeNode(TypeName);
3951+
3952+ n->val.type = T_String;
3953+ n->val.val.str = "now";
3954+ n->typename = t;
3955+
3956+ t->name = xlateSqlType("timestamp");
3957+ t->setof = FALSE;
3958+
3959+ $$ = (Node *)n;
3960+ }
3961+ | CURRENT_TIMESTAMP '(' Iconst ')'
3962+ {
3963+ FuncCall *n = makeNode(FuncCall);
3964+ A_Const *s = makeNode(A_Const);
3965+ TypeName *t = makeNode(TypeName);
3966+
3967+ n->funcname = xlateSqlType("timestamp");
3968+ n->args = lcons(s, NIL);
3969+
3970+ s->val.type = T_String;
3971+ s->val.val.str = "now";
3972+ s->typename = t;
3973+
3974+ t->name = xlateSqlType("timestamp");
3975+ t->setof = FALSE;
3976+
3977+ if ($3 != 0)
3978+ elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
3979+
3980+ $$ = (Node *)n;
3981+ }
3982+ | CURRENT_USER
3983+ {
3984+ FuncCall *n = makeNode(FuncCall);
3985+ n->funcname = "getpgusername";
3986+ n->args = NIL;
3987+ $$ = (Node *)n;
3988+ }
3989+ | POSITION '(' position_list ')'
3990+ {
3991+ FuncCall *n = makeNode(FuncCall);
3992+ n->funcname = "strpos";
3993+ n->args = $3;
3994+ $$ = (Node *)n;
3995+ }
3996+ | SUBSTRING '(' substr_list ')'
3997+ {
3998+ FuncCall *n = makeNode(FuncCall);
3999+ n->funcname = "substr";
4000+ n->args = $3;
4001+ $$ = (Node *)n;
4002+ }
4003+ /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
4004+ | TRIM '(' BOTH trim_list ')'
4005+ {
4006+ FuncCall *n = makeNode(FuncCall);
4007+ n->funcname = "btrim";
4008+ n->args = $4;
4009+ $$ = (Node *)n;
4010+ }
4011+ | TRIM '(' LEADING trim_list ')'
4012+ {
4013+ FuncCall *n = makeNode(FuncCall);
4014+ n->funcname = "ltrim";
4015+ n->args = $4;
4016+ $$ = (Node *)n;
4017+ }
4018+ | TRIM '(' TRAILING trim_list ')'
4019+ {
4020+ FuncCall *n = makeNode(FuncCall);
4021+ n->funcname = "rtrim";
4022+ n->args = $4;
4023+ $$ = (Node *)n;
4024+ }
4025+ | TRIM '(' trim_list ')'
4026+ {
4027+ FuncCall *n = makeNode(FuncCall);
4028+ n->funcname = "btrim";
4029+ n->args = $3;
4030+ $$ = (Node *)n;
4031+ }
4032+ ;
4033+
37994034opt_indirection: '[' a_expr ']' opt_indirection
38004035{
38014036A_Indices *ai = makeNode(A_Indices);