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)
579 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
649 if (check_permissions &&
653 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
654 errmsg(
"permission denied for sequence %s",
680 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
682 incby = pgsform->seqincrement;
683 maxv = pgsform->seqmax;
684 minv = pgsform->seqmin;
685 cache = pgsform->seqcache;
686 cycle = pgsform->seqcycle;
713 if (log < fetch || !seq->is_called)
740 if ((maxv >= 0 &&
next > maxv - incby) ||
741 (maxv < 0 && next + incby > maxv))
747 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
748 errmsg(
"nextval: reached maximum value of sequence \"%s\" (%lld)",
759 if ((minv < 0 &&
next < minv - incby) ||
760 (minv >= 0 &&
next + incby < minv))
766 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
767 errmsg(
"nextval: reached minimum value of sequence \"%s\" (%lld)",
879 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
880 errmsg(
"permission denied for sequence %s",
885 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
886 errmsg(
"currval of sequence \"%s\" is not yet defined in this session",
904 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
905 errmsg(
"lastval is not yet defined in this session")));
910 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
911 errmsg(
"lastval is not yet defined in this session")));
921 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
922 errmsg(
"permission denied for sequence %s",
962 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
963 errmsg(
"permission denied for sequence %s",
968 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
970 maxv = pgsform->seqmax;
971 minv = pgsform->seqmin;
990 (
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
991 errmsg(
"setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)",
993 (
long long) minv, (
long long) maxv)));
1090 if (seq->
lxid != thislxid)
1102 seq->
lxid = thislxid;
1117 ctl.keysize =
sizeof(
Oid);
1204 elog(
ERROR,
"bad magic number in sequence \"%s\": %08X",
1261 bool *need_seq_rewrite,
1266 DefElem *restart_value = NULL;
1273 bool reset_max_value =
false;
1274 bool reset_min_value =
false;
1276 *need_seq_rewrite =
false;
1283 if (strcmp(defel->
defname,
"as") == 0)
1288 *need_seq_rewrite =
true;
1290 else if (strcmp(defel->
defname,
"increment") == 0)
1294 increment_by = defel;
1295 *need_seq_rewrite =
true;
1297 else if (strcmp(defel->
defname,
"start") == 0)
1301 start_value = defel;
1302 *need_seq_rewrite =
true;
1304 else if (strcmp(defel->
defname,
"restart") == 0)
1308 restart_value = defel;
1309 *need_seq_rewrite =
true;
1311 else if (strcmp(defel->
defname,
"maxvalue") == 0)
1316 *need_seq_rewrite =
true;
1318 else if (strcmp(defel->
defname,
"minvalue") == 0)
1323 *need_seq_rewrite =
true;
1325 else if (strcmp(defel->
defname,
"cache") == 0)
1329 cache_value = defel;
1330 *need_seq_rewrite =
true;
1332 else if (strcmp(defel->
defname,
"cycle") == 0)
1337 *need_seq_rewrite =
true;
1339 else if (strcmp(defel->
defname,
"owned_by") == 0)
1345 else if (strcmp(defel->
defname,
"sequence_name") == 0)
1353 (
errcode(ERRCODE_SYNTAX_ERROR),
1354 errmsg(
"invalid sequence option SEQUENCE NAME"),
1358 elog(
ERROR,
"option \"%s\" not recognized",
1370 if (as_type != NULL)
1374 if (newtypid != INT2OID &&
1375 newtypid != INT4OID &&
1376 newtypid != INT8OID)
1378 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1380 ?
errmsg(
"identity column type must be smallint, integer, or bigint")
1381 :
errmsg(
"sequence type must be smallint, integer, or bigint")));
1391 if ((seqform->seqtypid == INT2OID && seqform->seqmax ==
PG_INT16_MAX) ||
1392 (seqform->seqtypid == INT4OID && seqform->seqmax ==
PG_INT32_MAX) ||
1393 (seqform->seqtypid == INT8OID && seqform->seqmax ==
PG_INT64_MAX))
1394 reset_max_value =
true;
1395 if ((seqform->seqtypid == INT2OID && seqform->seqmin ==
PG_INT16_MIN) ||
1396 (seqform->seqtypid == INT4OID && seqform->seqmin ==
PG_INT32_MIN) ||
1397 (seqform->seqtypid == INT8OID && seqform->seqmin ==
PG_INT64_MIN))
1398 reset_min_value =
true;
1401 seqform->seqtypid = newtypid;
1405 seqform->seqtypid = INT8OID;
1409 if (increment_by != NULL)
1411 seqform->seqincrement =
defGetInt64(increment_by);
1412 if (seqform->seqincrement == 0)
1414 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1415 errmsg(
"INCREMENT must not be zero")));
1420 seqform->seqincrement = 1;
1424 if (is_cycled != NULL)
1432 seqform->seqcycle =
false;
1436 if (max_value != NULL && max_value->
arg)
1441 else if (isInit || max_value != NULL || reset_max_value)
1443 if (seqform->seqincrement > 0 || reset_max_value)
1446 if (seqform->seqtypid == INT2OID)
1448 else if (seqform->seqtypid == INT4OID)
1454 seqform->seqmax = -1;
1462 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1463 errmsg(
"MAXVALUE (%lld) is out of range for sequence data type %s",
1464 (
long long) seqform->seqmax,
1468 if (min_value != NULL && min_value->
arg)
1473 else if (isInit || min_value != NULL || reset_min_value)
1475 if (seqform->seqincrement < 0 || reset_min_value)
1478 if (seqform->seqtypid == INT2OID)
1480 else if (seqform->seqtypid == INT4OID)
1486 seqform->seqmin = 1;
1494 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1495 errmsg(
"MINVALUE (%lld) is out of range for sequence data type %s",
1496 (
long long) seqform->seqmin,
1500 if (seqform->seqmin >= seqform->seqmax)
1502 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1503 errmsg(
"MINVALUE (%lld) must be less than MAXVALUE (%lld)",
1504 (
long long) seqform->seqmin,
1505 (
long long) seqform->seqmax)));
1508 if (start_value != NULL)
1514 if (seqform->seqincrement > 0)
1515 seqform->seqstart = seqform->seqmin;
1517 seqform->seqstart = seqform->seqmax;
1521 if (seqform->seqstart < seqform->seqmin)
1523 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1524 errmsg(
"START value (%lld) cannot be less than MINVALUE (%lld)",
1525 (
long long) seqform->seqstart,
1526 (
long long) seqform->seqmin)));
1527 if (seqform->seqstart > seqform->seqmax)
1529 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1530 errmsg(
"START value (%lld) cannot be greater than MAXVALUE (%lld)",
1531 (
long long) seqform->seqstart,
1532 (
long long) seqform->seqmax)));
1535 if (restart_value != NULL)
1537 if (restart_value->
arg != NULL)
1551 if (seqdataform->
last_value < seqform->seqmin)
1553 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1554 errmsg(
"RESTART value (%lld) cannot be less than MINVALUE (%lld)",
1556 (
long long) seqform->seqmin)));
1557 if (seqdataform->
last_value > seqform->seqmax)
1559 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1560 errmsg(
"RESTART value (%lld) cannot be greater than MAXVALUE (%lld)",
1562 (
long long) seqform->seqmax)));
1565 if (cache_value != NULL)
1568 if (seqform->seqcache <= 0)
1570 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1571 errmsg(
"CACHE (%lld) must be greater than zero",
1572 (
long long) seqform->seqcache)));
1577 seqform->seqcache = 1;
1606 (
errcode(ERRCODE_SYNTAX_ERROR),
1607 errmsg(
"invalid OWNED BY option"),
1608 errhint(
"Specify OWNED BY table.column or OWNED BY NONE.")));
1627 if (!(tablerel->
rd_rel->relkind == RELKIND_RELATION ||
1628 tablerel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1629 tablerel->
rd_rel->relkind == RELKIND_VIEW ||
1630 tablerel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1632 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1633 errmsg(
"sequence cannot be owned by relation \"%s\"",
1638 if (seqrel->
rd_rel->relowner != tablerel->
rd_rel->relowner)
1640 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1641 errmsg(
"sequence must have same owner as table it is linked to")));
1644 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1645 errmsg(
"sequence must be in same schema as table it is linked to")));
1651 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1652 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
1666 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1667 errmsg(
"cannot change ownership of identity sequence"),
1668 errdetail(
"Sequence \"%s\" is linked to table \"%s\".",
1678 RelationRelationId, deptype);
1685 refobject.
classId = RelationRelationId;
1688 depobject.
classId = RelationRelationId;
1712 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1749 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1750 errmsg(
"permission denied for sequence %s",
1754 elog(
ERROR,
"return type must be a row type");
1756 memset(isnull, 0,
sizeof(isnull));
1760 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1787 bool is_called =
false;
1840 elog(
PANIC,
"seq_redo: unknown op code %u", info);
1865 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 RELATION_IS_OTHER_TEMP(relation)
#define RelationGetNamespace(relation)
#define RelationIsPermanent(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)
bool RecoveryInProgress(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)