Skip to content

Commit

Permalink
Use more robust raw string quoting (#1098)
Browse files Browse the repository at this point in the history
Input data is likely to contain the string `"$$"`, so use an
interstitial label to make it less likely to collide with typical JSON
data.
  • Loading branch information
scotttrinh authored Sep 10, 2024
1 parent f500235 commit b3ca106
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
7 changes: 5 additions & 2 deletions integration-tests/lts/literals.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,13 @@ describe("literals", () => {
);
assert.equal(e.year("1234").toEdgeQL(), `<default::year>1234`);

assert.equal(e.std.json("asdf").toEdgeQL(), `to_json($$"asdf"$$)`);
assert.equal(
e.std.json("asdf$$$*").toEdgeQL(),
`to_json($jsonliteral$"asdf$$$*"$jsonliteral$)`,
);
assert.equal(
e.std.json({ a: 123, b: "some string", c: [true, false] }).toEdgeQL(),
'to_json($${"a":123,"b":"some string","c":[true,false]}$$)',
'to_json($jsonliteral${"a":123,"b":"some string","c":[true,false]}$jsonliteral$)',
);

assert.equal(e.std.str(`asdfaf`).toEdgeQL(), `"asdfaf"`);
Expand Down
19 changes: 19 additions & 0 deletions integration-tests/lts/select.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1559,4 +1559,23 @@ SELECT __scope_0_defaultPerson {
>
>(true);
});

test("select json literal", async () => {
const q = e.select({
jsonLiteral: e.json("$jsonliteral$delete Person"),
});

const result = await q.run(client);
assert.deepEqual(result, { jsonLiteral: "$jsonliteral$delete Person" });
});

test("select json literal: counter overflow", async () => {
let testString = "$jsonliteral$";
for (let i = 0; i < 100; i++) {
testString += `$jsonliteral${i}$`;
}
const q = e.select(e.json(testString));

assert.rejects(() => q.run(client), edgedb.InputDataError);
});
});
24 changes: 23 additions & 1 deletion packages/generate/src/syntax/toEdgeQL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
RelativeDuration,
DateDuration,
Range,
InputDataError,
} from "edgedb";
import {
Cardinality,
Expand Down Expand Up @@ -1448,13 +1449,34 @@ const numericalTypes: Record<string, boolean> = {
"std::float64": true,
};

function makeLabel(stringified: string): string {
const MAX_ITERATIONS = 100;
const prefix = "jsonliteral";
let counter = 0;
let label = `${prefix}`;

while (stringified.includes(`$${label}$`) && counter < MAX_ITERATIONS) {
label = `${prefix}${counter}`;
counter++;
}

if (counter >= MAX_ITERATIONS) {
throw new InputDataError(
"Counter reached 100 without finding a unique label.",
);
}
return label;
}

function literalToEdgeQL(type: BaseType, val: any): string {
const typename = (type as any).__casttype__?.__name__ ?? type.__name__;
let skipCast = false;
let stringRep;
if (typename === "std::json") {
skipCast = true;
stringRep = `to_json($$${JSON.stringify(val)}$$)`;
const stringified = JSON.stringify(val);
const label = `$${makeLabel(stringified)}$`;
stringRep = `to_json(${label}${JSON.stringify(val)}${label})`;
} else if (typeof val === "string") {
if (numericalTypes[typename]) {
skipCast = typename === type.__name__;
Expand Down

0 comments on commit b3ca106

Please sign in to comment.