*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.45 1997/09/13 03:15:46 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
* NOTES
* CAPITALS are used to represent terminal symbols.
* 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
* routines work
#include "nodes/parsenodes.h"
#include "nodes/print.h"
#include "parser/gramparse.h"
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h"
-#include "storage/smgr.h"
+#include "parser/parse_type.h"
#include "utils/acl.h"
+#include "utils/palloc.h"
#include "catalog/catname.h"
#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;
+
/*
* If you need access to certain yacc-generated variables and find that
* they're static by default, uncomment the next line. (this is not a
*/
/*#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);
+static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
+static void param_type_init(Oid *typev, int nargs);
+
+Oid param_type(int t); /* used in parse_expr.c */
/* old versions of flex define this as a macro */
#if defined(yywrap)
char chr;
char *str;
bool boolean;
+ bool* pboolean; /* for pg_shadow privileges */
List *list;
Node *node;
Value *value;
Attr *attr;
- ColumnDef *coldef;
- ConstraintDef *constrdef;
TypeName *typnam;
DefElem *defelt;
ParamString *param;
IndexElem *ielem;
RangeVar *range;
RelExpr *relexp;
- TimeRange *trange;
A_Indices *aind;
ResTarget *target;
ParamNo *paramno;
VersionStmt *vstmt;
DefineStmt *dstmt;
- PurgeStmt *pstmt;
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,
- IndexStmt, MoveStmt, ListenStmt, OptimizableStmt,
- ProcedureStmt, PurgeStmt,
- RecipeStmt, RemoveAggrStmt, RemoveOperStmt, RemoveFuncStmt, RemoveStmt,
+ CreatePLangStmt, DropPLangStmt,
+ 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,
- ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt
+ CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect, SubUnion,
+ UpdateStmt, InsertStmt, SelectStmt, NotifyStmt, DeleteStmt, ClusterStmt,
+ ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
+ CreateUserStmt, AlterUserStmt, DropUserStmt
+
+%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 <str> txname, char_type
-%type <node> SubSelect
%type <str> join_expr, join_outer, join_spec
-%type <boolean> TriggerActionTime, TriggerForSpec
+%type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
-%type <str> DateTime, TriggerEvents, TriggerFuncArg
+%type <str> TriggerEvents, TriggerFuncArg
%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,
- var_name, aggr_argtype
-
-%type <constrdef> ConstraintElem, ConstraintDef
+ class, index_name, name, func_name, file_name, recipe_name, aggr_argtype
%type <str> opt_id, opt_portal_name,
- before_clause, after_clause, all_Op, MathOp, opt_name, opt_unique,
- result, OptUseOp, opt_class, opt_range_start, opt_range_end,
- SpecialRuleRelation
+ all_Op, MathOp, opt_name, opt_unique,
+ result, OptUseOp, opt_class, SpecialRuleRelation
%type <str> privileges, operation_commalist, grantee
%type <chr> operation, TriggerOneEvent
%type <list> stmtblock, stmtmulti,
- relation_name_list, OptTableElementList, tableElementList,
- OptInherit, OptConstraint, ConstraintList, definition,
- opt_with, def_args, def_name_list, func_argtypes,
+ relation_name_list, OptTableElementList,
+ OptInherit, definition,
+ 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 <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 <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,
- index_opt_unique, opt_verbose, opt_analyze, opt_null
+%type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_copy,
+ index_opt_unique, opt_verbose, opt_analyze
-%type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
- def_type, opt_direction, remove_type, opt_column, event
+%type <ival> copy_dirn, def_type, opt_direction, remove_type,
+ opt_column, event
-%type <ival> OptLocation, opt_move_where, fetch_how_many
+%type <ival> fetch_how_many
%type <list> OptSeqList
%type <defelt> OptSeqElem
%type <dstmt> def_rest
-%type <pstmt> purge_quals
%type <astmt> insert_rest
-%type <typnam> Typename, typname, opt_type
-%type <coldef> columnDef
+%type <node> OptTableElement, ConstraintElem
+%type <node> columnDef, alter_clause
%type <defelt> def_elem
%type <node> def_arg, columnElem, where_clause,
- a_expr, a_expr_or_null, AexprConst,
- in_expr_nodes, not_in_expr_nodes,
+ 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 <ielem> index_elem, func_index
%type <range> from_val
%type <relexp> relation_expr
-%type <trange> time_range
%type <target> res_target_el, res_target_el2
%type <paramno> ParamNo
+%type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
+%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, date, var_value, zone_value
-%type <str> ColId
-
-%type <list> default_expr
-%type <str> opt_default
-%type <list> constraint_elem
+%type <str> UserId, var_value, zone_value
+%type <str> ColId, ColLabel
+%type <str> TypeId
+
+%type <node> TableConstraint
+%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
/*
* If you make any token changes, remember to:
* - update the keyword table in parser/keywords.c
*/
-/* Keywords */
-%token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
- AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
- BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BOTH, BY,
- CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN,
- COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CURRENT, CURSOR,
- DATABASE, DAYINTERVAL, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
- DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND,
- FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, HAVING, HEAVY, HOURINTERVAL,
- IN, INDEX, INHERITS, INNERJOIN, INSERT, INTERVAL, INSTEAD, INTO, IS, ISNULL,
- JOIN, LANGUAGE, LEADING, LEFT, LIGHT, LISTEN, LOAD, LOCAL, MERGE, MINUTEINTERVAL, MONTHINTERVAL, MOVE,
- NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
- OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
- PNULL, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE,
- RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE,
- SECONDINTERVAL, SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE,
- TABLE, TIME, TO, TRAILING, TRANSACTION, TRIGGER,
- UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
- VERBOSE, VERSION, VIEW, WHERE, WITH, WORK, YEARINTERVAL, ZONE
-%token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
-
-/* SQL-92 support */
-%token EXTRACT, POSITION, SUBSTRING, TRIM
-%token DOUBLE, PRECISION
-%token CHARACTER, VARYING
+/* Reserved word tokens
+ * SQL92 syntax has many type-specific constructs.
+ * So, go ahead and make these types reserved words,
+ * and call-out the syntax explicitly.
+ * This gets annoying when trying to also retain Postgres' nice
+ * type-extensible features, but we don't really have a choice.
+ * - thomas 1997-10-11
+ */
+
+/* Keywords (in SQL92 reserved words) */
+%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,
+ CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
+ DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
+ END_TRANS, EXECUTE, EXISTS, EXTRACT,
+ FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
+ GRANT, GROUP, HAVING, HOUR_P,
+ IN, INNER_P, INSERT, INTERVAL, INTO, IS,
+ JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
+ 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, 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 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, AFTER, AGGREGATE, ANALYZE,
+ BACKWARD, BEFORE, BINARY, CACHE, CLUSTER, COPY, CYCLE,
+ DATABASE, DELIMITERS, DO, EACH, EXPLAIN, EXTEND,
+ FORWARD, FUNCTION, HANDLER,
+ 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
+
+/*
+ * Tokens for pg_passwd support. The CREATEDB and CREATEUSER tokens should go away
+ * when some sort of pg_privileges relation is introduced.
+ *
+ * Todd A. Brandys
+ */
+%token PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
/* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT, SCONST, Op
%token OP
/* precedence */
-%left OR
-%left AND
-%right NOT
-%right '='
-%nonassoc LIKE
-%nonassoc BETWEEN
-%nonassoc IN
-%nonassoc Op
-%nonassoc NOTNULL
-%nonassoc ISNULL
-%nonassoc IS
-%left '+' '-'
-%left '*' '/'
-%left '|' /* this is the relation union op, not logical or */
-%right ':' /* Unary Operators */
-%left ';' /* end of statement or natural log */
-%nonassoc '<' '>'
-%right UMINUS
-%left '.'
-%left '[' ']'
-%nonassoc TYPECAST
-%nonassoc REDUCE
-%left UNION
+%left OR
+%left AND
+%right NOT
+%right '='
+%nonassoc '<' '>'
+%nonassoc LIKE
+%nonassoc BETWEEN
+%nonassoc IN
+%nonassoc Op /* multi-character ops and user-defined operators */
+%nonassoc NOTNULL
+%nonassoc ISNULL
+%nonassoc IS
+%left '+' '-'
+%left '*' '/'
+%left '|' /* this is the relation union op, not logical or */
+/* Unary Operators */
+%right ':'
+%left ';' /* end of statement or natural log */
+%right UMINUS
+%left '.'
+%left '[' ']'
+%nonassoc TYPECAST
+%left UNION
%%
-stmtblock: stmtmulti
+stmtblock: stmtmulti
{ parsetree = $1; }
- | stmt
+ | stmt
{ parsetree = lcons($1,NIL); }
;
-stmtmulti: stmtmulti stmt ';'
+stmtmulti: stmtmulti stmt ';'
{ $$ = lappend($1, $2); }
- | stmtmulti stmt
+ | stmtmulti stmt
{ $$ = lappend($1, $2); }
- | stmt ';'
+ | stmt ';'
{ $$ = lcons($1,NIL); }
;
stmt : AddAttrStmt
+ | AlterUserStmt
| ClosePortalStmt
| CopyStmt
| CreateStmt
+ | CreateAsStmt
| CreateSeqStmt
+ | CreatePLangStmt
| CreateTrigStmt
+ | CreateUserStmt
| ClusterStmt
| DefineStmt
| DestroyStmt
+ | DropPLangStmt
| DropTrigStmt
+ | DropUserStmt
| ExtendStmt
| ExplainStmt
| FetchStmt
| GrantStmt
| IndexStmt
- | MoveStmt
| ListenStmt
+ | LockStmt
| ProcedureStmt
- | PurgeStmt
| RecipeStmt
| RemoveAggrStmt
| RemoveOperStmt
| VariableResetStmt
;
+/*****************************************************************************
+ *
+ * Create a new Postgres DBMS user
+ *
+ *
+ *****************************************************************************/
+
+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;
+ }
+ ;
+
+/*****************************************************************************
+ *
+ * Alter a postresql DBMS user
+ *
+ *
+ *****************************************************************************/
+
+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;
+ }
+ ;
+
+/*****************************************************************************
+ *
+ * Drop a postresql DBMS user
+ *
+ *
+ *****************************************************************************/
+
+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; }
+ ;
+
/*****************************************************************************
*
* Set PG internal variable
- * SET var_name TO 'var_value'
+ * SET name TO 'var_value'
+ * Include SQL92 syntax (thomas 1997-10-22):
+ * SET TIME ZONE 'var_value'
*
*****************************************************************************/
-VariableSetStmt: SET var_name TO var_value
+VariableSetStmt: SET ColId TO var_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = $2;
n->value = $4;
$$ = (Node *) n;
}
- | SET var_name '=' var_value
+ | SET ColId '=' var_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = $2;
n->value = $4;
$$ = (Node *) n;
}
- | SET TIME ZONE zone_value
+ | SET TIME ZONE zone_value
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "timezone";
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; }
+var_value: Sconst { $$ = $1; }
+ | DEFAULT { $$ = NULL; }
;
-zone_value: Sconst { $$ = $1; }
- | LOCAL { $$ = NULL; }
+zone_value: Sconst { $$ = $1; }
+ | DEFAULT { $$ = NULL; }
+ | LOCAL { $$ = NULL; }
;
-VariableShowStmt: SHOW var_name
+VariableShowStmt: SHOW ColId
{
VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = $2;
$$ = (Node *) n;
}
+ | SHOW TIME ZONE
+ {
+ VariableShowStmt *n = makeNode(VariableShowStmt);
+ n->name = "timezone";
+ $$ = (Node *) n;
+ }
;
-VariableResetStmt: RESET var_name
+VariableResetStmt: RESET ColId
{
VariableResetStmt *n = makeNode(VariableResetStmt);
n->name = $2;
$$ = (Node *) n;
}
+ | RESET TIME ZONE
+ {
+ VariableResetStmt *n = makeNode(VariableResetStmt);
+ n->name = "timezone";
+ $$ = (Node *) n;
+ }
;
+
/*****************************************************************************
*
* QUERY :
*
*****************************************************************************/
-AddAttrStmt: ALTER TABLE relation_name opt_inh_star ADD COLUMN columnDef
+AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
{
AddAttrStmt *n = makeNode(AddAttrStmt);
n->relname = $3;
n->inh = $4;
- n->colDef = $7;
+ n->colDef = $5;
$$ = (Node *)n;
}
;
-/* Column definition might include WITH TIME ZONE, but only for the data types
- * called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
- * and "time". - thomas 1997-07-14
- */
-columnDef: Id Typename opt_with_col opt_default opt_null
+alter_clause: ADD opt_column columnDef
{
- $$ = makeNode(ColumnDef);
- $$->colname = $1;
- $$->typename = $2;
- $$->typename->timezone = $3;
- $$->defval = $4;
- $$->is_not_null = $5;
- if ($$->typename->timezone
- && (strcasecmp($$->typename->name, "timestamp")
- && strcasecmp($$->typename->name, "time")))
- elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
+ $$ = $3;
}
- ;
-
-opt_default: DEFAULT default_expr
+ | ADD '(' OptTableElementList ')'
{
- $$ = FlattenStringList($2);
- }
- | /*EMPTY*/ { $$ = NULL; }
- ;
+ Node *lp = lfirst($3);
-default_expr: AexprConst
- { $$ = makeConstantList((A_Const *) $1); }
- | Pnull
- { $$ = lcons( makeString("NULL"), NIL); }
- | '-' default_expr %prec UMINUS
- { $$ = lcons( makeString( "-"), $2); }
- | default_expr '+' default_expr
- { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
- | default_expr '-' default_expr
- { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
- | default_expr '/' default_expr
- { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
- | default_expr '*' default_expr
- { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
- | default_expr '=' default_expr
- { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
- | default_expr '<' default_expr
- { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
- | default_expr '>' default_expr
- { elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
- | ':' default_expr
- { $$ = lcons( makeString( ":"), $2); }
- | ';' default_expr
- { $$ = lcons( makeString( ";"), $2); }
- | '|' default_expr
- { $$ = lcons( makeString( "|"), $2); }
- | default_expr TYPECAST Typename
- {
- $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
- }
- | CAST default_expr AS Typename
- {
- $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
- }
- | '(' default_expr ')'
- { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
- | name '(' default_expr ')'
- {
- $$ = 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);
- $$ = nconc( $1, lcons( $2, $3));
+ if (length($3) != 1)
+ elog(ERROR,"ALTER TABLE/ADD() allows one column only");
+ $$ = lp;
}
- | Op default_expr
- { $$ = lcons( $1, $2); }
- | default_expr Op
- { $$ = lcons( $2, $1); }
- ;
-
-opt_null: NOT PNULL { $$ = TRUE; }
- | NOTNULL { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+ | DROP opt_column ColId
+ { elog(ERROR,"ALTER TABLE/DROP COLUMN not yet implemented"); }
+ | ALTER opt_column ColId SET DEFAULT default_expr
+ { elog(ERROR,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented"); }
+ | ALTER opt_column ColId DROP DEFAULT
+ { elog(ERROR,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented"); }
+ | ADD ConstraintElem
+ { elog(ERROR,"ALTER TABLE/ADD CONSTRAINT not yet implemented"); }
;
-opt_with_col: WITH TIME ZONE { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
- ;
/*****************************************************************************
*
copy_dirn: TO
{ $$ = TO; }
- | FROM
+ | FROM
{ $$ = FROM; }
;
| STDOUT { $$ = NULL; }
;
-opt_binary: BINARY { $$ = TRUE; }
- | /*EMPTY*/ { $$ = FALSE; }
+opt_binary: BINARY { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
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"; }
;
*****************************************************************************/
CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
- OptInherit OptConstraint OptArchiveType OptLocation
- OptArchiveLocation
+ OptInherit OptArchiveType
{
CreateStmt *n = makeNode(CreateStmt);
n->relname = $3;
n->tableElts = $5;
n->inhRelnames = $7;
- n->constraints = $8;
- n->archiveType = $9;
- n->location = $10;
- n->archiveLoc = $11;
+ n->constraints = NIL;
$$ = (Node *)n;
}
;
-OptTableElementList: tableElementList { $$ = $1; }
- | /* EMPTY */ { $$ = NULL; }
+OptTableElementList: OptTableElementList ',' OptTableElement
+ {
+ if ($3 != NULL)
+ $$ = lappend($1, $3);
+ else
+ $$ = $1;
+ }
+ | OptTableElement
+ {
+ if ($1 != NULL)
+ $$ = lcons($1, NIL);
+ else
+ $$ = NULL;
+ }
+ | /*EMPTY*/ { $$ = NULL; }
;
-tableElementList :
- tableElementList ',' columnDef
- { $$ = lappend($1, $3); }
- | columnDef
- { $$ = lcons($1, NIL); }
+OptTableElement: columnDef { $$ = $1; }
+ | TableConstraint { $$ = $1; }
;
-
-OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
- | /*EMPTY*/ { $$ = ARCH_NONE; }
+columnDef: ColId Typename ColQualifier
+ {
+ ColumnDef *n = makeNode(ColumnDef);
+ n->colname = $1;
+ n->typename = $2;
+ n->defval = NULL;
+ n->is_not_null = FALSE;
+ n->constraints = $3;
+ $$ = (Node *)n;
+ }
;
-archive_type: HEAVY { $$ = ARCH_HEAVY; }
- | LIGHT { $$ = ARCH_LIGHT; }
- | NONE { $$ = ARCH_NONE; }
+ColQualifier: ColQualList { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
;
-OptLocation: STORE '=' Sconst
- { $$ = smgrin($3); }
- | /*EMPTY*/
- { $$ = -1; }
+ColQualList: ColQualList ColConstraint
+ {
+ if ($2 != NULL)
+ $$ = lappend($1, $2);
+ else
+ $$ = $1;
+ }
+ | ColConstraint
+ {
+ if ($1 != NULL)
+ $$ = lcons($1, NIL);
+ else
+ $$ = NULL;
+ }
;
-OptArchiveLocation: ARCH_STORE '=' Sconst
- { $$ = smgrin($3); }
- | /*EMPTY*/
- { $$ = -1; }
+ColConstraint:
+ CONSTRAINT name ColConstraintElem
+ {
+ Constraint *n = (Constraint *)$3;
+ if (n != NULL) n->name = fmtId($2);
+ $$ = $3;
+ }
+ | ColConstraintElem
+ { $$ = $1; }
;
-OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
- | /*EMPTY*/ { $$ = NIL; }
+ColConstraintElem: CHECK '(' constraint_expr ')'
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_CHECK;
+ n->name = NULL;
+ n->def = FlattenStringList($3);
+ n->keys = NULL;
+ $$ = (Node *)n;
+ }
+ | DEFAULT default_expr
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_DEFAULT;
+ n->name = NULL;
+ n->def = FlattenStringList($2);
+ n->keys = NULL;
+ $$ = (Node *)n;
+ }
+ | NOT NULL_P
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_NOTNULL;
+ n->name = NULL;
+ n->def = NULL;
+ n->keys = NULL;
+ $$ = (Node *)n;
+ }
+ | UNIQUE
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_UNIQUE;
+ n->name = NULL;
+ n->def = NULL;
+ n->keys = NULL;
+ $$ = (Node *)n;
+ }
+ | PRIMARY KEY
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_PRIMARY;
+ n->name = NULL;
+ n->def = NULL;
+ n->keys = NULL;
+ $$ = (Node *)n;
+ }
+ | REFERENCES ColId opt_column_list key_match key_actions
+ {
+ elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
+ $$ = NULL;
+ }
;
-OptConstraint: ConstraintList { $$ = $1; }
- | /*EMPTY*/ { $$ = NULL; }
+default_list: default_list ',' default_expr
+ {
+ $$ = lappend($1,makeString(","));
+ $$ = nconc($$, $3);
+ }
+ | default_expr
+ {
+ $$ = $1;
+ }
;
-ConstraintList:
- ConstraintList ',' ConstraintElem
- { $$ = lappend($1, $3); }
+default_expr: AexprConst
+ { $$ = makeConstantList((A_Const *) $1); }
+ | NULL_P
+ { $$ = lcons( makeString("NULL"), NIL); }
+ | '-' default_expr %prec UMINUS
+ { $$ = lcons( makeString( "-"), $2); }
+ | default_expr '+' default_expr
+ { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
+ | default_expr '-' default_expr
+ { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
+ | default_expr '/' default_expr
+ { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
+ | default_expr '*' default_expr
+ { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
+ | default_expr '=' default_expr
+ { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
+ | default_expr '<' default_expr
+ { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
+ | default_expr '>' default_expr
+ { elog(ERROR,"boolean expressions not supported in DEFAULT"); }
+ | ':' default_expr
+ { $$ = lcons( makeString( ":"), $2); }
+ | ';' default_expr
+ { $$ = lcons( makeString( ";"), $2); }
+ | '|' default_expr
+ { $$ = lcons( makeString( "|"), $2); }
+ | default_expr TYPECAST Typename
+ {
+ $3->name = fmtId($3->name);
+ $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
+ }
+ | CAST '(' default_expr AS Typename ')'
+ {
+ $5->name = fmtId($5->name);
+ $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
+ }
+ | '(' default_expr ')'
+ { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
+ | func_name '(' ')'
+ {
+ $$ = makeList( makeString($1), makeString("("), -1);
+ $$ = lappend( $$, makeString(")"));
+ }
+ | func_name '(' default_list ')'
+ {
+ $$ = makeList( makeString($1), makeString("("), -1);
+ $$ = nconc( $$, $3);
+ $$ = lappend( $$, makeString(")"));
+ }
+ | default_expr Op default_expr
+ {
+ if (!strcmp("<=", $2) || !strcmp(">=", $2))
+ elog(ERROR,"boolean expressions not supported in DEFAULT");
+ $$ = nconc( $1, lcons( makeString( $2), $3));
+ }
+ | Op default_expr
+ { $$ = lcons( makeString( $1), $2); }
+ | default_expr Op
+ { $$ = 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(%d) precision not implemented; zero used instead",$3);
+ $$ = lcons( makeString( "'now'::time"), NIL);
+ }
+ | CURRENT_TIMESTAMP
+ { $$ = lcons( makeString( "now()"), NIL); }
+ | CURRENT_TIMESTAMP '(' Iconst ')'
+ {
+ if ($3 != 0)
+ elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
+ $$ = lcons( makeString( "now()"), NIL);
+ }
+ | CURRENT_USER
+ { $$ = lcons( makeString( "CURRENT_USER"), NIL); }
+ | USER
+ { $$ = lcons( makeString( "USER"), NIL); }
+ ;
+
+/* ConstraintElem specifies constraint syntax which is not embedded into
+ * a column definition. ColConstraintElem specifies the embedded form.
+ * - thomas 1997-12-03
+ */
+TableConstraint: CONSTRAINT name ConstraintElem
+ {
+ Constraint *n = (Constraint *)$3;
+ if (n != NULL) n->name = fmtId($2);
+ $$ = $3;
+ }
| ConstraintElem
- { $$ = lcons($1, NIL); }
+ { $$ = $1; }
;
-ConstraintElem:
- CONSTRAINT name ConstraintDef
+ConstraintElem: CHECK '(' constraint_expr ')'
{
- $3->name = $2;
- $$ = $3;
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_CHECK;
+ n->name = NULL;
+ n->def = FlattenStringList($3);
+ $$ = (Node *)n;
+ }
+ | UNIQUE '(' columnList ')'
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_UNIQUE;
+ n->name = NULL;
+ n->def = NULL;
+ n->keys = $3;
+ $$ = (Node *)n;
+ }
+ | PRIMARY KEY '(' columnList ')'
+ {
+ Constraint *n = makeNode(Constraint);
+ n->contype = CONSTR_PRIMARY;
+ n->name = NULL;
+ n->def = NULL;
+ n->keys = $4;
+ $$ = (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;
}
- | ConstraintDef { $$ = $1; }
;
-ConstraintDef: CHECK constraint_elem
+constraint_list: constraint_list ',' constraint_expr
{
- ConstraintDef *constr = palloc (sizeof(ConstraintDef));
-#ifdef PARSEDEBUG
-printf("in ConstraintDef\n");
-#endif
- constr->type = CONSTR_CHECK;
- constr->name = NULL;
- constr->def = FlattenStringList($2);
- $$ = constr;
+ $$ = lappend($1,makeString(","));
+ $$ = nconc($$, $3);
+ }
+ | constraint_expr
+ {
+ $$ = $1;
}
;
-constraint_elem: AexprConst
+constraint_expr: AexprConst
{ $$ = makeConstantList((A_Const *) $1); }
- | Pnull
+ | NULL_P
{ $$ = lcons( makeString("NULL"), NIL); }
- | Id
+ | ColId
+ {
+ $$ = lcons( makeString(fmtId($1)), NIL);
+ }
+ | '-' constraint_expr %prec UMINUS
+ { $$ = lcons( makeString( "-"), $2); }
+ | constraint_expr '+' constraint_expr
+ { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
+ | constraint_expr '-' constraint_expr
+ { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
+ | constraint_expr '/' constraint_expr
+ { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
+ | constraint_expr '*' constraint_expr
+ { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
+ | constraint_expr '=' constraint_expr
+ { $$ = nconc( $1, lcons( makeString( "="), $3)); }
+ | constraint_expr '<' constraint_expr
+ { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
+ | constraint_expr '>' constraint_expr
+ { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
+ | ':' constraint_expr
+ { $$ = lcons( makeString( ":"), $2); }
+ | ';' constraint_expr
+ { $$ = lcons( makeString( ";"), $2); }
+ | '|' constraint_expr
+ { $$ = lcons( makeString( "|"), $2); }
+ | constraint_expr TYPECAST Typename
+ {
+ $3->name = fmtId($3->name);
+ $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
+ }
+ | CAST '(' constraint_expr AS Typename ')'
+ {
+ $5->name = fmtId($5->name);
+ $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
+ }
+ | '(' constraint_expr ')'
+ { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
+ | func_name '(' ')'
{
-#ifdef PARSEDEBUG
-printf( "Id is %s\n", $1);
-#endif
- $$ = lcons( makeString($1), NIL);
- }
- | '-' constraint_elem %prec UMINUS
- { $$ = lcons( makeString( "-"), $2); }
- | constraint_elem '+' constraint_elem
- { $$ = nconc( $1, lcons( makeString( "+"), $3)); }
- | constraint_elem '-' constraint_elem
- { $$ = nconc( $1, lcons( makeString( "-"), $3)); }
- | constraint_elem '/' constraint_elem
- { $$ = nconc( $1, lcons( makeString( "/"), $3)); }
- | constraint_elem '*' constraint_elem
- { $$ = nconc( $1, lcons( makeString( "*"), $3)); }
- | constraint_elem '=' constraint_elem
- { $$ = nconc( $1, lcons( makeString( "="), $3)); }
- | constraint_elem '<' constraint_elem
- { $$ = nconc( $1, lcons( makeString( "<"), $3)); }
- | constraint_elem '>' constraint_elem
- { $$ = nconc( $1, lcons( makeString( ">"), $3)); }
- | ':' constraint_elem
- { $$ = lcons( makeString( ":"), $2); }
- | ';' constraint_elem
- { $$ = lcons( makeString( ";"), $2); }
- | '|' constraint_elem
- { $$ = lcons( makeString( "|"), $2); }
- | constraint_elem TYPECAST Typename
- {
- $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
- }
- | CAST constraint_elem AS Typename
- {
- $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
- }
- | '(' constraint_elem ')'
- { $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
- | name '(' constraint_elem ')'
+ $$ = makeList( makeString($1), makeString("("), -1);
+ $$ = lappend( $$, makeString(")"));
+ }
+ | func_name '(' constraint_list ')'
{
$$ = makeList( makeString($1), makeString("("), -1);
$$ = nconc( $$, $3);
$$ = lappend( $$, makeString(")"));
}
- | constraint_elem Op constraint_elem
- { $$ = nconc( $1, lcons( $2, $3)); }
- | constraint_elem AND constraint_elem
- { $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
- | constraint_elem OR constraint_elem
- { $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
- | Op constraint_elem
- { $$ = lcons( $1, $2); }
- | constraint_elem Op
- { $$ = lcons( $2, $1); }
+ | 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
+ { $$ = lappend( $1, makeString( "IS FALSE")); }
+ | constraint_expr IS NOT TRUE_P
+ { $$ = lappend( $1, makeString( "IS NOT TRUE")); }
+ | constraint_expr IS NOT FALSE_P
+ { $$ = lappend( $1, makeString( "IS NOT FALSE")); }
+ ;
+
+key_match: MATCH FULL { $$ = NULL; }
+ | MATCH PARTIAL { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; }
;
+key_actions: key_action key_action { $$ = NIL; }
+ | key_action { $$ = NIL; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
-/*****************************************************************************
- *
- * QUERY :
- * CREATE SEQUENCE seqname
- *
- *****************************************************************************/
-
-CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
- {
- CreateSeqStmt *n = makeNode(CreateSeqStmt);
- n->seqname = $3;
- n->options = $4;
- $$ = (Node *)n;
- }
+key_action: ON DELETE key_reference { $$ = NIL; }
+ | ON UPDATE key_reference { $$ = NIL; }
;
-OptSeqList:
- OptSeqList OptSeqElem
- { $$ = lappend($1, $2); }
- | { $$ = NIL; }
+key_reference: NO ACTION { $$ = NULL; }
+ | CASCADE { $$ = NULL; }
+ | SET DEFAULT { $$ = NULL; }
+ | SET NULL_P { $$ = NULL; }
;
-OptSeqElem: IDENT NumConst
+OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+/*
+ * "ARCHIVE" keyword was removed in 6.3, but we keep it for now
+ * so people can upgrade with old pg_dump scripts. - momjian 1997-11-20(?)
+ */
+OptArchiveType: ARCHIVE '=' NONE { }
+ | /*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;
+ }
+ ;
+
+
+/*****************************************************************************
+ *
+ * QUERY :
+ * CREATE SEQUENCE seqname
+ *
+ *****************************************************************************/
+
+CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
+ {
+ CreateSeqStmt *n = makeNode(CreateSeqStmt);
+ n->seqname = $3;
+ n->options = $4;
+ $$ = (Node *)n;
+ }
+ ;
+
+OptSeqList: OptSeqList OptSeqElem
+ { $$ = lappend($1, $2); }
+ | { $$ = NIL; }
+ ;
+
+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;
+ }
+ ;
+
+/*****************************************************************************
+ *
+ * QUERIES :
+ * CREATE PROCEDURAL LANGUAGE ...
+ * DROP PROCEDURAL LANGUAGE ...
+ *
+ *****************************************************************************/
+
+CreatePLangStmt: CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst
+ HANDLER def_name LANCOMPILER Sconst
+ {
+ CreatePLangStmt *n = makeNode(CreatePLangStmt);
+ n->plname = $5;
+ n->plhandler = $7;
+ n->plcompiler = $9;
+ n->pltrusted = $2;
+ $$ = (Node *)n;
+ }
;
+PLangTrusted: TRUSTED { $$ = TRUE; }
+ | { $$ = FALSE; }
+
+DropPLangStmt: DROP PROCEDURAL LANGUAGE Sconst
+ {
+ DropPLangStmt *n = makeNode(DropPLangStmt);
+ n->plname = $4;
+ $$ = (Node *)n;
+ }
+ ;
/*****************************************************************************
*
*
*****************************************************************************/
-CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
+CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
relation_name TriggerForSpec EXECUTE PROCEDURE
name '(' TriggerFuncArgs ')'
{
}
;
-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;
}
;
-TriggerFuncArgs: TriggerFuncArg
+TriggerForOpt: EACH { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+TriggerForType: ROW { $$ = TRUE; }
+ | STATEMENT { $$ = FALSE; }
+ ;
+
+TriggerFuncArgs: TriggerFuncArg
{ $$ = lcons($1, NIL); }
- | TriggerFuncArgs ',' TriggerFuncArg
+ | TriggerFuncArgs ',' TriggerFuncArg
{ $$ = lappend($1, $3); }
- | /* EMPTY */ { $$ = NIL; }
+ | /*EMPTY*/
+ { $$ = NIL; }
;
-TriggerFuncArg: ICONST
+TriggerFuncArg: ICONST
+ {
+ char *s = (char *) palloc (256);
+ sprintf (s, "%d", $1);
+ $$ = s;
+ }
+ | FCONST
{
- char *s = (char *) palloc (256);
- sprintf (s, "%d", $1);
- $$ = s;
+ char *s = (char *) palloc (256);
+ sprintf (s, "%g", $1);
+ $$ = s;
}
- | Sconst { $$ = $1; }
+ | 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;
}
;
+
/*****************************************************************************
*
* QUERY :
{
$$ = makeNode(DefineStmt);
$$->defname = $1;
-#ifdef PARSEDEBUG
-printf("def_rest: defname is %s\n", $1);
-#endif
$$->definition = $2;
}
;
def_type: OPERATOR { $$ = OPERATOR; }
- | Type
- {
-#ifdef PARSEDEBUG
-printf("def_type: decoding P_TYPE\n");
-#endif
- $$ = P_TYPE;
- }
- | AGGREGATE { $$ = AGGREGATE; }
+ | TYPE_P { $$ = TYPE_P; }
+ | AGGREGATE { $$ = AGGREGATE; }
;
def_name: PROCEDURE { $$ = "procedure"; }
- | Id { $$ = $1; }
- | MathOp { $$ = $1; }
- | Op { $$ = $1; }
+ | JOIN { $$ = "join"; }
+ | ColId { $$ = $1; }
+ | MathOp { $$ = $1; }
+ | Op { $$ = $1; }
;
definition: '(' def_list ')' { $$ = $2; }
;
def_list: def_elem { $$ = lcons($1, NIL); }
- | def_list ',' def_elem { $$ = lappend($1, $3); }
+ | def_list ',' def_elem { $$ = lappend($1, $3); }
;
def_elem: def_name '=' def_arg
{
-#ifdef PARSEDEBUG
-printf("def_elem: decoding %s =\n", $1);
-pprint($3);
-#endif
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)$3;
}
- | def_name
+ | def_name
{
-#ifdef PARSEDEBUG
-printf("def_elem: decoding %s\n", $1);
-#endif
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)NULL;
}
- | DEFAULT '=' def_arg
+ | DEFAULT '=' def_arg
{
-#ifdef PARSEDEBUG
-printf("def_elem: decoding DEFAULT =\n");
-pprint($3);
-#endif
$$ = makeNode(DefElem);
$$->defname = "default";
$$->arg = (Node *)$3;
}
;
-def_arg: Id { $$ = (Node *)makeString($1); }
- | all_Op { $$ = (Node *)makeString($1); }
- | NumConst { $$ = (Node *)$1; /* already a Value */ }
- | Sconst { $$ = (Node *)makeString($1); }
- | SETOF Id
+def_arg: ColId { $$ = (Node *)makeString($1); }
+ | all_Op { $$ = (Node *)makeString($1); }
+ | NumericOnly { $$ = (Node *)$1; }
+ | Sconst { $$ = (Node *)makeString($1); }
+ | SETOF ColId
{
TypeName *n = makeNode(TypeName);
n->name = $2;
n->setof = TRUE;
n->arrayBounds = NULL;
+ n->typmod = -1;
$$ = (Node *)n;
}
- | DOUBLE { $$ = (Node *)makeString("double"); }
;
*
*****************************************************************************/
-DestroyStmt: DROP TABLE relation_name_list
+DestroyStmt: DROP TABLE relation_name_list
{
DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3;
n->sequence = FALSE;
$$ = (Node *)n;
}
- | DROP SEQUENCE relation_name_list
+ | DROP SEQUENCE relation_name_list
{
DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3;
/*****************************************************************************
*
* QUERY:
- * fetch [forward | backward] [number | all ] [ in <portalname> ]
+ * fetch/move [forward | backward] [number | all ] [ in <portalname> ]
*
*****************************************************************************/
n->direction = $2;
n->howMany = $3;
n->portalname = $4;
+ n->ismove = false;
+ $$ = (Node *)n;
+ }
+ | MOVE opt_direction fetch_how_many opt_portal_name
+ {
+ FetchStmt *n = makeNode(FetchStmt);
+ n->direction = $2;
+ n->howMany = $3;
+ n->portalname = $4;
+ n->ismove = TRUE;
$$ = (Node *)n;
}
;
fetch_how_many: Iconst
{ $$ = $1;
- if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
- | ALL { $$ = 0; /* 0 means fetch all tuples*/}
- | /*EMPTY*/ { $$ = 1; /*default*/ }
+ 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; }
+ | /*EMPTY*/ { $$ = NULL; }
;
+
/*****************************************************************************
*
* QUERY:
*
*****************************************************************************/
-GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
+GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
{
$$ = (Node*)makeAclStmt($2,$4,$6,'+');
- free($2);
- free($6);
}
;
}
;
-operation_commalist: operation
+operation_commalist: operation
{
$$ = aclmakepriv("",$1);
}
| operation_commalist ',' operation
{
$$ = aclmakepriv($1,$3);
- free($1);
}
;
-operation: SELECT
+operation: SELECT
{
$$ = ACL_MODE_RD_CHR;
}
{
$$ = ACL_MODE_WR_CHR;
}
- | RULE
+ | RULE
{
$$ = ACL_MODE_RU_CHR;
}
{
$$ = aclmakeuser("A","");
}
- | GROUP Id
+ | GROUP ColId
{
$$ = aclmakeuser("G",$2);
}
- | Id
+ | ColId
{
$$ = aclmakeuser("U",$1);
}
;
-opt_with_grant : /* empty */
- | WITH GRANT OPTION
+opt_with_grant: WITH GRANT OPTION
{
yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
- }
+ }
+ | /*EMPTY*/
;
+
/*****************************************************************************
*
* QUERY:
*
*****************************************************************************/
-RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
+RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
{
$$ = (Node*)makeAclStmt($2,$4,$6,'-');
- free($2);
- free($6);
- }
- ;
-
-/*****************************************************************************
- *
- * QUERY:
- * move [<dirn>] [<whereto>] [<portalname>]
- *
- *****************************************************************************/
-
-MoveStmt: MOVE opt_direction opt_move_where opt_portal_name
- {
- MoveStmt *n = makeNode(MoveStmt);
- n->direction = $2;
- n->to = FALSE;
- n->where = $3;
- n->portalname = $4;
- $$ = (Node *)n;
- }
- | MOVE opt_direction TO Iconst opt_portal_name
- {
- MoveStmt *n = makeNode(MoveStmt);
- n->direction = $2;
- n->to = TRUE;
- n->where = $4;
- n->portalname = $5;
- $$ = (Node *)n;
}
;
-opt_move_where: Iconst { $$ = $1; }
- | /*EMPTY*/ { $$ = 1; /* default */ }
- ;
-
-opt_portal_name: IN name { $$ = $2;}
- | /*EMPTY*/ { $$ = NULL; }
- ;
-
/*****************************************************************************
*
* QUERY:
- * define [archive] index <indexname> on <relname>
+ * create index <indexname> on <relname>
* using <access> "(" (<col> with <op>)+ ")" [with
* <target_list>]
*
}
;
-access_method_clause: USING access_method { $$ = $2; }
- | /* empty -- 'btree' is default access method */
- { $$ = "btree"; }
+index_opt_unique: UNIQUE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+access_method_clause: USING access_method { $$ = $2; }
+ | /*EMPTY*/ { $$ = "btree"; }
+ ;
+
+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: func_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; }
;
-index_opt_unique: UNIQUE { $$ = TRUE; }
- | /*empty*/ { $$ = FALSE; }
+/* 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:
{
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; }
- | '(' ')' { $$ = NIL; }
+func_args: '(' func_args_list ')' { $$ = $2; }
+ | '(' ')' { $$ = NIL; }
;
-def_name_list: name_list;
-
-
-/*****************************************************************************
- *
- * QUERY:
- * purge <relname> [before <date>] [after <date>]
- * or
- * purge <relname> [after <date>] [before <date>]
- *
- *****************************************************************************/
-
-PurgeStmt: PURGE relation_name purge_quals
- {
- $3->relname = $2;
- $$ = (Node *)$3;
- }
+func_args_list: TypeId
+ { $$ = lcons(makeString($1),NIL); }
+ | func_args_list ',' TypeId
+ { $$ = lappend($1,makeString($3)); }
;
-purge_quals: before_clause
- {
- $$ = makeNode(PurgeStmt);
- $$->beforeDate = $1;
- $$->afterDate = NULL;
- }
- | after_clause
- {
- $$ = makeNode(PurgeStmt);
- $$->beforeDate = NULL;
- $$->afterDate = $1;
- }
- | before_clause after_clause
+func_return: set_opt TypeId
{
- $$ = makeNode(PurgeStmt);
- $$->beforeDate = $1;
- $$->afterDate = $2;
- }
- | after_clause before_clause
- {
- $$ = makeNode(PurgeStmt);
- $$->beforeDate = $2;
- $$->afterDate = $1;
- }
- | /*EMPTY*/
- {
- $$ = makeNode(PurgeStmt);
- $$->beforeDate = NULL;
- $$->afterDate = NULL;
+ TypeName *n = makeNode(TypeName);
+ n->name = $2;
+ n->setof = $1;
+ n->arrayBounds = NULL;
+ $$ = (Node *)n;
}
;
-before_clause: BEFORE date { $$ = $2; }
-after_clause: AFTER date { $$ = $2; }
-
+set_opt: SETOF { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
/*****************************************************************************
*
}
;
-remove_type: Type { $$ = P_TYPE; }
- | INDEX { $$ = INDEX; }
- | RULE { $$ = RULE; }
- | VIEW { $$ = VIEW; }
+remove_type: TYPE_P { $$ = TYPE_P; }
+ | INDEX { $$ = INDEX; }
+ | RULE { $$ = RULE; }
+ | VIEW { $$ = VIEW; }
;
+
RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
{
RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
;
aggr_argtype: name { $$ = $1; }
- | '*' { $$ = NULL; }
+ | '*' { $$ = 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 ')'
{
}
;
-all_Op: Op | MathOp;
+all_Op: Op | MathOp;
MathOp: '+' { $$ = "+"; }
- | '-' { $$ = "-"; }
- | '*' { $$ = "*"; }
- | '/' { $$ = "/"; }
- | '<' { $$ = "<"; }
- | '>' { $$ = ">"; }
- | '=' { $$ = "="; }
+ | '-' { $$ = "-"; }
+ | '*' { $$ = "*"; }
+ | '/' { $$ = "/"; }
+ | '<' { $$ = "<"; }
+ | '>' { $$ = ">"; }
+ | '=' { $$ = "="; }
;
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); }
{ $$ = makeList(makeString($1), NULL, -1); }
;
+
/*****************************************************************************
*
* QUERY:
;
opt_name: name { $$ = $1; }
- | /*EMPTY*/ { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; }
;
opt_column: COLUMN { $$ = COLUMN; }
OptStmtBlock: OptStmtMulti
{ $$ = $1; }
- | OptimizableStmt
+ | OptimizableStmt
{ $$ = lcons($1, NIL); }
;
OptStmtMulti: OptStmtMulti OptimizableStmt ';'
{ $$ = lappend($1, $2); }
- | OptStmtMulti OptimizableStmt
+ | OptStmtMulti OptimizableStmt
{ $$ = lappend($1, $2); }
- | OptimizableStmt ';'
+ | OptimizableStmt ';'
{ $$ = lcons($1, NIL); }
;
-event_object: relation_name '.' attr_name
+event_object: relation_name '.' attr_name
{
$$ = makeNode(Attr);
$$->relname = $1;
;
opt_instead: INSTEAD { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
*
*****************************************************************************/
-NotifyStmt: NOTIFY relation_name
+NotifyStmt: NOTIFY relation_name
{
NotifyStmt *n = makeNode(NotifyStmt);
n->relname = $2;
}
;
-ListenStmt: LISTEN relation_name
+ListenStmt: LISTEN relation_name
{
ListenStmt *n = makeNode(ListenStmt);
n->relname = $2;
*
*****************************************************************************/
-TransactionStmt: ABORT_TRANS TRANSACTION
+TransactionStmt: ABORT_TRANS opt_trans
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = ABORT_TRANS;
$$ = (Node *)n;
}
- | BEGIN_TRANS TRANSACTION
- {
- TransactionStmt *n = makeNode(TransactionStmt);
- n->command = BEGIN_TRANS;
- $$ = (Node *)n;
- }
- | BEGIN_TRANS WORK
+ | BEGIN_TRANS opt_trans
{
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;
}
;
*
*****************************************************************************/
-LoadStmt: LOAD file_name
+LoadStmt: LOAD file_name
{
LoadStmt *n = makeNode(LoadStmt);
n->filename = $2;
*
*****************************************************************************/
-CreatedbStmt: CREATE DATABASE database_name
+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 = NULL;
+#ifdef MULTIBYTE
+ n->encoding = GetTemplateEncoding();
+#endif
+ $$ = (Node *)n;
+ }
+ ;
+
+opt_database1: LOCATION '=' location { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+opt_database2: ENCODING '=' encoding { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+location: Sconst { $$ = $1; }
+ | DEFAULT { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+encoding: Sconst { $$ = $1; }
+ | DEFAULT { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
/*****************************************************************************
*
* QUERY:
}
;
+
/*****************************************************************************
*
* QUERY:
n->va_spec = NIL;
$$ = (Node *)n;
}
- | VACUUM opt_verbose relation_name opt_analyze opt_va_list
+ | VACUUM opt_verbose opt_analyze relation_name opt_va_list
{
VacuumStmt *n = makeNode(VacuumStmt);
n->verbose = $2;
- n->analyze = $4;
- n->vacrel = $3;
+ n->analyze = $3;
+ 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; }
+opt_verbose: VERBOSE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
-opt_analyze: ANALYZE { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+opt_analyze: ANALYZE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
-opt_va_list: '(' va_list ')'
- { $$ = $2; }
- | /* EMPTY */
- { $$ = NIL; }
+opt_va_list: '(' va_list ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
;
-va_list: name
+va_list: name
{ $$=lcons($1,NIL); }
| va_list ',' name
{ $$=lappend($1,$3); }
;
+
/*****************************************************************************
*
* QUERY:
}
;
+
/*****************************************************************************
* *
* Optimizable Stmts: *
* *
*****************************************************************************/
-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 ')'
+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;
}
;
-opt_column_list: '(' columnList ')' { $$ = $2; }
+opt_column_list: '(' columnList ')' { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
{ $$ = lcons($1, NIL); }
;
-columnElem: Id opt_indirection
+columnElem: ColId opt_indirection
{
Ident *id = makeNode(Ident);
id->name = $1;
}
;
+
/*****************************************************************************
*
* QUERY:
}
;
+/*
+ * 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
- result from_clause where_clause
- group_clause having_clause
- sort_clause
+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->sortClause = $9;
+ n->unionClause = $9;
+ n->sortClause = $10;
$$ = (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
+SubSelect: SELECT opt_unique res_target_list2
+ from_clause where_clause
+ group_clause having_clause
+ union_clause
{
- Select *n = makeNode(Select);
+ SelectStmt *n = makeNode(SelectStmt);
n->unique = $2;
n->targetList = $3;
- n->into = $4;
- n->fromClause = $5;
- n->whereClause = $6;
- n->groupClause = $7;
- n->havingClause = $8;
+ n->fromClause = $4;
+ n->whereClause = $5;
+ n->groupClause = $6;
+ n->havingClause = $7;
+ n->unionClause = $8;
$$ = (Node *)n;
}
;
-******************************************************************************/
-RetrieveStmt: SELECT opt_unique res_target_list2
- result from_clause where_clause
- group_clause having_clause
- union_clause sort_clause
+union_clause: UNION opt_union select_list
{
- RetrieveStmt *n = makeNode(RetrieveStmt);
- n->unique = $2;
- n->targetList = $3;
- n->into = $4;
- n->fromClause = $5;
- n->whereClause = $6;
- n->groupClause = $7;
- n->havingClause = $8;
- n->selectClause = $9;
- n->sortClause = $10;
- $$ = (Node *)n;
+ SelectStmt *n = (SelectStmt *)lfirst($3);
+ n->unionall = $2;
+ $$ = $3;
}
+ | /*EMPTY*/
+ { $$ = NIL; }
;
-union_clause: UNION select_list { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
-
-select_list: select_list UNION SubSelect
- { $$ = lappend($1, $3); }
- | 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
- result from_clause where_clause
- group_clause having_clause
+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 = $5;
- n->whereClause = $6;
- n->groupClause = $7;
- n->havingClause = $8;
+ n->fromClause = $4;
+ n->whereClause = $5;
+ n->groupClause = $6;
+ n->havingClause = $7;
$$ = (Node *)n;
}
;
-result: INTO TABLE relation_name
- { $$= $3; /* should check for archive level */ }
- | /*EMPTY*/
- { $$ = NULL; }
+result: INTO opt_table relation_name { $$= $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+opt_table: TABLE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+opt_union: ALL { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
-opt_unique: DISTINCT { $$ = "*"; }
- | DISTINCT ON Id { $$ = $3; }
- | /*EMPTY*/ { $$ = NULL;}
+opt_unique: DISTINCT { $$ = "*"; }
+ | DISTINCT ON ColId { $$ = $3; }
+ | ALL { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; }
;
sort_clause: ORDER BY sortby_list { $$ = $3; }
- | /*EMPTY*/ { $$ = NIL; }
+ | /*EMPTY*/ { $$ = NIL; }
;
-sortby_list: sortby
- { $$ = lcons($1, NIL); }
- | sortby_list ',' sortby
- { $$ = lappend($1, $3); }
+sortby_list: sortby { $$ = lcons($1, NIL); }
+ | sortby_list ',' sortby { $$ = lappend($1, $3); }
;
-sortby: Id OptUseOp
+sortby: ColId OptUseOp
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
$$->name = $1;
$$->useOp = $2;
}
- | Id '.' Id OptUseOp
+ | ColId '.' ColId OptUseOp
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
;
OptUseOp: USING Op { $$ = $2; }
- | USING '<' { $$ = "<"; }
- | USING '>' { $$ = ">"; }
- | ASC { $$ = "<"; }
- | DESC { $$ = ">"; }
- | /*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; }
+ | USING '<' { $$ = "<"; }
+ | USING '>' { $$ = ">"; }
+ | ASC { $$ = "<"; }
+ | DESC { $$ = ">"; }
+ | /*EMPTY*/ { $$ = "<"; /*default*/ }
;
/*
*
* ...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; }
+opt_inh_star: '*' { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
;
-relation_name_list: name_list ;
+relation_name_list: name_list;
-name_list: name
- { $$=lcons(makeString($1),NIL); }
+name_list: name
+ { $$ = lcons(makeString($1),NIL); }
| name_list ',' name
- { $$=lappend($1,makeString($3)); }
+ { $$ = lappend($1,makeString($3)); }
;
-group_clause: GROUP BY groupby_list { $$ = $3; }
+group_clause: GROUP BY groupby_list { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
;
-groupby_list: groupby { $$ = lcons($1, NIL); }
+groupby_list: groupby { $$ = lcons($1, NIL); }
| groupby_list ',' groupby { $$ = lappend($1, $3); }
;
-groupby: Id
+groupby: ColId
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
$$->name = $1;
$$->useOp = NULL;
}
- | Id '.' Id
+ | ColId '.' ColId
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
}
;
-having_clause: HAVING a_expr { $$ = $2; }
+having_clause: HAVING a_expr
+ {
+ $$ = $2;
+ }
| /*EMPTY*/ { $$ = NULL; }
;
+
/*****************************************************************************
*
* clauses common to all Optimizable Stmts:
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); }
- | from_val
+ | from_val CROSS JOIN from_val
+ { elog(ERROR,"CROSS JOIN not yet implemented"); }
+ | from_val
{ $$ = lcons($1, NIL); }
;
-from_val: relation_expr AS var_name
+from_val: relation_expr AS ColLabel
{
$$ = makeNode(RangeVar);
$$->relExpr = $1;
$$->name = $3;
}
- | relation_expr var_name
+ | relation_expr ColId
{
$$ = makeNode(RangeVar);
$$->relExpr = $1;
}
;
-join_expr: NATURAL join_expr { $$ = NULL; }
+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); }
- | OUTERJOIN
- { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
- | INNERJOIN
- { elog(WARN,"INNER JOIN not yet implemented",NULL); }
+ { elog(ERROR,"RIGHT OUTER JOIN not yet implemented"); }
+ | OUTER_P
+ { elog(ERROR,"OUTER JOIN not yet implemented"); }
+ | INNER_P
+ { 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: OUTERJOIN { $$ = NULL; }
- | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
+join_outer: OUTER_P { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
;
-join_spec: ON '(' a_expr ')' { $$ = NULL; }
- | USING '(' join_list ')' { $$ = NULL; }
- | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
+join_spec: ON '(' a_expr ')' { $$ = NULL; }
+ | USING '(' join_list ')' { $$ = NULL; }
+ | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
;
-join_list: join_using { $$ = lcons($1, NIL); }
+join_list: join_using { $$ = lcons($1, NIL); }
| join_list ',' join_using { $$ = lappend($1, $3); }
;
-join_using: Id
+join_using: ColId
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
$$->name = $1;
$$->useOp = NULL;
}
- | Id '.' Id
+ | ColId '.' ColId
{
$$ = makeNode(SortGroupBy);
$$->resno = 0;
}
;
-where_clause: WHERE a_expr { $$ = $2; }
- | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
+where_clause: WHERE a_expr { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
;
relation_expr: relation_name
$$ = makeNode(RelExpr);
$$->relname = $1;
$$->inh = FALSE;
- $$->timeRange = NULL;
}
| relation_name '*' %prec '='
{
- /* inheiritance query */
+ /* inheritance query */
$$ = makeNode(RelExpr);
$$->relname = $1;
$$->inh = TRUE;
- $$->timeRange = NULL;
- }
- | relation_name time_range
- {
- /* time-qualified query */
- $$ = makeNode(RelExpr);
- $$->relname = $1;
- $$->inh = FALSE;
- $$->timeRange = $2;
- }
- ;
-
-
-time_range: '[' opt_range_start ',' opt_range_end ']'
- {
- $$ = makeNode(TimeRange);
- $$->startDate = $2;
- $$->endDate = $4;
- }
- | '[' date ']'
- {
- $$ = makeNode(TimeRange);
- $$->startDate = $2;
- $$->endDate = NULL;
}
- ;
-
-opt_range_start: date
- | /*EMPTY*/ { $$ = "epoch"; }
- ;
-
-opt_range_end: date
- | /*EMPTY*/ { $$ = "now"; }
- ;
opt_array_bounds: '[' ']' nest_array_bounds
{ $$ = lcons(makeInteger(-1), $3); }
{ $$ = NIL; }
;
-typname: txname
+
+/*****************************************************************************
+ *
+ * Type syntax
+ * SQL92 introduces a large amount of type-specific syntax.
+ * Define individual clauses to handle these cases, and use
+ * the generic case to handle regular type-extensible Postgres syntax.
+ * - thomas 1997-10-10
+ *
+ *****************************************************************************/
+
+Typename: Array opt_array_bounds
{
- char *tname = xlateSqlType($1);
- $$ = makeNode(TypeName);
- $$->name = tname;
+ $$ = $1;
+ $$->arrayBounds = $2;
/* Is this the name of a complex type? If so, implement
* it as a set.
*/
- if (!strcmp(saved_relname, tname))
+ if (!strcmp(saved_relname, $$->name))
/* This attr is the same type as the relation
* being defined. The classic example: create
* emp(name=text,mgr=emp)
*/
$$->setof = TRUE;
- else if (get_typrelid((Type)type(tname)) != InvalidOid)
+ else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
/* (Eventually add in here that the set can only
* contain one element.)
*/
else
$$->setof = FALSE;
}
- | SETOF txname
+ | Character
+ | SETOF Array
{
- char *tname = xlateSqlType($2);
- $$ = makeNode(TypeName);
- $$->name = tname;
+ $$ = $2;
$$->setof = TRUE;
}
;
-txname: Id { $$ = $1; }
- | TIME { $$ = xlateSqlType("time"); }
- | INTERVAL interval_opts { $$ = xlateSqlType("interval"); }
- | CHARACTER char_type { $$ = $2; }
- | DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
+Array: Generic
+ | Datetime
+ | Numeric
;
-char_type: VARYING { $$ = xlateSqlType("varchar"); }
- | /*EMPTY*/ { $$ = xlateSqlType("char"); }
+Generic: generic
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType($1);
+ $$->typmod = -1;
+ }
;
-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; }
+generic: IDENT { $$ = $1; }
+ | TYPE_P { $$ = xlateSqlType("type"); }
;
-Typename: typname opt_array_bounds
+/* SQL92 numeric data types
+ * Check FLOAT() 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
+ */
+Numeric: FLOAT opt_float
{
- $$ = $1;
- $$->arrayBounds = $2;
- if (!strcasecmp($1->name, "varchar"))
- {
- $$->typlen = 4 + 1;
- }
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType($2);
+ $$->typmod = -1;
}
- | txname '(' Iconst ')'
+ | DOUBLE PRECISION
{
- /*
- * This block gets hit when the parser is passed a query
- * which contains only spaces (e.g. from psql type " \g").
- * Let's check explicitly for a zero-length argument
- * here, and do nothing if so. This seems to fix the problem.
- * - thomas 1997-07-13
- */
- if (strlen($1) > 0)
- {
+ $$ = 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;
+ }
+ ;
- /*
- * The following implements char() and varchar().
- * We do it here instead of the 'typname:' 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
- */
- $$ = makeNode(TypeName);
- if (!strcasecmp($1, "char"))
- $$->name = "bpchar"; /* strdup("bpchar"); */
- else if (!strcasecmp($1, "varchar"))
- $$->name = "varchar"; /* strdup("varchar"); */
- else
- yyerror("parse error");
- if ($3 < 1)
- elog(WARN,"length for '%s' type must be at least 1",$1);
- else if ($3 > 4096)
- /* we can store a char() of length up to the size
- * of a page (8KB) - page headers and friends but
- * just to be safe here... - ay 6/95
- * XXX note this hardcoded limit - thomas 1997-07-13
- */
- elog(WARN,"length for '%s' type cannot exceed 4096",$1);
-
- /* 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
+numeric: FLOAT
+ { $$ = xlateSqlType("float8"); }
+ | DOUBLE PRECISION
+ { $$ = xlateSqlType("float8"); }
+ | DECIMAL
+ { $$ = xlateSqlType("decimal"); }
+ | NUMERIC
+ { $$ = xlateSqlType("numeric"); }
+ ;
+
+opt_float: '(' Iconst ')'
+ {
+ if ($2 < 1)
+ elog(ERROR,"precision for FLOAT must be at least 1");
+ else if ($2 < 7)
+ $$ = xlateSqlType("float4");
+ else if ($2 < 16)
+ $$ = xlateSqlType("float8");
+ else
+ elog(ERROR,"precision for FLOAT must be less than 16");
+ }
+ | /*EMPTY*/
+ {
+ $$ = xlateSqlType("float8");
+ }
+ ;
+
+opt_numeric: '(' Iconst ',' Iconst ')'
+ {
+ if ($2 != 9)
+ elog(ERROR,"NUMERIC precision %d must be 9",$2);
+ if ($4 != 0)
+ elog(ERROR,"NUMERIC scale %d must be zero",$4);
+ }
+ | '(' Iconst ')'
+ {
+ if ($2 != 9)
+ elog(ERROR,"NUMERIC precision %d must be 9",$2);
+ }
+ | /*EMPTY*/
+ {
+ $$ = NULL;
+ }
+ ;
+
+opt_decimal: '(' Iconst ',' Iconst ')'
+ {
+ if ($2 > 9)
+ elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
+ if ($4 != 0)
+ elog(ERROR,"DECIMAL scale %d must be zero",$4);
+ $$ = NULL;
+ }
+ | '(' Iconst ')'
+ {
+ if ($2 > 9)
+ elog(ERROR,"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") == 0)
+ $$->name = xlateSqlType("bpchar");
+ else if (strcasecmp($1, "varchar") == 0)
+ $$->name = xlateSqlType("varchar");
+ else
+ yyerror("internal parsing error; unrecognized character type");
+
+ if ($3 < 1)
+ elog(ERROR,"length for '%s' type must be at least 1",$1);
+ else if ($3 > 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
*/
- $$->typlen = 4 + $3;
+ 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
+ */
+ $$->typmod = VARHDRSZ + $3;
+ }
+ | character
+ {
+ $$ = makeNode(TypeName);
+ /* Let's try to make all single-character types into bpchar(1)
+ * - thomas 1998-05-07
+ */
+ if (strcasecmp($1, "char") == 0)
+ {
+ $$->name = xlateSqlType("bpchar");
+ $$->typmod = VARHDRSZ + 1;
}
+ else
+ {
+ $$->name = xlateSqlType($1);
+ $$->typmod = -1;
+ }
+ }
+ ;
+
+character: CHARACTER opt_varying opt_charset opt_collate
+ {
+ char *type, *c;
+ if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
+ if ($2) type = xlateSqlType("varchar");
+ else type = xlateSqlType("char");
+ } else {
+ if ($2) {
+ c = palloc(strlen("var") + strlen($3) + 1);
+ strcpy(c, "var");
+ strcat(c, $3);
+ type = xlateSqlType(c);
+ } else {
+ type = xlateSqlType($3);
+ }
+ };
+ if ($4 != NULL)
+ elog(NOTICE,"COLLATE %s not yet implemented; clause ignored",$4);
+ $$ = type;
+ }
+ | CHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
+ | VARCHAR { $$ = xlateSqlType("varchar"); }
+ | NATIONAL CHARACTER opt_varying { $$ = xlateSqlType($3? "varchar": "char"); }
+ | NCHAR opt_varying { $$ = xlateSqlType($2? "varchar": "char"); }
+ ;
+
+opt_varying: VARYING { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+opt_charset: CHARACTER SET ColId { $$ = $3; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+opt_collate: COLLATE ColId { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+Datetime: datetime
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType($1);
+ $$->typmod = -1;
+ }
+ | TIMESTAMP opt_timezone
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType("timestamp");
+ $$->timezone = $2;
+ $$->typmod = -1;
+ }
+ | TIME
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType("time");
+ $$->typmod = -1;
+ }
+ | INTERVAL opt_interval
+ {
+ $$ = makeNode(TypeName);
+ $$->name = xlateSqlType("interval");
+ $$->typmod = -1;
}
;
+datetime: YEAR_P { $$ = "year"; }
+ | MONTH_P { $$ = "month"; }
+ | DAY_P { $$ = "day"; }
+ | HOUR_P { $$ = "hour"; }
+ | MINUTE_P { $$ = "minute"; }
+ | SECOND_P { $$ = "second"; }
+ ;
+
+opt_timezone: WITH TIME ZONE { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+opt_interval: datetime { $$ = lcons($1, NIL); }
+ | YEAR_P TO MONTH_P { $$ = NIL; }
+ | DAY_P TO HOUR_P { $$ = NIL; }
+ | DAY_P TO MINUTE_P { $$ = NIL; }
+ | DAY_P TO SECOND_P { $$ = NIL; }
+ | HOUR_P TO MINUTE_P { $$ = NIL; }
+ | HOUR_P TO SECOND_P { $$ = NIL; }
+ | MINUTE_P TO SECOND_P { $$ = NIL; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
/*****************************************************************************
*
*
*****************************************************************************/
-a_expr_or_null: a_expr
- { $$ = $1;}
- | Pnull
+a_expr_or_null: a_expr
+ { $$ = $1; }
+ | NULL_P
{
A_Const *n = makeNode(A_Const);
n->val.type = T_Null;
$$ = (Node *)n;
}
+ ;
-a_expr: attr opt_indirection
+/* 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 ')'
{
- $1->indirection = $2;
- $$ = (Node *)$1;
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = $2;
+ n->oper = lcons("<>",NIL);
+ n->useor = true;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $7;
+ $$ = (Node *)n;
}
- | AexprConst
- { $$ = $1; }
- | '-' a_expr %prec UMINUS
+ | '(' 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 ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("/",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '*' ALL '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("*",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '<' ALL '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("<",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '>' ALL '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons(">",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr '=' ALL '(' SubSelect ')'
+ {
+ SubLink *n = makeNode(SubLink);
+ n->lefthand = lcons($1, NULL);
+ n->oper = lcons("=",NIL);
+ n->useor = false;
+ n->subLinkType = ALL_SUBLINK;
+ n->subselect = $5;
+ $$ = (Node *)n;
+ }
+ | a_expr AND a_expr
+ { $$ = makeA_Expr(AND, NULL, $1, $3); }
+ | a_expr OR a_expr
+ { $$ = makeA_Expr(OR, NULL, $1, $3); }
+ | NOT a_expr
+ { $$ = makeA_Expr(NOT, NULL, NULL, $2); }
+ ;
+
+/*
+ * b_expr is a subset of the complete expression syntax
+ * defined by a_expr. b_expr is used in BETWEEN clauses
+ * to eliminate parser ambiguities stemming from the AND keyword.
+ */
+
+b_expr: attr opt_indirection
+ {
+ $1->indirection = $2;
+ $$ = (Node *)$1;
+ }
+ | AexprConst
+ { $$ = $1; }
+ | ColId
+ {
+ /* could be a column name or a relation_name */
+ Ident *n = makeNode(Ident);
+ n->name = $1;
+ n->indirection = NULL;
+ $$ = (Node *)n;
+ }
+ | '-' b_expr %prec UMINUS
{ $$ = 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); }
- | AexprConst TYPECAST Typename
+ | b_expr TYPECAST Typename
{
+ $$ = (Node *)$1;
/* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($1) == T_A_Const)
+ if (nodeTag($1) == T_A_Const) {
((A_Const *)$1)->typename = $3;
- else
+ } else if (nodeTag($1) == T_Param) {
((ParamNo *)$1)->typename = $3;
- $$ = (Node *)$1;
+ /* 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 AexprConst AS Typename
+ | CAST '(' b_expr AS Typename ')'
{
+ $$ = (Node *)$3;
/* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($2) == T_A_Const)
- ((A_Const *)$2)->typename = $4;
- else
- ((ParamNo *)$2)->typename = $4;
- $$ = (Node *)$2;
+ if (nodeTag($3) == T_A_Const) {
+ ((A_Const *)$3)->typename = $5;
+ } else if (nodeTag($3) == T_Param) {
+ ((ParamNo *)$3)->typename = $5;
+ /* otherwise, try to transform to a function call */
+ } else {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $5->name;
+ n->args = lcons($3,NIL);
+ $$ = (Node *)n;
+ }
}
- | '(' a_expr_or_null ')'
+ | '(' a_expr ')'
{ $$ = $2; }
- | a_expr Op a_expr
- { $$ = makeA_Expr(OP, $2, $1, $3); }
- | a_expr LIKE a_expr
- { $$ = makeA_Expr(OP, "~~", $1, $3); }
- | a_expr NOT LIKE a_expr
- { $$ = makeA_Expr(OP, "!~~", $1, $4); }
- | Op a_expr
+ | b_expr Op b_expr
+ { $$ = makeIndexable($2,$1,$3); }
+ | Op b_expr
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
- | a_expr Op
+ | b_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
- | Id
+ | func_name '(' ')'
{
- /* could be a column name or a relation_name */
- Ident *n = makeNode(Ident);
- n->name = $1;
- n->indirection = NULL;
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $1;
+ n->args = NIL;
$$ = (Node *)n;
}
- | name '(' '*' ')'
+ | func_name '(' expr_list ')'
{
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 = $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;
}
- | name '(' ')'
+ | CURRENT_TIME '(' Iconst ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = $1;
- n->args = NIL;
+ 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;
}
- /* 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 ')'
+ | CURRENT_TIMESTAMP
{
- elog(WARN,"EXISTS not yet supported",NULL);
- $$ = $3;
+ 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;
}
- | EXTRACT '(' extract_list ')'
+ | CURRENT_TIMESTAMP '(' Iconst ')'
{
FuncCall *n = makeNode(FuncCall);
- n->funcname = "date_part";
- n->args = $3;
+ A_Const *s = makeNode(A_Const);
+ TypeName *t = makeNode(TypeName);
+
+ n->funcname = xlateSqlType("timestamp");
+ n->args = lcons(s, NIL);
+
+ s->val.type = T_String;
+ s->val.val.str = "now";
+ s->typename = t;
+
+ t->name = xlateSqlType("timestamp");
+ t->setof = FALSE;
+ t->typmod = -1;
+
+ if ($3 != 0)
+ elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
+
+ $$ = (Node *)n;
+ }
+ | CURRENT_USER
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "getpgusername";
+ n->args = NIL;
+ $$ = (Node *)n;
+ }
+ | USER
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = "getpgusername";
+ n->args = NIL;
$$ = (Node *)n;
}
| POSITION '(' position_list ')'
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 PNULL
- { $$ = makeA_Expr(ISNULL, NULL, $1, NULL); }
- | a_expr NOTNULL
- { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
- | a_expr IS NOT PNULL
- { $$ = makeA_Expr(NOTNULL, NULL, $1, NULL); }
- | 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_nodes ')'
- { $$ = $5; }
- | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr_nodes ')'
- { $$ = $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
{ $$ = NIL; }
;
-expr_list: a_expr_or_null
+expr_list: a_expr_or_null
{ $$ = lcons($1, NIL); }
- | expr_list ',' a_expr_or_null
+ | expr_list ',' a_expr_or_null
{ $$ = lappend($1, $3); }
- | expr_list USING a_expr
+ | expr_list USING a_expr
{ $$ = 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;
n->val.val.str = $1;
-#ifdef PARSEDEBUG
-printf( "string is %s\n", $1);
-#endif
$$ = lappend(lcons((Node *)n,NIL), $3);
}
| /* EMPTY */
{ $$ = NIL; }
;
-position_list: position_expr IN position_expr
+extract_arg: datetime { $$ = $1; }
+ | TIMEZONE_HOUR { $$ = "tz_hour"; }
+ | TIMEZONE_MINUTE { $$ = "tz_minute"; }
+ ;
+
+position_list: position_expr IN position_expr
{ $$ = makeList($3, $1, -1); }
| /* EMPTY */
{ $$ = NIL; }
{ $$ = makeA_Expr(OP, "*", $1, $3); }
| '|' position_expr
{ $$ = makeA_Expr(OP, "|", NULL, $2); }
- | AexprConst TYPECAST Typename
+ | position_expr TYPECAST Typename
{
+ $$ = (Node *)$1;
/* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($1) == T_A_Const)
+ if (nodeTag($1) == T_A_Const) {
((A_Const *)$1)->typename = $3;
- else
+ } else if (nodeTag($1) == T_Param) {
((ParamNo *)$1)->typename = $3;
- $$ = (Node *)$1;
+ /* 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 AexprConst AS Typename
+ | CAST '(' position_expr AS Typename ')'
{
+ $$ = (Node *)$3;
/* AexprConst can be either A_Const or ParamNo */
- if (nodeTag($2) == T_A_Const)
- ((A_Const *)$2)->typename = $4;
- else
- ((ParamNo *)$2)->typename = $4;
- $$ = (Node *)$2;
+ if (nodeTag($3) == T_A_Const) {
+ ((A_Const *)$3)->typename = $5;
+ } else if (nodeTag($3) == T_Param) {
+ ((ParamNo *)$3)->typename = $5;
+ /* otherwise, try to transform to a function call */
+ } else {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = $5->name;
+ n->args = lcons($3,NIL);
+ $$ = (Node *)n;
+ }
}
| '(' position_expr ')'
{ $$ = $2; }
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
| position_expr Op
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
- | Id
+ | ColId
{
/* could be a column name or a relation_name */
Ident *n = makeNode(Ident);
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
+substr_list: expr_list substr_from substr_for
{
- $$ = $1;
- if ($2 != NULL) $$ = lappend($$, $2);
- if ($3 != NULL) $$ = lappend($$, $3);
+ $$ = nconc(nconc($1,$2),$3);
}
| /* EMPTY */
{ $$ = NIL; }
;
-substr_from: FROM expr_list
+substr_from: FROM expr_list
{ $$ = $2; }
| /* EMPTY */
- { $$ = NIL; }
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_Integer;
+ n->val.val.ival = 1;
+ $$ = lcons((Node *)n,NIL);
+ }
;
-substr_for: FOR expr_list
+substr_for: FOR expr_list
{ $$ = $2; }
| /* EMPTY */
{ $$ = NIL; }
;
-trim_list: a_expr FROM expr_list
+trim_list: a_expr FROM expr_list
{ $$ = lappend($3, $1); }
- | FROM expr_list
+ | FROM expr_list
{ $$ = $2; }
- | expr_list
+ | expr_list
{ $$ = $1; }
;
-in_expr_nodes: AexprConst
- { $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
- | in_expr_nodes ',' AexprConst
+in_expr: SubSelect
+ {
+ SubLink *n = makeNode(SubLink);
+ n->subselect = $1;
+ $$ = (Node *)n;
+ }
+ | in_expr_nodes
+ { $$ = $1; }
+ ;
+
+in_expr_nodes: AexprConst
+ { $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); }
+ | in_expr_nodes ',' AexprConst
{ $$ = makeA_Expr(OR, NULL, $1,
- makeA_Expr(OP, "=", saved_In_Expr, $3));
+ makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3));
+ }
+ ;
+
+not_in_expr: SubSelect
+ {
+ SubLink *n = makeNode(SubLink);
+ n->subselect = $1;
+ $$ = (Node *)n;
}
+ | not_in_expr_nodes
+ { $$ = $1; }
;
-not_in_expr_nodes: AexprConst
- { $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
- | not_in_expr_nodes ',' AexprConst
+not_in_expr_nodes: AexprConst
+ { $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); }
+ | not_in_expr_nodes ',' AexprConst
{ $$ = makeA_Expr(AND, NULL, $1,
- makeA_Expr(OP, "<>", saved_In_Expr, $3));
+ makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3));
}
;
{ $$ = lappend($1, makeString("*")); }
;
-DateTime: YEARINTERVAL { $$ = "year"; }
- | MONTHINTERVAL { $$ = "month"; }
- | DAYINTERVAL { $$ = "day"; }
- | HOURINTERVAL { $$ = "hour"; }
- | MINUTEINTERVAL { $$ = "minute"; }
- | SECONDINTERVAL { $$ = "second"; }
- ;
/*****************************************************************************
*
}
;
-res_target_el: Id opt_indirection '=' a_expr_or_null
+res_target_el: ColId opt_indirection '=' a_expr_or_null
{
$$ = makeNode(ResTarget);
$$->name = $1;
/*
** 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
+res_target_list2: res_target_list2 ',' res_target_el2
{ $$ = lappend($1, $3); }
| res_target_el2
{ $$ = lcons($1, NIL); }
;
/* AS is not optional because shift/red conflict with unary ops */
-res_target_el2: a_expr_or_null AS ColId
+res_target_el2: a_expr_or_null AS ColLabel
{
$$ = makeNode(ResTarget);
$$->name = $3;
}
;
-opt_id: Id { $$ = $1; }
+opt_id: ColId { $$ = $1; }
| /* EMPTY */ { $$ = NULL; }
;
relation_name: SpecialRuleRelation
{
$$ = $1;
- strNcpy(saved_relname, $1, NAMEDATALEN-1);
+ StrNCpy(saved_relname, $1, NAMEDATALEN);
}
| ColId
{
- /* disallow refs to magic system tables */
+ /* disallow refs to variable system tables */
if (strcmp(LogRelationName, $1) == 0
- || strcmp(VariableRelationName, $1) == 0
- || strcmp(TimeRelationName, $1) == 0
- || strcmp(MagicRelationName, $1) == 0)
- elog(WARN,"%s cannot be accessed by users",$1);
+ || strcmp(VariableRelationName, $1) == 0)
+ elog(ERROR,"%s cannot be accessed by users",$1);
else
$$ = $1;
- strNcpy(saved_relname, $1, NAMEDATALEN-1);
+ StrNCpy(saved_relname, $1, NAMEDATALEN);
}
;
-database_name: Id { $$ = $1; };
-access_method: Id { $$ = $1; };
+database_name: ColId { $$ = $1; };
+access_method: IDENT { $$ = $1; };
attr_name: ColId { $$ = $1; };
-class: Id { $$ = $1; };
-index_name: Id { $$ = $1; };
-var_name: Id { $$ = $1; };
-name: Id { $$ = $1; };
+class: IDENT { $$ = $1; };
+index_name: ColId { $$ = $1; };
+
+/* Functions
+ * Include date/time keywords as SQL92 extension.
+ * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
+ */
+name: ColId { $$ = $1; };
+func_name: ColId { $$ = xlateSqlFunc($1); };
-date: Sconst { $$ = $1; };
file_name: Sconst { $$ = $1; };
-recipe_name: Id { $$ = $1; };
+recipe_name: IDENT { $$ = $1; };
+/* Constants
+ * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
+ */
AexprConst: Iconst
{
A_Const *n = makeNode(A_Const);
n->val.val.str = $1;
$$ = (Node *)n;
}
+ | Typename Sconst
+ {
+ A_Const *n = makeNode(A_Const);
+ n->typename = $1;
+ n->val.type = T_String;
+ n->val.val.str = $2;
+ $$ = (Node *)n;
+ }
| ParamNo
{ $$ = (Node *)$1; }
+ | TRUE_P
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_String;
+ n->val.val.str = "t";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
+ $$ = (Node *)n;
+ }
+ | FALSE_P
+ {
+ A_Const *n = makeNode(A_Const);
+ n->val.type = T_String;
+ n->val.val.str = "f";
+ n->typename = makeNode(TypeName);
+ n->typename->name = xlateSqlType("bool");
+ n->typename->typmod = -1;
+ $$ = (Node *)n;
+ }
;
ParamNo: PARAM
}
;
-NumConst: Iconst { $$ = makeInteger($1); }
- | FCONST { $$ = makeFloat($1); }
- ;
-
Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; };
+UserId: IDENT { $$ = $1; };
-Id: IDENT { $$ = $1; };
-
-ColId: Id { $$ = $1; }
- | DateTime { $$ = $1; }
+/* Column and type identifier
+ * Does not include explicit datetime types
+ * since these must be decoupled in Typename syntax.
+ * Use ColId for most identifiers. - thomas 1997-10-21
+ */
+TypeId: ColId
+ { $$ = xlateSqlType($1); }
+ | numeric
+ { $$ = xlateSqlType($1); }
+ | character
+ { $$ = xlateSqlType($1); }
+ ;
+/* Column identifier
+ * Include date/time keywords as SQL92 extension.
+ * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
+ * Add other keywords. Note that as the syntax expands,
+ * some of these keywords will have to be removed from this
+ * list due to shift/reduce conflicts in yacc. If so, move
+ * down to the ColLabel entity. - thomas 1997-11-06
+ */
+ColId: IDENT { $$ = $1; }
+ | datetime { $$ = $1; }
+ | 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"; }
+ ;
+
+/* Column label
+ * Allowed labels in "AS" clauses.
+ * Include TRUE/FALSE SQL3 reserved words for Postgres backward
+ * compatibility. Cannot allow this for column names since the
+ * syntax would not distinguish between the constant value and
+ * a column name. - thomas 1997-10-24
+ * Add other keywords to this list. Note that they appear here
+ * rather than in ColId if there was a shift/reduce conflict
+ * when used as a full identifier. - thomas 1997-11-06
+ */
+ColLabel: ColId { $$ = $1; }
+ | ARCHIVE { $$ = "archive"; }
+ | CLUSTER { $$ = "cluster"; }
+ | CONSTRAINT { $$ = "constraint"; }
+ | CROSS { $$ = "cross"; }
+ | FOREIGN { $$ = "foreign"; }
+ | GROUP { $$ = "group"; }
+ | LOAD { $$ = "load"; }
+ | ORDER { $$ = "order"; }
+ | POSITION { $$ = "position"; }
+ | PRECISION { $$ = "precision"; }
+ | TABLE { $$ = "table"; }
+ | TRANSACTION { $$ = "transaction"; }
+ | TRUE_P { $$ = "true"; }
+ | FALSE_P { $$ = "false"; }
;
SpecialRuleRelation: CURRENT
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");
}
;
-Type: P_TYPE;
-Pnull: PNULL;
-
-
%%
-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)
+{
+ Node *result = NULL;
+
+ /* we do this so indexes can be used */
+ if (strcmp(opname,"~") == 0 ||
+ strcmp(opname,"~*") == 0)
+ {
+ if (nodeTag(rexpr) == T_A_Const &&
+ ((A_Const *)rexpr)->val.type == T_String &&
+ ((A_Const *)rexpr)->val.val.str[0] == '^')
+ {
+ A_Const *n = (A_Const *)rexpr;
+ char *match_least = palloc(strlen(n->val.val.str)+2);
+ char *match_most = palloc(strlen(n->val.val.str)+2);
+ int pos, match_pos=0;
+
+ /* skip leading ^ */
+ for (pos = 1; n->val.val.str[pos]; pos++)
+ {
+ if (n->val.val.str[pos] == '.' ||
+ n->val.val.str[pos] == '?' ||
+ n->val.val.str[pos] == '*' ||
+ n->val.val.str[pos] == '[' ||
+ n->val.val.str[pos] == '$' ||
+ (strcmp(opname,"~*") == 0 && isalpha(n->val.val.str[pos])))
+ break;
+ if (n->val.val.str[pos] == '\\')
+ pos++;
+ match_least[match_pos] = n->val.val.str[pos];
+ match_most[match_pos++] = n->val.val.str[pos];
+ }
+
+ if (match_pos != 0)
+ {
+ A_Const *least = makeNode(A_Const);
+ A_Const *most = makeNode(A_Const);
+
+ /* make strings to be used in index use */
+ match_least[match_pos] = '\0';
+ match_most[match_pos] = '\377';
+ match_most[match_pos+1] = '\0';
+ least->val.type = T_String;
+ least->val.val.str = match_least;
+ most->val.type = T_String;
+ most->val.val.str = match_most;
+ result = makeA_Expr(AND, NULL,
+ makeA_Expr(OP, "~", lexpr, rexpr),
+ makeA_Expr(AND, NULL,
+ makeA_Expr(OP, ">=", lexpr, (Node *)least),
+ makeA_Expr(OP, "<=", lexpr, (Node *)most)));
+ }
+ }
+ }
+ else if (strcmp(opname,"~~") == 0)
+ {
+ if (nodeTag(rexpr) == T_A_Const &&
+ ((A_Const *)rexpr)->val.type == T_String)
+ {
+ A_Const *n = (A_Const *)rexpr;
+ char *match_least = palloc(strlen(n->val.val.str)+2);
+ char *match_most = palloc(strlen(n->val.val.str)+2);
+ int pos, match_pos=0;
+
+ for (pos = 0; n->val.val.str[pos]; pos++)
+ {
+ 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];
+ }
+
+ if (match_pos != 0)
+ {
+ A_Const *least = makeNode(A_Const);
+ A_Const *most = makeNode(A_Const);
+
+ /* make strings to be used in index use */
+ match_least[match_pos] = '\0';
+ match_most[match_pos] = '\377';
+ match_most[match_pos+1] = '\0';
+ least->val.type = T_String;
+ least->val.val.str = match_least;
+ most->val.type = T_String;
+ most->val.val.str = match_most;
+ result = makeA_Expr(AND, NULL,
+ makeA_Expr(OP, "~~", lexpr, rexpr),
+ makeA_Expr(AND, NULL,
+ makeA_Expr(OP, ">=", lexpr, (Node *)least),
+ makeA_Expr(OP, "<=", lexpr, (Node *)most)));
+ }
+ }
+ }
+
+ if (result == NULL)
+ result = makeA_Expr(OP, opname, lexpr, rexpr);
+ return result;
+} /* makeIndexable() */
+
+
+/* xlateSqlFunc()
+ * Convert alternate type names to internal Postgres types.
+ * Do not convert "float", since that is handled elsewhere
+ * for FLOAT(p) syntax.
+ */
+static char *
+xlateSqlFunc(char *name)
+{
+ if (!strcasecmp(name,"character_length")
+ || !strcasecmp(name,"char_length"))
+ return "length";
+ else
+ return name;
+} /* xlateSqlFunc() */
+
/* xlateSqlType()
* Convert alternate type names to internal Postgres types.
*/
static char *
xlateSqlType(char *name)
{
- if (!strcasecmp(name,"int") ||
- !strcasecmp(name,"integer"))
- return "int4"; /* strdup("int4") -- strdup leaks memory here */
+ if (!strcasecmp(name,"int")
+ || !strcasecmp(name,"integer"))
+ return "int4";
else if (!strcasecmp(name, "smallint"))
return "int2";
- else if (!strcasecmp(name, "float") ||
- !strcasecmp(name, "real"))
+ else if (!strcasecmp(name, "real")
+ || !strcasecmp(name, "float"))
return "float8";
else if (!strcasecmp(name, "interval"))
return "timespan";
+ else if (!strcasecmp(name, "boolean"))
+ return "bool";
else
return name;
-}
+} /* xlateSqlType() */
+
void parser_init(Oid *typev, int nargs)
{
param_type_init(typev, nargs);
}
+
/* FlattenStringList()
* Traverse list of string nodes and convert to a single string.
* Used for reconstructing string form of complex expressions.
+ *
+ * Allocate at least one byte for terminator.
*/
static char *
FlattenStringList(List *list)
{
- List *l, *lp;
+ List *l;
+ Value *v;
char *s;
char *sp;
- int nlist, len = 1;
+ int nlist, len = 0;
nlist = length(list);
-#ifdef PARSEDEBUG
-printf( "list has %d elements\n", nlist);
-#endif
l = list;
while(l != NIL) {
- lp = lfirst(l);
- sp = (char *)(lp->elem.ptr_value);
+ v = (Value *)lfirst(l);
+ sp = v->val.str;
l = lnext(l);
-#ifdef PARSEDEBUG
-printf( "length of %s is %d\n", sp, strlen(sp));
-#endif
- len += strlen(sp)+1;
+ len += strlen(sp);
};
+ len += nlist;
- s = (char*) palloc(len);
+ s = (char*) palloc(len+1);
*s = '\0';
l = list;
while(l != NIL) {
- lp = lfirst(l);
- sp = (char *)(lp->elem.ptr_value);
+ v = (Value *)lfirst(l);
+ sp = v->val.str;
l = lnext(l);
-#ifdef PARSEDEBUG
-printf( "length of %s is %d\n", sp, strlen(sp));
-#endif
strcat(s,sp);
- strcat(s," ");
+ if (l != NIL) strcat(s," ");
};
- *(s+len-2) = '\0';
+ *(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() */
+
/* makeConstantList()
* Convert constant value node into string node.
*/
static List *
makeConstantList( A_Const *n)
{
+ List *result = NIL;
+ char *typval = NULL;
char *defval = NULL;
-#ifdef PARSEDEBUG
-printf( "in AexprConst\n");
-#endif
+
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) {
-#ifdef PARSEDEBUG
-printf( "AexprConst float is %f\n", n->val.val.dval);
-#endif
defval = (char*) palloc(20+1);
sprintf( defval, "%g", n->val.val.dval);
+ result = lcons( makeString(defval), NIL);
} else if (n->val.type == T_Integer) {
-#ifdef PARSEDEBUG
-printf( "AexprConst integer is %ld\n", n->val.val.ival);
-#endif
defval = (char*) palloc(20+1);
sprintf( defval, "%ld", n->val.val.ival);
+ result = lcons( makeString(defval), NIL);
} else if (n->val.type == T_String) {
-
-#ifdef PARSEDEBUG
-printf( "AexprConst string is \"%s\"\n", n->val.val.str);
-#endif
-
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: 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() */
+
+
+/* fmtId()
+ * Check input string for non-lowercase/non-numeric characters.
+ * Returns either input string or input surrounded by double quotes.
+ */
+static char *
+fmtId(char *rawid)
+{
+ static char *cp;
+
+ for (cp = rawid; *cp != '\0'; cp++)
+ if (! (islower(*cp) || isdigit(*cp) || (*cp == '_'))) break;
+
+ if (*cp != '\0') {
+ cp = palloc(strlen(rawid)+1);
+ strcpy(cp,"\"");
+ strcat(cp,rawid);
+ strcat(cp,"\"");
+ } else {
+ cp = rawid;
+ };
+
+#ifdef PARSEDEBUG
+ elog(DEBUG, "fmtId- %sconvert %s to %s\n",
+ ((cp == rawid)? "do not ": ""), rawid, cp);
+#endif
+
+ return (cp);
+}
+
+/*
+ * param_type_init()
+ *
+ * keep enough information around fill out the type of param nodes
+ * used in postquel functions
+ */
+static void
+param_type_init(Oid *typev, int nargs)
+{
+ pfunc_num_args = nargs;
+ param_type_info = typev;
+}
+
+Oid param_type(int t)
+{
+ if ((t > pfunc_num_args) || (t == 0))
+ return InvalidOid;
+ return param_type_info[t - 1];
+}