aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/analyze.c39
-rw-r--r--src/backend/parser/gram.y57
2 files changed, 91 insertions, 5 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 2cbe2c4a66d..ce96e13bb10 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.23 1997/03/12 20:51:33 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.24 1997/04/02 04:00:55 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,14 +29,18 @@
#include "utils/palloc.h"
#include "utils/mcxt.h"
#include "utils/syscache.h"
+#include "utils/acl.h"
#include "parser/parse_query.h"
#include "parser/parse_state.h"
#include "nodes/makefuncs.h" /* for makeResdom(), etc. */
#include "nodes/nodeFuncs.h"
+#include "commands/sequence.h"
#include "optimizer/clauses.h"
#include "access/heapam.h"
+#include "miscadmin.h"
+
#include "port-protos.h" /* strdup() */
/* convert the parse tree into a query tree */
@@ -65,6 +69,7 @@ static List *transformTargetList(ParseState *pstate, List *targetlist);
static TargetEntry *make_targetlist_expr(ParseState *pstate,
char *colname, Node *expr,
List *arrayRef);
+static bool inWhereClause = false;
static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
static List *transformGroupClause(ParseState *pstate, List *grouplist,
List *targetlist);
@@ -133,6 +138,8 @@ parse_analyze(List *pl)
result = malloc(sizeof(QueryTreeList));
result->len = length(pl);
result->qtrees = (Query**)malloc(result->len * sizeof(Query*));
+
+ inWhereClause = false; /* to avoid nextval(sequence) in WHERE */
while(pl!=NIL) {
pstate = makeParseState();
@@ -1446,7 +1453,9 @@ transformWhereClause(ParseState *pstate, Node *a_expr)
if (a_expr == NULL)
return (Node *)NULL; /* no qualifiers */
+ inWhereClause = true;
qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
+ inWhereClause = false;
if (exprType(qual) != BOOLOID) {
elog(WARN,
"where clause must return type bool, not %s",
@@ -2182,6 +2191,34 @@ ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
}
}
+ /*
+ * Sequence handling.
+ */
+ if ( funcid == SeqNextValueRegProcedure ||
+ funcid == SeqCurrValueRegProcedure )
+ {
+ Const *seq;
+ char *seqrel;
+ int32 aclcheck_result = -1;
+
+ Assert ( length(fargs) == 1 );
+ seq = (Const*)lfirst(fargs);
+ if ( ! IsA ((Node*)seq, Const) )
+ elog (WARN, "%s: only constant sequence names are acceptable", funcname);
+ seqrel = textout ((struct varlena *) (seq->constvalue));
+
+ if ( ( aclcheck_result = pg_aclcheck (seqrel, GetPgUserName(),
+ ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)) )
+ != ACLCHECK_OK )
+ elog (WARN, "%s.%s: %s",
+ seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
+
+ pfree (seqrel);
+
+ if ( funcid == SeqNextValueRegProcedure && inWhereClause )
+ elog (WARN, "nextval of a sequence in WHERE disallowed");
+ }
+
expr = makeNode(Expr);
expr->typeOid = rettype;
expr->opType = FUNC_EXPR;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0b62bdb8433..15fc14e9b13 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.27 1997/03/26 02:52:49 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.28 1997/04/02 04:01:03 vadim Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -100,7 +100,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%type <node> stmt,
AddAttrStmt, ClosePortalStmt,
- CopyStmt, CreateStmt, DefineStmt, DestroyStmt,
+ CopyStmt, CreateStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
ExtendStmt, FetchStmt, GrantStmt,
IndexStmt, MoveStmt, ListenStmt, OptimizableStmt,
ProcedureStmt, PurgeStmt,
@@ -141,6 +141,9 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
%type <ival> OptLocation, opt_move_where, fetch_how_many
+%type <list> OptSeqList
+%type <defelt> OptSeqElem
+
%type <dstmt> def_rest
%type <pstmt> purge_quals
%type <astmt> insert_rest
@@ -190,7 +193,7 @@ static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
SELECT, SET, SETOF, STDIN, STDOUT, STORE,
TABLE, TO, TRANSACTION, UNIQUE, UPDATE, USING, VACUUM, VALUES
VERBOSE, VERSION, VIEW, WHERE, WITH, WORK
-%token EXECUTE, RECIPE, EXPLAIN, LIKE
+%token EXECUTE, RECIPE, EXPLAIN, LIKE, SEQUENCE
/* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT, SCONST, Op
@@ -243,6 +246,7 @@ stmt : AddAttrStmt
| ClosePortalStmt
| CopyStmt
| CreateStmt
+ | CreateSeqStmt
| ClusterStmt
| DefineStmt
| DestroyStmt
@@ -427,6 +431,43 @@ OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
/*****************************************************************************
*
+ * QUERY :
+ * CREATE SEQUENCE seqname
+ *
+ *****************************************************************************/
+
+CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
+ {
+ CreateSeqStmt *n = makeNode(CreateSeqStmt);
+ n->seqname = $3;
+ n->options = $4;
+ $$ = (Node *)n;
+ }
+ ;
+
+OptSeqList:
+ OptSeqList OptSeqElem
+ { $$ = lappend($1, $2); }
+ | { $$ = NIL; }
+ ;
+
+OptSeqElem: IDENT NumConst
+ {
+ $$ = makeNode(DefElem);
+ $$->defname = $1;
+ $$->arg = (Node *)$2;
+ }
+ | IDENT
+ {
+ $$ = makeNode(DefElem);
+ $$->defname = $1;
+ $$->arg = (Node *)NULL;
+ }
+ ;
+
+
+/*****************************************************************************
+ *
* QUERY :
* define (type,operator,aggregate)
*
@@ -501,10 +542,18 @@ def_arg: Id { $$ = (Node *)makeString($1); }
*
*****************************************************************************/
-DestroyStmt: DROP TABLE relation_name_list
+DestroyStmt: DROP TABLE relation_name_list
+ {
+ DestroyStmt *n = makeNode(DestroyStmt);
+ n->relNames = $3;
+ n->sequence = false;
+ $$ = (Node *)n;
+ }
+ | DROP SEQUENCE relation_name_list
{
DestroyStmt *n = makeNode(DestroyStmt);
n->relNames = $3;
+ n->sequence = true;
$$ = (Node *)n;
}
;