From 08e1008c91ceba2274cde22527ef1844c3927337 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Mon, 20 Jan 2025 15:49:52 +0000 Subject: [PATCH] Support old history items by rewriting old typedescs to v2 format --- shared/studio/idbStore/index.ts | 12 ++- shared/studio/utils/rewriteTypedesc.ts | 144 +++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 shared/studio/utils/rewriteTypedesc.ts diff --git a/shared/studio/idbStore/index.ts b/shared/studio/idbStore/index.ts index 0f605b26..e8f5bac8 100644 --- a/shared/studio/idbStore/index.ts +++ b/shared/studio/idbStore/index.ts @@ -2,6 +2,7 @@ import {openDB, DBSchema, IDBPDatabase} from "idb"; import {ProtocolVersion} from "edgedb/dist/ifaces"; import {StoredSchemaData} from "../state/database"; import {StoredSessionStateData} from "../state/sessionState"; +import {rewriteTypedesc} from "../utils/rewriteTypedesc"; export interface QueryHistoryItem { instanceId: string; @@ -283,7 +284,16 @@ export function clearReplHistory( } export async function fetchResultData(itemId: string) { - return retryingIDBRequest((db) => db.get("queryResultData", itemId)); + return retryingIDBRequest(async (db) => { + const res = await db.get("queryResultData", itemId); + return res && !res.protoVer + ? { + ...res, + outCodecBuf: rewriteTypedesc(res.outCodecBuf), + protoVer: [2, 0] as ProtocolVersion, + } + : res; + }); } // schema data diff --git a/shared/studio/utils/rewriteTypedesc.ts b/shared/studio/utils/rewriteTypedesc.ts new file mode 100644 index 00000000..7906e343 --- /dev/null +++ b/shared/studio/utils/rewriteTypedesc.ts @@ -0,0 +1,144 @@ +import {ReadBuffer, WriteBuffer} from "edgedb/dist/primitives/buffer"; + +// converts a v1 encoded typedesc to a v2 encoded typedesc +export function rewriteTypedesc(oldDesc: Uint8Array): Uint8Array { + const oldBuf = new ReadBuffer(oldDesc); + + const typenames = new Map(); + const typedescs: [string, Uint8Array][] = []; + while (oldBuf.length) { + const descBuf = _rewrite(oldBuf, typenames); + if (descBuf) { + typedescs.push(descBuf); + } + } + + const newBuf = new WriteBuffer(); + for (const [tid, typedesc] of typedescs) { + if (typenames.has(tid)) { + const finalise = newBuf.writeDeferredSize(); + newBuf + .writeBuffer(typedesc.subarray(0, 17)) + .writeString(typenames.get(tid)!) + .writeBuffer(typedesc.subarray(21)); + finalise(); + } else { + newBuf.writeBytes(typedesc); + } + } + + return newBuf.unwrap(); +} + +const CTYPE_SET = 0; +const CTYPE_SHAPE = 1; +const CTYPE_SCALAR = 3; +const CTYPE_TUPLE = 4; +const CTYPE_NAMEDTUPLE = 5; +const CTYPE_ARRAY = 6; +const CTYPE_ENUM = 7; +const CTYPE_INPUT_SHAPE = 8; +const CTYPE_RANGE = 9; +const CTYPE_MULTIRANGE = 12; + +function _rewrite( + oldBuf: ReadBuffer, + typenames: Map +): [string, Uint8Array] | null { + const t = oldBuf.readUInt8(); + const tid = oldBuf.readUUID(); + + if (t >= 0x7f && t <= 0xff) { + if (t === 0xff) { + const typeName = oldBuf.readString(); + typenames.set(tid, typeName); + } else { + oldBuf.discard(oldBuf.readUInt32()); + } + return null; + } + + const newBuf = new WriteBuffer(); + + newBuf.writeUInt8(t); + // @ts-ignore + oldBuf.pos -= 16; + newBuf.writeBuffer(oldBuf.readBuffer(16)); + + switch (t) { + case CTYPE_SHAPE: + case CTYPE_INPUT_SHAPE: { + if (t === CTYPE_SHAPE) { + newBuf.writeUInt8(0).writeInt16(-1); + } + + const els = oldBuf.readUInt16(); + newBuf.writeUInt16(els); + for (let i = 0; i < els; i++) { + newBuf.writeBuffer(oldBuf.readBuffer(5)); + newBuf.writeBytes(oldBuf.readBuffer(oldBuf.readUInt32())); + newBuf.writeUInt16(oldBuf.readUInt16()); + + if (t === CTYPE_SHAPE) { + newBuf.writeInt16(-1); + } + } + break; + } + + case CTYPE_SET: { + newBuf.writeUInt16(oldBuf.readUInt16()); + break; + } + + case CTYPE_SCALAR: { + const pos = oldBuf.readUInt16(); + newBuf.writeString("").writeUInt8(0).writeUInt16(1).writeUInt16(pos); + break; + } + + case CTYPE_ARRAY: { + newBuf.writeString("").writeUInt8(0).writeUInt16(0); + newBuf.writeBuffer(oldBuf.readBuffer(8)); + break; + } + + case CTYPE_TUPLE: { + newBuf.writeString("").writeUInt8(0).writeUInt16(0); + const els = oldBuf.readUInt16(); + newBuf.writeUInt16(els).writeBuffer(oldBuf.readBuffer(els * 2)); + break; + } + + case CTYPE_NAMEDTUPLE: { + newBuf.writeString("").writeUInt8(0).writeUInt16(0); + const els = oldBuf.readUInt16(); + newBuf.writeUInt16(els); + for (let i = 0; i < els; i++) { + const len = oldBuf.readUInt32(); + newBuf.writeUInt32(len).writeBuffer(oldBuf.readBuffer(len + 2)); + } + break; + } + + case CTYPE_ENUM: { + newBuf.writeString("").writeUInt8(0).writeUInt16(0); + const els = oldBuf.readUInt16(); + newBuf.writeUInt16(els); + for (let i = 0; i < els; i++) { + const len = oldBuf.readUInt32(); + newBuf.writeUInt32(len).writeBuffer(oldBuf.readBuffer(len)); + } + break; + } + + case CTYPE_RANGE: + case CTYPE_MULTIRANGE: { + newBuf.writeString("").writeUInt8(0).writeUInt16(0); + newBuf.writeUInt16(oldBuf.readUInt16()); + break; + } + } + + return [tid, newBuf.unwrap()]; +}