gram.y
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:141k
- sort_clause: ORDER BY sortby_list { $$ = $3; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- sortby_list: sortby { $$ = lcons($1, NIL); }
- | sortby_list ',' sortby { $$ = lappend($1, $3); }
- ;
- sortby: a_expr OptUseOp
- {
- $$ = makeNode(SortGroupBy);
- $$->node = $1;
- $$->useOp = $2;
- }
- ;
- OptUseOp: USING Op { $$ = $2; }
- | USING '<' { $$ = "<"; }
- | USING '>' { $$ = ">"; }
- | ASC { $$ = "<"; }
- | DESC { $$ = ">"; }
- | /*EMPTY*/ { $$ = "<"; /*default*/ }
- ;
- opt_select_limit: LIMIT select_limit_value ',' select_offset_value
- { $$ = lappend(lappend(NIL, $4), $2); }
- | LIMIT select_limit_value OFFSET select_offset_value
- { $$ = lappend(lappend(NIL, $4), $2); }
- | LIMIT select_limit_value
- { $$ = lappend(lappend(NIL, NULL), $2); }
- | OFFSET select_offset_value LIMIT select_limit_value
- { $$ = lappend(lappend(NIL, $2), $4); }
- | OFFSET select_offset_value
- { $$ = lappend(lappend(NIL, $2), NULL); }
- | /* EMPTY */
- { $$ = lappend(lappend(NIL, NULL), NULL); }
- ;
- select_limit_value: Iconst
- {
- Const *n = makeNode(Const);
- if ($1 < 1)
- elog(ERROR, "selection limit must be ALL or a positive integer value > 0");
- n->consttype = INT4OID;
- n->constlen = sizeof(int4);
- n->constvalue = (Datum)$1;
- n->constisnull = FALSE;
- n->constbyval = TRUE;
- n->constisset = FALSE;
- n->constiscast = FALSE;
- $$ = (Node *)n;
- }
- | ALL
- {
- Const *n = makeNode(Const);
- n->consttype = INT4OID;
- n->constlen = sizeof(int4);
- n->constvalue = (Datum)0;
- n->constisnull = FALSE;
- n->constbyval = TRUE;
- n->constisset = FALSE;
- n->constiscast = FALSE;
- $$ = (Node *)n;
- }
- | PARAM
- {
- Param *n = makeNode(Param);
- n->paramkind = PARAM_NUM;
- n->paramid = $1;
- n->paramtype = INT4OID;
- $$ = (Node *)n;
- }
- ;
- select_offset_value: Iconst
- {
- Const *n = makeNode(Const);
- n->consttype = INT4OID;
- n->constlen = sizeof(int4);
- n->constvalue = (Datum)$1;
- n->constisnull = FALSE;
- n->constbyval = TRUE;
- n->constisset = FALSE;
- n->constiscast = FALSE;
- $$ = (Node *)n;
- }
- | PARAM
- {
- Param *n = makeNode(Param);
- n->paramkind = PARAM_NUM;
- n->paramid = $1;
- n->paramtype = INT4OID;
- $$ = (Node *)n;
- }
- ;
- /*
- * jimmy bell-style recursive queries aren't supported in the
- * current system.
- *
- * ...however, recursive addattr and rename supported. make special
- * cases for these.
- */
- opt_inh_star: '*' { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- relation_name_list: name_list;
- name_list: name
- { $$ = lcons(makeString($1),NIL); }
- | name_list ',' name
- { $$ = lappend($1,makeString($3)); }
- ;
- group_clause: GROUP BY expr_list { $$ = $3; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- having_clause: HAVING a_expr
- {
- $$ = $2;
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- for_update_clause: FOR UPDATE update_list { $$ = $3; }
- | FOR READ ONLY { $$ = NULL; }
- | /* EMPTY */ { $$ = NULL; }
- ;
- update_list: OF va_list { $$ = $2; }
- | /* EMPTY */ { $$ = lcons(NULL, NULL); }
- ;
- /*****************************************************************************
- *
- * clauses common to all Optimizable Stmts:
- * from_clause -
- * where_clause -
- *
- *****************************************************************************/
- from_clause: FROM from_expr { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- from_expr: '(' join_clause_with_union ')'
- { $$ = $2; }
- | join_clause
- { $$ = $1; }
- | table_list
- { $$ = $1; }
- ;
- table_list: table_list ',' table_expr
- { $$ = lappend($1, $3); }
- | table_expr
- { $$ = lcons($1, NIL); }
- ;
- table_expr: relation_expr AS ColLabel
- {
- $$ = makeNode(RangeVar);
- $$->relExpr = $1;
- $$->name = $3;
- }
- | relation_expr ColId
- {
- $$ = makeNode(RangeVar);
- $$->relExpr = $1;
- $$->name = $2;
- }
- | relation_expr
- {
- $$ = makeNode(RangeVar);
- $$->relExpr = $1;
- $$->name = NULL;
- }
- ;
- /* A UNION JOIN is the same as a FULL OUTER JOIN which *omits*
- * all result rows which would have matched on an INNER JOIN.
- * Let's reject this for now. - thomas 1999-01-08
- */
- join_clause_with_union: join_clause
- { $$ = $1; }
- | table_expr UNION JOIN table_expr
- { elog(ERROR,"UNION JOIN not yet implemented"); }
- ;
- join_clause: table_expr join_list
- {
- Node *n = lfirst($2);
- /* JoinExpr came back? then it is a join of some sort...
- */
- if (IsA(n, JoinExpr))
- {
- JoinExpr *j = (JoinExpr *)n;
- j->larg = $1;
- $$ = $2;
- }
- /* otherwise, it was a cross join,
- * which we just represent as an inner join...
- */
- else
- $$ = lcons($1, $2);
- }
- ;
- join_list: join_list join_expr
- {
- $$ = lappend($1, $2);
- }
- | join_expr
- {
- $$ = lcons($1, NIL);
- }
- ;
- /* This is everything but the left side of a join.
- * Note that a CROSS JOIN is the same as an unqualified
- * inner join, so just pass back the right-side table.
- * A NATURAL JOIN implicitly matches column names between
- * tables, so we'll collect those during the later transformation.
- */
- join_expr: join_type JOIN table_expr join_qual
- {
- JoinExpr *n = makeNode(JoinExpr);
- n->jointype = $1;
- n->rarg = (Node *)$3;
- n->quals = $4;
- $$ = (Node *)n;
- }
- | NATURAL join_type JOIN table_expr
- {
- JoinExpr *n = makeNode(JoinExpr);
- n->jointype = $2;
- n->rarg = (Node *)$4;
- n->quals = NULL; /* figure out which columns later... */
- $$ = (Node *)n;
- }
- | CROSS JOIN table_expr
- { $$ = (Node *)$3; }
- ;
- /* OUTER is just noise... */
- join_type: FULL join_outer
- {
- $$ = FULL;
- elog(NOTICE,"FULL OUTER JOIN not yet implemented");
- }
- | LEFT join_outer
- {
- $$ = LEFT;
- elog(NOTICE,"LEFT OUTER JOIN not yet implemented");
- }
- | RIGHT join_outer
- {
- $$ = RIGHT;
- elog(NOTICE,"RIGHT OUTER JOIN not yet implemented");
- }
- | OUTER_P
- {
- $$ = LEFT;
- elog(NOTICE,"OUTER JOIN not yet implemented");
- }
- | INNER_P
- {
- $$ = INNER_P;
- }
- | /*EMPTY*/
- {
- $$ = INNER_P;
- }
- ;
- join_outer: OUTER_P { $$ = NULL; }
- | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
- ;
- /* JOIN qualification clauses
- * Possibilities are:
- * USING ( column list ) allows only unqualified column names,
- * which must match between tables.
- * ON expr allows more general qualifications.
- * - thomas 1999-01-07
- */
- join_qual: USING '(' using_list ')' { $$ = $3; }
- | ON a_expr { $$ = lcons($2, NIL); }
- ;
- using_list: using_list ',' using_expr { $$ = lappend($1, $3); }
- | using_expr { $$ = lcons($1, NIL); }
- ;
- using_expr: ColId
- {
- /* could be a column name or a relation_name */
- Ident *n = makeNode(Ident);
- n->name = $1;
- n->indirection = NULL;
- $$ = (Node *)n;
- }
- ;
- where_clause: WHERE a_expr { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
- ;
- relation_expr: relation_name
- {
- /* normal relations */
- $$ = makeNode(RelExpr);
- $$->relname = $1;
- $$->inh = FALSE;
- }
- | relation_name '*' %prec '='
- {
- /* inheritance query */
- $$ = makeNode(RelExpr);
- $$->relname = $1;
- $$->inh = TRUE;
- }
- opt_array_bounds: '[' ']' nest_array_bounds
- { $$ = lcons(makeInteger(-1), $3); }
- | '[' Iconst ']' nest_array_bounds
- { $$ = lcons(makeInteger($2), $4); }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- nest_array_bounds: '[' ']' nest_array_bounds
- { $$ = lcons(makeInteger(-1), $3); }
- | '[' Iconst ']' nest_array_bounds
- { $$ = lcons(makeInteger($2), $4); }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- /*****************************************************************************
- *
- * Type syntax
- * SQL92 introduces a large amount of type-specific syntax.
- * Define individual clauses to handle these cases, and use
- * the generic case to handle regular type-extensible Postgres syntax.
- * - thomas 1997-10-10
- *
- *****************************************************************************/
- Typename: Array opt_array_bounds
- {
- $$ = $1;
- $$->arrayBounds = $2;
- /* Is this the name of a complex type? If so, implement
- * it as a set.
- */
- if (!strcmp(saved_relname, $$->name))
- /* This attr is the same type as the relation
- * being defined. The classic example: create
- * emp(name=text,mgr=emp)
- */
- $$->setof = TRUE;
- else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
- /* (Eventually add in here that the set can only
- * contain one element.)
- */
- $$->setof = TRUE;
- else
- $$->setof = FALSE;
- }
- | SETOF Array
- {
- $$ = $2;
- $$->setof = TRUE;
- }
- ;
- Array: Generic
- | Datetime
- | Numeric
- | Character
- ;
- Generic: generic
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType($1);
- $$->typmod = -1;
- }
- ;
- generic: IDENT { $$ = $1; }
- | TYPE_P { $$ = xlateSqlType("type"); }
- ;
- /* SQL92 numeric data types
- * Check FLOAT() precision limits assuming IEEE floating types.
- * Provide real DECIMAL() and NUMERIC() implementations now - Jan 1998-12-30
- * - thomas 1997-09-18
- */
- Numeric: FLOAT opt_float
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType($2);
- $$->typmod = -1;
- }
- | DOUBLE PRECISION
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("float");
- }
- | DECIMAL opt_decimal
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("numeric");
- $$->typmod = $2;
- }
- | NUMERIC opt_numeric
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("numeric");
- $$->typmod = $2;
- }
- ;
- numeric: FLOAT
- { $$ = xlateSqlType("float8"); }
- | DOUBLE PRECISION
- { $$ = xlateSqlType("float8"); }
- | DECIMAL
- { $$ = xlateSqlType("numeric"); }
- | NUMERIC
- { $$ = xlateSqlType("numeric"); }
- ;
- opt_float: '(' Iconst ')'
- {
- if ($2 < 1)
- elog(ERROR,"precision for FLOAT must be at least 1");
- else if ($2 < 7)
- $$ = xlateSqlType("float4");
- else if ($2 < 16)
- $$ = xlateSqlType("float8");
- else
- elog(ERROR,"precision for FLOAT must be less than 16");
- }
- | /*EMPTY*/
- {
- $$ = xlateSqlType("float8");
- }
- ;
- opt_numeric: '(' Iconst ',' Iconst ')'
- {
- if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
- elog(ERROR,"NUMERIC precision %d must be beween 1 and %d",
- $2, NUMERIC_MAX_PRECISION);
- if ($4 < 0 || $4 > $2)
- elog(ERROR,"NUMERIC scale %d must be between 0 and precision %d",
- $4,$2);
- $$ = (($2 << 16) | $4) + VARHDRSZ;
- }
- | '(' Iconst ')'
- {
- if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
- elog(ERROR,"NUMERIC precision %d must be beween 1 and %d",
- $2, NUMERIC_MAX_PRECISION);
- $$ = ($2 << 16) + VARHDRSZ;
- }
- | /*EMPTY*/
- {
- $$ = ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE) + VARHDRSZ;
- }
- ;
- opt_decimal: '(' Iconst ',' Iconst ')'
- {
- if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
- elog(ERROR,"DECIMAL precision %d must be beween 1 and %d",
- $2, NUMERIC_MAX_PRECISION);
- if ($4 < 0 || $4 > $2)
- elog(ERROR,"DECIMAL scale %d must be between 0 and precision %d",
- $4,$2);
- $$ = (($2 << 16) | $4) + VARHDRSZ;
- }
- | '(' Iconst ')'
- {
- if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
- elog(ERROR,"DECIMAL precision %d must be beween 1 and %d",
- $2, NUMERIC_MAX_PRECISION);
- $$ = ($2 << 16) + VARHDRSZ;
- }
- | /*EMPTY*/
- {
- $$ = ((NUMERIC_DEFAULT_PRECISION << 16) | NUMERIC_DEFAULT_SCALE) + VARHDRSZ;
- }
- ;
- /* SQL92 character data types
- * The following implements CHAR() and VARCHAR().
- */
- Character: character '(' Iconst ')'
- {
- $$ = makeNode(TypeName);
- if (strcasecmp($1, "char") == 0)
- $$->name = xlateSqlType("bpchar");
- else if (strcasecmp($1, "varchar") == 0)
- $$->name = xlateSqlType("varchar");
- else
- yyerror("internal parsing error; unrecognized character type");
- if ($3 < 1)
- elog(ERROR,"length for '%s' type must be at least 1",$1);
- else if ($3 > MaxAttrSize)
- elog(ERROR,"length for type '%s' cannot exceed %d",$1,
- MaxAttrSize);
- /* we actually implement this sort of like a varlen, so
- * the first 4 bytes is the length. (the difference
- * between this and "text" is that we blank-pad and
- * truncate where necessary
- */
- $$->typmod = VARHDRSZ + $3;
- }
- | character
- {
- $$ = makeNode(TypeName);
- /* Let's try to make all single-character types into bpchar(1)
- * - thomas 1998-05-07
- */
- if (strcasecmp($1, "char") == 0)
- {
- $$->name = xlateSqlType("bpchar");
- $$->typmod = VARHDRSZ + 1;
- }
- else
- {
- $$->name = xlateSqlType($1);
- $$->typmod = -1;
- }
- }
- ;
- character: CHARACTER opt_varying opt_charset opt_collate
- {
- char *type, *c;
- if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
- if ($2) type = xlateSqlType("varchar");
- else type = xlateSqlType("char");
- } else {
- if ($2) {
- c = palloc(strlen("var") + strlen($3) + 1);
- strcpy(c, "var");
- strcat(c, $3);
- type = xlateSqlType(c);
- } else {
- type = xlateSqlType($3);
- }
- };
- if ($4 != NULL)
- elog(NOTICE,"COLLATE %s not yet implemented; clause ignored",$4);
- $$ = type;
- }
- | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
- | VARCHAR { $$ = xlateSqlType("varchar"); }
- | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
- | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
- ;
- opt_varying: VARYING { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- opt_charset: CHARACTER SET ColId { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- opt_collate: COLLATE ColId { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- Datetime: datetime
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType($1);
- $$->typmod = -1;
- }
- | TIMESTAMP opt_timezone
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("timestamp");
- $$->timezone = $2;
- $$->typmod = -1;
- }
- | TIME
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("time");
- $$->typmod = -1;
- }
- | INTERVAL opt_interval
- {
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("interval");
- $$->typmod = -1;
- }
- ;
- datetime: YEAR_P { $$ = "year"; }
- | MONTH_P { $$ = "month"; }
- | DAY_P { $$ = "day"; }
- | HOUR_P { $$ = "hour"; }
- | MINUTE_P { $$ = "minute"; }
- | SECOND_P { $$ = "second"; }
- ;
- opt_timezone: WITH TIME ZONE { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
- opt_interval: datetime { $$ = lcons($1, NIL); }
- | YEAR_P TO MONTH_P { $$ = NIL; }
- | DAY_P TO HOUR_P { $$ = NIL; }
- | DAY_P TO MINUTE_P { $$ = NIL; }
- | DAY_P TO SECOND_P { $$ = NIL; }
- | HOUR_P TO MINUTE_P { $$ = NIL; }
- | HOUR_P TO SECOND_P { $$ = NIL; }
- | MINUTE_P TO SECOND_P { $$ = NIL; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
- /*****************************************************************************
- *
- * expression grammar, still needs some cleanup
- *
- *****************************************************************************/
- a_expr_or_null: a_expr
- { $$ = $1; }
- | NULL_P
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_Null;
- $$ = (Node *)n;
- }
- ;
- /* Expressions using row descriptors
- * Define row_descriptor to allow yacc to break the reduce/reduce conflict
- * with singleton expressions.
- * Eliminated lots of code by defining row_op and sub_type clauses.
- * However, can not consolidate EXPR_LINK case with others subselects
- * due to shift/reduce conflict with the non-subselect clause (the parser
- * would have to look ahead more than one token to resolve the conflict).
- * - thomas 1998-05-09
- */
- row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = $2;
- n->oper = lcons("=",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $6;
- $$ = (Node *)n;
- }
- | '(' row_descriptor ')' NOT IN '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = $2;
- n->oper = lcons("<>",NIL);
- n->useor = true;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $7;
- $$ = (Node *)n;
- }
- | '(' row_descriptor ')' row_op sub_type '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = $2;
- n->oper = lcons($4, NIL);
- if (strcmp($4,"<>") == 0)
- n->useor = true;
- else
- n->useor = false;
- n->subLinkType = $5;
- n->subselect = $7;
- $$ = (Node *)n;
- }
- | '(' row_descriptor ')' row_op '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = $2;
- n->oper = lcons($4, NIL);
- if (strcmp($4,"<>") == 0)
- n->useor = true;
- else
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $6;
- $$ = (Node *)n;
- }
- | '(' row_descriptor ')' row_op '(' row_descriptor ')'
- {
- $$ = makeRowExpr($4, $2, $6);
- }
- ;
- row_descriptor: row_list ',' a_expr
- {
- $$ = lappend($1, $3);
- }
- ;
- row_list: row_list ',' a_expr
- {
- $$ = lappend($1, $3);
- }
- | a_expr
- {
- $$ = lcons($1, NIL);
- }
- ;
- row_op: Op { $$ = $1; }
- | '<' { $$ = "<"; }
- | '=' { $$ = "="; }
- | '>' { $$ = ">"; }
- | '+' { $$ = "+"; }
- | '-' { $$ = "-"; }
- | '*' { $$ = "*"; }
- | '/' { $$ = "/"; }
- | '%' { $$ = "%"; }
- ;
- sub_type: ANY { $$ = ANY_SUBLINK; }
- | ALL { $$ = ALL_SUBLINK; }
- ;
- /* General expressions
- * 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/expressions are allowed in a BETWEEN clause
- * if surrounded by parens.
- */
- a_expr: attr opt_indirection
- {
- $1->indirection = $2;
- $$ = (Node *)$1;
- }
- | row_expr
- { $$ = $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
- { $$ = doNegate($2); }
- | '%' a_expr
- { $$ = makeA_Expr(OP, "%", NULL, $2); }
- | '^' a_expr
- { $$ = makeA_Expr(OP, "^", NULL, $2); }
- | a_expr '%'
- { $$ = makeA_Expr(OP, "%", $1, NULL); }
- | a_expr '^'
- { $$ = makeA_Expr(OP, "^", $1, NULL); }
- | a_expr '+' a_expr
- { $$ = makeA_Expr(OP, "+", $1, $3); }
- | a_expr '-' a_expr
- { $$ = makeA_Expr(OP, "-", $1, $3); }
- | a_expr '/' a_expr
- { $$ = makeA_Expr(OP, "/", $1, $3); }
- | a_expr '%' a_expr
- { $$ = makeA_Expr(OP, "%", $1, $3); }
- | a_expr '*' a_expr
- { $$ = makeA_Expr(OP, "*", $1, $3); }
- | a_expr '^' a_expr
- { $$ = makeA_Expr(OP, "^", $1, $3); }
- | a_expr '<' a_expr
- { $$ = makeA_Expr(OP, "<", $1, $3); }
- | a_expr '>' a_expr
- { $$ = makeA_Expr(OP, ">", $1, $3); }
- | a_expr '=' NULL_P
- { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
- /* We allow this for standards-broken SQL products, like MS stuff */
- | NULL_P '=' a_expr
- { $$ = makeA_Expr(ISNULL, NULL, $3, NULL); }
- | a_expr '=' a_expr
- { $$ = makeA_Expr(OP, "=", $1, $3); }
- | ':' a_expr
- { $$ = makeA_Expr(OP, ":", NULL, $2); }
- | ';' a_expr
- { $$ = makeA_Expr(OP, ";", NULL, $2); }
- | '|' a_expr
- { $$ = makeA_Expr(OP, "|", NULL, $2); }
- | a_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 '(' a_expr AS Typename ')'
- {
- $$ = (Node *)$3;
- /* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($3) == T_A_Const) {
- ((A_Const *)$3)->typename = $5;
- } else if (nodeTag($5) == T_Param) {
- ((ParamNo *)$3)->typename = $5;
- /* otherwise, try to transform to a function call */
- } else {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $5->name;
- n->args = lcons($3,NIL);
- $$ = (Node *)n;
- }
- }
- | '(' a_expr_or_null ')'
- { $$ = $2; }
- | a_expr Op a_expr
- { $$ = makeIndexable($2,$1,$3); }
- | a_expr LIKE a_expr
- { $$ = makeIndexable("~~", $1, $3); }
- | a_expr NOT LIKE a_expr
- { $$ = makeA_Expr(OP, "!~~", $1, $4); }
- | Op a_expr
- { $$ = makeA_Expr(OP, $1, NULL, $2); }
- | a_expr Op
- { $$ = makeA_Expr(OP, $2, $1, NULL); }
- | func_name '(' '*' ')'
- {
- /* cheap hack for aggregate (eg. count) */
- FuncCall *n = makeNode(FuncCall);
- A_Const *star = makeNode(A_Const);
- star->val.type = T_String;
- star->val.val.str = "";
- n->funcname = $1;
- n->args = lcons(star, NIL);
- $$ = (Node *)n;
- }
- | func_name '(' ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = NIL;
- $$ = (Node *)n;
- }
- | func_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;
- t->typmod = -1;
-
- $$ = (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;
- t->typmod = -1;
- $$ = (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;
- t->typmod = -1;
- 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;
- t->typmod = -1;
- $$ = (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;
- t->typmod = -1;
- 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;
- }
- | USER
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = "getpgusername";
- n->args = NIL;
- $$ = (Node *)n;
- }
- | EXISTS '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = NIL;
- n->useor = false;
- n->oper = NIL;
- n->subLinkType = EXISTS_SUBLINK;
- n->subselect = $3;
- $$ = (Node *)n;
- }
- | EXTRACT '(' extract_list ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = "date_part";
- n->args = $3;
- $$ = (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;
- }
- | a_expr ISNULL
- { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
- | a_expr IS NULL_P
- { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
- | a_expr NOTNULL
- { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
- | a_expr IS NOT NULL_P
- { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
- /* IS TRUE, IS FALSE, etc used to be function calls
- * but let's make them expressions to allow the optimizer
- * a chance to eliminate them if a_expr is a constant string.
- * - thomas 1997-12-22
- */
- | a_expr IS TRUE_P
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = "t";
- n->typename = makeNode(TypeName);
- n->typename->name = xlateSqlType("bool");
- n->typename->typmod = -1;
- $$ = makeA_Expr(OP, "=", $1,(Node *)n);
- }
- | a_expr IS NOT FALSE_P
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = "t";
- n->typename = makeNode(TypeName);
- n->typename->name = xlateSqlType("bool");
- n->typename->typmod = -1;
- $$ = makeA_Expr(OP, "=", $1,(Node *)n);
- }
- | a_expr IS FALSE_P
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = "f";
- n->typename = makeNode(TypeName);
- n->typename->name = xlateSqlType("bool");
- n->typename->typmod = -1;
- $$ = makeA_Expr(OP, "=", $1,(Node *)n);
- }
- | a_expr IS NOT TRUE_P
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = "f";
- n->typename = makeNode(TypeName);
- n->typename->name = xlateSqlType("bool");
- n->typename->typmod = -1;
- $$ = makeA_Expr(OP, "=", $1,(Node *)n);
- }
- | 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 b_expr AND b_expr
- {
- $$ = makeA_Expr(OR, NULL,
- makeA_Expr(OP, "<", $1, $4),
- makeA_Expr(OP, ">", $1, $6));
- }
- | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')'
- {
- saved_In_Expr = lnext(saved_In_Expr);
- if (nodeTag($5) == T_SubLink)
- {
- SubLink *n = (SubLink *)$5;
- n->lefthand = lcons($1, NIL);
- n->oper = lcons("=",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- $$ = (Node *)n;
- }
- else $$ = $5;
- }
- | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')'
- {
- saved_In_Expr = lnext(saved_In_Expr);
- if (nodeTag($6) == T_SubLink)
- {
- SubLink *n = (SubLink *)$6;
- n->lefthand = lcons($1, NIL);
- n->oper = lcons("<>",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- $$ = (Node *)n;
- }
- else $$ = $6;
- }
- | a_expr Op '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons($2,NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '+' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("+",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '-' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("-",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '/' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("/",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '%' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("%",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '*' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("*",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '<' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("<",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '>' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons(">",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr '=' '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("=",NIL);
- n->useor = false;
- n->subLinkType = EXPR_SUBLINK;
- n->subselect = $4;
- $$ = (Node *)n;
- }
- | a_expr Op ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons($2,NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '+' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons("+",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '-' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons("-",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '/' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons("/",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '%' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons("%",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '*' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons("*",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '<' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons("<",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '>' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons(">",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '=' ANY '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1,NIL);
- n->oper = lcons("=",NIL);
- n->useor = false;
- n->subLinkType = ANY_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr Op ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons($2,NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '+' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("+",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '-' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("-",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '/' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("/",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '%' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("%",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '*' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("*",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '<' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("<",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '>' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons(">",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr '=' ALL '(' SubSelect ')'
- {
- SubLink *n = makeNode(SubLink);
- n->lefthand = lcons($1, NULL);
- n->oper = lcons("=",NIL);
- n->useor = false;
- n->subLinkType = ALL_SUBLINK;
- n->subselect = $5;
- $$ = (Node *)n;
- }
- | a_expr AND a_expr
- { $$ = makeA_Expr(AND, NULL, $1, $3); }
- | a_expr OR a_expr
- { $$ = makeA_Expr(OR, NULL, $1, $3); }
- | NOT a_expr
- { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
- | case_expr
- { $$ = $1; }
- ;
- /* Restricted expressions
- * 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
- { $$ = doNegate($2); }
- | '%' b_expr
- { $$ = makeA_Expr(OP, "%", NULL, $2); }
- | '^' b_expr
- { $$ = makeA_Expr(OP, "^", NULL, $2); }
- | b_expr '%'
- { $$ = makeA_Expr(OP, "%", $1, NULL); }
- | b_expr '^'
- { $$ = makeA_Expr(OP, "^", $1, NULL); }
- | 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 '^' 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 *)$3;
- /* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($3) == T_A_Const) {
- ((A_Const *)$3)->typename = $5;
- } else if (nodeTag($3) == T_Param) {
- ((ParamNo *)$3)->typename = $5;
- /* otherwise, try to transform to a function call */
- } else {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $5->name;
- n->args = lcons($3,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); }
- | func_name '(' ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = NIL;
- $$ = (Node *)n;
- }
- | func_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;
- t->typmod = -1;
- $$ = (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;
- t->typmod = -1;
- $$ = (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;
- t->typmod = -1;
- 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;
- t->typmod = -1;
- $$ = (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;
- t->typmod = -1;
- 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;
- }
- | 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);
- ai->lidx = NULL;
- ai->uidx = $2;
- $$ = lcons(ai, $4);
- }
- | '[' a_expr ':' a_expr ']' opt_indirection
- {
- A_Indices *ai = makeNode(A_Indices);
- ai->lidx = $2;
- ai->uidx = $4;
- $$ = lcons(ai, $6);
- }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- expr_list: a_expr_or_null
- { $$ = lcons($1, NIL); }
- | expr_list ',' a_expr_or_null
- { $$ = lappend($1, $3); }
- | expr_list USING a_expr
- { $$ = lappend($1, $3); }
- ;
- extract_list: extract_arg FROM a_expr
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = $1;
- $$ = lappend(lcons((Node *)n,NIL), $3);
- }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- extract_arg: datetime { $$ = $1; }
- | TIMEZONE_HOUR { $$ = "tz_hour"; }
- | TIMEZONE_MINUTE { $$ = "tz_minute"; }
- ;
- position_list: position_expr IN position_expr
- { $$ = makeList($3, $1, -1); }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- position_expr: attr opt_indirection
- {
- $1->indirection = $2;
- $$ = (Node *)$1;
- }
- | AexprConst
- { $$ = $1; }
- | '-' position_expr %prec UMINUS
- { $$ = makeA_Expr(OP, "-", NULL, $2); }
- | position_expr '+' position_expr
- { $$ = makeA_Expr(OP, "+", $1, $3); }
- | position_expr '-' position_expr
- { $$ = makeA_Expr(OP, "-", $1, $3); }
- | position_expr '/' position_expr
- { $$ = makeA_Expr(OP, "/", $1, $3); }
- | position_expr '%' position_expr
- { $$ = makeA_Expr(OP, "%", $1, $3); }
- | position_expr '*' position_expr
- { $$ = makeA_Expr(OP, "*", $1, $3); }
- | '|' position_expr
- { $$ = makeA_Expr(OP, "|", NULL, $2); }
- | position_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 '(' position_expr AS Typename ')'
- {
- $$ = (Node *)$3;
- /* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($3) == T_A_Const) {
- ((A_Const *)$3)->typename = $5;
- } else if (nodeTag($3) == T_Param) {
- ((ParamNo *)$3)->typename = $5;
- /* otherwise, try to transform to a function call */
- } else {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $5->name;
- n->args = lcons($3,NIL);
- $$ = (Node *)n;
- }
- }
- | '(' position_expr ')'
- { $$ = $2; }
- | position_expr Op position_expr
- { $$ = makeA_Expr(OP, $2, $1, $3); }
- | Op position_expr
- { $$ = makeA_Expr(OP, $1, NULL, $2); }
- | position_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;
- }
- | func_name '(' ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = NIL;
- $$ = (Node *)n;
- }
- | func_name '(' expr_list ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $3;
- $$ = (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;
- }
- ;
- substr_list: expr_list substr_from substr_for
- {
- $$ = nconc(nconc($1,$2),$3);
- }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- substr_from: FROM expr_list
- { $$ = $2; }
- | /*EMPTY*/
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_Integer;
- n->val.val.ival = 1;
- $$ = lcons((Node *)n,NIL);
- }
- ;
- substr_for: FOR expr_list
- { $$ = $2; }
- | /*EMPTY*/
- { $$ = NIL; }
- ;
- trim_list: a_expr FROM expr_list
- { $$ = lappend($3, $1); }
- | FROM expr_list
- { $$ = $2; }
- | expr_list
- { $$ = $1; }
- ;
- in_expr: SubSelect
- {
- SubLink *n = makeNode(SubLink);
- n->subselect = $1;
- $$ = (Node *)n;
- }
- | in_expr_nodes
- { $$ = $1; }
- ;
- in_expr_nodes: AexprConst
- { $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); }
- | in_expr_nodes ',' AexprConst
- { $$ = makeA_Expr(OR, NULL, $1,
- makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3));
- }
- ;
- not_in_expr: SubSelect
- {
- SubLink *n = makeNode(SubLink);
- n->subselect = $1;
- $$ = (Node *)n;
- }
- | not_in_expr_nodes
- { $$ = $1; }
- ;
- not_in_expr_nodes: AexprConst
- { $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); }
- | not_in_expr_nodes ',' AexprConst
- { $$ = makeA_Expr(AND, NULL, $1,
- makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3));
- }
- ;
- /* Case clause
- * Define SQL92-style case clause.
- * Allow all four forms described in the standard:
- * - Full specification
- * CASE WHEN a = b THEN c ... ELSE d END
- * - Implicit argument
- * CASE a WHEN b THEN c ... ELSE d END
- * - Conditional NULL
- * NULLIF(x,y)
- * same as CASE WHEN x = y THEN NULL ELSE x END
- * - Conditional substitution from list, use first non-null argument
- * COALESCE(a,b,...)
- * same as CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ... END
- * - thomas 1998-11-09
- */
- case_expr: CASE case_arg when_clause_list case_default END_TRANS
- {
- CaseExpr *c = makeNode(CaseExpr);
- c->arg = $2;
- c->args = $3;
- c->defresult = $4;
- $$ = (Node *)c;
- }
- | NULLIF '(' a_expr ',' a_expr ')'
- {
- CaseExpr *c = makeNode(CaseExpr);
- CaseWhen *w = makeNode(CaseWhen);
- /*
- A_Const *n = makeNode(A_Const);
- n->val.type = T_Null;
- w->result = (Node *)n;
- */
- w->expr = makeA_Expr(OP, "=", $3, $5);
- c->args = lcons(w, NIL);
- c->defresult = $3;
- $$ = (Node *)c;
- }
- | COALESCE '(' expr_list ')'
- {
- CaseExpr *c = makeNode(CaseExpr);
- CaseWhen *w;
- List *l;
- foreach (l,$3)
- {
- w = makeNode(CaseWhen);
- w->expr = makeA_Expr(NOTNULL, NULL, lfirst(l), NULL);
- w->result = lfirst(l);
- c->args = lappend(c->args, w);
- }
- $$ = (Node *)c;
- }
- ;
- when_clause_list: when_clause_list when_clause
- { $$ = lappend($1, $2); }
- | when_clause
- { $$ = lcons($1, NIL); }
- ;
- when_clause: WHEN a_expr THEN a_expr_or_null
- {
- CaseWhen *w = makeNode(CaseWhen);
- w->expr = $2;
- w->result = $4;
- $$ = (Node *)w;
- }
- ;
- case_default: ELSE a_expr_or_null { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- case_arg: attr opt_indirection
- {
- $1->indirection = $2;
- $$ = (Node *)$1;
- }
- | ColId
- {
- /* could be a column name or a relation_name */
- Ident *n = makeNode(Ident);
- n->name = $1;
- n->indirection = NULL;
- $$ = (Node *)n;
- }
- | /*EMPTY*/
- { $$ = NULL; }
- ;
- attr: relation_name '.' attrs
- {
- $$ = makeNode(Attr);
- $$->relname = $1;
- $$->paramNo = NULL;
- $$->attrs = $3;
- $$->indirection = NULL;
- }
- | ParamNo '.' attrs
- {
- $$ = makeNode(Attr);
- $$->relname = NULL;
- $$->paramNo = $1;
- $$->attrs = $3;
- $$->indirection = NULL;
- }
- ;
- attrs: attr_name
- { $$ = lcons(makeString($1), NIL); }
- | attrs '.' attr_name
- { $$ = lappend($1, makeString($3)); }
- | attrs '.' '*'
- { $$ = lappend($1, makeString("*")); }
- ;
- /*****************************************************************************
- *
- * target lists
- *
- *****************************************************************************/
- res_target_list: res_target_list ',' res_target_el
- { $$ = lappend($1,$3); }
- | res_target_el
- { $$ = lcons($1, NIL); }
- | '*'
- {
- ResTarget *rt = makeNode(ResTarget);
- Attr *att = makeNode(Attr);
- att->relname = "*";
- att->paramNo = NULL;
- att->attrs = NULL;
- att->indirection = NIL;
- rt->name = NULL;
- rt->indirection = NULL;
- rt->val = (Node *)att;
- $$ = lcons(rt, NIL);
- }
- ;
- res_target_el: ColId opt_indirection '=' a_expr_or_null
- {
- $$ = makeNode(ResTarget);
- $$->name = $1;
- $$->indirection = $2;
- $$->val = (Node *)$4;
- }
- | attr opt_indirection
- {
- $$ = makeNode(ResTarget);
- $$->name = NULL;
- $$->indirection = $2;
- $$->val = (Node *)$1;
- }
- | relation_name '.' '*'
- {
- Attr *att = makeNode(Attr);
- att->relname = $1;
- att->paramNo = NULL;
- att->attrs = lcons(makeString("*"), NIL);
- att->indirection = NIL;
- $$ = makeNode(ResTarget);
- $$->name = NULL;
- $$->indirection = NULL;
- $$->val = (Node *)att;
- }
- ;
- /*
- ** target list for select.
- ** should get rid of the other but is still needed by the defunct select into
- ** and update (uses a subset)
- */
- res_target_list2: res_target_list2 ',' res_target_el2
- { $$ = lappend($1, $3); }
- | res_target_el2
- { $$ = lcons($1, NIL); }
- ;
- /* AS is not optional because shift/red conflict with unary ops */
- res_target_el2: a_expr_or_null AS ColLabel
- {
- $$ = makeNode(ResTarget);
- $$->name = $3;
- $$->indirection = NULL;
- $$->val = (Node *)$1;
- }
- | a_expr_or_null
- {
- $$ = makeNode(ResTarget);
- $$->name = NULL;
- $$->indirection = NULL;
- $$->val = (Node *)$1;
- }
- | relation_name '.' '*'
- {
- Attr *att = makeNode(Attr);
- att->relname = $1;
- att->paramNo = NULL;
- att->attrs = lcons(makeString("*"), NIL);
- att->indirection = NIL;
- $$ = makeNode(ResTarget);
- $$->name = NULL;
- $$->indirection = NULL;
- $$->val = (Node *)att;
- }
- | '*'
- {
- Attr *att = makeNode(Attr);
- att->relname = "*";
- att->paramNo = NULL;
- att->attrs = NULL;
- att->indirection = NIL;
- $$ = makeNode(ResTarget);
- $$->name = NULL;
- $$->indirection = NULL;
- $$->val = (Node *)att;
- }
- ;
- opt_id: ColId { $$ = $1; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
- relation_name: SpecialRuleRelation
- {
- $$ = $1;
- StrNCpy(saved_relname, $1, NAMEDATALEN);
- }
- | ColId
- {
- /* disallow refs to variable system tables */
- if (strcmp(LogRelationName, $1) == 0
- || strcmp(VariableRelationName, $1) == 0)
- elog(ERROR,"%s cannot be accessed by users",$1);
- else
- $$ = $1;
- StrNCpy(saved_relname, $1, NAMEDATALEN);
- }
- ;
- database_name: ColId { $$ = $1; };
- access_method: IDENT { $$ = $1; };
- attr_name: ColId { $$ = $1; };
- class: IDENT { $$ = $1; };
- index_name: ColId { $$ = $1; };
- /* Functions
- * Include date/time keywords as SQL92 extension.
- * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
- */
- name: ColId { $$ = $1; };
- func_name: ColId { $$ = xlateSqlFunc($1); };
- file_name: Sconst { $$ = $1; };
- /* NOT USED recipe_name: IDENT { $$ = $1; };*/
- /* Constants
- * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
- */
- AexprConst: Iconst
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_Integer;
- n->val.val.ival = $1;
- $$ = (Node *)n;
- }
- | FCONST
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_Float;
- n->val.val.dval = $1;
- $$ = (Node *)n;
- }
- | Sconst
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = $1;
- $$ = (Node *)n;
- }
- | Typename Sconst
- {
- A_Const *n = makeNode(A_Const);
- n->typename = $1;
- n->val.type = T_String;
- n->val.val.str = $2;
- $$ = (Node *)n;
- }
- | ParamNo
- { $$ = (Node *)$1; }
- | TRUE_P
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = "t";
- n->typename = makeNode(TypeName);
- n->typename->name = xlateSqlType("bool");
- n->typename->typmod = -1;
- $$ = (Node *)n;
- }
- | FALSE_P
- {
- A_Const *n = makeNode(A_Const);
- n->val.type = T_String;
- n->val.val.str = "f";
- n->typename = makeNode(TypeName);
- n->typename->name = xlateSqlType("bool");
- n->typename->typmod = -1;
- $$ = (Node *)n;
- }
- ;
- ParamNo: PARAM opt_indirection
- {
- $$ = makeNode(ParamNo);
- $$->number = $1;
- $$->indirection = $2;
- }
- ;
- Iconst: ICONST { $$ = $1; };
- Sconst: SCONST { $$ = $1; };
- UserId: IDENT { $$ = $1; };
- /* Column and type identifier
- * Does not include explicit datetime types
- * since these must be decoupled in Typename syntax.
- * Use ColId for most identifiers. - thomas 1997-10-21
- */
- TypeId: ColId
- { $$ = xlateSqlType($1); }
- | numeric
- { $$ = xlateSqlType($1); }
- | character
- { $$ = xlateSqlType($1); }
- ;
- /* Column identifier
- * Include date/time keywords as SQL92 extension.
- * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
- * Add other keywords. Note that as the syntax expands,
- * some of these keywords will have to be removed from this
- * list due to shift/reduce conflicts in yacc. If so, move
- * down to the ColLabel entity. - thomas 1997-11-06
- */
- ColId: IDENT { $$ = $1; }
- | datetime { $$ = $1; }
- | ABSOLUTE { $$ = "absolute"; }
- | ACCESS { $$ = "access"; }
- | ACTION { $$ = "action"; }
- | AFTER { $$ = "after"; }
- | AGGREGATE { $$ = "aggregate"; }
- | BACKWARD { $$ = "backward"; }
- | BEFORE { $$ = "before"; }
- | CACHE { $$ = "cache"; }
- | COMMITTED { $$ = "committed"; }
- | CREATEDB { $$ = "createdb"; }
- | CREATEUSER { $$ = "createuser"; }
- | CYCLE { $$ = "cycle"; }
- | DATABASE { $$ = "database"; }
- | DELIMITERS { $$ = "delimiters"; }
- | DOUBLE { $$ = "double"; }
- | EACH { $$ = "each"; }
- | ENCODING { $$ = "encoding"; }
- | EXCLUSIVE { $$ = "exclusive"; }
- | FORWARD { $$ = "forward"; }
- | FUNCTION { $$ = "function"; }
- | HANDLER { $$ = "handler"; }
- | INCREMENT { $$ = "increment"; }
- | INDEX { $$ = "index"; }
- | INHERITS { $$ = "inherits"; }
- | INSENSITIVE { $$ = "insensitive"; }
- | INSTEAD { $$ = "instead"; }
- | ISNULL { $$ = "isnull"; }
- | ISOLATION { $$ = "isolation"; }
- | KEY { $$ = "key"; }
- | LANGUAGE { $$ = "language"; }
- | LANCOMPILER { $$ = "lancompiler"; }
- | LEVEL { $$ = "level"; }
- | LOCATION { $$ = "location"; }
- | MATCH { $$ = "match"; }
- | MAXVALUE { $$ = "maxvalue"; }
- | MINVALUE { $$ = "minvalue"; }
- | MODE { $$ = "mode"; }
- | NEXT { $$ = "next"; }
- | NOCREATEDB { $$ = "nocreatedb"; }
- | NOCREATEUSER { $$ = "nocreateuser"; }
- | NOTHING { $$ = "nothing"; }
- | NOTNULL { $$ = "notnull"; }
- | OF { $$ = "of"; }
- | OIDS { $$ = "oids"; }
- | ONLY { $$ = "only"; }
- | OPERATOR { $$ = "operator"; }
- | OPTION { $$ = "option"; }
- | PASSWORD { $$ = "password"; }
- | PRIOR { $$ = "prior"; }
- | PRIVILEGES { $$ = "privileges"; }
- | PROCEDURAL { $$ = "procedural"; }
- | READ { $$ = "read"; }
- | RELATIVE { $$ = "relative"; }
- | RENAME { $$ = "rename"; }
- | RETURNS { $$ = "returns"; }
- | ROW { $$ = "row"; }
- | RULE { $$ = "rule"; }
- | SCROLL { $$ = "scroll"; }
- | SEQUENCE { $$ = "sequence"; }
- | SERIAL { $$ = "serial"; }
- | SERIALIZABLE { $$ = "serializable"; }
- | SHARE { $$ = "share"; }
- | START { $$ = "start"; }
- | STATEMENT { $$ = "statement"; }
- | STDIN { $$ = "stdin"; }
- | STDOUT { $$ = "stdout"; }
- | TIME { $$ = "time"; }
- | TIMESTAMP { $$ = "timestamp"; }
- | TIMEZONE_HOUR { $$ = "timezone_hour"; }
- | TIMEZONE_MINUTE { $$ = "timezone_minute"; }
- | TRIGGER { $$ = "trigger"; }
- | TRUSTED { $$ = "trusted"; }
- | TYPE_P { $$ = "type"; }
- | VALID { $$ = "valid"; }
- | VERSION { $$ = "version"; }
- | ZONE { $$ = "zone"; }
- ;
- /* Column label
- * Allowed labels in "AS" clauses.
- * Include TRUE/FALSE SQL3 reserved words for Postgres backward
- * compatibility. Cannot allow this for column names since the
- * syntax would not distinguish between the constant value and
- * a column name. - thomas 1997-10-24
- * Add other keywords to this list. Note that they appear here
- * rather than in ColId if there was a shift/reduce conflict
- * when used as a full identifier. - thomas 1997-11-06
- */
- ColLabel: ColId { $$ = $1; }
- | ABORT_TRANS { $$ = "abort"; }
- | ANALYZE { $$ = "analyze"; }
- | BINARY { $$ = "binary"; }
- | CASE { $$ = "case"; }
- | CLUSTER { $$ = "cluster"; }
- | COALESCE { $$ = "coalesce"; }
- | CONSTRAINT { $$ = "constraint"; }
- | COPY { $$ = "copy"; }
- | CURRENT { $$ = "current"; }
- | DO { $$ = "do"; }
- | ELSE { $$ = "else"; }
- | END_TRANS { $$ = "end"; }
- | EXPLAIN { $$ = "explain"; }
- | EXTEND { $$ = "extend"; }
- | FALSE_P { $$ = "false"; }
- | FOREIGN { $$ = "foreign"; }
- | GLOBAL { $$ = "global"; }
- | GROUP { $$ = "group"; }
- | LISTEN { $$ = "listen"; }
- | LOAD { $$ = "load"; }
- | LOCAL { $$ = "local"; }
- | LOCK_P { $$ = "lock"; }
- | MOVE { $$ = "move"; }
- | NEW { $$ = "new"; }
- | NONE { $$ = "none"; }
- | NULLIF { $$ = "nullif"; }
- | ORDER { $$ = "order"; }
- | POSITION { $$ = "position"; }
- | PRECISION { $$ = "precision"; }
- | RESET { $$ = "reset"; }
- | SETOF { $$ = "setof"; }
- | SHOW { $$ = "show"; }
- | TABLE { $$ = "table"; }
- | THEN { $$ = "then"; }
- | TRANSACTION { $$ = "transaction"; }
- | TRUE_P { $$ = "true"; }
- | VACUUM { $$ = "vacuum"; }
- | VERBOSE { $$ = "verbose"; }
- | WHEN { $$ = "when"; }
- ;
- SpecialRuleRelation: CURRENT
- {
- if (QueryIsRule)
- $$ = "*CURRENT*";
- else
- elog(ERROR,"CURRENT used in non-rule query");
- }
- | NEW
- {
- if (QueryIsRule)
- $$ = "*NEW*";
- else
- elog(ERROR,"NEW used in non-rule query");
- }
- ;
- %%
- static Node *
- makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
- {
- A_Expr *a = makeNode(A_Expr);
- a->oper = oper;
- a->opname = opname;
- a->lexpr = lexpr;
- a->rexpr = rexpr;
- return (Node *)a;
- }
- /* makeRowExpr()
- * Generate separate operator nodes for a single row descriptor expression.
- * Perhaps this should go deeper in the parser someday...
- * - thomas 1997-12-22
- */
- static Node *
- makeRowExpr(char *opr, List *largs, List *rargs)
- {
- Node *expr = NULL;
- Node *larg, *rarg;
- if (length(largs) != length(rargs))
- elog(ERROR,"Unequal number of entries in row expression");
- if (lnext(largs) != NIL)
- expr = makeRowExpr(opr,lnext(largs),lnext(rargs));
- larg = lfirst(largs);
- rarg = lfirst(rargs);
- if ((strcmp(opr, "=") == 0)
- || (strcmp(opr, "<") == 0)
- || (strcmp(opr, "<=") == 0)
- || (strcmp(opr, ">") == 0)
- || (strcmp(opr, ">=") == 0))
- {
- if (expr == NULL)
- expr = makeA_Expr(OP, opr, larg, rarg);
- else
- expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
- }
- else if (strcmp(opr, "<>") == 0)
- {
- if (expr == NULL)
- expr = makeA_Expr(OP, opr, larg, rarg);
- else
- expr = makeA_Expr(OR, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
- }
- else
- {
- elog(ERROR,"Operator '%s' not implemented for row expressions",opr);
- }
- return expr;
- }
- static void
- mapTargetColumns(List *src, List *dst)
- {
- ColumnDef *s;
- ResTarget *d;
- if (length(src) != length(dst))
- elog(ERROR,"CREATE TABLE/AS SELECT has mismatched column count");
- while ((src != NIL) && (dst != NIL))
- {
- s = (ColumnDef *)lfirst(src);
- d = (ResTarget *)lfirst(dst);
- d->name = s->colname;
- src = lnext(src);
- dst = lnext(dst);
- }
- return;
- } /* mapTargetColumns() */
- static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
- {
- Node *result = NULL;
-
- /* we do this so indexes can be used */
- if (strcmp(opname,"~") == 0 ||
- strcmp(opname,"~*") == 0)
- {
- if (nodeTag(rexpr) == T_A_Const &&
- ((A_Const *)rexpr)->val.type == T_String &&
- ((A_Const *)rexpr)->val.val.str[0] == '^')
- {
- A_Const *n = (A_Const *)rexpr;
- char *match_least = palloc(strlen(n->val.val.str)+2);
- char *match_most = palloc(strlen(n->val.val.str)+2);
- int pos, match_pos=0;
- bool found_special = false;
- /* Cannot optimize if unquoted | { } is present in pattern */
- for (pos = 1; n->val.val.str[pos]; pos++)
- {
- if (n->val.val.str[pos] == '|' ||
- n->val.val.str[pos] == '{' ||
- n->val.val.str[pos] == '}')
- {
- found_special = true;
- break;
- }
- if (n->val.val.str[pos] == '\')
- {
- pos++;
- if (n->val.val.str[pos] == ' ')
- break;
- }
- }
- if (!found_special)
- {
- /* note start at pos 1 to skip leading ^ */
- for (pos = 1; n->val.val.str[pos]; pos++)
- {
- if (n->val.val.str[pos] == '.' ||
- n->val.val.str[pos] == '?' ||
- n->val.val.str[pos] == '*' ||
- n->val.val.str[pos] == '[' ||
- n->val.val.str[pos] == '$' ||
- (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
- break;
- if (n->val.val.str[pos] == '\')
- {
- pos++;
- if (n->val.val.str[pos] == ' ')
- break;
- }
- match_least[match_pos] = n->val.val.str[pos];
- match_most[match_pos++] = n->val.val.str[pos];
- }
-
- if (match_pos != 0)
- {
- A_Const *least = makeNode(A_Const);
- A_Const *most = makeNode(A_Const);
-
- /* make strings to be used in index use */
- match_least[match_pos] = ' ';
- match_most[match_pos] = '377';
- match_most[match_pos+1] = ' ';
- least->val.type = T_String;
- least->val.val.str = match_least;
- most->val.type = T_String;
- most->val.val.str = match_most;
- #ifdef USE_LOCALE
- result = makeA_Expr(AND, NULL,
- makeA_Expr(OP, "~", lexpr, rexpr),
- makeA_Expr(OP, ">=", lexpr, (Node *)least));
- #else
- result = makeA_Expr(AND, NULL,
- makeA_Expr(OP, "~", lexpr, rexpr),
- makeA_Expr(AND, NULL,
- makeA_Expr(OP, ">=", lexpr, (Node *)least),
- makeA_Expr(OP, "<=", lexpr, (Node *)most)));
- #endif
- }
- }
- }
- }
- else if (strcmp(opname,"~~") == 0)
- {
- if (nodeTag(rexpr) == T_A_Const &&
- ((A_Const *)rexpr)->val.type == T_String)
- {
- A_Const *n = (A_Const *)rexpr;
- char *match_least = palloc(strlen(n->val.val.str)+2);
- char *match_most = palloc(strlen(n->val.val.str)+2);
- int pos, match_pos=0;
-
- for (pos = 0; n->val.val.str[pos]; pos++)
- {
- /* % and _ are wildcard characters in LIKE */
- if (n->val.val.str[pos] == '%' ||
- n->val.val.str[pos] == '_')
- break;
- /* Backslash quotes the next character */
- if (n->val.val.str[pos] == '\')
- {
- pos++;
- if (n->val.val.str[pos] == ' ')
- break;
- }
- /*
- * NOTE: this code used to think that %% meant a literal %,
- * but textlike() itself does not think that, and the SQL92
- * spec doesn't say any such thing either.
- */
- match_least[match_pos] = n->val.val.str[pos];
- match_most[match_pos++] = n->val.val.str[pos];
- }
-
- if (match_pos != 0)
- {
- A_Const *least = makeNode(A_Const);
- A_Const *most = makeNode(A_Const);
-
- /* make strings to be used in index use */
- match_least[match_pos] = ' ';
- match_most[match_pos] = '377';
- match_most[match_pos+1] = ' ';
- least->val.type = T_String;
- least->val.val.str = match_least;
- most->val.type = T_String;
- most->val.val.str = match_most;
- #ifdef USE_LOCALE
- result = makeA_Expr(AND, NULL,
- makeA_Expr(OP, "~~", lexpr, rexpr),
- makeA_Expr(OP, ">=", lexpr, (Node *)least));
- #else
- result = makeA_Expr(AND, NULL,
- makeA_Expr(OP, "~~", lexpr, rexpr),
- makeA_Expr(AND, NULL,
- makeA_Expr(OP, ">=", lexpr, (Node *)least),
- makeA_Expr(OP, "<=", lexpr, (Node *)most)));
- #endif
- }
- }
- }
-
- if (result == NULL)
- result = makeA_Expr(OP, opname, lexpr, rexpr);
- return result;
- } /* makeIndexable() */
- /* xlateSqlFunc()
- * Convert alternate type names to internal Postgres types.
- * Do not convert "float", since that is handled elsewhere
- * for FLOAT(p) syntax.
- */
- static char *
- xlateSqlFunc(char *name)
- {
- if (!strcasecmp(name,"character_length")
- || !strcasecmp(name,"char_length"))
- return "length";
- else
- return name;
- } /* xlateSqlFunc() */
- /* xlateSqlType()
- * Convert alternate type names to internal Postgres types.
- */
- static char *
- xlateSqlType(char *name)
- {
- if (!strcasecmp(name,"int")
- || !strcasecmp(name,"integer"))
- return "int4";
- else if (!strcasecmp(name, "smallint"))
- return "int2";
- else if (!strcasecmp(name, "real")
- || !strcasecmp(name, "float"))
- return "float8";
- else if (!strcasecmp(name, "interval"))
- return "timespan";
- else if (!strcasecmp(name, "boolean"))
- return "bool";
- else
- return name;
- } /* xlateSqlType() */
- void parser_init(Oid *typev, int nargs)
- {
- QueryIsRule = FALSE;
- saved_relname[0]= ' ';
- saved_In_Expr = NULL;
- param_type_init(typev, nargs);
- }
- /* FlattenStringList()
- * Traverse list of string nodes and convert to a single string.
- * Used for reconstructing string form of complex expressions.
- *
- * Allocate at least one byte for terminator.
- */
- static char *
- FlattenStringList(List *list)
- {
- List *l;
- Value *v;
- char *s;
- char *sp;
- int nlist, len = 0;
- nlist = length(list);
- l = list;
- while(l != NIL) {
- v = (Value *)lfirst(l);
- sp = v->val.str;
- l = lnext(l);
- len += strlen(sp);
- };
- len += nlist;
- s = (char*) palloc(len+1);
- *s = ' ';
- l = list;
- while(l != NIL) {
- v = (Value *)lfirst(l);
- sp = v->val.str;
- l = lnext(l);
- strcat(s,sp);
- if (l != NIL) strcat(s," ");
- };
- *(s+len) = ' ';
- return s;
- } /* FlattenStringList() */
- /* makeConstantList()
- * Convert constant value node into string node.
- */
- static List *
- makeConstantList( A_Const *n)
- {
- List *result = NIL;
- char *typval = NULL;
- char *defval = NULL;
- if (nodeTag(n) != T_A_Const) {
- elog(ERROR,"Cannot handle non-constant parameter");
- } else if (n->val.type == T_Float) {
- defval = (char*) palloc(20+1);
- sprintf( defval, "%g", n->val.val.dval);
- result = lcons( makeString(defval), NIL);
- } else if (n->val.type == T_Integer) {
- defval = (char*) palloc(20+1);
- sprintf( defval, "%ld", n->val.val.ival);
- result = lcons( makeString(defval), NIL);
- } else if (n->val.type == T_String) {
- defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
- strcpy( defval, "'");
- strcat( defval, ((A_Const *) n)->val.val.str);
- strcat( defval, "'");
- if (n->typename != NULL)
- {
- typval = (char*) palloc(strlen( n->typename->name) + 1);
- strcpy(typval, n->typename->name);
- result = lappend( lcons( makeString(typval), NIL), makeString(defval));
- }
- else
- {
- result = lcons( makeString(defval), NIL);
- }
- } else {
- elog(ERROR,"Internal error in makeConstantList(): cannot encode node");
- };
- return result;
- } /* makeConstantList() */
- /* fmtId()
- * Check input string for non-lowercase/non-numeric characters.
- * Returns either input string or input surrounded by double quotes.
- */
- static char *
- fmtId(char *rawid)
- {
- static char *cp;
- for (cp = rawid; *cp != ' '; cp++)
- if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
- if (*cp != ' ') {
- cp = palloc(strlen(rawid)+3);
- strcpy(cp,""");
- strcat(cp,rawid);
- strcat(cp,""");
- } else {
- cp = rawid;
- };
- return cp;
- }
- /*
- * param_type_init()
- *
- * keep enough information around fill out the type of param nodes
- * used in postquel functions
- */
- static void
- param_type_init(Oid *typev, int nargs)
- {
- pfunc_num_args = nargs;
- param_type_info = typev;
- }
- Oid param_type(int t)
- {
- if ((t > pfunc_num_args) || (t == 0))
- return InvalidOid;
- return param_type_info[t - 1];
- }
- /*
- * The optimizer doesn't like '-' 4 for index use. It only checks for
- * Var '=' Const. It wants an integer of -4, so we try to merge the
- * minus into the constant.
- */
- static Node *doNegate(Node *n)
- {
- if (IsA(n, A_Const))
- {
- A_Const *con = (A_Const *)n;
- if (con->val.type == T_Integer)
- {
- con->val.val.ival = -con->val.val.ival;
- return n;
- }
- if (con->val.type == T_Float)
- {
- con->val.val.dval = -con->val.val.dval;
- return n;
- }
- }
- return makeA_Expr(OP, "-", NULL, n);
- }