跳至內容
Astera Technology

搬移合成一組後,為何不能單靠目標還原原標籤?

轉換會丟資料,就須保留精確回復所需原資料。

下載完整個案資料及參考答案 ↓

先核來源與已訂規則

本例向前步驟把 1/A、2/B 合成 1/Group,再刪原 SQLite 表。目標已沒有兩原行。已准精確資料回復要用保留原資料;未留就暫停,不虛構標籤。

已填假設輸入
紀錄輸入 JSON
原例輸入{"original":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"collapse":true,"keepPreimage":true}
下載可編輯 CSV ↓

比較兩條實際路徑

更正從真正原資料表還原 1/A、2/B。只把目標拷回,仍只有 Group,沒有補回已丟資料。

錯誤與更正路徑的輸出
路徑輸出 JSON
錯誤路徑{"error":null,"target":[{"id":1,"label":"Group"}],"restored":[{"id":1,"label":"Group"}]}
更正路徑{"error":null,"target":[{"id":1,"label":"Group"}],"restored":[{"id":1,"label":"A"},{"id":2,"label":"B"}]}
下載可編輯 CSV ↓
本地 Node.js 程序:22.23.3 或 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 original(id INTEGER PRIMARY KEY,label TEXT);CREATE TABLE target(id INTEGER PRIMARY KEY,label TEXT);CREATE TABLE restored(id INTEGER PRIMARY KEY,label TEXT);');
      for(const r of i.original)db.prepare('INSERT INTO original VALUES(?,?)').run(r.id,r.label);
      if(i.keepPreimage)db.exec('CREATE TABLE preimage AS SELECT * FROM original;');
      if(i.collapse&&i.original.length)db.exec("INSERT INTO target VALUES(1,'Group');");else db.exec('INSERT INTO target SELECT * FROM original;');
      db.exec('DROP TABLE original;');let error=null;
      if(corrected&&i.collapse){if(!i.keepPreimage)error='missing-preimage';else db.exec('INSERT INTO restored SELECT * FROM preimage;');}
      else db.exec('INSERT INTO restored SELECT * FROM target;');
      return {error,target:rows(db,'SELECT * FROM target ORDER BY id'),restored:rows(db,'SELECT * FROM restored ORDER BY id')};
    }finally{db.close();}
  };
const cases=[{"label":"misleading base","input":{"original":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"collapse":true,"keepPreimage":true},"expected":{"error":null,"target":[{"id":1,"label":"Group"}],"restored":[{"id":1,"label":"Group"}]},"corrected":false},{"label":"corrected base","input":{"original":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"collapse":true,"keepPreimage":true},"expected":{"error":null,"target":[{"id":1,"label":"Group"}],"restored":[{"id":1,"label":"A"},{"id":2,"label":"B"}]},"corrected":true},{"label":"lossy target without preimage cannot restore","input":{"original":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"collapse":true,"keepPreimage":false},"expected":{"error":"missing-preimage","target":[{"id":1,"label":"Group"}],"restored":[]},"corrected":true},{"label":"identity transition has direct inverse","input":{"original":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"collapse":false,"keepPreimage":false},"expected":{"error":null,"target":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"restored":[{"id":1,"label":"A"},{"id":2,"label":"B"}]},"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);
}
下載可執行例子 ↓

下次載入前核邊界

有損目標未留原資料便停;沒有合併的恆等轉換,則可直接精確逆回。

可編輯邊界紀錄及預期輸出
情況輸入 JSON預期輸出 JSON
有損目標未留原資料{"original":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"collapse":true,"keepPreimage":false}{"error":"missing-preimage","target":[{"id":1,"label":"Group"}],"restored":[]}
可直接逆回的恆等轉換{"original":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"collapse":false,"keepPreimage":false}{"error":null,"target":[{"id":1,"label":"A"},{"id":2,"label":"B"}],"restored":[{"id":1,"label":"A"},{"id":2,"label":"B"}]}
下載可編輯 CSV ↓

只見 Group,可確定舊標籤就是 A、B 嗎?

查看參考答案

不可,要靠保留原資料才有這兩個精確行;否則不能聲稱已精確回復。

相關資源