diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/Makefile | 1 | ||||
-rw-r--r-- | src/backend/catalog/dependency.c | 6 | ||||
-rw-r--r-- | src/backend/catalog/information_schema.sql | 13 | ||||
-rw-r--r-- | src/backend/catalog/system_views.sql | 16 | ||||
-rw-r--r-- | src/backend/commands/sequence.c | 381 | ||||
-rw-r--r-- | src/backend/utils/cache/syscache.c | 12 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 22 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/indexing.h | 3 | ||||
-rw-r--r-- | src/include/catalog/pg_sequence.h | 30 | ||||
-rw-r--r-- | src/include/commands/sequence.h | 29 | ||||
-rw-r--r-- | src/include/utils/syscache.h | 1 | ||||
-rw-r--r-- | src/test/regress/expected/rules.out | 18 | ||||
-rw-r--r-- | src/test/regress/expected/sanity_check.out | 1 | ||||
-rw-r--r-- | src/test/regress/expected/sequence.out | 33 | ||||
-rw-r--r-- | src/test/regress/expected/updatable_views.out | 93 | ||||
-rw-r--r-- | src/test/regress/sql/sequence.sql | 8 | ||||
-rw-r--r-- | src/test/regress/sql/updatable_views.sql | 2 |
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; |