59#define SEQ_LOG_VALS 32
64#define SEQ_MAGIC 0x1717
113 bool *need_seq_rewrite,
129 bool need_seq_rewrite;
139 Datum pgs_values[Natts_pg_sequence];
140 bool pgs_nulls[Natts_pg_sequence];
162 (
errcode(ERRCODE_DUPLICATE_TABLE),
163 errmsg(
"relation \"%s\" already exists, skipping",
171 &seqform, &last_value, &reset_state, &is_called,
172 &need_seq_rewrite, &owned_by);
209 stmt->tablespacename = NULL;
233 memset(pgs_nulls, 0,
sizeof(pgs_nulls));
236 pgs_values[Anum_pg_sequence_seqtypid - 1] =
ObjectIdGetDatum(seqform.seqtypid);
238 pgs_values[Anum_pg_sequence_seqincrement - 1] =
Int64GetDatumFast(seqform.seqincrement);
242 pgs_values[Anum_pg_sequence_seqcycle - 1] =
BoolGetDatum(seqform.seqcycle);
288 elog(
ERROR,
"cache lookup failed for sequence %u", seq_relid);
290 startv = pgsform->seqstart;
346 if (rel->
rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
408 elog(
ERROR,
"failed to add sequence tuple to page");
449 bool need_seq_rewrite;
454 bool reset_state =
false;
468 (
errmsg(
"relation \"%s\" does not exist, skipping",
469 stmt->sequence->relname)));
479 elog(
ERROR,
"cache lookup failed for sequence %u",
497 seqform, &last_value, &reset_state, &is_called,
498 &need_seq_rewrite, &owned_by);
501 if (need_seq_rewrite)
591 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
661 if (check_permissions &&
665 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
666 errmsg(
"permission denied for sequence %s",
692 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
694 incby = pgsform->seqincrement;
695 maxv = pgsform->seqmax;
696 minv = pgsform->seqmin;
697 cache = pgsform->seqcache;
698 cycle = pgsform->seqcycle;
725 if (log < fetch || !seq->is_called)
752 if ((maxv >= 0 &&
next > maxv - incby) ||
753 (maxv < 0 && next + incby > maxv))
759 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
760 errmsg(
"nextval: reached maximum value of sequence \"%s\" (%" PRId64
")",
771 if ((minv < 0 &&
next < minv - incby) ||
772 (minv >= 0 &&
next + incby < minv))
778 (
errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
779 errmsg(
"nextval: reached minimum value of sequence \"%s\" (%" PRId64
")",
891 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
892 errmsg(
"permission denied for sequence %s",
897 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
898 errmsg(
"currval of sequence \"%s\" 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")));
922 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
923 errmsg(
"lastval is not yet defined in this session")));
933 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
934 errmsg(
"permission denied for sequence %s",
974 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
975 errmsg(
"permission denied for sequence %s",
980 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
982 maxv = pgsform->seqmax;
983 minv = pgsform->seqmin;
1000 if ((
next < minv) || (
next > maxv))
1002 (
errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1003 errmsg(
"setval: value %" PRId64
" is out of bounds for sequence \"%s\" (%" PRId64
"..%" PRId64
")",
1102 if (seq->
lxid != thislxid)
1114 seq->
lxid = thislxid;
1129 ctl.keysize =
sizeof(
Oid);
1216 elog(
ERROR,
"bad magic number in sequence \"%s\": %08X",
1277 bool *need_seq_rewrite,
1282 DefElem *restart_value = NULL;
1289 bool reset_max_value =
false;
1290 bool reset_min_value =
false;
1292 *need_seq_rewrite =
false;
1299 if (strcmp(defel->
defname,
"as") == 0)
1304 *need_seq_rewrite =
true;
1306 else if (strcmp(defel->
defname,
"increment") == 0)
1310 increment_by = defel;
1311 *need_seq_rewrite =
true;
1313 else if (strcmp(defel->
defname,
"start") == 0)
1317 start_value = defel;
1318 *need_seq_rewrite =
true;
1320 else if (strcmp(defel->
defname,
"restart") == 0)
1324 restart_value = defel;
1325 *need_seq_rewrite =
true;
1327 else if (strcmp(defel->
defname,
"maxvalue") == 0)
1332 *need_seq_rewrite =
true;
1334 else if (strcmp(defel->
defname,
"minvalue") == 0)
1339 *need_seq_rewrite =
true;
1341 else if (strcmp(defel->
defname,
"cache") == 0)
1345 cache_value = defel;
1346 *need_seq_rewrite =
true;
1348 else if (strcmp(defel->
defname,
"cycle") == 0)
1353 *need_seq_rewrite =
true;
1355 else if (strcmp(defel->
defname,
"owned_by") == 0)
1361 else if (strcmp(defel->
defname,
"sequence_name") == 0)
1372 (
errcode(ERRCODE_SYNTAX_ERROR),
1373 errmsg(
"invalid sequence option SEQUENCE NAME"),
1377 elog(
ERROR,
"option \"%s\" not recognized",
1386 *reset_state =
true;
1389 if (as_type != NULL)
1393 if (newtypid != INT2OID &&
1394 newtypid != INT4OID &&
1395 newtypid != INT8OID)
1397 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1399 ?
errmsg(
"identity column type must be smallint, integer, or bigint")
1400 :
errmsg(
"sequence type must be smallint, integer, or bigint")));
1410 if ((seqform->seqtypid == INT2OID && seqform->seqmax ==
PG_INT16_MAX) ||
1411 (seqform->seqtypid == INT4OID && seqform->seqmax ==
PG_INT32_MAX) ||
1412 (seqform->seqtypid == INT8OID && seqform->seqmax ==
PG_INT64_MAX))
1413 reset_max_value =
true;
1414 if ((seqform->seqtypid == INT2OID && seqform->seqmin ==
PG_INT16_MIN) ||
1415 (seqform->seqtypid == INT4OID && seqform->seqmin ==
PG_INT32_MIN) ||
1416 (seqform->seqtypid == INT8OID && seqform->seqmin ==
PG_INT64_MIN))
1417 reset_min_value =
true;
1420 seqform->seqtypid = newtypid;
1424 seqform->seqtypid = INT8OID;
1428 if (increment_by != NULL)
1430 seqform->seqincrement =
defGetInt64(increment_by);
1431 if (seqform->seqincrement == 0)
1433 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1434 errmsg(
"INCREMENT must not be zero")));
1435 *reset_state =
true;
1439 seqform->seqincrement = 1;
1443 if (is_cycled != NULL)
1447 *reset_state =
true;
1451 seqform->seqcycle =
false;
1455 if (max_value != NULL && max_value->
arg)
1458 *reset_state =
true;
1460 else if (isInit || max_value != NULL || reset_max_value)
1462 if (seqform->seqincrement > 0 || reset_max_value)
1465 if (seqform->seqtypid == INT2OID)
1467 else if (seqform->seqtypid == INT4OID)
1473 seqform->seqmax = -1;
1474 *reset_state =
true;
1481 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1482 errmsg(
"MAXVALUE (%" PRId64
") is out of range for sequence data type %s",
1487 if (min_value != NULL && min_value->
arg)
1490 *reset_state =
true;
1492 else if (isInit || min_value != NULL || reset_min_value)
1494 if (seqform->seqincrement < 0 || reset_min_value)
1497 if (seqform->seqtypid == INT2OID)
1499 else if (seqform->seqtypid == INT4OID)
1505 seqform->seqmin = 1;
1506 *reset_state =
true;
1513 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1514 errmsg(
"MINVALUE (%" PRId64
") is out of range for sequence data type %s",
1519 if (seqform->seqmin >= seqform->seqmax)
1521 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1522 errmsg(
"MINVALUE (%" PRId64
") must be less than MAXVALUE (%" PRId64
")",
1527 if (start_value != NULL)
1533 if (seqform->seqincrement > 0)
1534 seqform->seqstart = seqform->seqmin;
1536 seqform->seqstart = seqform->seqmax;
1540 if (seqform->seqstart < seqform->seqmin)
1542 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1543 errmsg(
"START value (%" PRId64
") cannot be less than MINVALUE (%" PRId64
")",
1546 if (seqform->seqstart > seqform->seqmax)
1548 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1549 errmsg(
"START value (%" PRId64
") cannot be greater than MAXVALUE (%" PRId64
")",
1554 if (restart_value != NULL)
1556 if (restart_value->
arg != NULL)
1559 *last_value = seqform->seqstart;
1561 *reset_state =
true;
1565 *last_value = seqform->seqstart;
1570 if (*last_value < seqform->seqmin)
1572 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1573 errmsg(
"RESTART value (%" PRId64
") cannot be less than MINVALUE (%" PRId64
")",
1576 if (*last_value > seqform->seqmax)
1578 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1579 errmsg(
"RESTART value (%" PRId64
") cannot be greater than MAXVALUE (%" PRId64
")",
1584 if (cache_value != NULL)
1587 if (seqform->seqcache <= 0)
1589 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1590 errmsg(
"CACHE (%" PRId64
") must be greater than zero",
1591 seqform->seqcache)));
1592 *reset_state =
true;
1596 seqform->seqcache = 1;
1625 (
errcode(ERRCODE_SYNTAX_ERROR),
1626 errmsg(
"invalid OWNED BY option"),
1627 errhint(
"Specify OWNED BY table.column or OWNED BY NONE.")));
1646 if (!(tablerel->
rd_rel->relkind == RELKIND_RELATION ||
1647 tablerel->
rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1648 tablerel->
rd_rel->relkind == RELKIND_VIEW ||
1649 tablerel->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1651 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1652 errmsg(
"sequence cannot be owned by relation \"%s\"",
1657 if (seqrel->
rd_rel->relowner != tablerel->
rd_rel->relowner)
1659 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1660 errmsg(
"sequence must have same owner as table it is linked to")));
1663 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1664 errmsg(
"sequence must be in same schema as table it is linked to")));
1670 (
errcode(ERRCODE_UNDEFINED_COLUMN),
1671 errmsg(
"column \"%s\" of relation \"%s\" does not exist",
1685 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1686 errmsg(
"cannot change ownership of identity sequence"),
1687 errdetail(
"Sequence \"%s\" is linked to table \"%s\".",
1697 RelationRelationId, deptype);
1704 refobject.
classId = RelationRelationId;
1707 depobject.
classId = RelationRelationId;
1731 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1768 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1769 errmsg(
"permission denied for sequence %s",
1773 elog(
ERROR,
"return type must be a row type");
1775 memset(isnull, 0,
sizeof(isnull));
1779 elog(
ERROR,
"cache lookup failed for sequence %u", relid);
1806#define PG_GET_SEQUENCE_DATA_COLS 3
1850 memset(isnull,
true,
sizeof(isnull));
1857#undef PG_GET_SEQUENCE_DATA_COLS
1872 bool is_called =
false;
1925 elog(
PANIC,
"seq_redo: unknown op code %u", info);
1949 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)
#define PageGetSpecialPointer(page)
static void * PageGetItem(const PageData *page, const ItemIdData *itemId)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static XLogRecPtr PageGetLSN(const PageData *page)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
#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)
List * sequence_options(Oid relid)
static SeqTableData * last_used_seq
ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
Datum pg_sequence_parameters(PG_FUNCTION_ARGS)
void SetSequence(Oid relid, int64 next, bool iscalled)
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 pg_get_sequence_data(PG_FUNCTION_ARGS)
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)
#define PG_GET_SEQUENCE_DATA_COLS
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)
void seq_redo(XLogReaderState *record)
struct SeqTableData SeqTableData
void ResetSequenceCaches(void)
static void create_seq_hashtable(void)
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, int64 *last_value, bool *reset_state, bool *is_called, bool *need_seq_rewrite, List **owned_by)
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
TypeName * defGetTypeName(DefElem *def)
List * defGetQualifiedName(DefElem *def)
int64 defGetInt64(DefElem *def)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
void hash_destroy(HTAB *hashp)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
#define PG_GETARG_TEXT_PP(n)
#define PG_RETURN_INT64(x)
#define PG_GETARG_INT64(n)
#define PG_GETARG_BOOL(n)
#define PG_RETURN_DATUM(x)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Assert(PointerIsAligned(start, uint64))
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)
static void HeapTupleHeaderSetXminFrozen(HeapTupleHeaderData *tup)
static void HeapTupleHeaderSetCmin(HeapTupleHeaderData *tup, CommandId cid)
static TransactionId HeapTupleHeaderGetRawXmax(const HeapTupleHeaderData *tup)
#define HEAP_XMAX_IS_MULTI
#define HEAP_XMAX_INVALID
static void * GETSTRUCT(const HeapTupleData *tuple)
static void HeapTupleHeaderSetXmin(HeapTupleHeaderData *tup, TransactionId xid)
static void HeapTupleHeaderSetXmax(HeapTupleHeaderData *tup, TransactionId xid)
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *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
char * get_rel_name(Oid relid)
AttrNumber get_attnum(Oid relid, const char *attname)
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)
static Datum LSNGetDatum(XLogRecPtr X)
FormData_pg_sequence * Form_pg_sequence
static Datum Int64GetDatum(int64 X)
#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
TupleDesc CreateTemplateTupleDesc(int natts)
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
void PreventCommandIfReadOnly(const char *cmdname)
void PreventCommandIfParallelMode(const char *cmdname)
Float * makeFloat(char *numericStr)
Boolean * makeBoolean(bool val)
List * textToQualifiedNameList(text *textval)
TransactionId GetTopTransactionId(void)
bool RecoveryInProgress(void)
XLogRecPtr GetRedoRecPtr(void)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterData(const void *data, uint32 len)
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)