From 9729f6ca0dfe46daeff8c23f7a08c698d034d949 Mon Sep 17 00:00:00 2001
From: "Vadim B. Mikheev" <vadim4o@yahoo.com>
Date: Wed, 2 Apr 1997 04:01:03 +0000
Subject: [PATCH] CREATE/DROP SEQUENCE ... Check nextval/currval permission in
 analyze.c.

---
 src/backend/parser/analyze.c | 39 +++++++++++++++++++++++-
 src/backend/parser/gram.y    | 57 +++++++++++++++++++++++++++++++++---
 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
@@ -425,6 +429,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 :
@@ -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;
 		}
 	;
-- 
GitLab