@askdb/core 1.0.0-beta.47 → 1.0.0-beta.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ask.d.ts +6 -5
- package/dist/ask.d.ts.map +1 -1
- package/dist/ask.js +33 -80
- package/dist/ask.js.map +1 -1
- package/dist/errors.d.ts +14 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/logging/create-askdb-logger.js +1 -1
- package/dist/logging/log-contract.d.ts +1 -1
- package/dist/logging/log-contract.js +1 -1
- package/dist/logging/log-events.d.ts +1 -1
- package/dist/logging/log-events.js +1 -1
- package/dist/modes/types.d.ts +1 -1
- package/dist/modes/types.d.ts.map +1 -1
- package/dist/modes/types.js +1 -1
- package/dist/modes/types.js.map +1 -1
- package/dist/retrieval/synthesize-ddl.d.ts +6 -6
- package/dist/retrieval/synthesize-ddl.d.ts.map +1 -1
- package/dist/retrieval/synthesize-ddl.js +7 -12
- package/dist/retrieval/synthesize-ddl.js.map +1 -1
- package/dist/retrieval/types.d.ts +1 -1
- package/dist/retrieval/types.d.ts.map +1 -1
- package/dist/schema/format.d.ts.map +1 -1
- package/dist/schema/format.js +8 -2
- package/dist/schema/format.js.map +1 -1
- package/dist/schema/normalize.d.ts.map +1 -1
- package/dist/schema/normalize.js +3 -4
- package/dist/schema/normalize.js.map +1 -1
- package/dist/schema/types.d.ts +2 -2
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/v2/format.d.ts +2 -1
- package/dist/schema/v2/format.d.ts.map +1 -1
- package/dist/schema/v2/format.js +1 -1
- package/dist/schema/v2/format.js.map +1 -1
- package/dist/schema/v2/loader.js +5 -5
- package/dist/schema/v2/loader.js.map +1 -1
- package/dist/schema/v2/parser.d.ts +8 -6
- package/dist/schema/v2/parser.d.ts.map +1 -1
- package/dist/schema/v2/parser.js +61 -24
- package/dist/schema/v2/parser.js.map +1 -1
- package/dist/schema/v2/physical.d.ts +0 -4
- package/dist/schema/v2/physical.d.ts.map +1 -1
- package/dist/schema/v2/physical.js +1 -1
- package/dist/schema/v2/physical.js.map +1 -1
- package/dist/schema/v2/tenant-policy-loader.d.ts.map +1 -1
- package/dist/schema/v2/tenant-policy-loader.js +3 -24
- package/dist/schema/v2/tenant-policy-loader.js.map +1 -1
- package/dist/schema/v2/tenant-policy.js +2 -2
- package/dist/schema/v2/tenant-policy.js.map +1 -1
- package/dist/schema/v2/writer.d.ts.map +1 -1
- package/dist/schema/v2/writer.js +6 -3
- package/dist/schema/v2/writer.js.map +1 -1
- package/dist/sql/extract-sql.d.ts +1 -1
- package/dist/sql/extract-sql.js +2 -2
- package/dist/sql/extract-sql.js.map +1 -1
- package/dist/sql/generate.d.ts.map +1 -1
- package/dist/sql/generate.js +7 -20
- package/dist/sql/generate.js.map +1 -1
- package/dist/sql/guardrails.d.ts +55 -36
- package/dist/sql/guardrails.d.ts.map +1 -1
- package/dist/sql/guardrails.js +71 -8
- package/dist/sql/guardrails.js.map +1 -1
- package/dist/sql/lexer.d.ts +19 -0
- package/dist/sql/lexer.d.ts.map +1 -1
- package/dist/sql/lexer.js +44 -1
- package/dist/sql/lexer.js.map +1 -1
- package/dist/sql/parameter-manifest.d.ts +4 -3
- package/dist/sql/parameter-manifest.d.ts.map +1 -1
- package/dist/sql/parameter-manifest.js +1 -6
- package/dist/sql/parameter-manifest.js.map +1 -1
- package/dist/sql/prompt.d.ts +1 -2
- package/dist/sql/prompt.d.ts.map +1 -1
- package/dist/sql/prompt.js +1 -2
- package/dist/sql/prompt.js.map +1 -1
- package/dist/sql/rebind.d.ts.map +1 -1
- package/dist/sql/rebind.js +5 -12
- package/dist/sql/rebind.js.map +1 -1
- package/dist/sql/tenant-guardrail.d.ts.map +1 -1
- package/dist/sql/tenant-guardrail.js +18 -8
- package/dist/sql/tenant-guardrail.js.map +1 -1
- package/dist/sql/tenant-prompt.d.ts.map +1 -1
- package/dist/sql/tenant-prompt.js +9 -5
- package/dist/sql/tenant-prompt.js.map +1 -1
- package/dist/sql/tenant-scope-expand.d.ts +1 -1
- package/dist/sql/tenant-scope-expand.js +1 -1
- package/dist/sql/tenant-scope-validate.d.ts.map +1 -1
- package/dist/sql/tenant-scope-validate.js +0 -5
- package/dist/sql/tenant-scope-validate.js.map +1 -1
- package/dist/sql/validate.d.ts +13 -9
- package/dist/sql/validate.d.ts.map +1 -1
- package/dist/sql/validate.js +21 -10
- package/dist/sql/validate.js.map +1 -1
- package/package.json +1 -1
- package/dist/sql/index.d.ts +0 -11
- package/dist/sql/index.d.ts.map +0 -1
- package/dist/sql/index.js +0 -11
- package/dist/sql/index.js.map +0 -1
package/dist/schema/v2/writer.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import matter from "gray-matter";
|
|
2
|
+
// Each `matter.stringify` call passes the body as `{ content }`, so gray-matter writes it as
|
|
3
|
+
// is. Given a string, it parses the body first: that caches it for the life of the process
|
|
4
|
+
// (#742), and a body that opens with a `---` rule is read as front-matter and emptied.
|
|
2
5
|
/**
|
|
3
6
|
* Serialize a table front-matter model back to markdown.
|
|
4
7
|
*
|
|
@@ -8,20 +11,20 @@ import matter from "gray-matter";
|
|
|
8
11
|
*/
|
|
9
12
|
export function writeTableMarkdown(frontmatter, body) {
|
|
10
13
|
const data = orderedTableFrontmatter(frontmatter);
|
|
11
|
-
return matter.stringify(body, data);
|
|
14
|
+
return matter.stringify({ content: body }, data);
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
14
17
|
* Serialize `concepts.md` front-matter + body back to markdown.
|
|
15
18
|
*/
|
|
16
19
|
export function writeConceptsMarkdown(frontmatter, body) {
|
|
17
|
-
return matter.stringify(body, { concepts: frontmatter.concepts });
|
|
20
|
+
return matter.stringify({ content: body }, { concepts: frontmatter.concepts });
|
|
18
21
|
}
|
|
19
22
|
/**
|
|
20
23
|
* Serialize `tenant-policy.md` front-matter + body back to markdown.
|
|
21
24
|
*/
|
|
22
25
|
export function writeTenantPolicyMarkdown(frontmatter, body) {
|
|
23
26
|
const data = orderedTenantPolicyFrontmatter(frontmatter);
|
|
24
|
-
return matter.stringify(body, data);
|
|
27
|
+
return matter.stringify({ content: body }, data);
|
|
25
28
|
}
|
|
26
29
|
/** Emit tenant policy front-matter keys in a stable order. */
|
|
27
30
|
function orderedTenantPolicyFrontmatter(fm) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/schema/v2/writer.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAIjC;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAA+B,EAAE,IAAY;IAC9E,MAAM,IAAI,GAAG,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAClD,OAAO,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/schema/v2/writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Prefer an explicitly `sql`-tagged fence; fall back to an untagged fence.
|
|
3
3
|
* Never return a fence tagged with anything else (e.g. `json`, `sql-unbound`).
|
|
4
|
-
*
|
|
4
|
+
* With no fence at all, the whole trimmed reply is the SQL.
|
|
5
5
|
*/
|
|
6
6
|
export declare function extractSqlFromModelText(raw: string): string;
|
|
7
7
|
/**
|
package/dist/sql/extract-sql.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Prefer an explicitly `sql`-tagged fence; fall back to an untagged fence.
|
|
3
3
|
* Never return a fence tagged with anything else (e.g. `json`, `sql-unbound`).
|
|
4
|
-
*
|
|
4
|
+
* With no fence at all, the whole trimmed reply is the SQL.
|
|
5
5
|
*/
|
|
6
6
|
export function extractSqlFromModelText(raw) {
|
|
7
7
|
const text = raw.trim();
|
|
@@ -17,7 +17,7 @@ export function extractSqlFromModelText(raw) {
|
|
|
17
17
|
if (/```[a-zA-Z][\w-]*/.test(text)) {
|
|
18
18
|
return "";
|
|
19
19
|
}
|
|
20
|
-
return text
|
|
20
|
+
return text;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Extract the ```sql-unbound fence from model text, if present.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract-sql.js","sourceRoot":"","sources":["../../src/sql/extract-sql.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,MAAM,SAAS,GAAG,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;IACD,MAAM,QAAQ,GAAG,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IACD,iFAAiF;IACjF,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,IAAI,CAAC
|
|
1
|
+
{"version":3,"file":"extract-sql.js","sourceRoot":"","sources":["../../src/sql/extract-sql.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,MAAM,SAAS,GAAG,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjE,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;IACD,MAAM,QAAQ,GAAG,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IACD,iFAAiF;IACjF,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAAC,GAAW;IACxD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/sql/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAA0C,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/sql/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAA0C,KAAK,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,CAAC,EAAE,OAAO,mBAAmB,CAAC;IAC1C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,qGAAqG;IACrG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,yCAAyC,CAAC,EAAE,OAAO,CAAC;IACpD;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,kEAAkE;IAClE,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,+FAA+F;IAC/F,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,2GAA2G;AAC3G,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,2FAA2F;IAC3F,OAAO,EAAE,gBAAgB,CAAC;IAC1B,qGAAqG;IACrG,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,iGAAiG;IACjG,KAAK,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACrG,wFAAwF;IACxF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,kBAAkB,EACzB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CAclC;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,kBAAkB,EACzB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,uBAAuB,EAAE,SAAS,CAAC,CAAC,CAEnD"}
|
package/dist/sql/generate.js
CHANGED
|
@@ -5,8 +5,7 @@ import { extractSqlFromModelText, extractUnboundSqlFromModelText } from "./extra
|
|
|
5
5
|
import { crossValidateManifestAgainstSql, parseParameterManifest, } from "./parameter-manifest.js";
|
|
6
6
|
import { buildNlToSqlSystemPrompt, buildNlToSqlUserPrompt } from "./prompt.js";
|
|
7
7
|
import { assertNlToSqlInputs, nlToSqlAmbiguityNotes } from "./schema-question-precheck.js";
|
|
8
|
-
import {
|
|
9
|
-
import { evaluateGuardrails, guardrailPlan, logGuardrailVerdict } from "./guardrails.js";
|
|
8
|
+
import { enforceGuardrails } from "./guardrails.js";
|
|
10
9
|
import { buildSelectGuardrailExplanation, validateSelectSql, } from "./validate.js";
|
|
11
10
|
/**
|
|
12
11
|
* Dialect-parameterized NL→SQL generator. Validates inputs, builds the user/system
|
|
@@ -23,30 +22,18 @@ import { buildSelectGuardrailExplanation, validateSelectSql, } from "./validate.
|
|
|
23
22
|
*/
|
|
24
23
|
export async function generateSelectSql(dialect, question, schema, model, deps = {}) {
|
|
25
24
|
const generated = await runGenerateSelectSql(dialect, question, schema, model, deps);
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const findings = evaluateGuardrails({
|
|
25
|
+
const { verdict, tenantGuardrail } = enforceGuardrails({
|
|
26
|
+
path: "generate",
|
|
29
27
|
forms: {
|
|
30
28
|
sql: generated.sql,
|
|
31
29
|
...(generated.unboundNamedSql !== undefined ? { template: generated.unboundNamedSql } : {}),
|
|
32
30
|
},
|
|
33
31
|
dialect,
|
|
34
32
|
schema,
|
|
35
|
-
...(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
throwIfDenied(verdict, modes, "return");
|
|
41
|
-
}
|
|
42
|
-
catch (e) {
|
|
43
|
-
logGenerateFailed(deps.logger, e);
|
|
44
|
-
throw e;
|
|
45
|
-
}
|
|
46
|
-
const out = { ...generated, verdict };
|
|
47
|
-
if (tenant)
|
|
48
|
-
out.tenantGuardrail = tenantGuardrailResult(findings);
|
|
49
|
-
return out;
|
|
33
|
+
...(deps.tenantPolicy && deps.tenantScope ? { tenant: { policy: deps.tenantPolicy, scope: deps.tenantScope } } : {}),
|
|
34
|
+
logger: deps.logger,
|
|
35
|
+
});
|
|
36
|
+
return { ...generated, verdict, ...(tenantGuardrail ? { tenantGuardrail } : {}) };
|
|
50
37
|
}
|
|
51
38
|
/**
|
|
52
39
|
* Internal entry used by `ask()`: the model call and extraction only. `sql` is returned
|
package/dist/sql/generate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/sql/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAyB,MAAM,cAAc,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMzD,OAAO,EAAE,uBAAuB,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAC3F,OAAO,EACL,+BAA+B,EAC/B,sBAAsB,GAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAC3F,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/sql/generate.ts"],"names":[],"mappings":"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"}
|
package/dist/sql/guardrails.d.ts
CHANGED
|
@@ -1,52 +1,71 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type GuardrailForm, type GuardrailVerdict } from "../errors.js";
|
|
2
2
|
import type { AskDbLogger } from "../logging/askdb-logger.js";
|
|
3
3
|
import type { AnyNormalizedSchema } from "../schema/types.js";
|
|
4
4
|
import type { NormalizedTenantPolicy, TenantScope } from "../schema/v2/tenant-policy.js";
|
|
5
5
|
import type { DialectSpec } from "./dialect-spec.js";
|
|
6
|
-
import { type
|
|
7
|
-
import { type
|
|
6
|
+
import { type SensitiveGuardrailMode, type SensitiveGuardrailResult } from "./sensitive-guardrail.js";
|
|
7
|
+
import { type TenantGuardrailResult } from "./tenant-guardrail.js";
|
|
8
8
|
/**
|
|
9
|
-
* The
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The enforcement step (ADR 0010, decisions 1–4). `enforceGuardrails()` is the one call
|
|
10
|
+
* each enforcement point makes: `ask()`, `generateSelectSql()` and `bindPreparedQuery()`.
|
|
11
|
+
* It picks the checks and the point from `path`, runs the checks on every form, decides
|
|
12
|
+
* through `decide` (`guardrail-decide.ts`), logs, and throws the typed error on `deny`.
|
|
13
|
+
* The checks below are pure rules: each takes a candidate and returns findings, knows
|
|
14
|
+
* nothing about modes and never throws for a finding. Internal to `@askdb/core`.
|
|
12
15
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
type Tenant = {
|
|
17
|
+
policy: NormalizedTenantPolicy;
|
|
18
|
+
scope: TenantScope;
|
|
19
|
+
};
|
|
20
|
+
/** The untrusted forms an enforcement point checks, before AskDB renders them. */
|
|
21
|
+
type Forms = Partial<Record<GuardrailForm, string>>;
|
|
22
|
+
/** What an enforcement point hands the step. Fields one point has no use for aren't on its variant. */
|
|
23
|
+
export type EnforceInput = {
|
|
24
|
+
path: "ask";
|
|
25
|
+
forms: Forms;
|
|
26
|
+
/** Undefined for a custom `AskDialect`, which may target non-SELECT SQL: no read-only check. */
|
|
18
27
|
dialect: DialectSpec | undefined;
|
|
19
28
|
schema: AnyNormalizedSchema;
|
|
20
|
-
/** A v2 schema's tenant policy, with the
|
|
21
|
-
tenant?:
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
/** A v2 schema's tenant policy, with the (expanded) scope. */
|
|
30
|
+
tenant?: Tenant;
|
|
31
|
+
/** Default `"warn"`. */
|
|
32
|
+
sensitiveGuardrailMode?: SensitiveGuardrailMode | "off";
|
|
33
|
+
/** A custom `AskDialect`'s own tenant result: decided with a tenant policy, passed through without one. */
|
|
34
|
+
generatorTenantGuardrail?: TenantGuardrailResult;
|
|
35
|
+
logger?: AskDbLogger;
|
|
36
|
+
} | {
|
|
37
|
+
path: "generate";
|
|
38
|
+
forms: Forms;
|
|
39
|
+
dialect: DialectSpec;
|
|
40
|
+
schema: AnyNormalizedSchema;
|
|
41
|
+
tenant?: Tenant;
|
|
42
|
+
logger?: AskDbLogger;
|
|
43
|
+
} | {
|
|
44
|
+
path: "rebind";
|
|
45
|
+
forms: {
|
|
46
|
+
template: string;
|
|
24
47
|
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* ADR 0010, decision 3: which checks each enforcement point runs, and the modes `decide`
|
|
28
|
-
* reads there. `ask()` with a custom `AskDialect` has no `dialect`, so no read-only check;
|
|
29
|
-
* `generateSelectSql()` takes no sensitive mode, so no sensitive check; `acceptWarnings`
|
|
30
|
-
* means something at rebind only.
|
|
31
|
-
*/
|
|
32
|
-
export declare function guardrailPlan(path: "ask" | "generate" | "rebind", input: {
|
|
33
|
-
dialect: DialectSpec | undefined;
|
|
48
|
+
dialect: DialectSpec;
|
|
34
49
|
schema: AnyNormalizedSchema;
|
|
35
|
-
|
|
50
|
+
tenant?: Tenant;
|
|
36
51
|
sensitiveGuardrailMode?: SensitiveGuardrailMode | "off";
|
|
37
52
|
acceptWarnings?: ReadonlyArray<"tenant">;
|
|
38
|
-
}): {
|
|
39
|
-
checks: GuardrailCheckId[];
|
|
40
|
-
modes: GuardrailModes;
|
|
41
53
|
};
|
|
42
|
-
/**
|
|
43
|
-
export
|
|
54
|
+
/** A verdict the point may hand back (`allow` or `warn`), with the results derived from it. */
|
|
55
|
+
export type Enforced = {
|
|
56
|
+
verdict: GuardrailVerdict;
|
|
57
|
+
/** With a tenant policy, derived from the verdict. Without one (`ask` only), a custom generator's result as reported. */
|
|
58
|
+
tenantGuardrail?: TenantGuardrailResult;
|
|
59
|
+
/** Present when the sensitive check ran. */
|
|
60
|
+
sensitiveGuardrail?: SensitiveGuardrailResult;
|
|
61
|
+
};
|
|
44
62
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
63
|
+
* Run the path's checks on every form, decide, log, and on `deny` throw the typed error
|
|
64
|
+
* with the verdict attached (`SqlValidationError`, then `TenantGuardrailError`, then
|
|
65
|
+
* `SensitiveReferenceError`). `ask` and `generate` decide at the `return` point and log
|
|
66
|
+
* with their logger: the tenant pass/fail event, the sensitive references, and
|
|
67
|
+
* `pipeline.failed` on a deny. `rebind` decides at the `rebind` point and logs nothing.
|
|
47
68
|
*/
|
|
48
|
-
export declare function
|
|
49
|
-
|
|
50
|
-
sensitiveChecked: boolean;
|
|
51
|
-
}): void;
|
|
69
|
+
export declare function enforceGuardrails(input: EnforceInput): Enforced;
|
|
70
|
+
export {};
|
|
52
71
|
//# sourceMappingURL=guardrails.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/sql/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/sql/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAYrD,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAsB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGvF;;;;;;;GAOG;AAEH,KAAK,MAAM,GAAG;IAAE,MAAM,EAAE,sBAAsB,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC;AAErE,kFAAkF;AAClF,KAAK,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAEpD,uGAAuG;AACvG,MAAM,MAAM,YAAY,GACpB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC;IACb,gGAAgG;IAChG,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,KAAK,CAAC;IACxD,2GAA2G;IAC3G,wBAAwB,CAAC,EAAE,qBAAqB,CAAC;IACjD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,KAAK,CAAC;IACxD,cAAc,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CAC1C,CAAC;AAEN,+FAA+F;AAC/F,MAAM,MAAM,QAAQ,GAAG;IACrB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,yHAAyH;IACzH,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,4CAA4C;IAC5C,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;CAC/C,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,QAAQ,CAqC/D"}
|
package/dist/sql/guardrails.js
CHANGED
|
@@ -1,9 +1,51 @@
|
|
|
1
1
|
import { SqlValidationError, } from "../errors.js";
|
|
2
2
|
import { AskDbLogEvent } from "../logging/log-events.js";
|
|
3
|
-
import { formatSensitiveReference, sensitiveFindings, sensitiveGuardrailResult, tenantFindings, tenantWarnings, } from "./guardrail-decide.js";
|
|
3
|
+
import { decide, formatSensitiveReference, sensitiveFindings, sensitiveGuardrailResult, tenantFindings, tenantGuardrailResult, tenantWarnings, throwIfDenied, } from "./guardrail-decide.js";
|
|
4
4
|
import { scanSensitiveReferences, schemaHasSensitiveIdentifiers, } from "./sensitive-guardrail.js";
|
|
5
5
|
import { tenantRuleWarnings } from "./tenant-guardrail.js";
|
|
6
6
|
import { validateSelectSql } from "./validate.js";
|
|
7
|
+
/**
|
|
8
|
+
* Run the path's checks on every form, decide, log, and on `deny` throw the typed error
|
|
9
|
+
* with the verdict attached (`SqlValidationError`, then `TenantGuardrailError`, then
|
|
10
|
+
* `SensitiveReferenceError`). `ask` and `generate` decide at the `return` point and log
|
|
11
|
+
* with their logger: the tenant pass/fail event, the sensitive references, and
|
|
12
|
+
* `pipeline.failed` on a deny. `rebind` decides at the `rebind` point and logs nothing.
|
|
13
|
+
*/
|
|
14
|
+
export function enforceGuardrails(input) {
|
|
15
|
+
const { checks, modes } = guardrailPlan(input);
|
|
16
|
+
const findings = evaluateGuardrails({
|
|
17
|
+
forms: input.forms,
|
|
18
|
+
dialect: input.dialect,
|
|
19
|
+
schema: input.schema,
|
|
20
|
+
...(input.tenant ? { tenant: input.tenant } : {}),
|
|
21
|
+
}, checks);
|
|
22
|
+
if (input.path === "ask" && input.tenant)
|
|
23
|
+
findings.push(...generatorFindings(input.generatorTenantGuardrail));
|
|
24
|
+
const point = input.path === "rebind" ? "rebind" : "return";
|
|
25
|
+
const verdict = decide(findings, modes, point);
|
|
26
|
+
const sensitiveChecked = checks.includes("sensitive");
|
|
27
|
+
const logger = input.path === "rebind" ? undefined : input.logger;
|
|
28
|
+
logGuardrailVerdict(logger, verdict, { tenantPolicy: input.tenant?.policy, sensitiveChecked });
|
|
29
|
+
try {
|
|
30
|
+
throwIfDenied(verdict, modes, point);
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
logger?.error({ event: AskDbLogEvent.PipelineFailed, phase: "generate", errMessage: e instanceof Error ? e.message : String(e) }, "nl-to-sql generate failed");
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
const enforced = { verdict };
|
|
37
|
+
if (input.tenant) {
|
|
38
|
+
enforced.tenantGuardrail = tenantGuardrailResult(findings);
|
|
39
|
+
}
|
|
40
|
+
else if (input.path === "ask" && input.generatorTenantGuardrail !== undefined) {
|
|
41
|
+
// Without a tenant policy there is no mode to decide with: pass through what a custom
|
|
42
|
+
// dialect reported.
|
|
43
|
+
enforced.tenantGuardrail = input.generatorTenantGuardrail;
|
|
44
|
+
}
|
|
45
|
+
if (sensitiveChecked)
|
|
46
|
+
enforced.sensitiveGuardrail = sensitiveGuardrailResult(findings);
|
|
47
|
+
return enforced;
|
|
48
|
+
}
|
|
7
49
|
const CHECKS = {
|
|
8
50
|
// Needs a DialectSpec: a custom AskDialect may target non-SELECT SQL (decision 3).
|
|
9
51
|
"read-only": ({ dialect }, form, sql) => {
|
|
@@ -37,26 +79,27 @@ const FORMS = ["sql", "template"];
|
|
|
37
79
|
* `generateSelectSql()` takes no sensitive mode, so no sensitive check; `acceptWarnings`
|
|
38
80
|
* means something at rebind only.
|
|
39
81
|
*/
|
|
40
|
-
|
|
41
|
-
const sensitive = path === "generate" ? "off" : (input.sensitiveGuardrailMode ?? "warn");
|
|
82
|
+
function guardrailPlan(input) {
|
|
83
|
+
const sensitive = input.path === "generate" ? "off" : (input.sensitiveGuardrailMode ?? "warn");
|
|
84
|
+
const policy = input.tenant?.policy;
|
|
42
85
|
const checks = [];
|
|
43
86
|
if (input.dialect)
|
|
44
87
|
checks.push("read-only");
|
|
45
|
-
if (
|
|
88
|
+
if (policy)
|
|
46
89
|
checks.push("tenant");
|
|
47
90
|
if (sensitive !== "off" && schemaHasSensitiveIdentifiers(input.schema))
|
|
48
91
|
checks.push("sensitive");
|
|
49
92
|
return {
|
|
50
93
|
checks,
|
|
51
94
|
modes: {
|
|
52
|
-
...(
|
|
95
|
+
...(policy ? { tenant: policy.enforcement } : {}),
|
|
53
96
|
sensitive,
|
|
54
|
-
...(path === "rebind" && input.acceptWarnings ? { acceptWarnings: input.acceptWarnings } : {}),
|
|
97
|
+
...(input.path === "rebind" && input.acceptWarnings ? { acceptWarnings: input.acceptWarnings } : {}),
|
|
55
98
|
},
|
|
56
99
|
};
|
|
57
100
|
}
|
|
58
101
|
/** Run each listed check on every form in the candidate. */
|
|
59
|
-
|
|
102
|
+
function evaluateGuardrails(candidate, checks) {
|
|
60
103
|
const findings = [];
|
|
61
104
|
for (const check of checks) {
|
|
62
105
|
for (const form of FORMS) {
|
|
@@ -67,11 +110,31 @@ export function evaluateGuardrails(candidate, checks) {
|
|
|
67
110
|
}
|
|
68
111
|
return findings;
|
|
69
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* A custom `AskDialect`'s reported tenant result as findings, so `decide` rules on it under
|
|
115
|
+
* the policy's mode. A failure it reports without details becomes one `UNPROVABLE_SCOPE`,
|
|
116
|
+
* so it is never dropped. They add to the step's own tenant check; they never replace it.
|
|
117
|
+
*/
|
|
118
|
+
function generatorFindings(reported) {
|
|
119
|
+
if (!reported)
|
|
120
|
+
return [];
|
|
121
|
+
const findings = tenantFindings(reported.warnings ?? [], "generator");
|
|
122
|
+
if (reported.passed === false && findings.length === 0) {
|
|
123
|
+
findings.push({
|
|
124
|
+
check: "tenant",
|
|
125
|
+
form: "generator",
|
|
126
|
+
rule: "UNPROVABLE_SCOPE",
|
|
127
|
+
tableId: "",
|
|
128
|
+
message: "The custom SQL generator reported a failed tenant guardrail without details.",
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return findings;
|
|
132
|
+
}
|
|
70
133
|
/**
|
|
71
134
|
* Log a verdict the way `ask()` and `generateSelectSql()` always have: one tenant
|
|
72
135
|
* pass/fail event (with a tenant policy), and the sensitive references (when checked).
|
|
73
136
|
*/
|
|
74
|
-
|
|
137
|
+
function logGuardrailVerdict(logger, verdict, context) {
|
|
75
138
|
if (context.tenantPolicy) {
|
|
76
139
|
const warnings = tenantWarnings(verdict.findings);
|
|
77
140
|
if (warnings.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../src/sql/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAKnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAIzD,OAAO,EAEL,wBAAwB,EACxB,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,EACd,cAAc,
|
|
1
|
+
{"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../src/sql/guardrails.ts"],"names":[],"mappings":"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"}
|
package/dist/sql/lexer.d.ts
CHANGED
|
@@ -122,6 +122,25 @@ export type SqlToken = {
|
|
|
122
122
|
export declare function startsDashComment(sql: string, i: number, needsSpace: boolean): boolean;
|
|
123
123
|
/** Split `sql` into tokens under `profile`. Whitespace is dropped; comments are kept. */
|
|
124
124
|
export declare function lexSql(sql: string, profile: SqlLexerProfile): SqlToken[];
|
|
125
|
+
/**
|
|
126
|
+
* The lexer profiles under which a dialect's SQL may be read as Postgres, for the checks that
|
|
127
|
+
* refuse what only that reading can hold (#703): the dialect's own profile when it is on the
|
|
128
|
+
* Postgres lexer (postgres, cockroachdb); for a dialect that is no built-in engine, or none,
|
|
129
|
+
* `POSTGRES_LEXER`, plus a copy with backslash escapes when the dialect sets `backslashEscapes`,
|
|
130
|
+
* since its server may read strings either way; none for any other built-in engine.
|
|
131
|
+
*/
|
|
132
|
+
export declare function postgresReadingProfiles(dialect?: Pick<DialectSpec, "id" | "backslashEscapes">): SqlLexerProfile[];
|
|
133
|
+
/**
|
|
134
|
+
* A Postgres `E'…'` string continued on a later line: the string, then a gap that contains a
|
|
135
|
+
* newline and holds only whitespace and comments, then a bare `'…'` string. Postgres joins the
|
|
136
|
+
* two and keeps the escape mode, so it reads the second one with backslash escapes, which this
|
|
137
|
+
* lexer doesn't: where `\'` ends one reading's string, the other's goes on. AskDB doesn't model
|
|
138
|
+
* the continuation. The read-only check and the tenant check refuse it at this boundary, where
|
|
139
|
+
* both readings still agree (#703, ADR 0012). Postgres allows only whitespace and `--` comments
|
|
140
|
+
* in the gap; a `/* … *\/` comment there is refused too. Returns the `E'…'` token; callers
|
|
141
|
+
* report its position, not its text, which may hold a value from the question.
|
|
142
|
+
*/
|
|
143
|
+
export declare function findEscapeStringContinuation(sql: string, tokens: readonly SqlToken[]): SqlToken | undefined;
|
|
125
144
|
/**
|
|
126
145
|
* A Postgres Unicode-escaped identifier, as `U&"…"` (either case) with no space between the
|
|
127
146
|
* parts: the form Postgres's scanner reads as one identifier. With a space, `U& "x"` is the
|
package/dist/sql/lexer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../src/sql/lexer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1F,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,iBAAiB,CAAC;IACtB,sEAAsE;IACtE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,4FAA4F;IAC5F,WAAW,EAAE,YAAY,GAAG,QAAQ,CAAC;IACrC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,yFAAyF;IACzF,kBAAkB,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IACjD,wCAAwC;IACxC,YAAY,EAAE,OAAO,CAAC;IACtB,sDAAsD;IACtD,aAAa,EAAE,OAAO,CAAC;IACvB,+BAA+B;IAC/B,YAAY,EAAE,OAAO,CAAC;IACtB,6FAA6F;IAC7F,qBAAqB,EAAE,OAAO,CAAC;IAC/B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gGAAgG;IAChG,kBAAkB,EAAE,OAAO,CAAC;IAC5B,+FAA+F;IAC/F,WAAW,EAAE,OAAO,CAAC;IACrB,iDAAiD;IACjD,eAAe,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,eAe5B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,eAezB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,eAe7B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,eAe1B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,eAe3B,CAAC;AAEF,qGAAqG;AACrG,eAAO,MAAM,qBAAqB,EAAE,SAAS,eAAe,EAK3D,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,kBAAkB,CAAC,GACpD,eAAe,GAAG,SAAS,CAmB7B;AAED,MAAM,MAAM,YAAY;AACtB,sCAAsC;AACpC,MAAM,GACN,mBAAmB,GACnB,QAAQ,GACR,QAAQ;AACV,wCAAwC;GACtC,WAAW;AACb,+EAA+E;GAC7E,OAAO,GACP,SAAS,CAAC;AAEd,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,8FAA8F;IAC9F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,YAAY,CAAC,EAAE,IAAI,CAAC;CACrB,CAAC;AAgBF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAItF;AAED,yFAAyF;AACzF,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../src/sql/lexer.ts"],"names":[],"mappings":"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"}
|
package/dist/sql/lexer.js
CHANGED
|
@@ -396,7 +396,10 @@ export function lexSql(sql, profile) {
|
|
|
396
396
|
i += 2;
|
|
397
397
|
continue;
|
|
398
398
|
}
|
|
399
|
-
|
|
399
|
+
// On an engine with `E'…'` strings, `:E'` is `:` then an escape string (a JSON_OBJECT key's
|
|
400
|
+
// `:`, an array slice's), never a `:name` placeholder, which a quote can't follow (#703).
|
|
401
|
+
const escapeStringAfterColon = profile.escapeStrings && (next === "e" || next === "E") && sql[i + 2] === "'";
|
|
402
|
+
if (ch === ":" && next !== undefined && WORD_START.test(next) && !escapeStringAfterColon) {
|
|
400
403
|
let j = i + 1;
|
|
401
404
|
while (j < n && isWordChar(sql[j]))
|
|
402
405
|
j++;
|
|
@@ -425,6 +428,46 @@ export function lexSql(sql, profile) {
|
|
|
425
428
|
tokens[executableOpener].unterminated = true;
|
|
426
429
|
return tokens;
|
|
427
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* The lexer profiles under which a dialect's SQL may be read as Postgres, for the checks that
|
|
433
|
+
* refuse what only that reading can hold (#703): the dialect's own profile when it is on the
|
|
434
|
+
* Postgres lexer (postgres, cockroachdb); for a dialect that is no built-in engine, or none,
|
|
435
|
+
* `POSTGRES_LEXER`, plus a copy with backslash escapes when the dialect sets `backslashEscapes`,
|
|
436
|
+
* since its server may read strings either way; none for any other built-in engine.
|
|
437
|
+
*/
|
|
438
|
+
export function postgresReadingProfiles(dialect) {
|
|
439
|
+
const known = dialect === undefined ? undefined : lexerProfileFor(dialect);
|
|
440
|
+
if (known !== undefined)
|
|
441
|
+
return known.id === "postgres" ? [known] : [];
|
|
442
|
+
return dialect?.backslashEscapes === true
|
|
443
|
+
? [POSTGRES_LEXER, { ...POSTGRES_LEXER, backslashEscapes: true }]
|
|
444
|
+
: [POSTGRES_LEXER];
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* A Postgres `E'…'` string continued on a later line: the string, then a gap that contains a
|
|
448
|
+
* newline and holds only whitespace and comments, then a bare `'…'` string. Postgres joins the
|
|
449
|
+
* two and keeps the escape mode, so it reads the second one with backslash escapes, which this
|
|
450
|
+
* lexer doesn't: where `\'` ends one reading's string, the other's goes on. AskDB doesn't model
|
|
451
|
+
* the continuation. The read-only check and the tenant check refuse it at this boundary, where
|
|
452
|
+
* both readings still agree (#703, ADR 0012). Postgres allows only whitespace and `--` comments
|
|
453
|
+
* in the gap; a `/* … *\/` comment there is refused too. Returns the `E'…'` token; callers
|
|
454
|
+
* report its position, not its text, which may hold a value from the question.
|
|
455
|
+
*/
|
|
456
|
+
export function findEscapeStringContinuation(sql, tokens) {
|
|
457
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
458
|
+
const t = tokens[i];
|
|
459
|
+
if (t.kind !== "string" || !/^[eE]'/.test(t.text))
|
|
460
|
+
continue;
|
|
461
|
+
let j = i + 1;
|
|
462
|
+
while (tokens[j]?.kind === "comment")
|
|
463
|
+
j++;
|
|
464
|
+
const next = tokens[j];
|
|
465
|
+
if (next?.kind === "string" && next.text.startsWith("'") && /[\n\r]/.test(sql.slice(t.end, next.start))) {
|
|
466
|
+
return t;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return undefined;
|
|
470
|
+
}
|
|
428
471
|
/**
|
|
429
472
|
* A Postgres Unicode-escaped identifier, as `U&"…"` (either case) with no space between the
|
|
430
473
|
* parts: the form Postgres's scanner reads as one identifier. With a space, `U& "x"` is the
|