58 #define SEQ_LOG_VALS 32
63 #define SEQ_MAGIC 0x1717
110 bool *need_seq_rewrite,
125 bool need_seq_rewrite;
135 Datum pgs_values[Natts_pg_sequence];
136 bool pgs_nulls[Natts_pg_sequence];
158 (
errcode(ERRCODE_DUPLICATE_TABLE),
159 errmsg(
"relation \"%s\" already exists, skipping",
167 &seqform, &seqdataform,
168 &need_seq_rewrite, &owned_by);
205 stmt->tablespacename = NULL;
229 memset(pgs_nulls, 0,
sizeof(pgs_nulls));
232 pgs_values[Anum_pg_sequence_seqtypid - 1] =
ObjectIdGetDatum(seqform.seqtypid);
234 pgs_values[Anum_pg_sequence_seqincrement - 1] =
Int64GetDatumFast(seqform.seqincrement);
238 pgs_values[Anum_pg_sequence_seqcycle - 1] =
BoolGetDatum(seqform.seqcycle);
284 elog(
ERROR,
"cache lookup failed for sequence %u", seq_relid);
286 startv = pgsform->seqstart;
342 if (rel->
rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
405 elog(
ERROR,
"failed to add sequence tuple to page");
446 bool need_seq_rewrite;
462 (
errmsg(
"relation \"%s\" does not exist, skipping",
463 stmt->sequence->relname)));
473 elog(
ERROR,
"cache lookup failed for sequence %u",
489 seqform, newdataform,
490 &need_seq_rewrite, &owned_by);
493 if (need_seq_rewrite)
572 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
642 if (check_permissions &&
646 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
647 errmsg(
"permission denied for sequence %s",
673 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
675 incby = pgsform->seqincrement;
676 maxv = pgsform->seqmax;
677 minv = pgsform->seqmin;
678 cache = pgsform->seqcache;
679 cycle = pgsform->seqcycle;
706 if (log < fetch || !seq->is_called)
733 if ((maxv >= 0 &&
next > maxv - incby) ||
734 (maxv < 0 && next + incby > maxv))
740 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
741 errmsg(
"nextval: reached maximum value of sequence \"%s\" (%lld)",
752 if ((minv < 0 &&
next < minv - incby) ||
753 (minv >= 0 &&
next + incby < minv))
759 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
760 errmsg(
"nextval: reached minimum value of sequence \"%s\" (%lld)",
872 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
873 errmsg(
"permission denied for sequence %s",
878 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
879 errmsg(
"currval of sequence \"%s\" is not yet defined in this session",
897 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
898 errmsg(
"lastval is not yet defined in this session")));
903 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
904 errmsg(
"lastval is not yet defined in this session")));
914 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
915 errmsg(
"permission denied for sequence %s",
955 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
956 errmsg(
"permission denied for sequence %s",
961 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
963 maxv = pgsform->seqmax;
964 minv = pgsform->seqmin;
983 (
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
984 errmsg(
"setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)",
986 (
long long) minv, (
long long) maxv)));
1083 if (seq->
lxid != thislxid)
1095 seq->
lxid = thislxid;
1110 ctl.keysize =
sizeof(
Oid);
1197 elog(
ERROR,
"bad magic number in sequence \"%s\": %08X",
1254 bool *need_seq_rewrite,
1259 DefElem *restart_value = NULL;
1266 bool reset_max_value =
false;
1267 bool reset_min_value =
false;
1269 *need_seq_rewrite =
false;
1276 if (strcmp(defel->
defname,
"as") == 0)
1281 *need_seq_rewrite =
true;
1283 else if (strcmp(defel->
defname,
"increment") == 0)
1287 increment_by = defel;
1288 *need_seq_rewrite =
true;
1290 else if (strcmp(defel->
defname,
"start") == 0)
1294 start_value = defel;
1295 *need_seq_rewrite =
true;
1297 else if (strcmp(defel->
defname,
"restart") == 0)
1301 restart_value = defel;
1302 *need_seq_rewrite =
true;
1304 else if (strcmp(defel->
defname,
"maxvalue") == 0)
1309 *need_seq_rewrite =
true;
1311 else if (strcmp(defel->
defname,
"minvalue") == 0)
1316 *need_seq_rewrite =
true;
1318 else if (strcmp(defel->
defname,
"cache") == 0)
1322 cache_value = defel;
1323 *need_seq_rewrite =
true;
1325 else if (strcmp(defel->
defname,
"cycle") == 0)
1330 *need_seq_rewrite =
true;
1332 else if (strcmp(defel->
defname,
"owned_by") == 0)
1338 else if (strcmp(defel->
defname,
"sequence_name") == 0)
1346 (
errcode(ERRCODE_SYNTAX_ERROR),
1347 errmsg(
"invalid sequence option SEQUENCE NAME"),
1351 elog(
ERROR,
"option \"%s\" not recognized",
1363 if (as_type != NULL)
1367 if (newtypid != INT2OID &&
1368 newtypid != INT4OID &&
1369 newtypid != INT8OID)
1371 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1373 ?
errmsg(
"identity column type must be smallint, integer, or bigint")
1374 :
errmsg(
"sequence type must be smallint, integer, or bigint")));
1384 if ((seqform->seqtypid == INT2OID && seqform->seqmax ==
PG_INT16_MAX) ||
1385 (seqform->seqtypid == INT4OID && seqform->seqmax ==
PG_INT32_MAX) ||
1386 (seqform->seqtypid == INT8OID && seqform->seqmax ==
PG_INT64_MAX))
1387 reset_max_value =
true;
1388 if ((seqform->seqtypid == INT2OID && seqform->seqmin ==
PG_INT16_MIN) ||
1389 (seqform->seqtypid == INT4OID && seqform->seqmin ==
PG_INT32_MIN) ||
1390 (seqform->seqtypid == INT8OID && seqform->seqmin ==
PG_INT64_MIN))
1391 reset_min_value =
true;
1394 seqform->seqtypid = newtypid;
1398 seqform->seqtypid = INT8OID;
1402 if (increment_by != NULL)
1404 seqform->seqincrement =
defGetInt64(increment_by);
1405 if (seqform->seqincrement == 0)
1407 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1408 errmsg(
"INCREMENT must not be zero")));
1413 seqform->seqincrement = 1;
1417 if (is_cycled != NULL)
1425 seqform->seqcycle =
false;
1429 if (max_value != NULL && max_value->
arg)
1434 else if (isInit || max_value != NULL || reset_max_value)
1436 if (seqform->seqincrement > 0 || reset_max_value)
1439 if (seqform->seqtypid == INT2OID)
1441 else if (seqform->seqtypid == INT4OID)
1447 seqform->seqmax = -1;
1455 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1456 errmsg(
"MAXVALUE (%lld) is out of range for sequence data type %s",
1457 (
long long) seqform->seqmax,
1461 if (min_value != NULL && min_value->
arg)
1466 else if (isInit || min_value != NULL || reset_min_value)
1468 if (seqform->seqincrement < 0 || reset_min_value)
1471 if (seqform->seqtypid == INT2OID)
1473 else if (seqform->seqtypid == INT4OID)
1479 seqform->seqmin = 1;
1487 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1488 errmsg(
"MINVALUE (%lld) is out of range for sequence data type %s",
1489 (
long long) seqform->seqmin,
1493 if (seqform->seqmin >= seqform->seqmax)
1495 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1496 errmsg(
"MINVALUE (%lld) must be less than MAXVALUE (%lld)",
1497 (
long long) seqform->seqmin,
1498 (
long long) seqform->seqmax)));
1501 if (start_value != NULL)
1507 if (seqform->seqincrement > 0)
1508 seqform->seqstart = seqform->seqmin;
1510 seqform->seqstart = seqform->seqmax;
1514 if (seqform->seqstart < seqform->seqmin)
1516 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1517 errmsg(
"START value (%lld) cannot be less than MINVALUE (%lld)",
1518 (
long long) seqform->seqstart,
1519 (
long long) seqform->seqmin)));
1520 if (seqform->seqstart > seqform->seqmax)
1522 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1523 errmsg(
"START value (%lld) cannot be greater than MAXVALUE (%lld)",
1524 (
long long) seqform->seqstart,
1525 (
long long) seqform->seqmax)));
1528 if (restart_value != NULL)
1530 if (restart_value->
arg != NULL)
1544 if (seqdataform->
last_value < seqform->seqmin)
1546 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1547 errmsg(
"RESTART value (%lld) cannot be less than MINVALUE (%lld)",
1549 (
long long) seqform->seqmin)));
1550 if (seqdataform->
last_value > seqform->seqmax)
1552 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1553 errmsg(
"RESTART value (%lld) cannot be greater than MAXVALUE (%lld)",
1555 (
long long) seqform->seqmax)));
1558 if (cache_value != NULL)
1561 if (seqform->seqcache <= 0)
1563 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1564 errmsg(
"CACHE (%lld) must be greater than zero",
1565 (
long long) seqform->seqcache)));
1570 seqform->seqcache = 1;
1599 (
errcode(ERRCODE_SYNTAX_ERROR),
1600 errmsg(
"invalid OWNED BY option"),
1601 errhint(
"Specify OWNED BY table.column or OWNED BY NONE.")));
1620 if (!(tablerel->
rd_rel->relkind == RELKIND_RELATION ||
1621 tablerel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1622 tablerel->
rd_rel->relkind == RELKIND_VIEW ||
1623 tablerel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1625 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1626 errmsg(
"sequence cannot be owned by relation \"%s\"",
1631 if (seqrel->
rd_rel->relowner != tablerel->
rd_rel->relowner)
1633 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1634 errmsg(
"sequence must have same owner as table it is linked to")));
1637 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1638 errmsg(
"sequence must be in same schema as table it is linked to")));
1644 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1645 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
1659 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1660 errmsg(
"cannot change ownership of identity sequence"),
1661 errdetail(
"Sequence \"%s\" is linked to table \"%s\".",
1671 RelationRelationId, deptype);
1678 refobject.
classId = RelationRelationId;
1681 depobject.
classId = RelationRelationId;
1705 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1742 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1743 errmsg(
"permission denied for sequence %s",
1747 elog(
ERROR,
"return type must be a row type");
1749 memset(isnull, 0,
sizeof(isnull));
1753 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1791 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1792 errmsg(
"permission denied for sequence %s",
1824 elog(
PANIC,
"seq_redo: unknown op code %u", info);
1849 elog(
PANIC,
"seq_redo: failed to add item to page");
Relation sequence_open(Oid relationId, LOCKMODE lockmode)
void sequence_close(Relation relation, LOCKMODE lockmode)
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
#define InvalidAttrNumber
static Datum values[MAXATTR]
void mask_page_lsn_and_checksum(Page page)
void mask_unused_space(Page page)
BlockNumber BufferGetBlockNumber(Buffer buffer)
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
void UnlockReleaseBuffer(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
void FlushRelationBuffers(Relation rel)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
static Page BufferGetPage(Buffer buffer)
static Size BufferGetPageSize(Buffer buffer)
#define BUFFER_LOCK_EXCLUSIVE
void PageInit(Page page, Size pageSize, Size specialSize)
static Item PageGetItem(Page page, ItemId itemId)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static XLogRecPtr PageGetLSN(Page page)
static char * PageGetSpecialPointer(Page page)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
#define Assert(condition)
#define BoolIsValid(boolean)
uint32 LocalTransactionId
#define OidIsValid(objectId)
ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
static void fill_seq_fork_with_data(Relation rel, HeapTuple tuple, ForkNumber forkNum)
void ResetSequence(Oid seq_relid)
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
struct sequence_magic sequence_magic
Datum setval_oid(PG_FUNCTION_ARGS)
static SeqTableData * last_used_seq
ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
Datum pg_sequence_parameters(PG_FUNCTION_ARGS)
Datum nextval_oid(PG_FUNCTION_ARGS)
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Datum setval3_oid(PG_FUNCTION_ARGS)
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Datum lastval(PG_FUNCTION_ARGS)
void seq_mask(char *page, BlockNumber blkno)
Datum nextval(PG_FUNCTION_ARGS)
int64 nextval_internal(Oid relid, bool check_permissions)
void SequenceChangePersistence(Oid relid, char newrelpersistence)
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Datum pg_sequence_last_value(PG_FUNCTION_ARGS)
Datum currval_oid(PG_FUNCTION_ARGS)
static void do_setval(Oid relid, int64 next, bool iscalled)
List * sequence_options(Oid relid)
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, bool *need_seq_rewrite, List **owned_by)
void seq_redo(XLogReaderState *record)
struct SeqTableData SeqTableData
void ResetSequenceCaches(void)
static void create_seq_hashtable(void)
static Relation lock_and_open_sequence(SeqTable seq)
void DeleteSequenceTuple(Oid relid)
FormData_pg_sequence_data * Form_pg_sequence_data
struct xl_seq_rec xl_seq_rec
List * defGetQualifiedName(DefElem *def)
int64 defGetInt64(DefElem *def)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
TypeName * defGetTypeName(DefElem *def)
void hash_destroy(HTAB *hashp)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Datum Int64GetDatum(int64 X)
#define PG_GETARG_TEXT_PP(n)
#define PG_RETURN_INT64(x)
#define PG_GETARG_INT64(n)
#define PG_GETARG_BOOL(n)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
HeapTuple heap_copytuple(HeapTuple tuple)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
HeapTupleHeaderData * HeapTupleHeader
#define HeapTupleIsValid(tuple)
#define HeapTupleHeaderSetXminFrozen(tup)
#define HeapTupleHeaderSetXmin(tup, xid)
#define HeapTupleHeaderSetXmax(tup, xid)
#define HeapTupleHeaderSetCmin(tup, cid)
#define HEAP_XMAX_IS_MULTI
#define HEAP_XMAX_COMMITTED
#define HEAP_XMAX_INVALID
#define HeapTupleHeaderGetRawXmax(tup)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
#define ItemIdGetLength(itemId)
#define ItemIdIsNormal(itemId)
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
List * lappend(List *list, void *datum)
List * list_copy_head(const List *oldlist, int len)
void LockRelationOid(Oid relid, LOCKMODE lockmode)
#define InvalidLocalTransactionId
#define AccessExclusiveLock
#define ShareRowExclusiveLock
AttrNumber get_attnum(Oid relid, const char *attname)
char * get_rel_name(Oid relid)
DefElem * makeDefElem(char *name, Node *arg, int location)
ColumnDef * makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid)
void pfree(void *pointer)
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
#define InvalidMultiXactId
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
RangeVar * makeRangeVarFromNameList(const List *names)
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
#define RangeVarGetRelid(relation, lockmode, missing_ok)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
#define InvalidOffsetNumber
#define FirstOffsetNumber
int parser_errposition(ParseState *pstate, int location)
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
int errdetail_relkind_not_supported(char relkind)
void checkMembershipInCurrentExtension(const ObjectAddress *object)
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
static int list_length(const List *l)
FormData_pg_sequence * Form_pg_sequence
#define Int64GetDatumFast(X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
#define INVALID_PROC_NUMBER
char * psprintf(const char *fmt,...)
#define RelationGetRelid(relation)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
#define RelationNeedsWAL(relation)
#define RelationGetNamespace(relation)
void RelationSetNewRelfilenumber(Relation relation, char persistence)
#define InvalidRelFileNumber
ResourceOwner TopTransactionResourceOwner
ResourceOwner CurrentResourceOwner
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
void smgrclose(SMgrRelation reln)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
RelFileLocator rd_locator
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define SearchSysCacheCopy1(cacheId, key1)
#define SearchSysCacheExists1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
#define FrozenTransactionId
#define InvalidTransactionId
void PreventCommandIfReadOnly(const char *cmdname)
void PreventCommandIfParallelMode(const char *cmdname)
Boolean * makeBoolean(bool val)
Float * makeFloat(char *numericStr)
List * textToQualifiedNameList(text *textval)
TransactionId GetTopTransactionId(void)
XLogRecPtr GetRedoRecPtr(void)
void XLogRegisterData(char *data, uint32 len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
void XLogBeginInsert(void)
#define XLogRecGetDataLen(decoder)
#define XLogRecGetInfo(decoder)
#define XLogRecGetData(decoder)
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)