Skip to content

Commit

Permalink
Reusable gaps (#364)
Browse files Browse the repository at this point in the history
  • Loading branch information
kearfy authored Oct 18, 2024
1 parent 2dbbfc5 commit 065e799
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 4 deletions.
20 changes: 17 additions & 3 deletions src/util/prepared-query.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Encoded,
type Fill,
Gap,
type PartiallyEncoded,
Writer,
encode,
Expand Down Expand Up @@ -47,9 +48,22 @@ export class PreparedQuery {
): PreparedQuery {
const base = this.length;
this.length += values.length;
const mapped_bindings = values.map(
(v, i) => [`bind___${base + i}`, v] as const,
);

let reused = 0;
const gaps = new Map<Gap, number>();
const mapped_bindings = values.map((v, i) => {
if (v instanceof Gap) {
const index = gaps.get(v);
if (index !== undefined) {
reused++;
return [`bind___${index}`, v] as const;
}

gaps.set(v, i - reused);
}

return [`bind___${base + i - reused}`, v] as const;
});

for (const [k, v] of mapped_bindings) {
this._bindings[k] = encode(v, {
Expand Down
18 changes: 17 additions & 1 deletion src/util/tagged-template.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import { Gap } from "../cbor/gap.ts";
import { PreparedQuery } from "./prepared-query.ts";

export function surrealql(
query_raw: string[] | TemplateStringsArray,
...values: unknown[]
): PreparedQuery {
const mapped_bindings = values.map((v, i) => [`bind___${i}`, v] as const);
let reused = 0;
const gaps = new Map<Gap, number>();
const mapped_bindings = values.map((v, i) => {
if (v instanceof Gap) {
const index = gaps.get(v);
if (index !== undefined) {
reused++;
return [`bind___${index}`, v] as const;
}

gaps.set(v, i - reused);
}

return [`bind___${i - reused}`, v] as const;
});

const bindings = mapped_bindings.reduce<Record<`bind___${number}`, unknown>>(
(prev, [k, v]) => {
prev[k] = v;
Expand Down
33 changes: 33 additions & 0 deletions tests/integration/tests/querying.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,39 @@ describe("template literal", async () => {
},
]);
});

test("reused gap", async () => {
const foo = new Gap();
const bar = new Gap();
const query = surql`RETURN [${foo}, ${bar}, ${1}, ${foo}, ${bar}, ${2}]`;
expect(Object.keys(query.bindings)).toStrictEqual([
"bind___0",
"bind___1",
"bind___2",
"bind___3",
]);

// Ensure appended segments also re-use
query.append`; RETURN [${foo}, ${bar}, ${1}, ${foo}, ${bar}, ${2}]`;
expect(Object.keys(query.bindings)).toStrictEqual([
"bind___0",
"bind___1",
"bind___2",
"bind___3",
"bind___4",
"bind___5",
"bind___6",
"bind___7",
]);

// Check result
const res = await surreal.query(query, [foo.fill("a"), bar.fill("b")]);

expect(res).toStrictEqual([
["a", "b", 1, "a", "b", 2],
["a", "b", 1, "a", "b", 2],
]);
});
});

test("query", async () => {
Expand Down

0 comments on commit 065e799

Please sign in to comment.