1996-07-09 08:22:35 +02:00
|
|
|
%{ /* -*-text-*- */
|
|
|
|
|
1996-11-28 06:46:08 +01:00
|
|
|
/*#define YYDEBUG 1*/
|
1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* gram.y--
|
1997-09-08 05:20:18 +02:00
|
|
|
* POSTGRES SQL YACC rules/actions
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
1997-09-25 16:11:42 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.51 1997/09/25 14:11:42 thomas Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* HISTORY
|
1997-09-08 05:20:18 +02:00
|
|
|
* AUTHOR DATE MAJOR EVENT
|
|
|
|
* Andrew Yu Sept, 1994 POSTQUEL to SQL conversion
|
|
|
|
* Andrew Yu Oct, 1994 lispy code conversion
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-08 05:20:18 +02:00
|
|
|
* CAPITALS are used to represent terminal symbols.
|
|
|
|
* non-capitals are used to represent non-terminals.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* if you use list, make sure the datum is a node so that the printing
|
|
|
|
* routines work
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* WARNING
|
1997-09-08 05:20:18 +02:00
|
|
|
* sometimes we assign constants to makeStrings. Make sure we don't free
|
|
|
|
* those.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include <ctype.h>
|
1996-11-08 21:46:33 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
#include "nodes/parsenodes.h"
|
1997-09-13 05:15:46 +02:00
|
|
|
#include "nodes/print.h"
|
1996-11-08 21:46:33 +01:00
|
|
|
#include "parser/gramparse.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "parser/catalog_utils.h"
|
|
|
|
#include "parser/parse_query.h"
|
1996-11-08 21:46:33 +01:00
|
|
|
#include "storage/smgr.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "utils/acl.h"
|
|
|
|
#include "catalog/catname.h"
|
|
|
|
#include "utils/elog.h"
|
|
|
|
#include "access/xact.h"
|
|
|
|
|
1996-11-28 06:46:08 +01:00
|
|
|
static char saved_relname[NAMEDATALEN]; /* need this for complex attributes */
|
1996-07-09 08:22:35 +02:00
|
|
|
static bool QueryIsRule = FALSE;
|
1996-11-30 04:38:09 +01:00
|
|
|
static Node *saved_In_Expr;
|
1996-07-09 08:22:35 +02:00
|
|
|
extern List *parsetree;
|
|
|
|
|
|
|
|
/*
|
1997-09-08 05:20:18 +02:00
|
|
|
* If you need access to certain yacc-generated variables and find that
|
1996-07-09 08:22:35 +02:00
|
|
|
* they're static by default, uncomment the next line. (this is not a
|
|
|
|
* problem, yet.)
|
|
|
|
*/
|
|
|
|
/*#define __YYSCLASS*/
|
|
|
|
|
|
|
|
static char *xlateSqlType(char *);
|
1996-11-30 04:38:09 +01:00
|
|
|
static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
|
1997-09-13 05:15:46 +02:00
|
|
|
static List *makeConstantList( A_Const *node);
|
|
|
|
static char *FlattenStringList(List *list);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/* old versions of flex define this as a macro */
|
|
|
|
#if defined(yywrap)
|
|
|
|
#undef yywrap
|
|
|
|
#endif /* yywrap */
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
%union
|
|
|
|
{
|
|
|
|
double dval;
|
|
|
|
int ival;
|
|
|
|
char chr;
|
|
|
|
char *str;
|
|
|
|
bool boolean;
|
|
|
|
List *list;
|
|
|
|
Node *node;
|
|
|
|
Value *value;
|
|
|
|
|
|
|
|
Attr *attr;
|
|
|
|
|
|
|
|
ColumnDef *coldef;
|
|
|
|
ConstraintDef *constrdef;
|
|
|
|
TypeName *typnam;
|
|
|
|
DefElem *defelt;
|
|
|
|
ParamString *param;
|
|
|
|
SortGroupBy *sortgroupby;
|
|
|
|
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;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
%type <node> stmt,
|
1997-09-08 05:20:18 +02:00
|
|
|
AddAttrStmt, ClosePortalStmt,
|
|
|
|
CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
|
|
|
|
ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt,
|
|
|
|
IndexStmt, MoveStmt, ListenStmt, OptimizableStmt,
|
|
|
|
ProcedureStmt, PurgeStmt,
|
|
|
|
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
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
%type <str> txname, char_type
|
1997-09-01 08:00:35 +02:00
|
|
|
%type <node> SubSelect
|
1997-09-13 05:15:46 +02:00
|
|
|
%type <str> join_expr, join_outer, join_spec
|
|
|
|
%type <boolean> TriggerActionTime, TriggerForSpec
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
%type <str> DateTime, TriggerEvents, TriggerFuncArg
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <str> relation_name, copy_file_name, copy_delimiter, def_name,
|
|
|
|
database_name, access_method_clause, access_method, attr_name,
|
1997-09-18 05:46:18 +02:00
|
|
|
class, index_name, name, file_name, recipe_name, aggr_argtype
|
1997-08-21 03:34:44 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <constrdef> ConstraintElem, ConstraintDef
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
%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
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <str> privileges, operation_commalist, grantee
|
|
|
|
%type <chr> operation, TriggerOneEvent
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-12-20 21:33:12 +01:00
|
|
|
%type <list> stmtblock, stmtmulti,
|
1997-09-08 05:20:18 +02:00
|
|
|
relation_name_list, OptTableElementList, tableElementList,
|
|
|
|
OptInherit, OptConstraint, ConstraintList, definition,
|
|
|
|
opt_with, def_args, def_name_list, func_argtypes,
|
|
|
|
oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
|
|
|
|
opt_column_list, columnList, opt_va_list, va_list,
|
|
|
|
sort_clause, sortby_list, index_params, index_list, name_list,
|
|
|
|
from_clause, from_list, opt_array_bounds, nest_array_bounds,
|
1997-09-13 05:15:46 +02:00
|
|
|
expr_list, attrs, res_target_list, res_target_list2,
|
1997-09-08 05:20:18 +02:00
|
|
|
def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
%type <list> union_clause, select_list
|
|
|
|
%type <list> join_list
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <sortgroupby> join_using
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
%type <node> position_expr
|
1997-09-01 08:00:35 +02:00
|
|
|
%type <list> extract_list, position_list
|
|
|
|
%type <list> substr_list, substr_from, substr_for, trim_list
|
|
|
|
%type <list> interval_opts
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <boolean> opt_inh_star, opt_binary, opt_instead, opt_with_col, opt_with_copy,
|
|
|
|
index_opt_unique, opt_verbose, opt_analyze, opt_null
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
%type <ival> copy_dirn, archive_type, OptArchiveType, OptArchiveLocation,
|
1997-09-08 05:20:18 +02:00
|
|
|
def_type, opt_direction, remove_type, opt_column, event
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
%type <ival> OptLocation, opt_move_where, fetch_how_many
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-04-02 06:01:03 +02:00
|
|
|
%type <list> OptSeqList
|
|
|
|
%type <defelt> OptSeqElem
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
%type <dstmt> def_rest
|
|
|
|
%type <pstmt> purge_quals
|
|
|
|
%type <astmt> insert_rest
|
|
|
|
|
1996-08-26 08:32:06 +02:00
|
|
|
%type <typnam> Typename, typname, opt_type
|
1997-09-18 05:46:18 +02:00
|
|
|
%type <coldef> columnDef, alter_clause
|
1996-07-09 08:22:35 +02:00
|
|
|
%type <defelt> def_elem
|
1997-09-01 08:00:35 +02:00
|
|
|
%type <node> def_arg, columnElem, where_clause,
|
1997-09-08 05:20:18 +02:00
|
|
|
a_expr, a_expr_or_null, AexprConst,
|
|
|
|
in_expr_nodes, not_in_expr_nodes,
|
|
|
|
having_clause
|
1996-07-09 08:22:35 +02:00
|
|
|
%type <value> NumConst
|
|
|
|
%type <attr> event_object, attr
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <sortgroupby> groupby
|
|
|
|
%type <sortgroupby> sortby
|
1996-07-09 08:22:35 +02:00
|
|
|
%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
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <paramno> ParamNo
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
%type <ival> Iconst
|
1997-09-08 05:20:18 +02:00
|
|
|
%type <str> Sconst
|
|
|
|
%type <str> Id, date, var_value, zone_value
|
|
|
|
%type <str> ColId
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
%type <list> default_expr
|
|
|
|
%type <str> opt_default
|
|
|
|
%type <list> constraint_elem
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If you make any token changes, remember to:
|
1997-09-08 05:20:18 +02:00
|
|
|
* - use "yacc -d" and update parse.h
|
|
|
|
* - update the keyword table in parser/keywords.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Keywords */
|
1997-09-01 08:00:35 +02:00
|
|
|
%token ABORT_TRANS, ACL, ADD, AFTER, AGGREGATE, ALL, ALTER, ANALYZE,
|
1997-09-08 05:20:18 +02:00
|
|
|
AND, APPEND, ARCHIVE, ARCH_STORE, AS, ASC,
|
1997-09-20 18:11:44 +02:00
|
|
|
BACKWARD, BEFORE, BEGIN_TRANS, BETWEEN, BINARY, BY,
|
1997-09-13 05:15:46 +02:00
|
|
|
CAST, CHANGE, CHECK, CLOSE, CLUSTER, COLUMN,
|
|
|
|
COMMIT, CONSTRAINT, COPY, CREATE, CROSS, CURRENT, CURSOR,
|
1997-09-20 18:11:44 +02:00
|
|
|
DATABASE, DECLARE, DEFAULT, DELETE, DELIMITERS, DESC,
|
1997-09-13 05:15:46 +02:00
|
|
|
DISTINCT, DO, DROP, END_TRANS, EXISTS, EXTEND,
|
1997-09-20 18:11:44 +02:00
|
|
|
FETCH, FOR, FORWARD, FROM, FULL, FUNCTION, GRANT, GROUP, HAVING, HEAVY,
|
|
|
|
IN, INDEX, INHERITS, INNERJOIN, INSERT, INSTEAD, INTO, IS, ISNULL,
|
|
|
|
JOIN, LANGUAGE, LEFT, LIGHT, LISTEN, LOAD, LOCAL, MERGE, MOVE,
|
1997-09-08 05:20:18 +02:00
|
|
|
NATURAL, NEW, NONE, NOT, NOTHING, NOTIFY, NOTNULL,
|
|
|
|
OIDS, ON, OPERATOR, OPTION, OR, ORDER, OUTERJOIN,
|
1997-09-13 05:15:46 +02:00
|
|
|
PNULL, PRIVILEGES, PROCEDURE, PUBLIC, PURGE, P_TYPE,
|
1997-09-08 05:20:18 +02:00
|
|
|
RENAME, REPLACE, RESET, RETRIEVE, RETURNS, REVOKE, RIGHT, ROLLBACK, RULE,
|
1997-09-20 18:11:44 +02:00
|
|
|
SELECT, SET, SETOF, SHOW, STDIN, STDOUT, STORE,
|
|
|
|
TABLE, TO, TRANSACTION, TRIGGER,
|
1997-09-08 05:20:18 +02:00
|
|
|
UNION, UNIQUE, UPDATE, USING, VACUUM, VALUES,
|
1997-09-20 18:11:44 +02:00
|
|
|
VERBOSE, VERSION, VIEW, WHERE, WITH, WORK
|
1997-04-02 06:01:03 +02:00
|
|
|
%token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
/* SQL-92 support */
|
1997-09-20 18:11:44 +02:00
|
|
|
%token INTERVAL, TIME, ZONE
|
|
|
|
%token DAYINTERVAL, HOURINTERVAL, MINUTEINTERVAL, MONTHINTERVAL,
|
|
|
|
SECONDINTERVAL, YEARINTERVAL
|
|
|
|
%token BOTH, LEADING, TRAILING,
|
1997-09-13 05:15:46 +02:00
|
|
|
%token EXTRACT, POSITION, SUBSTRING, TRIM
|
1997-09-20 18:11:44 +02:00
|
|
|
%token DOUBLE, PRECISION, FLOAT
|
1997-09-24 19:53:53 +02:00
|
|
|
%token DECIMAL, NUMERIC
|
1997-09-13 05:15:46 +02:00
|
|
|
%token CHARACTER, VARYING
|
1997-09-24 19:53:53 +02:00
|
|
|
%token CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP
|
1997-09-13 05:15:46 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* Special keywords, not in the query language - see the "lex" file */
|
1997-09-01 08:00:35 +02:00
|
|
|
%token <str> IDENT, SCONST, Op
|
1996-07-09 08:22:35 +02:00
|
|
|
%token <ival> ICONST, PARAM
|
|
|
|
%token <dval> FCONST
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
/* these are not real. they are here so that they get generated as #define's*/
|
1997-09-08 05:20:18 +02:00
|
|
|
%token OP
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/* precedence */
|
|
|
|
%left OR
|
|
|
|
%left AND
|
|
|
|
%right NOT
|
1997-09-01 08:00:35 +02:00
|
|
|
%right '='
|
1996-07-09 08:22:35 +02:00
|
|
|
%nonassoc LIKE
|
1996-11-30 04:38:09 +01:00
|
|
|
%nonassoc BETWEEN
|
|
|
|
%nonassoc IN
|
1996-07-09 08:22:35 +02:00
|
|
|
%nonassoc Op
|
|
|
|
%nonassoc NOTNULL
|
|
|
|
%nonassoc ISNULL
|
1996-08-06 18:43:41 +02:00
|
|
|
%nonassoc IS
|
1997-09-01 08:00:35 +02:00
|
|
|
%left '+' '-'
|
|
|
|
%left '*' '/'
|
1997-09-08 05:20:18 +02:00
|
|
|
%left '|' /* this is the relation union op, not logical or */
|
|
|
|
%right ':' /* Unary Operators */
|
|
|
|
%left ';' /* end of statement or natural log */
|
1996-07-09 08:22:35 +02:00
|
|
|
%nonassoc '<' '>'
|
1997-09-08 05:20:18 +02:00
|
|
|
%right UMINUS
|
1996-07-09 08:22:35 +02:00
|
|
|
%left '.'
|
1997-09-01 08:00:35 +02:00
|
|
|
%left '[' ']'
|
1996-07-09 08:22:35 +02:00
|
|
|
%nonassoc TYPECAST
|
|
|
|
%nonassoc REDUCE
|
1997-09-01 08:00:35 +02:00
|
|
|
%left UNION
|
1996-07-09 08:22:35 +02:00
|
|
|
%%
|
|
|
|
|
1996-12-20 21:33:12 +01:00
|
|
|
stmtblock: stmtmulti
|
1997-09-08 05:20:18 +02:00
|
|
|
{ parsetree = $1; }
|
|
|
|
| stmt
|
|
|
|
{ parsetree = lcons($1,NIL); }
|
|
|
|
;
|
1996-12-20 21:33:12 +01:00
|
|
|
|
|
|
|
stmtmulti: stmtmulti stmt ';'
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lappend($1, $2); }
|
|
|
|
| stmtmulti stmt
|
|
|
|
{ $$ = lappend($1, $2); }
|
|
|
|
| stmt ';'
|
|
|
|
{ $$ = lcons($1,NIL); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
stmt : AddAttrStmt
|
1997-09-08 05:20:18 +02:00
|
|
|
| ClosePortalStmt
|
|
|
|
| CopyStmt
|
|
|
|
| CreateStmt
|
|
|
|
| CreateSeqStmt
|
|
|
|
| CreateTrigStmt
|
|
|
|
| ClusterStmt
|
|
|
|
| DefineStmt
|
|
|
|
| DestroyStmt
|
|
|
|
| DropTrigStmt
|
|
|
|
| ExtendStmt
|
|
|
|
| ExplainStmt
|
|
|
|
| FetchStmt
|
|
|
|
| GrantStmt
|
|
|
|
| IndexStmt
|
|
|
|
| MoveStmt
|
|
|
|
| ListenStmt
|
|
|
|
| ProcedureStmt
|
|
|
|
| PurgeStmt
|
|
|
|
| RecipeStmt
|
|
|
|
| RemoveAggrStmt
|
|
|
|
| RemoveOperStmt
|
|
|
|
| RemoveFuncStmt
|
|
|
|
| RemoveStmt
|
|
|
|
| RenameStmt
|
|
|
|
| RevokeStmt
|
|
|
|
| OptimizableStmt
|
|
|
|
| RuleStmt
|
|
|
|
| TransactionStmt
|
|
|
|
| ViewStmt
|
|
|
|
| LoadStmt
|
|
|
|
| CreatedbStmt
|
|
|
|
| DestroydbStmt
|
|
|
|
| VacuumStmt
|
|
|
|
| VariableSetStmt
|
|
|
|
| VariableShowStmt
|
|
|
|
| VariableResetStmt
|
|
|
|
;
|
1997-04-02 20:24:52 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1997-04-02 20:24:52 +02:00
|
|
|
* Set PG internal variable
|
1997-09-18 05:46:18 +02:00
|
|
|
* SET name TO 'var_value'
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1997-04-02 20:24:52 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
VariableSetStmt: SET Id TO var_value
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
VariableSetStmt *n = makeNode(VariableSetStmt);
|
|
|
|
n->name = $2;
|
|
|
|
n->value = $4;
|
|
|
|
$$ = (Node *) n;
|
|
|
|
}
|
1997-09-18 05:46:18 +02:00
|
|
|
| SET Id '=' var_value
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
VariableSetStmt *n = makeNode(VariableSetStmt);
|
|
|
|
n->name = $2;
|
|
|
|
n->value = $4;
|
|
|
|
$$ = (Node *) n;
|
|
|
|
}
|
|
|
|
| SET TIME ZONE zone_value
|
|
|
|
{
|
|
|
|
VariableSetStmt *n = makeNode(VariableSetStmt);
|
|
|
|
n->name = "timezone";
|
|
|
|
n->value = $4;
|
|
|
|
$$ = (Node *) n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
var_value: Sconst { $$ = $1; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
zone_value: Sconst { $$ = $1; }
|
|
|
|
| LOCAL { $$ = NULL; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
VariableShowStmt: SHOW Id
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
VariableShowStmt *n = makeNode(VariableShowStmt);
|
|
|
|
n->name = $2;
|
|
|
|
$$ = (Node *) n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
VariableResetStmt: RESET Id
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
VariableResetStmt *n = makeNode(VariableResetStmt);
|
|
|
|
n->name = $2;
|
|
|
|
$$ = (Node *) n;
|
|
|
|
}
|
|
|
|
;
|
To: Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
Subject: Re: [PATCHES] SET DateStyle patches
On Tue, 22 Apr 1997, Thomas Lockhart wrote:
> Some more patches! These (try to) finish implementing SET variable TO value
> for "DateStyle" (changed the name from simply "date" to be more descriptive).
> This is based on code from Martin and Bruce (?), which was easy to modify.
> The syntax is
>
> SET DateStyle TO 'iso'
> SET DateStyle TO 'postgres'
> SET DateStyle TO 'sql'
> SET DateStyle TO 'european'
> SET DateStyle TO 'noneuropean'
> SET DateStyle TO 'us' (same as "noneuropean")
> SET DateStyle TO 'default' (current same as "postgres,us")
>
> ("european" is just compared for the first 4 characters, and "noneuropean"
> is compared for the first 7 to allow less typing).
>
> Multiple arguments are allowed, so SET datestyle TO 'sql,euro' is valid.
>
> My mods also try to implement "SHOW variable" and "RESET variable", but
> that part just core dumps at the moment. I would guess that my errors
> are obvious to someone who knows what they are doing with the parser stuff,
> so if someone (Bruce and/or Martin??) could have it do the right thing
> we will have a more complete set of what we need.
>
> Also, I would like to have a floating point precision global variable to
> implement "SET precision TO 10" and perhaps "SET precision TO 10,2" for
> float8 and float4, but I don't know how to do that for integer types rather
> than strings. If someone is fixing the SHOW and RESET code, perhaps they can
> add some hooks for me to do the floats while they are at it.
>
> I've left some remnants of variable structures in the source code which
> I did not use in the interests of getting something working for v6.1.
> We'll have time to clean things up for the next release...
1997-04-23 05:18:27 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY :
|
|
|
|
* addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
AddAttrStmt *n = makeNode(AddAttrStmt);
|
|
|
|
n->relname = $3;
|
|
|
|
n->inh = $4;
|
1997-09-18 05:46:18 +02:00
|
|
|
n->colDef = $5;
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
alter_clause: ADD opt_column columnDef
|
|
|
|
{
|
|
|
|
$$ = $3;
|
|
|
|
}
|
1997-09-20 18:11:44 +02:00
|
|
|
| ADD '(' tableElementList ')'
|
|
|
|
{
|
|
|
|
ColumnDef *lp = lfirst($3);
|
|
|
|
|
|
|
|
if (length($3) != 1)
|
|
|
|
elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf( "list has %d elements\n", length($3));
|
|
|
|
#endif
|
|
|
|
$$ = lp;
|
|
|
|
}
|
1997-09-18 05:46:18 +02:00
|
|
|
| DROP opt_column Id
|
|
|
|
{ elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
|
|
|
|
| ALTER opt_column Id SET opt_default
|
|
|
|
{ elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
|
|
|
|
| ALTER opt_column Id DROP DEFAULT
|
|
|
|
{ elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
|
|
|
|
| ADD ConstraintElem
|
|
|
|
{ elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
|
|
|
|
;
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
/* Column definition might include WITH TIME ZONE, but only for the data types
|
1997-09-13 05:15:46 +02:00
|
|
|
* called out in SQL92 date/time definitions. So, check explicitly for "timestamp"
|
1997-09-01 08:00:35 +02:00
|
|
|
* and "time". - thomas 1997-07-14
|
|
|
|
*/
|
1997-09-13 05:15:46 +02:00
|
|
|
columnDef: Id Typename opt_with_col opt_default opt_null
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(ColumnDef);
|
|
|
|
$$->colname = $1;
|
|
|
|
$$->typename = $2;
|
|
|
|
$$->typename->timezone = $3;
|
|
|
|
$$->defval = $4;
|
|
|
|
$$->is_not_null = $5;
|
|
|
|
if ($$->typename->timezone
|
1997-09-13 05:15:46 +02:00
|
|
|
&& (strcasecmp($$->typename->name, "timestamp")
|
|
|
|
&& strcasecmp($$->typename->name, "time")))
|
|
|
|
elog(NOTICE,"%s does not use WITH TIME ZONE",$$->typename->name);
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
|
|
|
;
|
1997-08-20 03:12:38 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
opt_default: DEFAULT default_expr
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
$$ = FlattenStringList($2);
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
| /*EMPTY*/ { $$ = NULL; }
|
|
|
|
;
|
1997-08-20 03:12:38 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
default_expr: AexprConst
|
|
|
|
{ $$ = makeConstantList((A_Const *) $1); }
|
|
|
|
| Pnull
|
|
|
|
{ $$ = lcons( makeString("NULL"), NIL); }
|
|
|
|
| '-' default_expr %prec UMINUS
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( "-"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr '+' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "+"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr '-' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "-"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr '/' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "/"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr '*' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "*"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr '=' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr '<' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr '>' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| ':' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( ":"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| ';' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( ";"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| '|' default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( "|"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr TYPECAST Typename
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
$$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
| CAST default_expr AS Typename
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
$$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
| '(' default_expr ')'
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| name '(' default_expr ')'
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
$$ = makeList( makeString($1), makeString("("), -1);
|
|
|
|
$$ = nconc( $$, $3);
|
|
|
|
$$ = lappend( $$, makeString(")"));
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
1997-09-24 10:31:04 +02:00
|
|
|
| name '(' ')'
|
|
|
|
{
|
|
|
|
$$ = makeList( makeString($1), makeString("("), -1);
|
|
|
|
$$ = lappend( $$, makeString(")"));
|
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr Op default_expr
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
if (!strcmp("<=", $2) || !strcmp(">=", $2))
|
|
|
|
elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
|
1997-09-16 18:11:20 +02:00
|
|
|
$$ = nconc( $1, lcons( makeString( $2), $3));
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
| Op default_expr
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( $1), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| default_expr Op
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lappend( $1, makeString( $2)); }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
opt_null: NOT PNULL { $$ = TRUE; }
|
|
|
|
| NOTNULL { $$ = TRUE; }
|
|
|
|
| /* EMPTY */ { $$ = FALSE; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
opt_with_col: WITH TIME ZONE { $$ = TRUE; }
|
1997-09-13 05:15:46 +02:00
|
|
|
| /* EMPTY */ { $$ = FALSE; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY :
|
|
|
|
* close <optname>
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
ClosePortalStmt: CLOSE opt_id
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
ClosePortalStmt *n = makeNode(ClosePortalStmt);
|
|
|
|
n->portalname = $2;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY :
|
|
|
|
* COPY [BINARY] <relname> FROM/TO
|
|
|
|
* [USING DELIMITERS <delimiter>]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1996-08-24 22:49:41 +02:00
|
|
|
CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
CopyStmt *n = makeNode(CopyStmt);
|
|
|
|
n->binary = $2;
|
|
|
|
n->relname = $3;
|
|
|
|
n->oids = $4;
|
|
|
|
n->direction = $5;
|
|
|
|
n->filename = $6;
|
|
|
|
n->delimiter = $7;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
copy_dirn: TO
|
|
|
|
{ $$ = TO; }
|
|
|
|
| FROM
|
|
|
|
{ $$ = FROM; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
/*
|
1996-07-09 08:22:35 +02:00
|
|
|
* copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
|
|
|
|
* used depends on the direction. (It really doesn't make sense to copy from
|
1997-09-08 05:20:18 +02:00
|
|
|
* stdout. We silently correct the "typo". - AY 9/94
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-08 05:20:18 +02:00
|
|
|
copy_file_name: Sconst { $$ = $1; }
|
|
|
|
| STDIN { $$ = NULL; }
|
|
|
|
| STDOUT { $$ = NULL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
opt_binary: BINARY { $$ = TRUE; }
|
|
|
|
| /*EMPTY*/ { $$ = FALSE; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
opt_with_copy: WITH OIDS { $$ = TRUE; }
|
|
|
|
| /* EMPTY */ { $$ = FALSE; }
|
|
|
|
;
|
1996-08-24 22:49:41 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
|
|
|
* the default copy delimiter is tab but the user can configure it
|
|
|
|
*/
|
|
|
|
copy_delimiter: USING DELIMITERS Sconst { $$ = $3;}
|
1997-09-08 05:20:18 +02:00
|
|
|
| /* EMPTY */ { $$ = "\t"; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY :
|
|
|
|
* CREATE relname
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
|
1997-09-08 05:20:18 +02:00
|
|
|
OptInherit OptConstraint OptArchiveType OptLocation
|
|
|
|
OptArchiveLocation
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
OptTableElementList: tableElementList { $$ = $1; }
|
|
|
|
| /* EMPTY */ { $$ = NULL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
tableElementList :
|
1997-09-08 05:20:18 +02:00
|
|
|
tableElementList ',' columnDef
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| columnDef
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
OptArchiveType: ARCHIVE '=' archive_type { $$ = $3; }
|
|
|
|
| /*EMPTY*/ { $$ = ARCH_NONE; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
archive_type: HEAVY { $$ = ARCH_HEAVY; }
|
|
|
|
| LIGHT { $$ = ARCH_LIGHT; }
|
|
|
|
| NONE { $$ = ARCH_NONE; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
OptLocation: STORE '=' Sconst
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = smgrin($3); }
|
|
|
|
| /*EMPTY*/
|
|
|
|
{ $$ = -1; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
OptArchiveLocation: ARCH_STORE '=' Sconst
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = smgrin($3); }
|
|
|
|
| /*EMPTY*/
|
|
|
|
{ $$ = -1; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
|
|
|
|
| /*EMPTY*/ { $$ = NIL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
OptConstraint: ConstraintList { $$ = $1; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1997-08-20 03:12:38 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
ConstraintList:
|
1997-09-08 05:20:18 +02:00
|
|
|
ConstraintList ',' ConstraintElem
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| ConstraintElem
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
|
|
|
|
|
|
|
ConstraintElem:
|
|
|
|
CONSTRAINT name ConstraintDef
|
|
|
|
{
|
|
|
|
$3->name = $2;
|
|
|
|
$$ = $3;
|
|
|
|
}
|
|
|
|
| ConstraintDef { $$ = $1; }
|
|
|
|
;
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
ConstraintDef: CHECK constraint_elem
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
ConstraintDef *constr = palloc (sizeof(ConstraintDef));
|
1997-09-13 05:15:46 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf("in ConstraintDef\n");
|
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
constr->type = CONSTR_CHECK;
|
|
|
|
constr->name = NULL;
|
1997-09-13 05:15:46 +02:00
|
|
|
constr->def = FlattenStringList($2);
|
1997-09-16 18:11:20 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf("ConstraintDef: string is %s\n", (char *) constr->def);
|
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = constr;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
constraint_elem: AexprConst
|
|
|
|
{ $$ = makeConstantList((A_Const *) $1); }
|
|
|
|
| Pnull
|
|
|
|
{ $$ = lcons( makeString("NULL"), NIL); }
|
|
|
|
| Id
|
|
|
|
{
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf( "Id is %s\n", $1);
|
|
|
|
#endif
|
|
|
|
$$ = lcons( makeString($1), NIL);
|
|
|
|
}
|
|
|
|
| '-' constraint_elem %prec UMINUS
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( "-"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem '+' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "+"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem '-' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "-"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem '/' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "/"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem '*' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "*"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem '=' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "="), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem '<' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "<"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem '>' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( ">"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| ':' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( ":"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| ';' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( ";"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| '|' constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( "|"), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| 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 ')'
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| name '(' constraint_elem ')'
|
|
|
|
{
|
|
|
|
$$ = makeList( makeString($1), makeString("("), -1);
|
|
|
|
$$ = nconc( $$, $3);
|
|
|
|
$$ = lappend( $$, makeString(")"));
|
|
|
|
}
|
|
|
|
| constraint_elem Op constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( $2), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem AND constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem OR constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = nconc( $1, lcons( makeString( "OR"), $3)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| Op constraint_elem
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lcons( makeString( $1), $2); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| constraint_elem Op
|
1997-09-16 18:11:20 +02:00
|
|
|
{ $$ = lappend( $1, makeString( $2)); }
|
1997-09-13 05:15:46 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
1997-04-02 06:01:03 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY :
|
|
|
|
* CREATE SEQUENCE seqname
|
1997-04-02 06:01:03 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
|
|
|
|
{
|
|
|
|
CreateSeqStmt *n = makeNode(CreateSeqStmt);
|
|
|
|
n->seqname = $3;
|
|
|
|
n->options = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1997-04-02 06:01:03 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
OptSeqList:
|
1997-09-08 05:20:18 +02:00
|
|
|
OptSeqList OptSeqElem
|
|
|
|
{ $$ = lappend($1, $2); }
|
|
|
|
| { $$ = NIL; }
|
|
|
|
;
|
|
|
|
|
|
|
|
OptSeqElem: IDENT NumConst
|
|
|
|
{
|
|
|
|
$$ = makeNode(DefElem);
|
|
|
|
$$->defname = $1;
|
|
|
|
$$->arg = (Node *)$2;
|
|
|
|
}
|
|
|
|
| IDENT
|
|
|
|
{
|
|
|
|
$$ = makeNode(DefElem);
|
|
|
|
$$->defname = $1;
|
|
|
|
$$->arg = (Node *)NULL;
|
|
|
|
}
|
|
|
|
;
|
1997-04-02 06:01:03 +02:00
|
|
|
|
|
|
|
|
1997-09-04 15:24:26 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERIES :
|
|
|
|
* CREATE TRIGGER ...
|
|
|
|
* DROP TRIGGER ...
|
1997-09-04 15:24:26 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
|
1997-09-08 05:20:18 +02:00
|
|
|
relation_name TriggerForSpec EXECUTE PROCEDURE
|
|
|
|
name '(' TriggerFuncArgs ')'
|
|
|
|
{
|
|
|
|
CreateTrigStmt *n = makeNode(CreateTrigStmt);
|
|
|
|
n->trigname = $3;
|
|
|
|
n->relname = $7;
|
|
|
|
n->funcname = $11;
|
|
|
|
n->args = $13;
|
|
|
|
n->before = $4;
|
|
|
|
n->row = $8;
|
|
|
|
memcpy (n->actions, $5, 4);
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
TriggerActionTime: BEFORE { $$ = TRUE; }
|
|
|
|
| AFTER { $$ = FALSE; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
TriggerOneEvent: INSERT { $$ = 'i'; }
|
|
|
|
| DELETE { $$ = 'd'; }
|
|
|
|
| UPDATE { $$ = 'u'; }
|
|
|
|
;
|
|
|
|
|
|
|
|
TriggerForSpec: FOR name name
|
|
|
|
{
|
|
|
|
if ( strcmp ($2, "each") != 0 )
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"parser: syntax error near %s",$2);
|
1997-09-08 05:20:18 +02:00
|
|
|
if ( strcmp ($3, "row") == 0 )
|
1997-09-13 05:15:46 +02:00
|
|
|
$$ = TRUE;
|
1997-09-08 05:20:18 +02:00
|
|
|
else if ( strcmp ($3, "statement") == 0 )
|
1997-09-13 05:15:46 +02:00
|
|
|
$$ = FALSE;
|
1997-09-08 05:20:18 +02:00
|
|
|
else
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"parser: syntax error near %s",$3);
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
|
|
|
;
|
1997-09-04 15:24:26 +02:00
|
|
|
|
|
|
|
TriggerFuncArgs: TriggerFuncArg
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
| TriggerFuncArgs ',' TriggerFuncArg
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| /* EMPTY */ { $$ = NIL; }
|
|
|
|
;
|
|
|
|
|
|
|
|
TriggerFuncArg: ICONST
|
1997-09-24 10:31:04 +02:00
|
|
|
{
|
1997-09-08 05:20:18 +02:00
|
|
|
char *s = (char *) palloc (256);
|
|
|
|
sprintf (s, "%d", $1);
|
|
|
|
$$ = s;
|
1997-09-24 10:31:04 +02:00
|
|
|
}
|
|
|
|
| FCONST
|
|
|
|
{
|
|
|
|
char *s = (char *) palloc (256);
|
|
|
|
sprintf (s, "%g", $1);
|
|
|
|
$$ = s;
|
|
|
|
}
|
1997-09-08 05:20:18 +02:00
|
|
|
| Sconst { $$ = $1; }
|
1997-09-24 10:31:04 +02:00
|
|
|
| IDENT { $$ = $1; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1997-09-04 15:24:26 +02:00
|
|
|
|
|
|
|
DropTrigStmt: DROP TRIGGER name ON relation_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
DropTrigStmt *n = makeNode(DropTrigStmt);
|
|
|
|
n->trigname = $3;
|
|
|
|
n->relname = $5;
|
|
|
|
$$ = (Node *) n;
|
|
|
|
}
|
|
|
|
;
|
1997-09-04 15:24:26 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY :
|
|
|
|
* define (type,operator,aggregate)
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
DefineStmt: CREATE def_type def_rest
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$3->defType = $2;
|
|
|
|
$$ = (Node *)$3;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
def_rest: def_name definition
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(DefineStmt);
|
|
|
|
$$->defname = $1;
|
1997-09-13 05:15:46 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf("def_rest: defname is %s\n", $1);
|
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
$$->definition = $2;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
def_type: OPERATOR { $$ = OPERATOR; }
|
|
|
|
| Type
|
|
|
|
{
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf("def_type: decoding P_TYPE\n");
|
|
|
|
#endif
|
|
|
|
$$ = P_TYPE;
|
|
|
|
}
|
|
|
|
| AGGREGATE { $$ = AGGREGATE; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
def_name: PROCEDURE { $$ = "procedure"; }
|
|
|
|
| Id { $$ = $1; }
|
|
|
|
| MathOp { $$ = $1; }
|
|
|
|
| Op { $$ = $1; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
definition: '(' def_list ')' { $$ = $2; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
def_list: def_elem { $$ = lcons($1, NIL); }
|
|
|
|
| def_list ',' def_elem { $$ = lappend($1, $3); }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
def_elem: def_name '=' def_arg
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf("def_elem: decoding %s =\n", $1);
|
|
|
|
pprint($3);
|
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = makeNode(DefElem);
|
|
|
|
$$->defname = $1;
|
|
|
|
$$->arg = (Node *)$3;
|
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
| def_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf("def_elem: decoding %s\n", $1);
|
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = makeNode(DefElem);
|
|
|
|
$$->defname = $1;
|
|
|
|
$$->arg = (Node *)NULL;
|
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
| DEFAULT '=' def_arg
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf("def_elem: decoding DEFAULT =\n");
|
|
|
|
pprint($3);
|
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = makeNode(DefElem);
|
1997-09-13 05:15:46 +02:00
|
|
|
$$->defname = "default";
|
1997-09-08 05:20:18 +02:00
|
|
|
$$->arg = (Node *)$3;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
def_arg: Id { $$ = (Node *)makeString($1); }
|
|
|
|
| all_Op { $$ = (Node *)makeString($1); }
|
|
|
|
| NumConst { $$ = (Node *)$1; /* already a Value */ }
|
|
|
|
| Sconst { $$ = (Node *)makeString($1); }
|
|
|
|
| SETOF Id
|
|
|
|
{
|
|
|
|
TypeName *n = makeNode(TypeName);
|
|
|
|
n->name = $2;
|
|
|
|
n->setof = TRUE;
|
|
|
|
n->arrayBounds = NULL;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| DOUBLE { $$ = (Node *)makeString("double"); }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* destroy <relname1> [, <relname2> .. <relnameN> ]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-04-02 06:01:03 +02:00
|
|
|
DestroyStmt: DROP TABLE relation_name_list
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
DestroyStmt *n = makeNode(DestroyStmt);
|
|
|
|
n->relNames = $3;
|
1997-09-13 05:15:46 +02:00
|
|
|
n->sequence = FALSE;
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| DROP SEQUENCE relation_name_list
|
|
|
|
{
|
|
|
|
DestroyStmt *n = makeNode(DestroyStmt);
|
|
|
|
n->relNames = $3;
|
1997-09-13 05:15:46 +02:00
|
|
|
n->sequence = TRUE;
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* fetch [forward | backward] [number | all ] [ in <portalname> ]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name
|
|
|
|
{
|
|
|
|
FetchStmt *n = makeNode(FetchStmt);
|
|
|
|
n->direction = $2;
|
|
|
|
n->howMany = $3;
|
|
|
|
n->portalname = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_direction: FORWARD { $$ = FORWARD; }
|
|
|
|
| BACKWARD { $$ = BACKWARD; }
|
|
|
|
| /*EMPTY*/ { $$ = FORWARD; /* default */ }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
fetch_how_many: Iconst
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = $1;
|
1997-09-13 05:15:46 +02:00
|
|
|
if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
|
1997-09-08 05:20:18 +02:00
|
|
|
| ALL { $$ = 0; /* 0 means fetch all tuples*/}
|
|
|
|
| /*EMPTY*/ { $$ = 1; /*default*/ }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* GRANT [privileges] ON [relation_name_list] TO [GROUP] grantee
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = (Node*)makeAclStmt($2,$4,$6,'+');
|
|
|
|
free($2);
|
|
|
|
free($6);
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
privileges: ALL PRIVILEGES
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = aclmakepriv("rwaR",0);
|
|
|
|
}
|
|
|
|
| ALL
|
|
|
|
{
|
|
|
|
$$ = aclmakepriv("rwaR",0);
|
|
|
|
}
|
|
|
|
| operation_commalist
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
operation_commalist: operation
|
|
|
|
{
|
|
|
|
$$ = aclmakepriv("",$1);
|
|
|
|
}
|
|
|
|
| operation_commalist ',' operation
|
|
|
|
{
|
|
|
|
$$ = aclmakepriv($1,$3);
|
|
|
|
free($1);
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
operation: SELECT
|
|
|
|
{
|
|
|
|
$$ = ACL_MODE_RD_CHR;
|
|
|
|
}
|
|
|
|
| INSERT
|
|
|
|
{
|
|
|
|
$$ = ACL_MODE_AP_CHR;
|
|
|
|
}
|
|
|
|
| UPDATE
|
|
|
|
{
|
|
|
|
$$ = ACL_MODE_WR_CHR;
|
|
|
|
}
|
|
|
|
| DELETE
|
|
|
|
{
|
|
|
|
$$ = ACL_MODE_WR_CHR;
|
|
|
|
}
|
|
|
|
| RULE
|
|
|
|
{
|
|
|
|
$$ = ACL_MODE_RU_CHR;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
grantee: PUBLIC
|
|
|
|
{
|
|
|
|
$$ = aclmakeuser("A","");
|
|
|
|
}
|
|
|
|
| GROUP Id
|
|
|
|
{
|
|
|
|
$$ = aclmakeuser("G",$2);
|
|
|
|
}
|
|
|
|
| Id
|
|
|
|
{
|
|
|
|
$$ = aclmakeuser("U",$1);
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
opt_with_grant : /* empty */
|
1997-09-08 05:20:18 +02:00
|
|
|
| WITH GRANT OPTION
|
|
|
|
{
|
|
|
|
yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* REVOKE [privileges] ON [relation_name] FROM [user]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = (Node*)makeAclStmt($2,$4,$6,'-');
|
|
|
|
free($2);
|
|
|
|
free($6);
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* move [<dirn>] [<whereto>] [<portalname>]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
MoveStmt: MOVE opt_direction opt_move_where opt_portal_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
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; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* define [archive] index <indexname> on <relname>
|
|
|
|
* using <access> "(" (<col> with <op>)+ ")" [with
|
|
|
|
* <target_list>]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* [where <qual>] is not supported anymore
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
|
|
|
|
access_method_clause '(' index_params ')' opt_with
|
|
|
|
{
|
|
|
|
/* should check that access_method is valid,
|
|
|
|
etc ... but doesn't */
|
|
|
|
IndexStmt *n = makeNode(IndexStmt);
|
|
|
|
n->unique = $2;
|
|
|
|
n->idxname = $4;
|
|
|
|
n->relname = $6;
|
|
|
|
n->accessMethod = $7;
|
|
|
|
n->indexParams = $9;
|
|
|
|
n->withClause = $11;
|
|
|
|
n->whereClause = NULL;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
access_method_clause: USING access_method { $$ = $2; }
|
|
|
|
| /* empty -- 'btree' is default access method */
|
|
|
|
{ $$ = "btree"; }
|
|
|
|
;
|
|
|
|
|
|
|
|
index_opt_unique: UNIQUE { $$ = TRUE; }
|
|
|
|
| /*empty*/ { $$ = FALSE; }
|
|
|
|
;
|
1996-08-15 09:42:52 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* extend index <indexname> [where <qual>]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
ExtendStmt: EXTEND INDEX index_name where_clause
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
ExtendStmt *n = makeNode(ExtendStmt);
|
|
|
|
n->idxname = $3;
|
|
|
|
n->whereClause = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* execute recipe <recipeName>
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
RecipeStmt: EXECUTE RECIPE recipe_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
RecipeStmt *n;
|
|
|
|
if (!IsTransactionBlock())
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
|
1997-09-08 05:20:18 +02:00
|
|
|
|
|
|
|
n = makeNode(RecipeStmt);
|
|
|
|
n->recipeName = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* define function <fname>
|
|
|
|
* (language = <lang>, returntype = <typename>
|
|
|
|
* [, arch_pct = <percentage | pre-defined>]
|
|
|
|
* [, disk_pct = <percentage | pre-defined>]
|
|
|
|
* [, byte_pct = <percentage | pre-defined>]
|
|
|
|
* [, perbyte_cpu = <int | pre-defined>]
|
|
|
|
* [, percall_cpu = <int | pre-defined>]
|
|
|
|
* [, iscachable])
|
|
|
|
* [arg is (<type-1> { , <type-n>})]
|
|
|
|
* as <filename or code in language as appropriate>
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
ProcedureStmt: CREATE FUNCTION def_name def_args
|
|
|
|
RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
|
|
|
|
{
|
|
|
|
ProcedureStmt *n = makeNode(ProcedureStmt);
|
|
|
|
n->funcname = $3;
|
|
|
|
n->defArgs = $4;
|
|
|
|
n->returnType = (Node *)$6;
|
|
|
|
n->withClause = $7;
|
|
|
|
n->as = $9;
|
|
|
|
n->language = $11;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
};
|
|
|
|
|
|
|
|
opt_with: WITH definition { $$ = $2; }
|
|
|
|
| /* EMPTY */ { $$ = NIL; }
|
|
|
|
;
|
|
|
|
|
|
|
|
def_args: '(' def_name_list ')' { $$ = $2; }
|
|
|
|
| '(' ')' { $$ = NIL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
def_name_list: name_list;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* purge <relname> [before <date>] [after <date>]
|
|
|
|
* or
|
|
|
|
* purge <relname> [after <date>] [before <date>]
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
PurgeStmt: PURGE relation_name purge_quals
|
|
|
|
{
|
|
|
|
$3->relname = $2;
|
|
|
|
$$ = (Node *)$3;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
purge_quals: before_clause
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(PurgeStmt);
|
|
|
|
$$->beforeDate = $1;
|
|
|
|
$$->afterDate = NULL;
|
|
|
|
}
|
|
|
|
| after_clause
|
|
|
|
{
|
|
|
|
$$ = makeNode(PurgeStmt);
|
|
|
|
$$->beforeDate = NULL;
|
|
|
|
$$->afterDate = $1;
|
|
|
|
}
|
|
|
|
| before_clause after_clause
|
|
|
|
{
|
|
|
|
$$ = makeNode(PurgeStmt);
|
|
|
|
$$->beforeDate = $1;
|
|
|
|
$$->afterDate = $2;
|
|
|
|
}
|
|
|
|
| after_clause before_clause
|
|
|
|
{
|
|
|
|
$$ = makeNode(PurgeStmt);
|
|
|
|
$$->beforeDate = $2;
|
|
|
|
$$->afterDate = $1;
|
|
|
|
}
|
|
|
|
| /*EMPTY*/
|
|
|
|
{
|
|
|
|
$$ = makeNode(PurgeStmt);
|
|
|
|
$$->beforeDate = NULL;
|
|
|
|
$$->afterDate = NULL;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
before_clause: BEFORE date { $$ = $2; }
|
|
|
|
after_clause: AFTER date { $$ = $2; }
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* remove function <funcname>
|
|
|
|
* (REMOVE FUNCTION "funcname" (arg1, arg2, ...))
|
|
|
|
* remove aggregate <aggname>
|
|
|
|
* (REMOVE AGGREGATE "aggname" "aggtype")
|
|
|
|
* remove operator <opname>
|
|
|
|
* (REMOVE OPERATOR "opname" (leftoperand_typ rightoperand_typ))
|
|
|
|
* remove type <typename>
|
|
|
|
* (REMOVE TYPE "typename")
|
|
|
|
* remove rule <rulename>
|
|
|
|
* (REMOVE RULE "rulename")
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
RemoveStmt: DROP remove_type name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
RemoveStmt *n = makeNode(RemoveStmt);
|
|
|
|
n->removeType = $2;
|
|
|
|
n->name = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
remove_type: Type { $$ = P_TYPE; }
|
|
|
|
| INDEX { $$ = INDEX; }
|
|
|
|
| RULE { $$ = RULE; }
|
|
|
|
| VIEW { $$ = VIEW; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-05-22 02:17:24 +02:00
|
|
|
RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
|
|
|
|
n->aggname = $3;
|
|
|
|
n->aggtype = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
aggr_argtype: name { $$ = $1; }
|
|
|
|
| '*' { $$ = NULL; }
|
|
|
|
;
|
1997-05-22 02:17:24 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
RemoveFuncStmt: DROP FUNCTION name '(' func_argtypes ')'
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
|
|
|
|
n->funcname = $3;
|
|
|
|
n->args = $5;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
func_argtypes: name_list { $$ = $1; }
|
|
|
|
| /*EMPTY*/ { $$ = NIL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
RemoveOperStmt *n = makeNode(RemoveOperStmt);
|
|
|
|
n->opname = $3;
|
|
|
|
n->args = $5;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
all_Op: Op | MathOp;
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
MathOp: '+' { $$ = "+"; }
|
1997-09-08 05:20:18 +02:00
|
|
|
| '-' { $$ = "-"; }
|
|
|
|
| '*' { $$ = "*"; }
|
|
|
|
| '/' { $$ = "/"; }
|
|
|
|
| '<' { $$ = "<"; }
|
|
|
|
| '>' { $$ = ">"; }
|
|
|
|
| '=' { $$ = "="; }
|
|
|
|
;
|
|
|
|
|
|
|
|
oper_argtypes: name
|
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
|
|
|
| name ',' name
|
|
|
|
{ $$ = makeList(makeString($1), makeString($3), -1); }
|
|
|
|
| NONE ',' name /* left unary */
|
|
|
|
{ $$ = makeList(NULL, makeString($3), -1); }
|
|
|
|
| name ',' NONE /* right unary */
|
|
|
|
{ $$ = makeList(makeString($1), NULL, -1); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* rename <attrname1> in <relname> [*] to <attrname2>
|
|
|
|
* rename <relname1> to <relname2>
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
RenameStmt: ALTER TABLE relation_name opt_inh_star
|
1997-09-08 05:20:18 +02:00
|
|
|
RENAME opt_column opt_name TO name
|
|
|
|
{
|
|
|
|
RenameStmt *n = makeNode(RenameStmt);
|
|
|
|
n->relname = $3;
|
|
|
|
n->inh = $4;
|
|
|
|
n->column = $7;
|
|
|
|
n->newname = $9;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_name: name { $$ = $1; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL; }
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_column: COLUMN { $$ = COLUMN; }
|
|
|
|
| /*EMPTY*/ { $$ = 0; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY: Define Rewrite Rule , Define Tuple Rule
|
|
|
|
* Define Rule <old rules >
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* only rewrite rule is supported -- ay 9/94
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
RuleStmt: CREATE RULE name AS
|
1997-09-08 05:20:18 +02:00
|
|
|
{ QueryIsRule=TRUE; }
|
|
|
|
ON event TO event_object where_clause
|
|
|
|
DO opt_instead OptStmtList
|
|
|
|
{
|
|
|
|
RuleStmt *n = makeNode(RuleStmt);
|
|
|
|
n->rulename = $3;
|
|
|
|
n->event = $7;
|
|
|
|
n->object = $9;
|
|
|
|
n->whereClause = $10;
|
|
|
|
n->instead = $12;
|
|
|
|
n->actions = $13;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
OptStmtList: NOTHING { $$ = NIL; }
|
|
|
|
| OptimizableStmt { $$ = lcons($1, NIL); }
|
|
|
|
| '[' OptStmtBlock ']' { $$ = $2; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-12-20 21:33:12 +01:00
|
|
|
OptStmtBlock: OptStmtMulti
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = $1; }
|
|
|
|
| OptimizableStmt
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-12-20 21:33:12 +01:00
|
|
|
OptStmtMulti: OptStmtMulti OptimizableStmt ';'
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lappend($1, $2); }
|
|
|
|
| OptStmtMulti OptimizableStmt
|
|
|
|
{ $$ = lappend($1, $2); }
|
|
|
|
| OptimizableStmt ';'
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
event_object: relation_name '.' attr_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(Attr);
|
|
|
|
$$->relname = $1;
|
|
|
|
$$->paramNo = NULL;
|
|
|
|
$$->attrs = lcons(makeString($3), NIL);
|
|
|
|
$$->indirection = NIL;
|
|
|
|
}
|
|
|
|
| relation_name
|
|
|
|
{
|
|
|
|
$$ = makeNode(Attr);
|
|
|
|
$$->relname = $1;
|
|
|
|
$$->paramNo = NULL;
|
|
|
|
$$->attrs = NIL;
|
|
|
|
$$->indirection = NIL;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/* change me to select, update, etc. some day */
|
1997-09-08 05:20:18 +02:00
|
|
|
event: SELECT { $$ = CMD_SELECT; }
|
|
|
|
| UPDATE { $$ = CMD_UPDATE; }
|
|
|
|
| DELETE { $$ = CMD_DELETE; }
|
|
|
|
| INSERT { $$ = CMD_INSERT; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
opt_instead: INSTEAD { $$ = TRUE; }
|
|
|
|
| /* EMPTY */ { $$ = FALSE; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* NOTIFY <relation_name> can appear both in rule bodies and
|
|
|
|
* as a query-level command
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
NotifyStmt: NOTIFY relation_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
NotifyStmt *n = makeNode(NotifyStmt);
|
|
|
|
n->relname = $2;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
ListenStmt: LISTEN relation_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
ListenStmt *n = makeNode(ListenStmt);
|
|
|
|
n->relname = $2;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* Transactions:
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* abort transaction
|
|
|
|
* (ABORT)
|
|
|
|
* begin transaction
|
|
|
|
* (BEGIN)
|
|
|
|
* end transaction
|
|
|
|
* (END)
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
TransactionStmt: ABORT_TRANS TRANSACTION
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
|
|
|
TransactionStmt *n = makeNode(TransactionStmt);
|
|
|
|
n->command = BEGIN_TRANS;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| COMMIT WORK
|
|
|
|
{
|
|
|
|
TransactionStmt *n = makeNode(TransactionStmt);
|
|
|
|
n->command = END_TRANS;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| END_TRANS TRANSACTION
|
|
|
|
{
|
|
|
|
TransactionStmt *n = makeNode(TransactionStmt);
|
|
|
|
n->command = END_TRANS;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| ROLLBACK WORK
|
|
|
|
{
|
|
|
|
TransactionStmt *n = makeNode(TransactionStmt);
|
|
|
|
n->command = ABORT_TRANS;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
|
|
|
|
| ABORT_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;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* define view <viewname> '('target-list ')' [where <quals> ]
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
ViewStmt: CREATE VIEW name AS RetrieveStmt
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
ViewStmt *n = makeNode(ViewStmt);
|
|
|
|
n->viewname = $3;
|
|
|
|
n->query = (Query *)$5;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* load "filename"
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
LoadStmt: LOAD file_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
LoadStmt *n = makeNode(LoadStmt);
|
|
|
|
n->filename = $2;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* createdb dbname
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
CreatedbStmt: CREATE DATABASE database_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
CreatedbStmt *n = makeNode(CreatedbStmt);
|
|
|
|
n->dbname = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* destroydb dbname
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
DestroydbStmt: DROP DATABASE database_name
|
|
|
|
{
|
|
|
|
DestroydbStmt *n = makeNode(DestroydbStmt);
|
|
|
|
n->dbname = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* cluster <index_name> on <relation_name>
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
ClusterStmt: CLUSTER index_name ON relation_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
ClusterStmt *n = makeNode(ClusterStmt);
|
|
|
|
n->relname = $4;
|
|
|
|
n->indexname = $2;
|
|
|
|
$$ = (Node*)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* vacuum
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-04-23 08:04:46 +02:00
|
|
|
VacuumStmt: VACUUM opt_verbose opt_analyze
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
VacuumStmt *n = makeNode(VacuumStmt);
|
|
|
|
n->verbose = $2;
|
|
|
|
n->analyze = $3;
|
|
|
|
n->vacrel = NULL;
|
|
|
|
n->va_spec = NIL;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| VACUUM opt_verbose relation_name opt_analyze opt_va_list
|
|
|
|
{
|
|
|
|
VacuumStmt *n = makeNode(VacuumStmt);
|
|
|
|
n->verbose = $2;
|
|
|
|
n->analyze = $4;
|
|
|
|
n->vacrel = $3;
|
|
|
|
n->va_spec = $5;
|
|
|
|
if ( $5 != NIL && !$4 )
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"parser: syntax error at or near \"(\"",NULL);
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_verbose: VERBOSE { $$ = TRUE; }
|
|
|
|
| /* EMPTY */ { $$ = FALSE; }
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_analyze: ANALYZE { $$ = TRUE; }
|
|
|
|
| /* EMPTY */ { $$ = FALSE; }
|
|
|
|
;
|
1997-04-23 08:04:46 +02:00
|
|
|
|
|
|
|
opt_va_list: '(' va_list ')'
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = $2; }
|
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1997-04-23 08:04:46 +02:00
|
|
|
|
|
|
|
va_list: name
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$=lcons($1,NIL); }
|
|
|
|
| va_list ',' name
|
|
|
|
{ $$=lappend($1,$3); }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* EXPLAIN query
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-01-16 15:56:59 +01:00
|
|
|
ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
ExplainStmt *n = makeNode(ExplainStmt);
|
|
|
|
n->verbose = $2;
|
|
|
|
n->query = (Query*)$3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
1997-09-08 05:20:18 +02:00
|
|
|
* *
|
|
|
|
* Optimizable Stmts: *
|
|
|
|
* *
|
|
|
|
* one of the five queries processed by the planner *
|
|
|
|
* *
|
|
|
|
* [ultimately] produces query-trees as specified *
|
|
|
|
* in the query-spec document in ~postgres/ref *
|
|
|
|
* *
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
OptimizableStmt: RetrieveStmt
|
1997-09-08 05:20:18 +02:00
|
|
|
| CursorStmt
|
|
|
|
| ReplaceStmt
|
|
|
|
| AppendStmt
|
|
|
|
| NotifyStmt
|
|
|
|
| DeleteStmt /* by default all are $$=$1 */
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* INSERT STATEMENTS
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
AppendStmt: INSERT INTO relation_name opt_column_list insert_rest
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$5->relname = $3;
|
|
|
|
$5->cols = $4;
|
|
|
|
$$ = (Node *)$5;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-10-30 03:02:41 +01:00
|
|
|
insert_rest: VALUES '(' res_target_list2 ')'
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(AppendStmt);
|
|
|
|
$$->targetList = $3;
|
|
|
|
$$->fromClause = NIL;
|
|
|
|
$$->whereClause = NULL;
|
|
|
|
}
|
|
|
|
| SELECT res_target_list2 from_clause where_clause
|
|
|
|
{
|
|
|
|
$$ = makeNode(AppendStmt);
|
|
|
|
$$->targetList = $2;
|
|
|
|
$$->fromClause = $3;
|
|
|
|
$$->whereClause = $4;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_column_list: '(' columnList ')' { $$ = $2; }
|
|
|
|
| /*EMPTY*/ { $$ = NIL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
columnList:
|
1997-09-08 05:20:18 +02:00
|
|
|
columnList ',' columnElem
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| columnElem
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
columnElem: Id opt_indirection
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
Ident *id = makeNode(Ident);
|
|
|
|
id->name = $1;
|
|
|
|
id->indirection = $2;
|
|
|
|
$$ = (Node *)id;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* DELETE STATEMENTS
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
DeleteStmt: DELETE FROM relation_name
|
1997-09-08 05:20:18 +02:00
|
|
|
where_clause
|
|
|
|
{
|
|
|
|
DeleteStmt *n = makeNode(DeleteStmt);
|
|
|
|
n->relname = $3;
|
|
|
|
n->whereClause = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* ReplaceStmt (UPDATE)
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
ReplaceStmt: UPDATE relation_name
|
1997-09-08 05:20:18 +02:00
|
|
|
SET res_target_list
|
|
|
|
from_clause
|
|
|
|
where_clause
|
|
|
|
{
|
|
|
|
ReplaceStmt *n = makeNode(ReplaceStmt);
|
|
|
|
n->relname = $2;
|
|
|
|
n->targetList = $4;
|
|
|
|
n->fromClause = $5;
|
|
|
|
n->whereClause = $6;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* CURSOR STATEMENTS
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
CursorStmt: DECLARE name opt_binary CURSOR FOR
|
1997-09-08 05:20:18 +02:00
|
|
|
SELECT opt_unique res_target_list2
|
|
|
|
from_clause where_clause group_clause sort_clause
|
|
|
|
{
|
|
|
|
CursorStmt *n = makeNode(CursorStmt);
|
|
|
|
|
|
|
|
/* from PORTAL name */
|
|
|
|
/*
|
|
|
|
* 15 august 1991 -- since 3.0 postgres does locking
|
|
|
|
* right, we discovered that portals were violating
|
|
|
|
* locking protocol. portal locks cannot span xacts.
|
|
|
|
* as a short-term fix, we installed the check here.
|
|
|
|
* -- mao
|
|
|
|
*/
|
|
|
|
if (!IsTransactionBlock())
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
|
1997-09-08 05:20:18 +02:00
|
|
|
|
|
|
|
n->portalname = $2;
|
|
|
|
n->binary = $3;
|
|
|
|
n->unique = $7;
|
|
|
|
n->targetList = $8;
|
|
|
|
n->fromClause = $9;
|
|
|
|
n->whereClause = $10;
|
|
|
|
n->groupClause = $11;
|
|
|
|
n->sortClause = $12;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* QUERY:
|
|
|
|
* SELECT STATEMENTS
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
/******************************************************************************
|
1996-07-09 08:22:35 +02:00
|
|
|
RetrieveStmt: SELECT opt_unique res_target_list2
|
1997-09-08 05:20:18 +02:00
|
|
|
result from_clause where_clause
|
|
|
|
group_clause having_clause
|
|
|
|
sort_clause
|
|
|
|
{
|
|
|
|
RetrieveStmt *n = makeNode(RetrieveStmt);
|
|
|
|
n->unique = $2;
|
|
|
|
n->targetList = $3;
|
|
|
|
n->into = $4;
|
|
|
|
n->fromClause = $5;
|
|
|
|
n->whereClause = $6;
|
|
|
|
n->groupClause = $7;
|
|
|
|
n->havingClause = $8;
|
|
|
|
n->sortClause = $9;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
RetrieveStmt: Select UNION select_list sort_clause
|
1997-09-08 05:20:18 +02:00
|
|
|
| Select sort_clause
|
1997-09-01 08:00:35 +02:00
|
|
|
Select: SELECT opt_unique res_target_list2
|
1997-09-08 05:20:18 +02:00
|
|
|
result from_clause where_clause
|
|
|
|
group_clause having_clause
|
|
|
|
{
|
|
|
|
Select *n = makeNode(Select);
|
|
|
|
n->unique = $2;
|
|
|
|
n->targetList = $3;
|
|
|
|
n->into = $4;
|
|
|
|
n->fromClause = $5;
|
|
|
|
n->whereClause = $6;
|
|
|
|
n->groupClause = $7;
|
|
|
|
n->havingClause = $8;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
RetrieveStmt: SELECT opt_unique res_target_list2
|
1997-09-08 05:20:18 +02:00
|
|
|
result from_clause where_clause
|
|
|
|
group_clause having_clause
|
|
|
|
union_clause sort_clause
|
|
|
|
{
|
|
|
|
RetrieveStmt *n = makeNode(RetrieveStmt);
|
|
|
|
n->unique = $2;
|
|
|
|
n->targetList = $3;
|
|
|
|
n->into = $4;
|
|
|
|
n->fromClause = $5;
|
|
|
|
n->whereClause = $6;
|
|
|
|
n->groupClause = $7;
|
|
|
|
n->havingClause = $8;
|
|
|
|
n->selectClause = $9;
|
|
|
|
n->sortClause = $10;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
union_clause: UNION select_list { $$ = $2; }
|
|
|
|
| /*EMPTY*/ { $$ = NIL; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
|
|
|
select_list: select_list UNION SubSelect
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| SubSelect
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
|
|
|
|
|
|
|
SubSelect: SELECT opt_unique res_target_list2
|
|
|
|
result from_clause where_clause
|
|
|
|
group_clause having_clause
|
|
|
|
{
|
|
|
|
SubSelect *n = makeNode(SubSelect);
|
|
|
|
n->unique = $2;
|
|
|
|
n->targetList = $3;
|
|
|
|
n->fromClause = $5;
|
|
|
|
n->whereClause = $6;
|
|
|
|
n->groupClause = $7;
|
|
|
|
n->havingClause = $8;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
result: INTO TABLE relation_name
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$= $3; /* should check for archive level */ }
|
|
|
|
| /*EMPTY*/
|
|
|
|
{ $$ = NULL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
opt_unique: DISTINCT { $$ = "*"; }
|
|
|
|
| DISTINCT ON Id { $$ = $3; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL;}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
sort_clause: ORDER BY sortby_list { $$ = $3; }
|
|
|
|
| /*EMPTY*/ { $$ = NIL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
sortby_list: sortby
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
| sortby_list ',' sortby
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
sortby: Id OptUseOp
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = 0;
|
|
|
|
$$->range = NULL;
|
|
|
|
$$->name = $1;
|
|
|
|
$$->useOp = $2;
|
|
|
|
}
|
|
|
|
| Id '.' Id OptUseOp
|
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = 0;
|
|
|
|
$$->range = $1;
|
|
|
|
$$->name = $3;
|
|
|
|
$$->useOp = $4;
|
|
|
|
}
|
|
|
|
| Iconst OptUseOp
|
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = $1;
|
|
|
|
$$->range = NULL;
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->useOp = $2;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
OptUseOp: USING Op { $$ = $2; }
|
|
|
|
| USING '<' { $$ = "<"; }
|
|
|
|
| USING '>' { $$ = ">"; }
|
|
|
|
| ASC { $$ = "<"; }
|
|
|
|
| DESC { $$ = ">"; }
|
|
|
|
| /*EMPTY*/ { $$ = "<"; /*default*/ }
|
|
|
|
;
|
|
|
|
|
|
|
|
index_params: index_list { $$ = $1; }
|
|
|
|
| func_index { $$ = lcons($1,NIL); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-03-26 03:52:49 +01:00
|
|
|
index_list:
|
1997-09-08 05:20:18 +02:00
|
|
|
index_list ',' index_elem
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| index_elem
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-08-26 08:32:06 +02:00
|
|
|
func_index: name '(' name_list ')' opt_type opt_class
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(IndexElem);
|
|
|
|
$$->name = $1;
|
|
|
|
$$->args = $3;
|
|
|
|
$$->class = $6;
|
|
|
|
$$->tname = $5;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-08-26 08:32:06 +02:00
|
|
|
index_elem: attr_name opt_type opt_class
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(IndexElem);
|
|
|
|
$$->name = $1;
|
|
|
|
$$->args = NIL;
|
|
|
|
$$->class = $3;
|
|
|
|
$$->tname = $2;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_type: ':' Typename { $$ = $2;}
|
|
|
|
| /*EMPTY*/ { $$ = NULL;}
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_class: class
|
|
|
|
| WITH class { $$ = $2; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
1997-09-08 05:20:18 +02:00
|
|
|
* jimmy bell-style recursive queries aren't supported in the
|
|
|
|
* current system.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* ...however, recursive addattr and rename supported. make special
|
|
|
|
* cases for these.
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* XXX i believe '*' should be the default behavior, but...
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-08 05:20:18 +02:00
|
|
|
opt_inh_star: '*' { $$ = TRUE; }
|
|
|
|
| /*EMPTY*/ { $$ = FALSE; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
relation_name_list: name_list;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
name_list: name
|
1997-09-18 05:46:18 +02:00
|
|
|
{ $$ = lcons(makeString($1),NIL); }
|
1997-09-08 05:20:18 +02:00
|
|
|
| name_list ',' name
|
1997-09-18 05:46:18 +02:00
|
|
|
{ $$ = lappend($1,makeString($3)); }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
group_clause: GROUP BY groupby_list { $$ = $3; }
|
|
|
|
| /*EMPTY*/ { $$ = NIL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
groupby_list: groupby { $$ = lcons($1, NIL); }
|
|
|
|
| groupby_list ',' groupby { $$ = lappend($1, $3); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-12-17 02:53:43 +01:00
|
|
|
groupby: Id
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = 0;
|
|
|
|
$$->range = NULL;
|
|
|
|
$$->name = $1;
|
|
|
|
$$->useOp = NULL;
|
|
|
|
}
|
|
|
|
| Id '.' Id
|
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = 0;
|
|
|
|
$$->range = $1;
|
|
|
|
$$->name = $3;
|
|
|
|
$$->useOp = NULL;
|
|
|
|
}
|
|
|
|
| Iconst
|
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = $1;
|
|
|
|
$$->range = NULL;
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->useOp = NULL;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
having_clause: HAVING a_expr { $$ = $2; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* clauses common to all Optimizable Stmts:
|
|
|
|
* from_clause -
|
|
|
|
* where_clause -
|
1997-09-01 08:00:35 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = NIL;
|
|
|
|
elog(WARN,"JOIN not yet implemented",NULL);
|
|
|
|
}
|
|
|
|
| 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
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-18 05:46:18 +02:00
|
|
|
from_val: relation_expr AS Id
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(RangeVar);
|
|
|
|
$$->relExpr = $1;
|
|
|
|
$$->name = $3;
|
|
|
|
}
|
1997-09-18 05:46:18 +02:00
|
|
|
| relation_expr Id
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(RangeVar);
|
|
|
|
$$->relExpr = $1;
|
|
|
|
$$->name = $2;
|
|
|
|
}
|
|
|
|
| relation_expr
|
|
|
|
{
|
|
|
|
$$ = makeNode(RangeVar);
|
|
|
|
$$->relExpr = $1;
|
|
|
|
$$->name = NULL;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
join_expr: NATURAL join_expr { $$ = NULL; }
|
|
|
|
| FULL join_outer
|
1997-09-08 05:20:18 +02:00
|
|
|
{ elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
|
|
|
|
| LEFT join_outer
|
|
|
|
{ elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
|
|
|
|
| RIGHT join_outer
|
|
|
|
{ elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| OUTERJOIN
|
1997-09-08 05:20:18 +02:00
|
|
|
{ elog(WARN,"OUTER JOIN not yet implemented",NULL); }
|
|
|
|
| INNERJOIN
|
|
|
|
{ elog(WARN,"INNER JOIN not yet implemented",NULL); }
|
|
|
|
| UNION
|
|
|
|
{ elog(WARN,"UNION JOIN not yet implemented",NULL); }
|
1997-09-13 05:15:46 +02:00
|
|
|
| /*EMPTY*/
|
|
|
|
{ elog(WARN,"INNER JOIN not yet implemented",NULL); }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
join_outer: OUTERJOIN { $$ = NULL; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
|
|
|
|
;
|
|
|
|
|
|
|
|
join_spec: ON '(' a_expr ')' { $$ = NULL; }
|
|
|
|
| USING '(' join_list ')' { $$ = NULL; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
|
|
|
|
;
|
|
|
|
|
|
|
|
join_list: join_using { $$ = lcons($1, NIL); }
|
|
|
|
| join_list ',' join_using { $$ = lappend($1, $3); }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
|
|
|
join_using: Id
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = 0;
|
|
|
|
$$->range = NULL;
|
|
|
|
$$->name = $1;
|
|
|
|
$$->useOp = NULL;
|
|
|
|
}
|
|
|
|
| Id '.' Id
|
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = 0;
|
|
|
|
$$->range = $1;
|
|
|
|
$$->name = $3;
|
|
|
|
$$->useOp = NULL;
|
|
|
|
}
|
|
|
|
| Iconst
|
|
|
|
{
|
|
|
|
$$ = makeNode(SortGroupBy);
|
|
|
|
$$->resno = $1;
|
|
|
|
$$->range = NULL;
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->useOp = NULL;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
where_clause: WHERE a_expr { $$ = $2; }
|
|
|
|
| /*EMPTY*/ { $$ = NULL; /* no qualifiers */ }
|
|
|
|
;
|
|
|
|
|
|
|
|
relation_expr: relation_name
|
|
|
|
{
|
|
|
|
/* normal relations */
|
|
|
|
$$ = makeNode(RelExpr);
|
|
|
|
$$->relname = $1;
|
|
|
|
$$->inh = FALSE;
|
|
|
|
$$->timeRange = NULL;
|
|
|
|
}
|
|
|
|
| relation_name '*' %prec '='
|
|
|
|
{
|
|
|
|
/* inheiritance query */
|
|
|
|
$$ = makeNode(RelExpr);
|
|
|
|
$$->relname = $1;
|
|
|
|
$$->inh = TRUE;
|
|
|
|
$$->timeRange = NULL;
|
|
|
|
}
|
|
|
|
| relation_name time_range
|
|
|
|
{
|
|
|
|
/* time-qualified query */
|
|
|
|
$$ = makeNode(RelExpr);
|
|
|
|
$$->relname = $1;
|
|
|
|
$$->inh = FALSE;
|
|
|
|
$$->timeRange = $2;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
time_range: '[' opt_range_start ',' opt_range_end ']'
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(TimeRange);
|
|
|
|
$$->startDate = $2;
|
|
|
|
$$->endDate = $4;
|
|
|
|
}
|
|
|
|
| '[' date ']'
|
|
|
|
{
|
|
|
|
$$ = makeNode(TimeRange);
|
|
|
|
$$->startDate = $2;
|
|
|
|
$$->endDate = NULL;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
opt_range_start: date
|
1997-09-08 05:20:18 +02:00
|
|
|
| /*EMPTY*/ { $$ = "epoch"; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
opt_range_end: date
|
|
|
|
| /*EMPTY*/ { $$ = "now"; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
opt_array_bounds: '[' ']' nest_array_bounds
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lcons(makeInteger(-1), $3); }
|
|
|
|
| '[' Iconst ']' nest_array_bounds
|
|
|
|
{ $$ = lcons(makeInteger($2), $4); }
|
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
|
|
|
|
|
|
|
nest_array_bounds: '[' ']' nest_array_bounds
|
|
|
|
{ $$ = lcons(makeInteger(-1), $3); }
|
|
|
|
| '[' Iconst ']' nest_array_bounds
|
|
|
|
{ $$ = lcons(makeInteger($2), $4); }
|
|
|
|
| /*EMPTY*/
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-20 18:11:44 +02:00
|
|
|
/*
|
|
|
|
* typname handles types without trailing parens for size specification.
|
|
|
|
* Typename uses either typname or explicit txname(size).
|
|
|
|
* So, must handle float in both places. - thomas 1997-09-20
|
|
|
|
*/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
typname: txname
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
1997-09-20 18:11:44 +02:00
|
|
|
char *tname;
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = makeNode(TypeName);
|
1997-09-20 18:11:44 +02:00
|
|
|
|
|
|
|
if (!strcasecmp($1, "float"))
|
|
|
|
tname = xlateSqlType("float8");
|
1997-09-24 19:53:53 +02:00
|
|
|
else if (!strcasecmp($1, "decimal"))
|
|
|
|
tname = xlateSqlType("integer");
|
|
|
|
else if (!strcasecmp($1, "numeric"))
|
|
|
|
tname = xlateSqlType("integer");
|
1997-09-20 18:11:44 +02:00
|
|
|
else
|
|
|
|
tname = xlateSqlType($1);
|
1997-09-08 05:20:18 +02:00
|
|
|
$$->name = tname;
|
|
|
|
|
|
|
|
/* Is this the name of a complex type? If so, implement
|
|
|
|
* it as a set.
|
|
|
|
*/
|
|
|
|
if (!strcmp(saved_relname, tname))
|
|
|
|
/* 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)
|
|
|
|
/* (Eventually add in here that the set can only
|
|
|
|
* contain one element.)
|
|
|
|
*/
|
|
|
|
$$->setof = TRUE;
|
|
|
|
else
|
|
|
|
$$->setof = FALSE;
|
|
|
|
}
|
|
|
|
| SETOF txname
|
|
|
|
{
|
|
|
|
char *tname = xlateSqlType($2);
|
|
|
|
$$ = makeNode(TypeName);
|
|
|
|
$$->name = tname;
|
|
|
|
$$->setof = TRUE;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
txname: Id { $$ = $1; }
|
1997-09-13 05:15:46 +02:00
|
|
|
| TIME { $$ = xlateSqlType("time"); }
|
|
|
|
| INTERVAL interval_opts { $$ = xlateSqlType("interval"); }
|
|
|
|
| CHARACTER char_type { $$ = $2; }
|
|
|
|
| DOUBLE PRECISION { $$ = xlateSqlType("float8"); }
|
1997-09-20 18:11:44 +02:00
|
|
|
| FLOAT { $$ = xlateSqlType("float"); }
|
1997-09-24 19:53:53 +02:00
|
|
|
| DECIMAL { $$ = "decimal"; }
|
|
|
|
| NUMERIC { $$ = "numeric"; }
|
1997-09-13 05:15:46 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
char_type: VARYING { $$ = xlateSqlType("varchar"); }
|
|
|
|
| /*EMPTY*/ { $$ = xlateSqlType("char"); }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
|
|
|
|
|
|
|
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; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
|
|
|
Typename: typname opt_array_bounds
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
$$->arrayBounds = $2;
|
1997-09-24 19:53:53 +02:00
|
|
|
#if FALSE
|
1997-09-13 05:15:46 +02:00
|
|
|
if (!strcasecmp($1->name, "varchar"))
|
|
|
|
$$->typlen = 4 + 1;
|
1997-09-24 19:53:53 +02:00
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
|
|
|
| txname '(' Iconst ')'
|
|
|
|
{
|
|
|
|
/*
|
1997-09-20 18:11:44 +02:00
|
|
|
* 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.
|
1997-09-24 19:53:53 +02:00
|
|
|
* - ay 6/95
|
|
|
|
* Also implements FLOAT().
|
|
|
|
* Check precision limits assuming IEEE floating types.
|
|
|
|
* - thomas 1997-09-18
|
1997-09-08 05:20:18 +02:00
|
|
|
*/
|
1997-09-20 18:11:44 +02:00
|
|
|
$$ = makeNode(TypeName);
|
|
|
|
if (!strcasecmp($1, "float")) {
|
|
|
|
if ($3 < 1)
|
1997-09-24 19:53:53 +02:00
|
|
|
elog(WARN,"precision for FLOAT must be at least 1",NULL);
|
|
|
|
else if ($3 < 7)
|
1997-09-20 18:11:44 +02:00
|
|
|
$$->name = xlateSqlType("float4");
|
1997-09-24 19:53:53 +02:00
|
|
|
else if ($3 < 16)
|
1997-09-20 18:11:44 +02:00
|
|
|
$$->name = xlateSqlType("float8");
|
|
|
|
else
|
1997-09-24 19:53:53 +02:00
|
|
|
elog(WARN,"precision for FLOAT must be less than 16",NULL);
|
|
|
|
} else if (!strcasecmp($1, "decimal")) {
|
|
|
|
/* DECIMAL is allowed to have more precision than specified */
|
|
|
|
if ($3 > 9)
|
|
|
|
elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
|
|
|
|
$$->name = xlateSqlType("integer");
|
|
|
|
|
|
|
|
} else if (!strcasecmp($1, "numeric")) {
|
|
|
|
/* integer holds 9.33 decimal places, so assume an even 9 for now */
|
|
|
|
if ($3 != 9)
|
|
|
|
elog(WARN,"NUMERIC precision %d must be 9",$3);
|
|
|
|
$$->name = xlateSqlType("integer");
|
1997-09-08 05:20:18 +02:00
|
|
|
|
1997-09-20 18:11:44 +02:00
|
|
|
} else {
|
1997-09-08 05:20:18 +02:00
|
|
|
if (!strcasecmp($1, "char"))
|
1997-09-20 18:11:44 +02:00
|
|
|
$$->name = xlateSqlType("bpchar");
|
1997-09-08 05:20:18 +02:00
|
|
|
else if (!strcasecmp($1, "varchar"))
|
1997-09-20 18:11:44 +02:00
|
|
|
$$->name = xlateSqlType("varchar");
|
1997-09-08 05:20:18 +02:00
|
|
|
else
|
|
|
|
yyerror("parse error");
|
|
|
|
if ($3 < 1)
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"length for '%s' type must be at least 1",$1);
|
1997-09-08 05:20:18 +02:00
|
|
|
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
|
|
|
|
*/
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"length for '%s' type cannot exceed 4096",$1);
|
1997-09-08 05:20:18 +02:00
|
|
|
|
|
|
|
/* we actually implement this sort of like a varlen, so
|
|
|
|
* the first 4 bytes is the length. (the difference
|
|
|
|
* between this and "text" is that we blank-pad and
|
|
|
|
* truncate where necessary
|
|
|
|
*/
|
|
|
|
$$->typlen = 4 + $3;
|
|
|
|
}
|
|
|
|
}
|
1997-09-24 19:53:53 +02:00
|
|
|
| txname '(' Iconst ',' Iconst ')'
|
|
|
|
{
|
|
|
|
$$ = makeNode(TypeName);
|
|
|
|
if (!strcasecmp($1, "decimal")) {
|
|
|
|
if ($3 > 9)
|
|
|
|
elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$3);
|
|
|
|
if ($5 != 0)
|
|
|
|
elog(WARN,"DECIMAL scale %d must be zero",$5);
|
|
|
|
$$->name = xlateSqlType("integer");
|
|
|
|
|
|
|
|
} else if (!strcasecmp($1, "numeric")) {
|
|
|
|
if ($3 != 9)
|
|
|
|
elog(WARN,"NUMERIC precision %d must be 9",$3);
|
|
|
|
if ($5 != 0)
|
|
|
|
elog(WARN,"NUMERIC scale %d must be zero",$5);
|
|
|
|
$$->name = xlateSqlType("integer");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
elog(WARN,"%s(%d,%d) not implemented",$1,$3,$5);
|
|
|
|
}
|
|
|
|
$$->name = xlateSqlType("integer");
|
|
|
|
}
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* expression grammar, still needs some cleanup
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-02-13 16:40:03 +01:00
|
|
|
a_expr_or_null: a_expr
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = $1;}
|
|
|
|
| Pnull
|
|
|
|
{
|
|
|
|
A_Const *n = makeNode(A_Const);
|
|
|
|
n->val.type = T_Null;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
a_expr: attr opt_indirection
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$1->indirection = $2;
|
|
|
|
$$ = (Node *)$1;
|
|
|
|
}
|
|
|
|
| AexprConst
|
|
|
|
{ $$ = $1; }
|
|
|
|
| '-' 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); }
|
|
|
|
| AexprConst TYPECAST Typename
|
|
|
|
{
|
|
|
|
/* AexprConst can be either A_Const or ParamNo */
|
|
|
|
if (nodeTag($1) == T_A_Const)
|
|
|
|
((A_Const *)$1)->typename = $3;
|
|
|
|
else
|
|
|
|
((ParamNo *)$1)->typename = $3;
|
|
|
|
$$ = (Node *)$1;
|
|
|
|
}
|
|
|
|
| CAST AexprConst AS Typename
|
|
|
|
{
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
| '(' a_expr_or_null ')'
|
|
|
|
{ $$ = $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
|
|
|
|
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
|
|
|
|
| a_expr Op
|
|
|
|
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
|
|
|
|
| Id
|
|
|
|
{
|
|
|
|
/* could be a column name or a relation_name */
|
|
|
|
Ident *n = makeNode(Ident);
|
|
|
|
n->name = $1;
|
|
|
|
n->indirection = NULL;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| name '(' '*' ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
Ident *star = makeNode(Ident);
|
|
|
|
|
|
|
|
/* cheap hack for aggregate (eg. count) */
|
|
|
|
star->name = "oid";
|
|
|
|
n->funcname = $1;
|
|
|
|
n->args = lcons(star, NIL);
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| name '(' ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = $1;
|
|
|
|
n->args = NIL;
|
1997-09-24 19:53:53 +02:00
|
|
|
$$ = (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;
|
|
|
|
|
|
|
|
$$ = (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;
|
|
|
|
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| CURRENT_TIME '(' AexprConst ')'
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
elog(NOTICE,"CURRENT_TIME(p) precision not implemented",NULL);
|
|
|
|
|
|
|
|
$$ = (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;
|
|
|
|
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| CURRENT_TIMESTAMP '(' AexprConst ')'
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
elog(NOTICE,"CURRENT_TIMESTAMP(p) precision not implemented",NULL);
|
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
/* We probably need to define an "exists" node,
|
|
|
|
* since the optimizer could choose to find only one match.
|
|
|
|
* Perhaps the first implementation could just check for
|
|
|
|
* count(*) > 0? - thomas 1997-07-19
|
|
|
|
*/
|
|
|
|
| EXISTS '(' SubSelect ')'
|
|
|
|
{
|
|
|
|
elog(WARN,"EXISTS not yet supported",NULL);
|
|
|
|
$$ = $3;
|
|
|
|
}
|
|
|
|
| EXTRACT '(' extract_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "date_part";
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| POSITION '(' position_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "strpos";
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| SUBSTRING '(' substr_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "substr";
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
/* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
|
|
|
|
| TRIM '(' BOTH trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "btrim";
|
|
|
|
n->args = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| TRIM '(' LEADING trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "ltrim";
|
|
|
|
n->args = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| TRIM '(' TRAILING trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "rtrim";
|
|
|
|
n->args = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| TRIM '(' trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "btrim";
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| name '(' expr_list ')'
|
|
|
|
{
|
|
|
|
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); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
opt_indirection: '[' a_expr ']' opt_indirection
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
A_Indices *ai = makeNode(A_Indices);
|
|
|
|
ai->lidx = NULL;
|
|
|
|
ai->uidx = $2;
|
|
|
|
$$ = lcons(ai, $4);
|
|
|
|
}
|
|
|
|
| '[' a_expr ':' a_expr ']' opt_indirection
|
|
|
|
{
|
|
|
|
A_Indices *ai = makeNode(A_Indices);
|
|
|
|
ai->lidx = $2;
|
|
|
|
ai->uidx = $4;
|
|
|
|
$$ = lcons(ai, $6);
|
|
|
|
}
|
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-02-13 16:40:03 +01:00
|
|
|
expr_list: a_expr_or_null
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
| expr_list ',' a_expr_or_null
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| expr_list USING a_expr
|
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
extract_list: DateTime FROM a_expr
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
A_Const *n = makeNode(A_Const);
|
|
|
|
n->val.type = T_String;
|
|
|
|
n->val.val.str = $1;
|
1997-09-13 05:15:46 +02:00
|
|
|
#ifdef PARSEDEBUG
|
1997-09-01 08:00:35 +02:00
|
|
|
printf( "string is %s\n", $1);
|
1997-09-13 05:15:46 +02:00
|
|
|
#endif
|
1997-09-08 05:20:18 +02:00
|
|
|
$$ = lappend(lcons((Node *)n,NIL), $3);
|
|
|
|
}
|
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
position_list: position_expr IN position_expr
|
|
|
|
{ $$ = makeList($3, $1, -1); }
|
1997-09-08 05:20:18 +02:00
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
position_expr: attr opt_indirection
|
|
|
|
{
|
|
|
|
$1->indirection = $2;
|
|
|
|
$$ = (Node *)$1;
|
|
|
|
}
|
|
|
|
| AexprConst
|
|
|
|
{ $$ = $1; }
|
|
|
|
| '-' position_expr %prec UMINUS
|
|
|
|
{ $$ = makeA_Expr(OP, "-", NULL, $2); }
|
|
|
|
| position_expr '+' position_expr
|
|
|
|
{ $$ = makeA_Expr(OP, "+", $1, $3); }
|
|
|
|
| position_expr '-' position_expr
|
|
|
|
{ $$ = makeA_Expr(OP, "-", $1, $3); }
|
|
|
|
| position_expr '/' position_expr
|
|
|
|
{ $$ = makeA_Expr(OP, "/", $1, $3); }
|
|
|
|
| position_expr '*' position_expr
|
|
|
|
{ $$ = makeA_Expr(OP, "*", $1, $3); }
|
|
|
|
| '|' position_expr
|
|
|
|
{ $$ = makeA_Expr(OP, "|", NULL, $2); }
|
|
|
|
| AexprConst TYPECAST Typename
|
|
|
|
{
|
|
|
|
/* AexprConst can be either A_Const or ParamNo */
|
|
|
|
if (nodeTag($1) == T_A_Const)
|
|
|
|
((A_Const *)$1)->typename = $3;
|
|
|
|
else
|
|
|
|
((ParamNo *)$1)->typename = $3;
|
|
|
|
$$ = (Node *)$1;
|
|
|
|
}
|
|
|
|
| CAST AexprConst AS Typename
|
|
|
|
{
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
| '(' position_expr ')'
|
|
|
|
{ $$ = $2; }
|
|
|
|
| position_expr Op position_expr
|
|
|
|
{ $$ = makeA_Expr(OP, $2, $1, $3); }
|
|
|
|
| Op position_expr
|
|
|
|
{ $$ = makeA_Expr(OP, $1, NULL, $2); }
|
|
|
|
| position_expr Op
|
|
|
|
{ $$ = makeA_Expr(OP, $2, $1, NULL); }
|
|
|
|
| Id
|
|
|
|
{
|
|
|
|
/* could be a column name or a relation_name */
|
|
|
|
Ident *n = makeNode(Ident);
|
|
|
|
n->name = $1;
|
|
|
|
n->indirection = NULL;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| name '(' ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = $1;
|
|
|
|
n->args = NIL;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| POSITION '(' position_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "strpos";
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| SUBSTRING '(' substr_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "substr";
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
/* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
|
|
|
|
| TRIM '(' BOTH trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "btrim";
|
|
|
|
n->args = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| TRIM '(' LEADING trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "ltrim";
|
|
|
|
n->args = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| TRIM '(' TRAILING trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "rtrim";
|
|
|
|
n->args = $4;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| TRIM '(' trim_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = "btrim";
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| name '(' expr_list ')'
|
|
|
|
{
|
|
|
|
FuncCall *n = makeNode(FuncCall);
|
|
|
|
n->funcname = $1;
|
|
|
|
n->args = $3;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
substr_list: expr_list substr_from substr_for
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
if ($2 != NULL) $$ = lappend($$, $2);
|
|
|
|
if ($3 != NULL) $$ = lappend($$, $3);
|
|
|
|
}
|
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
|
|
|
substr_from: FROM expr_list
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = $2; }
|
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
|
|
|
substr_for: FOR expr_list
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = $2; }
|
|
|
|
| /* EMPTY */
|
|
|
|
{ $$ = NIL; }
|
|
|
|
;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
|
|
|
trim_list: a_expr FROM expr_list
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lappend($3, $1); }
|
|
|
|
| FROM expr_list
|
|
|
|
{ $$ = $2; }
|
|
|
|
| expr_list
|
|
|
|
{ $$ = $1; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1996-11-30 04:38:09 +01:00
|
|
|
in_expr_nodes: AexprConst
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
|
|
|
|
| in_expr_nodes ',' AexprConst
|
|
|
|
{ $$ = makeA_Expr(OR, NULL, $1,
|
|
|
|
makeA_Expr(OP, "=", saved_In_Expr, $3));
|
|
|
|
}
|
|
|
|
;
|
1996-11-30 04:38:09 +01:00
|
|
|
|
|
|
|
not_in_expr_nodes: AexprConst
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
|
|
|
|
| not_in_expr_nodes ',' AexprConst
|
|
|
|
{ $$ = makeA_Expr(AND, NULL, $1,
|
|
|
|
makeA_Expr(OP, "<>", saved_In_Expr, $3));
|
|
|
|
}
|
|
|
|
;
|
1996-11-30 04:38:09 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
attr: relation_name '.' attrs
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(Attr);
|
|
|
|
$$->relname = $1;
|
|
|
|
$$->paramNo = NULL;
|
|
|
|
$$->attrs = $3;
|
|
|
|
$$->indirection = NULL;
|
|
|
|
}
|
|
|
|
| ParamNo '.' attrs
|
|
|
|
{
|
|
|
|
$$ = makeNode(Attr);
|
|
|
|
$$->relname = NULL;
|
|
|
|
$$->paramNo = $1;
|
|
|
|
$$->attrs = $3;
|
|
|
|
$$->indirection = NULL;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
attrs: attr_name
|
|
|
|
{ $$ = lcons(makeString($1), NIL); }
|
|
|
|
| attrs '.' attr_name
|
|
|
|
{ $$ = lappend($1, makeString($3)); }
|
|
|
|
| attrs '.' '*'
|
|
|
|
{ $$ = lappend($1, makeString("*")); }
|
|
|
|
;
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
DateTime: YEARINTERVAL { $$ = "year"; }
|
1997-09-08 05:20:18 +02:00
|
|
|
| MONTHINTERVAL { $$ = "month"; }
|
|
|
|
| DAYINTERVAL { $$ = "day"; }
|
|
|
|
| HOURINTERVAL { $$ = "hour"; }
|
|
|
|
| MINUTEINTERVAL { $$ = "minute"; }
|
|
|
|
| SECONDINTERVAL { $$ = "second"; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-08 05:20:18 +02:00
|
|
|
* target lists
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
1997-09-01 08:00:35 +02:00
|
|
|
res_target_list: res_target_list ',' res_target_el
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lappend($1,$3); }
|
|
|
|
| res_target_el
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
| '*'
|
|
|
|
{
|
|
|
|
ResTarget *rt = makeNode(ResTarget);
|
|
|
|
Attr *att = makeNode(Attr);
|
|
|
|
att->relname = "*";
|
|
|
|
att->paramNo = NULL;
|
|
|
|
att->attrs = NULL;
|
|
|
|
att->indirection = NIL;
|
|
|
|
rt->name = NULL;
|
|
|
|
rt->indirection = NULL;
|
|
|
|
rt->val = (Node *)att;
|
|
|
|
$$ = lcons(rt, NIL);
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-02-13 16:40:03 +01:00
|
|
|
res_target_el: Id opt_indirection '=' a_expr_or_null
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(ResTarget);
|
|
|
|
$$->name = $1;
|
|
|
|
$$->indirection = $2;
|
|
|
|
$$->val = (Node *)$4;
|
|
|
|
}
|
|
|
|
| attr opt_indirection
|
|
|
|
{
|
|
|
|
$$ = makeNode(ResTarget);
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->indirection = $2;
|
|
|
|
$$->val = (Node *)$1;
|
|
|
|
}
|
|
|
|
| relation_name '.' '*'
|
|
|
|
{
|
|
|
|
Attr *att = makeNode(Attr);
|
|
|
|
att->relname = $1;
|
|
|
|
att->paramNo = NULL;
|
|
|
|
att->attrs = lcons(makeString("*"), NIL);
|
|
|
|
att->indirection = NIL;
|
|
|
|
$$ = makeNode(ResTarget);
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->indirection = NULL;
|
|
|
|
$$->val = (Node *)att;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
** target list for select.
|
|
|
|
** should get rid of the other but is still needed by the defunct retrieve into
|
|
|
|
** and update (uses a subset)
|
|
|
|
*/
|
1997-09-01 08:00:35 +02:00
|
|
|
res_target_list2: res_target_list2 ',' res_target_el2
|
1997-09-08 05:20:18 +02:00
|
|
|
{ $$ = lappend($1, $3); }
|
|
|
|
| res_target_el2
|
|
|
|
{ $$ = lcons($1, NIL); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/* AS is not optional because shift/red conflict with unary ops */
|
1997-09-13 00:14:48 +02:00
|
|
|
res_target_el2: a_expr_or_null AS ColId
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(ResTarget);
|
|
|
|
$$->name = $3;
|
|
|
|
$$->indirection = NULL;
|
|
|
|
$$->val = (Node *)$1;
|
|
|
|
}
|
|
|
|
| a_expr_or_null
|
|
|
|
{
|
|
|
|
$$ = makeNode(ResTarget);
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->indirection = NULL;
|
|
|
|
$$->val = (Node *)$1;
|
|
|
|
}
|
|
|
|
| relation_name '.' '*'
|
|
|
|
{
|
|
|
|
Attr *att = makeNode(Attr);
|
|
|
|
att->relname = $1;
|
|
|
|
att->paramNo = NULL;
|
|
|
|
att->attrs = lcons(makeString("*"), NIL);
|
|
|
|
att->indirection = NIL;
|
|
|
|
$$ = makeNode(ResTarget);
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->indirection = NULL;
|
|
|
|
$$->val = (Node *)att;
|
|
|
|
}
|
|
|
|
| '*'
|
|
|
|
{
|
|
|
|
Attr *att = makeNode(Attr);
|
|
|
|
att->relname = "*";
|
|
|
|
att->paramNo = NULL;
|
|
|
|
att->attrs = NULL;
|
|
|
|
att->indirection = NIL;
|
|
|
|
$$ = makeNode(ResTarget);
|
|
|
|
$$->name = NULL;
|
|
|
|
$$->indirection = NULL;
|
|
|
|
$$->val = (Node *)att;
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
opt_id: Id { $$ = $1; }
|
|
|
|
| /* EMPTY */ { $$ = NULL; }
|
|
|
|
;
|
|
|
|
|
|
|
|
relation_name: SpecialRuleRelation
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
strNcpy(saved_relname, $1, NAMEDATALEN-1);
|
|
|
|
}
|
|
|
|
| ColId
|
|
|
|
{
|
|
|
|
/* disallow refs to magic system tables */
|
|
|
|
if (strcmp(LogRelationName, $1) == 0
|
|
|
|
|| strcmp(VariableRelationName, $1) == 0
|
|
|
|
|| strcmp(TimeRelationName, $1) == 0
|
|
|
|
|| strcmp(MagicRelationName, $1) == 0)
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"%s cannot be accessed by users",$1);
|
1997-09-08 05:20:18 +02:00
|
|
|
else
|
|
|
|
$$ = $1;
|
|
|
|
strNcpy(saved_relname, $1, NAMEDATALEN-1);
|
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
database_name: Id { $$ = $1; };
|
|
|
|
access_method: Id { $$ = $1; };
|
|
|
|
attr_name: ColId { $$ = $1; };
|
|
|
|
class: Id { $$ = $1; };
|
|
|
|
index_name: Id { $$ = $1; };
|
1997-09-24 19:53:53 +02:00
|
|
|
|
|
|
|
name: Id { $$ = $1; }
|
|
|
|
| TIME { $$ = xlateSqlType("time"); }
|
|
|
|
;
|
1997-09-08 05:20:18 +02:00
|
|
|
|
|
|
|
date: Sconst { $$ = $1; };
|
|
|
|
file_name: Sconst { $$ = $1; };
|
|
|
|
recipe_name: Id { $$ = $1; };
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
AexprConst: Iconst
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
A_Const *n = makeNode(A_Const);
|
|
|
|
n->val.type = T_Integer;
|
|
|
|
n->val.val.ival = $1;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| FCONST
|
|
|
|
{
|
|
|
|
A_Const *n = makeNode(A_Const);
|
|
|
|
n->val.type = T_Float;
|
|
|
|
n->val.val.dval = $1;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| Sconst
|
|
|
|
{
|
|
|
|
A_Const *n = makeNode(A_Const);
|
|
|
|
n->val.type = T_String;
|
|
|
|
n->val.val.str = $1;
|
|
|
|
$$ = (Node *)n;
|
|
|
|
}
|
|
|
|
| ParamNo
|
|
|
|
{ $$ = (Node *)$1; }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
ParamNo: PARAM
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
$$ = makeNode(ParamNo);
|
|
|
|
$$->number = $1;
|
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
NumConst: Iconst { $$ = makeInteger($1); }
|
|
|
|
| FCONST { $$ = makeFloat($1); }
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
Iconst: ICONST { $$ = $1; };
|
|
|
|
Sconst: SCONST { $$ = $1; };
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
Id: IDENT { $$ = $1; };
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
ColId: Id { $$ = $1; }
|
1997-09-13 05:15:46 +02:00
|
|
|
| DateTime { $$ = $1; }
|
1997-09-08 05:20:18 +02:00
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
SpecialRuleRelation: CURRENT
|
1997-09-08 05:20:18 +02:00
|
|
|
{
|
|
|
|
if (QueryIsRule)
|
|
|
|
$$ = "*CURRENT*";
|
|
|
|
else
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"CURRENT used in non-rule query",NULL);
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
|
|
|
| NEW
|
|
|
|
{
|
|
|
|
if (QueryIsRule)
|
|
|
|
$$ = "*NEW*";
|
|
|
|
else
|
1997-09-13 05:15:46 +02:00
|
|
|
elog(WARN,"NEW used in non-rule query",NULL);
|
1997-09-08 05:20:18 +02:00
|
|
|
}
|
|
|
|
;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
Type: P_TYPE;
|
|
|
|
Pnull: PNULL;
|
|
|
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
1996-11-30 04:38:09 +01:00
|
|
|
static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 05:20:18 +02:00
|
|
|
A_Expr *a = makeNode(A_Expr);
|
|
|
|
a->oper = oper;
|
|
|
|
a->opname = opname;
|
|
|
|
a->lexpr = lexpr;
|
|
|
|
a->rexpr = rexpr;
|
|
|
|
return (Node *)a;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-13 05:15:46 +02:00
|
|
|
/* xlateSqlType()
|
|
|
|
* Convert alternate type names to internal Postgres types.
|
1997-09-20 18:11:44 +02:00
|
|
|
* Do not convert "float", since that is handled elsewhere
|
|
|
|
* for FLOAT(p) syntax.
|
1997-09-13 05:15:46 +02:00
|
|
|
*/
|
1996-07-09 08:22:35 +02:00
|
|
|
static char *
|
|
|
|
xlateSqlType(char *name)
|
|
|
|
{
|
1997-09-08 05:20:18 +02:00
|
|
|
if (!strcasecmp(name,"int") ||
|
|
|
|
!strcasecmp(name,"integer"))
|
|
|
|
return "int4"; /* strdup("int4") -- strdup leaks memory here */
|
|
|
|
else if (!strcasecmp(name, "smallint"))
|
|
|
|
return "int2";
|
1997-09-20 18:11:44 +02:00
|
|
|
else if (!strcasecmp(name, "real"))
|
1997-09-08 05:20:18 +02:00
|
|
|
return "float8";
|
|
|
|
else if (!strcasecmp(name, "interval"))
|
|
|
|
return "timespan";
|
|
|
|
else
|
|
|
|
return name;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void parser_init(Oid *typev, int nargs)
|
|
|
|
{
|
1997-09-13 05:15:46 +02:00
|
|
|
QueryIsRule = FALSE;
|
1997-09-08 05:20:18 +02:00
|
|
|
saved_relname[0]= '\0';
|
|
|
|
saved_In_Expr = NULL;
|
1997-09-01 08:00:35 +02:00
|
|
|
|
1997-09-08 05:20:18 +02:00
|
|
|
param_type_init(typev, nargs);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-13 05:15:46 +02:00
|
|
|
|
|
|
|
/* FlattenStringList()
|
|
|
|
* Traverse list of string nodes and convert to a single string.
|
|
|
|
* Used for reconstructing string form of complex expressions.
|
1997-09-24 19:53:53 +02:00
|
|
|
*
|
|
|
|
* Allocate at least one byte for terminator.
|
1997-09-13 05:15:46 +02:00
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
FlattenStringList(List *list)
|
|
|
|
{
|
1997-09-25 16:11:42 +02:00
|
|
|
List *l;
|
|
|
|
Value *v;
|
1997-09-13 05:15:46 +02:00
|
|
|
char *s;
|
|
|
|
char *sp;
|
1997-09-24 19:53:53 +02:00
|
|
|
int nlist, len = 0;
|
1997-09-13 05:15:46 +02:00
|
|
|
|
|
|
|
nlist = length(list);
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf( "list has %d elements\n", nlist);
|
|
|
|
#endif
|
|
|
|
l = list;
|
|
|
|
while(l != NIL) {
|
1997-09-25 16:11:42 +02:00
|
|
|
v = (Value *)lfirst(l);
|
|
|
|
sp = v->val.str;
|
1997-09-13 05:15:46 +02:00
|
|
|
l = lnext(l);
|
|
|
|
#ifdef PARSEDEBUG
|
1997-09-24 19:53:53 +02:00
|
|
|
printf( "sp is x%8p; length of %s is %d\n", sp, sp, strlen(sp));
|
1997-09-13 05:15:46 +02:00
|
|
|
#endif
|
1997-09-24 19:53:53 +02:00
|
|
|
len += strlen(sp);
|
1997-09-13 05:15:46 +02:00
|
|
|
};
|
1997-09-24 19:53:53 +02:00
|
|
|
len += nlist;
|
1997-09-13 05:15:46 +02:00
|
|
|
|
1997-09-24 19:53:53 +02:00
|
|
|
s = (char*) palloc(len+1);
|
1997-09-13 05:15:46 +02:00
|
|
|
*s = '\0';
|
|
|
|
|
|
|
|
l = list;
|
|
|
|
while(l != NIL) {
|
1997-09-25 16:11:42 +02:00
|
|
|
v = (Value *)lfirst(l);
|
|
|
|
sp = v->val.str;
|
1997-09-13 05:15:46 +02:00
|
|
|
l = lnext(l);
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf( "length of %s is %d\n", sp, strlen(sp));
|
|
|
|
#endif
|
|
|
|
strcat(s,sp);
|
1997-09-24 19:53:53 +02:00
|
|
|
if (l != NIL) strcat(s," ");
|
1997-09-13 05:15:46 +02:00
|
|
|
};
|
1997-09-24 19:53:53 +02:00
|
|
|
*(s+len) = '\0';
|
1997-09-13 05:15:46 +02:00
|
|
|
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf( "flattened string is \"%s\"\n", s);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return(s);
|
|
|
|
} /* FlattenStringList() */
|
|
|
|
|
|
|
|
/* makeConstantList()
|
|
|
|
* Convert constant value node into string node.
|
|
|
|
*/
|
|
|
|
static List *
|
|
|
|
makeConstantList( A_Const *n)
|
|
|
|
{
|
|
|
|
char *defval = NULL;
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf( "in AexprConst\n");
|
|
|
|
#endif
|
|
|
|
if (nodeTag(n) != T_A_Const) {
|
|
|
|
elog(WARN,"Cannot handle non-constant parameter",NULL);
|
|
|
|
|
|
|
|
} 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);
|
|
|
|
|
|
|
|
} 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);
|
|
|
|
|
|
|
|
} 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, "'");
|
|
|
|
|
|
|
|
} else {
|
|
|
|
elog(WARN,"Internal error: cannot encode node",NULL);
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
printf( "AexprConst argument is \"%s\"\n", defval);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return( lcons( makeString(defval), NIL));
|
|
|
|
} /* makeConstantList() */
|