sof-mssql 2.1.0 → 2.3.0
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/fhirpath/visitor.d.ts +78 -0
- package/dist/fhirpath/visitor.d.ts.map +1 -1
- package/dist/fhirpath/visitor.js +208 -11
- package/dist/fhirpath/visitor.js.map +1 -1
- package/dist/parser.d.ts +1 -1
- package/dist/parser.js +1 -1
- package/dist/queryGenerator/index.d.ts +0 -4
- package/dist/queryGenerator/index.d.ts.map +1 -1
- package/dist/queryGenerator/index.js +1 -9
- package/dist/queryGenerator/index.js.map +1 -1
- package/dist/queryGenerator/treeWalker/aliasGenerator.d.ts +26 -0
- package/dist/queryGenerator/treeWalker/aliasGenerator.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/aliasGenerator.js +31 -0
- package/dist/queryGenerator/treeWalker/aliasGenerator.js.map +1 -0
- package/dist/queryGenerator/treeWalker/classify.d.ts +19 -0
- package/dist/queryGenerator/treeWalker/classify.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/classify.js +36 -0
- package/dist/queryGenerator/treeWalker/classify.js.map +1 -0
- package/dist/queryGenerator/treeWalker/compile.d.ts +29 -0
- package/dist/queryGenerator/treeWalker/compile.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/compile.js +97 -0
- package/dist/queryGenerator/treeWalker/compile.js.map +1 -0
- package/dist/queryGenerator/treeWalker/cteTemplates.d.ts +58 -0
- package/dist/queryGenerator/treeWalker/cteTemplates.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/cteTemplates.js +131 -0
- package/dist/queryGenerator/treeWalker/cteTemplates.js.map +1 -0
- package/dist/queryGenerator/treeWalker/index.d.ts +6 -0
- package/dist/queryGenerator/treeWalker/index.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/index.js +9 -0
- package/dist/queryGenerator/treeWalker/index.js.map +1 -0
- package/dist/queryGenerator/treeWalker/mergeSiblings.d.ts +28 -0
- package/dist/queryGenerator/treeWalker/mergeSiblings.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/mergeSiblings.js +54 -0
- package/dist/queryGenerator/treeWalker/mergeSiblings.js.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/columnsOnly.d.ts +40 -0
- package/dist/queryGenerator/treeWalker/operators/columnsOnly.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/columnsOnly.js +56 -0
- package/dist/queryGenerator/treeWalker/operators/columnsOnly.js.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/forEach.d.ts +47 -0
- package/dist/queryGenerator/treeWalker/operators/forEach.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/forEach.js +150 -0
- package/dist/queryGenerator/treeWalker/operators/forEach.js.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/group.d.ts +35 -0
- package/dist/queryGenerator/treeWalker/operators/group.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/group.js +56 -0
- package/dist/queryGenerator/treeWalker/operators/group.js.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/repeat.d.ts +47 -0
- package/dist/queryGenerator/treeWalker/operators/repeat.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/repeat.js +122 -0
- package/dist/queryGenerator/treeWalker/operators/repeat.js.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/unionAll.d.ts +54 -0
- package/dist/queryGenerator/treeWalker/operators/unionAll.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/operators/unionAll.js +121 -0
- package/dist/queryGenerator/treeWalker/operators/unionAll.js.map +1 -0
- package/dist/queryGenerator/treeWalker/render.d.ts +34 -0
- package/dist/queryGenerator/treeWalker/render.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/render.js +41 -0
- package/dist/queryGenerator/treeWalker/render.js.map +1 -0
- package/dist/queryGenerator/treeWalker/types.d.ts +64 -0
- package/dist/queryGenerator/treeWalker/types.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/types.js +14 -0
- package/dist/queryGenerator/treeWalker/types.js.map +1 -0
- package/dist/queryGenerator/treeWalker/walker.d.ts +36 -0
- package/dist/queryGenerator/treeWalker/walker.d.ts.map +1 -0
- package/dist/queryGenerator/treeWalker/walker.js +58 -0
- package/dist/queryGenerator/treeWalker/walker.js.map +1 -0
- package/dist/queryGenerator.d.ts +8 -94
- package/dist/queryGenerator.d.ts.map +1 -1
- package/dist/queryGenerator.js +16 -268
- package/dist/queryGenerator.js.map +1 -1
- package/dist/tests/utils/database.d.ts +2 -0
- package/dist/tests/utils/database.d.ts.map +1 -1
- package/dist/tests/utils/database.js +10 -1
- package/dist/tests/utils/database.js.map +1 -1
- package/dist/tests/utils/generator.d.ts +2 -0
- package/dist/tests/utils/generator.d.ts.map +1 -1
- package/dist/tests/utils/generator.js +24 -0
- package/dist/tests/utils/generator.js.map +1 -1
- package/dist/tests/utils/reporter.d.ts +1 -1
- package/dist/tests/utils/reporter.d.ts.map +1 -1
- package/dist/tests/utils/reporter.js +5 -4
- package/dist/tests/utils/reporter.js.map +1 -1
- package/dist/tests/utils/types.d.ts +1 -1
- package/dist/tests/utils/types.js +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +2 -1
- package/dist/queryGenerator/ForEachProcessor.d.ts +0 -127
- package/dist/queryGenerator/ForEachProcessor.d.ts.map +0 -1
- package/dist/queryGenerator/ForEachProcessor.js +0 -351
- package/dist/queryGenerator/ForEachProcessor.js.map +0 -1
- package/dist/queryGenerator/RepeatProcessor.d.ts +0 -177
- package/dist/queryGenerator/RepeatProcessor.d.ts.map +0 -1
- package/dist/queryGenerator/RepeatProcessor.js +0 -336
- package/dist/queryGenerator/RepeatProcessor.js.map +0 -1
- package/dist/queryGenerator/SelectClauseBuilder.d.ts +0 -108
- package/dist/queryGenerator/SelectClauseBuilder.d.ts.map +0 -1
- package/dist/queryGenerator/SelectClauseBuilder.js +0 -346
- package/dist/queryGenerator/SelectClauseBuilder.js.map +0 -1
- package/dist/queryGenerator/SelectCombinationExpander.d.ts +0 -42
- package/dist/queryGenerator/SelectCombinationExpander.d.ts.map +0 -1
- package/dist/queryGenerator/SelectCombinationExpander.js +0 -95
- package/dist/queryGenerator/SelectCombinationExpander.js.map +0 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walker for ColumnsOnly nodes — emits the projected columns for the
|
|
3
|
+
* select.column[] array using the current transpiler context.
|
|
4
|
+
*/
|
|
5
|
+
import type { ViewDefinitionColumn, ViewDefinitionSelect } from "../../../types.js";
|
|
6
|
+
import type { ColumnExpressionGenerator } from "../../ColumnExpressionGenerator.js";
|
|
7
|
+
import type { Context, Fragment, ProjectedColumn } from "../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Projects an array of ViewDefinition column descriptors into SQL expressions.
|
|
10
|
+
*
|
|
11
|
+
* Delegates expression generation to `ColumnExpressionGenerator`, which
|
|
12
|
+
* translates each column's FHIRPath expression into a T-SQL expression
|
|
13
|
+
* relative to the current transpiler context (iteration source, aliases, etc.).
|
|
14
|
+
*
|
|
15
|
+
* @param columns - The column descriptors from the ViewDefinition select node.
|
|
16
|
+
* @param ctx - The current walker context supplying the transpiler context
|
|
17
|
+
* used for FHIRPath-to-SQL translation.
|
|
18
|
+
* @param columnGenerator - The generator that converts each column descriptor
|
|
19
|
+
* into its SQL expression string.
|
|
20
|
+
* @returns An ordered array of `ProjectedColumn` objects, each pairing the
|
|
21
|
+
* column's logical name with its SQL expression.
|
|
22
|
+
*/
|
|
23
|
+
export declare function projectColumns(columns: ViewDefinitionColumn[], ctx: Context, columnGenerator: ColumnExpressionGenerator): ProjectedColumn[];
|
|
24
|
+
/**
|
|
25
|
+
* Walker for ColumnsOnly nodes — emits the projected columns for a leaf select node.
|
|
26
|
+
*
|
|
27
|
+
* Produces a Fragment with no CTEs, no FROM extensions, and columns derived
|
|
28
|
+
* from `node.column[]` via `projectColumns`. If `node.column` is absent or
|
|
29
|
+
* empty, the returned Fragment has an empty columns array.
|
|
30
|
+
*
|
|
31
|
+
* @param node - The leaf select node whose `column[]` array is projected.
|
|
32
|
+
* @param ctx - The current walker context supplying partition keys and the
|
|
33
|
+
* transpiler context for expression generation.
|
|
34
|
+
* @param columnGenerator - The generator that converts column descriptors into
|
|
35
|
+
* T-SQL expressions.
|
|
36
|
+
* @returns A Fragment carrying only projected columns; `ctes` and
|
|
37
|
+
* `fromExtensions` are always empty.
|
|
38
|
+
*/
|
|
39
|
+
export declare function walkColumnsOnly(node: ViewDefinitionSelect, ctx: Context, columnGenerator: ColumnExpressionGenerator): Fragment;
|
|
40
|
+
//# sourceMappingURL=columnsOnly.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columnsOnly.d.ts","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/columnsOnly.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEtE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,oBAAoB,EAAE,EAC/B,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,yBAAyB,GACzC,eAAe,EAAE,CAKnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,oBAAoB,EAC1B,GAAG,EAAE,OAAO,EACZ,eAAe,EAAE,yBAAyB,GACzC,QAAQ,CAUV"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Walker for ColumnsOnly nodes — emits the projected columns for the
|
|
4
|
+
* select.column[] array using the current transpiler context.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.projectColumns = projectColumns;
|
|
8
|
+
exports.walkColumnsOnly = walkColumnsOnly;
|
|
9
|
+
/**
|
|
10
|
+
* Projects an array of ViewDefinition column descriptors into SQL expressions.
|
|
11
|
+
*
|
|
12
|
+
* Delegates expression generation to `ColumnExpressionGenerator`, which
|
|
13
|
+
* translates each column's FHIRPath expression into a T-SQL expression
|
|
14
|
+
* relative to the current transpiler context (iteration source, aliases, etc.).
|
|
15
|
+
*
|
|
16
|
+
* @param columns - The column descriptors from the ViewDefinition select node.
|
|
17
|
+
* @param ctx - The current walker context supplying the transpiler context
|
|
18
|
+
* used for FHIRPath-to-SQL translation.
|
|
19
|
+
* @param columnGenerator - The generator that converts each column descriptor
|
|
20
|
+
* into its SQL expression string.
|
|
21
|
+
* @returns An ordered array of `ProjectedColumn` objects, each pairing the
|
|
22
|
+
* column's logical name with its SQL expression.
|
|
23
|
+
*/
|
|
24
|
+
function projectColumns(columns, ctx, columnGenerator) {
|
|
25
|
+
return columns.map((column) => ({
|
|
26
|
+
name: column.name,
|
|
27
|
+
sqlExpr: columnGenerator.generateExpression(column, ctx.transpilerCtx),
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Walker for ColumnsOnly nodes — emits the projected columns for a leaf select node.
|
|
32
|
+
*
|
|
33
|
+
* Produces a Fragment with no CTEs, no FROM extensions, and columns derived
|
|
34
|
+
* from `node.column[]` via `projectColumns`. If `node.column` is absent or
|
|
35
|
+
* empty, the returned Fragment has an empty columns array.
|
|
36
|
+
*
|
|
37
|
+
* @param node - The leaf select node whose `column[]` array is projected.
|
|
38
|
+
* @param ctx - The current walker context supplying partition keys and the
|
|
39
|
+
* transpiler context for expression generation.
|
|
40
|
+
* @param columnGenerator - The generator that converts column descriptors into
|
|
41
|
+
* T-SQL expressions.
|
|
42
|
+
* @returns A Fragment carrying only projected columns; `ctes` and
|
|
43
|
+
* `fromExtensions` are always empty.
|
|
44
|
+
*/
|
|
45
|
+
function walkColumnsOnly(node, ctx, columnGenerator) {
|
|
46
|
+
const columns = node.column
|
|
47
|
+
? projectColumns(node.column, ctx, columnGenerator)
|
|
48
|
+
: [];
|
|
49
|
+
return {
|
|
50
|
+
ctes: [],
|
|
51
|
+
fromExtensions: "",
|
|
52
|
+
columns,
|
|
53
|
+
partitionKeys: ctx.partitionKeys,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=columnsOnly.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columnsOnly.js","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/columnsOnly.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAwBH,wCASC;AAiBD,0CAcC;AAvDD;;;;;;;;;;;;;;GAcG;AACH,SAAgB,cAAc,CAC5B,OAA+B,EAC/B,GAAY,EACZ,eAA0C;IAE1C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,eAAe,CAAC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC;KACvE,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,eAAe,CAC7B,IAA0B,EAC1B,GAAY,EACZ,eAA0C;IAE1C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM;QACzB,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,eAAe,CAAC;QACnD,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;QACL,IAAI,EAAE,EAAE;QACR,cAAc,EAAE,EAAE;QAClB,OAAO;QACP,aAAa,EAAE,GAAG,CAAC,aAAa;KACjC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walker for ForEach / ForEachOrNull nodes.
|
|
3
|
+
*
|
|
4
|
+
* Emits a CROSS APPLY (or OUTER APPLY) clause that iterates over a JSON
|
|
5
|
+
* array. Threads `ctx.source` and `ctx.transpilerCtx` so child nodes
|
|
6
|
+
* project columns relative to the iteration value, and appends a
|
|
7
|
+
* `<alias>_key` partition key.
|
|
8
|
+
*
|
|
9
|
+
* Path-handling parity is delegated to PathParser (`.where()`, `.first()`,
|
|
10
|
+
* array indexing, multi-segment array flattening).
|
|
11
|
+
*
|
|
12
|
+
* @author John Grimes
|
|
13
|
+
*/
|
|
14
|
+
import type { ViewDefinitionSelect } from "../../../types.js";
|
|
15
|
+
import type { PathParser } from "../../PathParser.js";
|
|
16
|
+
import { type Context, type Fragment } from "../types.js";
|
|
17
|
+
interface ForEachDeps {
|
|
18
|
+
pathParser: PathParser;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Walker for ForEach and ForEachOrNull nodes.
|
|
22
|
+
*
|
|
23
|
+
* Emits a `CROSS APPLY` (or `OUTER APPLY` for `forEachOrNull`) clause that
|
|
24
|
+
* iterates over a JSON array identified by the node's FHIRPath expression.
|
|
25
|
+
* Updates `ctx.source`, `ctx.transpilerCtx`, and `ctx.partitionKeys` so that
|
|
26
|
+
* child nodes project columns relative to each iteration value, then walks
|
|
27
|
+
* the child sub-tree (`column`, `select`, `unionAll`) in that inner context.
|
|
28
|
+
* The apply clause is prepended to the inner Fragment's `fromExtensions`.
|
|
29
|
+
*
|
|
30
|
+
* Path features handled via `PathParser`: `.where()` filters, `.first()`
|
|
31
|
+
* selectors, array indexing, and multi-segment array flattening (nested
|
|
32
|
+
* `CROSS APPLY OPENJSON` chains).
|
|
33
|
+
*
|
|
34
|
+
* @param node - The ForEach or ForEachOrNull select node. `node.forEach` or
|
|
35
|
+
* `node.forEachOrNull` supplies the FHIRPath expression to iterate.
|
|
36
|
+
* @param ctx - The current walker context; the inner context is derived from
|
|
37
|
+
* it by updating `source`, `partitionKeys`, `ancestorApplies`, and
|
|
38
|
+
* `transpilerCtx`.
|
|
39
|
+
* @param walk - The recursive walk function used to visit the inner sub-tree.
|
|
40
|
+
* @param deps - Dependencies containing the `PathParser` used to parse and
|
|
41
|
+
* decompose the FHIRPath expression.
|
|
42
|
+
* @returns A Fragment whose `fromExtensions` begins with the generated APPLY
|
|
43
|
+
* clause followed by any extensions produced by the inner walk.
|
|
44
|
+
*/
|
|
45
|
+
export declare function walkForEach(node: ViewDefinitionSelect, ctx: Context, walk: (n: ViewDefinitionSelect, c: Context) => Fragment, deps: ForEachDeps): Fragment;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=forEach.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forEach.d.ts","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/forEach.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,QAAQ,EAGd,MAAM,aAAa,CAAC;AAErB,UAAU,WAAW;IACnB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,oBAAoB,EAC1B,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,OAAO,KAAK,QAAQ,EACvD,IAAI,EAAE,WAAW,GAChB,QAAQ,CA2BV"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Walker for ForEach / ForEachOrNull nodes.
|
|
4
|
+
*
|
|
5
|
+
* Emits a CROSS APPLY (or OUTER APPLY) clause that iterates over a JSON
|
|
6
|
+
* array. Threads `ctx.source` and `ctx.transpilerCtx` so child nodes
|
|
7
|
+
* project columns relative to the iteration value, and appends a
|
|
8
|
+
* `<alias>_key` partition key.
|
|
9
|
+
*
|
|
10
|
+
* Path-handling parity is delegated to PathParser (`.where()`, `.first()`,
|
|
11
|
+
* array indexing, multi-segment array flattening).
|
|
12
|
+
*
|
|
13
|
+
* @author John Grimes
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.walkForEach = walkForEach;
|
|
17
|
+
const aliasGenerator_js_1 = require("../aliasGenerator.js");
|
|
18
|
+
const types_js_1 = require("../types.js");
|
|
19
|
+
/**
|
|
20
|
+
* Walker for ForEach and ForEachOrNull nodes.
|
|
21
|
+
*
|
|
22
|
+
* Emits a `CROSS APPLY` (or `OUTER APPLY` for `forEachOrNull`) clause that
|
|
23
|
+
* iterates over a JSON array identified by the node's FHIRPath expression.
|
|
24
|
+
* Updates `ctx.source`, `ctx.transpilerCtx`, and `ctx.partitionKeys` so that
|
|
25
|
+
* child nodes project columns relative to each iteration value, then walks
|
|
26
|
+
* the child sub-tree (`column`, `select`, `unionAll`) in that inner context.
|
|
27
|
+
* The apply clause is prepended to the inner Fragment's `fromExtensions`.
|
|
28
|
+
*
|
|
29
|
+
* Path features handled via `PathParser`: `.where()` filters, `.first()`
|
|
30
|
+
* selectors, array indexing, and multi-segment array flattening (nested
|
|
31
|
+
* `CROSS APPLY OPENJSON` chains).
|
|
32
|
+
*
|
|
33
|
+
* @param node - The ForEach or ForEachOrNull select node. `node.forEach` or
|
|
34
|
+
* `node.forEachOrNull` supplies the FHIRPath expression to iterate.
|
|
35
|
+
* @param ctx - The current walker context; the inner context is derived from
|
|
36
|
+
* it by updating `source`, `partitionKeys`, `ancestorApplies`, and
|
|
37
|
+
* `transpilerCtx`.
|
|
38
|
+
* @param walk - The recursive walk function used to visit the inner sub-tree.
|
|
39
|
+
* @param deps - Dependencies containing the `PathParser` used to parse and
|
|
40
|
+
* decompose the FHIRPath expression.
|
|
41
|
+
* @returns A Fragment whose `fromExtensions` begins with the generated APPLY
|
|
42
|
+
* clause followed by any extensions produced by the inner walk.
|
|
43
|
+
*/
|
|
44
|
+
function walkForEach(node, ctx, walk, deps) {
|
|
45
|
+
const isOrNull = node.forEachOrNull !== undefined;
|
|
46
|
+
const rawPath = node.forEach ?? node.forEachOrNull ?? "";
|
|
47
|
+
const applyType = isOrNull ? "OUTER APPLY" : "CROSS APPLY";
|
|
48
|
+
const alias = (0, aliasGenerator_js_1.freshAlias)(ctx, "forEach");
|
|
49
|
+
const applyClause = buildForEachApply(rawPath, ctx.source, alias, applyType, ctx.transpilerCtx, deps.pathParser);
|
|
50
|
+
const innerCtx = buildInnerCtx(ctx, alias, rawPath, applyClause);
|
|
51
|
+
const innerNode = {
|
|
52
|
+
column: node.column,
|
|
53
|
+
select: node.select,
|
|
54
|
+
unionAll: node.unionAll,
|
|
55
|
+
};
|
|
56
|
+
const inner = walk(innerNode, innerCtx);
|
|
57
|
+
return {
|
|
58
|
+
...inner,
|
|
59
|
+
fromExtensions: applyClause + inner.fromExtensions,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function buildInnerCtx(ctx, alias, rawPath, applyClause) {
|
|
63
|
+
const innerTranspilerCtx = {
|
|
64
|
+
...ctx.transpilerCtx,
|
|
65
|
+
iterationContext: `${alias}.value`,
|
|
66
|
+
currentForEachAlias: alias,
|
|
67
|
+
forEachSource: ctx.source,
|
|
68
|
+
forEachPath: `$.${rawPath}`,
|
|
69
|
+
// `%rowIndex` resolves to the iterated element's 0-based position, which is
|
|
70
|
+
// the OPENJSON `[key]` column. For forEachOrNull over an empty collection
|
|
71
|
+
// the OUTER APPLY yields a single null-padded row whose `[key]` is NULL;
|
|
72
|
+
// the spec requires `%rowIndex` to be 0 for that row, hence the COALESCE.
|
|
73
|
+
rowIndexExpr: `COALESCE(CAST(${alias}.[key] AS INT), 0)`,
|
|
74
|
+
};
|
|
75
|
+
const innerKey = {
|
|
76
|
+
name: `${alias}_key`,
|
|
77
|
+
sqlExpr: `${alias}.[key]`,
|
|
78
|
+
sqlType: types_js_1.SQL_NVARCHAR_4000,
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
...ctx,
|
|
82
|
+
source: `${alias}.value`,
|
|
83
|
+
partitionKeys: [...ctx.partitionKeys, innerKey],
|
|
84
|
+
ancestorApplies: ctx.ancestorApplies + applyClause,
|
|
85
|
+
transpilerCtx: innerTranspilerCtx,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Builds the CROSS/OUTER APPLY clause string for a forEach path, handling
|
|
90
|
+
* `.where()`, `.first()`, array indexing, and multi-segment array
|
|
91
|
+
* flattening.
|
|
92
|
+
*/
|
|
93
|
+
function buildForEachApply(rawPath, source, alias, applyType, transpilerCtx, pathParser) {
|
|
94
|
+
const { path: pathWithoutWhere, whereCondition, useFirst, } = pathParser.parseFhirPathWhere(rawPath, transpilerCtx);
|
|
95
|
+
const { path: forEachPath, arrayIndex } = pathParser.parseArrayIndexing(pathWithoutWhere);
|
|
96
|
+
const arrayPaths = pathParser.detectArrayFlatteningPaths(forEachPath);
|
|
97
|
+
if (arrayPaths.length > 1) {
|
|
98
|
+
return buildNestedApply(arrayPaths, source, alias, applyType, pathParser, arrayIndex, whereCondition);
|
|
99
|
+
}
|
|
100
|
+
return buildSimpleApply(applyType, source, forEachPath, alias, arrayIndex, whereCondition, useFirst);
|
|
101
|
+
}
|
|
102
|
+
function buildSimpleApply(applyType, source, path, alias, arrayIndex, whereCondition, useFirst) {
|
|
103
|
+
const whereClauses = [];
|
|
104
|
+
if (arrayIndex !== null)
|
|
105
|
+
whereClauses.push(`[key] = '${arrayIndex}'`);
|
|
106
|
+
if (whereCondition !== null)
|
|
107
|
+
whereClauses.push(whereCondition);
|
|
108
|
+
if (whereClauses.length > 0 || useFirst) {
|
|
109
|
+
const topClause = useFirst ? "TOP 1 " : "";
|
|
110
|
+
const orderBy = useFirst ? " ORDER BY [key]" : "";
|
|
111
|
+
const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
|
|
112
|
+
return `\n${applyType} (
|
|
113
|
+
SELECT ${topClause}* FROM OPENJSON(${source}, '$.${path}')
|
|
114
|
+
${whereClause}${orderBy}
|
|
115
|
+
) AS ${alias}`;
|
|
116
|
+
}
|
|
117
|
+
return `\n${applyType} OPENJSON(${source}, '$.${path}') AS ${alias}`;
|
|
118
|
+
}
|
|
119
|
+
function buildNestedApply(arrayPaths, source, finalAlias, applyType, pathParser, arrayIndex, whereCondition) {
|
|
120
|
+
let clauses = "";
|
|
121
|
+
let currentSource = source;
|
|
122
|
+
for (let i = 0; i < arrayPaths.length; i++) {
|
|
123
|
+
const isLast = i === arrayPaths.length - 1;
|
|
124
|
+
const alias = isLast ? finalAlias : `${finalAlias}_nest${i}`;
|
|
125
|
+
const segment = pathParser.extractPathSegment(arrayPaths, i);
|
|
126
|
+
const { cleanSegment, segmentIndex } = pathParser.parseSegmentIndexing(segment);
|
|
127
|
+
const jsonPath = `$.${cleanSegment}`;
|
|
128
|
+
const whereClauses = [];
|
|
129
|
+
if (segmentIndex !== null) {
|
|
130
|
+
whereClauses.push(`[key] = '${segmentIndex}'`);
|
|
131
|
+
}
|
|
132
|
+
else if (isLast && arrayIndex !== null) {
|
|
133
|
+
whereClauses.push(`[key] = '${arrayIndex}'`);
|
|
134
|
+
}
|
|
135
|
+
if (isLast && whereCondition !== null)
|
|
136
|
+
whereClauses.push(whereCondition);
|
|
137
|
+
if (whereClauses.length > 0) {
|
|
138
|
+
clauses += `\n${applyType} (
|
|
139
|
+
SELECT * FROM OPENJSON(${currentSource}, '${jsonPath}')
|
|
140
|
+
WHERE ${whereClauses.join(" AND ")}
|
|
141
|
+
) AS ${alias}`;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
clauses += `\n${applyType} OPENJSON(${currentSource}, '${jsonPath}') AS ${alias}`;
|
|
145
|
+
}
|
|
146
|
+
currentSource = `${alias}.value`;
|
|
147
|
+
}
|
|
148
|
+
return clauses;
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=forEach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forEach.js","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/forEach.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walker for Group nodes — visits each child and merges their fragments.
|
|
3
|
+
*
|
|
4
|
+
* If the node has both `column` and `select`, the columns are emitted as
|
|
5
|
+
* an implicit first ColumnsOnly child so they appear before the children's
|
|
6
|
+
* projections in lexical order.
|
|
7
|
+
*/
|
|
8
|
+
import type { ViewDefinitionSelect } from "../../../types.js";
|
|
9
|
+
import type { ColumnExpressionGenerator } from "../../ColumnExpressionGenerator.js";
|
|
10
|
+
import type { Context, Fragment } from "../types.js";
|
|
11
|
+
import { projectColumns } from "./columnsOnly.js";
|
|
12
|
+
/**
|
|
13
|
+
* Walker for Group nodes — visits each child select and merges their Fragments.
|
|
14
|
+
*
|
|
15
|
+
* If the node has both `column[]` and `select[]`, the columns are emitted as
|
|
16
|
+
* an implicit first ColumnsOnly child so they appear before the child select
|
|
17
|
+
* projections in lexical order. All children are walked with the same
|
|
18
|
+
* unmodified `ctx`; their Fragments are merged via `mergeSiblings`.
|
|
19
|
+
*
|
|
20
|
+
* Returns an empty Fragment when the node has neither `column[]` nor
|
|
21
|
+
* `select[]` children.
|
|
22
|
+
*
|
|
23
|
+
* @param node - The Group select node, which may carry `column[]`, `select[]`,
|
|
24
|
+
* or both.
|
|
25
|
+
* @param ctx - The current walker context passed unchanged to every child.
|
|
26
|
+
* @param walk - The recursive walk function used to visit each child select
|
|
27
|
+
* node.
|
|
28
|
+
* @param columnGenerator - The generator forwarded to `walkColumnsOnly` when
|
|
29
|
+
* the node also carries inline `column[]` entries.
|
|
30
|
+
* @returns A merged Fragment whose columns, CTEs, and FROM extensions are the
|
|
31
|
+
* ordered union of all child Fragments.
|
|
32
|
+
*/
|
|
33
|
+
export declare function walkGroup(node: ViewDefinitionSelect, ctx: Context, walk: (n: ViewDefinitionSelect, c: Context) => Fragment, columnGenerator: ColumnExpressionGenerator): Fragment;
|
|
34
|
+
export { projectColumns };
|
|
35
|
+
//# sourceMappingURL=group.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/group.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAEpF,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,cAAc,EAAmB,MAAM,kBAAkB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,oBAAoB,EAC1B,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,OAAO,KAAK,QAAQ,EACvD,eAAe,EAAE,yBAAyB,GACzC,QAAQ,CAuBV;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Walker for Group nodes — visits each child and merges their fragments.
|
|
4
|
+
*
|
|
5
|
+
* If the node has both `column` and `select`, the columns are emitted as
|
|
6
|
+
* an implicit first ColumnsOnly child so they appear before the children's
|
|
7
|
+
* projections in lexical order.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.projectColumns = void 0;
|
|
11
|
+
exports.walkGroup = walkGroup;
|
|
12
|
+
const mergeSiblings_js_1 = require("../mergeSiblings.js");
|
|
13
|
+
const columnsOnly_js_1 = require("./columnsOnly.js");
|
|
14
|
+
Object.defineProperty(exports, "projectColumns", { enumerable: true, get: function () { return columnsOnly_js_1.projectColumns; } });
|
|
15
|
+
/**
|
|
16
|
+
* Walker for Group nodes — visits each child select and merges their Fragments.
|
|
17
|
+
*
|
|
18
|
+
* If the node has both `column[]` and `select[]`, the columns are emitted as
|
|
19
|
+
* an implicit first ColumnsOnly child so they appear before the child select
|
|
20
|
+
* projections in lexical order. All children are walked with the same
|
|
21
|
+
* unmodified `ctx`; their Fragments are merged via `mergeSiblings`.
|
|
22
|
+
*
|
|
23
|
+
* Returns an empty Fragment when the node has neither `column[]` nor
|
|
24
|
+
* `select[]` children.
|
|
25
|
+
*
|
|
26
|
+
* @param node - The Group select node, which may carry `column[]`, `select[]`,
|
|
27
|
+
* or both.
|
|
28
|
+
* @param ctx - The current walker context passed unchanged to every child.
|
|
29
|
+
* @param walk - The recursive walk function used to visit each child select
|
|
30
|
+
* node.
|
|
31
|
+
* @param columnGenerator - The generator forwarded to `walkColumnsOnly` when
|
|
32
|
+
* the node also carries inline `column[]` entries.
|
|
33
|
+
* @returns A merged Fragment whose columns, CTEs, and FROM extensions are the
|
|
34
|
+
* ordered union of all child Fragments.
|
|
35
|
+
*/
|
|
36
|
+
function walkGroup(node, ctx, walk, columnGenerator) {
|
|
37
|
+
const children = [];
|
|
38
|
+
if (node.column && node.column.length > 0) {
|
|
39
|
+
children.push((0, columnsOnly_js_1.walkColumnsOnly)(node, ctx, columnGenerator));
|
|
40
|
+
}
|
|
41
|
+
if (node.select) {
|
|
42
|
+
for (const child of node.select) {
|
|
43
|
+
children.push(walk(child, ctx));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (children.length === 0) {
|
|
47
|
+
return {
|
|
48
|
+
ctes: [],
|
|
49
|
+
fromExtensions: "",
|
|
50
|
+
columns: [],
|
|
51
|
+
partitionKeys: ctx.partitionKeys,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return (0, mergeSiblings_js_1.mergeSiblings)(children, ctx);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=group.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group.js","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/group.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AA6BH,8BA4BC;AArDD,0DAAoD;AAEpD,qDAAmE;AAsD1D,+FAtDA,+BAAc,OAsDA;AApDvB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,SAAS,CACvB,IAA0B,EAC1B,GAAY,EACZ,IAAuD,EACvD,eAA0C;IAE1C,MAAM,QAAQ,GAAe,EAAE,CAAC;IAEhC,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,IAAA,gCAAe,EAAC,IAAI,EAAE,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,IAAI,EAAE,EAAE;YACR,cAAc,EAAE,EAAE;YAClB,OAAO,EAAE,EAAE;YACX,aAAa,EAAE,GAAG,CAAC,aAAa;SACjC,CAAC;IACJ,CAAC;IAED,OAAO,IAAA,gCAAa,EAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walker for Repeat nodes — emits a recursive CTE and returns a set Fragment.
|
|
3
|
+
*
|
|
4
|
+
* The CTE projects the current partition keys and any baked scalar columns
|
|
5
|
+
* plus a content-derived `__path` for stable identity across re-evaluations.
|
|
6
|
+
* The Fragment's `fromExtensions` is an INNER JOIN to the CTE on the partition key
|
|
7
|
+
* `[id]`; sibling-level composite-key joins are added by `mergeSiblings`.
|
|
8
|
+
*
|
|
9
|
+
* @author John Grimes
|
|
10
|
+
*/
|
|
11
|
+
import type { ViewDefinitionSelect } from "../../../types.js";
|
|
12
|
+
import { type Context, type Fragment } from "../types.js";
|
|
13
|
+
export interface RepeatDeps {
|
|
14
|
+
schemaName: string;
|
|
15
|
+
tableName: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Walker for Repeat nodes — emits a recursive CTE and returns a set Fragment.
|
|
19
|
+
*
|
|
20
|
+
* Generates a `WITH RECURSIVE`-style CTE (via `buildRepeatCte`) whose anchor
|
|
21
|
+
* member starts at the resource root and whose recursive members re-expand
|
|
22
|
+
* each element's `item_json` using the same path list. The CTE accumulates a
|
|
23
|
+
* `__path` string for stable per-element identity across recursion levels.
|
|
24
|
+
*
|
|
25
|
+
* The returned Fragment contains the CTE plus an `INNER JOIN` to it in
|
|
26
|
+
* `fromExtensions`; the join is keyed on all current partition keys so that
|
|
27
|
+
* only rows belonging to the enclosing resource (and any ancestor forEach)
|
|
28
|
+
* are included. The inner context updates `source` to `<cteAlias>.item_json`
|
|
29
|
+
* and appends a new `<cteAlias>_path` partition key so that nested operators
|
|
30
|
+
* can further partition the result set.
|
|
31
|
+
*
|
|
32
|
+
* @param node - The Repeat select node; `node.repeat` supplies the ordered
|
|
33
|
+
* list of FHIRPath strings used as the anchor and recursive paths.
|
|
34
|
+
* @param ctx - The current walker context; the inner context is derived from
|
|
35
|
+
* it by updating `source`, `partitionKeys`, `ancestorApplies`, and
|
|
36
|
+
* `transpilerCtx`.
|
|
37
|
+
* @param walk - The recursive walk function used to visit the inner sub-tree
|
|
38
|
+
* (`column`, `select`, `unionAll`) in the repeat-item context.
|
|
39
|
+
* @param deps - Schema and table name needed to construct the resource FROM
|
|
40
|
+
* clause inside the CTE anchor.
|
|
41
|
+
* @returns A Fragment whose `ctes` list begins with the recursive CTE,
|
|
42
|
+
* `fromExtensions` begins with the INNER JOIN to that CTE, and `columns`
|
|
43
|
+
* are those produced by the inner walk.
|
|
44
|
+
* @throws {Error} When `node.repeat` is absent or empty.
|
|
45
|
+
*/
|
|
46
|
+
export declare function walkRepeat(node: ViewDefinitionSelect, ctx: Context, walk: (n: ViewDefinitionSelect, c: Context) => Fragment, deps: RepeatDeps): Fragment;
|
|
47
|
+
//# sourceMappingURL=repeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repeat.d.ts","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/repeat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,QAAQ,EAGd,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,oBAAoB,EAC1B,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,OAAO,KAAK,QAAQ,EACvD,IAAI,EAAE,UAAU,GACf,QAAQ,CAmCV"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Walker for Repeat nodes — emits a recursive CTE and returns a set Fragment.
|
|
4
|
+
*
|
|
5
|
+
* The CTE projects the current partition keys and any baked scalar columns
|
|
6
|
+
* plus a content-derived `__path` for stable identity across re-evaluations.
|
|
7
|
+
* The Fragment's `fromExtensions` is an INNER JOIN to the CTE on the partition key
|
|
8
|
+
* `[id]`; sibling-level composite-key joins are added by `mergeSiblings`.
|
|
9
|
+
*
|
|
10
|
+
* @author John Grimes
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.walkRepeat = walkRepeat;
|
|
14
|
+
const aliasGenerator_js_1 = require("../aliasGenerator.js");
|
|
15
|
+
const cteTemplates_js_1 = require("../cteTemplates.js");
|
|
16
|
+
const types_js_1 = require("../types.js");
|
|
17
|
+
/**
|
|
18
|
+
* Walker for Repeat nodes — emits a recursive CTE and returns a set Fragment.
|
|
19
|
+
*
|
|
20
|
+
* Generates a `WITH RECURSIVE`-style CTE (via `buildRepeatCte`) whose anchor
|
|
21
|
+
* member starts at the resource root and whose recursive members re-expand
|
|
22
|
+
* each element's `item_json` using the same path list. The CTE accumulates a
|
|
23
|
+
* `__path` string for stable per-element identity across recursion levels.
|
|
24
|
+
*
|
|
25
|
+
* The returned Fragment contains the CTE plus an `INNER JOIN` to it in
|
|
26
|
+
* `fromExtensions`; the join is keyed on all current partition keys so that
|
|
27
|
+
* only rows belonging to the enclosing resource (and any ancestor forEach)
|
|
28
|
+
* are included. The inner context updates `source` to `<cteAlias>.item_json`
|
|
29
|
+
* and appends a new `<cteAlias>_path` partition key so that nested operators
|
|
30
|
+
* can further partition the result set.
|
|
31
|
+
*
|
|
32
|
+
* @param node - The Repeat select node; `node.repeat` supplies the ordered
|
|
33
|
+
* list of FHIRPath strings used as the anchor and recursive paths.
|
|
34
|
+
* @param ctx - The current walker context; the inner context is derived from
|
|
35
|
+
* it by updating `source`, `partitionKeys`, `ancestorApplies`, and
|
|
36
|
+
* `transpilerCtx`.
|
|
37
|
+
* @param walk - The recursive walk function used to visit the inner sub-tree
|
|
38
|
+
* (`column`, `select`, `unionAll`) in the repeat-item context.
|
|
39
|
+
* @param deps - Schema and table name needed to construct the resource FROM
|
|
40
|
+
* clause inside the CTE anchor.
|
|
41
|
+
* @returns A Fragment whose `ctes` list begins with the recursive CTE,
|
|
42
|
+
* `fromExtensions` begins with the INNER JOIN to that CTE, and `columns`
|
|
43
|
+
* are those produced by the inner walk.
|
|
44
|
+
* @throws {Error} When `node.repeat` is absent or empty.
|
|
45
|
+
*/
|
|
46
|
+
function walkRepeat(node, ctx, walk, deps) {
|
|
47
|
+
const cteAlias = (0, aliasGenerator_js_1.freshAlias)(ctx, "repeat");
|
|
48
|
+
const paths = node.repeat ?? [];
|
|
49
|
+
if (paths.length === 0) {
|
|
50
|
+
throw new Error("walkRepeat: repeat node has empty paths array");
|
|
51
|
+
}
|
|
52
|
+
const tableRef = `[${deps.schemaName}].[${deps.tableName}]`;
|
|
53
|
+
const cte = (0, cteTemplates_js_1.buildRepeatCte)({
|
|
54
|
+
cteAlias,
|
|
55
|
+
paths,
|
|
56
|
+
source: ctx.source,
|
|
57
|
+
fromClause: `FROM ${tableRef} AS [${ctx.resourceAlias}]`,
|
|
58
|
+
ancestorApplies: ctx.ancestorApplies,
|
|
59
|
+
partitionKeys: ctx.partitionKeys,
|
|
60
|
+
resourcePredicate: null, // Resource-level WHERE goes in the outer SELECT.
|
|
61
|
+
});
|
|
62
|
+
const joinClause = buildJoinClause(cteAlias, ctx);
|
|
63
|
+
const innerCtx = buildRepeatInnerCtx(ctx, cteAlias, paths, joinClause);
|
|
64
|
+
const innerNode = {
|
|
65
|
+
column: node.column,
|
|
66
|
+
select: node.select,
|
|
67
|
+
unionAll: node.unionAll,
|
|
68
|
+
};
|
|
69
|
+
const inner = walk(innerNode, innerCtx);
|
|
70
|
+
return {
|
|
71
|
+
ctes: [cte, ...inner.ctes],
|
|
72
|
+
// Join the CTE FIRST so subsequent applies/joins inside the repeat
|
|
73
|
+
// (which reference `<cteAlias>.item_json`) have the alias in scope.
|
|
74
|
+
fromExtensions: joinClause + inner.fromExtensions,
|
|
75
|
+
columns: inner.columns,
|
|
76
|
+
partitionKeys: innerCtx.partitionKeys,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Outer-SELECT join condition aligning this CTE's rows with the enclosing
|
|
81
|
+
* partition (resource id plus any forEach/repeat keys above this scope).
|
|
82
|
+
*/
|
|
83
|
+
function buildJoinClause(cteAlias, ctx) {
|
|
84
|
+
const joinConditions = ctx.partitionKeys
|
|
85
|
+
.map((k) => `${cteAlias}.[${k.name}] = ${k.sqlExpr}`)
|
|
86
|
+
.join(" AND ");
|
|
87
|
+
return `\nINNER JOIN ${cteAlias} ON ${joinConditions}`;
|
|
88
|
+
}
|
|
89
|
+
function buildRepeatInnerCtx(ctx, cteAlias, paths, joinClause) {
|
|
90
|
+
const newKey = {
|
|
91
|
+
name: `${cteAlias}_path`,
|
|
92
|
+
sqlExpr: `${cteAlias}.__path`,
|
|
93
|
+
sqlType: types_js_1.SQL_NVARCHAR_MAX,
|
|
94
|
+
};
|
|
95
|
+
// `%rowIndex` inside a repeat is the 0-based position within the flattened
|
|
96
|
+
// depth-first traversal. The CTE exposes a padded `__order` accumulator whose
|
|
97
|
+
// lexical order matches pre-order; ROW_NUMBER over it (less one) yields the
|
|
98
|
+
// index. Partitioning on the ancestor keys captured before the repeat key is
|
|
99
|
+
// appended (the resource, and any enclosing forEach element) restarts the
|
|
100
|
+
// sequence per partition. The window lives in the outer SELECT, which already
|
|
101
|
+
// INNER JOINs the CTE, so the reference is in scope.
|
|
102
|
+
const partitionCols = (0, cteTemplates_js_1.qualifiedKeyCols)(cteAlias, ctx.partitionKeys);
|
|
103
|
+
const partitionClause = partitionCols ? `PARTITION BY ${partitionCols} ` : "";
|
|
104
|
+
const innerTranspilerCtx = {
|
|
105
|
+
...ctx.transpilerCtx,
|
|
106
|
+
iterationContext: `${cteAlias}.item_json`,
|
|
107
|
+
currentForEachAlias: cteAlias,
|
|
108
|
+
forEachSource: ctx.source,
|
|
109
|
+
forEachPath: paths.map((p) => `$.${p}`).join(", "),
|
|
110
|
+
rowIndexExpr: `(ROW_NUMBER() OVER (${partitionClause}ORDER BY ${cteAlias}.__order) - 1)`,
|
|
111
|
+
};
|
|
112
|
+
// Propagate the join into ancestorApplies so any *nested* Repeat builds
|
|
113
|
+
// its CTE anchor with this CTE in scope.
|
|
114
|
+
return {
|
|
115
|
+
...ctx,
|
|
116
|
+
source: `${cteAlias}.item_json`,
|
|
117
|
+
partitionKeys: [...ctx.partitionKeys, newKey],
|
|
118
|
+
ancestorApplies: ctx.ancestorApplies + joinClause,
|
|
119
|
+
transpilerCtx: innerTranspilerCtx,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=repeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repeat.js","sourceRoot":"","sources":["../../../../src/queryGenerator/treeWalker/operators/repeat.ts"],"names":[],"mappings":"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"}
|