rawsql-ts 0.26.0 → 0.27.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/esm/index.d.ts +2 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +2 -2
- package/dist/esm/index.min.js.map +4 -4
- package/dist/esm/transformers/ConditionOptimization.d.ts +11 -1
- package/dist/esm/transformers/ConditionOptimization.js +122 -66
- package/dist/esm/transformers/ConditionOptimization.js.map +1 -1
- package/dist/esm/transformers/ParameterConditionPlacementOptimizer.d.ts +26 -7
- package/dist/esm/transformers/ParameterConditionPlacementOptimizer.js +408 -141
- package/dist/esm/transformers/ParameterConditionPlacementOptimizer.js.map +1 -1
- package/dist/esm/transformers/SSSQLFilterBuilder.d.ts +6 -0
- package/dist/esm/transformers/SSSQLFilterBuilder.js +84 -8
- package/dist/esm/transformers/SSSQLFilterBuilder.js.map +1 -1
- package/dist/esm/transformers/SqlComponentFormatter.d.ts +11 -0
- package/dist/esm/transformers/SqlComponentFormatter.js +16 -0
- package/dist/esm/transformers/SqlComponentFormatter.js.map +1 -0
- package/dist/esm/transformers/StaticPredicatePlacementOptimizer.d.ts +103 -0
- package/dist/esm/transformers/StaticPredicatePlacementOptimizer.js +1435 -0
- package/dist/esm/transformers/StaticPredicatePlacementOptimizer.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +4 -4
- package/dist/src/index.d.ts +2 -0
- package/dist/src/transformers/ConditionOptimization.d.ts +11 -1
- package/dist/src/transformers/ParameterConditionPlacementOptimizer.d.ts +26 -7
- package/dist/src/transformers/SSSQLFilterBuilder.d.ts +6 -0
- package/dist/src/transformers/SqlComponentFormatter.d.ts +11 -0
- package/dist/src/transformers/StaticPredicatePlacementOptimizer.d.ts +103 -0
- package/dist/transformers/ConditionOptimization.js +146 -65
- package/dist/transformers/ConditionOptimization.js.map +1 -1
- package/dist/transformers/ParameterConditionPlacementOptimizer.js +407 -140
- package/dist/transformers/ParameterConditionPlacementOptimizer.js.map +1 -1
- package/dist/transformers/SSSQLFilterBuilder.js +92 -16
- package/dist/transformers/SSSQLFilterBuilder.js.map +1 -1
- package/dist/transformers/SqlComponentFormatter.js +21 -0
- package/dist/transformers/SqlComponentFormatter.js.map +1 -0
- package/dist/transformers/StaticPredicatePlacementOptimizer.js +1445 -0
- package/dist/transformers/StaticPredicatePlacementOptimizer.js.map +1 -0
- package/dist/tsconfig.browser.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/src/index.d.ts
CHANGED
|
@@ -77,8 +77,10 @@ export * from './transformers/FilterableItemCollector';
|
|
|
77
77
|
export { FixtureCteBuilder, FixtureTableDefinition, FixtureColumnDefinition } from './transformers/FixtureCteBuilder';
|
|
78
78
|
export * from './transformers/DynamicQueryBuilder';
|
|
79
79
|
export * from './transformers/SSSQLFilterBuilder';
|
|
80
|
+
export type { FormattableSqlComponent, SqlComponentFormatter, SqlComponentFormatOptions } from './transformers/SqlComponentFormatter';
|
|
80
81
|
export * from './transformers/ConditionOptimization';
|
|
81
82
|
export * from './transformers/ParameterConditionPlacementOptimizer';
|
|
83
|
+
export * from './transformers/StaticPredicatePlacementOptimizer';
|
|
82
84
|
export * from './transformers/PruneOptionalConditionBranches';
|
|
83
85
|
export { SchemaInfo, optimizeUnusedLeftJoins, optimizeUnusedLeftJoinsToFixedPoint, optimizeUnusedCtes, optimizeUnusedCtesToFixedPoint } from './transformers/OptimizeUnusedLeftJoins';
|
|
84
86
|
export * from './transformers/TableColumnResolver';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { SelectQuery, SimpleSelectQuery } from "../models/SelectQuery";
|
|
2
2
|
import { ParameterConditionMove, ParameterConditionOptimizationError, ParameterConditionOptimizationOptions, ParameterConditionOptimizationWarning, ParameterConditionSkipped } from "./ParameterConditionPlacementOptimizer";
|
|
3
|
+
import { StaticPredicateMove, StaticPredicatePlacementError, StaticPredicatePlacementWarning, StaticPredicateSkipped } from "./StaticPredicatePlacementOptimizer";
|
|
3
4
|
import { OptionalConditionPruningParameters } from "./PruneOptionalConditionBranches";
|
|
4
5
|
export type ConditionOptimizationInput = string | SelectQuery | SimpleSelectQuery;
|
|
5
|
-
export type ConditionOptimizationPhaseKind = "sssql_optional_condition" | "parameter_condition_placement";
|
|
6
|
+
export type ConditionOptimizationPhaseKind = "sssql_optional_condition" | "parameter_condition_placement" | "static_predicate_placement";
|
|
6
7
|
export interface ConditionOptimizationOptions extends ParameterConditionOptimizationOptions {
|
|
7
8
|
/**
|
|
8
9
|
* Explicit opt-in values for SSSQL optional branch pruning.
|
|
@@ -36,15 +37,23 @@ export interface SssqlOptionalConditionSkipped {
|
|
|
36
37
|
}
|
|
37
38
|
export type ConditionOptimizationApplied = SssqlOptionalConditionApplied | (ParameterConditionMove & {
|
|
38
39
|
phaseKind: "parameter_condition_placement";
|
|
40
|
+
}) | (StaticPredicateMove & {
|
|
41
|
+
phaseKind: "static_predicate_placement";
|
|
39
42
|
});
|
|
40
43
|
export type ConditionOptimizationSkipped = SssqlOptionalConditionSkipped | (ParameterConditionSkipped & {
|
|
41
44
|
phaseKind: "parameter_condition_placement";
|
|
45
|
+
}) | (StaticPredicateSkipped & {
|
|
46
|
+
phaseKind: "static_predicate_placement";
|
|
42
47
|
});
|
|
43
48
|
export type ConditionOptimizationWarning = (ParameterConditionOptimizationWarning & {
|
|
44
49
|
phaseKind: ConditionOptimizationPhaseKind;
|
|
50
|
+
}) | (StaticPredicatePlacementWarning & {
|
|
51
|
+
phaseKind: ConditionOptimizationPhaseKind;
|
|
45
52
|
});
|
|
46
53
|
export type ConditionOptimizationError = (ParameterConditionOptimizationError & {
|
|
47
54
|
phaseKind: ConditionOptimizationPhaseKind;
|
|
55
|
+
}) | (StaticPredicatePlacementError & {
|
|
56
|
+
phaseKind: ConditionOptimizationPhaseKind;
|
|
48
57
|
});
|
|
49
58
|
export interface ConditionOptimizationSafety {
|
|
50
59
|
mode: "safe_only";
|
|
@@ -55,6 +64,7 @@ export interface ConditionOptimizationSafety {
|
|
|
55
64
|
export interface ConditionOptimizationResult {
|
|
56
65
|
ok: boolean;
|
|
57
66
|
sql: string;
|
|
67
|
+
query: SelectQuery | null;
|
|
58
68
|
phases: readonly ConditionOptimizationPhaseSummary[];
|
|
59
69
|
applied: readonly ConditionOptimizationApplied[];
|
|
60
70
|
skipped: readonly ConditionOptimizationSkipped[];
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { SelectQuery, SimpleSelectQuery } from "../models/SelectQuery";
|
|
2
|
+
import { SqlComponentFormatOptions } from "./SqlComponentFormatter";
|
|
2
3
|
export type ParameterConditionOptimizationInput = string | SelectQuery | SimpleSelectQuery;
|
|
3
4
|
/**
|
|
4
5
|
* First-phase safe-only placement for ordinary parameter predicates.
|
|
5
6
|
*
|
|
6
7
|
* The optimizer intentionally handles only root top-level AND predicates and one
|
|
7
8
|
* CTE/derived-table hop where the destination output is a direct column reference.
|
|
8
|
-
* Unsupported boundaries such as OR,
|
|
9
|
-
*
|
|
9
|
+
* Unsupported boundaries such as OR, DISTINCT ON, WINDOW, OUTER JOIN,
|
|
10
|
+
* expression outputs, and function predicates are reported as skipped.
|
|
10
11
|
*/
|
|
11
|
-
export interface ParameterConditionOptimizationOptions {
|
|
12
|
+
export interface ParameterConditionOptimizationOptions extends SqlComponentFormatOptions {
|
|
12
13
|
dryRun?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Whether AST/model inputs should be cloned before optimization.
|
|
16
|
+
* Defaults to true for public-call safety. Internal pipelines can pass false
|
|
17
|
+
* when they own the model and want to avoid AST -> SQL -> AST round trips.
|
|
18
|
+
*/
|
|
19
|
+
cloneInput?: boolean;
|
|
13
20
|
}
|
|
14
21
|
export interface ParameterConditionOptimizationWarning {
|
|
15
22
|
code: string;
|
|
@@ -45,6 +52,7 @@ export interface ParameterConditionOptimizationSafety {
|
|
|
45
52
|
export interface ParameterConditionOptimizationResult {
|
|
46
53
|
ok: boolean;
|
|
47
54
|
sql: string;
|
|
55
|
+
query: SelectQuery | null;
|
|
48
56
|
applied: readonly ParameterConditionMove[];
|
|
49
57
|
skipped: readonly ParameterConditionSkipped[];
|
|
50
58
|
warnings: readonly ParameterConditionOptimizationWarning[];
|
|
@@ -58,21 +66,32 @@ export declare class ParameterConditionPlacementOptimizer {
|
|
|
58
66
|
private parseInput;
|
|
59
67
|
private analyzeCandidate;
|
|
60
68
|
private findUnsupportedExpression;
|
|
69
|
+
private findUnsupportedParameterPredicateShape;
|
|
61
70
|
private isSupportedInPredicate;
|
|
62
71
|
private resolveTarget;
|
|
63
|
-
private
|
|
64
|
-
private
|
|
72
|
+
private findRootQueryBoundary;
|
|
73
|
+
private resolveTargetPlacement;
|
|
65
74
|
private resolveSourceBinding;
|
|
66
75
|
private resolveUpstreamQuery;
|
|
67
|
-
private
|
|
76
|
+
private resolveUnionTarget;
|
|
77
|
+
private resolveTargetColumns;
|
|
78
|
+
private resolveTargetColumnByOutputIndex;
|
|
79
|
+
private resolveDeepestBranchTarget;
|
|
68
80
|
private verifyColumnResolvableInQuery;
|
|
81
|
+
private isGroupKeyColumn;
|
|
82
|
+
private sameResolvableColumnInQuery;
|
|
83
|
+
private resolveColumnSourceAlias;
|
|
69
84
|
private rebaseCondition;
|
|
70
85
|
private getSourceBindings;
|
|
71
86
|
private findNullableSideBoundary;
|
|
72
87
|
private hasOuterJoin;
|
|
88
|
+
private hasDistinctOnBoundary;
|
|
89
|
+
private hasOrdinaryDistinct;
|
|
73
90
|
private getOutputColumnMatchCount;
|
|
91
|
+
private collectUnionBranches;
|
|
92
|
+
private resolveUnionOutputIndex;
|
|
93
|
+
private collectSelectOutputs;
|
|
74
94
|
private resolveSourceQueryForColumns;
|
|
75
|
-
private getSelectItemOutputName;
|
|
76
95
|
private findCte;
|
|
77
96
|
private countTableSourceReferences;
|
|
78
97
|
private hasWindowUsage;
|
|
@@ -136,6 +136,12 @@ export declare class SSSQLFilterBuilder {
|
|
|
136
136
|
private resolveSourceExpressionToUpstreamQuery;
|
|
137
137
|
private resolveAnchorTargetInQuery;
|
|
138
138
|
private getSourceAlias;
|
|
139
|
+
private buildScalarRefreshPlan;
|
|
140
|
+
private resolveScalarTargetInQuery;
|
|
141
|
+
private isNullableBranchColumn;
|
|
142
|
+
private hasLaterJoinThatNullsPriorSources;
|
|
143
|
+
private isPriorSourcesNullableJoin;
|
|
144
|
+
private isJoinedSourceNullable;
|
|
139
145
|
private rebaseMovedBranch;
|
|
140
146
|
private rebaseMovedBranchByAlias;
|
|
141
147
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SelectQuery, SimpleSelectQuery } from "../models/SelectQuery";
|
|
2
|
+
import { ValueComponent } from "../models/ValueComponent";
|
|
3
|
+
import { SqlFormatterOptions } from "./SqlFormatter";
|
|
4
|
+
export type FormattableSqlComponent = SelectQuery | SimpleSelectQuery | ValueComponent;
|
|
5
|
+
export type SqlComponentFormatter = (component: FormattableSqlComponent) => string;
|
|
6
|
+
export interface SqlComponentFormatOptions {
|
|
7
|
+
formatter?: SqlComponentFormatter;
|
|
8
|
+
formatOptions?: SqlFormatterOptions;
|
|
9
|
+
}
|
|
10
|
+
export declare const formatSqlComponent: (component: FormattableSqlComponent, options?: SqlComponentFormatOptions) => string;
|
|
11
|
+
export declare const hasSqlComponentFormatOverride: (options?: SqlComponentFormatOptions) => boolean;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { SelectQuery, SimpleSelectQuery } from "../models/SelectQuery";
|
|
2
|
+
import { SqlComponentFormatOptions } from "./SqlComponentFormatter";
|
|
3
|
+
export type StaticPredicatePlacementInput = string | SelectQuery | SimpleSelectQuery;
|
|
4
|
+
/**
|
|
5
|
+
* Safe-only placement for parameter-free static predicates.
|
|
6
|
+
*
|
|
7
|
+
* The optimizer only moves top-level AND terms whose outer column references can
|
|
8
|
+
* be mechanically rebased to direct outputs of a single-use simple CTE or
|
|
9
|
+
* derived table. Unsupported or ambiguous predicates stay in place.
|
|
10
|
+
*/
|
|
11
|
+
export interface StaticPredicatePlacementOptions extends SqlComponentFormatOptions {
|
|
12
|
+
dryRun?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Whether AST/model inputs should be cloned before optimization.
|
|
15
|
+
* Defaults to true for public-call safety. Internal pipelines can pass false
|
|
16
|
+
* when they own the model and want to avoid AST -> SQL -> AST round trips.
|
|
17
|
+
*/
|
|
18
|
+
cloneInput?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface StaticPredicatePlacementWarning {
|
|
21
|
+
code: string;
|
|
22
|
+
message: string;
|
|
23
|
+
detail?: unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface StaticPredicatePlacementError {
|
|
26
|
+
code: string;
|
|
27
|
+
message: string;
|
|
28
|
+
detail?: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface StaticPredicateMove {
|
|
31
|
+
kind: "move_static_predicate";
|
|
32
|
+
predicateSql: string;
|
|
33
|
+
fromScopeId: string;
|
|
34
|
+
toScopeId: string;
|
|
35
|
+
reason: string;
|
|
36
|
+
columnReferences: readonly string[];
|
|
37
|
+
}
|
|
38
|
+
export interface StaticPredicateSkipped {
|
|
39
|
+
predicateSql: string;
|
|
40
|
+
scopeId: string;
|
|
41
|
+
reason: string;
|
|
42
|
+
code: string;
|
|
43
|
+
}
|
|
44
|
+
export interface StaticPredicatePlacementSafety {
|
|
45
|
+
mode: "safe_only";
|
|
46
|
+
unsafeRewriteApplied: false;
|
|
47
|
+
dryRun: boolean;
|
|
48
|
+
formatterGeneratedSource: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface StaticPredicatePlacementResult {
|
|
51
|
+
ok: boolean;
|
|
52
|
+
sql: string;
|
|
53
|
+
query: SelectQuery | null;
|
|
54
|
+
applied: readonly StaticPredicateMove[];
|
|
55
|
+
skipped: readonly StaticPredicateSkipped[];
|
|
56
|
+
warnings: readonly StaticPredicatePlacementWarning[];
|
|
57
|
+
errors: readonly StaticPredicatePlacementError[];
|
|
58
|
+
safety: StaticPredicatePlacementSafety;
|
|
59
|
+
staticPredicateMoves: readonly StaticPredicateMove[];
|
|
60
|
+
}
|
|
61
|
+
export declare class StaticPredicatePlacementOptimizer {
|
|
62
|
+
plan(input: StaticPredicatePlacementInput, options?: StaticPredicatePlacementOptions): StaticPredicatePlacementResult;
|
|
63
|
+
optimize(input: StaticPredicatePlacementInput, options?: StaticPredicatePlacementOptions): StaticPredicatePlacementResult;
|
|
64
|
+
private parseInput;
|
|
65
|
+
private analyzeCandidate;
|
|
66
|
+
private isExistsPredicate;
|
|
67
|
+
private findUnsupportedExpression;
|
|
68
|
+
private resolveTarget;
|
|
69
|
+
private findRootQueryBoundary;
|
|
70
|
+
private resolveTargetPlacement;
|
|
71
|
+
private resolveSourceBinding;
|
|
72
|
+
private resolveUpstreamQuery;
|
|
73
|
+
private resolveUnionTarget;
|
|
74
|
+
private resolveTargetColumns;
|
|
75
|
+
private resolveDeepestBranchTarget;
|
|
76
|
+
private verifyColumnResolvableInQuery;
|
|
77
|
+
private isGroupKeyColumn;
|
|
78
|
+
private sameResolvableColumnInQuery;
|
|
79
|
+
private resolveColumnSourceAlias;
|
|
80
|
+
private rebasePredicate;
|
|
81
|
+
private getSourceBindings;
|
|
82
|
+
private findNullableSideBoundary;
|
|
83
|
+
private hasLaterJoinThatNullsPriorSources;
|
|
84
|
+
private hasOuterJoin;
|
|
85
|
+
private hasDistinctOnBoundary;
|
|
86
|
+
private hasOrdinaryDistinct;
|
|
87
|
+
private getOutputColumnMatchCount;
|
|
88
|
+
private collectUnionBranches;
|
|
89
|
+
private resolveUnionOutputIndex;
|
|
90
|
+
private resolveTargetColumnByOutputIndex;
|
|
91
|
+
private collectSelectOutputs;
|
|
92
|
+
private resolveSourceQueryForColumns;
|
|
93
|
+
private findCte;
|
|
94
|
+
private countTableSourceReferences;
|
|
95
|
+
private collectSourceAliases;
|
|
96
|
+
private collectRootColumnReferences;
|
|
97
|
+
private hasWindowUsage;
|
|
98
|
+
private collectParameterNames;
|
|
99
|
+
private makeSkipped;
|
|
100
|
+
private buildResult;
|
|
101
|
+
}
|
|
102
|
+
export declare const planStaticPredicatePlacement: (input: StaticPredicatePlacementInput, options?: StaticPredicatePlacementOptions) => StaticPredicatePlacementResult;
|
|
103
|
+
export declare const optimizeStaticPredicatePlacement: (input: StaticPredicatePlacementInput, options?: StaticPredicatePlacementOptions) => StaticPredicatePlacementResult;
|
|
@@ -3,19 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.optimizeConditions = exports.planConditionOptimization = void 0;
|
|
4
4
|
const SelectQueryParser_1 = require("../parsers/SelectQueryParser");
|
|
5
5
|
const ParameterConditionPlacementOptimizer_1 = require("./ParameterConditionPlacementOptimizer");
|
|
6
|
+
const StaticPredicatePlacementOptimizer_1 = require("./StaticPredicatePlacementOptimizer");
|
|
6
7
|
const PruneOptionalConditionBranches_1 = require("./PruneOptionalConditionBranches");
|
|
7
8
|
const SSSQLFilterBuilder_1 = require("./SSSQLFilterBuilder");
|
|
8
|
-
const
|
|
9
|
-
const formatSqlComponent = (component) => {
|
|
10
|
-
return new SqlFormatter_1.SqlFormatter().format(component).formattedSql;
|
|
11
|
-
};
|
|
9
|
+
const SqlComponentFormatter_1 = require("./SqlComponentFormatter");
|
|
12
10
|
const hasOwnParameter = (parameters, parameterName) => Object.prototype.hasOwnProperty.call(parameters, parameterName);
|
|
13
11
|
const isAbsentOptionalValue = (parameters, parameterName) => parameters[parameterName] === null || parameters[parameterName] === undefined;
|
|
14
|
-
const parseConditionOptimizationInput = (input) => {
|
|
12
|
+
const parseConditionOptimizationInput = (input, options) => {
|
|
15
13
|
const warnings = [];
|
|
16
14
|
const errors = [];
|
|
17
|
-
const sourceSql = typeof input === "string" ? input : formatSqlComponent(input);
|
|
15
|
+
const sourceSql = typeof input === "string" ? input : (0, SqlComponentFormatter_1.formatSqlComponent)(input, options);
|
|
18
16
|
const formatterGeneratedSource = typeof input !== "string";
|
|
17
|
+
if (typeof input !== "string" && options.cloneInput === false) {
|
|
18
|
+
return {
|
|
19
|
+
query: input,
|
|
20
|
+
sql: sourceSql,
|
|
21
|
+
formatterGeneratedSource: false,
|
|
22
|
+
warnings,
|
|
23
|
+
errors
|
|
24
|
+
};
|
|
25
|
+
}
|
|
19
26
|
if (formatterGeneratedSource) {
|
|
20
27
|
warnings.push({
|
|
21
28
|
phaseKind: "sssql_optional_condition",
|
|
@@ -48,31 +55,31 @@ const parseConditionOptimizationInput = (input) => {
|
|
|
48
55
|
};
|
|
49
56
|
}
|
|
50
57
|
};
|
|
51
|
-
const buildSssqlApplied = (branch) => {
|
|
58
|
+
const buildSssqlApplied = (branch, options) => {
|
|
52
59
|
return {
|
|
53
60
|
phaseKind: "sssql_optional_condition",
|
|
54
61
|
kind: "prune_optional_branch",
|
|
55
|
-
conditionSql: formatSqlComponent(branch.expression),
|
|
62
|
+
conditionSql: (0, SqlComponentFormatter_1.formatSqlComponent)(branch.expression, options),
|
|
56
63
|
parameterName: branch.parameterName,
|
|
57
64
|
reason: "The optional branch parameter is explicitly absent, so the safe-only SSSQL phase pruned the branch."
|
|
58
65
|
};
|
|
59
66
|
};
|
|
60
|
-
const buildSssqlRefreshApplied = (branch, previousConditionSql) => {
|
|
67
|
+
const buildSssqlRefreshApplied = (branch, previousConditionSql, options) => {
|
|
61
68
|
return {
|
|
62
69
|
phaseKind: "sssql_optional_condition",
|
|
63
70
|
kind: "refresh_optional_branch",
|
|
64
|
-
conditionSql: formatSqlComponent(branch.expression),
|
|
71
|
+
conditionSql: (0, SqlComponentFormatter_1.formatSqlComponent)(branch.expression, options),
|
|
65
72
|
previousConditionSql,
|
|
66
73
|
parameterName: branch.parameterName,
|
|
67
74
|
reason: "The safe-only SSSQL phase refreshed the optional branch placement before ordinary parameter placement."
|
|
68
75
|
};
|
|
69
76
|
};
|
|
70
|
-
const buildSssqlSkipped = (branch, parameters) => {
|
|
77
|
+
const buildSssqlSkipped = (branch, parameters, options) => {
|
|
71
78
|
const parameterProvided = hasOwnParameter(parameters, branch.parameterName);
|
|
72
79
|
return {
|
|
73
80
|
phaseKind: "sssql_optional_condition",
|
|
74
81
|
kind: "optional_branch_skipped",
|
|
75
|
-
conditionSql: formatSqlComponent(branch.expression),
|
|
82
|
+
conditionSql: (0, SqlComponentFormatter_1.formatSqlComponent)(branch.expression, options),
|
|
76
83
|
parameterName: branch.parameterName,
|
|
77
84
|
code: parameterProvided
|
|
78
85
|
? "SSSQL_OPTIONAL_PARAMETER_PRESENT"
|
|
@@ -82,11 +89,11 @@ const buildSssqlSkipped = (branch, parameters) => {
|
|
|
82
89
|
: "No optional branch parameter value was provided, so the branch remains unchanged."
|
|
83
90
|
};
|
|
84
91
|
};
|
|
85
|
-
const buildSssqlRefreshSkipped = (branch, code, reason) => {
|
|
92
|
+
const buildSssqlRefreshSkipped = (branch, code, reason, options) => {
|
|
86
93
|
return {
|
|
87
94
|
phaseKind: "sssql_optional_condition",
|
|
88
95
|
kind: "optional_branch_skipped",
|
|
89
|
-
conditionSql: formatSqlComponent(branch.expression),
|
|
96
|
+
conditionSql: (0, SqlComponentFormatter_1.formatSqlComponent)(branch.expression, options),
|
|
90
97
|
parameterName: branch.parameterName,
|
|
91
98
|
code,
|
|
92
99
|
reason
|
|
@@ -101,78 +108,94 @@ const buildSssqlRefreshFilters = (branches, parameters) => {
|
|
|
101
108
|
}
|
|
102
109
|
return filters;
|
|
103
110
|
};
|
|
104
|
-
const refreshRemainingSssqlBranches = (
|
|
105
|
-
const parsed = parseConditionOptimizationInput(sql);
|
|
111
|
+
const refreshRemainingSssqlBranches = (query, fallbackSql, parameters, options) => {
|
|
106
112
|
const applied = [];
|
|
107
113
|
const skipped = [];
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
sql: parsed.sql,
|
|
111
|
-
applied,
|
|
112
|
-
skipped,
|
|
113
|
-
warnings: parsed.warnings,
|
|
114
|
-
errors: parsed.errors,
|
|
115
|
-
formatterGeneratedSource: parsed.formatterGeneratedSource
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
const beforeBranches = (0, PruneOptionalConditionBranches_1.collectSupportedOptionalConditionBranches)(parsed.query);
|
|
114
|
+
const beforeBranches = (0, PruneOptionalConditionBranches_1.collectSupportedOptionalConditionBranches)(query);
|
|
119
115
|
if (beforeBranches.length === 0) {
|
|
120
116
|
return {
|
|
121
|
-
|
|
117
|
+
query,
|
|
118
|
+
sql: fallbackSql,
|
|
122
119
|
applied,
|
|
123
120
|
skipped,
|
|
124
|
-
warnings:
|
|
125
|
-
errors:
|
|
126
|
-
formatterGeneratedSource:
|
|
121
|
+
warnings: [],
|
|
122
|
+
errors: [],
|
|
123
|
+
formatterGeneratedSource: false
|
|
127
124
|
};
|
|
128
125
|
}
|
|
129
126
|
const beforeBranchSql = new WeakMap();
|
|
130
127
|
const beforeBranchQuery = new WeakMap();
|
|
131
128
|
for (const branch of beforeBranches) {
|
|
132
|
-
beforeBranchSql.set(branch.expression, formatSqlComponent(branch.expression));
|
|
129
|
+
beforeBranchSql.set(branch.expression, (0, SqlComponentFormatter_1.formatSqlComponent)(branch.expression, options));
|
|
133
130
|
beforeBranchQuery.set(branch.expression, branch.query);
|
|
134
131
|
}
|
|
135
132
|
try {
|
|
136
|
-
new SSSQLFilterBuilder_1.SSSQLFilterBuilder().refresh(
|
|
133
|
+
new SSSQLFilterBuilder_1.SSSQLFilterBuilder().refresh(query, buildSssqlRefreshFilters(beforeBranches, parameters));
|
|
137
134
|
}
|
|
138
135
|
catch (error) {
|
|
139
136
|
const detail = error instanceof Error ? error.message : String(error);
|
|
140
137
|
return {
|
|
141
|
-
|
|
138
|
+
query,
|
|
139
|
+
sql: fallbackSql,
|
|
142
140
|
applied,
|
|
143
|
-
skipped: beforeBranches.map(branch => buildSssqlRefreshSkipped(branch, "SSSQL_OPTIONAL_REFRESH_UNSUPPORTED", `SSSQL optional branch refresh was skipped because safe refresh could not be proven: ${detail}
|
|
144
|
-
warnings:
|
|
145
|
-
errors:
|
|
146
|
-
formatterGeneratedSource:
|
|
141
|
+
skipped: beforeBranches.map(branch => buildSssqlRefreshSkipped(branch, "SSSQL_OPTIONAL_REFRESH_UNSUPPORTED", `SSSQL optional branch refresh was skipped because safe refresh could not be proven: ${detail}`, options)),
|
|
142
|
+
warnings: [],
|
|
143
|
+
errors: [],
|
|
144
|
+
formatterGeneratedSource: false
|
|
147
145
|
};
|
|
148
146
|
}
|
|
149
|
-
const afterBranches = (0, PruneOptionalConditionBranches_1.collectSupportedOptionalConditionBranches)(
|
|
147
|
+
const afterBranches = (0, PruneOptionalConditionBranches_1.collectSupportedOptionalConditionBranches)(query);
|
|
150
148
|
for (const branch of afterBranches) {
|
|
151
149
|
const previousSql = beforeBranchSql.get(branch.expression);
|
|
152
150
|
const previousQuery = beforeBranchQuery.get(branch.expression);
|
|
153
151
|
if (!previousSql || !previousQuery) {
|
|
154
|
-
skipped.push(buildSssqlRefreshSkipped(branch, "SSSQL_OPTIONAL_REFRESH_UNSUPPORTED", "SSSQL optional branch refresh left an untracked branch unchanged."));
|
|
152
|
+
skipped.push(buildSssqlRefreshSkipped(branch, "SSSQL_OPTIONAL_REFRESH_UNSUPPORTED", "SSSQL optional branch refresh left an untracked branch unchanged.", options));
|
|
155
153
|
continue;
|
|
156
154
|
}
|
|
157
|
-
const refreshedSql = formatSqlComponent(branch.expression);
|
|
155
|
+
const refreshedSql = (0, SqlComponentFormatter_1.formatSqlComponent)(branch.expression, options);
|
|
158
156
|
if (previousQuery !== branch.query || previousSql !== refreshedSql) {
|
|
159
|
-
applied.push(buildSssqlRefreshApplied(branch, previousSql));
|
|
157
|
+
applied.push(buildSssqlRefreshApplied(branch, previousSql, options));
|
|
160
158
|
continue;
|
|
161
159
|
}
|
|
162
|
-
skipped.push(buildSssqlRefreshSkipped(branch, "SSSQL_OPTIONAL_REFRESH_NOOP", "SSSQL optional branch refresh found no safe placement change to apply."));
|
|
160
|
+
skipped.push(buildSssqlRefreshSkipped(branch, "SSSQL_OPTIONAL_REFRESH_NOOP", "SSSQL optional branch refresh found no safe placement change to apply.", options));
|
|
163
161
|
}
|
|
164
162
|
return {
|
|
165
|
-
|
|
163
|
+
query,
|
|
164
|
+
sql: applied.length > 0 || (0, SqlComponentFormatter_1.hasSqlComponentFormatOverride)(options)
|
|
165
|
+
? (0, SqlComponentFormatter_1.formatSqlComponent)(query, options)
|
|
166
|
+
: fallbackSql,
|
|
166
167
|
applied,
|
|
167
168
|
skipped,
|
|
168
|
-
warnings:
|
|
169
|
-
errors:
|
|
170
|
-
formatterGeneratedSource:
|
|
169
|
+
warnings: [],
|
|
170
|
+
errors: [],
|
|
171
|
+
formatterGeneratedSource: false
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
const refreshRemainingSssqlBranchesFromSql = (sql, parameters, options) => {
|
|
175
|
+
const parsed = parseConditionOptimizationInput(sql, options);
|
|
176
|
+
if (!parsed.query) {
|
|
177
|
+
return {
|
|
178
|
+
query: null,
|
|
179
|
+
sql: parsed.sql,
|
|
180
|
+
applied: [],
|
|
181
|
+
skipped: [],
|
|
182
|
+
warnings: parsed.warnings,
|
|
183
|
+
errors: parsed.errors,
|
|
184
|
+
formatterGeneratedSource: parsed.formatterGeneratedSource
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const refreshed = refreshRemainingSssqlBranches(parsed.query, sql, parameters, options);
|
|
188
|
+
return {
|
|
189
|
+
...refreshed,
|
|
190
|
+
warnings: [...parsed.warnings, ...refreshed.warnings],
|
|
191
|
+
errors: [...parsed.errors, ...refreshed.errors],
|
|
192
|
+
formatterGeneratedSource: parsed.formatterGeneratedSource || refreshed.formatterGeneratedSource
|
|
171
193
|
};
|
|
172
194
|
};
|
|
173
195
|
const runSssqlOptionalConditionPhase = (input, options) => {
|
|
174
196
|
var _a;
|
|
175
|
-
const
|
|
197
|
+
const reuseOwnedModel = options.cloneInput === false && typeof input !== "string";
|
|
198
|
+
const parsed = parseConditionOptimizationInput(input, options);
|
|
176
199
|
const warnings = [...parsed.warnings];
|
|
177
200
|
let errors = [...parsed.errors];
|
|
178
201
|
const applied = [];
|
|
@@ -180,6 +203,7 @@ const runSssqlOptionalConditionPhase = (input, options) => {
|
|
|
180
203
|
const optionalConditionParameters = (_a = options.optionalConditionParameters) !== null && _a !== void 0 ? _a : {};
|
|
181
204
|
if (!parsed.query) {
|
|
182
205
|
return {
|
|
206
|
+
query: null,
|
|
183
207
|
sql: parsed.sql,
|
|
184
208
|
applied,
|
|
185
209
|
skipped,
|
|
@@ -189,14 +213,16 @@ const runSssqlOptionalConditionPhase = (input, options) => {
|
|
|
189
213
|
};
|
|
190
214
|
}
|
|
191
215
|
let currentSql = parsed.sql;
|
|
216
|
+
let currentQuery = parsed.query;
|
|
217
|
+
let formatterGeneratedSource = parsed.formatterGeneratedSource;
|
|
192
218
|
const branches = (0, PruneOptionalConditionBranches_1.collectSupportedOptionalConditionBranches)(parsed.query);
|
|
193
219
|
const pruneBranches = branches.filter(branch => hasOwnParameter(optionalConditionParameters, branch.parameterName)
|
|
194
220
|
&& isAbsentOptionalValue(optionalConditionParameters, branch.parameterName));
|
|
195
221
|
if (pruneBranches.length > 0) {
|
|
196
222
|
try {
|
|
197
223
|
(0, PruneOptionalConditionBranches_1.pruneOptionalConditionBranches)(parsed.query, optionalConditionParameters);
|
|
198
|
-
currentSql = formatSqlComponent(parsed.query);
|
|
199
|
-
applied.push(...pruneBranches.map(buildSssqlApplied));
|
|
224
|
+
currentSql = (0, SqlComponentFormatter_1.formatSqlComponent)(parsed.query, options);
|
|
225
|
+
applied.push(...pruneBranches.map(branch => buildSssqlApplied(branch, options)));
|
|
200
226
|
}
|
|
201
227
|
catch (error) {
|
|
202
228
|
errors = [...errors, {
|
|
@@ -208,28 +234,33 @@ const runSssqlOptionalConditionPhase = (input, options) => {
|
|
|
208
234
|
}
|
|
209
235
|
}
|
|
210
236
|
if (errors.length === 0) {
|
|
211
|
-
const refreshPhase =
|
|
237
|
+
const refreshPhase = reuseOwnedModel
|
|
238
|
+
? refreshRemainingSssqlBranches(parsed.query, currentSql, optionalConditionParameters, options)
|
|
239
|
+
: refreshRemainingSssqlBranchesFromSql(currentSql, optionalConditionParameters, options);
|
|
212
240
|
applied.push(...refreshPhase.applied);
|
|
213
241
|
skipped.push(...refreshPhase.skipped);
|
|
214
242
|
warnings.push(...refreshPhase.warnings);
|
|
215
243
|
errors.push(...refreshPhase.errors);
|
|
216
244
|
currentSql = refreshPhase.sql;
|
|
245
|
+
currentQuery = refreshPhase.query;
|
|
246
|
+
formatterGeneratedSource = formatterGeneratedSource || refreshPhase.formatterGeneratedSource;
|
|
217
247
|
}
|
|
218
248
|
else {
|
|
219
249
|
for (const branch of branches) {
|
|
220
250
|
if (pruneBranches.includes(branch)) {
|
|
221
251
|
continue;
|
|
222
252
|
}
|
|
223
|
-
skipped.push(buildSssqlSkipped(branch, optionalConditionParameters));
|
|
253
|
+
skipped.push(buildSssqlSkipped(branch, optionalConditionParameters, options));
|
|
224
254
|
}
|
|
225
255
|
}
|
|
226
256
|
return {
|
|
257
|
+
query: errors.length === 0 ? currentQuery : null,
|
|
227
258
|
sql: errors.length === 0 ? currentSql : parsed.sql,
|
|
228
259
|
applied,
|
|
229
260
|
skipped,
|
|
230
261
|
warnings,
|
|
231
262
|
errors,
|
|
232
|
-
formatterGeneratedSource
|
|
263
|
+
formatterGeneratedSource
|
|
233
264
|
};
|
|
234
265
|
};
|
|
235
266
|
const mapParameterWarnings = (warnings) => warnings.map(warning => ({
|
|
@@ -248,6 +279,22 @@ const mapParameterSkipped = (skipped) => skipped.map(item => ({
|
|
|
248
279
|
phaseKind: "parameter_condition_placement",
|
|
249
280
|
...item
|
|
250
281
|
}));
|
|
282
|
+
const mapStaticWarnings = (warnings) => warnings.map(warning => ({
|
|
283
|
+
phaseKind: "static_predicate_placement",
|
|
284
|
+
...warning
|
|
285
|
+
}));
|
|
286
|
+
const mapStaticErrors = (errors) => errors.map(error => ({
|
|
287
|
+
phaseKind: "static_predicate_placement",
|
|
288
|
+
...error
|
|
289
|
+
}));
|
|
290
|
+
const mapStaticApplied = (applied) => applied.map(item => ({
|
|
291
|
+
phaseKind: "static_predicate_placement",
|
|
292
|
+
...item
|
|
293
|
+
}));
|
|
294
|
+
const mapStaticSkipped = (skipped) => skipped.map(item => ({
|
|
295
|
+
phaseKind: "static_predicate_placement",
|
|
296
|
+
...item
|
|
297
|
+
}));
|
|
251
298
|
const makePhaseSummary = (kind, counts) => ({
|
|
252
299
|
kind,
|
|
253
300
|
appliedCount: counts.appliedCount,
|
|
@@ -256,24 +303,50 @@ const makePhaseSummary = (kind, counts) => ({
|
|
|
256
303
|
errorCount: counts.errorCount
|
|
257
304
|
});
|
|
258
305
|
const runConditionOptimization = (input, options, defaultDryRun) => {
|
|
259
|
-
var _a;
|
|
306
|
+
var _a, _b, _c;
|
|
260
307
|
const dryRun = (_a = options.dryRun) !== null && _a !== void 0 ? _a : defaultDryRun;
|
|
261
|
-
|
|
262
|
-
//
|
|
263
|
-
//
|
|
308
|
+
const reuseOwnedModel = options.cloneInput === false && typeof input !== "string";
|
|
309
|
+
// Run semantic SSSQL handling before generic placement phases so optional
|
|
310
|
+
// branches remain owned by SSSQL even if later phases grow broader support.
|
|
264
311
|
const sssqlPhase = runSssqlOptionalConditionPhase(input, { ...options, dryRun });
|
|
312
|
+
const parameterOptimizer = new ParameterConditionPlacementOptimizer_1.ParameterConditionPlacementOptimizer();
|
|
313
|
+
const parameterInput = reuseOwnedModel
|
|
314
|
+
? (_b = sssqlPhase.query) !== null && _b !== void 0 ? _b : sssqlPhase.sql
|
|
315
|
+
: sssqlPhase.sql;
|
|
316
|
+
const parameterOptions = {
|
|
317
|
+
...options,
|
|
318
|
+
dryRun,
|
|
319
|
+
cloneInput: reuseOwnedModel && sssqlPhase.query ? false : options.cloneInput
|
|
320
|
+
};
|
|
265
321
|
const parameterPhase = dryRun
|
|
266
|
-
?
|
|
267
|
-
:
|
|
322
|
+
? parameterOptimizer.plan(parameterInput, parameterOptions)
|
|
323
|
+
: parameterOptimizer.optimize(parameterInput, parameterOptions);
|
|
268
324
|
const parameterWarnings = mapParameterWarnings(parameterPhase.warnings);
|
|
269
325
|
const parameterErrors = mapParameterErrors(parameterPhase.errors);
|
|
270
326
|
const parameterApplied = mapParameterApplied(parameterPhase.applied);
|
|
271
327
|
const parameterSkipped = mapParameterSkipped(parameterPhase.skipped);
|
|
272
|
-
const
|
|
273
|
-
const
|
|
328
|
+
const staticOptimizer = new StaticPredicatePlacementOptimizer_1.StaticPredicatePlacementOptimizer();
|
|
329
|
+
const staticInput = reuseOwnedModel
|
|
330
|
+
? (_c = parameterPhase.query) !== null && _c !== void 0 ? _c : parameterPhase.sql
|
|
331
|
+
: parameterPhase.sql;
|
|
332
|
+
const staticOptions = {
|
|
333
|
+
...options,
|
|
334
|
+
dryRun,
|
|
335
|
+
cloneInput: reuseOwnedModel && parameterPhase.query ? false : options.cloneInput
|
|
336
|
+
};
|
|
337
|
+
const staticPhase = dryRun
|
|
338
|
+
? staticOptimizer.plan(staticInput, staticOptions)
|
|
339
|
+
: staticOptimizer.optimize(staticInput, staticOptions);
|
|
340
|
+
const staticWarnings = mapStaticWarnings(staticPhase.warnings);
|
|
341
|
+
const staticErrors = mapStaticErrors(staticPhase.errors);
|
|
342
|
+
const staticApplied = mapStaticApplied(staticPhase.applied);
|
|
343
|
+
const staticSkipped = mapStaticSkipped(staticPhase.skipped);
|
|
344
|
+
const warnings = [...sssqlPhase.warnings, ...parameterWarnings, ...staticWarnings];
|
|
345
|
+
const errors = [...sssqlPhase.errors, ...parameterErrors, ...staticErrors];
|
|
274
346
|
return {
|
|
275
347
|
ok: errors.length === 0,
|
|
276
|
-
sql:
|
|
348
|
+
sql: staticPhase.sql,
|
|
349
|
+
query: staticPhase.query,
|
|
277
350
|
phases: [
|
|
278
351
|
makePhaseSummary("sssql_optional_condition", {
|
|
279
352
|
appliedCount: sssqlPhase.applied.length,
|
|
@@ -286,17 +359,25 @@ const runConditionOptimization = (input, options, defaultDryRun) => {
|
|
|
286
359
|
skippedCount: parameterSkipped.length,
|
|
287
360
|
warningCount: parameterWarnings.length,
|
|
288
361
|
errorCount: parameterErrors.length
|
|
362
|
+
}),
|
|
363
|
+
makePhaseSummary("static_predicate_placement", {
|
|
364
|
+
appliedCount: staticApplied.length,
|
|
365
|
+
skippedCount: staticSkipped.length,
|
|
366
|
+
warningCount: staticWarnings.length,
|
|
367
|
+
errorCount: staticErrors.length
|
|
289
368
|
})
|
|
290
369
|
],
|
|
291
|
-
applied: [...sssqlPhase.applied, ...parameterApplied],
|
|
292
|
-
skipped: [...sssqlPhase.skipped, ...parameterSkipped],
|
|
370
|
+
applied: [...sssqlPhase.applied, ...parameterApplied, ...staticApplied],
|
|
371
|
+
skipped: [...sssqlPhase.skipped, ...parameterSkipped, ...staticSkipped],
|
|
293
372
|
warnings,
|
|
294
373
|
errors,
|
|
295
374
|
safety: {
|
|
296
375
|
mode: "safe_only",
|
|
297
376
|
unsafeRewriteApplied: false,
|
|
298
377
|
dryRun,
|
|
299
|
-
formatterGeneratedSource: sssqlPhase.formatterGeneratedSource
|
|
378
|
+
formatterGeneratedSource: sssqlPhase.formatterGeneratedSource
|
|
379
|
+
|| parameterPhase.safety.formatterGeneratedSource
|
|
380
|
+
|| staticPhase.safety.formatterGeneratedSource
|
|
300
381
|
}
|
|
301
382
|
};
|
|
302
383
|
};
|