diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2016-12-20 12:00:00 -0500 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2016-12-20 08:28:18 -0500 |
commit | 1753b1b027035029c2a2a1649065762fafbf63f3 (patch) | |
tree | cd5b4d8fca4ffca2581e3822a2fa7b5f2f49062a /src/backend/commands/sequence.c | |
parent | db80acfc9d50ac56811d22802ab3d822ab313055 (diff) | |
download | postgresql-1753b1b027035029c2a2a1649065762fafbf63f3.tar.gz postgresql-1753b1b027035029c2a2a1649065762fafbf63f3.zip |
Add pg_sequence system catalog
Move sequence metadata (start, increment, etc.) into a proper system
catalog instead of storing it in the sequence heap object. This
separates the metadata from the sequence data. Sequence metadata is now
operated on transactionally by DDL commands, whereas previously
rollbacks of sequence-related DDL commands would be ignored.
Reviewed-by: Andreas Karlsson <andreas@proxel.se>
Diffstat (limited to 'src/backend/commands/sequence.c')
-rw-r--r-- | src/backend/commands/sequence.c | 381 |
1 files changed, 216 insertions, 165 deletions
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; |