From: Massimo Dal Zotto
authorMarc G. Fournier
Tue, 25 Aug 1998 21:25:46 +0000 (21:25 +0000)
committerMarc G. Fournier
Tue, 25 Aug 1998 21:25:46 +0000 (21:25 +0000)
> sequence.patch
>
>       adds the missing setval command to sequences. Owner of sequences
>       can now set the last value to any value between min and max
>       without recreating the sequence. This is useful after loading
>       data from external files.

src/backend/commands/sequence.c
src/backend/parser/parse_func.c
src/include/catalog/pg_proc.h
src/include/commands/sequence.h

index f28ec52b0099faa18a407e9730b6c0a784e11465..20f9bef503a2de9a98ec2da2adbea1506347867e 100644 (file)
@@ -9,6 +9,7 @@
 #include 
 
 #include 
+#include 
 
 #include 
 #include 
@@ -18,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define SEQ_MAGIC    0x1717
 
@@ -311,6 +313,52 @@ currval(struct varlena * seqin)
 
 }
 
+int4
+setval(struct varlena * seqin, int4 next)
+{
+   char    *seqname = textout(seqin);
+   SeqTable    elm;
+   Buffer  buf;
+   SequenceTupleForm seq;
+   ItemPointerData iptr;
+
+#ifndef NO_SECURITY
+   if (pg_aclcheck(seqname, getpgusername(), ACL_WR) != ACLCHECK_OK)
+       elog(ERROR, "%s.setval: you don't have permissions to set sequence %s",
+            seqname, seqname);
+#endif
+
+   /* open and WIntentLock sequence */
+   elm = init_sequence ("setval", seqname);
+   seq = read_info ("setval", elm, &buf);  /* lock page and read tuple */
+
+   if ( seq->cache_value != 1 ) {
+       elog (ERROR, "%s.setval: can't set value of sequence %s, cache != 1",
+             seqname, seqname);
+   }
+
+   if ((next < seq->min_value) || (next > seq->max_value)) {
+       elog (ERROR, "%s.setval: value %d is of of bounds (%d,%d)",
+             seqname, next, seq->min_value, seq->max_value);
+   }
+
+   /* save info in local cache */
+   elm->last = next;           /* last returned number */
+   elm->cached = next;         /* last cached number */
+
+   /* save info in sequence relation */
+   seq->last_value = next;     /* last fetched number */
+   seq->is_called = 't';
+
+   if ( WriteBuffer (buf) == STATUS_ERROR )
+       elog (ERROR, "%s.settval: WriteBuffer failed", seqname);
+
+   ItemPointerSet(&iptr, 0, FirstOffsetNumber);
+   RelationUnsetSingleWLockPage (elm->rel, &iptr);
+
+   return (next);
+}
+
 static SequenceTupleForm
 read_info(char *caller, SeqTable elm, Buffer *buf)
 {
index 4b02a1f344f004cfc1c06b046d476f5bbcd1d682..88871fa3eeff0c3fe55055c24d31b132c3e5d52e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.25 1998/08/19 02:02:20 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.26 1998/08/25 21:25:42 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -427,7 +427,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
     * Sequence handling.
     */
    if (funcid == F_NEXTVAL ||
-       funcid == F_CURRVAL)
+       funcid == F_CURRVAL ||
+       funcid == F_SETVAL)
    {
        Const      *seq;
        char       *seqrel;
@@ -435,7 +436,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
        int32       aclcheck_result = -1;
        extern text *lower(text *string);
 
-       Assert(length(fargs) == 1);
+       Assert(length(fargs) == ((funcid == F_SETVAL) ? 2 : 1));
        seq = (Const *) lfirst(fargs);
        if (!IsA((Node *) seq, Const))
            elog(ERROR, "Only constant sequence names are acceptable for function '%s'", funcname);
@@ -445,7 +446,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
        seqrel = textout(seqname);
 
        if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
-              ((funcid == F_NEXTVAL) ? ACL_WR : ACL_RD)))
+              (((funcid == F_NEXTVAL) || (funcid == F_SETVAL)) ? 
+               ACL_WR : ACL_RD)))
            != ACLCHECK_OK)
            elog(ERROR, "%s.%s: %s",
              seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
@@ -454,6 +456,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 
        if (funcid == F_NEXTVAL && pstate->p_in_where_clause)
            elog(ERROR, "Sequence function nextval is not allowed in WHERE clauses");
+       if (funcid == F_SETVAL && pstate->p_in_where_clause)
+           elog(ERROR, "Sequence function setval is not allowed in WHERE clauses");
    }
 
    expr = makeNode(Expr);
index 902b057f172ebc9186851077b36644a38382f39a..88f304ea1ade4894bff1d59fe330e8b08d0b0447 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.67 1998/08/24 01:38:08 momjian Exp $
+ * $Id: pg_proc.h,v 1.68 1998/08/25 21:25:44 scrappy Exp $
  *
  * NOTES
  *   The script catalog/genbki.sh reads this file and generates .bki
@@ -2029,6 +2029,8 @@ DATA(insert OID =  1317 (  nextval       PGUID 11 f t f 1 f 23 "25" 100 0 0 100  fo
 DESCR("sequence next value");
 DATA(insert OID =  1319 (  currval    PGUID 11 f t f 1 f 23 "25" 100 0 0 100  foo bar ));
 DESCR("sequence current value");
+DATA(insert OID =  1618 (  setval     PGUID 11 f t f 2 f 23 "25 23" 100 0 0 100  foo bar ));
+DESCR("sequence set value");
 
 /* for multi-byte support */
 DATA(insert OID = 1039 (  getdatabaseencoding     PGUID 11 f t f 0 f 19 "0" 100 0 0 100  foo bar ));
index 2ffa42639b46ac54b004652e20d1b92e4930d5c8..f2186cccda31656b9cfde18a47548c9f00fc309e 100644 (file)
@@ -30,6 +30,7 @@
 extern void DefineSequence(CreateSeqStmt *stmt);
 extern int4 nextval(struct varlena * seqname);
 extern int4 currval(struct varlena * seqname);
+extern int4 setval (struct varlena * seqname, int4 next);
 extern void CloseSequences(void);
 
 #endif                         /* SEQUENCE_H */