Skip to content

Commit eea3f34

Browse files
committed
fix(vnext): authenticate join continuations
1 parent 8fc0a97 commit eea3f34

4 files changed

Lines changed: 429 additions & 88 deletions

File tree

docs/adr/0005-parser-independent-relation-completion.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,20 @@ embedded region are unavailable or inactive according to the closed result.
9797
CTE visibility is the one narrow scope-semantics exception; general
9898
parser-derived scope semantics remain deferred.
9999

100+
The recognizer may cross a `USING` join constraint only after authenticating
101+
the complete bounded grammar `USING(identifier [, identifier ...])` with
102+
dialect-owned identifier validation. It does not interpret `ON` expressions:
103+
encountering `ON` makes the query site unavailable until a future
104+
parser-backed or separately specified expression recognizer can prove the
105+
boundary.
106+
100107
The conformance corpus includes positive base `FROM`, qualified prefix,
101-
aliased `JOIN`, same-depth comma, and nested supported-query cases. It includes
108+
aliased `JOIN`, authenticated `USING`, same-depth comma, and nested
109+
supported-query cases. It includes
102110
negative `IS DISTINCT FROM`, `substring(... FROM ...)`, `extract(... FROM
103-
...)`, `DELETE FROM`, `COPY ... FROM`, set-operation, `QUALIFY`, `WINDOW`, join
104-
constraint, DML, and expression cases. A keyword match alone never creates a
105-
site.
111+
...)`, `DELETE FROM`, `COPY ... FROM`, set-operation, `QUALIFY`, `WINDOW`,
112+
`ON`, malformed `USING`, DML, and expression cases. A keyword match alone
113+
never creates a site.
106114

107115
The result distinguishes:
108116

src/vnext/__tests__/query-site.bench.ts

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import {
1111
} from "../statement-index.js";
1212

1313
const dialect: SqlQuerySiteDialect = {
14-
classifyRelationAlias: (rawAlias) => ({
14+
classifyIdentifierToken: (rawIdentifier) => ({
1515
status: "identifier",
16-
value: rawAlias,
16+
value: rawIdentifier,
1717
}),
1818
decodeRelationPath: (rawPath, cursorOffset) => ({
1919
finalSegment: { from: 0, to: rawPath.length },
@@ -29,10 +29,20 @@ const dialect: SqlQuerySiteDialect = {
2929
maximumPathDepth: 16,
3030
supportsNaturalJoin: true,
3131
};
32-
const tenKilobyteQuery = `SELECT ${Array.from(
33-
{ length: 1_100 },
34-
(_, index) => `value_${index}`,
35-
).join(", ")} FROM schema_prefix`;
32+
const TEN_KIBIBYTES = 10 * 1_024;
33+
const queryPrefix = "SELECT ";
34+
const querySuffix = " FROM schema_prefix";
35+
const projectedListLength =
36+
TEN_KIBIBYTES - queryPrefix.length - querySuffix.length;
37+
const projectedList = `${"x,".repeat(
38+
Math.floor((projectedListLength - 1) / 2),
39+
)}x`;
40+
const tenKilobyteQuery = `${queryPrefix}${projectedList}${" ".repeat(
41+
projectedListLength - projectedList.length,
42+
)}${querySuffix}`;
43+
if (tenKilobyteQuery.length !== TEN_KIBIBYTES) {
44+
throw new Error("Query benchmark fixture must be exactly 10 KiB");
45+
}
3646
const source = createIdentitySqlSource(tenKilobyteQuery);
3747
const index = buildSqlStatementIndex(
3848
source.analysisText,
@@ -55,6 +65,21 @@ const aliasHeavySlot = findSqlStatementSlot(
5565
aliasHeavyPosition,
5666
"left",
5767
);
68+
const usingHeavyQuery = `SELECT * FROM first_table JOIN second_table USING(${Array.from(
69+
{ length: 1_000 },
70+
(_, columnIndex) => `column_${columnIndex}`,
71+
).join(", ")}) JOIN target`;
72+
const usingHeavySource = createIdentitySqlSource(usingHeavyQuery);
73+
const usingHeavyIndex = buildSqlStatementIndex(
74+
usingHeavySource.analysisText,
75+
dialect.lexicalProfile,
76+
);
77+
const usingHeavyPosition = usingHeavyQuery.length;
78+
const usingHeavySlot = findSqlStatementSlot(
79+
usingHeavyIndex,
80+
usingHeavyPosition,
81+
"left",
82+
);
5883

5984
describe("query-site recognizer", () => {
6085
bench("10 KiB active statement", () => {
@@ -69,4 +94,13 @@ describe("query-site recognizer", () => {
6994
dialect,
7095
);
7196
});
97+
98+
bench("1,000 authenticated USING columns", () => {
99+
recognizeSqlRelationQuerySite(
100+
usingHeavySource,
101+
usingHeavySlot,
102+
usingHeavyPosition,
103+
dialect,
104+
);
105+
});
72106
});

0 commit comments

Comments
 (0)