57 #define SEQ_LOG_VALS 32
62 #define SEQ_MAGIC 0x1717
109 bool *need_seq_rewrite,
124 bool need_seq_rewrite;
134 Datum pgs_values[Natts_pg_sequence];
135 bool pgs_nulls[Natts_pg_sequence];
157 (
errcode(ERRCODE_DUPLICATE_TABLE),
158 errmsg(
"relation \"%s\" already exists, skipping",
166 &seqform, &seqdataform,
167 &need_seq_rewrite, &owned_by);
195 coldef->
colname =
"last_value";
217 stmt->tablespacename = NULL;
241 memset(pgs_nulls, 0,
sizeof(pgs_nulls));
244 pgs_values[Anum_pg_sequence_seqtypid - 1] =
ObjectIdGetDatum(seqform.seqtypid);
246 pgs_values[Anum_pg_sequence_seqincrement - 1] =
Int64GetDatumFast(seqform.seqincrement);
250 pgs_values[Anum_pg_sequence_seqcycle - 1] =
BoolGetDatum(seqform.seqcycle);
296 elog(
ERROR,
"cache lookup failed for sequence %u", seq_relid);
298 startv = pgsform->seqstart;
354 if (rel->
rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
418 elog(
ERROR,
"failed to add sequence tuple to page");
459 bool need_seq_rewrite;
475 (
errmsg(
"relation \"%s\" does not exist, skipping",
476 stmt->sequence->relname)));
486 elog(
ERROR,
"cache lookup failed for sequence %u",
502 seqform, newdataform,
503 &need_seq_rewrite, &owned_by);
510 if (need_seq_rewrite)
585 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
655 if (check_permissions &&
659 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
660 errmsg(
"permission denied for sequence %s",
686 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
688 incby = pgsform->seqincrement;
689 maxv = pgsform->seqmax;
690 minv = pgsform->seqmin;
691 cache = pgsform->seqcache;
692 cycle = pgsform->seqcycle;
720 if (log < fetch || !seq->is_called)
747 if ((maxv >= 0 &&
next > maxv - incby) ||
748 (maxv < 0 && next + incby > maxv))
754 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
755 errmsg(
"nextval: reached maximum value of sequence \"%s\" (%lld)",
766 if ((minv < 0 &&
next < minv - incby) ||
767 (minv >= 0 &&
next + incby < minv))
773 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
774 errmsg(
"nextval: reached minimum value of sequence \"%s\" (%lld)",
885 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
886 errmsg(
"permission denied for sequence %s",
891 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
892 errmsg(
"currval of sequence \"%s\" 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")));
916 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
917 errmsg(
"lastval is not yet defined in this session")));
927 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
928 errmsg(
"permission denied for sequence %s",
968 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
969 errmsg(
"permission denied for sequence %s",
974 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
976 maxv = pgsform->seqmax;
977 minv = pgsform->seqmin;
996 (
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
997 errmsg(
"setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)",
999 (
long long) minv, (
long long) maxv)));
1096 if (seq->
lxid != thislxid)
1108 seq->
lxid = thislxid;
1169 if (seqrel->
rd_rel->relkind != RELKIND_SEQUENCE)
1171 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1172 errmsg(
"\"%s\" is not a sequence",
1216 elog(
ERROR,
"bad magic number in sequence \"%s\": %08X",
1273 bool *need_seq_rewrite,
1278 DefElem *restart_value = NULL;
1285 bool reset_max_value =
false;
1286 bool reset_min_value =
false;
1288 *need_seq_rewrite =
false;
1295 if (strcmp(defel->
defname,
"as") == 0)
1300 *need_seq_rewrite =
true;
1302 else if (strcmp(defel->
defname,
"increment") == 0)
1306 increment_by = defel;
1307 *need_seq_rewrite =
true;
1309 else if (strcmp(defel->
defname,
"start") == 0)
1313 start_value = defel;
1314 *need_seq_rewrite =
true;
1316 else if (strcmp(defel->
defname,
"restart") == 0)
1320 restart_value = defel;
1321 *need_seq_rewrite =
true;
1323 else if (strcmp(defel->
defname,
"maxvalue") == 0)
1328 *need_seq_rewrite =
true;
1330 else if (strcmp(defel->
defname,
"minvalue") == 0)
1335 *need_seq_rewrite =
true;
1337 else if (strcmp(defel->
defname,
"cache") == 0)
1341 cache_value = defel;
1342 *need_seq_rewrite =
true;
1344 else if (strcmp(defel->
defname,
"cycle") == 0)
1349 *need_seq_rewrite =
true;
1351 else if (strcmp(defel->
defname,
"owned_by") == 0)
1357 else if (strcmp(defel->
defname,
"sequence_name") == 0)
1365 (
errcode(ERRCODE_SYNTAX_ERROR),
1366 errmsg(
"invalid sequence option SEQUENCE NAME"),
1370 elog(
ERROR,
"option \"%s\" not recognized",
1382 if (as_type != NULL)
1386 if (newtypid != INT2OID &&
1387 newtypid != INT4OID &&
1388 newtypid != INT8OID)
1390 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1392 ?
errmsg(
"identity column type must be smallint, integer, or bigint")
1393 :
errmsg(
"sequence type must be smallint, integer, or bigint")));
1403 if ((seqform->seqtypid == INT2OID && seqform->seqmax ==
PG_INT16_MAX) ||
1404 (seqform->seqtypid == INT4OID && seqform->seqmax ==
PG_INT32_MAX) ||
1405 (seqform->seqtypid == INT8OID && seqform->seqmax ==
PG_INT64_MAX))
1406 reset_max_value =
true;
1407 if ((seqform->seqtypid == INT2OID && seqform->seqmin ==
PG_INT16_MIN) ||
1408 (seqform->seqtypid == INT4OID && seqform->seqmin ==
PG_INT32_MIN) ||
1409 (seqform->seqtypid == INT8OID && seqform->seqmin ==
PG_INT64_MIN))
1410 reset_min_value =
true;
1413 seqform->seqtypid = newtypid;
1417 seqform->seqtypid = INT8OID;
1421 if (increment_by != NULL)
1423 seqform->seqincrement =
defGetInt64(increment_by);
1424 if (seqform->seqincrement == 0)
1426 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1427 errmsg(
"INCREMENT must not be zero")));
1432 seqform->seqincrement = 1;
1436 if (is_cycled != NULL)
1444 seqform->seqcycle =
false;
1448 if (max_value != NULL && max_value->
arg)
1453 else if (isInit || max_value != NULL || reset_max_value)
1455 if (seqform->seqincrement > 0 || reset_max_value)
1458 if (seqform->seqtypid == INT2OID)
1460 else if (seqform->seqtypid == INT4OID)
1466 seqform->seqmax = -1;
1474 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1475 errmsg(
"MAXVALUE (%lld) is out of range for sequence data type %s",
1476 (
long long) seqform->seqmax,
1480 if (min_value != NULL && min_value->
arg)
1485 else if (isInit || min_value != NULL || reset_min_value)
1487 if (seqform->seqincrement < 0 || reset_min_value)
1490 if (seqform->seqtypid == INT2OID)
1492 else if (seqform->seqtypid == INT4OID)
1498 seqform->seqmin = 1;
1506 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1507 errmsg(
"MINVALUE (%lld) is out of range for sequence data type %s",
1508 (
long long) seqform->seqmin,
1512 if (seqform->seqmin >= seqform->seqmax)
1514 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1515 errmsg(
"MINVALUE (%lld) must be less than MAXVALUE (%lld)",
1516 (
long long) seqform->seqmin,
1517 (
long long) seqform->seqmax)));
1520 if (start_value != NULL)
1526 if (seqform->seqincrement > 0)
1527 seqform->seqstart = seqform->seqmin;
1529 seqform->seqstart = seqform->seqmax;
1533 if (seqform->seqstart < seqform->seqmin)
1535 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1536 errmsg(
"START value (%lld) cannot be less than MINVALUE (%lld)",
1537 (
long long) seqform->seqstart,
1538 (
long long) seqform->seqmin)));
1539 if (seqform->seqstart > seqform->seqmax)
1541 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1542 errmsg(
"START value (%lld) cannot be greater than MAXVALUE (%lld)",
1543 (
long long) seqform->seqstart,
1544 (
long long) seqform->seqmax)));
1547 if (restart_value != NULL)
1549 if (restart_value->
arg != NULL)
1563 if (seqdataform->
last_value < seqform->seqmin)
1565 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1566 errmsg(
"RESTART value (%lld) cannot be less than MINVALUE (%lld)",
1568 (
long long) seqform->seqmin)));
1569 if (seqdataform->
last_value > seqform->seqmax)
1571 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1572 errmsg(
"RESTART value (%lld) cannot be greater than MAXVALUE (%lld)",
1574 (
long long) seqform->seqmax)));
1577 if (cache_value != NULL)
1580 if (seqform->seqcache <= 0)
1582 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1583 errmsg(
"CACHE (%lld) must be greater than zero",
1584 (
long long) seqform->seqcache)));
1589 seqform->seqcache = 1;
1618 (
errcode(ERRCODE_SYNTAX_ERROR),
1619 errmsg(
"invalid OWNED BY option"),
1620 errhint(
"Specify OWNED BY table.column or OWNED BY NONE.")));
1639 if (!(tablerel->
rd_rel->relkind == RELKIND_RELATION ||
1640 tablerel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1641 tablerel->
rd_rel->relkind == RELKIND_VIEW ||
1642 tablerel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1644 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1645 errmsg(
"sequence cannot be owned by relation \"%s\"",
1650 if (seqrel->
rd_rel->relowner != tablerel->
rd_rel->relowner)
1652 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1653 errmsg(
"sequence must have same owner as table it is linked to")));
1656 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1657 errmsg(
"sequence must be in same schema as table it is linked to")));
1663 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1664 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
1678 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1679 errmsg(
"cannot change ownership of identity sequence"),
1680 errdetail(
"Sequence \"%s\" is linked to table \"%s\".",
1690 RelationRelationId, deptype);
1697 refobject.
classId = RelationRelationId;
1700 depobject.
classId = RelationRelationId;
1724 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1761 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1762 errmsg(
"permission denied for sequence %s",
1766 elog(
ERROR,
"return type must be a row type");
1768 memset(isnull, 0,
sizeof(isnull));
1772 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1810 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1811 errmsg(
"permission denied for sequence %s",
1843 elog(
PANIC,
"seq_redo: unknown op code %u", info);
1868 elog(
PANIC,
"seq_redo: failed to add item to page");
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)
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 ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
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 BoolIsValid(boolean)
uint32 LocalTransactionId
#define OidIsValid(objectId)
elog(ERROR, "%s: %s", p2, msg)
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_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
HeapTuple heap_copytuple(HeapTuple tuple)
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)
Assert(fmt[strlen(fmt) - 1] !='\n')
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)
TypeName * makeTypeNameFromOid(Oid typeOid, int32 typmod)
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(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)
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
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
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
void smgrclose(SMgrRelation reln)
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
CollateClause * collClause
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)