*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.77 1997/12/04 23:07:23 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.19 1998/07/26 04:30:31 scrappy Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
#include "utils/elog.h"
#include "access/xact.h"
+#ifdef MULTIBYTE
+#include "mb/pg_wchar.h"
+#endif
+
static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
static bool QueryIsRule = FALSE;
-static Node *saved_In_Expr;
+static List *saved_In_Expr = NIL;
static Oid *param_type_info;
static int pfunc_num_args;
extern List *parsetree;
*/
/*#define __YYSCLASS*/
+static char *xlateSqlFunc(char *);
static char *xlateSqlType(char *);
static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
+static Node *makeRowExpr(char *opr, List *largs, List *rargs);
+void mapTargetColumns(List *source, List *target);
static List *makeConstantList( A_Const *node);
static char *FlattenStringList(List *list);
static char *fmtId(char *rawid);
char chr;
char *str;
bool boolean;
- bool* pboolean; /* for pg_user privileges */
+ bool* pboolean; /* for pg_shadow privileges */
List *list;
Node *node;
Value *value;
VersionStmt *vstmt;
DefineStmt *dstmt;
RuleStmt *rstmt;
- AppendStmt *astmt;
+ InsertStmt *astmt;
}
%type <node> stmt,
AddAttrStmt, ClosePortalStmt,
- CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
+ CopyStmt, CreateStmt, CreateAsStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
CreatePLangStmt, DropPLangStmt,
- IndexStmt, ListenStmt, OptimizableStmt,
+ IndexStmt, ListenStmt, LockStmt, OptimizableStmt,
ProcedureStmt, RecipeStmt, RemoveAggrStmt, RemoveOperStmt,
RemoveFuncStmt, RemoveStmt,
RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
- CreatedbStmt, DestroydbStmt, VacuumStmt, RetrieveStmt, CursorStmt,
- ReplaceStmt, AppendStmt, NotifyStmt, DeleteStmt, ClusterStmt,
+ CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect, SubUnion,
+ UpdateStmt, InsertStmt, SelectStmt, NotifyStmt, DeleteStmt, ClusterStmt,
ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
CreateUserStmt, AlterUserStmt, DropUserStmt
-%type <str> opt_database, location
+%type <str> opt_database1, opt_database2, location, encoding
%type <pboolean> user_createdb_clause, user_createuser_clause
%type <str> user_passwd_clause
%type <str> user_valid_clause
%type <list> user_group_list, user_group_clause
-%type <node> SubSelect
%type <str> join_expr, join_outer, join_spec
%type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
%type <str> relation_name, copy_file_name, copy_delimiter, def_name,
database_name, access_method_clause, access_method, attr_name,
- class, index_name, name, file_name, recipe_name, aggr_argtype
+ class, index_name, name, func_name, file_name, recipe_name, aggr_argtype
%type <str> opt_id, opt_portal_name,
all_Op, MathOp, opt_name, opt_unique,
%type <list> stmtblock, stmtmulti,
relation_name_list, OptTableElementList,
OptInherit, definition,
- opt_with, def_args, def_name_list, func_argtypes,
+ opt_with, func_args, func_args_list,
oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
opt_column_list, columnList, opt_va_list, va_list,
sort_clause, sortby_list, index_params, index_list, name_list,
expr_list, attrs, res_target_list, res_target_list2,
def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
+%type <node> func_return
+%type <boolean> set_opt
+
+%type <boolean> TriggerForOpt, TriggerForType
+
%type <list> union_clause, select_list
%type <list> join_list
%type <sortgroupby>
join_using
%type <boolean> opt_union
+%type <boolean> opt_table
+%type <boolean> opt_trans
%type <node> position_expr
%type <list> extract_list, position_list
%type <node> columnDef, alter_clause
%type <defelt> def_elem
%type <node> def_arg, columnElem, where_clause,
- a_expr, a_expr_or_null, AexprConst,
+ a_expr, a_expr_or_null, b_expr, AexprConst,
in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
having_clause
-%type <value> NumConst
+%type <list> row_descriptor, row_list
+%type <node> row_expr
+%type <str> row_op
+%type <ival> sub_type
+%type <list> OptCreateAs, CreateAsList
+%type <node> CreateAsElement
+%type <value> NumericOnly, FloatOnly, IntegerOnly
%type <attr> event_object, attr
%type <sortgroupby> groupby
%type <sortgroupby> sortby
%type <paramno> ParamNo
%type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
-%type <str> generic, character, datetime
+%type <str> generic, numeric, character, datetime
+%type <str> extract_arg
%type <str> opt_charset, opt_collate
%type <str> opt_float, opt_numeric, opt_decimal
%type <boolean> opt_varying, opt_timezone
%type <ival> Iconst
%type <str> Sconst
-%type <str> Id, var_value, zone_value
+%type <str> UserId, var_value, zone_value
%type <str> ColId, ColLabel
+%type <str> TypeId
%type <node> TableConstraint
-%type <list> constraint_expr
-%type <list> default_expr
-%type <list> ColQualList
+%type <list> constraint_list, constraint_expr
+%type <list> default_list, default_expr
+%type <list> ColQualList, ColQualifier
%type <node> ColConstraint, ColConstraintElem
%type <list> key_actions, key_action
%type <str> key_match, key_reference
*/
/* Keywords (in SQL92 reserved words) */
-%token ACTION, ADD, ALL, ALTER, AND, AS, ASC,
+%token ACTION, ADD, ALL, ALTER, AND, ANY AS, ASC,
BEGIN_TRANS, BETWEEN, BOTH, BY,
CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT,
CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
GRANT, GROUP, HAVING, HOUR_P,
IN, INNER_P, INSERT, INTERVAL, INTO, IS,
JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
- MATCH, MINUTE_P, MONTH_P,
- NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NOTNULL, NULL_P, NUMERIC,
+ MATCH, MINUTE_P, MONTH_P, NAMES,
+ NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NULL_P, NUMERIC,
ON, OPTION, OR, ORDER, OUTER_P,
PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
REFERENCES, REVOKE, RIGHT, ROLLBACK,
SECOND_P, SELECT, SET, SUBSTRING,
- TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
- UNION, UNIQUE, UPDATE, USING,
- VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
+ TABLE, TIME, TIMESTAMP, TIMEZONE_HOUR, TIMEZONE_MINUTE,
+ TO, TRAILING, TRANSACTION, TRIM,
+ UNION, UNIQUE, UPDATE, USER, USING,
+ VALUES, VARCHAR, VARYING, VIEW,
WHERE, WITH, WORK, YEAR_P, ZONE
/* Keywords (in SQL3 reserved words) */
%token TYPE_P
/* Keywords for Postgres support (not in SQL92 reserved words) */
-%token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
- APPEND, BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
- DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
+%token ABORT_TRANS, AFTER, AGGREGATE, ANALYZE,
+ BACKWARD, BEFORE, BINARY, CACHE, CLUSTER, COPY, CYCLE,
+ DATABASE, DELIMITERS, DO, EACH, EXPLAIN, EXTEND,
FORWARD, FUNCTION, HANDLER,
- INDEX, INHERITS, INSTEAD, ISNULL,
- LANCOMPILER, LISTEN, LOAD, LOCATION, MERGE, MOVE,
- NEW, NONE, NOTHING, OIDS, OPERATOR, PROCEDURAL,
- RECIPE, RENAME, REPLACE, RESET, RETRIEVE, RETURNS, RULE,
- SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED,
- VACUUM, VERBOSE, VERSION
-
-/* Keywords (obsolete; retain temporarily for parser - thomas 1997-12-04) */
+ INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
+ LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION, MAXVALUE, MINVALUE, MOVE,
+ NEW, NONE, NOTHING, NOTNULL, OIDS, OPERATOR, PROCEDURAL,
+ RECIPE, RENAME, RESET, RETURNS, ROW, RULE,
+ SEQUENCE, SETOF, SHOW, START, STATEMENT, STDIN, STDOUT, TRUSTED,
+ VACUUM, VERBOSE, VERSION, ENCODING
+
+/* Keywords (obsolete; retain through next version for parser - thomas 1997-12-04) */
%token ARCHIVE
/*
*
* Todd A. Brandys
*/
-%token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
+%token PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
/* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT, SCONST, Op
%left AND
%right NOT
%right '='
+%nonassoc '<' '>'
%nonassoc LIKE
%nonassoc BETWEEN
%nonassoc IN
-%nonassoc Op
+%nonassoc Op /* multi-character ops and user-defined operators */
%nonassoc NOTNULL
%nonassoc ISNULL
%nonassoc IS
/* Unary Operators */
%right ':'
%left ';' /* end of statement or natural log */
-%nonassoc '<' '>'
%right UMINUS
%left '.'
%left '[' ']'
%nonassoc TYPECAST
-%nonassoc REDUCE
%left UNION
%%
| ClosePortalStmt
| CopyStmt
| CreateStmt
+ | CreateAsStmt
| CreateSeqStmt
| CreatePLangStmt
| CreateTrigStmt
| GrantStmt
| IndexStmt
| ListenStmt
+ | LockStmt
| ProcedureStmt
| RecipeStmt
| RemoveAggrStmt
/*****************************************************************************
*
- * Create a new postresql DBMS user
+ * Create a new Postgres DBMS user
*
*
*****************************************************************************/
-CreateUserStmt: CREATE USER Id
- user_passwd_clause
- user_createdb_clause
- user_createuser_clause
- user_group_clause
- user_valid_clause
- { CreateUserStmt *n = makeNode(CreateUserStmt);
- n->user = $3;
- n->password = $4;
- n->createdb = $5;
- n->createuser = $6;
- n->groupElts = $7;
- n->validUntil = $8;
- $$ = (Node *)n;
- }
- ;
+CreateUserStmt: CREATE USER UserId user_passwd_clause user_createdb_clause
+ user_createuser_clause user_group_clause user_valid_clause
+ {
+ CreateUserStmt *n = makeNode(CreateUserStmt);
+ n->user = $3;
+ n->password = $4;
+ n->createdb = $5;
+ n->createuser = $6;
+ n->groupElts = $7;
+ n->validUntil = $8;
+ $$ = (Node *)n;
+ }
+ ;
/*****************************************************************************
*
*
*****************************************************************************/
-AlterUserStmt: ALTER USER Id
- user_passwd_clause
- user_createdb_clause
- user_createuser_clause
- user_group_clause
- user_valid_clause
- { AlterUserStmt *n = makeNode(AlterUserStmt);
- n->user = $3;
- n->password = $4;
- n->createdb = $5;
- n->createuser = $6;
- n->groupElts = $7;
- n->validUntil = $8;
- $$ = (Node *)n;
- }
- ;
+AlterUserStmt: ALTER USER UserId user_passwd_clause user_createdb_clause
+ user_createuser_clause user_group_clause user_valid_clause
+ {
+ AlterUserStmt *n = makeNode(AlterUserStmt);
+ n->user = $3;
+ n->password = $4;
+ n->createdb = $5;
+ n->createuser = $6;
+ n->groupElts = $7;
+ n->validUntil = $8;
+ $$ = (Node *)n;
+ }
+ ;
/*****************************************************************************
*
*
*****************************************************************************/
-DropUserStmt: DROP USER Id
- { DropUserStmt *n = makeNode(DropUserStmt);
- n->user = $3;
- $$ = (Node *)n;
- }
- ;
-
-user_passwd_clause: WITH PASSWORD Id { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
-user_createdb_clause: CREATEDB { bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = true;
- }
- | NOCREATEDB { bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = false;
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
-user_createuser_clause: CREATEUSER { bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = true;
- }
- | NOCREATEUSER { bool* b;
- $$ = (b = (bool*)palloc(sizeof(bool)));
- *b = false;
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
-user_group_list: user_group_list ',' Id { $$ = lcons((void*)makeString($3), $1); }
- | Id { $$ = makeList((void*)makeString($1), NULL); }
- ;
-
-user_group_clause: IN GROUP user_group_list { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
-user_valid_clause: VALID UNTIL SCONST { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
+DropUserStmt: DROP USER UserId
+ {
+ DropUserStmt *n = makeNode(DropUserStmt);
+ n->user = $3;
+ $$ = (Node *)n;
+ }
+ ;
+
+user_passwd_clause: WITH PASSWORD UserId { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+user_createdb_clause: CREATEDB
+ {
+ bool* b;
+ $$ = (b = (bool*)palloc(sizeof(bool)));
+ *b = true;
+ }
+ | NOCREATEDB
+ {
+ bool* b;
+ $$ = (b = (bool*)palloc(sizeof(bool)));
+ *b = false;
+ }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+user_createuser_clause: CREATEUSER
+ {
+ bool* b;
+ $$ = (b = (bool*)palloc(sizeof(bool)));
+ *b = true;
+ }
+ | NOCREATEUSER
+ {
+ bool* b;
+ $$ = (b = (bool*)palloc(sizeof(bool)));
+ *b = false;
+ }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+user_group_list: user_group_list ',' UserId
+ {
+ $$ = lcons((void*)makeString($3), $1);
+ }
+ | UserId
+ {
+ $$ = lcons((void*)makeString($1), NIL);
+ }
+ ;
+
+user_group_clause: IN GROUP user_group_list { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+user_valid_clause: VALID UNTIL SCONST { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
/*****************************************************************************
*
n->value = $4;
$$ = (Node *) n;
}
+ | SET NAMES encoding
+ {
+#ifdef MB
+ VariableSetStmt *n = makeNode(VariableSetStmt);
+ n->name = "client_encoding";
+ n->value = $3;
+ $$ = (Node *) n;
+#else
+ elog(ERROR, "SET NAMES is not supported");
+#endif
+ }
;
var_value: Sconst { $$ = $1; }
zone_value: Sconst { $$ = $1; }
| DEFAULT { $$ = NULL; }
- | LOCAL { $$ = "default"; }
+ | LOCAL { $$ = NULL; }
;
VariableShowStmt: SHOW ColId
Node *lp = lfirst($3);
if (length($3) != 1)
- elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
+ elog(ERROR,"ALTER TABLE/ADD() allows one column only");
$$ = lp;
}
| DROP opt_column ColId
- { elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
+ { elog(ERROR,"ALTER TABLE/DROP COLUMN not yet implemented"); }
| ALTER opt_column ColId SET DEFAULT default_expr
- { elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
+ { elog(ERROR,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented"); }
| ALTER opt_column ColId DROP DEFAULT
- { elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
+ { elog(ERROR,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented"); }
| ADD ConstraintElem
- { elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
+ { elog(ERROR,"ALTER TABLE/ADD CONSTRAINT not yet implemented"); }
;
;
opt_with_copy: WITH OIDS { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
/*
* the default copy delimiter is tab but the user can configure it
*/
-copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
- | /* EMPTY */ { $$ = "\t"; }
+copy_delimiter: USING DELIMITERS Sconst { $$ = $3; }
+ | /*EMPTY*/ { $$ = "\t"; }
;
;
OptTableElementList: OptTableElementList ',' OptTableElement
- { $$ = lappend($1, $3); }
- | OptTableElement { $$ = lcons($1, NIL); }
+ {
+ if ($3 != NULL)
+ $$ = lappend($1, $3);
+ else
+ $$ = $1;
+ }
+ | OptTableElement
+ {
+ if ($1 != NULL)
+ $$ = lcons($1, NIL);
+ else
+ $$ = NULL;
+ }
| /*EMPTY*/ { $$ = NULL; }
;
| TableConstraint { $$ = $1; }
;
-columnDef: ColId Typename ColQualList
+columnDef: ColId Typename ColQualifier
{
ColumnDef *n = makeNode(ColumnDef);
n->colname = $1;
}
;
-/* ColQualList decodes column-specific qualifiers.
- * Seem to need to specify the explicit combinations
- * to eliminate reduce/reduce conflicts.
- * I think this is because there are no explicit delimiters
- * (like commas) between clauses.
- * - thomas 1997-12-03
- */
-ColQualList: ColConstraint ColConstraint ColConstraint ColConstraint
- { $$ = lappend(lappend(lappend(lcons($1, NIL), $2), $3), $4); }
- | ColConstraint ColConstraint ColConstraint
- { $$ = lappend(lappend(lcons($1, NIL), $2), $3); }
- | ColConstraint ColConstraint { $$ = lappend(lcons($1, NIL), $2); }
- | ColConstraint { $$ = lcons($1, NIL); }
+ColQualifier: ColQualList { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
+ColQualList: ColQualList ColConstraint
+ {
+ if ($2 != NULL)
+ $$ = lappend($1, $2);
+ else
+ $$ = $1;
+ }
+ | ColConstraint
+ {
+ if ($1 != NULL)
+ $$ = lcons($1, NIL);
+ else
+ $$ = NULL;
+ }
+ ;
+
ColConstraint:
CONSTRAINT name ColConstraintElem
{
Constraint *n = (Constraint *)$3;
- n->name = fmtId($2);
+ if (n != NULL) n->name = fmtId($2);
$$ = $3;
}
| ColConstraintElem
n->keys = NULL;
$$ = (Node *)n;
}
- | NOTNULL
- {
- Constraint *n = makeNode(Constraint);
- n->contype = CONSTR_NOTNULL;
- n->name = NULL;
- n->def = NULL;
- n->keys = NULL;
- $$ = (Node *)n;
- }
| UNIQUE
{
Constraint *n = makeNode(Constraint);
}
| REFERENCES ColId opt_column_list key_match key_actions
{
- elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented",NULL);
+ elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
$$ = NULL;
}
;
+default_list: default_list ',' default_expr
+ {
+ $$ = lappend($1,makeString(","));
+ $$ = nconc($$, $3);
+ }
+ | default_expr
+ {
+ $$ = $1;
+ }
+ ;
+
default_expr: AexprConst
{ $$ = makeConstantList((A_Const *) $1); }
| NULL_P
| default_expr '*' default_expr
{ $$ = nconc( $1, lcons( makeString( "*"), $3)); }
| default_expr '=' default_expr
- { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
+ { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
| default_expr '<' default_expr
- { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
+ { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
| default_expr '>' default_expr
- { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
+ { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
| ':' default_expr
{ $$ = lcons( makeString( ":"), $2); }
| ';' default_expr
$3->name = fmtId($3->name);
$$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
}
- | CAST default_expr AS Typename
+ | CAST '(' default_expr AS Typename ')'
{
- $4->name = fmtId($4->name);
- $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
+ $5->name = fmtId($5->name);
+ $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
}
| '(' default_expr ')'
{ $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
- | name '(' default_expr ')'
+ | func_name '(' ')'
{
$$ = makeList( makeString($1), makeString("("), -1);
- $$ = nconc( $$, $3);
$$ = lappend( $$, makeString(")"));
}
- | name '(' ')'
+ | func_name '(' default_list ')'
{
$$ = makeList( makeString($1), makeString("("), -1);
+ $$ = nconc( $$, $3);
$$ = lappend( $$, makeString(")"));
}
| default_expr Op default_expr
{
if (!strcmp("<=", $2) || !strcmp(">=", $2))
- elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
+ elog(ERROR,"boolean expressions not supported in DEFAULT");
$$ = nconc( $1, lcons( makeString( $2), $3));
}
| Op default_expr
}
| CURRENT_USER
{ $$ = lcons( makeString( "CURRENT_USER"), NIL); }
+ | USER
+ { $$ = lcons( makeString( "USER"), NIL); }
;
/* ConstraintElem specifies constraint syntax which is not embedded into
TableConstraint: CONSTRAINT name ConstraintElem
{
Constraint *n = (Constraint *)$3;
- n->name = fmtId($2);
+ if (n != NULL) n->name = fmtId($2);
$$ = $3;
}
| ConstraintElem
$$ = (Node *)n;
}
| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
- { elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented",NULL); }
+ {
+ elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
+ $$ = NULL;
+ }
+ ;
+
+constraint_list: constraint_list ',' constraint_expr
+ {
+ $$ = lappend($1,makeString(","));
+ $$ = nconc($$, $3);
+ }
+ | constraint_expr
+ {
+ $$ = $1;
+ }
;
constraint_expr: AexprConst
$3->name = fmtId($3->name);
$$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
}
- | CAST constraint_expr AS Typename
+ | CAST '(' constraint_expr AS Typename ')'
{
- $4->name = fmtId($4->name);
- $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
+ $5->name = fmtId($5->name);
+ $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
}
| '(' constraint_expr ')'
{ $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
- | name '(' constraint_expr ')'
+ | func_name '(' ')'
+ {
+ $$ = makeList( makeString($1), makeString("("), -1);
+ $$ = lappend( $$, makeString(")"));
+ }
+ | func_name '(' constraint_list ')'
{
$$ = makeList( makeString($1), makeString("("), -1);
$$ = nconc( $$, $3);
}
| constraint_expr Op constraint_expr
{ $$ = nconc( $1, lcons( makeString( $2), $3)); }
+ | constraint_expr LIKE constraint_expr
+ { $$ = nconc( $1, lcons( makeString( "like"), $3)); }
| constraint_expr AND constraint_expr
{ $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
| constraint_expr OR constraint_expr
{ $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
+ | NOT constraint_expr
+ { $$ = lcons( makeString( "NOT"), $2); }
| Op constraint_expr
{ $$ = lcons( makeString( $1), $2); }
| constraint_expr Op
{ $$ = lappend( $1, makeString( $2)); }
+ | constraint_expr ISNULL
+ { $$ = lappend( $1, makeString( "IS NULL")); }
+ | constraint_expr IS NULL_P
+ { $$ = lappend( $1, makeString( "IS NULL")); }
+ | constraint_expr NOTNULL
+ { $$ = lappend( $1, makeString( "IS NOT NULL")); }
+ | constraint_expr IS NOT NULL_P
+ { $$ = lappend( $1, makeString( "IS NOT NULL")); }
| constraint_expr IS TRUE_P
{ $$ = lappend( $1, makeString( "IS TRUE")); }
| constraint_expr IS FALSE_P
| /*EMPTY*/ { }
;
+CreateAsStmt: CREATE TABLE relation_name OptCreateAs AS SubSelect
+ {
+ SelectStmt *n = (SelectStmt *)$6;
+ if ($4 != NIL)
+ mapTargetColumns($4, n->targetList);
+ n->into = $3;
+ $$ = (Node *)n;
+ }
+ ;
+
+OptCreateAs: '(' CreateAsList ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+CreateAsList: CreateAsList ',' CreateAsElement { $$ = lappend($1, $3); }
+ | CreateAsElement { $$ = lcons($1, NIL); }
+ ;
+
+CreateAsElement: ColId
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ n->colname = $1;
+ n->typename = NULL;
+ n->defval = NULL;
+ n->is_not_null = FALSE;
+ n->constraints = NULL;
+ $$ = (Node *)n;
+ }
+ ;
+
/*****************************************************************************
*
*
*****************************************************************************/
-CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
+CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
{
CreateSeqStmt *n = makeNode(CreateSeqStmt);
n->seqname = $3;
}
;
-OptSeqList:
- OptSeqList OptSeqElem
+OptSeqList: OptSeqList OptSeqElem
{ $$ = lappend($1, $2); }
- | { $$ = NIL; }
+ | { $$ = NIL; }
;
-OptSeqElem: IDENT NumConst
+OptSeqElem: CACHE IntegerOnly
{
$$ = makeNode(DefElem);
- $$->defname = $1;
+ $$->defname = "cache";
$$->arg = (Node *)$2;
}
- | IDENT
+ | CYCLE
{
$$ = makeNode(DefElem);
- $$->defname = $1;
+ $$->defname = "cycle";
$$->arg = (Node *)NULL;
}
+ | INCREMENT IntegerOnly
+ {
+ $$ = makeNode(DefElem);
+ $$->defname = "increment";
+ $$->arg = (Node *)$2;
+ }
+ | MAXVALUE IntegerOnly
+ {
+ $$ = makeNode(DefElem);
+ $$->defname = "maxvalue";
+ $$->arg = (Node *)$2;
+ }
+ | MINVALUE IntegerOnly
+ {
+ $$ = makeNode(DefElem);
+ $$->defname = "minvalue";
+ $$->arg = (Node *)$2;
+ }
+ | START IntegerOnly
+ {
+ $$ = makeNode(DefElem);
+ $$->defname = "start";
+ $$->arg = (Node *)$2;
+ }
+ ;
+
+NumericOnly: FloatOnly { $$ = $1; }
+ | IntegerOnly { $$ = $1; }
+
+FloatOnly: FCONST
+ {
+ $$ = makeFloat($1);
+ }
+ | '-' FCONST
+ {
+ $$ = makeFloat($2);
+ $$->val.dval = - $$->val.dval;
+ }
+ ;
+
+IntegerOnly: Iconst
+ {
+ $$ = makeInteger($1);
+ }
+ | '-' Iconst
+ {
+ $$ = makeInteger($2);
+ $$->val.ival = - $$->val.ival;
+ }
;
/*****************************************************************************
}
;
-TriggerActionTime: BEFORE { $$ = TRUE; }
- | AFTER { $$ = FALSE; }
+TriggerActionTime: BEFORE { $$ = TRUE; }
+ | AFTER { $$ = FALSE; }
;
TriggerEvents: TriggerOneEvent
- {
- char *e = palloc (4);
- e[0] = $1; e[1] = 0; $$ = e;
- }
- | TriggerOneEvent OR TriggerOneEvent
- {
- char *e = palloc (4);
- e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
- }
- | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
- {
- char *e = palloc (4);
- e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
- $$ = e;
- }
+ {
+ char *e = palloc (4);
+ e[0] = $1; e[1] = 0; $$ = e;
+ }
+ | TriggerOneEvent OR TriggerOneEvent
+ {
+ char *e = palloc (4);
+ e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
+ }
+ | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
+ {
+ char *e = palloc (4);
+ e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
+ $$ = e;
+ }
;
-TriggerOneEvent: INSERT { $$ = 'i'; }
- | DELETE { $$ = 'd'; }
- | UPDATE { $$ = 'u'; }
+TriggerOneEvent: INSERT { $$ = 'i'; }
+ | DELETE { $$ = 'd'; }
+ | UPDATE { $$ = 'u'; }
;
-TriggerForSpec: FOR name name
+TriggerForSpec: FOR TriggerForOpt TriggerForType
{
- if ( strcmp ($2, "each") != 0 )
- elog(WARN,"parser: syntax error near %s",$2);
- if ( strcmp ($3, "row") == 0 )
- $$ = TRUE;
- else if ( strcmp ($3, "statement") == 0 )
- $$ = FALSE;
- else
- elog(WARN,"parser: syntax error near %s",$3);
+ $$ = $3;
}
;
+TriggerForOpt: EACH { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+TriggerForType: ROW { $$ = TRUE; }
+ | STATEMENT { $$ = FALSE; }
+ ;
+
TriggerFuncArgs: TriggerFuncArg
{ $$ = lcons($1, NIL); }
- | TriggerFuncArgs ',' TriggerFuncArg
+ | TriggerFuncArgs ',' TriggerFuncArg
{ $$ = lappend($1, $3); }
- | /*EMPTY*/
+ | /*EMPTY*/
{ $$ = NIL; }
;
TriggerFuncArg: ICONST
- {
- char *s = (char *) palloc (256);
- sprintf (s, "%d", $1);
- $$ = s;
- }
- | FCONST
- {
- char *s = (char *) palloc (256);
- sprintf (s, "%g", $1);
- $$ = s;
- }
- | Sconst { $$ = $1; }
- | IDENT { $$ = $1; }
+ {
+ char *s = (char *) palloc (256);
+ sprintf (s, "%d", $1);
+ $$ = s;
+ }
+ | FCONST
+ {
+ char *s = (char *) palloc (256);
+ sprintf (s, "%g", $1);
+ $$ = s;
+ }
+ | Sconst { $$ = $1; }
+ | IDENT { $$ = $1; }
;
-DropTrigStmt: DROP TRIGGER name ON relation_name
+DropTrigStmt: DROP TRIGGER name ON relation_name
{
DropTrigStmt *n = makeNode(DropTrigStmt);
n->trigname = $3;
def_arg: ColId { $$ = (Node *)makeString($1); }
| all_Op { $$ = (Node *)makeString($1); }
- | NumConst { $$ = (Node *)$1; /* already a Value */ }
+ | NumericOnly { $$ = (Node *)$1; }
| Sconst { $$ = (Node *)makeString($1); }
| SETOF ColId
{
n->name = $2;
n->setof = TRUE;
n->arrayBounds = NULL;
+ n->typmod = -1;
$$ = (Node *)n;
}
- | DOUBLE { $$ = (Node *)makeString("double"); }
;
fetch_how_many: Iconst
{ $$ = $1;
- if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
- | ALL { $$ = 0; /* 0 means fetch all tuples*/}
+ if ($1 <= 0) elog(ERROR,"Please specify nonnegative count for fetch"); }
+ | ALL { $$ = 0; /* 0 means fetch all tuples*/ }
| /*EMPTY*/ { $$ = 1; /*default*/ }
;
-opt_portal_name: IN name { $$ = $2;}
+opt_portal_name: IN name { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; }
;
GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
{
$$ = (Node*)makeAclStmt($2,$4,$6,'+');
- free($2);
- free($6);
}
;
| operation_commalist ',' operation
{
$$ = aclmakepriv($1,$3);
- free($1);
}
;
RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
{
$$ = (Node*)makeAclStmt($2,$4,$6,'-');
- free($2);
- free($6);
}
;
| index_elem { $$ = lcons($1, NIL); }
;
-func_index: name '(' name_list ')' opt_type opt_class
+func_index: func_name '(' name_list ')' opt_type opt_class
{
$$ = makeNode(IndexElem);
$$->name = $1;
}
;
-opt_type: ':' Typename { $$ = $2;}
- | FOR Typename { $$ = $2;}
- | /*EMPTY*/ { $$ = NULL;}
+opt_type: ':' Typename { $$ = $2; }
+ | FOR Typename { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
;
/* opt_class "WITH class" conflicts with preceeding opt_type
{
RecipeStmt *n;
if (!IsTransactionBlock())
- elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
+ elog(ERROR,"EXECUTE RECIPE may only be used in begin/end transaction blocks");
n = makeNode(RecipeStmt);
n->recipeName = $3;
*
*****************************************************************************/
-ProcedureStmt: CREATE FUNCTION def_name def_args
- RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
+ProcedureStmt: CREATE FUNCTION func_name func_args
+ RETURNS func_return opt_with AS Sconst LANGUAGE Sconst
{
ProcedureStmt *n = makeNode(ProcedureStmt);
n->funcname = $3;
n->defArgs = $4;
- n->returnType = (Node *)$6;
+ n->returnType = $6;
n->withClause = $7;
n->as = $9;
n->language = $11;
};
opt_with: WITH definition { $$ = $2; }
- | /* EMPTY */ { $$ = NIL; }
+ | /*EMPTY*/ { $$ = NIL; }
;
-def_args: '(' def_name_list ')' { $$ = $2; }
+func_args: '(' func_args_list ')' { $$ = $2; }
| '(' ')' { $$ = NIL; }
;
-def_name_list: name_list;
+func_args_list: TypeId
+ { $$ = lcons(makeString($1),NIL); }
+ | func_args_list ',' TypeId
+ { $$ = lappend($1,makeString($3)); }
+ ;
+
+func_return: set_opt TypeId
+ {
+ TypeName *n = makeNode(TypeName);
+ n->name = $2;
+ n->setof = $1;
+ n->arrayBounds = NULL;
+ $$ = (Node *)n;
+ }
+ ;
+
+set_opt: SETOF { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
/*****************************************************************************
*
| VIEW { $$ = VIEW; }
;
+
RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
{
RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
| '*' { $$ = NULL; }
;
-RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
+
+RemoveFuncStmt: DROP FUNCTION func_name func_args
{
RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
n->funcname = $3;
- n->args = $5;
+ n->args = $4;
$$ = (Node *)n;
}
;
-func_argtypes: name_list { $$ = $1; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
{
oper_argtypes: name
{
- elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
+ elog(ERROR,"parser: argument type missing (use NONE for unary operators)");
}
| name ',' name
{ $$ = makeList(makeString($1), makeString($3), -1); }
;
opt_instead: INSTEAD { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
*
*****************************************************************************/
-TransactionStmt: ABORT_TRANS TRANSACTION
+TransactionStmt: ABORT_TRANS opt_trans
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = ABORT_TRANS;
$$ = (Node *)n;
}
- | BEGIN_TRANS TRANSACTION
+ | BEGIN_TRANS opt_trans
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = BEGIN_TRANS;
$$ = (Node *)n;
}
- | BEGIN_TRANS WORK
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = BEGIN_TRANS;
- $$ = (Node *)n;
- }
- | COMMIT WORK
+ | COMMIT opt_trans
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = END_TRANS;
$$ = (Node *)n;
}
- | END_TRANS TRANSACTION
+ | END_TRANS opt_trans
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = END_TRANS;
$$ = (Node *)n;
}
- | ROLLBACK WORK
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = ABORT_TRANS;
- $$ = (Node *)n;
- }
-
- | ABORT_TRANS
+ | ROLLBACK opt_trans
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = ABORT_TRANS;
$$ = (Node *)n;
}
- | BEGIN_TRANS
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = BEGIN_TRANS;
- $$ = (Node *)n;
- }
- | COMMIT
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = END_TRANS;
- $$ = (Node *)n;
- }
+ ;
- | END_TRANS
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = END_TRANS;
- $$ = (Node *)n;
- }
- | ROLLBACK
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = ABORT_TRANS;
- $$ = (Node *)n;
- }
+opt_trans: WORK { $$ = TRUE; }
+ | TRANSACTION { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = TRUE; }
;
*
*****************************************************************************/
-ViewStmt: CREATE VIEW name AS RetrieveStmt
+ViewStmt: CREATE VIEW name AS SelectStmt
{
ViewStmt *n = makeNode(ViewStmt);
n->viewname = $3;
n->query = (Query *)$5;
+ if (((SelectStmt *)n->query)->sortClause != NULL)
+ elog(ERROR,"Order by and Distinct on views is not implemented.");
+ if (((SelectStmt *)n->query)->unionClause != NULL)
+ elog(ERROR,"Views on unions not implemented.");
$$ = (Node *)n;
}
;
*
*****************************************************************************/
-CreatedbStmt: CREATE DATABASE database_name opt_database
+CreatedbStmt: CREATE DATABASE database_name WITH opt_database1 opt_database2
+ {
+ CreatedbStmt *n = makeNode(CreatedbStmt);
+ if ($5 == NULL && $6 == NULL) {
+ elog(ERROR, "CREATE DATABASE WITH requires at least an option");
+ }
+ n->dbname = $3;
+ n->dbpath = $5;
+#ifdef MULTIBYTE
+ if ($6 != NULL) {
+ n->encoding = pg_char_to_encoding($6);
+ if (n->encoding < 0) {
+ elog(ERROR, "invalid encoding name %s", $6);
+ }
+ } else {
+ n->encoding = GetTemplateEncoding();
+ }
+#else
+ elog(ERROR, "WITH ENCODING is not supported");
+#endif
+ $$ = (Node *)n;
+ }
+ | CREATE DATABASE database_name
{
CreatedbStmt *n = makeNode(CreatedbStmt);
n->dbname = $3;
- n->dbpath = $4;
+ n->dbpath = NULL;
+#ifdef MULTIBYTE
+ n->encoding = GetTemplateEncoding();
+#endif
$$ = (Node *)n;
}
;
-opt_database: WITH LOCATION '=' location { $$ = $4; }
+opt_database1: LOCATION '=' location { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+opt_database2: ENCODING '=' encoding { $$ = $3; }
| /*EMPTY*/ { $$ = NULL; }
;
| /*EMPTY*/ { $$ = NULL; }
;
+encoding: Sconst { $$ = $1; }
+ | DEFAULT { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
/*****************************************************************************
*
* QUERY:
n->vacrel = $4;
n->va_spec = $5;
if ( $5 != NIL && !$4 )
- elog(WARN,"parser: syntax error at or near \"(\"",NULL);
+ elog(ERROR,"parser: syntax error at or near \"(\"");
$$ = (Node *)n;
}
;
opt_verbose: VERBOSE { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
opt_analyze: ANALYZE { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
-opt_va_list: '(' va_list ')'
- { $$ = $2; }
- | /* EMPTY */
- { $$ = NIL; }
+opt_va_list: '(' va_list ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
;
va_list: name
* *
*****************************************************************************/
-OptimizableStmt: RetrieveStmt
+OptimizableStmt: SelectStmt
| CursorStmt
- | ReplaceStmt
- | AppendStmt
+ | UpdateStmt
+ | InsertStmt
| NotifyStmt
| DeleteStmt /* by default all are $$=$1 */
;
*
*****************************************************************************/
-AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
+InsertStmt: INSERT INTO relation_name opt_column_list insert_rest
{
$5->relname = $3;
$5->cols = $4;
insert_rest: VALUES '(' res_target_list2 ')'
{
- $$ = makeNode(AppendStmt);
+ $$ = makeNode(InsertStmt);
+ $$->unique = NULL;
$$->targetList = $3;
$$->fromClause = NIL;
$$->whereClause = NULL;
+ $$->groupClause = NIL;
+ $$->havingClause = NULL;
+ $$->unionClause = NIL;
}
- | SELECT res_target_list2 from_clause where_clause
+ | SELECT opt_unique res_target_list2
+ from_clause where_clause
+ group_clause having_clause
+ union_clause
{
- $$ = makeNode(AppendStmt);
- $$->targetList = $2;
- $$->fromClause = $3;
- $$->whereClause = $4;
+ $$ = makeNode(InsertStmt);
+ $$->unique = $2;
+ $$->targetList = $3;
+ $$->fromClause = $4;
+ $$->whereClause = $5;
+ $$->groupClause = $6;
+ $$->havingClause = $7;
+ $$->unionClause = $8;
}
;
}
;
+/*
+ * Total hack to just lock a table inside a transaction.
+ * Is it worth making this a separate command, with
+ * its own node type and file. I don't think so. bjm 1998/1/22
+ */
+LockStmt: LOCK_P opt_table relation_name
+ {
+ DeleteStmt *n = makeNode(DeleteStmt);
+ A_Const *c = makeNode(A_Const);
+
+ c->val.type = T_String;
+ c->val.val.str = "f";
+ c->typename = makeNode(TypeName);
+ c->typename->name = xlateSqlType("bool");
+ c->typename->typmod = -1;
+
+ n->relname = $3;
+ n->whereClause = (Node *)c;
+ $$ = (Node *)n;
+ }
+ ;
+
/*****************************************************************************
*
* QUERY:
- * ReplaceStmt (UPDATE)
+ * UpdateStmt (UPDATE)
*
*****************************************************************************/
-ReplaceStmt: UPDATE relation_name
+UpdateStmt: UPDATE relation_name
SET res_target_list
from_clause
where_clause
{
- ReplaceStmt *n = makeNode(ReplaceStmt);
+ UpdateStmt *n = makeNode(UpdateStmt);
n->relname = $2;
n->targetList = $4;
n->fromClause = $5;
* CURSOR STATEMENTS
*
*****************************************************************************/
-
CursorStmt: DECLARE name opt_binary CURSOR FOR
- SELECT opt_unique res_target_list2
- from_clause where_clause group_clause sort_clause
+ SELECT opt_unique res_target_list2
+ from_clause where_clause
+ group_clause having_clause
+ union_clause sort_clause
{
- CursorStmt *n = makeNode(CursorStmt);
+ SelectStmt *n = makeNode(SelectStmt);
/* from PORTAL name */
/*
* -- mao
*/
if (!IsTransactionBlock())
- elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
+ elog(ERROR,"Named portals may only be used in begin/end transaction blocks");
n->portalname = $2;
n->binary = $3;
n->fromClause = $9;
n->whereClause = $10;
n->groupClause = $11;
- n->sortClause = $12;
+ n->havingClause = $12;
+ n->unionClause = $13;
+ n->sortClause = $14;
$$ = (Node *)n;
}
;
*
*****************************************************************************/
-RetrieveStmt: SELECT opt_unique res_target_list2
+SelectStmt: SELECT opt_unique res_target_list2
result from_clause where_clause
group_clause having_clause
union_clause sort_clause
{
- RetrieveStmt *n = makeNode(RetrieveStmt);
+ SelectStmt *n = makeNode(SelectStmt);
n->unique = $2;
n->targetList = $3;
n->into = $4;
n->whereClause = $6;
n->groupClause = $7;
n->havingClause = $8;
- n->selectClause = $9;
+ n->unionClause = $9;
n->sortClause = $10;
$$ = (Node *)n;
}
;
-union_clause: UNION opt_union select_list { $$ = $3; }
- | /*EMPTY*/ { $$ = NIL; }
+SubSelect: SELECT opt_unique res_target_list2
+ from_clause where_clause
+ group_clause having_clause
+ union_clause
+ {
+ SelectStmt *n = makeNode(SelectStmt);
+ n->unique = $2;
+ n->targetList = $3;
+ n->fromClause = $4;
+ n->whereClause = $5;
+ n->groupClause = $6;
+ n->havingClause = $7;
+ n->unionClause = $8;
+ $$ = (Node *)n;
+ }
+ ;
+
+union_clause: UNION opt_union select_list
+ {
+ SelectStmt *n = (SelectStmt *)lfirst($3);
+ n->unionall = $2;
+ $$ = $3;
+ }
+ | /*EMPTY*/
+ { $$ = NIL; }
;
-select_list: select_list UNION opt_union SubSelect
- { $$ = lappend($1, $4); }
- | SubSelect
+select_list: select_list UNION opt_union SubUnion
+ {
+ SelectStmt *n = (SelectStmt *)$4;
+ n->unionall = $3;
+ $$ = lappend($1, $4);
+ }
+ | SubUnion
{ $$ = lcons($1, NIL); }
;
-SubSelect: SELECT opt_unique res_target_list2
+SubUnion: SELECT opt_unique res_target_list2
from_clause where_clause
group_clause having_clause
{
- SubSelect *n = makeNode(SubSelect);
+ SelectStmt *n = makeNode(SelectStmt);
n->unique = $2;
+ n->unionall = FALSE;
n->targetList = $3;
n->fromClause = $4;
n->whereClause = $5;
}
;
-result: INTO TABLE relation_name
- { $$= $3; }
- | /*EMPTY*/
- { $$ = NULL; }
+result: INTO opt_table relation_name { $$= $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+opt_table: TABLE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
opt_union: ALL { $$ = TRUE; }
*
* ...however, recursive addattr and rename supported. make special
* cases for these.
- *
- * XXX i believe '*' should be the default behavior, but...
*/
opt_inh_star: '*' { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
}
;
-having_clause: HAVING a_expr { $$ = $2; }
+having_clause: HAVING a_expr
+ {
+ $$ = $2;
+ }
| /*EMPTY*/ { $$ = NULL; }
;
from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
{
$$ = NIL;
- elog(WARN,"JOIN not yet implemented",NULL);
+ elog(ERROR,"JOIN not yet implemented");
}
| FROM from_list { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
from_list: from_list ',' from_val
{ $$ = lappend($1, $3); }
| from_val CROSS JOIN from_val
- { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
+ { elog(ERROR,"CROSS JOIN not yet implemented"); }
| from_val
{ $$ = lcons($1, NIL); }
;
join_expr: NATURAL join_expr { $$ = NULL; }
| FULL join_outer
- { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
+ { elog(ERROR,"FULL OUTER JOIN not yet implemented"); }
| LEFT join_outer
- { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
+ { elog(ERROR,"LEFT OUTER JOIN not yet implemented"); }
| RIGHT join_outer
- { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
+ { elog(ERROR,"RIGHT OUTER JOIN not yet implemented"); }
| OUTER_P
- { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
+ { elog(ERROR,"OUTER JOIN not yet implemented"); }
| INNER_P
- { elog(WARN,"INNER JOIN not yet implemented",NULL); }
+ { elog(ERROR,"INNER JOIN not yet implemented"); }
| UNION
- { elog(WARN,"UNION JOIN not yet implemented",NULL); }
+ { elog(ERROR,"UNION JOIN not yet implemented"); }
| /*EMPTY*/
- { elog(WARN,"INNER JOIN not yet implemented",NULL); }
+ { elog(ERROR,"INNER JOIN not yet implemented"); }
;
join_outer: OUTER_P { $$ = NULL; }
}
| relation_name '*' %prec '='
{
- /* inheiritance query */
+ /* inheritance query */
$$ = makeNode(RelExpr);
$$->relname = $1;
$$->inh = TRUE;
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType($1);
+ $$->typmod = -1;
}
;
-generic: Id { $$ = $1; }
+generic: IDENT { $$ = $1; }
| TYPE_P { $$ = xlateSqlType("type"); }
- | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
;
/* SQL92 numeric data types
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType($2);
+ $$->typmod = -1;
+ }
+ | DOUBLE PRECISION
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType("float");
}
| DECIMAL opt_decimal
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("integer");
+ $$->typmod = -1;
}
| NUMERIC opt_numeric
{
$$ = makeNode(TypeName);
$$->name = xlateSqlType("integer");
+ $$->typmod = -1;
}
;
+numeric: FLOAT
+ { $$ = xlateSqlType("float8"); }
+ | DOUBLE PRECISION
+ { $$ = xlateSqlType("float8"); }
+ | DECIMAL
+ { $$ = xlateSqlType("decimal"); }
+ | NUMERIC
+ { $$ = xlateSqlType("numeric"); }
+ ;
+
opt_float: '(' Iconst ')'
{
if ($2 < 1)
- elog(WARN,"precision for FLOAT must be at least 1",NULL);
+ elog(ERROR,"precision for FLOAT must be at least 1");
else if ($2 < 7)
$$ = xlateSqlType("float4");
else if ($2 < 16)
$$ = xlateSqlType("float8");
else
- elog(WARN,"precision for FLOAT must be less than 16",NULL);
+ elog(ERROR,"precision for FLOAT must be less than 16");
}
| /*EMPTY*/
{
opt_numeric: '(' Iconst ',' Iconst ')'
{
if ($2 != 9)
- elog(WARN,"NUMERIC precision %d must be 9",$2);
+ elog(ERROR,"NUMERIC precision %d must be 9",$2);
if ($4 != 0)
- elog(WARN,"NUMERIC scale %d must be zero",$4);
+ elog(ERROR,"NUMERIC scale %d must be zero",$4);
}
| '(' Iconst ')'
{
if ($2 != 9)
- elog(WARN,"NUMERIC precision %d must be 9",$2);
+ elog(ERROR,"NUMERIC precision %d must be 9",$2);
}
| /*EMPTY*/
{
opt_decimal: '(' Iconst ',' Iconst ')'
{
if ($2 > 9)
- elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
+ elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
if ($4 != 0)
- elog(WARN,"DECIMAL scale %d must be zero",$4);
+ elog(ERROR,"DECIMAL scale %d must be zero",$4);
$$ = NULL;
}
| '(' Iconst ')'
{
if ($2 > 9)
- elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
+ elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
$$ = NULL;
}
| /*EMPTY*/
Character: character '(' Iconst ')'
{
$$ = makeNode(TypeName);
- if (!strcasecmp($1, "char"))
+ if (strcasecmp($1, "char") == 0)
$$->name = xlateSqlType("bpchar");
- else if (!strcasecmp($1, "varchar"))
+ else if (strcasecmp($1, "varchar") == 0)
$$->name = xlateSqlType("varchar");
else
- yyerror("parse error");
+ yyerror("internal parsing error; unrecognized character type");
+
if ($3 < 1)
- elog(WARN,"length for '%s' type must be at least 1",$1);
+ elog(ERROR,"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 type '%s' cannot exceed 4096",$1);
+ elog(ERROR,"length for type '%s' cannot exceed 4096",$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;
+ $$->typmod = VARHDRSZ + $3;
}
| character
{
$$ = makeNode(TypeName);
- $$->name = xlateSqlType($1);
+ /* Let's try to make all single-character types into bpchar(1)
+ * - thomas 1998-05-07
+ */
+ if (strcasecmp($1, "char") == 0)
+ {
+ $$->name = xlateSqlType("bpchar");
+ $$->typmod = VARHDRSZ + 1;
+ }
+ else
+ {
+ $$->name = xlateSqlType($1);
+ $$->typmod = -1;
+ }
}
;
}
};
if ($4 != NULL)
- elog(WARN,"COLLATE %s not yet implemented",$4);
+ elog(NOTICE,"COLLATE %s not yet implemented; clause ignored",$4);
$$ = type;
}
- | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
- | VARCHAR { $$ = xlateSqlType("varchar"); }
- | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
- | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
- ;
-
-opt_varying: VARYING { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
- ;
-
-opt_charset: CHARACTER SET ColId { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
-opt_collate: COLLATE ColId { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
-Datetime: datetime
+ | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
+ | VARCHAR { $$ = xlateSqlType("varchar"); }
+ | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
+ | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
+ ;
+
+opt_varying: VARYING { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+opt_charset: CHARACTER SET ColId { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+opt_collate: COLLATE ColId { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+Datetime: datetime
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType($1);
+ $$->typmod = -1;
+ }
+ | TIMESTAMP opt_timezone
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType("timestamp");
+ $$->timezone = $2;
+ $$->typmod = -1;
+ }
+ | TIME
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType("time");
+ $$->typmod = -1;
+ }
+ | INTERVAL opt_interval
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType("interval");
+ $$->typmod = -1;
+ }
+ ;
+
+datetime: YEAR_P { $$ = "year"; }
+ | MONTH_P { $$ = "month"; }
+ | DAY_P { $$ = "day"; }
+ | HOUR_P { $$ = "hour"; }
+ | MINUTE_P { $$ = "minute"; }
+ | SECOND_P { $$ = "second"; }
+ ;
+
+opt_timezone: WITH TIME ZONE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+opt_interval: datetime { $$ = lcons($1, NIL); }
+ | YEAR_P TO MONTH_P { $$ = NIL; }
+ | DAY_P TO HOUR_P { $$ = NIL; }
+ | DAY_P TO MINUTE_P { $$ = NIL; }
+ | DAY_P TO SECOND_P { $$ = NIL; }
+ | HOUR_P TO MINUTE_P { $$ = NIL; }
+ | HOUR_P TO SECOND_P { $$ = NIL; }
+ | MINUTE_P TO SECOND_P { $$ = NIL; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+
+/*****************************************************************************
+ *
+ * expression grammar, still needs some cleanup
+ *
+ *****************************************************************************/
+
+a_expr_or_null: a_expr
+ { $$ = $1; }
+ | NULL_P
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_Null;
+ $$ = (Node *)n;
+ }
+ ;
+
+/* Expressions using row descriptors
+ * Define row_descriptor to allow yacc to break the reduce/reduce conflict
+ * with singleton expressions.
+ * Eliminated lots of code by defining row_op and sub_type clauses.
+ * However, can not consolidate EXPR_LINK case with others subselects
+ * due to shift/reduce conflict with the non-subselect clause (the parser
+ * would have to look ahead more than one token to resolve the conflict).
+ * - thomas 1998-05-09
+ */
+row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = $2;
+ n->oper = lcons("=",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $6;
+ $$ = (Node *)n;
+ }
+ | '(' row_descriptor ')' NOT IN '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = $2;
+ n->oper = lcons("<>",NIL);
+ n->useor = true;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $7;
+ $$ = (Node *)n;
+ }
+ | '(' row_descriptor ')' row_op sub_type '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = $2;
+ n->oper = lcons($4, NIL);
+ if (strcmp($4,"<>") == 0)
+ n->useor = true;
+ else
+ n->useor = false;
+ n->subLinkType = $5;
+ n->subselect = $7;
+ $$ = (Node *)n;
+ }
+ | '(' row_descriptor ')' row_op '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = $2;
+ n->oper = lcons($4, NIL);
+ if (strcmp($4,"<>") == 0)
+ n->useor = true;
+ else
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $6;
+ $$ = (Node *)n;
+ }
+ | '(' row_descriptor ')' row_op '(' row_descriptor ')'
+ {
+ $$ = makeRowExpr($4, $2, $6);
+ }
+ ;
+
+row_descriptor: row_list ',' a_expr
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+row_list: row_list ',' a_expr
+ {
+ $$ = lappend($1, $3);
+ }
+ | a_expr
+ {
+ $$ = lcons($1, NIL);
+ }
+ ;
+
+row_op: Op { $$ = $1; }
+ | '<' { $$ = "<"; }
+ | '=' { $$ = "="; }
+ | '>' { $$ = ">"; }
+ | '+' { $$ = "+"; }
+ | '-' { $$ = "-"; }
+ | '*' { $$ = "*"; }
+ | '/' { $$ = "/"; }
+ ;
+
+sub_type: ANY { $$ = ANY_SUBLINK; }
+ | ALL { $$ = ALL_SUBLINK; }
+ ;
+
+/*
+ * This is the heart of the expression syntax.
+ * Note that the BETWEEN clause looks similar to a boolean expression
+ * and so we must define b_expr which is almost the same as a_expr
+ * but without the boolean expressions.
+ * All operations are allowed in a BETWEEN clause if surrounded by parens.
+ */
+
+a_expr: attr opt_indirection
+ {
+ $1->indirection = $2;
+ $$ = (Node *)$1;
+ }
+ | row_expr
+ { $$ = $1; }
+ | AexprConst
+ { $$ = $1; }
+ | ColId
+ {
+ /* could be a column name or a relation_name */
+ Ident *n = makeNode(Ident);
+ n->name = $1;
+ n->indirection = NULL;
+ $$ = (Node *)n;
+ }
+ | '-' a_expr %prec UMINUS
+ { $$ = makeA_Expr(OP, "-", NULL, $2); }
+ | a_expr '+' a_expr
+ { $$ = makeA_Expr(OP, "+", $1, $3); }
+ | a_expr '-' a_expr
+ { $$ = makeA_Expr(OP, "-", $1, $3); }
+ | a_expr '/' a_expr
+ { $$ = makeA_Expr(OP, "/", $1, $3); }
+ | a_expr '*' a_expr
+ { $$ = makeA_Expr(OP, "*", $1, $3); }
+ | a_expr '<' a_expr
+ { $$ = makeA_Expr(OP, "<", $1, $3); }
+ | a_expr '>' a_expr
+ { $$ = makeA_Expr(OP, ">", $1, $3); }
+ | a_expr '=' a_expr
+ { $$ = makeA_Expr(OP, "=", $1, $3); }
+ | ':' a_expr
+ { $$ = makeA_Expr(OP, ":", NULL, $2); }
+ | ';' a_expr
+ { $$ = makeA_Expr(OP, ";", NULL, $2); }
+ | '|' a_expr
+ { $$ = makeA_Expr(OP, "|", NULL, $2); }
+ | a_expr TYPECAST Typename
+ {
+ $$ = (Node *)$1;
+ /* AexprConst can be either A_Const or ParamNo */
+ if (nodeTag($1) == T_A_Const) {
+ ((A_Const *)$1)->typename = $3;
+ } else if (nodeTag($1) == T_Param) {
+ ((ParamNo *)$1)->typename = $3;
+ /* otherwise, try to transform to a function call */
+ } else {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $3->name;
+ n->args = lcons($1,NIL);
+ $$ = (Node *)n;
+ }
+ }
+ | CAST '(' a_expr AS Typename ')'
+ {
+ $$ = (Node *)$3;
+ /* AexprConst can be either A_Const or ParamNo */
+ if (nodeTag($3) == T_A_Const) {
+ ((A_Const *)$3)->typename = $5;
+ } else if (nodeTag($5) == T_Param) {
+ ((ParamNo *)$3)->typename = $5;
+ /* otherwise, try to transform to a function call */
+ } else {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $5->name;
+ n->args = lcons($3,NIL);
+ $$ = (Node *)n;
+ }
+ }
+ | '(' a_expr_or_null ')'
+ { $$ = $2; }
+ | a_expr Op a_expr
+ { $$ = makeIndexable($2,$1,$3); }
+ | a_expr LIKE a_expr
+ { $$ = makeIndexable("~~", $1, $3); }
+ | a_expr NOT LIKE a_expr
+ { $$ = makeA_Expr(OP, "!~~", $1, $4); }
+ | Op a_expr
+ { $$ = makeA_Expr(OP, $1, NULL, $2); }
+ | a_expr Op
+ { $$ = makeA_Expr(OP, $2, $1, NULL); }
+ | func_name '(' '*' ')'
+ {
+ /* cheap hack for aggregate (eg. count) */
+ FuncCall *n = makeNode(FuncCall);
+ A_Const *star = makeNode(A_Const);
+
+ star->val.type = T_String;
+ star->val.val.str = "";
+ n->funcname = $1;
+ n->args = lcons(star, NIL);
+ $$ = (Node *)n;
+ }
+ | func_name '(' ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $1;
+ n->args = NIL;
+ $$ = (Node *)n;
+ }
+ | func_name '(' expr_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $1;
+ n->args = $3;
+ $$ = (Node *)n;
+ }
+ | CURRENT_DATE
+ {
+ A_Const *n = makeNode(A_Const);
+ TypeName *t = makeNode(TypeName);
+
+ n->val.type = T_String;
+ n->val.val.str = "now";
+ n->typename = t;
+
+ t->name = xlateSqlType("date");
+ t->setof = FALSE;
+ t->typmod = -1;
+
+ $$ = (Node *)n;
+ }
+ | CURRENT_TIME
+ {
+ A_Const *n = makeNode(A_Const);
+ TypeName *t = makeNode(TypeName);
+
+ n->val.type = T_String;
+ n->val.val.str = "now";
+ n->typename = t;
+
+ t->name = xlateSqlType("time");
+ t->setof = FALSE;
+ t->typmod = -1;
+
+ $$ = (Node *)n;
+ }
+ | CURRENT_TIME '(' Iconst ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ A_Const *s = makeNode(A_Const);
+ TypeName *t = makeNode(TypeName);
+
+ n->funcname = xlateSqlType("time");
+ n->args = lcons(s, NIL);
+
+ s->val.type = T_String;
+ s->val.val.str = "now";
+ s->typename = t;
+
+ t->name = xlateSqlType("time");
+ t->setof = FALSE;
+ t->typmod = -1;
+
+ if ($3 != 0)
+ elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
+
+ $$ = (Node *)n;
+ }
+ | CURRENT_TIMESTAMP
+ {
+ A_Const *n = makeNode(A_Const);
+ TypeName *t = makeNode(TypeName);
+
+ n->val.type = T_String;
+ n->val.val.str = "now";
+ n->typename = t;
+
+ t->name = xlateSqlType("timestamp");
+ t->setof = FALSE;
+ t->typmod = -1;
+
+ $$ = (Node *)n;
+ }
+ | CURRENT_TIMESTAMP '(' Iconst ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ A_Const *s = makeNode(A_Const);
+ TypeName *t = makeNode(TypeName);
+
+ n->funcname = xlateSqlType("timestamp");
+ n->args = lcons(s, NIL);
+
+ s->val.type = T_String;
+ s->val.val.str = "now";
+ s->typename = t;
+
+ t->name = xlateSqlType("timestamp");
+ t->setof = FALSE;
+ t->typmod = -1;
+
+ if ($3 != 0)
+ elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
+
+ $$ = (Node *)n;
+ }
+ | CURRENT_USER
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "getpgusername";
+ n->args = NIL;
+ $$ = (Node *)n;
+ }
+ | USER
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "getpgusername";
+ n->args = NIL;
+ $$ = (Node *)n;
+ }
+ | EXISTS '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = NIL;
+ n->useor = false;
+ n->oper = NIL;
+ n->subLinkType = EXISTS_SUBLINK;
+ n->subselect = $3;
+ $$ = (Node *)n;
+ }
+ | EXTRACT '(' extract_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "date_part";
+ n->args = $3;
+ $$ = (Node *)n;
+ }
+ | POSITION '(' position_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "strpos";
+ n->args = $3;
+ $$ = (Node *)n;
+ }
+ | SUBSTRING '(' substr_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "substr";
+ n->args = $3;
+ $$ = (Node *)n;
+ }
+ /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
+ | TRIM '(' BOTH trim_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "btrim";
+ n->args = $4;
+ $$ = (Node *)n;
+ }
+ | TRIM '(' LEADING trim_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "ltrim";
+ n->args = $4;
+ $$ = (Node *)n;
+ }
+ | TRIM '(' TRAILING trim_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "rtrim";
+ n->args = $4;
+ $$ = (Node *)n;
+ }
+ | TRIM '(' trim_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "btrim";
+ n->args = $3;
+ $$ = (Node *)n;
+ }
+ | a_expr ISNULL
+ { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
+ | a_expr IS NULL_P
+ { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
+ | a_expr NOTNULL
+ { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
+ | a_expr IS NOT NULL_P
+ { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
+ /* IS TRUE, IS FALSE, etc used to be function calls
+ * but let's make them expressions to allow the optimizer
+ * a chance to eliminate them if a_expr is a constant string.
+ * - thomas 1997-12-22
+ */
+ | a_expr IS TRUE_P
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_String;
+ n->val.val.str = "t";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
+ $$ = makeA_Expr(OP, "=", $1,(Node *)n);
+ }
+ | a_expr IS NOT FALSE_P
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_String;
+ n->val.val.str = "t";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
+ $$ = makeA_Expr(OP, "=", $1,(Node *)n);
+ }
+ | a_expr IS FALSE_P
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_String;
+ n->val.val.str = "f";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
+ $$ = makeA_Expr(OP, "=", $1,(Node *)n);
+ }
+ | a_expr IS NOT TRUE_P
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_String;
+ n->val.val.str = "f";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
+ $$ = makeA_Expr(OP, "=", $1,(Node *)n);
+ }
+ | a_expr BETWEEN b_expr AND b_expr
+ {
+ $$ = makeA_Expr(AND, NULL,
+ makeA_Expr(OP, ">=", $1, $3),
+ makeA_Expr(OP, "<=", $1, $5));
+ }
+ | a_expr NOT BETWEEN b_expr AND b_expr
+ {
+ $$ = makeA_Expr(OR, NULL,
+ makeA_Expr(OP, "<", $1, $4),
+ makeA_Expr(OP, ">", $1, $6));
+ }
+ | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')'
+ {
+ saved_In_Expr = lnext(saved_In_Expr);
+ if (nodeTag($5) == T_SubLink)
+ {
+ SubLink *n = (SubLink *)$5;
+ n->lefthand = lcons($1, NIL);
+ n->oper = lcons("=",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ $$ = (Node *)n;
+ }
+ else $$ = $5;
+ }
+ | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')'
+ {
+ saved_In_Expr = lnext(saved_In_Expr);
+ if (nodeTag($6) == T_SubLink)
+ {
+ SubLink *n = (SubLink *)$6;
+ n->lefthand = lcons($1, NIL);
+ n->oper = lcons("<>",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ $$ = (Node *)n;
+ }
+ else $$ = $6;
+ }
+ | a_expr Op '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons($2,NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr '+' '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("+",NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr '-' '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("-",NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr '/' '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("/",NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr '*' '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("*",NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr '<' '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("<",NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr '>' '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons(">",NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr '=' '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("=",NIL);
+ n->useor = false;
+ n->subLinkType = EXPR_SUBLINK;
+ n->subselect = $4;
+ $$ = (Node *)n;
+ }
+ | a_expr Op ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons($2,NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '+' ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons("+",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '-' ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons("-",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '/' ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons("/",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '*' ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons("*",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '<' ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons("<",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '>' ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons(">",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '=' ANY '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1,NIL);
+ n->oper = lcons("=",NIL);
+ n->useor = false;
+ n->subLinkType = ANY_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr Op ALL '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons($2,NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '+' ALL '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("+",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '-' ALL '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("-",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '/' ALL '(' SubSelect ')'
{
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType($1);
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("/",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
}
- | TIMESTAMP opt_timezone
+ | a_expr '*' ALL '(' SubSelect ')'
{
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("timestamp");
- $$->timezone = $2;
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("*",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
}
- | TIME
+ | a_expr '<' ALL '(' SubSelect ')'
{
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("time");
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("<",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
}
- | INTERVAL opt_interval
+ | a_expr '>' ALL '(' SubSelect ')'
{
- $$ = makeNode(TypeName);
- $$->name = xlateSqlType("interval");
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons(">",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
}
- ;
-
-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; }
- ;
-
-
-/*****************************************************************************
- *
- * expression grammar, still needs some cleanup
- *
- *****************************************************************************/
-
-a_expr_or_null: a_expr
- { $$ = $1;}
- | NULL_P
+ | a_expr '=' ALL '(' SubSelect ')'
{
- A_Const *n = makeNode(A_Const);
- n->val.type = T_Null;
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("=",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
$$ = (Node *)n;
}
+ | a_expr AND a_expr
+ { $$ = makeA_Expr(AND, NULL, $1, $3); }
+ | a_expr OR a_expr
+ { $$ = makeA_Expr(OR, NULL, $1, $3); }
+ | NOT a_expr
+ { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
+ ;
-a_expr: attr opt_indirection
+/*
+ * b_expr is a subset of the complete expression syntax
+ * defined by a_expr. b_expr is used in BETWEEN clauses
+ * to eliminate parser ambiguities stemming from the AND keyword.
+ */
+
+b_expr: attr opt_indirection
{
$1->indirection = $2;
$$ = (Node *)$1;
}
| AexprConst
{ $$ = $1; }
- | '-' a_expr %prec UMINUS
+ | ColId
+ {
+ /* could be a column name or a relation_name */
+ Ident *n = makeNode(Ident);
+ n->name = $1;
+ n->indirection = NULL;
+ $$ = (Node *)n;
+ }
+ | '-' b_expr %prec UMINUS
{ $$ = makeA_Expr(OP, "-", NULL, $2); }
- | a_expr '+' a_expr
+ | b_expr '+' b_expr
{ $$ = makeA_Expr(OP, "+", $1, $3); }
- | a_expr '-' a_expr
+ | b_expr '-' b_expr
{ $$ = makeA_Expr(OP, "-", $1, $3); }
- | a_expr '/' a_expr
+ | b_expr '/' b_expr
{ $$ = makeA_Expr(OP, "/", $1, $3); }
- | a_expr '*' a_expr
+ | b_expr '*' b_expr
{ $$ = makeA_Expr(OP, "*", $1, $3); }
- | a_expr '<' a_expr
- { $$ = makeA_Expr(OP, "<", $1, $3); }
- | a_expr '>' a_expr
- { $$ = makeA_Expr(OP, ">", $1, $3); }
- | a_expr '=' a_expr
- { $$ = makeA_Expr(OP, "=", $1, $3); }
- | ':' a_expr
+ | ':' b_expr
{ $$ = makeA_Expr(OP, ":", NULL, $2); }
- | ';' a_expr
+ | ';' b_expr
{ $$ = makeA_Expr(OP, ";", NULL, $2); }
- | '|' a_expr
+ | '|' b_expr
{ $$ = makeA_Expr(OP, "|", NULL, $2); }
- | a_expr TYPECAST Typename
+ | b_expr TYPECAST Typename
{
$$ = (Node *)$1;
/* AexprConst can be either A_Const or ParamNo */
$$ = (Node *)n;
}
}
- | CAST a_expr AS Typename
+ | CAST '(' b_expr AS Typename ')'
{
- $$ = (Node *)$2;
+ $$ = (Node *)$3;
/* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($2) == T_A_Const) {
- ((A_Const *)$2)->typename = $4;
- } else if (nodeTag($2) == T_Param) {
- ((ParamNo *)$2)->typename = $4;
+ if (nodeTag($3) == T_A_Const) {
+ ((A_Const *)$3)->typename = $5;
+ } else if (nodeTag($3) == T_Param) {
+ ((ParamNo *)$3)->typename = $5;
/* otherwise, try to transform to a function call */
} else {
FuncCall *n = makeNode(FuncCall);
- n->funcname = $4->name;
- n->args = lcons($2,NIL);
+ n->funcname = $5->name;
+ n->args = lcons($3,NIL);
$$ = (Node *)n;
}
}
- | '(' a_expr_or_null ')'
+ | '(' a_expr ')'
{ $$ = $2; }
- | a_expr Op a_expr
+ | b_expr Op b_expr
{ $$ = makeIndexable($2,$1,$3); }
- | a_expr LIKE a_expr
- { $$ = makeIndexable("~~", $1, $3); }
- | a_expr NOT LIKE a_expr
- { $$ = makeA_Expr(OP, "!~~", $1, $4); }
- | Op a_expr
+ | Op b_expr
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
- | a_expr Op
+ | b_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
- | ColId
- {
- /* could be a column name or a relation_name */
- Ident *n = makeNode(Ident);
- n->name = $1;
- n->indirection = NULL;
- $$ = (Node *)n;
- }
- | name '(' '*' ')'
+ | func_name '(' ')'
{
FuncCall *n = makeNode(FuncCall);
- Ident *star = makeNode(Ident);
-
- /* cheap hack for aggregate (eg. count) */
- star->name = "oid";
n->funcname = $1;
- n->args = lcons(star, NIL);
+ n->args = NIL;
$$ = (Node *)n;
}
- | name '(' ')'
+ | func_name '(' expr_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
- n->args = NIL;
+ n->args = $3;
$$ = (Node *)n;
}
| CURRENT_DATE
t->name = xlateSqlType("date");
t->setof = FALSE;
+ t->typmod = -1;
$$ = (Node *)n;
}
t->name = xlateSqlType("time");
t->setof = FALSE;
+ t->typmod = -1;
$$ = (Node *)n;
}
t->name = xlateSqlType("time");
t->setof = FALSE;
+ t->typmod = -1;
if ($3 != 0)
elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
t->name = xlateSqlType("timestamp");
t->setof = FALSE;
+ t->typmod = -1;
$$ = (Node *)n;
}
t->name = xlateSqlType("timestamp");
t->setof = FALSE;
+ t->typmod = -1;
if ($3 != 0)
elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
n->args = NIL;
$$ = (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 implemented",NULL);
- $$ = $3;
- }
- | EXTRACT '(' extract_list ')'
+ | USER
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "date_part";
- n->args = $3;
+ n->funcname = "getpgusername";
+ n->args = NIL;
$$ = (Node *)n;
}
| POSITION '(' position_list ')'
n->args = $3;
$$ = (Node *)n;
}
- | name '(' expr_list ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $3;
- $$ = (Node *)n;
- }
- | a_expr ISNULL
- { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
- | a_expr IS NULL_P
- { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
- | a_expr NOTNULL
- { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
- | a_expr IS NOT NULL_P
- { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
- | a_expr IS TRUE_P
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = "istrue";
- n->args = lcons($1,NIL);
- $$ = (Node *)n;
- }
- | a_expr IS FALSE_P
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = "isfalse";
- n->args = lcons($1,NIL);
- $$ = (Node *)n;
- }
- | a_expr IS NOT TRUE_P
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = "isfalse";
- n->args = lcons($1,NIL);
- $$ = (Node *)n;
- }
- | a_expr IS NOT FALSE_P
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = "istrue";
- n->args = lcons($1,NIL);
- $$ = (Node *)n;
- }
- | a_expr BETWEEN AexprConst AND AexprConst
- {
- $$ = makeA_Expr(AND, NULL,
- makeA_Expr(OP, ">=", $1, $3),
- makeA_Expr(OP, "<=", $1, $5));
- }
- | a_expr NOT BETWEEN AexprConst AND AexprConst
- {
- $$ = makeA_Expr(OR, NULL,
- makeA_Expr(OP, "<", $1, $4),
- makeA_Expr(OP, ">", $1, $6));
- }
- | a_expr IN { saved_In_Expr = $1; } '(' in_expr ')'
- { $$ = $5; }
- | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
- { $$ = $6; }
- | a_expr AND a_expr
- { $$ = makeA_Expr(AND, NULL, $1, $3); }
- | a_expr OR a_expr
- { $$ = makeA_Expr(OR, NULL, $1, $3); }
- | NOT a_expr
- { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
;
opt_indirection: '[' a_expr ']' opt_indirection
{ $$ = lappend($1, $3); }
;
-extract_list: datetime FROM a_expr
+extract_list: extract_arg FROM a_expr
{
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
{ $$ = NIL; }
;
+extract_arg: datetime { $$ = $1; }
+ | TIMEZONE_HOUR { $$ = "tz_hour"; }
+ | TIMEZONE_MINUTE { $$ = "tz_minute"; }
+ ;
+
position_list: position_expr IN position_expr
{ $$ = makeList($3, $1, -1); }
| /* EMPTY */
$$ = (Node *)n;
}
}
- | CAST position_expr AS Typename
+ | CAST '(' position_expr AS Typename ')'
{
- $$ = (Node *)$2;
+ $$ = (Node *)$3;
/* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($2) == T_A_Const) {
- ((A_Const *)$2)->typename = $4;
- } else if (nodeTag($2) == T_Param) {
- ((ParamNo *)$2)->typename = $4;
+ if (nodeTag($3) == T_A_Const) {
+ ((A_Const *)$3)->typename = $5;
+ } else if (nodeTag($3) == T_Param) {
+ ((ParamNo *)$3)->typename = $5;
/* otherwise, try to transform to a function call */
} else {
FuncCall *n = makeNode(FuncCall);
- n->funcname = $4->name;
- n->args = lcons($2,NIL);
+ n->funcname = $5->name;
+ n->args = lcons($3,NIL);
$$ = (Node *)n;
}
}
n->indirection = NULL;
$$ = (Node *)n;
}
- | name '(' ')'
+ | func_name '(' ')'
{
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = NIL;
$$ = (Node *)n;
}
+ | func_name '(' expr_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $1;
+ n->args = $3;
+ $$ = (Node *)n;
+ }
| POSITION '(' position_list ')'
{
FuncCall *n = makeNode(FuncCall);
n->args = $3;
$$ = (Node *)n;
}
- | name '(' expr_list ')'
- {
- FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = $3;
- $$ = (Node *)n;
- }
;
substr_list: expr_list substr_from substr_for
in_expr: SubSelect
{
- elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
- $$ = $1;
+ SubLink *n = makeNode(SubLink);
+ n->subselect = $1;
+ $$ = (Node *)n;
}
| in_expr_nodes
{ $$ = $1; }
;
in_expr_nodes: AexprConst
- { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
+ { $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); }
| in_expr_nodes ',' AexprConst
{ $$ = makeA_Expr(OR, NULL, $1,
- makeA_Expr(OP, "=", saved_In_Expr, $3));
+ makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3));
}
;
not_in_expr: SubSelect
{
- elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
- $$ = $1;
+ SubLink *n = makeNode(SubLink);
+ n->subselect = $1;
+ $$ = (Node *)n;
}
| not_in_expr_nodes
{ $$ = $1; }
;
not_in_expr_nodes: AexprConst
- { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
+ { $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); }
| not_in_expr_nodes ',' AexprConst
{ $$ = makeA_Expr(AND, NULL, $1,
- makeA_Expr(OP, "<>", saved_In_Expr, $3));
+ makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3));
}
;
/*
** 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 select into
** and update (uses a subset)
*/
res_target_list2: res_target_list2 ',' res_target_el2
/* disallow refs to variable system tables */
if (strcmp(LogRelationName, $1) == 0
|| strcmp(VariableRelationName, $1) == 0)
- elog(WARN,"%s cannot be accessed by users",$1);
+ elog(ERROR,"%s cannot be accessed by users",$1);
else
$$ = $1;
StrNCpy(saved_relname, $1, NAMEDATALEN);
;
database_name: ColId { $$ = $1; };
-access_method: Id { $$ = $1; };
+access_method: IDENT { $$ = $1; };
attr_name: ColId { $$ = $1; };
-class: Id { $$ = $1; };
+class: IDENT { $$ = $1; };
index_name: ColId { $$ = $1; };
/* Functions
* Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
*/
name: ColId { $$ = $1; };
+func_name: ColId { $$ = xlateSqlFunc($1); };
file_name: Sconst { $$ = $1; };
-recipe_name: Id { $$ = $1; };
+recipe_name: IDENT { $$ = $1; };
/* Constants
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = "t";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
$$ = (Node *)n;
}
| FALSE_P
A_Const *n = makeNode(A_Const);
n->val.type = T_String;
n->val.val.str = "f";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
$$ = (Node *)n;
}
;
}
;
-NumConst: Iconst { $$ = makeInteger($1); }
- | FCONST { $$ = makeFloat($1); }
- ;
-
Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; };
+UserId: IDENT { $$ = $1; };
/* Column and type identifier
* Does not include explicit datetime types
* since these must be decoupled in Typename syntax.
* Use ColId for most identifiers. - thomas 1997-10-21
*/
-Id: IDENT { $$ = $1; };
-
+TypeId: ColId
+ { $$ = xlateSqlType($1); }
+ | numeric
+ { $$ = xlateSqlType($1); }
+ | character
+ { $$ = xlateSqlType($1); }
+ ;
/* Column identifier
* Include date/time keywords as SQL92 extension.
* Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
* list due to shift/reduce conflicts in yacc. If so, move
* down to the ColLabel entity. - thomas 1997-11-06
*/
-ColId: Id { $$ = $1; }
+ColId: IDENT { $$ = $1; }
| datetime { $$ = $1; }
| ACTION { $$ = "action"; }
+ | CACHE { $$ = "cache"; }
+ | CYCLE { $$ = "cycle"; }
| DATABASE { $$ = "database"; }
| DELIMITERS { $$ = "delimiters"; }
+ | DOUBLE { $$ = "double"; }
+ | EACH { $$ = "each"; }
+ | ENCODING { $$ = "encoding"; }
| FUNCTION { $$ = "function"; }
+ | INCREMENT { $$ = "increment"; }
| INDEX { $$ = "index"; }
| KEY { $$ = "key"; }
| LANGUAGE { $$ = "language"; }
| LOCATION { $$ = "location"; }
| MATCH { $$ = "match"; }
+ | MAXVALUE { $$ = "maxvalue"; }
+ | MINVALUE { $$ = "minvalue"; }
| OPERATOR { $$ = "operator"; }
| OPTION { $$ = "option"; }
+ | PASSWORD { $$ = "password"; }
| PRIVILEGES { $$ = "privileges"; }
| RECIPE { $$ = "recipe"; }
+ | ROW { $$ = "row"; }
+ | START { $$ = "start"; }
+ | STATEMENT { $$ = "statement"; }
| TIME { $$ = "time"; }
+ | TIMEZONE_HOUR { $$ = "timezone_hour"; }
+ | TIMEZONE_MINUTE { $$ = "timezone_minute"; }
| TRIGGER { $$ = "trigger"; }
| TYPE_P { $$ = "type"; }
+ | VALID { $$ = "valid"; }
| VERSION { $$ = "version"; }
| ZONE { $$ = "zone"; }
;
if (QueryIsRule)
$$ = "*CURRENT*";
else
- elog(WARN,"CURRENT used in non-rule query",NULL);
+ elog(ERROR,"CURRENT used in non-rule query");
}
| NEW
{
if (QueryIsRule)
$$ = "*NEW*";
else
- elog(WARN,"NEW used in non-rule query",NULL);
+ elog(ERROR,"NEW used in non-rule query");
}
;
%%
-static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
+static Node *
+makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
{
A_Expr *a = makeNode(A_Expr);
a->oper = oper;
return (Node *)a;
}
+/* makeRowExpr()
+ * Generate separate operator nodes for a single row descriptor expression.
+ * Perhaps this should go deeper in the parser someday... - thomas 1997-12-22
+ */
+static Node *
+makeRowExpr(char *opr, List *largs, List *rargs)
+{
+ Node *expr = NULL;
+ Node *larg, *rarg;
+
+ if (length(largs) != length(rargs))
+ elog(ERROR,"Unequal number of entries in row expression");
+
+ if (lnext(largs) != NIL)
+ expr = makeRowExpr(opr,lnext(largs),lnext(rargs));
+
+ larg = lfirst(largs);
+ rarg = lfirst(rargs);
+
+ if ((strcmp(opr, "=") == 0)
+ || (strcmp(opr, "<") == 0)
+ || (strcmp(opr, "<=") == 0)
+ || (strcmp(opr, ">") == 0)
+ || (strcmp(opr, ">=") == 0))
+ {
+ if (expr == NULL)
+ expr = makeA_Expr(OP, opr, larg, rarg);
+ else
+ expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
+ }
+ else if (strcmp(opr, "<>") == 0)
+ {
+ if (expr == NULL)
+ expr = makeA_Expr(OP, opr, larg, rarg);
+ else
+ expr = makeA_Expr(OR, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
+ }
+ else
+ {
+ elog(ERROR,"Operator '%s' not implemented for row expressions",opr);
+ }
+
+#if FALSE
+ while ((largs != NIL) && (rargs != NIL))
+ {
+ larg = lfirst(largs);
+ rarg = lfirst(rargs);
+
+ if (expr == NULL)
+ expr = makeA_Expr(OP, opr, larg, rarg);
+ else
+ expr = makeA_Expr(AND, NULL, expr, makeA_Expr(OP, opr, larg, rarg));
+
+ largs = lnext(largs);
+ rargs = lnext(rargs);
+ }
+ pprint(expr);
+#endif
+
+ return expr;
+}
+
+void
+mapTargetColumns(List *src, List *dst)
+{
+ ColumnDef *s;
+ ResTarget *d;
+
+ if (length(src) != length(dst))
+ elog(ERROR,"CREATE TABLE/AS SELECT has mismatched column count");
+
+ while ((src != NIL) && (dst != NIL))
+ {
+ s = (ColumnDef *)lfirst(src);
+ d = (ResTarget *)lfirst(dst);
+
+ d->name = s->colname;
+
+ src = lnext(src);
+ dst = lnext(dst);
+ }
+
+ return;
+} /* mapTargetColumns() */
static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
{
for (pos = 0; n->val.val.str[pos]; pos++)
{
- if ((n->val.val.str[pos] == '%' &&
- n->val.val.str[pos+1] != '%') ||
- (n->val.val.str[pos] == '_' &&
- n->val.val.str[pos+1] != '_'))
- break;
- if (n->val.val.str[pos] == '%' ||
- n->val.val.str[pos] == '_' ||
- n->val.val.str[pos] == '\\')
+ if (n->val.val.str[pos] == '%' &&
+ n->val.val.str[pos+1] != '%')
+ break;
+ if(n->val.val.str[pos] == '_')
+ break;
+ if (n->val.val.str[pos] == '\\' ||
+ n->val.val.str[pos] == '%')
pos++;
+ if (n->val.val.str[pos] == '\0')
+ break;
match_least[match_pos] = n->val.val.str[pos];
match_most[match_pos++] = n->val.val.str[pos];
}
} /* makeIndexable() */
-/* xlateSqlType()
+/* xlateSqlFunc()
* Convert alternate type names to internal Postgres types.
* Do not convert "float", since that is handled elsewhere
* for FLOAT(p) syntax.
*/
static char *
+xlateSqlFunc(char *name)
+{
+ if (!strcasecmp(name,"character_length")
+ || !strcasecmp(name,"char_length"))
+ return "length";
+ else
+ return name;
+} /* xlateSqlFunc() */
+
+/* xlateSqlType()
+ * Convert alternate type names to internal Postgres types.
+ */
+static char *
xlateSqlType(char *name)
{
if (!strcasecmp(name,"int")
return "int4";
else if (!strcasecmp(name, "smallint"))
return "int2";
- else if (!strcasecmp(name, "real"))
+ else if (!strcasecmp(name, "real")
+ || !strcasecmp(name, "float"))
return "float8";
else if (!strcasecmp(name, "interval"))
return "timespan";
return "bool";
else
return name;
-} /* xlateSqlName() */
+} /* xlateSqlType() */
void parser_init(Oid *typev, int nargs)
*(s+len) = '\0';
#ifdef PARSEDEBUG
-printf( "flattened string is \"%s\"\n", s);
+ elog(DEBUG, "flattened string is \"%s\"\n", s);
#endif
- return(s);
+ return (s);
} /* FlattenStringList() */
static List *
makeConstantList( A_Const *n)
{
+ List *result = NIL;
+ char *typval = NULL;
char *defval = NULL;
+
if (nodeTag(n) != T_A_Const) {
- elog(WARN,"Cannot handle non-constant parameter",NULL);
+ elog(ERROR,"Cannot handle non-constant parameter");
} else if (n->val.type == T_Float) {
defval = (char*) palloc(20+1);
sprintf( defval, "%g", n->val.val.dval);
+ result = lcons( makeString(defval), NIL);
} else if (n->val.type == T_Integer) {
defval = (char*) palloc(20+1);
sprintf( defval, "%ld", n->val.val.ival);
+ result = lcons( makeString(defval), NIL);
} else if (n->val.type == T_String) {
defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
strcpy( defval, "'");
strcat( defval, ((A_Const *) n)->val.val.str);
strcat( defval, "'");
+ if (n->typename != NULL)
+ {
+ typval = (char*) palloc(strlen( n->typename->name) + 1);
+ strcpy(typval, n->typename->name);
+ result = lappend( lcons( makeString(typval), NIL), makeString(defval));
+ }
+ else
+ {
+ result = lcons( makeString(defval), NIL);
+ }
} else {
- elog(WARN,"Internal error in makeConstantList(): cannot encode node",NULL);
+ elog(ERROR,"Internal error in makeConstantList(): cannot encode node");
};
#ifdef PARSEDEBUG
-printf( "AexprConst argument is \"%s\"\n", defval);
+ elog(DEBUG, "AexprConst argument is \"%s\"\n", defval);
#endif
- return( lcons( makeString(defval), NIL));
+ return (result);
} /* makeConstantList() */
};
#ifdef PARSEDEBUG
-printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);
+ elog(DEBUG, "fmtId- %sconvert %s to %s\n",
+ ((cp == rawid)? "do not ": ""), rawid, cp);
#endif
- return(cp);
+ return (cp);
}
/*