diff options
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; |