Skip to content
Astera Technology

Why did the next migrated record reuse a deleted number?

Preserve the historical generator high-water value under the supplied no-reuse rule.

Download complete case notes and answer keys ↓

Read the source and its declared rule

This original target must not reuse a previously generated number. Source AUTOINCREMENT created 1 and 2, then deleted 2. Its actual sequence remains 2. Rebuilding an ordinary INTEGER PRIMARY KEY from surviving row 1 forgets that history; the controlled corrected rebuild carries the recorded sequence.

Filled synthetic input
RecordInput JSON
Base input{"created":[1,2],"deleted":[2]}
Download editable CSV ↓

Compare the actual paths

Bad next id is 2; corrected next id is 3. The code inspects source sqlite_sequence before copying, using a tiny synthetic database rather than a live generator repair.

Misleading and corrected outputs
PathOutput JSON
Misleading path{"previousSequence":2,"records":[{"id":1,"label":"old"},{"id":2,"label":"new"}]}
Corrected path{"previousSequence":2,"records":[{"id":1,"label":"old"},{"id":3,"label":"new"}]}
Download editable CSV ↓
Local Node.js program: 22.23.3 or 24.14.1
import {DatabaseSync} from 'node:sqlite';
import {TextDecoder} from 'node:util';
import {inflateSync} from 'node:zlib';
import {posix} from 'node:path';
import {createHash} from 'node:crypto';
const rows=(db,sql)=>db.prepare(sql).all().map(r=>({...r}));
const failed=(action)=>{try{action();return null;}catch(e){return {code:e.errcode??e.code??e.name};}};

import assert from 'node:assert/strict';
const run=function run(i,corrected=true){
    const db=new DatabaseSync(':memory:');try{db.exec('CREATE TABLE source(id INTEGER PRIMARY KEY AUTOINCREMENT,label TEXT);');
      for(const id of i.created)db.prepare('INSERT INTO source VALUES(?,?)').run(id,'old');
      for(const id of i.deleted)db.prepare('DELETE FROM source WHERE id=?').run(id);
      const sequence=db.prepare("SELECT seq FROM sqlite_sequence WHERE name='source'").get()?.seq??0;
      db.exec('CREATE TABLE target(id INTEGER PRIMARY KEY'+(corrected?' AUTOINCREMENT':'')+',label TEXT);INSERT INTO target SELECT * FROM source;');
      if(corrected){db.prepare("DELETE FROM sqlite_sequence WHERE name='target'").run();db.prepare('INSERT INTO sqlite_sequence(name,seq) VALUES(?,?)').run('target',sequence);}
      db.exec("INSERT INTO target(label) VALUES('new');");
      return {previousSequence:sequence,records:rows(db,'SELECT * FROM target ORDER BY id')};
    }finally{db.close();}
  };
const cases=[{"label":"misleading base","input":{"created":[1,2],"deleted":[2]},"expected":{"previousSequence":2,"records":[{"id":1,"label":"old"},{"id":2,"label":"new"}]},"corrected":false},{"label":"corrected base","input":{"created":[1,2],"deleted":[2]},"expected":{"previousSequence":2,"records":[{"id":1,"label":"old"},{"id":3,"label":"new"}]},"corrected":true},{"label":"highest old row still present","input":{"created":[1,2],"deleted":[]},"expected":{"previousSequence":2,"records":[{"id":1,"label":"old"},{"id":2,"label":"old"},{"id":3,"label":"new"}]},"corrected":true},{"label":"empty no-history source","input":{"created":[],"deleted":[]},"expected":{"previousSequence":0,"records":[{"id":1,"label":"new"}]},"corrected":true}];
for(const test of cases){
  const actual=run(test.input,test.corrected);
  assert.deepEqual(actual,test.expected,test.label);
  console.log(test.label,actual);
}
Download runnable example ↓

Check boundaries before the next load

If id 2 remains, next 3 agrees naturally. A genuinely empty no-history source starts at 1.

Editable boundary records and expected outputs
CaseInput JSONExpected output JSON
Highest row remains present{"created":[1,2],"deleted":[]}{"previousSequence":2,"records":[{"id":1,"label":"old"},{"id":2,"label":"old"},{"id":3,"label":"new"}]}
No generated history{"created":[],"deleted":[]}{"previousSequence":0,"records":[{"id":1,"label":"new"}]}
Download editable CSV ↓

Is surviving maximum id 1 sufficient history for this policy?

Show the worked answer

No. Deleted id 2 was already generated. Carry sequence 2 so the next new record receives 3.

Related resources