Commit 570620c5 authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Add SQL92 string handling features (SUBSTRING, TRIM, EXTRACT).

Add parsing for UNION and outer JOINs.
Implement SQL92 "WITH TIME ZONE".
Allow some reserved words as identifiers and column labels.
Clean up indentation and "orphan spaces and tabs".
parent 05cdb99b
...@@ -2,15 +2,15 @@ ...@@ -2,15 +2,15 @@
/*#define YYDEBUG 1*/ /*#define YYDEBUG 1*/
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* gram.y-- * gram.y--
* POSTGRES SQL YACC rules/actions * POSTGRES SQL YACC rules/actions
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.40 1997/08/28 05:02:01 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.41 1997/09/01 06:00:35 thomas Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -72,7 +72,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -72,7 +72,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%union { %union {
double dval; double dval;
int ival; int ival;
char chr; char chr;
char *str; char *str;
...@@ -96,7 +96,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -96,7 +96,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
A_Indices *aind; A_Indices *aind;
ResTarget *target; ResTarget *target;
ParamNo *paramno; ParamNo *paramno;
VersionStmt *vstmt; VersionStmt *vstmt;
DefineStmt *dstmt; DefineStmt *dstmt;
PurgeStmt *pstmt; PurgeStmt *pstmt;
...@@ -104,11 +104,11 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -104,11 +104,11 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
AppendStmt *astmt; AppendStmt *astmt;
} }
%type <node> stmt, %type <node> stmt,
AddAttrStmt, ClosePortalStmt, AddAttrStmt, ClosePortalStmt,
CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt, CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
ExtendStmt, FetchStmt, GrantStmt, ExtendStmt, FetchStmt, GrantStmt,
IndexStmt, MoveStmt, ListenStmt, OptimizableStmt, IndexStmt, MoveStmt, ListenStmt, OptimizableStmt,
ProcedureStmt, PurgeStmt, ProcedureStmt, PurgeStmt,
RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt, RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt, RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
...@@ -116,6 +116,13 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -116,6 +116,13 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt, ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
%type <str> txname
%type <node> SubSelect
%type <str> join_clause, join_type, join_outer, join_spec
%type <boolean> join_qual
%type <str> datetime
%type <str> relation_name, copy_file_name, copy_delimiter, def_name, %type <str> relation_name, copy_file_name, copy_delimiter, def_name,
database_name, access_method_clause, access_method, attr_name, database_name, access_method_clause, access_method, attr_name,
class, index_name, name, file_name, recipe_name, class, index_name, name, file_name, recipe_name,
...@@ -142,13 +149,21 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -142,13 +149,21 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
expr_list, default_expr_list, attrs, res_target_list, res_target_list2, expr_list, default_expr_list, attrs, res_target_list, res_target_list2,
def_list, opt_indirection, group_clause, groupby_list def_list, opt_indirection, group_clause, groupby_list
%type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy, %type <list> union_clause, select_list
%type <list> join_list
%type <sortgroupby> join_using
%type <list> extract_list, position_list
%type <list> substr_list, substr_from, substr_for, trim_list
%type <list> interval_opts
%type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_col, opt_with_copy,
index_opt_unique, opt_verbose, opt_analyze, opt_null index_opt_unique, opt_verbose, opt_analyze, opt_null
%type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation, %type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
def_type, opt_direction, remove_type, opt_column, event def_type, opt_direction, remove_type, opt_column, event
%type <ival> OptLocation, opt_move_where, fetch_how_many %type <ival> OptLocation, opt_move_where, fetch_how_many
%type <list> OptSeqList %type <list> OptSeqList
%type <defelt> OptSeqElem %type <defelt> OptSeqElem
...@@ -160,7 +175,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -160,7 +175,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%type <typnam> Typename, typname, opt_type %type <typnam> Typename, typname, opt_type
%type <coldef> columnDef %type <coldef> columnDef
%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, AexprConst,
default_expr, default_expr_or_null, default_expr, default_expr_or_null,
in_expr_nodes, not_in_expr_nodes, in_expr_nodes, not_in_expr_nodes,
...@@ -178,36 +193,40 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -178,36 +193,40 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%type <ival> Iconst %type <ival> Iconst
%type <str> Sconst %type <str> Sconst
%type <str> Id, date, var_value %type <str> Id, date, var_value, zone_value
%type <str> ColId
/* /*
* If you make any token changes, remember to: * If you make any token changes, remember to:
* - use "yacc -d" and update parse.h * - use "yacc -d" and update parse.h
* - update the keyword table in parser/keywords.c * - update the keyword table in parser/keywords.c
*/ */
/* Keywords */ /* Keywords */
%token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE, %token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC, AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BY, BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY,
CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN, COMMIT, CONSTRAINT, CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN, COMMIT, CONSTRAINT, COPY, CREATE, CROSS,
COPY, CREATE, CURRENT, CURSOR, DATABASE, DECLARE, DEFAULT, DELETE, CURRENT, CURSOR, DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
DELIMITERS, DESC, DISTINCT, DO, DROP, END_TRANS, DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND, EXTRACT,
EXTEND, FETCH, FOR, FORWARD, FROM, FUNCTION, GRANT, GROUP, FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP,
HAVING, HEAVY, IN, INDEX, INHERITS, INSERT, INSTEAD, INTO, IS, HAVING, HEAVY, HOURINTERVAL,
ISNULL, LANGUAGE, LIGHT, LISTEN, LOAD, MERGE, MOVE, NEW, IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTERVAL, INTO, IS, ISNULL,
NONE, NOT, NOTHING, NOTIFY, NOTNULL, JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL,
OIDS, ON, OPERATOR, OPTION, OR, ORDER, MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
PNULL, PRIVILEGES, PUBLIC, PURGE, P_TYPE, NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, ROLLBACK, RULE, OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE, PNULL, POSITION, PRIVILEGES, PUBLIC, PURGE, P_TYPE,
TABLE, TO, TRANSACTION, UNIQUE, UPDATE, USING, VACUUM, VALUES RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE,
VERBOSE, VERSION, VIEW, WHERE, WITH, WORK SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE, SUBSTRING,
TABLE, TIME, TO, TRAILING, TRANSACTION, TRIM,
UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE
%token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE %token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
/* Special keywords, not in the query language - see the "lex" file */ /* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT, SCONST, Op %token <str> IDENT, SCONST, Op
%token <ival> ICONST, PARAM %token <ival> ICONST, PARAM
%token <dval> FCONST %token <dval> FCONST
...@@ -218,7 +237,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -218,7 +237,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%left OR %left OR
%left AND %left AND
%right NOT %right NOT
%right '=' %right '='
%nonassoc LIKE %nonassoc LIKE
%nonassoc BETWEEN %nonassoc BETWEEN
%nonassoc IN %nonassoc IN
...@@ -226,17 +245,18 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr); ...@@ -226,17 +245,18 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%nonassoc NOTNULL %nonassoc NOTNULL
%nonassoc ISNULL %nonassoc ISNULL
%nonassoc IS %nonassoc IS
%left '+' '-' %left '+' '-'
%left '*' '/' %left '*' '/'
%left '|' /* this is the relation union op, not logical or */ %left '|' /* this is the relation union op, not logical or */
%right ':' /* Unary Operators */ %right ':' /* Unary Operators */
%left ';' /* end of statement or natural log */ %left ';' /* end of statement or natural log */
%nonassoc '<' '>' %nonassoc '<' '>'
%right UMINUS %right UMINUS
%left '.' %left '.'
%left '[' ']' %left '[' ']'
%nonassoc TYPECAST %nonassoc TYPECAST
%nonassoc REDUCE %nonassoc REDUCE
%left UNION
%% %%
stmtblock: stmtmulti stmtblock: stmtmulti
...@@ -264,23 +284,23 @@ stmt : AddAttrStmt ...@@ -264,23 +284,23 @@ stmt : AddAttrStmt
| ExtendStmt | ExtendStmt
| ExplainStmt | ExplainStmt
| FetchStmt | FetchStmt
| GrantStmt | GrantStmt
| IndexStmt | IndexStmt
| MoveStmt | MoveStmt
| ListenStmt | ListenStmt
| ProcedureStmt | ProcedureStmt
| PurgeStmt | PurgeStmt
| RecipeStmt | RecipeStmt
| RemoveAggrStmt | RemoveAggrStmt
| RemoveOperStmt | RemoveOperStmt
| RemoveFuncStmt | RemoveFuncStmt
| RemoveStmt | RemoveStmt
| RenameStmt | RenameStmt
| RevokeStmt | RevokeStmt
| OptimizableStmt | OptimizableStmt
| RuleStmt | RuleStmt
| TransactionStmt | TransactionStmt
| ViewStmt | ViewStmt
| LoadStmt | LoadStmt
| CreatedbStmt | CreatedbStmt
| DestroydbStmt | DestroydbStmt
...@@ -291,25 +311,43 @@ stmt : AddAttrStmt ...@@ -291,25 +311,43 @@ stmt : AddAttrStmt
; ;
/***************************************************************************** /*****************************************************************************
* *
* Set PG internal variable * Set PG internal variable
* SET var_name TO 'var_value' * SET var_name TO 'var_value'
* *
*****************************************************************************/ *****************************************************************************/
VariableSetStmt: SET var_name TO var_value VariableSetStmt: SET var_name TO var_value
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = $2; n->name = $2;
n->value = $4; n->value = $4;
$$ = (Node *) n; $$ = (Node *) n;
} }
| SET var_name '=' var_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = $2;
n->value = $4;
$$ = (Node *) n;
}
| SET TIME ZONE zone_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "timezone";
n->value = $4;
$$ = (Node *) n;
}
; ;
var_value: Sconst { $$ = $1; } var_value: Sconst { $$ = $1; }
; ;
VariableShowStmt: SHOW var_name zone_value: Sconst { $$ = $1; }
| LOCAL { $$ = NULL; }
;
VariableShowStmt: SHOW var_name
{ {
VariableShowStmt *n = makeNode(VariableShowStmt); VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = $2; n->name = $2;
...@@ -317,7 +355,7 @@ VariableShowStmt: SHOW var_name ...@@ -317,7 +355,7 @@ VariableShowStmt: SHOW var_name
} }
; ;
VariableResetStmt: RESET var_name VariableResetStmt: RESET var_name
{ {
VariableResetStmt *n = makeNode(VariableResetStmt); VariableResetStmt *n = makeNode(VariableResetStmt);
n->name = $2; n->name = $2;
...@@ -342,13 +380,22 @@ AddAttrStmt: ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef ...@@ -342,13 +380,22 @@ AddAttrStmt: ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef
} }
; ;
columnDef: Id Typename OptDefault opt_null /* Column definition might include WITH TIME ZONE, but only for the data types
* called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
* and "time". - thomas 1997-07-14
*/
columnDef: Id Typename opt_with_col OptDefault opt_null
{ {
$$ = makeNode(ColumnDef); $$ = makeNode(ColumnDef);
$$->colname = $1; $$->colname = $1;
$$->typename = $2; $$->typename = $2;
$$->defval = $3; $$->typename->timezone = $3;
$$->is_not_null = $4; $$->defval = $4;
$$->is_not_null = $5;
if ($$->typename->timezone
&& (strcasecmp($$->typename->name, "timestamp")
&& strcasecmp($$->typename->name, "time")))
elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
} }
; ;
...@@ -457,18 +504,21 @@ default_expr_list: default_expr_or_null ...@@ -457,18 +504,21 @@ default_expr_list: default_expr_or_null
opt_null: NOT PNULL { $$ = true; } opt_null: NOT PNULL { $$ = true; }
| NOTNULL { $$ = true; } | NOTNULL { $$ = true; }
| /* EMPTY */ { $$ = false; } | /* EMPTY */ { $$ = false; }
;
opt_with_col: WITH TIME ZONE { $$ = TRUE; }
| /* EMPTY */ { $$ = FALSE; }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY : * QUERY :
* close <optname> * close <optname>
* *
*****************************************************************************/ *****************************************************************************/
ClosePortalStmt: CLOSE opt_id ClosePortalStmt: CLOSE opt_id
{ {
ClosePortalStmt *n = makeNode(ClosePortalStmt); ClosePortalStmt *n = makeNode(ClosePortalStmt);
n->portalname = $2; n->portalname = $2;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -479,7 +529,7 @@ ClosePortalStmt: CLOSE opt_id ...@@ -479,7 +529,7 @@ ClosePortalStmt: CLOSE opt_id
/***************************************************************************** /*****************************************************************************
* *
* QUERY : * QUERY :
* COPY [BINARY] <relname> FROM/TO * COPY [BINARY] <relname> FROM/TO
* [USING DELIMITERS <delimiter>] * [USING DELIMITERS <delimiter>]
* *
*****************************************************************************/ *****************************************************************************/
...@@ -497,13 +547,13 @@ CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name ...@@ -497,13 +547,13 @@ CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name
} }
; ;
copy_dirn: TO copy_dirn: TO
{ $$ = TO; } { $$ = TO; }
| FROM | FROM
{ $$ = FROM; } { $$ = FROM; }
; ;
/* /*
* copy_file_name NULL indicates stdio is used. Whether stdin or stdout is * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
* used depends on the direction. (It really doesn't make sense to copy from * used depends on the direction. (It really doesn't make sense to copy from
* stdout. We silently correct the "typo". - AY 9/94 * stdout. We silently correct the "typo". - AY 9/94
...@@ -557,9 +607,9 @@ OptTableElementList: tableElementList { $$ = $1; } ...@@ -557,9 +607,9 @@ OptTableElementList: tableElementList { $$ = $1; }
; ;
tableElementList : tableElementList :
tableElementList ',' columnDef tableElementList ',' columnDef
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
| columnDef | columnDef
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
...@@ -568,20 +618,20 @@ OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; } ...@@ -568,20 +618,20 @@ OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
| /*EMPTY*/ { $$ = ARCH_NONE; } | /*EMPTY*/ { $$ = ARCH_NONE; }
; ;
archive_type: HEAVY { $$ = ARCH_HEAVY; } archive_type: HEAVY { $$ = ARCH_HEAVY; }
| LIGHT { $$ = ARCH_LIGHT; } | LIGHT { $$ = ARCH_LIGHT; }
| NONE { $$ = ARCH_NONE; } | NONE { $$ = ARCH_NONE; }
; ;
OptLocation: STORE '=' Sconst OptLocation: STORE '=' Sconst
{ $$ = smgrin($3); } { $$ = smgrin($3); }
| /*EMPTY*/ | /*EMPTY*/
{ $$ = -1; } { $$ = -1; }
; ;
OptArchiveLocation: ARCH_STORE '=' Sconst OptArchiveLocation: ARCH_STORE '=' Sconst
{ $$ = smgrin($3); } { $$ = smgrin($3); }
| /*EMPTY*/ | /*EMPTY*/
{ $$ = -1; } { $$ = -1; }
; ;
...@@ -642,14 +692,14 @@ CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList ...@@ -642,14 +692,14 @@ CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
} }
; ;
OptSeqList: OptSeqList:
OptSeqList OptSeqElem OptSeqList OptSeqElem
{ $$ = lappend($1, $2); } { $$ = lappend($1, $2); }
| { $$ = NIL; } | { $$ = NIL; }
; ;
OptSeqElem: IDENT NumConst OptSeqElem: IDENT NumConst
{ {
$$ = makeNode(DefElem); $$ = makeNode(DefElem);
$$->defname = $1; $$->defname = $1;
$$->arg = (Node *)$2; $$->arg = (Node *)$2;
...@@ -665,7 +715,7 @@ OptSeqElem: IDENT NumConst ...@@ -665,7 +715,7 @@ OptSeqElem: IDENT NumConst
/***************************************************************************** /*****************************************************************************
* *
* QUERY : * QUERY :
* define (type,operator,aggregate) * define (type,operator,aggregate)
* *
*****************************************************************************/ *****************************************************************************/
...@@ -677,7 +727,7 @@ DefineStmt: CREATE def_type def_rest ...@@ -677,7 +727,7 @@ DefineStmt: CREATE def_type def_rest
} }
; ;
def_rest: def_name definition def_rest: def_name definition
{ {
$$ = makeNode(DefineStmt); $$ = makeNode(DefineStmt);
$$->defname = $1; $$->defname = $1;
...@@ -685,12 +735,12 @@ def_rest: def_name definition ...@@ -685,12 +735,12 @@ def_rest: def_name definition
} }
; ;
def_type: OPERATOR { $$ = OPERATOR; } def_type: OPERATOR { $$ = OPERATOR; }
| Type { $$ = P_TYPE; } | Type { $$ = P_TYPE; }
| AGGREGATE { $$ = AGGREGATE; } | AGGREGATE { $$ = AGGREGATE; }
; ;
def_name: Id | MathOp | Op def_name: Id | MathOp | Op
; ;
...@@ -705,7 +755,7 @@ def_list: def_elem ...@@ -705,7 +755,7 @@ def_list: def_elem
; ;
def_elem: def_name '=' def_arg def_elem: def_name '=' def_arg
{ {
$$ = makeNode(DefElem); $$ = makeNode(DefElem);
$$->defname = $1; $$->defname = $1;
$$->arg = (Node *)$3; $$->arg = (Node *)$3;
...@@ -728,33 +778,33 @@ def_elem: def_name '=' def_arg ...@@ -728,33 +778,33 @@ def_elem: def_name '=' def_arg
def_arg: Id { $$ = (Node *)makeString($1); } def_arg: Id { $$ = (Node *)makeString($1); }
| all_Op { $$ = (Node *)makeString($1); } | all_Op { $$ = (Node *)makeString($1); }
| NumConst { $$ = (Node *)$1; /* already a Value */ } | NumConst { $$ = (Node *)$1; /* already a Value */ }
| Sconst { $$ = (Node *)makeString($1); } | Sconst { $$ = (Node *)makeString($1); }
| SETOF Id { | SETOF Id {
TypeName *n = makeNode(TypeName); TypeName *n = makeNode(TypeName);
n->name = $2; n->name = $2;
n->setof = TRUE; n->setof = TRUE;
n->arrayBounds = NULL; n->arrayBounds = NULL;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
* destroy <relname1> [, <relname2> .. <relnameN> ] * destroy <relname1> [, <relname2> .. <relnameN> ]
* *
*****************************************************************************/ *****************************************************************************/
DestroyStmt: DROP TABLE relation_name_list DestroyStmt: DROP TABLE relation_name_list
{ {
DestroyStmt *n = makeNode(DestroyStmt); DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3; n->relNames = $3;
n->sequence = false; n->sequence = false;
$$ = (Node *)n; $$ = (Node *)n;
} }
| DROP SEQUENCE relation_name_list | DROP SEQUENCE relation_name_list
{ {
DestroyStmt *n = makeNode(DestroyStmt); DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3; n->relNames = $3;
n->sequence = true; n->sequence = true;
...@@ -785,7 +835,7 @@ opt_direction: FORWARD { $$ = FORWARD; } ...@@ -785,7 +835,7 @@ opt_direction: FORWARD { $$ = FORWARD; }
| /*EMPTY*/ { $$ = FORWARD; /* default */ } | /*EMPTY*/ { $$ = FORWARD; /* default */ }
; ;
fetch_how_many: Iconst fetch_how_many: Iconst
{ $$ = $1; { $$ = $1;
if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch"); } if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch"); }
| ALL { $$ = 0; /* 0 means fetch all tuples*/} | ALL { $$ = 0; /* 0 means fetch all tuples*/}
...@@ -800,70 +850,70 @@ fetch_how_many: Iconst ...@@ -800,70 +850,70 @@ fetch_how_many: Iconst
*****************************************************************************/ *****************************************************************************/
GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
{ {
$$ = (Node*)makeAclStmt($2,$4,$6,'+'); $$ = (Node*)makeAclStmt($2,$4,$6,'+');
free($2); free($2);
free($6); free($6);
} }
; ;
privileges: ALL PRIVILEGES privileges: ALL PRIVILEGES
{ {
$$ = aclmakepriv("rwaR",0); $$ = aclmakepriv("rwaR",0);
} }
| ALL | ALL
{ {
$$ = aclmakepriv("rwaR",0); $$ = aclmakepriv("rwaR",0);
} }
| operation_commalist { | operation_commalist {
$$ = $1; $$ = $1;
} }
; ;
operation_commalist: operation { operation_commalist: operation {
$$ = aclmakepriv("",$1); $$ = aclmakepriv("",$1);
} }
| operation_commalist ',' operation | operation_commalist ',' operation
{ {
$$ = aclmakepriv($1,$3); $$ = aclmakepriv($1,$3);
free($1); free($1);
} }
; ;
operation: SELECT { operation: SELECT {
$$ = ACL_MODE_RD_CHR; $$ = ACL_MODE_RD_CHR;
} }
| INSERT { | INSERT {
$$ = ACL_MODE_AP_CHR; $$ = ACL_MODE_AP_CHR;
} }
| UPDATE { | UPDATE {
$$ = ACL_MODE_WR_CHR; $$ = ACL_MODE_WR_CHR;
} }
| DELETE { | DELETE {
$$ = ACL_MODE_WR_CHR; $$ = ACL_MODE_WR_CHR;
} }
| RULE { | RULE {
$$ = ACL_MODE_RU_CHR; $$ = ACL_MODE_RU_CHR;
} }
; ;
grantee: PUBLIC { grantee: PUBLIC {
$$ = aclmakeuser("A",""); $$ = aclmakeuser("A","");
} }
| GROUP Id { | GROUP Id {
$$ = aclmakeuser("G",$2); $$ = aclmakeuser("G",$2);
} }
| Id { | Id {
$$ = aclmakeuser("U",$1); $$ = aclmakeuser("U",$1);
} }
; ;
opt_with_grant : /* empty */ opt_with_grant : /* empty */
| WITH GRANT OPTION | WITH GRANT OPTION
{ {
yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges"); yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -872,12 +922,12 @@ opt_with_grant : /* empty */ ...@@ -872,12 +922,12 @@ opt_with_grant : /* empty */
*****************************************************************************/ *****************************************************************************/
RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
{ {
$$ = (Node*)makeAclStmt($2,$4,$6,'-'); $$ = (Node*)makeAclStmt($2,$4,$6,'-');
free($2); free($2);
free($6); free($6);
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
...@@ -887,7 +937,7 @@ RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee ...@@ -887,7 +937,7 @@ RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
*****************************************************************************/ *****************************************************************************/
MoveStmt: MOVE opt_direction opt_move_where opt_portal_name MoveStmt: MOVE opt_direction opt_move_where opt_portal_name
{ {
MoveStmt *n = makeNode(MoveStmt); MoveStmt *n = makeNode(MoveStmt);
n->direction = $2; n->direction = $2;
n->to = FALSE; n->to = FALSE;
...@@ -896,7 +946,7 @@ MoveStmt: MOVE opt_direction opt_move_where opt_portal_name ...@@ -896,7 +946,7 @@ MoveStmt: MOVE opt_direction opt_move_where opt_portal_name
$$ = (Node *)n; $$ = (Node *)n;
} }
| MOVE opt_direction TO Iconst opt_portal_name | MOVE opt_direction TO Iconst opt_portal_name
{ {
MoveStmt *n = makeNode(MoveStmt); MoveStmt *n = makeNode(MoveStmt);
n->direction = $2; n->direction = $2;
n->to = TRUE; n->to = TRUE;
...@@ -970,11 +1020,11 @@ ExtendStmt: EXTEND INDEX index_name where_clause ...@@ -970,11 +1020,11 @@ ExtendStmt: EXTEND INDEX index_name where_clause
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
* execute recipe <recipeName> * execute recipe <recipeName>
* *
*****************************************************************************/ *****************************************************************************/
RecipeStmt: EXECUTE RECIPE recipe_name RecipeStmt: EXECUTE RECIPE recipe_name
{ {
RecipeStmt *n; RecipeStmt *n;
if (!IsTransactionBlock()) if (!IsTransactionBlock())
...@@ -991,7 +1041,7 @@ RecipeStmt: EXECUTE RECIPE recipe_name ...@@ -991,7 +1041,7 @@ RecipeStmt: EXECUTE RECIPE recipe_name
* *
* QUERY: * QUERY:
* define function <fname> * define function <fname>
* (language = <lang>, returntype = <typename> * (language = <lang>, returntype = <typename>
* [, arch_pct = <percentage | pre-defined>] * [, arch_pct = <percentage | pre-defined>]
* [, disk_pct = <percentage | pre-defined>] * [, disk_pct = <percentage | pre-defined>]
* [, byte_pct = <percentage | pre-defined>] * [, byte_pct = <percentage | pre-defined>]
...@@ -1003,9 +1053,9 @@ RecipeStmt: EXECUTE RECIPE recipe_name ...@@ -1003,9 +1053,9 @@ RecipeStmt: EXECUTE RECIPE recipe_name
* *
*****************************************************************************/ *****************************************************************************/
ProcedureStmt: CREATE FUNCTION def_name def_args ProcedureStmt: CREATE FUNCTION def_name def_args
RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
{ {
ProcedureStmt *n = makeNode(ProcedureStmt); ProcedureStmt *n = makeNode(ProcedureStmt);
n->funcname = $3; n->funcname = $3;
n->defArgs = $4; n->defArgs = $4;
...@@ -1021,10 +1071,10 @@ opt_with: WITH definition { $$ = $2; } ...@@ -1021,10 +1071,10 @@ opt_with: WITH definition { $$ = $2; }
; ;
def_args: '(' def_name_list ')' { $$ = $2; } def_args: '(' def_name_list ')' { $$ = $2; }
| '(' ')' { $$ = NIL; } | '(' ')' { $$ = NIL; }
; ;
def_name_list: name_list; def_name_list: name_list;
/***************************************************************************** /*****************************************************************************
...@@ -1032,43 +1082,43 @@ def_name_list: name_list; ...@@ -1032,43 +1082,43 @@ def_name_list: name_list;
* QUERY: * QUERY:
* purge <relname> [before <date>] [after <date>] * purge <relname> [before <date>] [after <date>]
* or * or
* purge <relname> [after<date>][before <date>] * purge <relname> [after <date>] [before <date>]
* *
*****************************************************************************/ *****************************************************************************/
PurgeStmt: PURGE relation_name purge_quals PurgeStmt: PURGE relation_name purge_quals
{ {
$3->relname = $2; $3->relname = $2;
$$ = (Node *)$3; $$ = (Node *)$3;
} }
; ;
purge_quals: before_clause purge_quals: before_clause
{ {
$$ = makeNode(PurgeStmt); $$ = makeNode(PurgeStmt);
$$->beforeDate = $1; $$->beforeDate = $1;
$$->afterDate = NULL; $$->afterDate = NULL;
} }
| after_clause | after_clause
{ {
$$ = makeNode(PurgeStmt); $$ = makeNode(PurgeStmt);
$$->beforeDate = NULL; $$->beforeDate = NULL;
$$->afterDate = $1; $$->afterDate = $1;
} }
| before_clause after_clause | before_clause after_clause
{ {
$$ = makeNode(PurgeStmt); $$ = makeNode(PurgeStmt);
$$->beforeDate = $1; $$->beforeDate = $1;
$$->afterDate = $2; $$->afterDate = $2;
} }
| after_clause before_clause | after_clause before_clause
{ {
$$ = makeNode(PurgeStmt); $$ = makeNode(PurgeStmt);
$$->beforeDate = $2; $$->beforeDate = $2;
$$->afterDate = $1; $$->afterDate = $1;
} }
| /*EMPTY*/ | /*EMPTY*/
{ {
$$ = makeNode(PurgeStmt); $$ = makeNode(PurgeStmt);
$$->beforeDate = NULL; $$->beforeDate = NULL;
$$->afterDate = NULL; $$->afterDate = NULL;
...@@ -1105,11 +1155,11 @@ RemoveStmt: DROP remove_type name ...@@ -1105,11 +1155,11 @@ RemoveStmt: DROP remove_type name
} }
; ;
remove_type: Type { $$ = P_TYPE; } remove_type: Type { $$ = P_TYPE; }
| INDEX { $$ = INDEX; } | INDEX { $$ = INDEX; }
| RULE { $$ = RULE; } | RULE { $$ = RULE; }
| VIEW { $$ = VIEW; } | VIEW { $$ = VIEW; }
; ;
RemoveAggrStmt: DROP AGGREGATE name aggr_argtype RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
{ {
...@@ -1125,16 +1175,16 @@ aggr_argtype: name { $$ = $1; } ...@@ -1125,16 +1175,16 @@ aggr_argtype: name { $$ = $1; }
; ;
RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')' RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
{ {
RemoveFuncStmt *n = makeNode(RemoveFuncStmt); RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
n->funcname = $3; n->funcname = $3;
n->args = $5; n->args = $5;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
func_argtypes: name_list { $$ = $1; } func_argtypes: name_list { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')' RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
...@@ -1144,21 +1194,21 @@ RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')' ...@@ -1144,21 +1194,21 @@ RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
n->args = $5; n->args = $5;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
all_Op: Op | MathOp; all_Op: Op | MathOp;
MathOp: '+' { $$ = "+"; } MathOp: '+' { $$ = "+"; }
| '-' { $$ = "-"; } | '-' { $$ = "-"; }
| '*' { $$ = "*"; } | '*' { $$ = "*"; }
| '/' { $$ = "/"; } | '/' { $$ = "/"; }
| '<' { $$ = "<"; } | '<' { $$ = "<"; }
| '>' { $$ = ">"; } | '>' { $$ = ">"; }
| '=' { $$ = "="; } | '=' { $$ = "="; }
; ;
oper_argtypes: name oper_argtypes: name
{ {
elog(WARN, "parser: argument type missing (use NONE for unary operators)"); elog(WARN, "parser: argument type missing (use NONE for unary operators)");
} }
| name ',' name | name ',' name
...@@ -1171,15 +1221,15 @@ oper_argtypes: name ...@@ -1171,15 +1221,15 @@ oper_argtypes: name
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
* rename <attrname1> in <relname> [*] to <attrname2> * rename <attrname1> in <relname> [*] to <attrname2>
* rename <relname1> to <relname2> * rename <relname1> to <relname2>
* *
*****************************************************************************/ *****************************************************************************/
RenameStmt: ALTER TABLE relation_name opt_inh_star RenameStmt: ALTER TABLE relation_name opt_inh_star
RENAME opt_column opt_name TO name RENAME opt_column opt_name TO name
{ {
RenameStmt *n = makeNode(RenameStmt); RenameStmt *n = makeNode(RenameStmt);
n->relname = $3; n->relname = $3;
n->inh = $4; n->inh = $4;
...@@ -1199,15 +1249,15 @@ opt_column: COLUMN { $$ = COLUMN; } ...@@ -1199,15 +1249,15 @@ opt_column: COLUMN { $$ = COLUMN; }
/***************************************************************************** /*****************************************************************************
* *
* QUERY: Define Rewrite Rule , Define Tuple Rule * QUERY: Define Rewrite Rule , Define Tuple Rule
* Define Rule <old rules > * Define Rule <old rules >
* *
* only rewrite rule is supported -- ay 9/94 * only rewrite rule is supported -- ay 9/94
* *
*****************************************************************************/ *****************************************************************************/
RuleStmt: CREATE RULE name AS RuleStmt: CREATE RULE name AS
{ QueryIsRule=TRUE; } { QueryIsRule=TRUE; }
ON event TO event_object where_clause ON event TO event_object where_clause
DO opt_instead OptStmtList DO opt_instead OptStmtList
...@@ -1224,26 +1274,26 @@ RuleStmt: CREATE RULE name AS ...@@ -1224,26 +1274,26 @@ RuleStmt: CREATE RULE name AS
; ;
OptStmtList: NOTHING { $$ = NIL; } OptStmtList: NOTHING { $$ = NIL; }
| OptimizableStmt { $$ = lcons($1, NIL); } | OptimizableStmt { $$ = lcons($1, NIL); }
| '[' OptStmtBlock ']' { $$ = $2; } | '[' OptStmtBlock ']' { $$ = $2; }
; ;
OptStmtBlock: OptStmtMulti OptStmtBlock: OptStmtMulti
{ $$ = $1; } { $$ = $1; }
| OptimizableStmt | OptimizableStmt
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
OptStmtMulti: OptStmtMulti OptimizableStmt ';' OptStmtMulti: OptStmtMulti OptimizableStmt ';'
{ $$ = lappend($1, $2); } { $$ = lappend($1, $2); }
| OptStmtMulti OptimizableStmt | OptStmtMulti OptimizableStmt
{ $$ = lappend($1, $2); } { $$ = lappend($1, $2); }
| OptimizableStmt ';' | OptimizableStmt ';'
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
event_object: relation_name '.' attr_name event_object: relation_name '.' attr_name
{ {
$$ = makeNode(Attr); $$ = makeNode(Attr);
$$->relname = $1; $$->relname = $1;
$$->paramNo = NULL; $$->paramNo = NULL;
...@@ -1258,12 +1308,12 @@ event_object: relation_name '.' attr_name ...@@ -1258,12 +1308,12 @@ event_object: relation_name '.' attr_name
$$->attrs = NIL; $$->attrs = NIL;
$$->indirection = NIL; $$->indirection = NIL;
} }
; ;
/* change me to select, update, etc. some day */ /* change me to select, update, etc. some day */
event: SELECT { $$ = CMD_SELECT; } event: SELECT { $$ = CMD_SELECT; }
| UPDATE { $$ = CMD_UPDATE; } | UPDATE { $$ = CMD_UPDATE; }
| DELETE { $$ = CMD_DELETE; } | DELETE { $$ = CMD_DELETE; }
| INSERT { $$ = CMD_INSERT; } | INSERT { $$ = CMD_INSERT; }
; ;
...@@ -1280,7 +1330,7 @@ opt_instead: INSTEAD { $$ = TRUE; } ...@@ -1280,7 +1330,7 @@ opt_instead: INSTEAD { $$ = TRUE; }
* *
*****************************************************************************/ *****************************************************************************/
NotifyStmt: NOTIFY relation_name NotifyStmt: NOTIFY relation_name
{ {
NotifyStmt *n = makeNode(NotifyStmt); NotifyStmt *n = makeNode(NotifyStmt);
n->relname = $2; n->relname = $2;
...@@ -1288,7 +1338,7 @@ NotifyStmt: NOTIFY relation_name ...@@ -1288,7 +1338,7 @@ NotifyStmt: NOTIFY relation_name
} }
; ;
ListenStmt: LISTEN relation_name ListenStmt: LISTEN relation_name
{ {
ListenStmt *n = makeNode(ListenStmt); ListenStmt *n = makeNode(ListenStmt);
n->relname = $2; n->relname = $2;
...@@ -1307,74 +1357,74 @@ ListenStmt: LISTEN relation_name ...@@ -1307,74 +1357,74 @@ ListenStmt: LISTEN relation_name
* (BEGIN) * (BEGIN)
* end transaction * end transaction
* (END) * (END)
* *
*****************************************************************************/ *****************************************************************************/
TransactionStmt: ABORT_TRANS TRANSACTION TransactionStmt: ABORT_TRANS TRANSACTION
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = ABORT_TRANS; n->command = ABORT_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| BEGIN_TRANS TRANSACTION | BEGIN_TRANS TRANSACTION
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = BEGIN_TRANS; n->command = BEGIN_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| BEGIN_TRANS WORK | BEGIN_TRANS WORK
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = BEGIN_TRANS; n->command = BEGIN_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| COMMIT WORK | COMMIT WORK
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = END_TRANS; n->command = END_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| END_TRANS TRANSACTION | END_TRANS TRANSACTION
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = END_TRANS; n->command = END_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ROLLBACK WORK | ROLLBACK WORK
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = ABORT_TRANS; n->command = ABORT_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ABORT_TRANS | ABORT_TRANS
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = ABORT_TRANS; n->command = ABORT_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| BEGIN_TRANS | BEGIN_TRANS
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = BEGIN_TRANS; n->command = BEGIN_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| COMMIT | COMMIT
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = END_TRANS; n->command = END_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| END_TRANS | END_TRANS
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = END_TRANS; n->command = END_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ROLLBACK | ROLLBACK
{ {
TransactionStmt *n = makeNode(TransactionStmt); TransactionStmt *n = makeNode(TransactionStmt);
n->command = ABORT_TRANS; n->command = ABORT_TRANS;
$$ = (Node *)n; $$ = (Node *)n;
} }
...@@ -1389,7 +1439,7 @@ TransactionStmt: ABORT_TRANS TRANSACTION ...@@ -1389,7 +1439,7 @@ TransactionStmt: ABORT_TRANS TRANSACTION
*****************************************************************************/ *****************************************************************************/
ViewStmt: CREATE VIEW name AS RetrieveStmt ViewStmt: CREATE VIEW name AS RetrieveStmt
{ {
ViewStmt *n = makeNode(ViewStmt); ViewStmt *n = makeNode(ViewStmt);
n->viewname = $3; n->viewname = $3;
n->query = (Query *)$5; n->query = (Query *)$5;
...@@ -1406,12 +1456,12 @@ ViewStmt: CREATE VIEW name AS RetrieveStmt ...@@ -1406,12 +1456,12 @@ ViewStmt: CREATE VIEW name AS RetrieveStmt
*****************************************************************************/ *****************************************************************************/
LoadStmt: LOAD file_name LoadStmt: LOAD file_name
{ {
LoadStmt *n = makeNode(LoadStmt); LoadStmt *n = makeNode(LoadStmt);
n->filename = $2; n->filename = $2;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
/***************************************************************************** /*****************************************************************************
...@@ -1422,12 +1472,12 @@ LoadStmt: LOAD file_name ...@@ -1422,12 +1472,12 @@ LoadStmt: LOAD file_name
*****************************************************************************/ *****************************************************************************/
CreatedbStmt: CREATE DATABASE database_name CreatedbStmt: CREATE DATABASE database_name
{ {
CreatedbStmt *n = makeNode(CreatedbStmt); CreatedbStmt *n = makeNode(CreatedbStmt);
n->dbname = $3; n->dbname = $3;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
/***************************************************************************** /*****************************************************************************
...@@ -1438,12 +1488,12 @@ CreatedbStmt: CREATE DATABASE database_name ...@@ -1438,12 +1488,12 @@ CreatedbStmt: CREATE DATABASE database_name
*****************************************************************************/ *****************************************************************************/
DestroydbStmt: DROP DATABASE database_name DestroydbStmt: DROP DATABASE database_name
{ {
DestroydbStmt *n = makeNode(DestroydbStmt); DestroydbStmt *n = makeNode(DestroydbStmt);
n->dbname = $3; n->dbname = $3;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
/***************************************************************************** /*****************************************************************************
...@@ -1453,7 +1503,7 @@ DestroydbStmt: DROP DATABASE database_name ...@@ -1453,7 +1503,7 @@ DestroydbStmt: DROP DATABASE database_name
* *
*****************************************************************************/ *****************************************************************************/
ClusterStmt: CLUSTER index_name ON relation_name ClusterStmt: CLUSTER index_name ON relation_name
{ {
ClusterStmt *n = makeNode(ClusterStmt); ClusterStmt *n = makeNode(ClusterStmt);
n->relname = $4; n->relname = $4;
...@@ -1470,26 +1520,26 @@ ClusterStmt: CLUSTER index_name ON relation_name ...@@ -1470,26 +1520,26 @@ ClusterStmt: CLUSTER index_name ON relation_name
*****************************************************************************/ *****************************************************************************/
VacuumStmt: VACUUM opt_verbose opt_analyze VacuumStmt: VACUUM opt_verbose opt_analyze
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->verbose = $2; n->verbose = $2;
n->analyze = $3; n->analyze = $3;
n->vacrel = NULL; n->vacrel = NULL;
n->va_spec = NIL; n->va_spec = NIL;
$$ = (Node *)n; $$ = (Node *)n;
} }
| VACUUM opt_verbose relation_name opt_analyze opt_va_list | VACUUM opt_verbose relation_name opt_analyze opt_va_list
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->verbose = $2; n->verbose = $2;
n->analyze = $4; n->analyze = $4;
n->vacrel = $3; n->vacrel = $3;
n->va_spec = $5; n->va_spec = $5;
if ( $5 != NIL && !$4 ) if ( $5 != NIL && !$4 )
elog (WARN, "parser: syntax error at or near \"(\""); elog (WARN, "parser: syntax error at or near \"(\"");
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
opt_verbose: VERBOSE { $$ = TRUE; } opt_verbose: VERBOSE { $$ = TRUE; }
| /* EMPTY */ { $$ = FALSE; } | /* EMPTY */ { $$ = FALSE; }
...@@ -1503,14 +1553,14 @@ opt_va_list: '(' va_list ')' ...@@ -1503,14 +1553,14 @@ opt_va_list: '(' va_list ')'
{ $$ = $2; } { $$ = $2; }
| /* EMPTY */ | /* EMPTY */
{ $$ = NIL; } { $$ = NIL; }
; ;
va_list: name va_list: name
{ $$=lcons($1,NIL); } { $$=lcons($1,NIL); }
| va_list ',' name | va_list ',' name
{ $$=lappend($1,$3); } { $$=lappend($1,$3); }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1539,11 +1589,11 @@ ExplainStmt: EXPLAIN opt_verbose OptimizableStmt ...@@ -1539,11 +1589,11 @@ ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
*****************************************************************************/ *****************************************************************************/
OptimizableStmt: RetrieveStmt OptimizableStmt: RetrieveStmt
| CursorStmt | CursorStmt
| ReplaceStmt | ReplaceStmt
| AppendStmt | AppendStmt
| NotifyStmt | NotifyStmt
| DeleteStmt /* by default all are $$=$1 */ | DeleteStmt /* by default all are $$=$1 */
; ;
...@@ -1551,7 +1601,7 @@ OptimizableStmt: RetrieveStmt ...@@ -1551,7 +1601,7 @@ OptimizableStmt: RetrieveStmt
* *
* QUERY: * QUERY:
* INSERT STATEMENTS * INSERT STATEMENTS
* *
*****************************************************************************/ *****************************************************************************/
AppendStmt: INSERT INTO relation_name opt_column_list insert_rest AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
...@@ -1559,7 +1609,7 @@ AppendStmt: INSERT INTO relation_name opt_column_list insert_rest ...@@ -1559,7 +1609,7 @@ AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
$5->relname = $3; $5->relname = $3;
$5->cols = $4; $5->cols = $4;
$$ = (Node *)$5; $$ = (Node *)$5;
} }
; ;
insert_rest: VALUES '(' res_target_list2 ')' insert_rest: VALUES '(' res_target_list2 ')'
...@@ -1582,7 +1632,7 @@ opt_column_list: '(' columnList ')' { $$ = $2; } ...@@ -1582,7 +1632,7 @@ opt_column_list: '(' columnList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
columnList: columnList:
columnList ',' columnElem columnList ',' columnElem
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
| columnElem | columnElem
...@@ -1590,7 +1640,7 @@ columnList: ...@@ -1590,7 +1640,7 @@ columnList:
; ;
columnElem: Id opt_indirection columnElem: Id opt_indirection
{ {
Ident *id = makeNode(Ident); Ident *id = makeNode(Ident);
id->name = $1; id->name = $1;
id->indirection = $2; id->indirection = $2;
...@@ -1604,16 +1654,16 @@ columnElem: Id opt_indirection ...@@ -1604,16 +1654,16 @@ columnElem: Id opt_indirection
* DELETE STATEMENTS * DELETE STATEMENTS
* *
*****************************************************************************/ *****************************************************************************/
DeleteStmt: DELETE FROM relation_name DeleteStmt: DELETE FROM relation_name
where_clause where_clause
{ {
DeleteStmt *n = makeNode(DeleteStmt); DeleteStmt *n = makeNode(DeleteStmt);
n->relname = $3; n->relname = $3;
n->whereClause = $4; n->whereClause = $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
/***************************************************************************** /*****************************************************************************
...@@ -1623,20 +1673,20 @@ DeleteStmt: DELETE FROM relation_name ...@@ -1623,20 +1673,20 @@ DeleteStmt: DELETE FROM relation_name
* *
*****************************************************************************/ *****************************************************************************/
ReplaceStmt: UPDATE relation_name ReplaceStmt: UPDATE relation_name
SET res_target_list SET res_target_list
from_clause from_clause
where_clause where_clause
{ {
ReplaceStmt *n = makeNode(ReplaceStmt); ReplaceStmt *n = makeNode(ReplaceStmt);
n->relname = $2; n->relname = $2;
n->targetList = $4; n->targetList = $4;
n->fromClause = $5; n->fromClause = $5;
n->whereClause = $6; n->whereClause = $6;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
...@@ -1645,8 +1695,8 @@ ReplaceStmt: UPDATE relation_name ...@@ -1645,8 +1695,8 @@ ReplaceStmt: UPDATE relation_name
* *
*****************************************************************************/ *****************************************************************************/
CursorStmt: DECLARE name opt_binary CURSOR FOR CursorStmt: DECLARE name opt_binary CURSOR FOR
SELECT opt_unique res_target_list2 SELECT opt_unique res_target_list2
from_clause where_clause group_clause sort_clause from_clause where_clause group_clause sort_clause
{ {
CursorStmt *n = makeNode(CursorStmt); CursorStmt *n = makeNode(CursorStmt);
...@@ -1656,7 +1706,7 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR ...@@ -1656,7 +1706,7 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
* 15 august 1991 -- since 3.0 postgres does locking * 15 august 1991 -- since 3.0 postgres does locking
* right, we discovered that portals were violating * right, we discovered that portals were violating
* locking protocol. portal locks cannot span xacts. * locking protocol. portal locks cannot span xacts.
* as a short-term fix, we installed the check here. * as a short-term fix, we installed the check here.
* -- mao * -- mao
*/ */
if (!IsTransactionBlock()) if (!IsTransactionBlock())
...@@ -1682,11 +1732,12 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR ...@@ -1682,11 +1732,12 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
* *
*****************************************************************************/ *****************************************************************************/
/******************************************************************************
RetrieveStmt: SELECT opt_unique res_target_list2 RetrieveStmt: SELECT opt_unique res_target_list2
result from_clause where_clause result from_clause where_clause
group_clause having_clause group_clause having_clause
sort_clause sort_clause
{ {
RetrieveStmt *n = makeNode(RetrieveStmt); RetrieveStmt *n = makeNode(RetrieveStmt);
n->unique = $2; n->unique = $2;
n->targetList = $3; n->targetList = $3;
...@@ -1700,6 +1751,69 @@ RetrieveStmt: SELECT opt_unique res_target_list2 ...@@ -1700,6 +1751,69 @@ RetrieveStmt: SELECT opt_unique res_target_list2
} }
; ;
RetrieveStmt: Select UNION select_list sort_clause
| Select sort_clause
Select: SELECT opt_unique res_target_list2
result from_clause where_clause
group_clause having_clause
{
Select *n = makeNode(Select);
n->unique = $2;
n->targetList = $3;
n->into = $4;
n->fromClause = $5;
n->whereClause = $6;
n->groupClause = $7;
n->havingClause = $8;
$$ = (Node *)n;
}
;
******************************************************************************/
RetrieveStmt: SELECT opt_unique res_target_list2
result from_clause where_clause
group_clause having_clause
union_clause sort_clause
{
RetrieveStmt *n = makeNode(RetrieveStmt);
n->unique = $2;
n->targetList = $3;
n->into = $4;
n->fromClause = $5;
n->whereClause = $6;
n->groupClause = $7;
n->havingClause = $8;
n->selectClause = $9;
n->sortClause = $10;
$$ = (Node *)n;
}
;
union_clause: UNION select_list { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
select_list: select_list UNION SubSelect
{ $$ = lappend($1, $3); }
| SubSelect
{ $$ = lcons($1, NIL); }
;
SubSelect: SELECT opt_unique res_target_list2
result from_clause where_clause
group_clause having_clause
{
SubSelect *n = makeNode(SubSelect);
n->unique = $2;
n->targetList = $3;
n->fromClause = $5;
n->whereClause = $6;
n->groupClause = $7;
n->havingClause = $8;
$$ = (Node *)n;
}
;
result: INTO TABLE relation_name result: INTO TABLE relation_name
{ $$= $3; /* should check for archive level */ } { $$= $3; /* should check for archive level */ }
| /*EMPTY*/ | /*EMPTY*/
...@@ -1711,7 +1825,7 @@ opt_unique: DISTINCT { $$ = "*"; } ...@@ -1711,7 +1825,7 @@ opt_unique: DISTINCT { $$ = "*"; }
| /*EMPTY*/ { $$ = NULL;} | /*EMPTY*/ { $$ = NULL;}
; ;
sort_clause: ORDER BY sortby_list { $$ = $3; } sort_clause: ORDER BY sortby_list { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
...@@ -1722,7 +1836,7 @@ sortby_list: sortby ...@@ -1722,7 +1836,7 @@ sortby_list: sortby
; ;
sortby: Id OptUseOp sortby: Id OptUseOp
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortGroupBy);
$$->resno = 0; $$->resno = 0;
$$->range = NULL; $$->range = NULL;
...@@ -1782,13 +1896,13 @@ index_elem: attr_name opt_type opt_class ...@@ -1782,13 +1896,13 @@ index_elem: attr_name opt_type opt_class
$$->name = $1; $$->name = $1;
$$->args = NIL; $$->args = NIL;
$$->class = $3; $$->class = $3;
$$->tname = $2; $$->tname = $2;
} }
; ;
opt_type: ':' Typename { $$ = $2;} opt_type: ':' Typename { $$ = $2;}
| /*EMPTY*/ { $$ = NULL;} | /*EMPTY*/ { $$ = NULL;}
; ;
opt_class: class opt_class: class
| WITH class { $$ = $2; } | WITH class { $$ = $2; }
...@@ -1799,9 +1913,9 @@ opt_class: class ...@@ -1799,9 +1913,9 @@ opt_class: class
* jimmy bell-style recursive queries aren't supported in the * jimmy bell-style recursive queries aren't supported in the
* current system. * current system.
* *
* ...however, recursive addattr and rename supported. make special * ...however, recursive addattr and rename supported. make special
* cases for these. * cases for these.
* *
* XXX i believe '*' should be the default behavior, but... * XXX i believe '*' should be the default behavior, but...
*/ */
opt_inh_star: '*' { $$ = TRUE; } opt_inh_star: '*' { $$ = TRUE; }
...@@ -1810,11 +1924,11 @@ opt_inh_star: '*' { $$ = TRUE; } ...@@ -1810,11 +1924,11 @@ opt_inh_star: '*' { $$ = TRUE; }
relation_name_list: name_list ; relation_name_list: name_list ;
name_list: name name_list: name
{ $$=lcons(makeString($1),NIL); } { $$=lcons(makeString($1),NIL); }
| name_list ',' name | name_list ',' name
{ $$=lappend($1,makeString($3)); } { $$=lappend($1,makeString($3)); }
; ;
group_clause: GROUP BY groupby_list { $$ = $3; } group_clause: GROUP BY groupby_list { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
...@@ -1855,19 +1969,26 @@ having_clause: HAVING a_expr { $$ = $2; } ...@@ -1855,19 +1969,26 @@ having_clause: HAVING a_expr { $$ = $2; }
; ;
/***************************************************************************** /*****************************************************************************
* *
* clauses common to all Optimizable Stmts: * clauses common to all Optimizable Stmts:
* from_clause - * from_clause -
* where_clause - * where_clause -
* *
*****************************************************************************/ *****************************************************************************/
from_clause: FROM from_list { $$ = $2; } from_clause: FROM '(' relation_expr join_clause relation_expr join_spec ')'
{
$$ = NIL;
elog(WARN,"JOIN not yet implemented",NULL);
}
| FROM from_list { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
from_list: from_list ',' from_val from_list: from_list ',' from_val
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
| from_val CROSS JOIN from_val
{ elog(WARN,"CROSS JOIN not yet implemented",NULL); }
| from_val | from_val
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
...@@ -1877,7 +1998,7 @@ from_val: relation_expr AS var_name ...@@ -1877,7 +1998,7 @@ from_val: relation_expr AS var_name
$$ = makeNode(RangeVar); $$ = makeNode(RangeVar);
$$->relExpr = $1; $$->relExpr = $1;
$$->name = $3; $$->name = $3;
} }
| relation_expr var_name | relation_expr var_name
{ {
$$ = makeNode(RangeVar); $$ = makeNode(RangeVar);
...@@ -1892,12 +2013,76 @@ from_val: relation_expr AS var_name ...@@ -1892,12 +2013,76 @@ from_val: relation_expr AS var_name
} }
; ;
join_clause: join_qual join_type JOIN
{
$$ = NULL;
}
;
join_qual: NATURAL { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
join_type: FULL join_outer
{ elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
| LEFT join_outer
{ elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
| RIGHT join_outer
{ elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
| join_outer
{ elog(WARN,"OUTER JOIN not yet implemented",NULL); }
| INNERJOIN
{ elog(WARN,"INNER JOIN not yet implemented",NULL); }
| UNION
{ elog(WARN,"UNION JOIN not yet implemented",NULL); }
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
;
join_outer: OUTERJOIN { $$ = NULL; }
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
;
join_spec: ON '(' a_expr ')' { $$ = NULL; }
| USING '(' join_list ')' { $$ = NULL; }
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
;
join_list: join_using { $$ = lcons($1, NIL); }
| join_list ',' join_using { $$ = lappend($1, $3); }
;
join_using: Id
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
$$->range = NULL;
$$->name = $1;
$$->useOp = NULL;
}
| Id '.' Id
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
$$->range = $1;
$$->name = $3;
$$->useOp = NULL;
}
| Iconst
{
$$ = makeNode(SortGroupBy);
$$->resno = $1;
$$->range = NULL;
$$->name = NULL;
$$->useOp = NULL;
}
;
where_clause: WHERE a_expr { $$ = $2; } where_clause: WHERE a_expr { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ } | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
; ;
relation_expr: relation_name relation_expr: relation_name
{ {
/* normal relations */ /* normal relations */
$$ = makeNode(RelExpr); $$ = makeNode(RelExpr);
$$->relname = $1; $$->relname = $1;
...@@ -1905,15 +2090,15 @@ relation_expr: relation_name ...@@ -1905,15 +2090,15 @@ relation_expr: relation_name
$$->timeRange = NULL; $$->timeRange = NULL;
} }
| relation_name '*' %prec '=' | relation_name '*' %prec '='
{ {
/* inheiritance query */ /* inheiritance query */
$$ = makeNode(RelExpr); $$ = makeNode(RelExpr);
$$->relname = $1; $$->relname = $1;
$$->inh = TRUE; $$->inh = TRUE;
$$->timeRange = NULL; $$->timeRange = NULL;
} }
| relation_name time_range | relation_name time_range
{ {
/* time-qualified query */ /* time-qualified query */
$$ = makeNode(RelExpr); $$ = makeNode(RelExpr);
$$->relname = $1; $$->relname = $1;
...@@ -1922,20 +2107,20 @@ relation_expr: relation_name ...@@ -1922,20 +2107,20 @@ relation_expr: relation_name
} }
; ;
time_range: '[' opt_range_start ',' opt_range_end ']' time_range: '[' opt_range_start ',' opt_range_end ']'
{ {
$$ = makeNode(TimeRange); $$ = makeNode(TimeRange);
$$->startDate = $2; $$->startDate = $2;
$$->endDate = $4; $$->endDate = $4;
} }
| '[' date ']' | '[' date ']'
{ {
$$ = makeNode(TimeRange); $$ = makeNode(TimeRange);
$$->startDate = $2; $$->startDate = $2;
$$->endDate = NULL; $$->endDate = NULL;
} }
; ;
opt_range_start: date opt_range_start: date
| /*EMPTY*/ { $$ = "epoch"; } | /*EMPTY*/ { $$ = "epoch"; }
...@@ -1949,19 +2134,19 @@ opt_array_bounds: '[' ']' nest_array_bounds ...@@ -1949,19 +2134,19 @@ opt_array_bounds: '[' ']' nest_array_bounds
{ $$ = lcons(makeInteger(-1), $3); } { $$ = lcons(makeInteger(-1), $3); }
| '[' Iconst ']' nest_array_bounds | '[' Iconst ']' nest_array_bounds
{ $$ = lcons(makeInteger($2), $4); } { $$ = lcons(makeInteger($2), $4); }
| /* EMPTY */ | /* EMPTY */
{ $$ = NIL; } { $$ = NIL; }
; ;
nest_array_bounds: '[' ']' nest_array_bounds nest_array_bounds: '[' ']' nest_array_bounds
{ $$ = lcons(makeInteger(-1), $3); } { $$ = lcons(makeInteger(-1), $3); }
| '[' Iconst ']' nest_array_bounds | '[' Iconst ']' nest_array_bounds
{ $$ = lcons(makeInteger($2), $4); } { $$ = lcons(makeInteger($2), $4); }
| /*EMPTY*/ | /*EMPTY*/
{ $$ = NIL; } { $$ = NIL; }
; ;
typname: name typname: txname
{ {
char *tname = xlateSqlType($1); char *tname = xlateSqlType($1);
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
...@@ -1971,66 +2156,101 @@ typname: name ...@@ -1971,66 +2156,101 @@ typname: name
* it as a set. * it as a set.
*/ */
if (!strcmp(saved_relname, tname)) { if (!strcmp(saved_relname, tname)) {
/* This attr is the same type as the relation /* This attr is the same type as the relation
* being defined. The classic example: create * being defined. The classic example: create
* emp(name=text,mgr=emp) * emp(name=text,mgr=emp)
*/ */
$$->setof = TRUE; $$->setof = TRUE;
}else if (get_typrelid((Type)type(tname)) }else if (get_typrelid((Type)type(tname))
!= InvalidOid) { != InvalidOid) {
/* (Eventually add in here that the set can only /* (Eventually add in here that the set can only
* contain one element.) * contain one element.)
*/ */
$$->setof = TRUE; $$->setof = TRUE;
} else { } else {
$$->setof = FALSE; $$->setof = FALSE;
} }
} }
| SETOF name | SETOF txname
{ {
char *tname = xlateSqlType($2);
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
$$->name = $2; $$->name = tname;
$$->setof = TRUE; $$->setof = TRUE;
} }
; ;
Typename: typname opt_array_bounds txname: Id { $$ = $1; }
{ | TIME { $$ = "time"; }
| INTERVAL interval_opts { $$ = "interval"; }
;
interval_opts: YEARINTERVAL { $$ = lcons("year", NIL); }
| MONTHINTERVAL { $$ = NIL; }
| DAYINTERVAL { $$ = NIL; }
| HOURINTERVAL { $$ = NIL; }
| MINUTEINTERVAL { $$ = NIL; }
| SECONDINTERVAL { $$ = NIL; }
| YEARINTERVAL TO MONTHINTERVAL { $$ = NIL; }
| DAYINTERVAL TO HOURINTERVAL { $$ = NIL; }
| DAYINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
| DAYINTERVAL TO SECONDINTERVAL { $$ = NIL; }
| HOURINTERVAL TO MINUTEINTERVAL { $$ = NIL; }
| HOURINTERVAL TO SECONDINTERVAL { $$ = NIL; }
| /* EMPTY */ { $$ = NIL; }
;
Typename: typname opt_array_bounds
{
$$ = $1; $$ = $1;
$$->arrayBounds = $2; $$->arrayBounds = $2;
} }
| name '(' Iconst ')' | txname '(' Iconst ')'
{ {
/* /*
* The following implements char() and varchar(). * This block gets hit when the parser is passed a query
* We do it here instead of the 'typname:' production * which contains only spaces (e.g. from psql type " \g").
* because we don't want to allow arrays of varchar(). * Let's check explicitly for a zero-length argument
* I haven't thought about whether that will work or not. * here, and do nothing if so. This seems to fix the problem.
* - ay 6/95 * - thomas 1997-07-13
*/ */
$$ = makeNode(TypeName); if (strlen($1) > 0) {
if (!strcasecmp($1, "char")) {
$$->name = "bpchar"; /* strdup("bpchar"); */ /*
} else if (!strcasecmp($1, "varchar")) { * The following implements char() and varchar().
$$->name = "varchar"; /* strdup("varchar"); */ * We do it here instead of the 'typname:' production
} else { * because we don't want to allow arrays of varchar().
yyerror("parse error"); * I haven't thought about whether that will work or not.
} * - ay 6/95
if ($3 < 1) { */
elog(WARN, "length for '%s' type must be at least 1", $$ = makeNode(TypeName);
$1); if (!strcasecmp($1, "char")) {
} else if ($3 > 4096) { $$->name = "bpchar"; /* strdup("bpchar"); */
/* we can store a char() of length up to the size } else if (!strcasecmp($1, "varchar")) {
of a page (8KB) - page headers and friends but $$->name = "varchar"; /* strdup("varchar"); */
just to be safe here... - ay 6/95 */ } else {
elog(WARN, "length for '%s' type cannot exceed 4096", yyerror("parse error");
}
if ($3 < 1) {
elog(WARN, "length for '%s' type must be at least 1",
$1);
} else if ($3 > 4096) {
/* we can store a char() of length up to the size
* of a page (8KB) - page headers and friends but
* just to be safe here... - ay 6/95
* XXX note this hardcoded limit - thomas 1997-07-13
*/
elog(WARN, "length for '%s' type cannot exceed 4096",
$1); $1);
}
/* 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
*/
$$->typlen = 4 + $3;
} }
/* 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 */
$$->typlen = 4 + $3;
} }
; ;
...@@ -2044,12 +2264,12 @@ Typename: typname opt_array_bounds ...@@ -2044,12 +2264,12 @@ Typename: typname opt_array_bounds
a_expr_or_null: a_expr a_expr_or_null: a_expr
{ $$ = $1;} { $$ = $1;}
| Pnull | Pnull
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
n->val.type = T_Null; n->val.type = T_Null;
$$ = (Node *)n; $$ = (Node *)n;
} }
a_expr: attr opt_indirection a_expr: attr opt_indirection
{ {
$1->indirection = $2; $1->indirection = $2;
...@@ -2080,7 +2300,7 @@ a_expr: attr opt_indirection ...@@ -2080,7 +2300,7 @@ a_expr: attr opt_indirection
| '|' a_expr | '|' a_expr
{ $$ = makeA_Expr(OP, "|", NULL, $2); } { $$ = makeA_Expr(OP, "|", NULL, $2); }
| AexprConst TYPECAST Typename | AexprConst TYPECAST Typename
{ {
/* AexprConst can be either A_Const or ParamNo */ /* AexprConst can be either A_Const or ParamNo */
if (nodeTag($1) == T_A_Const) { if (nodeTag($1) == T_A_Const) {
((A_Const *)$1)->typename = $3; ((A_Const *)$1)->typename = $3;
...@@ -2124,7 +2344,7 @@ a_expr: attr opt_indirection ...@@ -2124,7 +2344,7 @@ a_expr: attr opt_indirection
Ident *star = makeNode(Ident); Ident *star = makeNode(Ident);
/* cheap hack for aggregate (eg. count) */ /* cheap hack for aggregate (eg. count) */
star->name = "oid"; star->name = "oid";
n->funcname = $1; n->funcname = $1;
n->args = lcons(star, NIL); n->args = lcons(star, NIL);
$$ = (Node *)n; $$ = (Node *)n;
...@@ -2136,6 +2356,66 @@ a_expr: attr opt_indirection ...@@ -2136,6 +2356,66 @@ a_expr: attr opt_indirection
n->args = NIL; n->args = NIL;
$$ = (Node *)n; $$ = (Node *)n;
} }
/* We probably need to define an "exists" node,
* since the optimizer could choose to find only one match.
* Perhaps the first implementation could just check for
* count(*) > 0? - thomas 1997-07-19
*/
| EXISTS '(' SubSelect ')'
{
elog(WARN,"EXISTS not yet supported",NULL);
$$ = $3;
}
| 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;
}
| name '(' expr_list ')' | name '(' expr_list ')'
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
...@@ -2154,7 +2434,7 @@ a_expr: attr opt_indirection ...@@ -2154,7 +2434,7 @@ a_expr: attr opt_indirection
| a_expr BETWEEN AexprConst AND AexprConst | a_expr BETWEEN AexprConst AND AexprConst
{ $$ = 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 AexprConst AND AexprConst
{ $$ = makeA_Expr(OR, NULL, { $$ = makeA_Expr(OR, NULL,
...@@ -2173,28 +2453,80 @@ a_expr: attr opt_indirection ...@@ -2173,28 +2453,80 @@ a_expr: attr opt_indirection
{ $$ = makeA_Expr(NOT, NULL, NULL, $2); } { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
; ;
opt_indirection: '[' a_expr ']' opt_indirection opt_indirection: '[' a_expr ']' opt_indirection
{ {
A_Indices *ai = makeNode(A_Indices); A_Indices *ai = makeNode(A_Indices);
ai->lidx = NULL; ai->lidx = NULL;
ai->uidx = $2; ai->uidx = $2;
$$ = lcons(ai, $4); $$ = lcons(ai, $4);
} }
| '[' a_expr ':' a_expr ']' opt_indirection | '[' a_expr ':' a_expr ']' opt_indirection
{ {
A_Indices *ai = makeNode(A_Indices); A_Indices *ai = makeNode(A_Indices);
ai->lidx = $2; ai->lidx = $2;
ai->uidx = $4; ai->uidx = $4;
$$ = lcons(ai, $6); $$ = lcons(ai, $6);
} }
| /* EMPTY */ | /* EMPTY */
{ $$ = NIL; } { $$ = NIL; }
; ;
expr_list: a_expr_or_null expr_list: a_expr_or_null
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
| expr_list ',' a_expr_or_null | expr_list ',' a_expr_or_null
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
| expr_list USING a_expr
{ $$ = lappend($1, $3); }
;
extract_list: datetime FROM a_expr
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = $1;
printf( "string is %s\n", $1);
$$ = lappend(lcons((Node *)n,NIL), $3);
}
| /* EMPTY */
{ $$ = NIL; }
;
position_list: a_expr IN expr_list
{
$$ = lappend($3, $1);
}
| /* EMPTY */
{ $$ = NIL; }
;
substr_list: expr_list substr_from substr_for
{
$$ = $1;
if ($2 != NULL) $$ = lappend($$, $2);
if ($3 != NULL) $$ = lappend($$, $3);
}
| /* EMPTY */
{ $$ = NIL; }
;
substr_from: FROM expr_list
{ $$ = $2; }
| /* EMPTY */
{ $$ = 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_nodes: AexprConst in_expr_nodes: AexprConst
...@@ -2214,7 +2546,7 @@ not_in_expr_nodes: AexprConst ...@@ -2214,7 +2546,7 @@ not_in_expr_nodes: AexprConst
; ;
attr: relation_name '.' attrs attr: relation_name '.' attrs
{ {
$$ = makeNode(Attr); $$ = makeNode(Attr);
$$->relname = $1; $$->relname = $1;
$$->paramNo = NULL; $$->paramNo = NULL;
...@@ -2231,14 +2563,21 @@ attr: relation_name '.' attrs ...@@ -2231,14 +2563,21 @@ attr: relation_name '.' attrs
} }
; ;
attrs: attr_name attrs: attr_name
{ $$ = lcons(makeString($1), NIL); } { $$ = lcons(makeString($1), NIL); }
| attrs '.' attr_name | attrs '.' attr_name
{ $$ = lappend($1, makeString($3)); } { $$ = lappend($1, makeString($3)); }
| attrs '.' '*' | attrs '.' '*'
{ $$ = lappend($1, makeString("*")); } { $$ = lappend($1, makeString("*")); }
; ;
datetime: YEARINTERVAL { $$ = "year"; }
| MONTHINTERVAL { $$ = "month"; }
| DAYINTERVAL { $$ = "day"; }
| HOURINTERVAL { $$ = "hour"; }
| MINUTEINTERVAL { $$ = "minute"; }
| SECONDINTERVAL { $$ = "second"; }
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -2246,9 +2585,9 @@ attrs: attr_name ...@@ -2246,9 +2585,9 @@ attrs: attr_name
* *
*****************************************************************************/ *****************************************************************************/
res_target_list: res_target_list ',' res_target_el res_target_list: res_target_list ',' res_target_el
{ $$ = lappend($1,$3); } { $$ = lappend($1,$3); }
| res_target_el | res_target_el
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
| '*' | '*'
{ {
...@@ -2280,7 +2619,7 @@ res_target_el: Id opt_indirection '=' a_expr_or_null ...@@ -2280,7 +2619,7 @@ res_target_el: Id opt_indirection '=' a_expr_or_null
$$->val = (Node *)$1; $$->val = (Node *)$1;
} }
| relation_name '.' '*' | relation_name '.' '*'
{ {
Attr *att = makeNode(Attr); Attr *att = makeNode(Attr);
att->relname = $1; att->relname = $1;
att->paramNo = NULL; att->paramNo = NULL;
...@@ -2291,23 +2630,22 @@ res_target_el: Id opt_indirection '=' a_expr_or_null ...@@ -2291,23 +2630,22 @@ res_target_el: Id opt_indirection '=' a_expr_or_null
$$->indirection = NULL; $$->indirection = NULL;
$$->val = (Node *)att; $$->val = (Node *)att;
} }
; ;
/* /*
** target list for select. ** target list for select.
** should get rid of the other but is still needed by the defunct retrieve into ** should get rid of the other but is still needed by the defunct retrieve into
** and update (uses a subset) ** and update (uses a subset)
*/ */
res_target_list2: res_target_list2: res_target_list2 ',' res_target_el2
res_target_list2 ',' res_target_el2
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
| res_target_el2 | res_target_el2
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
/* AS is not optional because shift/red conflict with unary ops */ /* AS is not optional because shift/red conflict with unary ops */
res_target_el2: a_expr AS Id res_target_el2: a_expr AS ColId
{ {
$$ = makeNode(ResTarget); $$ = makeNode(ResTarget);
$$->name = $3; $$->name = $3;
$$->indirection = NULL; $$->indirection = NULL;
...@@ -2351,30 +2689,30 @@ opt_id: Id { $$ = $1; } ...@@ -2351,30 +2689,30 @@ opt_id: Id { $$ = $1; }
; ;
relation_name: SpecialRuleRelation relation_name: SpecialRuleRelation
{ {
$$ = $1; $$ = $1;
strNcpy(saved_relname, $1, NAMEDATALEN-1); strNcpy(saved_relname, $1, NAMEDATALEN-1);
} }
| Id | ColId
{ {
/* disallow refs to magic system tables */ /* disallow refs to magic system tables */
if (strcmp(LogRelationName, $1) == 0 if (strcmp(LogRelationName, $1) == 0
|| strcmp(VariableRelationName, $1) == 0 || strcmp(VariableRelationName, $1) == 0
|| strcmp(TimeRelationName, $1) == 0 || strcmp(TimeRelationName, $1) == 0
|| strcmp(MagicRelationName, $1) == 0) { || strcmp(MagicRelationName, $1) == 0) {
elog(WARN, "%s cannot be accessed by users", $1); elog(WARN, "%s cannot be accessed by users", $1);
} else { } else {
$$ = $1; $$ = $1;
} }
strNcpy(saved_relname, $1, NAMEDATALEN-1); strNcpy(saved_relname, $1, NAMEDATALEN-1);
} }
; ;
database_name: Id { $$ = $1; }; database_name: Id { $$ = $1; };
access_method: Id { $$ = $1; }; access_method: Id { $$ = $1; };
attr_name: Id { $$ = $1; }; attr_name: ColId { $$ = $1; };
class: Id { $$ = $1; }; class: Id { $$ = $1; };
index_name: Id { $$ = $1; }; index_name: Id { $$ = $1; };
var_name: Id { $$ = $1; }; var_name: Id { $$ = $1; };
name: Id { $$ = $1; }; name: Id { $$ = $1; };
...@@ -2383,21 +2721,21 @@ file_name: Sconst { $$ = $1; }; ...@@ -2383,21 +2721,21 @@ file_name: Sconst { $$ = $1; };
recipe_name: Id { $$ = $1; }; recipe_name: Id { $$ = $1; };
AexprConst: Iconst AexprConst: Iconst
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
n->val.type = T_Integer; n->val.type = T_Integer;
n->val.val.ival = $1; n->val.val.ival = $1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| FCONST | FCONST
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
n->val.type = T_Float; n->val.type = T_Float;
n->val.val.dval = $1; n->val.val.dval = $1;
$$ = (Node *)n; $$ = (Node *)n;
} }
| Sconst | Sconst
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
n->val.type = T_String; n->val.type = T_String;
n->val.val.str = $1; n->val.val.str = $1;
...@@ -2415,27 +2753,31 @@ ParamNo: PARAM ...@@ -2415,27 +2753,31 @@ ParamNo: PARAM
; ;
NumConst: Iconst { $$ = makeInteger($1); } NumConst: Iconst { $$ = makeInteger($1); }
| FCONST { $$ = makeFloat($1); } | FCONST { $$ = makeFloat($1); }
; ;
Iconst: ICONST { $$ = $1; }; Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; }; Sconst: SCONST { $$ = $1; };
Id: IDENT { $$ = $1; }; Id: IDENT { $$ = $1; };
ColId: Id { $$ = $1; }
| datetime { $$ = $1; }
;
SpecialRuleRelation: CURRENT SpecialRuleRelation: CURRENT
{ {
if (QueryIsRule) if (QueryIsRule)
$$ = "*CURRENT*"; $$ = "*CURRENT*";
else else
elog(WARN,"CURRENT used in non-rule query"); elog(WARN,"CURRENT used in non-rule query");
} }
| NEW | NEW
{ {
if (QueryIsRule) if (QueryIsRule)
$$ = "*NEW*"; $$ = "*NEW*";
else else
elog(WARN,"NEW used in non-rule query"); elog(WARN,"NEW used in non-rule query");
} }
; ;
...@@ -2466,6 +2808,8 @@ xlateSqlType(char *name) ...@@ -2466,6 +2808,8 @@ xlateSqlType(char *name)
else if (!strcasecmp(name, "float") || else if (!strcasecmp(name, "float") ||
!strcasecmp(name, "real")) !strcasecmp(name, "real"))
return "float8"; return "float8";
else if (!strcasecmp(name, "interval"))
return "timespan";
else else
return name; return name;
} }
...@@ -2475,7 +2819,7 @@ void parser_init(Oid *typev, int nargs) ...@@ -2475,7 +2819,7 @@ void parser_init(Oid *typev, int nargs)
QueryIsRule = false; QueryIsRule = false;
saved_relname[0]= '\0'; saved_relname[0]= '\0';
saved_In_Expr = NULL; saved_In_Expr = NULL;
param_type_init(typev, nargs); param_type_init(typev, nargs);
} }
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