aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/Makefile1
-rw-r--r--src/backend/catalog/dependency.c6
-rw-r--r--src/backend/catalog/information_schema.sql13
-rw-r--r--src/backend/catalog/system_views.sql16
-rw-r--r--src/backend/commands/sequence.c381
-rw-r--r--src/backend/utils/cache/syscache.c12
-rw-r--r--src/bin/pg_dump/pg_dump.c22
-rw-r--r--src/include/catalog/catversion.h2
-rw-r--r--src/include/catalog/indexing.h3
-rw-r--r--src/include/catalog/pg_sequence.h30
-rw-r--r--src/include/commands/sequence.h29
-rw-r--r--src/include/utils/syscache.h1
-rw-r--r--src/test/regress/expected/rules.out18
-rw-r--r--src/test/regress/expected/sanity_check.out1
-rw-r--r--src/test/regress/expected/sequence.out33
-rw-r--r--src/test/regress/expected/updatable_views.out93
-rw-r--r--src/test/regress/sql/sequence.sql8
-rw-r--r--src/test/regress/sql/updatable_views.sql2
18 files changed, 403 insertions, 268 deletions
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 2d5ac09bece..cd38c8ab3ff 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -42,6 +42,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_foreign_table.h pg_policy.h pg_replication_origin.h \
pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
pg_collation.h pg_partitioned_table.h pg_range.h pg_transform.h \
+ pg_sequence.h \
toasting.h indexing.h \
)
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 0cdd1c5c6cb..18a14bf146d 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -66,6 +66,7 @@
#include "commands/proclang.h"
#include "commands/schemacmds.h"
#include "commands/seclabel.h"
+#include "commands/sequence.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
#include "nodes/nodeFuncs.h"
@@ -1114,6 +1115,11 @@ doDeletion(const ObjectAddress *object, int flags)
else
heap_drop_with_catalog(object->objectId);
}
+
+ /* for a sequence, in addition to dropping the heap, also
+ * delete pg_sequence tuple */
+ if (relKind == RELKIND_SEQUENCE)
+ DeleteSequenceTuple(object->objectId);
break;
}
diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
index 00550eb8044..182d2d06746 100644
--- a/src/backend/catalog/information_schema.sql
+++ b/src/backend/catalog/information_schema.sql
@@ -1535,15 +1535,16 @@ CREATE VIEW sequences AS
CAST(64 AS cardinal_number) AS numeric_precision,
CAST(2 AS cardinal_number) AS numeric_precision_radix,
CAST(0 AS cardinal_number) AS numeric_scale,
- CAST(p.start_value AS character_data) AS start_value,
- CAST(p.minimum_value AS character_data) AS minimum_value,
- CAST(p.maximum_value AS character_data) AS maximum_value,
- CAST(p.increment AS character_data) AS increment,
- CAST(CASE WHEN p.cycle_option THEN 'YES' ELSE 'NO' END AS yes_or_no) AS cycle_option
- FROM pg_namespace nc, pg_class c, LATERAL pg_sequence_parameters(c.oid) p
+ CAST(s.seqstart AS character_data) AS start_value,
+ CAST(s.seqmin AS character_data) AS minimum_value,
+ CAST(s.seqmax AS character_data) AS maximum_value,
+ CAST(s.seqincrement AS character_data) AS increment,
+ CAST(CASE WHEN s.seqcycle THEN 'YES' ELSE 'NO' END AS yes_or_no) AS cycle_option
+ FROM pg_namespace nc, pg_class c, pg_sequence s
WHERE c.relnamespace = nc.oid
AND c.relkind = 'S'
AND (NOT pg_is_other_temp_schema(nc.oid))
+ AND c.oid = s.seqrelid
AND (pg_has_role(c.relowner, 'USAGE')
OR has_sequence_privilege(c.oid, 'SELECT, UPDATE, USAGE') );
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 48e7c4b7f95..649cef86c53 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -169,15 +169,15 @@ CREATE OR REPLACE VIEW pg_sequences AS
N.nspname AS schemaname,
C.relname AS sequencename,
pg_get_userbyid(C.relowner) AS sequenceowner,
- p.start_value AS start_value,
- p.minimum_value AS min_value,
- p.maximum_value AS max_value,
- p.increment AS increment_by,
- p.cycle_option AS cycle,
- p.cache_size AS cache_size,
+ S.seqstart AS start_value,
+ S.seqmin AS min_value,
+ S.seqmax AS max_value,
+ S.seqincrement AS increment_by,
+ S.seqcycle AS cycle,
+ S.seqcache AS cache_size,
pg_sequence_last_value(C.oid) AS last_value
- FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace),
- LATERAL pg_sequence_parameters(C.oid) p
+ FROM pg_sequence S JOIN pg_class C ON (C.oid = S.seqrelid)
+ LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE NOT pg_is_other_temp_schema(N.oid)
AND relkind = 'S';
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index d953b4408bd..cdd32bc17e0 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -22,8 +22,10 @@
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/dependency.h"
+#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
+#include "catalog/pg_sequence.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/sequence.h"
@@ -74,7 +76,7 @@ typedef struct SeqTableData
int64 cached; /* last value already cached for nextval */
/* if last != cached, we have not used up all the cached values */
int64 increment; /* copy of sequence's increment field */
- /* note that increment is zero until we first do read_seq_tuple() */
+ /* note that increment is zero until we first do nextval_internal() */
} SeqTableData;
typedef SeqTableData *SeqTable;
@@ -92,10 +94,11 @@ static int64 nextval_internal(Oid relid);
static Relation open_share_lock(SeqTable seq);
static void create_seq_hashtable(void);
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel);
-static Form_pg_sequence read_seq_tuple(SeqTable elm, Relation rel,
- Buffer *buf, HeapTuple seqtuple);
+static Form_pg_sequence_data read_seq_tuple(Relation rel,
+ Buffer *buf, HeapTuple seqdatatuple);
static void init_params(ParseState *pstate, List *options, bool isInit,
- Form_pg_sequence new, List **owned_by);
+ Form_pg_sequence seqform,
+ Form_pg_sequence_data seqdataform, List **owned_by);
static void do_setval(Oid relid, int64 next, bool iscalled);
static void process_owned_by(Relation seqrel, List *owned_by);
@@ -107,7 +110,8 @@ static void process_owned_by(Relation seqrel, List *owned_by);
ObjectAddress
DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
{
- FormData_pg_sequence new;
+ FormData_pg_sequence seqform;
+ FormData_pg_sequence_data seqdataform;
List *owned_by;
CreateStmt *stmt = makeNode(CreateStmt);
Oid seqoid;
@@ -117,8 +121,9 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
TupleDesc tupDesc;
Datum value[SEQ_COL_LASTCOL];
bool null[SEQ_COL_LASTCOL];
+ Datum pgs_values[Natts_pg_sequence];
+ bool pgs_nulls[Natts_pg_sequence];
int i;
- NameData name;
/* Unlogged sequences are not implemented -- not clear if useful. */
if (seq->sequence->relpersistence == RELPERSISTENCE_UNLOGGED)
@@ -145,7 +150,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
}
/* Check and set all option values */
- init_params(pstate, seq->options, true, &new, &owned_by);
+ init_params(pstate, seq->options, true, &seqform, &seqdataform, &owned_by);
/*
* Create relation (and fill value[] and null[] for the tuple)
@@ -171,52 +176,16 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
switch (i)
{
- case SEQ_COL_NAME:
- coldef->typeName = makeTypeNameFromOid(NAMEOID, -1);
- coldef->colname = "sequence_name";
- namestrcpy(&name, seq->sequence->relname);
- value[i - 1] = NameGetDatum(&name);
- break;
case SEQ_COL_LASTVAL:
coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "last_value";
- value[i - 1] = Int64GetDatumFast(new.last_value);
- break;
- case SEQ_COL_STARTVAL:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "start_value";
- value[i - 1] = Int64GetDatumFast(new.start_value);
- break;
- case SEQ_COL_INCBY:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "increment_by";
- value[i - 1] = Int64GetDatumFast(new.increment_by);
- break;
- case SEQ_COL_MAXVALUE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "max_value";
- value[i - 1] = Int64GetDatumFast(new.max_value);
- break;
- case SEQ_COL_MINVALUE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "min_value";
- value[i - 1] = Int64GetDatumFast(new.min_value);
- break;
- case SEQ_COL_CACHE:
- coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
- coldef->colname = "cache_value";
- value[i - 1] = Int64GetDatumFast(new.cache_value);
+ value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
break;
case SEQ_COL_LOG:
coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
coldef->colname = "log_cnt";
value[i - 1] = Int64GetDatum((int64) 0);
break;
- case SEQ_COL_CYCLE:
- coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
- coldef->colname = "is_cycled";
- value[i - 1] = BoolGetDatum(new.is_cycled);
- break;
case SEQ_COL_CALLED:
coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
coldef->colname = "is_called";
@@ -251,6 +220,27 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
heap_close(rel, NoLock);
+ /* fill in pg_sequence */
+ rel = heap_open(SequenceRelationId, RowExclusiveLock);
+ tupDesc = RelationGetDescr(rel);
+
+ memset(pgs_nulls, 0, sizeof(pgs_nulls));
+
+ pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
+ pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
+ pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
+ pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
+ pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
+ pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
+ pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
+
+ tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
+ simple_heap_insert(rel, tuple);
+ CatalogUpdateIndexes(rel, tuple);
+
+ heap_freetuple(tuple);
+ heap_close(rel, RowExclusiveLock);
+
return address;
}
@@ -271,10 +261,13 @@ ResetSequence(Oid seq_relid)
{
Relation seq_rel;
SeqTable elm;
- Form_pg_sequence seq;
+ Form_pg_sequence_data seq;
Buffer buf;
- HeapTupleData seqtuple;
+ HeapTupleData seqdatatuple;
HeapTuple tuple;
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
+ int64 startv;
/*
* Read the old sequence. This does a bit more work than really
@@ -282,12 +275,19 @@ ResetSequence(Oid seq_relid)
* indeed a sequence.
*/
init_sequence(seq_relid, &elm, &seq_rel);
- (void) read_seq_tuple(elm, seq_rel, &buf, &seqtuple);
+ (void) read_seq_tuple(seq_rel, &buf, &seqdatatuple);
+
+ pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seq_relid));
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", seq_relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+ startv = pgsform->seqstart;
+ ReleaseSysCache(pgstuple);
/*
* Copy the existing sequence tuple.
*/
- tuple = heap_copytuple(&seqtuple);
+ tuple = heap_copytuple(&seqdatatuple);
/* Now we're done with the old page */
UnlockReleaseBuffer(buf);
@@ -296,8 +296,8 @@ ResetSequence(Oid seq_relid)
* Modify the copied tuple to execute the restart (compare the RESTART
* action in AlterSequence)
*/
- seq = (Form_pg_sequence) GETSTRUCT(tuple);
- seq->last_value = seq->start_value;
+ seq = (Form_pg_sequence_data) GETSTRUCT(tuple);
+ seq->last_value = startv;
seq->is_called = false;
seq->log_cnt = 0;
@@ -410,11 +410,14 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
SeqTable elm;
Relation seqrel;
Buffer buf;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
- FormData_pg_sequence new;
+ HeapTupleData seqdatatuple;
+ Form_pg_sequence seqform;
+ Form_pg_sequence_data seqdata;
+ FormData_pg_sequence_data newseqdata;
List *owned_by;
ObjectAddress address;
+ Relation rel;
+ HeapTuple tuple;
/* Open and lock sequence. */
relid = RangeVarGetRelid(stmt->sequence, AccessShareLock, stmt->missing_ok);
@@ -434,13 +437,22 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
stmt->sequence->relname);
/* lock page' buffer and read tuple into new sequence structure */
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ seqdata = read_seq_tuple(seqrel, &buf, &seqdatatuple);
/* Copy old values of options into workspace */
- memcpy(&new, seq, sizeof(FormData_pg_sequence));
+ memcpy(&newseqdata, seqdata, sizeof(FormData_pg_sequence_data));
+
+ rel = heap_open(SequenceRelationId, RowExclusiveLock);
+ tuple = SearchSysCacheCopy1(SEQRELID,
+ ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for sequence %u",
+ relid);
+
+ seqform = (Form_pg_sequence) GETSTRUCT(tuple);
/* Check and set new values */
- init_params(pstate, stmt->options, false, &new, &owned_by);
+ init_params(pstate, stmt->options, false, seqform, &newseqdata, &owned_by);
/* Clear local cache so that we don't think we have cached numbers */
/* Note that we do not change the currval() state */
@@ -453,7 +465,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
/* Now okay to update the on-disk tuple */
START_CRIT_SECTION();
- memcpy(seq, &new, sizeof(FormData_pg_sequence));
+ memcpy(seqdata, &newseqdata, sizeof(FormData_pg_sequence_data));
MarkBufferDirty(buf);
@@ -470,7 +482,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
xlrec.node = seqrel->rd_node;
XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
- XLogRegisterData((char *) seqtuple.t_data, seqtuple.t_len);
+ XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
@@ -491,9 +503,30 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
relation_close(seqrel, NoLock);
+ simple_heap_update(rel, &tuple->t_self, tuple);
+ CatalogUpdateIndexes(rel, tuple);
+ heap_close(rel, RowExclusiveLock);
+
return address;
}
+void
+DeleteSequenceTuple(Oid relid)
+{
+ Relation rel;
+ HeapTuple tuple;
+
+ rel = heap_open(SequenceRelationId, RowExclusiveLock);
+
+ tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+
+ simple_heap_delete(rel, &tuple->t_self);
+
+ ReleaseSysCache(tuple);
+ heap_close(rel, RowExclusiveLock);
+}
/*
* Note: nextval with a text argument is no longer exported as a pg_proc
@@ -537,8 +570,10 @@ nextval_internal(Oid relid)
Relation seqrel;
Buffer buf;
Page page;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
+ HeapTupleData seqdatatuple;
+ Form_pg_sequence_data seq;
int64 incby,
maxv,
minv,
@@ -549,6 +584,7 @@ nextval_internal(Oid relid)
int64 result,
next,
rescnt = 0;
+ bool cycle;
bool logit = false;
/* open and AccessShareLock sequence */
@@ -582,15 +618,24 @@ nextval_internal(Oid relid)
return elm->last;
}
+ pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+ incby = pgsform->seqincrement;
+ maxv = pgsform->seqmax;
+ minv = pgsform->seqmin;
+ cache = pgsform->seqcache;
+ cycle = pgsform->seqcycle;
+ ReleaseSysCache(pgstuple);
+
/* lock page' buffer and read tuple */
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
page = BufferGetPage(buf);
+ elm->increment = incby;
last = next = result = seq->last_value;
- incby = seq->increment_by;
- maxv = seq->max_value;
- minv = seq->min_value;
- fetch = cache = seq->cache_value;
+ fetch = cache;
log = seq->log_cnt;
if (!seq->is_called)
@@ -641,7 +686,7 @@ nextval_internal(Oid relid)
{
if (rescnt > 0)
break; /* stop fetching */
- if (!seq->is_cycled)
+ if (!cycle)
{
char buf[100];
@@ -664,7 +709,7 @@ nextval_internal(Oid relid)
{
if (rescnt > 0)
break; /* stop fetching */
- if (!seq->is_cycled)
+ if (!cycle)
{
char buf[100];
@@ -747,7 +792,7 @@ nextval_internal(Oid relid)
xlrec.node = seqrel->rd_node;
XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
- XLogRegisterData((char *) seqtuple.t_data, seqtuple.t_len);
+ XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
@@ -853,8 +898,12 @@ do_setval(Oid relid, int64 next, bool iscalled)
SeqTable elm;
Relation seqrel;
Buffer buf;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
+ HeapTupleData seqdatatuple;
+ Form_pg_sequence_data seq;
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
+ int64 maxv,
+ minv;
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
@@ -865,6 +914,14 @@ do_setval(Oid relid, int64 next, bool iscalled)
errmsg("permission denied for sequence %s",
RelationGetRelationName(seqrel))));
+ pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+ maxv = pgsform->seqmax;
+ minv = pgsform->seqmin;
+ ReleaseSysCache(pgstuple);
+
/* read-only transactions may only modify temp sequences */
if (!seqrel->rd_islocaltemp)
PreventCommandIfReadOnly("setval()");
@@ -877,17 +934,17 @@ do_setval(Oid relid, int64 next, bool iscalled)
PreventCommandIfParallelMode("setval()");
/* lock page' buffer and read tuple */
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
- if ((next < seq->min_value) || (next > seq->max_value))
+ if ((next < minv) || (next > maxv))
{
char bufv[100],
bufm[100],
bufx[100];
snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, seq->min_value);
- snprintf(bufx, sizeof(bufx), INT64_FORMAT, seq->max_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
+ snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
@@ -930,7 +987,7 @@ do_setval(Oid relid, int64 next, bool iscalled)
xlrec.node = seqrel->rd_node;
XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
- XLogRegisterData((char *) seqtuple.t_data, seqtuple.t_len);
+ XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
@@ -1064,7 +1121,7 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
elm->filenode = InvalidOid;
elm->lxid = InvalidLocalTransactionId;
elm->last_valid = false;
- elm->last = elm->cached = elm->increment = 0;
+ elm->last = elm->cached = 0;
}
/*
@@ -1099,18 +1156,18 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
* Given an opened sequence relation, lock the page buffer and find the tuple
*
* *buf receives the reference to the pinned-and-ex-locked buffer
- * *seqtuple receives the reference to the sequence tuple proper
+ * *seqdatatuple receives the reference to the sequence tuple proper
* (this arg should point to a local variable of type HeapTupleData)
*
* Function's return value points to the data payload of the tuple
*/
-static Form_pg_sequence
-read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
+static Form_pg_sequence_data
+read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
{
Page page;
ItemId lp;
sequence_magic *sm;
- Form_pg_sequence seq;
+ Form_pg_sequence_data seq;
*buf = ReadBuffer(rel, 0);
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
@@ -1125,9 +1182,9 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
lp = PageGetItemId(page, FirstOffsetNumber);
Assert(ItemIdIsNormal(lp));
- /* Note we currently only bother to set these two fields of *seqtuple */
- seqtuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
- seqtuple->t_len = ItemIdGetLength(lp);
+ /* Note we currently only bother to set these two fields of *seqdatatuple */
+ seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
+ seqdatatuple->t_len = ItemIdGetLength(lp);
/*
* Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
@@ -1137,19 +1194,16 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
* bit update, ie, don't bother to WAL-log it, since we can certainly do
* this again if the update gets lost.
*/
- Assert(!(seqtuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
- if (HeapTupleHeaderGetRawXmax(seqtuple->t_data) != InvalidTransactionId)
+ Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
+ if (HeapTupleHeaderGetRawXmax(seqdatatuple->t_data) != InvalidTransactionId)
{
- HeapTupleHeaderSetXmax(seqtuple->t_data, InvalidTransactionId);
- seqtuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
- seqtuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
+ HeapTupleHeaderSetXmax(seqdatatuple->t_data, InvalidTransactionId);
+ seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
+ seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
MarkBufferDirtyHint(*buf, true);
}
- seq = (Form_pg_sequence) GETSTRUCT(seqtuple);
-
- /* this is a handy place to update our copy of the increment */
- elm->increment = seq->increment_by;
+ seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
return seq;
}
@@ -1164,7 +1218,8 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
*/
static void
init_params(ParseState *pstate, List *options, bool isInit,
- Form_pg_sequence new, List **owned_by)
+ Form_pg_sequence seqform,
+ Form_pg_sequence_data seqdataform, List **owned_by)
{
DefElem *start_value = NULL;
DefElem *restart_value = NULL;
@@ -1263,69 +1318,69 @@ init_params(ParseState *pstate, List *options, bool isInit,
* would affect future nextval allocations.
*/
if (isInit)
- new->log_cnt = 0;
+ seqdataform->log_cnt = 0;
/* INCREMENT BY */
if (increment_by != NULL)
{
- new->increment_by = defGetInt64(increment_by);
- if (new->increment_by == 0)
+ seqform->seqincrement = defGetInt64(increment_by);
+ if (seqform->seqincrement == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("INCREMENT must not be zero")));
- new->log_cnt = 0;
+ seqdataform->log_cnt = 0;
}
else if (isInit)
- new->increment_by = 1;
+ seqform->seqincrement = 1;
/* CYCLE */
if (is_cycled != NULL)
{
- new->is_cycled = intVal(is_cycled->arg);
- Assert(BoolIsValid(new->is_cycled));
- new->log_cnt = 0;
+ seqform->seqcycle = intVal(is_cycled->arg);
+ Assert(BoolIsValid(seqform->seqcycle));
+ seqdataform->log_cnt = 0;
}
else if (isInit)
- new->is_cycled = false;
+ seqform->seqcycle = false;
/* MAXVALUE (null arg means NO MAXVALUE) */
if (max_value != NULL && max_value->arg)
{
- new->max_value = defGetInt64(max_value);
- new->log_cnt = 0;
+ seqform->seqmax = defGetInt64(max_value);
+ seqdataform->log_cnt = 0;
}
else if (isInit || max_value != NULL)
{
- if (new->increment_by > 0)
- new->max_value = SEQ_MAXVALUE; /* ascending seq */
+ if (seqform->seqincrement > 0)
+ seqform->seqmax = SEQ_MAXVALUE; /* ascending seq */
else
- new->max_value = -1; /* descending seq */
- new->log_cnt = 0;
+ seqform->seqmax = -1; /* descending seq */
+ seqdataform->log_cnt = 0;
}
/* MINVALUE (null arg means NO MINVALUE) */
if (min_value != NULL && min_value->arg)
{
- new->min_value = defGetInt64(min_value);
- new->log_cnt = 0;
+ seqform->seqmin = defGetInt64(min_value);
+ seqdataform->log_cnt = 0;
}
else if (isInit || min_value != NULL)
{
- if (new->increment_by > 0)
- new->min_value = 1; /* ascending seq */
+ if (seqform->seqincrement > 0)
+ seqform->seqmin = 1; /* ascending seq */
else
- new->min_value = SEQ_MINVALUE; /* descending seq */
- new->log_cnt = 0;
+ seqform->seqmin = SEQ_MINVALUE; /* descending seq */
+ seqdataform->log_cnt = 0;
}
/* crosscheck min/max */
- if (new->min_value >= new->max_value)
+ if (seqform->seqmin >= seqform->seqmax)
{
char bufm[100],
bufx[100];
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
- snprintf(bufx, sizeof(bufx), INT64_FORMAT, new->max_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
+ snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("MINVALUE (%s) must be less than MAXVALUE (%s)",
@@ -1334,35 +1389,35 @@ init_params(ParseState *pstate, List *options, bool isInit,
/* START WITH */
if (start_value != NULL)
- new->start_value = defGetInt64(start_value);
+ seqform->seqstart = defGetInt64(start_value);
else if (isInit)
{
- if (new->increment_by > 0)
- new->start_value = new->min_value; /* ascending seq */
+ if (seqform->seqincrement > 0)
+ seqform->seqstart = seqform->seqmin; /* ascending seq */
else
- new->start_value = new->max_value; /* descending seq */
+ seqform->seqstart = seqform->seqmax; /* descending seq */
}
/* crosscheck START */
- if (new->start_value < new->min_value)
+ if (seqform->seqstart < seqform->seqmin)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->start_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("START value (%s) cannot be less than MINVALUE (%s)",
bufs, bufm)));
}
- if (new->start_value > new->max_value)
+ if (seqform->seqstart > seqform->seqmax)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->start_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("START value (%s) cannot be greater than MAXVALUE (%s)",
@@ -1373,38 +1428,38 @@ init_params(ParseState *pstate, List *options, bool isInit,
if (restart_value != NULL)
{
if (restart_value->arg != NULL)
- new->last_value = defGetInt64(restart_value);
+ seqdataform->last_value = defGetInt64(restart_value);
else
- new->last_value = new->start_value;
- new->is_called = false;
- new->log_cnt = 0;
+ seqdataform->last_value = seqform->seqstart;
+ seqdataform->is_called = false;
+ seqdataform->log_cnt = 0;
}
else if (isInit)
{
- new->last_value = new->start_value;
- new->is_called = false;
+ seqdataform->last_value = seqform->seqstart;
+ seqdataform->is_called = false;
}
/* crosscheck RESTART (or current value, if changing MIN/MAX) */
- if (new->last_value < new->min_value)
+ if (seqdataform->last_value < seqform->seqmin)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)",
bufs, bufm)));
}
- if (new->last_value > new->max_value)
+ if (seqdataform->last_value > seqform->seqmax)
{
char bufs[100],
bufm[100];
- snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);
- snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value);
+ snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
+ snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)",
@@ -1414,21 +1469,21 @@ init_params(ParseState *pstate, List *options, bool isInit,
/* CACHE */
if (cache_value != NULL)
{
- new->cache_value = defGetInt64(cache_value);
- if (new->cache_value <= 0)
+ seqform->seqcache = defGetInt64(cache_value);
+ if (seqform->seqcache <= 0)
{
char buf[100];
- snprintf(buf, sizeof(buf), INT64_FORMAT, new->cache_value);
+ snprintf(buf, sizeof(buf), INT64_FORMAT, seqform->seqcache);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("CACHE (%s) must be greater than zero",
buf)));
}
- new->log_cnt = 0;
+ seqdataform->log_cnt = 0;
}
else if (isInit)
- new->cache_value = 1;
+ seqform->seqcache = 1;
}
/*
@@ -1528,7 +1583,7 @@ process_owned_by(Relation seqrel, List *owned_by)
/*
- * Return sequence parameters, for use by information schema
+ * Return sequence parameters (formerly for use by information schema)
*/
Datum
pg_sequence_parameters(PG_FUNCTION_ARGS)
@@ -1537,20 +1592,14 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
TupleDesc tupdesc;
Datum values[6];
bool isnull[6];
- SeqTable elm;
- Relation seqrel;
- Buffer buf;
- HeapTupleData seqtuple;
- Form_pg_sequence seq;
-
- /* open and AccessShareLock sequence */
- init_sequence(relid, &elm, &seqrel);
+ HeapTuple pgstuple;
+ Form_pg_sequence pgsform;
if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT | ACL_UPDATE | ACL_USAGE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
- RelationGetRelationName(seqrel))));
+ get_rel_name(relid))));
tupdesc = CreateTemplateTupleDesc(6, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
@@ -1570,17 +1619,19 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
memset(isnull, 0, sizeof(isnull));
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ pgstuple = SearchSysCache1(SEQRELID, relid);
+ if (!HeapTupleIsValid(pgstuple))
+ elog(ERROR, "cache lookup failed for sequence %u", relid);
+ pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
- values[0] = Int64GetDatum(seq->start_value);
- values[1] = Int64GetDatum(seq->min_value);
- values[2] = Int64GetDatum(seq->max_value);
- values[3] = Int64GetDatum(seq->increment_by);
- values[4] = BoolGetDatum(seq->is_cycled);
- values[5] = Int64GetDatum(seq->cache_value);
+ values[0] = Int64GetDatum(pgsform->seqstart);
+ values[1] = Int64GetDatum(pgsform->seqmin);
+ values[2] = Int64GetDatum(pgsform->seqmax);
+ values[3] = Int64GetDatum(pgsform->seqincrement);
+ values[4] = BoolGetDatum(pgsform->seqcycle);
+ values[5] = Int64GetDatum(pgsform->seqcache);
- UnlockReleaseBuffer(buf);
- relation_close(seqrel, NoLock);
+ ReleaseSysCache(pgstuple);
return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
}
@@ -1598,7 +1649,7 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
Relation seqrel;
Buffer buf;
HeapTupleData seqtuple;
- Form_pg_sequence seq;
+ Form_pg_sequence_data seq;
bool is_called;
int64 result;
@@ -1611,7 +1662,7 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
errmsg("permission denied for sequence %s",
RelationGetRelationName(seqrel))));
- seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+ seq = read_seq_tuple(seqrel, &buf, &seqtuple);
is_called = seq->is_called;
result = seq->last_value;
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index a3e0517b940..e87fe0ef548 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -53,6 +53,7 @@
#include "catalog/pg_range.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_seclabel.h"
+#include "catalog/pg_sequence.h"
#include "catalog/pg_shdepend.h"
#include "catalog/pg_shdescription.h"
#include "catalog/pg_shseclabel.h"
@@ -668,6 +669,17 @@ static const struct cachedesc cacheinfo[] = {
},
8
},
+ {SequenceRelationId, /* SEQRELID */
+ SequenceRelidIndexId,
+ 1,
+ {
+ Anum_pg_sequence_seqrelid,
+ 0,
+ 0,
+ 0
+ },
+ 32
+ },
{StatisticRelationId, /* STATRELATTINH */
StatisticRelidAttnumInhIndexId,
3,
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 7949aad3670..c5adc9da388 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -15351,7 +15351,27 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
- if (fout->remoteVersion >= 80400)
+ if (fout->remoteVersion >= 100000)
+ {
+ appendPQExpBuffer(query,
+ "SELECT relname, "
+ "seqstart, seqincrement, "
+ "CASE WHEN seqincrement > 0 AND seqmax = %s THEN NULL "
+ " WHEN seqincrement < 0 AND seqmax = -1 THEN NULL "
+ " ELSE seqmax "
+ "END AS seqmax, "
+ "CASE WHEN seqincrement > 0 AND seqmin = 1 THEN NULL "
+ " WHEN seqincrement < 0 AND seqmin = %s THEN NULL "
+ " ELSE seqmin "
+ "END AS seqmin, "
+ "seqcache, seqcycle "
+ "FROM pg_class c "
+ "JOIN pg_sequence s ON (s.seqrelid = c.oid) "
+ "WHERE relname = ",
+ bufx, bufm);
+ appendStringLiteralAH(query, tbinfo->dobj.name, fout);
+ }
+ else if (fout->remoteVersion >= 80400)
{
appendPQExpBuffer(query,
"SELECT sequence_name, "
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index e13e3991df8..5779f0d617f 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201612121
+#define CATALOG_VERSION_NO 201612201
#endif
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 40f7576b7b6..293985db4ec 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -209,6 +209,9 @@ DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index, 2692, on pg_rewrite using btree(oid o
DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
#define RewriteRelRulenameIndexId 2693
+DECLARE_UNIQUE_INDEX(pg_sequence_seqrelid_index, 5002, on pg_sequence using btree(seqrelid oid_ops));
+#define SequenceRelidIndexId 5002
+
DECLARE_INDEX(pg_shdepend_depender_index, 1232, on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
#define SharedDependDependerIndexId 1232
DECLARE_INDEX(pg_shdepend_reference_index, 1233, on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops));
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
new file mode 100644
index 00000000000..3bcda6bef17
--- /dev/null
+++ b/src/include/catalog/pg_sequence.h
@@ -0,0 +1,30 @@
+#ifndef PG_SEQUENCE_H
+#define PG_SEQUENCE_H
+
+#include "catalog/genbki.h"
+
+#define SequenceRelationId 2224
+
+CATALOG(pg_sequence,2224) BKI_WITHOUT_OIDS
+{
+ Oid seqrelid;
+ int64 seqstart;
+ int64 seqincrement;
+ int64 seqmax;
+ int64 seqmin;
+ int64 seqcache;
+ bool seqcycle;
+} FormData_pg_sequence;
+
+typedef FormData_pg_sequence *Form_pg_sequence;
+
+#define Natts_pg_sequence 7
+#define Anum_pg_sequence_seqrelid 1
+#define Anum_pg_sequence_seqstart 2
+#define Anum_pg_sequence_seqincrement 3
+#define Anum_pg_sequence_seqmax 4
+#define Anum_pg_sequence_seqmin 5
+#define Anum_pg_sequence_seqcache 6
+#define Anum_pg_sequence_seqcycle 7
+
+#endif /* PG_SEQUENCE_H */
diff --git a/src/include/commands/sequence.h b/src/include/commands/sequence.h
index 6695bbe4c7a..1fd75b216df 100644
--- a/src/include/commands/sequence.h
+++ b/src/include/commands/sequence.h
@@ -22,38 +22,24 @@
#include "storage/relfilenode.h"
-typedef struct FormData_pg_sequence
+typedef struct FormData_pg_sequence_data
{
- NameData sequence_name;
int64 last_value;
- int64 start_value;
- int64 increment_by;
- int64 max_value;
- int64 min_value;
- int64 cache_value;
int64 log_cnt;
- bool is_cycled;
bool is_called;
-} FormData_pg_sequence;
+} FormData_pg_sequence_data;
-typedef FormData_pg_sequence *Form_pg_sequence;
+typedef FormData_pg_sequence_data *Form_pg_sequence_data;
/*
* Columns of a sequence relation
*/
-#define SEQ_COL_NAME 1
-#define SEQ_COL_LASTVAL 2
-#define SEQ_COL_STARTVAL 3
-#define SEQ_COL_INCBY 4
-#define SEQ_COL_MAXVALUE 5
-#define SEQ_COL_MINVALUE 6
-#define SEQ_COL_CACHE 7
-#define SEQ_COL_LOG 8
-#define SEQ_COL_CYCLE 9
-#define SEQ_COL_CALLED 10
+#define SEQ_COL_LASTVAL 1
+#define SEQ_COL_LOG 2
+#define SEQ_COL_CALLED 3
-#define SEQ_COL_FIRSTCOL SEQ_COL_NAME
+#define SEQ_COL_FIRSTCOL SEQ_COL_LASTVAL
#define SEQ_COL_LASTCOL SEQ_COL_CALLED
/* XLOG stuff */
@@ -77,6 +63,7 @@ extern Datum pg_sequence_last_value(PG_FUNCTION_ARGS);
extern ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *stmt);
extern ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt);
+extern void DeleteSequenceTuple(Oid relid);
extern void ResetSequence(Oid seq_relid);
extern void ResetSequenceCaches(void);
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 39fe947d6e7..4b7631e7634 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -81,6 +81,7 @@ enum SysCacheIdentifier
REPLORIGIDENT,
REPLORIGNAME,
RULERELNAME,
+ SEQRELID,
STATRELATTINH,
TABLESPACEOID,
TRFOID,
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 5314b9c207f..e9cfadbc0f1 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1623,16 +1623,16 @@ UNION ALL
pg_sequences| SELECT n.nspname AS schemaname,
c.relname AS sequencename,
pg_get_userbyid(c.relowner) AS sequenceowner,
- p.start_value,
- p.minimum_value AS min_value,
- p.maximum_value AS max_value,
- p.increment AS increment_by,
- p.cycle_option AS cycle,
- p.cache_size,
+ s.seqstart AS start_value,
+ s.seqmin AS min_value,
+ s.seqmax AS max_value,
+ s.seqincrement AS increment_by,
+ s.seqcycle AS cycle,
+ s.seqcache AS cache_size,
pg_sequence_last_value((c.oid)::regclass) AS last_value
- FROM (pg_class c
- LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))),
- LATERAL pg_sequence_parameters(c.oid) p(start_value, minimum_value, maximum_value, increment, cycle_option, cache_size)
+ FROM ((pg_sequence s
+ JOIN pg_class c ON ((c.oid = s.seqrelid)))
+ LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
WHERE ((NOT pg_is_other_temp_schema(n.oid)) AND (c.relkind = 'S'::"char"));
pg_settings| SELECT a.name,
a.setting,
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 8fa929a6aa3..7ad68c745b0 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -128,6 +128,7 @@ pg_range|t
pg_replication_origin|t
pg_rewrite|t
pg_seclabel|t
+pg_sequence|t
pg_shdepend|t
pg_shdescription|t
pg_shseclabel|t
diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out
index c5413e09f3b..a2bdd3002b0 100644
--- a/src/test/regress/expected/sequence.out
+++ b/src/test/regress/expected/sequence.out
@@ -173,9 +173,9 @@ DROP SEQUENCE sequence_test;
CREATE SEQUENCE foo_seq;
ALTER TABLE foo_seq RENAME TO foo_seq_new;
SELECT * FROM foo_seq_new;
- sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
----------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
- foo_seq | 1 | 1 | 1 | 9223372036854775807 | 1 | 1 | 0 | f | f
+ last_value | log_cnt | is_called
+------------+---------+-----------
+ 1 | 0 | f
(1 row)
SELECT nextval('foo_seq_new');
@@ -191,9 +191,9 @@ SELECT nextval('foo_seq_new');
(1 row)
SELECT * FROM foo_seq_new;
- sequence_name | last_value | start_value | increment_by | max_value | min_value | cache_value | log_cnt | is_cycled | is_called
----------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
- foo_seq | 2 | 1 | 1 | 9223372036854775807 | 1 | 1 | 31 | f | t
+ last_value | log_cnt | is_called
+------------+---------+-----------
+ 2 | 31 | t
(1 row)
DROP SEQUENCE foo_seq_new;
@@ -536,3 +536,24 @@ SELECT * FROM information_schema.sequences WHERE sequence_name IN
DROP USER regress_seq_user;
DROP SEQUENCE seq;
+-- cache tests
+CREATE SEQUENCE test_seq1 CACHE 10;
+SELECT nextval('test_seq1');
+ nextval
+---------
+ 1
+(1 row)
+
+SELECT nextval('test_seq1');
+ nextval
+---------
+ 2
+(1 row)
+
+SELECT nextval('test_seq1');
+ nextval
+---------
+ 3
+(1 row)
+
+DROP SEQUENCE test_seq1;
diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out
index 79ddbdee4f7..8201d77a561 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -86,55 +86,48 @@ SELECT table_name, column_name, is_updatable
FROM information_schema.columns
WHERE table_name LIKE E'r_\\_view%'
ORDER BY table_name, ordinal_position;
- table_name | column_name | is_updatable
-------------+---------------+--------------
- ro_view1 | a | NO
- ro_view1 | b | NO
- ro_view10 | a | NO
- ro_view11 | a | NO
- ro_view11 | b | NO
- ro_view12 | a | NO
- ro_view13 | a | NO
- ro_view13 | b | NO
- ro_view17 | a | NO
- ro_view17 | b | NO
- ro_view18 | a | NO
- ro_view19 | sequence_name | NO
- ro_view19 | last_value | NO
- ro_view19 | start_value | NO
- ro_view19 | increment_by | NO
- ro_view19 | max_value | NO
- ro_view19 | min_value | NO
- ro_view19 | cache_value | NO
- ro_view19 | log_cnt | NO
- ro_view19 | is_cycled | NO
- ro_view19 | is_called | NO
- ro_view2 | a | NO
- ro_view2 | b | NO
- ro_view20 | a | NO
- ro_view20 | b | NO
- ro_view20 | g | NO
- ro_view3 | ?column? | NO
- ro_view4 | count | NO
- ro_view5 | a | NO
- ro_view5 | rank | NO
- ro_view6 | a | NO
- ro_view6 | b | NO
- ro_view7 | a | NO
- ro_view7 | b | NO
- ro_view8 | a | NO
- ro_view8 | b | NO
- ro_view9 | a | NO
- ro_view9 | b | NO
- rw_view14 | ctid | NO
- rw_view14 | a | YES
- rw_view14 | b | YES
- rw_view15 | a | YES
- rw_view15 | upper | NO
- rw_view16 | a | YES
- rw_view16 | b | YES
- rw_view16 | aa | YES
-(46 rows)
+ table_name | column_name | is_updatable
+------------+-------------+--------------
+ ro_view1 | a | NO
+ ro_view1 | b | NO
+ ro_view10 | a | NO
+ ro_view11 | a | NO
+ ro_view11 | b | NO
+ ro_view12 | a | NO
+ ro_view13 | a | NO
+ ro_view13 | b | NO
+ ro_view17 | a | NO
+ ro_view17 | b | NO
+ ro_view18 | a | NO
+ ro_view19 | last_value | NO
+ ro_view19 | log_cnt | NO
+ ro_view19 | is_called | NO
+ ro_view2 | a | NO
+ ro_view2 | b | NO
+ ro_view20 | a | NO
+ ro_view20 | b | NO
+ ro_view20 | g | NO
+ ro_view3 | ?column? | NO
+ ro_view4 | count | NO
+ ro_view5 | a | NO
+ ro_view5 | rank | NO
+ ro_view6 | a | NO
+ ro_view6 | b | NO
+ ro_view7 | a | NO
+ ro_view7 | b | NO
+ ro_view8 | a | NO
+ ro_view8 | b | NO
+ ro_view9 | a | NO
+ ro_view9 | b | NO
+ rw_view14 | ctid | NO
+ rw_view14 | a | YES
+ rw_view14 | b | YES
+ rw_view15 | a | YES
+ rw_view15 | upper | NO
+ rw_view16 | a | YES
+ rw_view16 | b | YES
+ rw_view16 | aa | YES
+(39 rows)
-- Read-only views
DELETE FROM ro_view1;
@@ -327,7 +320,7 @@ DELETE FROM ro_view18;
ERROR: cannot delete from view "ro_view18"
DETAIL: Views that do not select from a single table or view are not automatically updatable.
HINT: To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
-UPDATE ro_view19 SET max_value=1000;
+UPDATE ro_view19 SET last_value=1000;
ERROR: cannot update view "ro_view19"
DETAIL: Views that do not select from a single table or view are not automatically updatable.
HINT: To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
diff --git a/src/test/regress/sql/sequence.sql b/src/test/regress/sql/sequence.sql
index e2b6b633930..a79330e7804 100644
--- a/src/test/regress/sql/sequence.sql
+++ b/src/test/regress/sql/sequence.sql
@@ -273,3 +273,11 @@ SELECT * FROM information_schema.sequences WHERE sequence_name IN
DROP USER regress_seq_user;
DROP SEQUENCE seq;
+
+-- cache tests
+CREATE SEQUENCE test_seq1 CACHE 10;
+SELECT nextval('test_seq1');
+SELECT nextval('test_seq1');
+SELECT nextval('test_seq1');
+
+DROP SEQUENCE test_seq1;
diff --git a/src/test/regress/sql/updatable_views.sql b/src/test/regress/sql/updatable_views.sql
index 03c3f9d35eb..f0084795416 100644
--- a/src/test/regress/sql/updatable_views.sql
+++ b/src/test/regress/sql/updatable_views.sql
@@ -95,7 +95,7 @@ DELETE FROM rw_view16 WHERE a=-3; -- should be OK
-- Read-only views
INSERT INTO ro_view17 VALUES (3, 'ROW 3');
DELETE FROM ro_view18;
-UPDATE ro_view19 SET max_value=1000;
+UPDATE ro_view19 SET last_value=1000;
UPDATE ro_view20 SET b=upper(b);
DROP TABLE base_tbl CASCADE;