From 8e9d69d6ac76001458f0c190a35990b23abf81de Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Tue, 25 Aug 1998 21:25:46 +0000 Subject: [PATCH] From: Massimo Dal Zotto > 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 | 48 +++++++++++++++++++++++++++++++++ src/backend/parser/parse_func.c | 12 ++++++--- src/include/catalog/pg_proc.h | 4 ++- src/include/commands/sequence.h | 1 + 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index f28ec52b009..20f9bef503a 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -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) { diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 4b02a1f344f..88871fa3eef 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -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); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 902b057f172..88f304ea1ad 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -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 )); diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h index 2ffa42639b4..f2186cccda3 100644 --- a/src/include/commands/sequence.h +++ b/src/include/commands/sequence.h @@ -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 */