Skip to content

Commit 91f84d0

Browse files
fix(indexer-sqlite3): map fixedArray(u8) parent ids as BLOB
Fix nested table __parent_id type for fixedArray(u8) primary keys and add regression coverage.
2 parents d4fb855 + 35fd560 commit 91f84d0

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed

packages/utils/indexer/sqlite3/src/schema.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,14 @@ const resolvePrimaryFieldInfoFromSchema = (
207207
fieldType = fieldType.elementType;
208208
}
209209

210-
fieldType = unwrapNestedType(fieldType);
210+
// fixedArray(u8, N) represents bytes and must map to BLOB in SQL. Note that
211+
// FixedArrayKind is also a WrappedType, so unwrapNestedType() would otherwise
212+
// turn it into the scalar "u8" and incorrectly treat it as INTEGER.
213+
if (fieldType instanceof FixedArrayKind && fieldType.elementType === "u8") {
214+
fieldType = Uint8Array;
215+
} else {
216+
fieldType = unwrapNestedType(fieldType);
217+
}
211218

212219
// Arrays are always stored in separate tables.
213220
if (fieldType instanceof VecKind) {

packages/utils/indexer/sqlite3/test/schema.spec.ts

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { field, variant } from "@dao-xyz/borsh";
1+
import { field, fixedArray, variant } from "@dao-xyz/borsh";
22
import { id } from "@peerbit/indexer-interface";
33
import { expect } from "chai";
44
import {
@@ -33,7 +33,7 @@ describe("schema", () => {
3333
abstract class ChildBase {}
3434

3535
@variant(0)
36-
class ChildV0 extends ChildBase {
36+
class _ChildV0 extends ChildBase {
3737
@field({ type: "string" })
3838
value: string;
3939

@@ -44,7 +44,7 @@ describe("schema", () => {
4444
}
4545

4646
@variant(1)
47-
class ChildV1 extends ChildBase {
47+
class _ChildV1 extends ChildBase {
4848
@field({ type: "string" })
4949
value: string;
5050

@@ -90,5 +90,53 @@ describe("schema", () => {
9090
);
9191
}
9292
});
93+
94+
it("uses bytes primary key for child FKs", () => {
95+
abstract class ChildBase {}
96+
97+
@variant(0)
98+
class _ChildV0 extends ChildBase {
99+
@field({ type: "string" })
100+
value: string;
101+
102+
constructor(value: string) {
103+
super();
104+
this.value = value;
105+
}
106+
}
107+
108+
@variant("Root")
109+
class Root {
110+
// Intentionally declared before the primary key.
111+
@field({ type: ChildBase })
112+
child: ChildBase;
113+
114+
@id({ type: fixedArray("u8", 32) })
115+
id: Uint8Array;
116+
117+
constructor(id: Uint8Array, child: ChildBase) {
118+
this.id = id;
119+
this.child = child;
120+
}
121+
}
122+
123+
const primary = getInlineTableFieldName(["id"]);
124+
const [rootTable] = getSQLTable(Root, [], primary, false, undefined, false);
125+
expect(rootTable).to.exist;
126+
expect(rootTable.children.length).to.equal(1);
127+
128+
const [childTable] = rootTable.children;
129+
expect(childTable.inline).to.equal(false);
130+
131+
const parentIdField = childTable.fields.find((f) => f.name === "__parent_id");
132+
expect(parentIdField?.type).to.equal("BLOB");
133+
134+
const fkConstraint = childTable.constraints.find(
135+
(c) => c.name === "__parent_id_fk",
136+
);
137+
expect(fkConstraint?.definition).to.include(
138+
`REFERENCES ${rootTable.name}(${primary})`,
139+
);
140+
});
93141
});
94142
});

0 commit comments

Comments
 (0)