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

Add SQL92 "constants" CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP,

 CURRENT_USER.
Add syntax for primary and foreign keys.
Change optional syntax in CREATE INDEX to avoid parsing conflict with
 TIMESTAMP WITH TIME ZONE data type (use USING <class> rather than WITH...).
Decouple various categories of data type syntax to allow the most possible
 non-ambiguous extensions to SQL92 for column names and labels. This should
 make the parser a bit more understandable, or at least easier to find
 where and how the data types are handled.
Support syntax for IN and EXISTS clauses with subselects.
Support SQL92 syntax for IS TRUE/IS FALSE/IS NOT TRUE/IS NOT FALSE.
parent 27d0d1a1
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.57 1997/10/25 01:09:41 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.58 1997/10/25 05:56:41 thomas Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
* NOTES * NOTES
* CAPITALS are used to represent terminal symbols. * CAPITALS are used to represent terminal symbols.
* non-capitals are used to represent non-terminals. * non-capitals are used to represent non-terminals.
* SQL92-specific syntax is separated from plain SQL/Postgres syntax
* to help isolate the non-extensible portions of the parser.
* *
* if you use list, make sure the datum is a node so that the printing * if you use list, make sure the datum is a node so that the printing
* routines work * routines work
...@@ -115,19 +117,16 @@ static char *FlattenStringList(List *list); ...@@ -115,19 +117,16 @@ static char *FlattenStringList(List *list);
ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt, ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
%type <str> txname, char_type
%type <node> SubSelect %type <node> SubSelect
%type <str> join_expr, join_outer, join_spec %type <str> join_expr, join_outer, join_spec
%type <boolean> TriggerActionTime, TriggerForSpec %type <boolean> TriggerActionTime, TriggerForSpec
%type <str> DateTime, TriggerEvents, TriggerFuncArg %type <str> TriggerEvents, TriggerFuncArg
%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, aggr_argtype class, index_name, name, file_name, recipe_name, aggr_argtype
%type <constrdef> ConstraintElem, ConstraintDef
%type <str> opt_id, opt_portal_name, %type <str> opt_id, opt_portal_name,
before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique, before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
result, OptUseOp, opt_class, opt_range_start, opt_range_end, result, OptUseOp, opt_class, opt_range_start, opt_range_end,
...@@ -154,10 +153,10 @@ static char *FlattenStringList(List *list); ...@@ -154,10 +153,10 @@ static char *FlattenStringList(List *list);
%type <node> position_expr %type <node> position_expr
%type <list> extract_list, position_list %type <list> extract_list, position_list
%type <list> substr_list, substr_from, substr_for, trim_list %type <list> substr_list, substr_from, substr_for, trim_list
%type <list> interval_opts %type <list> opt_interval
%type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_col, opt_with_copy, %type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
index_opt_unique, opt_verbose, opt_analyze, opt_null index_opt_unique, opt_verbose, opt_analyze
%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
...@@ -171,12 +170,11 @@ static char *FlattenStringList(List *list); ...@@ -171,12 +170,11 @@ static char *FlattenStringList(List *list);
%type <pstmt> purge_quals %type <pstmt> purge_quals
%type <astmt> insert_rest %type <astmt> insert_rest
%type <typnam> Typename, typname, opt_type
%type <coldef> columnDef, alter_clause %type <coldef> columnDef, alter_clause
%type <defelt> def_elem %type <defelt> def_elem
%type <node> def_arg, columnElem, where_clause, %type <node> def_arg, columnElem, where_clause,
a_expr, a_expr_or_null, AexprConst, a_expr, a_expr_or_null, AexprConst,
in_expr_nodes, not_in_expr_nodes, in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
having_clause having_clause
%type <value> NumConst %type <value> NumConst
%type <attr> event_object, attr %type <attr> event_object, attr
...@@ -189,14 +187,25 @@ static char *FlattenStringList(List *list); ...@@ -189,14 +187,25 @@ static char *FlattenStringList(List *list);
%type <target> res_target_el, res_target_el2 %type <target> res_target_el, res_target_el2
%type <paramno> ParamNo %type <paramno> ParamNo
%type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
%type <str> generic, character, datetime
%type <str> opt_charset, opt_collate
%type <str> opt_float, opt_numeric, opt_decimal
%type <boolean> opt_varying, opt_timezone
%type <ival> Iconst %type <ival> Iconst
%type <str> Sconst %type <str> Sconst
%type <str> Id, date, var_value, zone_value %type <str> Id, date, var_value, zone_value
%type <str> ColId %type <str> ColId, ColLabel
%type <constrdef> ConstraintElem, ConstraintDef
%type <list> constraint_elem
%type <list> default_expr %type <list> default_expr
%type <str> opt_default %type <str> opt_default
%type <list> constraint_elem %type <boolean> opt_constraint
%type <list> key_actions, key_action
%type <str> key_match, key_reference
/* /*
* If you make any token changes, remember to: * If you make any token changes, remember to:
...@@ -204,37 +213,56 @@ static char *FlattenStringList(List *list); ...@@ -204,37 +213,56 @@ static char *FlattenStringList(List *list);
* - update the keyword table in parser/keywords.c * - update the keyword table in parser/keywords.c
*/ */
/* Keywords */ /* Reserved word tokens
%token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE, * SQL92 syntax has many type-specific constructs.
AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC, * So, go ahead and make these types reserved words,
BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BY, * and call-out the syntax explicitly.
CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN, * This gets annoying when trying to also retain Postgres' nice
COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CURRENT, CURSOR, * type-extensible features, but we don't really have a choice.
DATABASE, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC, * - thomas 1997-10-11
DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND, */
FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, HAVING, HEAVY,
IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTO, IS, ISNULL, /* Keywords (in SQL92 reserved words) */
JOIN, LANGUAGE, LEFT, LIGHT, LISTEN, LOAD, LOCAL, MERGE, MOVE, %token ACTION, ADD, ALL, ALTER, AND, AS, ASC,
NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL, BEGIN_TRANS, BETWEEN, BOTH, BY,
OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN, CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
PNULL, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE, COLLATE, COLUMN, COMMIT, CONSTRAINT, CREATE, CROSS,
RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE, CURRENT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE, DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
TABLE, TO, TRANSACTION, TRIGGER, END_TRANS, EXECUTE, EXISTS, EXTRACT,
UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
VERBOSE, VERSION, VIEW, WHERE, WITH, WORK GRANT, GROUP, HAVING, HOUR_P,
%token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE IN, INNER_P, INSERT, INTERVAL, INTO, IS,
JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
/* SQL-92 support */ MATCH, MINUTE_P, MONTH_P,
%token INTERVAL, TIME, ZONE NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NOTNULL, NULL_P, NUMERIC,
%token DAYINTERVAL, HOURINTERVAL, MINUTEINTERVAL, MONTHINTERVAL, ON, OPTION, OR, ORDER, OUTER_P,
SECONDINTERVAL, YEARINTERVAL PARTIAL, PRECISION, POSITION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
%token BOTH, LEADING, TRAILING, REFERENCES, REVOKE, RIGHT, ROLLBACK,
%token EXTRACT, POSITION, SUBSTRING, TRIM SECOND_P, SELECT, SET, SUBSTRING,
%token DOUBLE, PRECISION, FLOAT TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
%token DECIMAL, NUMERIC UNION, UNIQUE, UPDATE, USING,
%token CHARACTER, VARYING VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
%token CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP WHERE, WITH, WORK, YEAR_P, ZONE
/* Keywords (in SQL3 reserved words) */
%token FALSE_P, TRIGGER, TRUE_P
/* Keywords (in SQL92 non-reserved words) */
%token TYPE_P
/* Keywords for Postgres support (not in SQL92 reserved words) */
%token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
APPEND, ARCHIVE, ARCH_STORE,
BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
FORWARD, FUNCTION, HEAVY,
INDEX, INHERITS, INSTEAD, ISNULL,
LIGHT, LISTEN, LOAD, MERGE, MOVE,
NEW, NONE, NOTHING, OIDS, OPERATOR, PURGE,
RECIPE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, RULE,
SEQUENCE, SETOF, SHOW, STDIN, STDOUT, STORE,
VACUUM, VERBOSE, VERSION
/* 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
...@@ -259,7 +287,8 @@ static char *FlattenStringList(List *list); ...@@ -259,7 +287,8 @@ static char *FlattenStringList(List *list);
%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 */ /* Unary Operators */
%right ':'
%left ';' /* end of statement or natural log */ %left ';' /* end of statement or natural log */
%nonassoc '<' '>' %nonassoc '<' '>'
%right UMINUS %right UMINUS
...@@ -322,21 +351,24 @@ stmt : AddAttrStmt ...@@ -322,21 +351,24 @@ stmt : AddAttrStmt
| VariableResetStmt | VariableResetStmt
; ;
/***************************************************************************** /*****************************************************************************
* *
* Set PG internal variable * Set PG internal variable
* SET name TO 'var_value' * SET name TO 'var_value'
* Include SQL92 syntax (thomas 1997-10-22):
* SET TIME ZONE 'var_value'
* *
*****************************************************************************/ *****************************************************************************/
VariableSetStmt: SET Id TO var_value VariableSetStmt: SET ColId 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 Id '=' var_value | SET ColId '=' var_value
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = $2; n->name = $2;
...@@ -356,10 +388,10 @@ var_value: Sconst { $$ = $1; } ...@@ -356,10 +388,10 @@ var_value: Sconst { $$ = $1; }
; ;
zone_value: Sconst { $$ = $1; } zone_value: Sconst { $$ = $1; }
| LOCAL { $$ = NULL; } | LOCAL { $$ = "default"; }
; ;
VariableShowStmt: SHOW Id VariableShowStmt: SHOW ColId
{ {
VariableShowStmt *n = makeNode(VariableShowStmt); VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = $2; n->name = $2;
...@@ -367,7 +399,7 @@ VariableShowStmt: SHOW Id ...@@ -367,7 +399,7 @@ VariableShowStmt: SHOW Id
} }
; ;
VariableResetStmt: RESET Id VariableResetStmt: RESET ColId
{ {
VariableResetStmt *n = makeNode(VariableResetStmt); VariableResetStmt *n = makeNode(VariableResetStmt);
n->name = $2; n->name = $2;
...@@ -375,6 +407,7 @@ VariableResetStmt: RESET Id ...@@ -375,6 +407,7 @@ VariableResetStmt: RESET Id
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY : * QUERY :
...@@ -407,32 +440,23 @@ printf( "list has %d elements\n", length($3)); ...@@ -407,32 +440,23 @@ printf( "list has %d elements\n", length($3));
#endif #endif
$$ = lp; $$ = lp;
} }
| DROP opt_column Id | DROP opt_column ColId
{ elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); } { elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
| ALTER opt_column Id SET opt_default | ALTER opt_column ColId SET opt_default
{ elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); } { elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
| ALTER opt_column Id DROP DEFAULT | ALTER opt_column ColId DROP DEFAULT
{ elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); } { elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
| ADD ConstraintElem | ADD ConstraintElem
{ elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); } { elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
; ;
/* Column definition might include WITH TIME ZONE, but only for the data types columnDef: ColId Typename opt_default opt_constraint
* called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
* and "time". - thomas 1997-07-14
*/
columnDef: Id Typename opt_with_col opt_default opt_null
{ {
$$ = makeNode(ColumnDef); $$ = makeNode(ColumnDef);
$$->colname = $1; $$->colname = $1;
$$->typename = $2; $$->typename = $2;
$$->typename->timezone = $3; $$->defval = $3;
$$->defval = $4; $$->is_not_null = $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);
} }
; ;
...@@ -500,16 +524,49 @@ default_expr: AexprConst ...@@ -500,16 +524,49 @@ default_expr: AexprConst
{ $$ = lcons( makeString( $1), $2); } { $$ = lcons( makeString( $1), $2); }
| default_expr Op | default_expr Op
{ $$ = lappend( $1, makeString( $2)); } { $$ = lappend( $1, makeString( $2)); }
/* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
| CURRENT_DATE
{ $$ = lcons( makeString( "date( 'current'::datetime + '0 sec')"), NIL); }
| CURRENT_TIME
{ $$ = lcons( makeString( "'now'::time"), NIL); }
| CURRENT_TIME '(' Iconst ')'
{
if ($3 != 0)
elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
$$ = lcons( makeString( "'now'::time"), NIL);
}
| CURRENT_TIMESTAMP
{ $$ = lcons( makeString( "now()"), NIL); }
| CURRENT_TIMESTAMP '(' Iconst ')'
{
if ($3 != 0)
elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
$$ = lcons( makeString( "now()"), NIL);
}
| CURRENT_USER
{ $$ = lcons( makeString( "CURRENT_USER"), NIL); }
; ;
opt_null: NOT PNULL { $$ = TRUE; } opt_constraint: NOT NULL_P { $$ = TRUE; }
| NOTNULL { $$ = TRUE; } | NOTNULL { $$ = TRUE; }
| UNIQUE
{
elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL);
$$ = FALSE;
}
| PRIMARY KEY
{
elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL);
$$ = FALSE;
}
| REFERENCES ColId opt_column_list key_match key_actions
{
elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL);
$$ = FALSE;
}
| /* EMPTY */ { $$ = FALSE; } | /* EMPTY */ { $$ = FALSE; }
; ;
opt_with_col: WITH TIME ZONE { $$ = TRUE; }
| /* EMPTY */ { $$ = FALSE; }
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -674,16 +731,22 @@ printf("ConstraintDef: string is %s\n", (char *) constr->def); ...@@ -674,16 +731,22 @@ printf("ConstraintDef: string is %s\n", (char *) constr->def);
#endif #endif
$$ = constr; $$ = constr;
} }
| UNIQUE '(' columnList ')'
{ elog(WARN,"CREATE TABLE/UNIQUE not yet implemented",NULL); }
| PRIMARY KEY '(' columnList ')'
{ elog(WARN,"CREATE TABLE/PRIMARY KEY not yet implemented",NULL); }
| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
{ elog(WARN,"CREATE TABLE/FOREIGN KEY not yet implemented",NULL); }
; ;
constraint_elem: AexprConst constraint_elem: AexprConst
{ $$ = makeConstantList((A_Const *) $1); } { $$ = makeConstantList((A_Const *) $1); }
| Pnull | Pnull
{ $$ = lcons( makeString("NULL"), NIL); } { $$ = lcons( makeString("NULL"), NIL); }
| Id | ColId
{ {
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf( "Id is %s\n", $1); printf( "ColId is %s\n", $1);
#endif #endif
$$ = lcons( makeString($1), NIL); $$ = lcons( makeString($1), NIL);
} }
...@@ -737,6 +800,26 @@ printf( "Id is %s\n", $1); ...@@ -737,6 +800,26 @@ printf( "Id is %s\n", $1);
{ $$ = lappend( $1, makeString( $2)); } { $$ = lappend( $1, makeString( $2)); }
; ;
key_match: MATCH FULL { $$ = NULL; }
| MATCH PARTIAL { $$ = NULL; }
| /*EMPTY*/ { $$ = NULL; }
;
key_actions: key_action key_action { $$ = NIL; }
| key_action { $$ = NIL; }
| /*EMPTY*/ { $$ = NIL; }
;
key_action: ON DELETE key_reference { $$ = NIL; }
| ON UPDATE key_reference { $$ = NIL; }
;
key_reference: NO ACTION { $$ = NULL; }
| CASCADE { $$ = NULL; }
| SET DEFAULT { $$ = NULL; }
| SET NULL_P { $$ = NULL; }
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -871,6 +954,7 @@ DropTrigStmt: DROP TRIGGER name ON relation_name ...@@ -871,6 +954,7 @@ DropTrigStmt: DROP TRIGGER name ON relation_name
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY : * QUERY :
...@@ -900,15 +984,15 @@ def_type: OPERATOR { $$ = OPERATOR; } ...@@ -900,15 +984,15 @@ def_type: OPERATOR { $$ = OPERATOR; }
| Type | Type
{ {
#ifdef PARSEDEBUG #ifdef PARSEDEBUG
printf("def_type: decoding P_TYPE\n"); printf("def_type: decoding TYPE_P\n");
#endif #endif
$$ = P_TYPE; $$ = TYPE_P;
} }
| AGGREGATE { $$ = AGGREGATE; } | AGGREGATE { $$ = AGGREGATE; }
; ;
def_name: PROCEDURE { $$ = "procedure"; } def_name: PROCEDURE { $$ = "procedure"; }
| Id { $$ = $1; } | ColId { $$ = $1; }
| MathOp { $$ = $1; } | MathOp { $$ = $1; }
| Op { $$ = $1; } | Op { $$ = $1; }
; ;
...@@ -951,11 +1035,11 @@ pprint($3); ...@@ -951,11 +1035,11 @@ pprint($3);
} }
; ;
def_arg: Id { $$ = (Node *)makeString($1); } def_arg: ColId { $$ = (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 ColId
{ {
TypeName *n = makeNode(TypeName); TypeName *n = makeNode(TypeName);
n->name = $2; n->name = $2;
...@@ -1034,6 +1118,7 @@ opt_portal_name: IN name { $$ = $2;} ...@@ -1034,6 +1118,7 @@ opt_portal_name: IN name { $$ = $2;}
| /*EMPTY*/ { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1100,23 +1185,24 @@ grantee: PUBLIC ...@@ -1100,23 +1185,24 @@ grantee: PUBLIC
{ {
$$ = aclmakeuser("A",""); $$ = aclmakeuser("A","");
} }
| GROUP Id | GROUP ColId
{ {
$$ = aclmakeuser("G",$2); $$ = aclmakeuser("G",$2);
} }
| Id | ColId
{ {
$$ = aclmakeuser("U",$1); $$ = aclmakeuser("U",$1);
} }
; ;
opt_with_grant : /* empty */ opt_with_grant: 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");
} }
| /*EMPTY*/
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1132,6 +1218,7 @@ RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee ...@@ -1132,6 +1218,7 @@ RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1159,15 +1246,59 @@ IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name ...@@ -1159,15 +1246,59 @@ IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
} }
; ;
index_opt_unique: UNIQUE { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
access_method_clause: USING access_method { $$ = $2; } access_method_clause: USING access_method { $$ = $2; }
| /* empty -- 'btree' is default access method */ | /*EMPTY*/ { $$ = "btree"; }
{ $$ = "btree"; }
; ;
index_opt_unique: UNIQUE { $$ = TRUE; } index_params: index_list { $$ = $1; }
| /*empty*/ { $$ = FALSE; } | func_index { $$ = lcons($1,NIL); }
;
index_list: index_list ',' index_elem { $$ = lappend($1, $3); }
| index_elem { $$ = lcons($1, NIL); }
;
func_index: name '(' name_list ')' opt_type opt_class
{
$$ = makeNode(IndexElem);
$$->name = $1;
$$->args = $3;
$$->class = $6;
$$->tname = $5;
}
; ;
index_elem: attr_name opt_type opt_class
{
$$ = makeNode(IndexElem);
$$->name = $1;
$$->args = NIL;
$$->class = $3;
$$->tname = $2;
}
;
opt_type: ':' Typename { $$ = $2;}
| FOR Typename { $$ = $2;}
| /*EMPTY*/ { $$ = NULL;}
;
/* opt_class "WITH class" conflicts with preceeding opt_type
* for Typename of "TIMESTAMP WITH TIME ZONE"
* So, remove "WITH class" from the syntax. OK??
* - thomas 1997-10-12
* | WITH class { $$ = $2; }
*/
opt_class: class { $$ = $1; }
| USING class { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; }
;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1184,6 +1315,7 @@ ExtendStmt: EXTEND INDEX index_name where_clause ...@@ -1184,6 +1315,7 @@ ExtendStmt: EXTEND INDEX index_name where_clause
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1322,7 +1454,7 @@ RemoveStmt: DROP remove_type name ...@@ -1322,7 +1454,7 @@ RemoveStmt: DROP remove_type name
} }
; ;
remove_type: Type { $$ = P_TYPE; } remove_type: Type { $$ = TYPE_P; }
| INDEX { $$ = INDEX; } | INDEX { $$ = INDEX; }
| RULE { $$ = RULE; } | RULE { $$ = RULE; }
| VIEW { $$ = VIEW; } | VIEW { $$ = VIEW; }
...@@ -1386,6 +1518,7 @@ oper_argtypes: name ...@@ -1386,6 +1518,7 @@ oper_argtypes: name
{ $$ = makeList(makeString($1), NULL, -1); } { $$ = makeList(makeString($1), NULL, -1); }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1679,6 +1812,7 @@ ClusterStmt: CLUSTER index_name ON relation_name ...@@ -1679,6 +1812,7 @@ ClusterStmt: CLUSTER index_name ON relation_name
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1728,6 +1862,7 @@ va_list: name ...@@ -1728,6 +1862,7 @@ va_list: name
{ $$=lappend($1,$3); } { $$=lappend($1,$3); }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1744,6 +1879,7 @@ ExplainStmt: EXPLAIN opt_verbose OptimizableStmt ...@@ -1744,6 +1879,7 @@ ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
} }
; ;
/***************************************************************************** /*****************************************************************************
* * * *
* Optimizable Stmts: * * Optimizable Stmts: *
...@@ -1806,7 +1942,7 @@ columnList: ...@@ -1806,7 +1942,7 @@ columnList:
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
columnElem: Id opt_indirection columnElem: ColId opt_indirection
{ {
Ident *id = makeNode(Ident); Ident *id = makeNode(Ident);
id->name = $1; id->name = $1;
...@@ -1815,6 +1951,7 @@ columnElem: Id opt_indirection ...@@ -1815,6 +1951,7 @@ columnElem: Id opt_indirection
} }
; ;
/***************************************************************************** /*****************************************************************************
* *
* QUERY: * QUERY:
...@@ -1899,44 +2036,6 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR ...@@ -1899,44 +2036,6 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR
* *
*****************************************************************************/ *****************************************************************************/
/******************************************************************************
RetrieveStmt: SELECT opt_unique res_target_list2
result from_clause where_clause
group_clause having_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->sortClause = $9;
$$ = (Node *)n;
}
;
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 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
...@@ -1988,7 +2087,7 @@ result: INTO TABLE relation_name ...@@ -1988,7 +2087,7 @@ result: INTO TABLE relation_name
; ;
opt_unique: DISTINCT { $$ = "*"; } opt_unique: DISTINCT { $$ = "*"; }
| DISTINCT ON Id { $$ = $3; } | DISTINCT ON ColId { $$ = $3; }
| /*EMPTY*/ { $$ = NULL;} | /*EMPTY*/ { $$ = NULL;}
; ;
...@@ -1996,13 +2095,11 @@ sort_clause: ORDER BY sortby_list { $$ = $3; } ...@@ -1996,13 +2095,11 @@ sort_clause: ORDER BY sortby_list { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; }
; ;
sortby_list: sortby sortby_list: sortby { $$ = lcons($1, NIL); }
{ $$ = lcons($1, NIL); } | sortby_list ',' sortby { $$ = lappend($1, $3); }
| sortby_list ',' sortby
{ $$ = lappend($1, $3); }
; ;
sortby: Id OptUseOp sortby: ColId OptUseOp
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortGroupBy);
$$->resno = 0; $$->resno = 0;
...@@ -2010,7 +2107,7 @@ sortby: Id OptUseOp ...@@ -2010,7 +2107,7 @@ sortby: Id OptUseOp
$$->name = $1; $$->name = $1;
$$->useOp = $2; $$->useOp = $2;
} }
| Id '.' Id OptUseOp | ColId '.' ColId OptUseOp
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortGroupBy);
$$->resno = 0; $$->resno = 0;
...@@ -2036,46 +2133,6 @@ OptUseOp: USING Op { $$ = $2; } ...@@ -2036,46 +2133,6 @@ OptUseOp: USING Op { $$ = $2; }
| /*EMPTY*/ { $$ = "<"; /*default*/ } | /*EMPTY*/ { $$ = "<"; /*default*/ }
; ;
index_params: index_list { $$ = $1; }
| func_index { $$ = lcons($1,NIL); }
;
index_list:
index_list ',' index_elem
{ $$ = lappend($1, $3); }
| index_elem
{ $$ = lcons($1, NIL); }
;
func_index: name '(' name_list ')' opt_type opt_class
{
$$ = makeNode(IndexElem);
$$->name = $1;
$$->args = $3;
$$->class = $6;
$$->tname = $5;
}
;
index_elem: attr_name opt_type opt_class
{
$$ = makeNode(IndexElem);
$$->name = $1;
$$->args = NIL;
$$->class = $3;
$$->tname = $2;
}
;
opt_type: ':' Typename { $$ = $2;}
| /*EMPTY*/ { $$ = NULL;}
;
opt_class: class
| WITH class { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; }
;
/* /*
* jimmy bell-style recursive queries aren't supported in the * jimmy bell-style recursive queries aren't supported in the
* current system. * current system.
...@@ -2105,7 +2162,7 @@ groupby_list: groupby { $$ = lcons($1, NIL); } ...@@ -2105,7 +2162,7 @@ groupby_list: groupby { $$ = lcons($1, NIL); }
| groupby_list ',' groupby { $$ = lappend($1, $3); } | groupby_list ',' groupby { $$ = lappend($1, $3); }
; ;
groupby: Id groupby: ColId
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortGroupBy);
$$->resno = 0; $$->resno = 0;
...@@ -2113,7 +2170,7 @@ groupby: Id ...@@ -2113,7 +2170,7 @@ groupby: Id
$$->name = $1; $$->name = $1;
$$->useOp = NULL; $$->useOp = NULL;
} }
| Id '.' Id | ColId '.' ColId
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortGroupBy);
$$->resno = 0; $$->resno = 0;
...@@ -2135,6 +2192,7 @@ having_clause: HAVING a_expr { $$ = $2; } ...@@ -2135,6 +2192,7 @@ having_clause: HAVING a_expr { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
/***************************************************************************** /*****************************************************************************
* *
* clauses common to all Optimizable Stmts: * clauses common to all Optimizable Stmts:
...@@ -2160,13 +2218,13 @@ from_list: from_list ',' from_val ...@@ -2160,13 +2218,13 @@ from_list: from_list ',' from_val
{ $$ = lcons($1, NIL); } { $$ = lcons($1, NIL); }
; ;
from_val: relation_expr AS Id from_val: relation_expr AS ColLabel
{ {
$$ = makeNode(RangeVar); $$ = makeNode(RangeVar);
$$->relExpr = $1; $$->relExpr = $1;
$$->name = $3; $$->name = $3;
} }
| relation_expr Id | relation_expr ColId
{ {
$$ = makeNode(RangeVar); $$ = makeNode(RangeVar);
$$->relExpr = $1; $$->relExpr = $1;
...@@ -2187,9 +2245,9 @@ join_expr: NATURAL join_expr { $$ = NULL; } ...@@ -2187,9 +2245,9 @@ join_expr: NATURAL join_expr { $$ = NULL; }
{ elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); } { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
| RIGHT join_outer | RIGHT join_outer
{ elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); } { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
| OUTERJOIN | OUTER_P
{ elog(WARN,"OUTER JOIN not yet implemented",NULL); } { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
| INNERJOIN | INNER_P
{ elog(WARN,"INNER JOIN not yet implemented",NULL); } { elog(WARN,"INNER JOIN not yet implemented",NULL); }
| UNION | UNION
{ elog(WARN,"UNION JOIN not yet implemented",NULL); } { elog(WARN,"UNION JOIN not yet implemented",NULL); }
...@@ -2197,7 +2255,7 @@ join_expr: NATURAL join_expr { $$ = NULL; } ...@@ -2197,7 +2255,7 @@ join_expr: NATURAL join_expr { $$ = NULL; }
{ elog(WARN,"INNER JOIN not yet implemented",NULL); } { elog(WARN,"INNER JOIN not yet implemented",NULL); }
; ;
join_outer: OUTERJOIN { $$ = NULL; } join_outer: OUTER_P { $$ = NULL; }
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ } | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
; ;
...@@ -2210,7 +2268,7 @@ join_list: join_using { $$ = lcons($1, NIL); } ...@@ -2210,7 +2268,7 @@ join_list: join_using { $$ = lcons($1, NIL); }
| join_list ',' join_using { $$ = lappend($1, $3); } | join_list ',' join_using { $$ = lappend($1, $3); }
; ;
join_using: Id join_using: ColId
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortGroupBy);
$$->resno = 0; $$->resno = 0;
...@@ -2218,7 +2276,7 @@ join_using: Id ...@@ -2218,7 +2276,7 @@ join_using: Id
$$->name = $1; $$->name = $1;
$$->useOp = NULL; $$->useOp = NULL;
} }
| Id '.' Id | ColId '.' ColId
{ {
$$ = makeNode(SortGroupBy); $$ = makeNode(SortGroupBy);
$$->resno = 0; $$->resno = 0;
...@@ -2266,7 +2324,9 @@ relation_expr: relation_name ...@@ -2266,7 +2324,9 @@ relation_expr: relation_name
} }
; ;
/* Time travel
* Range specification clause.
*/
time_range: '[' opt_range_start ',' opt_range_end ']' time_range: '[' opt_range_start ',' opt_range_end ']'
{ {
$$ = makeNode(TimeRange); $$ = makeNode(TimeRange);
...@@ -2305,36 +2365,32 @@ nest_array_bounds: '[' ']' nest_array_bounds ...@@ -2305,36 +2365,32 @@ nest_array_bounds: '[' ']' nest_array_bounds
{ $$ = NIL; } { $$ = NIL; }
; ;
/*
* typname handles types without trailing parens for size specification.
* Typename uses either typname or explicit txname(size).
* So, must handle FLOAT in both places. - thomas 1997-09-20
*/
typname: txname
{
char *tname;
$$ = makeNode(TypeName);
if (!strcasecmp($1, "float")) /*****************************************************************************
tname = xlateSqlType("float8"); *
else if (!strcasecmp($1, "decimal")) * Type syntax
tname = xlateSqlType("integer"); * SQL92 introduces a large amount of type-specific syntax.
else if (!strcasecmp($1, "numeric")) * Define individual clauses to handle these cases, and use
tname = xlateSqlType("integer"); * the generic case to handle regular type-extensible Postgres syntax.
else * - thomas 1997-10-10
tname = xlateSqlType($1); *
$$->name = tname; *****************************************************************************/
Typename: Array opt_array_bounds
{
$$ = $1;
$$->arrayBounds = $2;
/* Is this the name of a complex type? If so, implement /* Is this the name of a complex type? If so, implement
* it as a set. * it as a set.
*/ */
if (!strcmp(saved_relname, tname)) if (!strcmp(saved_relname, $$->name))
/* 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)) != InvalidOid) else if (get_typrelid((Type)type($$->name)) != 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.)
*/ */
...@@ -2342,98 +2398,119 @@ typname: txname ...@@ -2342,98 +2398,119 @@ typname: txname
else else
$$->setof = FALSE; $$->setof = FALSE;
} }
| SETOF txname | Character
| SETOF Array
{ {
char *tname = xlateSqlType($2); $$ = $2;
$$ = makeNode(TypeName);
$$->name = tname;
$$->setof = TRUE; $$->setof = TRUE;
} }
; ;
/* Type names Array: Generic
* Allow the following parsing categories: | Datetime
* - strings which are not keywords (Id) | Numeric
* - some explicit SQL/92 data types (e.g. DOUBLE PRECISION)
* - TYPE as an SQL/92 non-reserved word, but parser keyword
* - other date/time strings (e.g. YEAR)
* - thomas 1997-10-08
*/
txname: Id { $$ = $1; }
| DateTime { $$ = $1; }
| TIME { $$ = xlateSqlType("time"); }
| P_TYPE { $$ = xlateSqlType("type"); }
| INTERVAL interval_opts { $$ = xlateSqlType("interval"); }
| CHARACTER char_type { $$ = $2; }
| DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
| FLOAT { $$ = xlateSqlType("float"); }
| DECIMAL { $$ = "decimal"; }
| NUMERIC { $$ = "numeric"; }
;
char_type: VARYING { $$ = xlateSqlType("varchar"); }
| /*EMPTY*/ { $$ = xlateSqlType("char"); }
;
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 Generic: generic
{ {
$$ = $1; $$ = makeNode(TypeName);
$$->arrayBounds = $2; $$->name = xlateSqlType($1);
#if FALSE
if (!strcasecmp($1->name, "varchar"))
$$->typlen = 4 + 1;
#endif
} }
| txname '(' Iconst ')' ;
{
/* generic: Id { $$ = $1; }
* The following implements CHAR() and VARCHAR(). | TYPE_P { $$ = xlateSqlType("type"); }
* We do it here instead of the 'typname:' production | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
* because we don't want to allow arrays of VARCHAR(). ;
* I haven't thought about whether that will work or not.
* - ay 6/95 /* SQL92 numeric data types
* Also implements FLOAT(). * Check FLOAT() precision limits assuming IEEE floating types.
* Check precision limits assuming IEEE floating types. * Provide rudimentary DECIMAL() and NUMERIC() implementations
* by checking parameters and making sure they match what is possible with INTEGER.
* - thomas 1997-09-18 * - thomas 1997-09-18
*/ */
Numeric: FLOAT opt_float
{
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
if (!strcasecmp($1, "float")) { $$->name = xlateSqlType($2);
if ($3 < 1) }
| DECIMAL opt_decimal
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("integer");
}
| NUMERIC opt_numeric
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("integer");
}
;
opt_float: '(' Iconst ')'
{
if ($2 < 1)
elog(WARN,"precision for FLOAT must be at least 1",NULL); elog(WARN,"precision for FLOAT must be at least 1",NULL);
else if ($3 < 7) else if ($2 < 7)
$$->name = xlateSqlType("float4"); $$ = xlateSqlType("float4");
else if ($3 < 16) else if ($2 < 16)
$$->name = xlateSqlType("float8"); $$ = xlateSqlType("float8");
else else
elog(WARN,"precision for FLOAT must be less than 16",NULL); elog(WARN,"precision for FLOAT must be less than 16",NULL);
} else if (!strcasecmp($1, "decimal")) { }
/* DECIMAL is allowed to have more precision than specified */ | /*EMPTY*/
if ($3 > 9) {
elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3); $$ = xlateSqlType("float8");
$$->name = xlateSqlType("integer"); }
;
} else if (!strcasecmp($1, "numeric")) { opt_numeric: '(' Iconst ',' Iconst ')'
/* integer holds 9.33 decimal places, so assume an even 9 for now */ {
if ($3 != 9) if ($2 != 9)
elog(WARN,"NUMERIC precision %d must be 9",$3); elog(WARN,"NUMERIC precision %d must be 9",$2);
$$->name = xlateSqlType("integer"); if ($4 != 0)
elog(WARN,"NUMERIC scale %d must be zero",$4);
}
| '(' Iconst ')'
{
if ($2 != 9)
elog(WARN,"NUMERIC precision %d must be 9",$2);
}
| /*EMPTY*/
{
$$ = NULL;
}
;
} else { opt_decimal: '(' Iconst ',' Iconst ')'
{
if ($2 > 9)
elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
if ($4 != 0)
elog(WARN,"DECIMAL scale %d must be zero",$4);
$$ = NULL;
}
| '(' Iconst ')'
{
if ($2 > 9)
elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
$$ = NULL;
}
| /*EMPTY*/
{
$$ = NULL;
}
;
/* SQL92 character data types
* The following implements CHAR() and VARCHAR().
* We do it here instead of the 'Generic' production
* because we don't want to allow arrays of VARCHAR().
* I haven't thought about whether that will work or not.
* - ay 6/95
*/
Character: character '(' Iconst ')'
{
$$ = makeNode(TypeName);
if (!strcasecmp($1, "char")) if (!strcasecmp($1, "char"))
$$->name = xlateSqlType("bpchar"); $$->name = xlateSqlType("bpchar");
else if (!strcasecmp($1, "varchar")) else if (!strcasecmp($1, "varchar"))
...@@ -2448,7 +2525,7 @@ Typename: typname opt_array_bounds ...@@ -2448,7 +2525,7 @@ Typename: typname opt_array_bounds
* just to be safe here... - ay 6/95 * just to be safe here... - ay 6/95
* XXX note this hardcoded limit - thomas 1997-07-13 * XXX note this hardcoded limit - thomas 1997-07-13
*/ */
elog(WARN,"length for '%s' type cannot exceed 4096",$1); elog(WARN,"length for type '%s' cannot exceed 4096",$1);
/* we actually implement this sort of like a varlen, so /* we actually implement this sort of like a varlen, so
* the first 4 bytes is the length. (the difference * the first 4 bytes is the length. (the difference
...@@ -2457,29 +2534,94 @@ Typename: typname opt_array_bounds ...@@ -2457,29 +2534,94 @@ Typename: typname opt_array_bounds
*/ */
$$->typlen = 4 + $3; $$->typlen = 4 + $3;
} }
} | character
| txname '(' Iconst ',' Iconst ')'
{ {
$$ = makeNode(TypeName); $$ = makeNode(TypeName);
if (!strcasecmp($1, "decimal")) { $$->name = xlateSqlType($1);
if ($3 > 9) }
elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3); ;
if ($5 != 0)
elog(WARN,"DECIMAL scale %d must be zero",$5);
$$->name = xlateSqlType("integer");
} else if (!strcasecmp($1, "numeric")) {
if ($3 != 9)
elog(WARN,"NUMERIC precision %d must be 9",$3);
if ($5 != 0)
elog(WARN,"NUMERIC scale %d must be zero",$5);
$$->name = xlateSqlType("integer");
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 { } else {
elog(WARN,"%s(%d,%d) not implemented",$1,$3,$5); type = xlateSqlType($3);
} }
$$->name = xlateSqlType("integer"); };
if ($4 != NULL)
elog(WARN,"COLLATE %s not yet implemented",$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);
}
| TIMESTAMP opt_timezone
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("timestamp");
$$->timezone = $2;
} }
| TIME
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("time");
}
| INTERVAL opt_interval
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("interval");
}
;
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; }
| /* EMPTY */ { $$ = NIL; }
; ;
...@@ -2536,14 +2678,21 @@ a_expr: attr opt_indirection ...@@ -2536,14 +2678,21 @@ a_expr: attr opt_indirection
((ParamNo *)$1)->typename = $3; ((ParamNo *)$1)->typename = $3;
$$ = (Node *)$1; $$ = (Node *)$1;
} }
| CAST AexprConst AS Typename | CAST a_expr AS Typename
{ {
$$ = (Node *)$2;
/* AexprConst can be either A_Const or ParamNo */ /* AexprConst can be either A_Const or ParamNo */
if (nodeTag($2) == T_A_Const) if (nodeTag($2) == T_A_Const) {
((A_Const *)$2)->typename = $4; ((A_Const *)$2)->typename = $4;
else } else if (nodeTag($2) == T_Param) {
((ParamNo *)$2)->typename = $4; ((ParamNo *)$2)->typename = $4;
$$ = (Node *)$2; /* otherwise, try to transform to a function call */
} else {
FuncCall *n = makeNode(FuncCall);
n->funcname = $4->name;
n->args = lcons($2,NIL);
$$ = (Node *)n;
}
} }
| '(' a_expr_or_null ')' | '(' a_expr_or_null ')'
{ $$ = $2; } { $$ = $2; }
...@@ -2557,7 +2706,7 @@ a_expr: attr opt_indirection ...@@ -2557,7 +2706,7 @@ a_expr: attr opt_indirection
{ $$ = makeA_Expr(OP, $1, NULL, $2); } { $$ = makeA_Expr(OP, $1, NULL, $2); }
| a_expr Op | a_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); } { $$ = makeA_Expr(OP, $2, $1, NULL); }
| Id | ColId
{ {
/* could be a column name or a relation_name */ /* could be a column name or a relation_name */
Ident *n = makeNode(Ident); Ident *n = makeNode(Ident);
...@@ -2611,7 +2760,7 @@ a_expr: attr opt_indirection ...@@ -2611,7 +2760,7 @@ a_expr: attr opt_indirection
$$ = (Node *)n; $$ = (Node *)n;
} }
| CURRENT_TIME '(' AexprConst ')' | CURRENT_TIME '(' Iconst ')'
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
A_Const *s = makeNode(A_Const); A_Const *s = makeNode(A_Const);
...@@ -2627,7 +2776,8 @@ a_expr: attr opt_indirection ...@@ -2627,7 +2776,8 @@ a_expr: attr opt_indirection
t->name = xlateSqlType("time"); t->name = xlateSqlType("time");
t->setof = FALSE; t->setof = FALSE;
elog(NOTICE,"CURRENT_TIME(p) precision not implemented",NULL); if ($3 != 0)
elog(NOTICE,"CURRENT_TIME(p) precision must be zero",NULL);
$$ = (Node *)n; $$ = (Node *)n;
} }
...@@ -2645,7 +2795,7 @@ a_expr: attr opt_indirection ...@@ -2645,7 +2795,7 @@ a_expr: attr opt_indirection
$$ = (Node *)n; $$ = (Node *)n;
} }
| CURRENT_TIMESTAMP '(' AexprConst ')' | CURRENT_TIMESTAMP '(' Iconst ')'
{ {
FuncCall *n = makeNode(FuncCall); FuncCall *n = makeNode(FuncCall);
A_Const *s = makeNode(A_Const); A_Const *s = makeNode(A_Const);
...@@ -2661,10 +2811,18 @@ a_expr: attr opt_indirection ...@@ -2661,10 +2811,18 @@ a_expr: attr opt_indirection
t->name = xlateSqlType("timestamp"); t->name = xlateSqlType("timestamp");
t->setof = FALSE; t->setof = FALSE;
elog(NOTICE,"CURRENT_TIMESTAMP(p) precision not implemented",NULL); if ($3 != 0)
elog(NOTICE,"CURRENT_TIMESTAMP(p) precision must be zero",NULL);
$$ = (Node *)n; $$ = (Node *)n;
} }
| CURRENT_USER
{
FuncCall *n = makeNode(FuncCall);
n->funcname = "getpgusername";
n->args = NIL;
$$ = (Node *)n;
}
/* We probably need to define an "exists" node, /* We probably need to define an "exists" node,
* since the optimizer could choose to find only one match. * since the optimizer could choose to find only one match.
* Perhaps the first implementation could just check for * Perhaps the first implementation could just check for
...@@ -2672,7 +2830,7 @@ a_expr: attr opt_indirection ...@@ -2672,7 +2830,7 @@ a_expr: attr opt_indirection
*/ */
| EXISTS '(' SubSelect ')' | EXISTS '(' SubSelect ')'
{ {
elog(WARN,"EXISTS not yet supported",NULL); elog(WARN,"EXISTS not yet implemented",NULL);
$$ = $3; $$ = $3;
} }
| EXTRACT '(' extract_list ')' | EXTRACT '(' extract_list ')'
...@@ -2734,12 +2892,40 @@ a_expr: attr opt_indirection ...@@ -2734,12 +2892,40 @@ a_expr: attr opt_indirection
} }
| a_expr ISNULL | a_expr ISNULL
{ $$ = makeA_Expr(ISNULL, NULL, $1, NULL); } { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
| a_expr IS PNULL | a_expr IS NULL_P
{ $$ = makeA_Expr(ISNULL, NULL, $1, NULL); } { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
| a_expr NOTNULL | a_expr NOTNULL
{ $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); } { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
| a_expr IS NOT PNULL | a_expr IS NOT NULL_P
{ $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); } { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
| a_expr IS TRUE_P
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = "t";
$$ = 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";
$$ = 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";
$$ = 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";
$$ = makeA_Expr(OP, "=", $1, (Node *)n);
}
| a_expr BETWEEN AexprConst AND AexprConst | a_expr BETWEEN AexprConst AND AexprConst
{ {
$$ = makeA_Expr(AND, NULL, $$ = makeA_Expr(AND, NULL,
...@@ -2752,9 +2938,9 @@ a_expr: attr opt_indirection ...@@ -2752,9 +2938,9 @@ a_expr: attr opt_indirection
makeA_Expr(OP, "<", $1, $4), makeA_Expr(OP, "<", $1, $4),
makeA_Expr(OP, ">", $1, $6)); makeA_Expr(OP, ">", $1, $6));
} }
| a_expr IN { saved_In_Expr = $1; } '(' in_expr_nodes ')' | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')'
{ $$ = $5; } { $$ = $5; }
| a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')' | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
{ $$ = $6; } { $$ = $6; }
| a_expr AND a_expr | a_expr AND a_expr
{ $$ = makeA_Expr(AND, NULL, $1, $3); } { $$ = makeA_Expr(AND, NULL, $1, $3); }
...@@ -2790,7 +2976,7 @@ expr_list: a_expr_or_null ...@@ -2790,7 +2976,7 @@ expr_list: a_expr_or_null
{ $$ = lappend($1, $3); } { $$ = lappend($1, $3); }
; ;
extract_list: DateTime FROM a_expr extract_list: datetime FROM a_expr
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
n->val.type = T_String; n->val.type = T_String;
...@@ -2838,14 +3024,21 @@ position_expr: attr opt_indirection ...@@ -2838,14 +3024,21 @@ position_expr: attr opt_indirection
((ParamNo *)$1)->typename = $3; ((ParamNo *)$1)->typename = $3;
$$ = (Node *)$1; $$ = (Node *)$1;
} }
| CAST AexprConst AS Typename | CAST position_expr AS Typename
{ {
$$ = (Node *)$2;
/* AexprConst can be either A_Const or ParamNo */ /* AexprConst can be either A_Const or ParamNo */
if (nodeTag($2) == T_A_Const) if (nodeTag($2) == T_A_Const) {
((A_Const *)$2)->typename = $4; ((A_Const *)$2)->typename = $4;
else } else if (nodeTag($2) == T_Param) {
((ParamNo *)$2)->typename = $4; ((ParamNo *)$2)->typename = $4;
$$ = (Node *)$2; /* otherwise, try to transform to a function call */
} else {
FuncCall *n = makeNode(FuncCall);
n->funcname = $4->name;
n->args = lcons($2,NIL);
$$ = (Node *)n;
}
} }
| '(' position_expr ')' | '(' position_expr ')'
{ $$ = $2; } { $$ = $2; }
...@@ -2855,7 +3048,7 @@ position_expr: attr opt_indirection ...@@ -2855,7 +3048,7 @@ position_expr: attr opt_indirection
{ $$ = makeA_Expr(OP, $1, NULL, $2); } { $$ = makeA_Expr(OP, $1, NULL, $2); }
| position_expr Op | position_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); } { $$ = makeA_Expr(OP, $2, $1, NULL); }
| Id | ColId
{ {
/* could be a column name or a relation_name */ /* could be a column name or a relation_name */
Ident *n = makeNode(Ident); Ident *n = makeNode(Ident);
...@@ -2955,6 +3148,15 @@ trim_list: a_expr FROM expr_list ...@@ -2955,6 +3148,15 @@ trim_list: a_expr FROM expr_list
{ $$ = $1; } { $$ = $1; }
; ;
in_expr: SubSelect
{
elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
$$ = $1;
}
| in_expr_nodes
{ $$ = $1; }
;
in_expr_nodes: AexprConst in_expr_nodes: AexprConst
{ $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); } { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
| in_expr_nodes ',' AexprConst | in_expr_nodes ',' AexprConst
...@@ -2963,6 +3165,15 @@ in_expr_nodes: AexprConst ...@@ -2963,6 +3165,15 @@ in_expr_nodes: AexprConst
} }
; ;
not_in_expr: SubSelect
{
elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
$$ = $1;
}
| not_in_expr_nodes
{ $$ = $1; }
;
not_in_expr_nodes: AexprConst not_in_expr_nodes: AexprConst
{ $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); } { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
| not_in_expr_nodes ',' AexprConst | not_in_expr_nodes ',' AexprConst
...@@ -2997,13 +3208,6 @@ attrs: attr_name ...@@ -2997,13 +3208,6 @@ attrs: attr_name
{ $$ = lappend($1, makeString("*")); } { $$ = lappend($1, makeString("*")); }
; ;
DateTime: YEARINTERVAL { $$ = "year"; }
| MONTHINTERVAL { $$ = "month"; }
| DAYINTERVAL { $$ = "day"; }
| HOURINTERVAL { $$ = "hour"; }
| MINUTEINTERVAL { $$ = "minute"; }
| SECONDINTERVAL { $$ = "second"; }
;
/***************************************************************************** /*****************************************************************************
* *
...@@ -3030,7 +3234,7 @@ res_target_list: res_target_list ',' res_target_el ...@@ -3030,7 +3234,7 @@ res_target_list: res_target_list ',' res_target_el
} }
; ;
res_target_el: Id opt_indirection '=' a_expr_or_null res_target_el: ColId opt_indirection '=' a_expr_or_null
{ {
$$ = makeNode(ResTarget); $$ = makeNode(ResTarget);
$$->name = $1; $$->name = $1;
...@@ -3070,7 +3274,7 @@ res_target_list2: res_target_list2 ',' res_target_el2 ...@@ -3070,7 +3274,7 @@ res_target_list2: res_target_list2 ',' res_target_el2
; ;
/* 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_or_null AS ColId res_target_el2: a_expr_or_null AS ColLabel
{ {
$$ = makeNode(ResTarget); $$ = makeNode(ResTarget);
$$->name = $3; $$->name = $3;
...@@ -3110,7 +3314,7 @@ res_target_el2: a_expr_or_null AS ColId ...@@ -3110,7 +3314,7 @@ res_target_el2: a_expr_or_null AS ColId
} }
; ;
opt_id: Id { $$ = $1; } opt_id: ColId { $$ = $1; }
| /* EMPTY */ { $$ = NULL; } | /* EMPTY */ { $$ = NULL; }
; ;
...@@ -3133,22 +3337,25 @@ relation_name: SpecialRuleRelation ...@@ -3133,22 +3337,25 @@ relation_name: SpecialRuleRelation
} }
; ;
database_name: Id { $$ = $1; }; database_name: ColId { $$ = $1; };
access_method: Id { $$ = $1; }; access_method: Id { $$ = $1; };
attr_name: ColId { $$ = $1; }; attr_name: ColId { $$ = $1; };
class: Id { $$ = $1; }; class: Id { $$ = $1; };
index_name: Id { $$ = $1; }; index_name: ColId { $$ = $1; };
name: Id { $$ = $1; } /* Functions
| DateTime { $$ = $1; } * Include date/time keywords as SQL92 extension.
| TIME { $$ = xlateSqlType("time"); } * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
| P_TYPE { $$ = xlateSqlType("type"); } */
; name: ColId { $$ = $1; };
date: Sconst { $$ = $1; }; date: Sconst { $$ = $1; };
file_name: Sconst { $$ = $1; }; file_name: Sconst { $$ = $1; };
recipe_name: Id { $$ = $1; }; recipe_name: Id { $$ = $1; };
/* Constants
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
*/
AexprConst: Iconst AexprConst: Iconst
{ {
A_Const *n = makeNode(A_Const); A_Const *n = makeNode(A_Const);
...@@ -3172,6 +3379,20 @@ AexprConst: Iconst ...@@ -3172,6 +3379,20 @@ AexprConst: Iconst
} }
| ParamNo | ParamNo
{ $$ = (Node *)$1; } { $$ = (Node *)$1; }
| TRUE_P
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = "t";
$$ = (Node *)n;
}
| FALSE_P
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = "f";
$$ = (Node *)n;
}
; ;
ParamNo: PARAM ParamNo: PARAM
...@@ -3188,17 +3409,33 @@ NumConst: Iconst { $$ = makeInteger($1); } ...@@ -3188,17 +3409,33 @@ NumConst: Iconst { $$ = makeInteger($1); }
Iconst: ICONST { $$ = $1; }; Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; }; Sconst: SCONST { $$ = $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
*/
Id: IDENT { $$ = $1; }; Id: IDENT { $$ = $1; };
/* Column identifier (also used for table identifier) /* Column identifier
* Allow date/time names ("year", etc.) (SQL/92 extension). * Include date/time keywords as SQL92 extension.
* Allow TYPE (SQL/92 non-reserved word). * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
* - thomas 1997-10-08
*/ */
ColId: Id { $$ = $1; } ColId: Id { $$ = $1; }
| DateTime { $$ = $1; } | datetime { $$ = $1; }
| TIME { $$ = "time"; } | TIME { $$ = "time"; }
| P_TYPE { $$ = "type"; } | TYPE_P { $$ = "type"; }
;
/* 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
*/
ColLabel: ColId { $$ = $1; }
| TRUE_P { $$ = "true"; }
| FALSE_P { $$ = "false"; }
; ;
SpecialRuleRelation: CURRENT SpecialRuleRelation: CURRENT
...@@ -3217,9 +3454,8 @@ SpecialRuleRelation: CURRENT ...@@ -3217,9 +3454,8 @@ SpecialRuleRelation: CURRENT
} }
; ;
Type: P_TYPE; Type: TYPE_P;
Pnull: PNULL; Pnull: NULL_P;
%% %%
...@@ -3243,16 +3479,18 @@ xlateSqlType(char *name) ...@@ -3243,16 +3479,18 @@ xlateSqlType(char *name)
{ {
if (!strcasecmp(name,"int") || if (!strcasecmp(name,"int") ||
!strcasecmp(name,"integer")) !strcasecmp(name,"integer"))
return "int4"; /* strdup("int4") -- strdup leaks memory here */ return "int4";
else if (!strcasecmp(name, "smallint")) else if (!strcasecmp(name, "smallint"))
return "int2"; return "int2";
else if (!strcasecmp(name, "real")) else if (!strcasecmp(name, "real"))
return "float8"; return "float8";
else if (!strcasecmp(name, "interval")) else if (!strcasecmp(name, "interval"))
return "timespan"; return "timespan";
else if (!strcasecmp(name, "boolean"))
return "bool";
else else
return name; return name;
} } /* xlateSqlName() */
void parser_init(Oid *typev, int nargs) void parser_init(Oid *typev, int 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