diff --git a/skills/clickhouse-js-node-rowbinary/src/readers/compile.ts b/skills/clickhouse-js-node-rowbinary/src/readers/compile.ts index 9f3861be..5a3dd099 100644 --- a/skills/clickhouse-js-node-rowbinary/src/readers/compile.ts +++ b/skills/clickhouse-js-node-rowbinary/src/readers/compile.ts @@ -162,6 +162,8 @@ function dataTypeReader(node: Node): Reader { return variantReader(node); case "Nested": return nestedReader(node); + case "Tuple": + return tupleReader(node); // --- parameterized scalars --- case "FixedString": @@ -211,7 +213,9 @@ function tupleReader(node: Node): Reader { const readers = node.arguments.map(astToReader); const names = node.element_names; const named = - names.length === readers.length && names.every((n) => n.length > 0); + names.length > 0 && + names.length === readers.length && + names.every((n) => n.length > 0); if (named) { const fields: Record> = {}; for (let i = 0; i < names.length; i++) fields[names[i]!] = readers[i]!; diff --git a/skills/clickhouse-js-node-rowbinary/tests/compile.test.ts b/skills/clickhouse-js-node-rowbinary/tests/compile.test.ts index 475cec9e..6f48516a 100644 --- a/skills/clickhouse-js-node-rowbinary/tests/compile.test.ts +++ b/skills/clickhouse-js-node-rowbinary/tests/compile.test.ts @@ -111,4 +111,25 @@ describe("astToReader (AST -> Reader fold)", () => { /cannot build a column reader/, ); }); + + it("folds an empty Tuple to an empty array reader", () => { + const read = reader("Tuple()"); + const s = new Cursor(Buffer.alloc(0)); + expect(read(s)).toEqual([]); + expect(s.pos).toBe(0); + }); + + it("folds a nested empty Tuple", () => { + const read = reader("Tuple(Tuple())"); + const s = new Cursor(Buffer.alloc(0)); + expect(read(s)).toEqual([[]]); + expect(s.pos).toBe(0); + }); + + it("folds an empty Tuple alongside other columns", () => { + const read = reader("Tuple(Tuple(), UInt8)"); + const s = new Cursor(Buffer.from([0x05])); + expect(read(s)).toEqual([[], 5]); + expect(s.pos).toBe(1); + }); });