@rex0220/kintone-sql-tools 3.64.0 → 3.66.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-cli/ksql.js +969 -124
- package/dist-engine/index.cjs +14 -14
- package/dist-engine/index.mjs +14 -14
- package/dist-engine/ksql-engine.umd.js +14 -14
- package/dist-engine/meta/bundle-baseline.json +10 -10
- package/dist-engine/meta/cjs.json +27 -14
- package/dist-engine/meta/esm.json +27 -14
- package/dist-engine/meta/umd.json +27 -14
- package/dist-engine/publicTypes.d.ts +6 -0
- package/dist-mcp/ksql-mcp.js +982 -136
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/cli/index.ts
|
|
22
22
|
var index_exports = {};
|
|
23
23
|
__export(index_exports, {
|
|
24
|
+
CLI_HELP_TEXT: () => CLI_HELP_TEXT,
|
|
24
25
|
CLI_IMPORT_SOURCE_REQUIRED_MESSAGE: () => CLI_IMPORT_SOURCE_REQUIRED_MESSAGE,
|
|
25
26
|
HELP_TEXT: () => HELP_TEXT,
|
|
26
27
|
buildBatchDmlConfirmMessage: () => buildBatchDmlConfirmMessage,
|
|
@@ -1085,6 +1086,12 @@ var Parser = class {
|
|
|
1085
1086
|
this.tempTableRefs = [];
|
|
1086
1087
|
/** GROUP BY を読む前に作る B124 候補 leaf の診断位置。AST 公開型へ位置情報を足さない。 */
|
|
1087
1088
|
this.aggregateGroupKeyTokens = /* @__PURE__ */ new WeakMap();
|
|
1089
|
+
// ----------------------------------------------------------
|
|
1090
|
+
// WITH 句(CTE)
|
|
1091
|
+
// ----------------------------------------------------------
|
|
1092
|
+
/** B53 parser-private state. Kept here so earlier diagnostic source locations remain stable. */
|
|
1093
|
+
this.activeCteDefinition = null;
|
|
1094
|
+
this.provisionalRecursiveCte = null;
|
|
1088
1095
|
this.allowSelectArithVariable = false;
|
|
1089
1096
|
}
|
|
1090
1097
|
// ----------------------------------------------------------
|
|
@@ -1919,34 +1926,172 @@ var Parser = class {
|
|
|
1919
1926
|
offset
|
|
1920
1927
|
};
|
|
1921
1928
|
}
|
|
1922
|
-
// ----------------------------------------------------------
|
|
1923
|
-
// WITH 句(CTE)
|
|
1924
|
-
// ----------------------------------------------------------
|
|
1925
1929
|
parseWith() {
|
|
1926
1930
|
this.expect("WITH" /* WITH */);
|
|
1931
|
+
const recursive = this.isSoftKeyword("RECURSIVE") && this.peekAt(1).kind !== "AS" /* AS */ && this.peekAt(1).kind !== "(" /* LPAREN */;
|
|
1932
|
+
if (recursive) this.advance();
|
|
1927
1933
|
const ctes = [];
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1934
|
+
let recursiveCount = 0;
|
|
1935
|
+
try {
|
|
1936
|
+
do {
|
|
1937
|
+
const name = this.parseIdentifier();
|
|
1938
|
+
const columnAliases = this.parseOptionalCteColumnAliases();
|
|
1939
|
+
this.expect("AS" /* AS */);
|
|
1940
|
+
this.expect("(" /* LPAREN */);
|
|
1941
|
+
this.activeCteDefinition = { name, recursiveWith: recursive, phase: "SEED" };
|
|
1942
|
+
let query2;
|
|
1943
|
+
let recursiveSpec;
|
|
1944
|
+
const inner = this.peek().kind;
|
|
1945
|
+
if (inner === "SHOW" /* SHOW */) {
|
|
1946
|
+
query2 = this.parseShow();
|
|
1947
|
+
} else if (inner === "DESCRIBE" /* DESCRIBE */ || inner === "DESC" /* DESC */) {
|
|
1948
|
+
query2 = this.parseDescribe();
|
|
1949
|
+
} else if (inner === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === "GENERATE_SERIES") {
|
|
1950
|
+
query2 = this.parseGenerateSeries();
|
|
1951
|
+
} else if (recursive) {
|
|
1952
|
+
const parsed = this.parseRecursiveCteCandidate(name);
|
|
1953
|
+
query2 = parsed.query;
|
|
1954
|
+
recursiveSpec = parsed.recursiveSpec;
|
|
1955
|
+
} else {
|
|
1956
|
+
query2 = this.tryParseUnionChain(this.parseSelect());
|
|
1957
|
+
}
|
|
1958
|
+
this.expect(")" /* RPAREN */);
|
|
1959
|
+
const cycle = recursive && this.isSoftKeyword("CYCLE") ? this.parseRecursiveCycleClause() : null;
|
|
1960
|
+
if (cycle && !recursiveSpec) {
|
|
1961
|
+
throw new ParseError("CYCLE \u53E5\u306F\u81EA\u5DF1\u53C2\u7167\u3059\u308B\u518D\u5E30 CTE \u306B\u3060\u3051\u6307\u5B9A\u3067\u304D\u307E\u3059", this.prev());
|
|
1962
|
+
}
|
|
1963
|
+
if (recursiveSpec) {
|
|
1964
|
+
recursiveSpec = { ...recursiveSpec, cycle };
|
|
1965
|
+
this.validateRecursiveCte(name, columnAliases, recursiveSpec);
|
|
1966
|
+
recursiveCount++;
|
|
1967
|
+
if (recursiveCount > 1) {
|
|
1968
|
+
throw new ParseError("WITH RECURSIVE \u3067\u5B9A\u7FA9\u3067\u304D\u308B\u518D\u5E30 CTE \u306F1\u500B\u307E\u3067\u3067\u3059", this.prev());
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
if (columnAliases && !recursiveSpec) {
|
|
1972
|
+
throw new ParseError("CTE \u306E\u5217\u540D\u30EA\u30B9\u30C8\u306F WITH RECURSIVE \u306E\u518D\u5E30 CTE \u306B\u3060\u3051\u6307\u5B9A\u3067\u304D\u307E\u3059", this.prev());
|
|
1973
|
+
}
|
|
1974
|
+
const definition = { name, query: query2 };
|
|
1975
|
+
if (columnAliases) definition.columnAliases = columnAliases;
|
|
1976
|
+
if (recursiveSpec) definition.recursiveSpec = recursiveSpec;
|
|
1977
|
+
ctes.push(definition);
|
|
1978
|
+
this.activeCteDefinition = null;
|
|
1979
|
+
this.provisionalRecursiveCte = null;
|
|
1980
|
+
this.cteNames.add(name);
|
|
1981
|
+
} while (this.consume("," /* COMMA */));
|
|
1982
|
+
const query = this.tryParseUnionChain(this.parseSelect());
|
|
1983
|
+
return recursive ? { type: "WITH", ctes, query, recursive: true } : { type: "WITH", ctes, query };
|
|
1984
|
+
} finally {
|
|
1985
|
+
this.activeCteDefinition = null;
|
|
1986
|
+
this.provisionalRecursiveCte = null;
|
|
1987
|
+
this.cteNames.clear();
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
parseOptionalCteColumnAliases() {
|
|
1991
|
+
if (!this.consume("(" /* LPAREN */)) return void 0;
|
|
1992
|
+
const aliases = [];
|
|
1993
|
+
if (this.peek().kind === ")" /* RPAREN */) {
|
|
1994
|
+
throw new ParseError("CTE \u306E\u5217\u540D\u30EA\u30B9\u30C8\u306B\u306F1\u500B\u4EE5\u4E0A\u306E\u5217\u540D\u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
1995
|
+
}
|
|
1996
|
+
do
|
|
1997
|
+
aliases.push(this.parseIdentifier());
|
|
1998
|
+
while (this.consume("," /* COMMA */));
|
|
1999
|
+
this.expect(")" /* RPAREN */);
|
|
2000
|
+
if (new Set(aliases).size !== aliases.length) {
|
|
2001
|
+
throw new ParseError("CTE \u306E\u5217\u540D\u30EA\u30B9\u30C8\u306B\u540C\u3058\u5217\u540D\u3092\u91CD\u8907\u3057\u3066\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093", this.prev());
|
|
2002
|
+
}
|
|
2003
|
+
return aliases;
|
|
2004
|
+
}
|
|
2005
|
+
parseRecursiveCteCandidate(name) {
|
|
2006
|
+
const seed = this.parseSelect();
|
|
2007
|
+
if (this.peek().kind !== "UNION" /* UNION */) return { query: seed };
|
|
2008
|
+
this.advance();
|
|
2009
|
+
const all = this.consume("ALL" /* ALL */);
|
|
2010
|
+
this.activeCteDefinition = { name, recursiveWith: true, phase: "RECURSIVE_TERM" };
|
|
2011
|
+
this.provisionalRecursiveCte = { name, references: 0 };
|
|
2012
|
+
const recursiveTerm = this.parseSelect();
|
|
2013
|
+
const references = this.provisionalRecursiveCte.references;
|
|
2014
|
+
this.provisionalRecursiveCte = null;
|
|
2015
|
+
let query = { type: "UNION", all, left: seed, right: recursiveTerm };
|
|
2016
|
+
query = this.tryParseUnionChain(query);
|
|
2017
|
+
this.activeCteDefinition = { name, recursiveWith: true, phase: "SEED" };
|
|
2018
|
+
if (references === 0) return { query };
|
|
2019
|
+
if (!all || query.type !== "UNION" || query.left !== seed || query.right !== recursiveTerm) {
|
|
2020
|
+
throw new ParseError("\u518D\u5E30 CTE \u306F seed SELECT UNION ALL recursive SELECT \u306E2\u5206\u5C90\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
|
|
2021
|
+
}
|
|
2022
|
+
if (references !== 1) {
|
|
2023
|
+
throw new ParseError("\u518D\u5E30\u9805\u304B\u3089\u306E\u81EA\u5DF1\u53C2\u7167\u306F\u3061\u3087\u3046\u30691\u56DE\u306B\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
|
|
2024
|
+
}
|
|
2025
|
+
return {
|
|
2026
|
+
query,
|
|
2027
|
+
recursiveSpec: { seed, recursiveTerm, unionAll: true, cycle: null }
|
|
2028
|
+
};
|
|
2029
|
+
}
|
|
2030
|
+
parseRecursiveCycleClause() {
|
|
2031
|
+
this.advance();
|
|
2032
|
+
const column = this.parseIdentifier();
|
|
2033
|
+
this.expect("SET" /* SET */, "CYCLE \u306E\u5217\u540D\u306E\u5F8C\u306B\u306F SET \u304C\u5FC5\u8981\u3067\u3059");
|
|
2034
|
+
const markColumn = this.parseIdentifier();
|
|
2035
|
+
if (!this.isSoftKeyword("TO")) throw new ParseError("CYCLE \u306E mark \u5217\u306E\u5F8C\u306B\u306F TO \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
2036
|
+
this.advance();
|
|
2037
|
+
const mark = this.expect("STRING" /* STRING */, "CYCLE TO \u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
2038
|
+
if (!this.isSoftKeyword("DEFAULT")) throw new ParseError("CYCLE TO \u306E\u5024\u306E\u5F8C\u306B\u306F DEFAULT \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
2039
|
+
this.advance();
|
|
2040
|
+
const normal = this.expect("STRING" /* STRING */, "CYCLE DEFAULT \u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
2041
|
+
if (mark.value === normal.value) {
|
|
2042
|
+
throw new ParseError("CYCLE \u306E TO \u3068 DEFAULT \u306B\u306F\u7570\u306A\u308B\u6587\u5B57\u5217\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", normal);
|
|
2043
|
+
}
|
|
2044
|
+
return { column, markColumn, markValue: mark.value, defaultValue: normal.value, exposePath: false };
|
|
2045
|
+
}
|
|
2046
|
+
validateRecursiveCte(name, columnAliases, spec) {
|
|
2047
|
+
const token = this.prev();
|
|
2048
|
+
const seed = spec.seed;
|
|
2049
|
+
const term = spec.recursiveTerm;
|
|
2050
|
+
const { groupBy } = term;
|
|
2051
|
+
if (seed.columns.length !== term.columns.length) {
|
|
2052
|
+
throw new ParseError("\u518D\u5E30 CTE \u306E seed \u3068\u518D\u5E30\u9805\u306E\u5217\u6570\u3092\u4E00\u81F4\u3055\u305B\u3066\u304F\u3060\u3055\u3044", token);
|
|
2053
|
+
}
|
|
2054
|
+
if (columnAliases && columnAliases.length !== seed.columns.length) {
|
|
2055
|
+
throw new ParseError("CTE \u306E\u5217\u540D\u30EA\u30B9\u30C8\u3068 SELECT \u306E\u5217\u6570\u3092\u4E00\u81F4\u3055\u305B\u3066\u304F\u3060\u3055\u3044", token);
|
|
2056
|
+
}
|
|
2057
|
+
if (seed.columns.some((column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD") || term.columns.some((column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD")) {
|
|
2058
|
+
throw new ParseError("\u518D\u5E30 CTE \u306E seed \u3068\u518D\u5E30\u9805\u3067\u306F\u5217\u3092\u660E\u793A\u7684\u306B\u5C04\u5F71\u3057\u3066\u304F\u3060\u3055\u3044", token);
|
|
2059
|
+
}
|
|
2060
|
+
if (term.distinct || groupBy.length > 0 || term.grouping !== void 0 || term.having !== null || term.orderBy.length > 0 || term.orderMode !== "CANONICAL" || term.limit !== null || term.offset !== null) {
|
|
2061
|
+
throw new ParseError("\u518D\u5E30\u9805\u3067\u306F DISTINCT\u3001\u96C6\u8A08\u3001window\u3001GROUP BY\u3001HAVING\u3001ORDER BY\u3001LIMIT\u3001OFFSET \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", token);
|
|
2062
|
+
}
|
|
2063
|
+
if (term.joins.length !== 1 || term.joins[0].type !== "INNER") {
|
|
2064
|
+
throw new ParseError("\u518D\u5E30\u9805\u306F\u81EA\u5DF1\u53C2\u7167\u3068\u7269\u7406 source \u307E\u305F\u306F\u5148\u884C CTE \u306E INNER JOIN 1\u500B\u3067\u69CB\u6210\u3057\u3066\u304F\u3060\u3055\u3044", token);
|
|
2065
|
+
}
|
|
2066
|
+
const relationNames = [term.from.cteName, term.joins[0].table.cteName];
|
|
2067
|
+
if (relationNames.filter((value) => value === name).length !== 1) {
|
|
2068
|
+
throw new ParseError("\u518D\u5E30\u9805\u306E INNER JOIN \u306B\u306F\u81EA\u5DF1\u53C2\u7167\u3092\u3061\u3087\u3046\u30691\u56DE\u542B\u3081\u3066\u304F\u3060\u3055\u3044", token);
|
|
2069
|
+
}
|
|
2070
|
+
if (this.containsRecursiveForbiddenNode(term.columns) || this.containsRecursiveForbiddenNode(term.where)) {
|
|
2071
|
+
throw new ParseError("\u518D\u5E30\u9805\u3067\u306F\u96C6\u8A08\u3001window\u3001DISTINCT\u3001subquery \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", token);
|
|
2072
|
+
}
|
|
2073
|
+
const outputNames = columnAliases ?? seed.columns.map((column) => this.selectColumnOutputName(column));
|
|
2074
|
+
if (spec.cycle) {
|
|
2075
|
+
const cycleMatches = outputNames.filter((value) => value === spec.cycle.column).length;
|
|
2076
|
+
if (cycleMatches !== 1) {
|
|
2077
|
+
throw new ParseError("CYCLE \u5217\u306F\u518D\u5E30 CTE \u306E\u51FA\u529B\u52171\u500B\u3078\u4E00\u610F\u306B\u89E3\u6C7A\u3067\u304D\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059", token);
|
|
1942
2078
|
}
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
}
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
2079
|
+
if (outputNames.includes(spec.cycle.markColumn)) {
|
|
2080
|
+
throw new ParseError("CYCLE \u306E mark \u5217\u306F\u518D\u5E30 CTE \u306E\u65E2\u5B58\u51FA\u529B\u5217\u3068\u540C\u540D\u306B\u3067\u304D\u307E\u305B\u3093", token);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
containsRecursiveForbiddenNode(value) {
|
|
2085
|
+
if (Array.isArray(value)) return value.some((item) => this.containsRecursiveForbiddenNode(item));
|
|
2086
|
+
if (value === null || typeof value !== "object") return false;
|
|
2087
|
+
const node = value;
|
|
2088
|
+
if (node.type === "AGGREGATE" || node.type === "AGG_REF" || node.type === "ARITH_AGG_COL" || node.type === "WINDOW_COL" || node.type === "SCALAR_SUBQUERY" || node.type === "SCALAR_SUBQUERY_COL" || node.type === "SUBQUERY_IN_LIST" || node.type === "EXISTS") return true;
|
|
2089
|
+
return Object.values(node).some((item) => this.containsRecursiveForbiddenNode(item));
|
|
2090
|
+
}
|
|
2091
|
+
selectColumnOutputName(column) {
|
|
2092
|
+
if ("alias" in column && typeof column.alias === "string") return column.alias;
|
|
2093
|
+
if (column.type === "FIELD") return column.field;
|
|
2094
|
+
return null;
|
|
1950
2095
|
}
|
|
1951
2096
|
parseGenerateSeries() {
|
|
1952
2097
|
const name = this.advance();
|
|
@@ -2985,6 +3130,15 @@ var Parser = class {
|
|
|
2985
3130
|
const alias2 = this.consume("AS" /* AS */) ? this.parseTableAliasName() : this.tryParseImplicitAlias();
|
|
2986
3131
|
return { appId: 0, alias: alias2, cteName: name };
|
|
2987
3132
|
}
|
|
3133
|
+
if (this.activeCteDefinition?.name === name) {
|
|
3134
|
+
if (this.activeCteDefinition.recursiveWith && this.activeCteDefinition.phase === "RECURSIVE_TERM" && this.provisionalRecursiveCte?.name === name) {
|
|
3135
|
+
this.provisionalRecursiveCte.references++;
|
|
3136
|
+
const alias2 = this.consume("AS" /* AS */) ? this.parseTableAliasName() : this.tryParseImplicitAlias();
|
|
3137
|
+
return { appId: 0, alias: alias2, cteName: name };
|
|
3138
|
+
}
|
|
3139
|
+
const message = this.activeCteDefinition.recursiveWith ? this.activeCteDefinition.phase === "RECURSIVE_TERM" ? "\u518D\u5E30 CTE \u306F seed SELECT UNION ALL recursive SELECT \u306E2\u5206\u5C90\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044" : "\u518D\u5E30 CTE \u306E seed \u304B\u3089\u81EA\u5206\u81EA\u8EAB\u3092\u53C2\u7167\u3067\u304D\u307E\u305B\u3093" : "CTE \u306E\u5B9A\u7FA9\u5185\u304B\u3089\u81EA\u5206\u81EA\u8EAB\u3092\u53C2\u7167\u3057\u3066\u3044\u307E\u3059\u3002\u81EA\u5DF1\u53C2\u7167\u306B\u306F `WITH RECURSIVE` \u304C\u5FC5\u8981\u3067\u3059";
|
|
3140
|
+
throw new ParseError(message, nameTok);
|
|
3141
|
+
}
|
|
2988
3142
|
const { appId, subtableCode } = extractTableRef(name, this.prev());
|
|
2989
3143
|
if (subtableCode) {
|
|
2990
3144
|
const alias2 = this.consume("AS" /* AS */) ? this.parseTableAliasName() : this.tryParseImplicitAlias();
|
|
@@ -10008,6 +10162,10 @@ function resolveField(field, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
10008
10162
|
if (field.type === "ARITH_FIELD") return String(evalArithExpr(field.expr, row));
|
|
10009
10163
|
if (field.type === "CASE_FIELD") return evalCaseWhen(field.expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
10010
10164
|
if (field.type === "GROUPING_FIELD") return evalGroupingRef(field.ref, row);
|
|
10165
|
+
if (field.aggregateRef) {
|
|
10166
|
+
const ref = field.aggregateRef;
|
|
10167
|
+
return resolveFieldRef(row, aggregateSyntheticName(ref.func, ref.distinct, ref.arg));
|
|
10168
|
+
}
|
|
10011
10169
|
const key = field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
|
|
10012
10170
|
return resolveFieldRef(row, key);
|
|
10013
10171
|
}
|
|
@@ -12800,6 +12958,71 @@ function isOuterJoinNonPreservedTable(statement, table, isMainTable) {
|
|
|
12800
12958
|
return false;
|
|
12801
12959
|
}
|
|
12802
12960
|
|
|
12961
|
+
// src/core/recursiveCte.ts
|
|
12962
|
+
var RECURSIVE_CTE_MAX_DEPTH = 100;
|
|
12963
|
+
var RECURSIVE_CTE_MAX_ROWS = 1e4;
|
|
12964
|
+
var RECURSIVE_CTE_MAX_EXPANSIONS = 1e5;
|
|
12965
|
+
function resolveRecursiveCteLimits(options) {
|
|
12966
|
+
const entries = [
|
|
12967
|
+
["recursiveCteMaxDepth", options.recursiveCteMaxDepth, RECURSIVE_CTE_MAX_DEPTH],
|
|
12968
|
+
["recursiveCteMaxRows", options.recursiveCteMaxRows, RECURSIVE_CTE_MAX_ROWS],
|
|
12969
|
+
["recursiveCteMaxExpansions", options.recursiveCteMaxExpansions, RECURSIVE_CTE_MAX_EXPANSIONS]
|
|
12970
|
+
];
|
|
12971
|
+
for (const [name, value] of entries) {
|
|
12972
|
+
if (value !== void 0 && (!Number.isSafeInteger(value) || value <= 0)) {
|
|
12973
|
+
throw new RangeError(`${name} must be a positive safe integer`);
|
|
12974
|
+
}
|
|
12975
|
+
}
|
|
12976
|
+
return {
|
|
12977
|
+
depth: options.recursiveCteMaxDepth ?? RECURSIVE_CTE_MAX_DEPTH,
|
|
12978
|
+
rows: options.recursiveCteMaxRows ?? RECURSIVE_CTE_MAX_ROWS,
|
|
12979
|
+
expansions: options.recursiveCteMaxExpansions ?? RECURSIVE_CTE_MAX_EXPANSIONS
|
|
12980
|
+
};
|
|
12981
|
+
}
|
|
12982
|
+
var RecursiveCteLimitError = class extends Error {
|
|
12983
|
+
constructor(kind, limit, detected, cteName) {
|
|
12984
|
+
const label = kind === "DEPTH" ? "\u6DF1\u3055" : kind === "ROWS" ? "\u7D50\u679C\u884C\u6570" : "\u4E2D\u9593\u5C55\u958B\u6570";
|
|
12985
|
+
const unit = kind === "DEPTH" ? "" : " \u4EF6";
|
|
12986
|
+
super(`\u518D\u5E30 CTE\u300C${cteName}\u300D\u306E${label}\u304C\u4E0A\u9650 ${limit}${unit}\u3092\u8D85\u3048\u307E\u3057\u305F\uFF08\u691C\u51FA\u5024: ${detected}${unit}\uFF09\u3002`);
|
|
12987
|
+
this.name = "RecursiveCteLimitError";
|
|
12988
|
+
this.kind = kind;
|
|
12989
|
+
this.limit = limit;
|
|
12990
|
+
this.detected = detected;
|
|
12991
|
+
this.cteName = cteName;
|
|
12992
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
12993
|
+
}
|
|
12994
|
+
};
|
|
12995
|
+
var RecursiveCteLimitCounter = class {
|
|
12996
|
+
constructor(cteName, limits = resolveRecursiveCteLimits({})) {
|
|
12997
|
+
this.cteName = cteName;
|
|
12998
|
+
this.limits = limits;
|
|
12999
|
+
this.rows = 0;
|
|
13000
|
+
this.expansions = 0;
|
|
13001
|
+
}
|
|
13002
|
+
observeDepth(detected) {
|
|
13003
|
+
if (detected > this.limits.depth) {
|
|
13004
|
+
throw new RecursiveCteLimitError("DEPTH", this.limits.depth, detected, this.cteName);
|
|
13005
|
+
}
|
|
13006
|
+
}
|
|
13007
|
+
addRow() {
|
|
13008
|
+
this.rows++;
|
|
13009
|
+
if (this.rows > this.limits.rows) {
|
|
13010
|
+
throw new RecursiveCteLimitError("ROWS", this.limits.rows, this.rows, this.cteName);
|
|
13011
|
+
}
|
|
13012
|
+
}
|
|
13013
|
+
addExpansion() {
|
|
13014
|
+
this.expansions++;
|
|
13015
|
+
if (this.expansions > this.limits.expansions) {
|
|
13016
|
+
throw new RecursiveCteLimitError(
|
|
13017
|
+
"EXPANSIONS",
|
|
13018
|
+
this.limits.expansions,
|
|
13019
|
+
this.expansions,
|
|
13020
|
+
this.cteName
|
|
13021
|
+
);
|
|
13022
|
+
}
|
|
13023
|
+
}
|
|
13024
|
+
};
|
|
13025
|
+
|
|
12803
13026
|
// src/core/optimization/joinKeyPrefilter.ts
|
|
12804
13027
|
var JOIN_KEY_IN_CHUNK_SIZE = 50;
|
|
12805
13028
|
function buildJoinKeyPrefilterQueries(plan, field, quoteValue) {
|
|
@@ -14129,6 +14352,7 @@ async function deriveEmptyWildcardColumns(fields, subtableCode, loadProcessStatu
|
|
|
14129
14352
|
// src/engine/process.ts
|
|
14130
14353
|
var materializedSelectValues = /* @__PURE__ */ new WeakMap();
|
|
14131
14354
|
var sourceRows = /* @__PURE__ */ new WeakMap();
|
|
14355
|
+
var UNRESOLVED_AGGREGATE_COMPARISON_WARNING = "\u6BD4\u8F03\u6761\u4EF6\u3067\u53C2\u7167\u3057\u305F\u96C6\u8A08\u5024\u3092\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\u3002SELECT \u30EA\u30B9\u30C8\u306B\u540C\u3058\u96C6\u8A08\u5F0F\u3092\u542B\u3081\u3066\u304F\u3060\u3055\u3044\u3002";
|
|
14132
14356
|
function asProcessingRow(source) {
|
|
14133
14357
|
if (sourceRows.has(source)) return source;
|
|
14134
14358
|
let row;
|
|
@@ -14177,6 +14401,31 @@ function getMaterializedLookupValue(row, key) {
|
|
|
14177
14401
|
function getLegacyMaterializedValue(row, key) {
|
|
14178
14402
|
return materializedSelectValues.has(row) ? void 0 : row[key];
|
|
14179
14403
|
}
|
|
14404
|
+
function warnOnUnresolvedAggregateComparisons(node, rows, warnings) {
|
|
14405
|
+
if (!warnings || rows.length === 0) return;
|
|
14406
|
+
const keys = /* @__PURE__ */ new Set();
|
|
14407
|
+
const visit = (value) => {
|
|
14408
|
+
if (value === null || typeof value !== "object") return;
|
|
14409
|
+
if (Array.isArray(value)) {
|
|
14410
|
+
value.forEach(visit);
|
|
14411
|
+
return;
|
|
14412
|
+
}
|
|
14413
|
+
const record = value;
|
|
14414
|
+
if (record["type"] === "FIELD" && record["aggregateRef"] !== void 0) {
|
|
14415
|
+
const ref = record["aggregateRef"];
|
|
14416
|
+
keys.add(aggregateSyntheticName(ref.func, ref.distinct, ref.arg));
|
|
14417
|
+
return;
|
|
14418
|
+
}
|
|
14419
|
+
if (record["type"] === "SELECT" || record["type"] === "SCALAR_SUBQUERY") return;
|
|
14420
|
+
Object.values(record).forEach(visit);
|
|
14421
|
+
};
|
|
14422
|
+
visit(node);
|
|
14423
|
+
if ([...keys].some((key) => rows.some(
|
|
14424
|
+
(row) => getMaterializedLookupValue(row, key) === void 0 && row[key] === void 0
|
|
14425
|
+
))) {
|
|
14426
|
+
warnings.add(UNRESOLVED_AGGREGATE_COMPARISON_WARNING);
|
|
14427
|
+
}
|
|
14428
|
+
}
|
|
14180
14429
|
function havingEvaluationRow(row) {
|
|
14181
14430
|
const lookups = materializedSelectValues.get(row)?.byLookupKey;
|
|
14182
14431
|
if (!lookups || lookups.size === 0) return row;
|
|
@@ -14215,8 +14464,15 @@ function applyJoin(leftRows, rightRows, join2, columns = {}) {
|
|
|
14215
14464
|
return result2;
|
|
14216
14465
|
}
|
|
14217
14466
|
const { on, type: joinType } = join2;
|
|
14218
|
-
const
|
|
14219
|
-
|
|
14467
|
+
const normalizedOn = normalizeJoinConditionSides(
|
|
14468
|
+
on,
|
|
14469
|
+
leftRows,
|
|
14470
|
+
rightRows,
|
|
14471
|
+
columns.leftColumns,
|
|
14472
|
+
columns.rightColumns
|
|
14473
|
+
);
|
|
14474
|
+
const leftKey = joinFieldKey(normalizedOn.left);
|
|
14475
|
+
const rightKey = joinFieldKey(normalizedOn.right);
|
|
14220
14476
|
assertJoinKeyAvailable(leftRows, leftKey, columns.leftColumns);
|
|
14221
14477
|
assertJoinKeyAvailable(rightRows, rightKey, columns.rightColumns);
|
|
14222
14478
|
if (joinType === "RIGHT") {
|
|
@@ -14264,6 +14520,37 @@ function applyJoin(leftRows, rightRows, join2, columns = {}) {
|
|
|
14264
14520
|
}
|
|
14265
14521
|
return result;
|
|
14266
14522
|
}
|
|
14523
|
+
function joinFieldKey(ref) {
|
|
14524
|
+
return ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
|
|
14525
|
+
}
|
|
14526
|
+
function normalizeJoinConditionSides(on, leftRows, rightRows, leftColumns, rightColumns) {
|
|
14527
|
+
const leftSchema = leftColumns ?? Object.keys(leftRows[0] ?? {});
|
|
14528
|
+
const rightSchema = rightColumns ?? Object.keys(rightRows[0] ?? {});
|
|
14529
|
+
const leftAliases = qualifiedAliases(leftSchema);
|
|
14530
|
+
const rightAliases = qualifiedAliases(rightSchema);
|
|
14531
|
+
const sideFor = (ref) => {
|
|
14532
|
+
if (ref.tableAlias) {
|
|
14533
|
+
const inLeft2 = leftAliases.has(ref.tableAlias);
|
|
14534
|
+
const inRight2 = rightAliases.has(ref.tableAlias);
|
|
14535
|
+
if (inLeft2 !== inRight2) return inLeft2 ? "LEFT" : "RIGHT";
|
|
14536
|
+
}
|
|
14537
|
+
const key = joinFieldKey(ref);
|
|
14538
|
+
const inLeft = leftSchema.includes(key);
|
|
14539
|
+
const inRight = rightSchema.includes(key);
|
|
14540
|
+
return inLeft !== inRight ? inLeft ? "LEFT" : "RIGHT" : "UNKNOWN";
|
|
14541
|
+
};
|
|
14542
|
+
const leftSide = sideFor(on.left);
|
|
14543
|
+
const rightSide = sideFor(on.right);
|
|
14544
|
+
return leftSide === "RIGHT" && rightSide === "LEFT" ? { left: on.right, right: on.left } : on;
|
|
14545
|
+
}
|
|
14546
|
+
function qualifiedAliases(columns) {
|
|
14547
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
14548
|
+
for (const column of columns) {
|
|
14549
|
+
const separator = column.indexOf(".");
|
|
14550
|
+
if (separator > 0) aliases.add(column.slice(0, separator));
|
|
14551
|
+
}
|
|
14552
|
+
return aliases;
|
|
14553
|
+
}
|
|
14267
14554
|
function assertJoinKeyAvailable(rows, key, savedColumns) {
|
|
14268
14555
|
const missing = rows.length > 0 ? rows.some((row) => !Object.prototype.hasOwnProperty.call(row, key)) : savedColumns !== void 0 && !savedColumns.includes(key);
|
|
14269
14556
|
if (missing) {
|
|
@@ -15481,7 +15768,8 @@ function runFullScan(input) {
|
|
|
15481
15768
|
tableColumns,
|
|
15482
15769
|
hiddenQualifiedAliases,
|
|
15483
15770
|
resolvedGroupingSpec,
|
|
15484
|
-
plainGroupByPlan
|
|
15771
|
+
plainGroupByPlan,
|
|
15772
|
+
warnings
|
|
15485
15773
|
} = input;
|
|
15486
15774
|
const effectiveOrderSemantics = deriveOutputOrderSemantics(stmt.columns, aggregateSortKindResolver);
|
|
15487
15775
|
for (const [key, value] of orderSemantics ?? []) effectiveOrderSemantics.set(key, value);
|
|
@@ -15537,7 +15825,9 @@ function runFullScan(input) {
|
|
|
15537
15825
|
}
|
|
15538
15826
|
);
|
|
15539
15827
|
}
|
|
15828
|
+
warnOnUnresolvedAggregateComparisons(stmt.columns, rows, warnings);
|
|
15540
15829
|
const resolveHavingSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, aggregateSortKindResolver) : havingFieldSemanticsResolver?.(field);
|
|
15830
|
+
warnOnUnresolvedAggregateComparisons(stmt.having, rows, warnings);
|
|
15541
15831
|
rows = applyHaving(rows, stmt.having, havingFieldTypeResolver, resolveHavingSemantics);
|
|
15542
15832
|
rows = applyWindow(
|
|
15543
15833
|
rows,
|
|
@@ -17298,6 +17588,7 @@ function createInvocationCacheContext(cacheContext) {
|
|
|
17298
17588
|
return `${cacheContext}\0inv:${nextCacheInvocationId++}`;
|
|
17299
17589
|
}
|
|
17300
17590
|
async function execute(sql, client, options = {}) {
|
|
17591
|
+
resolveRecursiveCteLimits(options);
|
|
17301
17592
|
const startedAt = Date.now();
|
|
17302
17593
|
const cacheContext = createInvocationCacheContext(
|
|
17303
17594
|
resolveCacheContext(client, options.cacheContext)
|
|
@@ -17609,7 +17900,10 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
17609
17900
|
options.cursorMaxActive ?? 2,
|
|
17610
17901
|
stmt.query.type === "UPDATE" && stmt.query.applyBlocks?.length ? resolveApplyGuardLimit(options.dmlMaxRows, "dmlMaxRows", DEFAULT_APPLY_MAX_ROWS) : DEFAULT_APPLY_MAX_ROWS,
|
|
17611
17902
|
stmt.query.type === "UPDATE" && stmt.query.applyBlocks?.length ? resolveApplyGuardLimit(options.dmlMaxSubtableRows, "dmlMaxSubtableRows", DEFAULT_APPLY_MAX_SUBTABLE_ROWS) : DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
17612
|
-
relativeDatePlan
|
|
17903
|
+
relativeDatePlan,
|
|
17904
|
+
options.recursiveCteMaxDepth,
|
|
17905
|
+
options.recursiveCteMaxRows,
|
|
17906
|
+
options.recursiveCteMaxExpansions
|
|
17613
17907
|
);
|
|
17614
17908
|
// 一時テーブルはバッチスコープのため単文実行では拒否する(executeBatch を使う)
|
|
17615
17909
|
case "CREATE_TEMP_TABLE":
|
|
@@ -17881,6 +18175,7 @@ var BatchTimeoutError = class extends Error {
|
|
|
17881
18175
|
}
|
|
17882
18176
|
};
|
|
17883
18177
|
async function executeBatch(sql, client, options = {}) {
|
|
18178
|
+
resolveRecursiveCteLimits(options);
|
|
17884
18179
|
const statements = parseSqlBatch(sql, options.enableImport === true);
|
|
17885
18180
|
const analysis = analyzeBatch(statements);
|
|
17886
18181
|
statements.forEach((statement) => assertApplyExecutionScope("phase15b", statement));
|
|
@@ -18707,7 +19002,7 @@ function canProveTotalWindowOrder(stmt, orderBy, resolveField2, context, generat
|
|
|
18707
19002
|
}
|
|
18708
19003
|
function tieBreakAdvice(context, kind) {
|
|
18709
19004
|
if (context !== "DIRECT") {
|
|
18710
|
-
return "\
|
|
19005
|
+
return "\u30A6\u30A3\u30F3\u30C9\u30A6\u306E\u5404\u30D1\u30FC\u30C6\u30A3\u30B7\u30E7\u30F3\u5185\u3067\u3001ORDER BY \u306E\u5024\u306E\u7D44\u304C\u5165\u529B\u884C\u3092\u4E00\u610F\u306B\u8B58\u5225\u3059\u308B\u3068\u30AF\u30A8\u30EA\u69CB\u9020\u307E\u305F\u306F\u4FDD\u8A3C\u6E08\u307F\u306E\u30C7\u30FC\u30BF\u5236\u7D04\u304B\u3089\u78BA\u8A8D\u3067\u304D\u308B\u5834\u5408\u306B\u9650\u308A\u3001\u3053\u306E\u8B66\u544A\u306F\u7121\u8996\u3067\u304D\u307E\u3059\u3002\u5143\u306E\u96C6\u7D04\u30AD\u30FC\u3092\u3059\u3079\u3066 ORDER BY \u306B\u542B\u3080\u5F62\u3084\u3001JOIN \u5F8C\u3082\u540C\u3058\u7CFB\u5217\u5024\u304C\u5404\u30D1\u30FC\u30C6\u30A3\u30B7\u30E7\u30F3\u5185\u3067\u9AD8\u30051\u884C\u3068\u4FDD\u8A3C\u3067\u304D\u308B\u5F62\u304C\u8A72\u5F53\u3057\u307E\u3059\u3002\u751F\u6210\u5217\u3001\u518D\u5E30\u306E\u6DF1\u3055\u5217\u3001\u307E\u305F\u306F $id \u306B\u7531\u6765\u3059\u308B\u5217\u3067\u3042\u308B\u3068\u3044\u3046\u7406\u7531\u3060\u3051\u3067\u306F\u7121\u8996\u3067\u304D\u307E\u305B\u3093\u3002";
|
|
18711
19006
|
}
|
|
18712
19007
|
return kind === "RANGE" ? "ORDER BY \u306B\u30EC\u30B3\u30FC\u30C9\u756A\u53F7\u306A\u3069\u306E\u30BF\u30A4\u30D6\u30EC\u30FC\u30AF\u30AD\u30FC\u3092\u8DB3\u3057\u3066\u304F\u3060\u3055\u3044\u3002" : "\u30EC\u30B3\u30FC\u30C9\u756A\u53F7\u7B49\u3092 ORDER BY \u306B\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
|
|
18713
19008
|
}
|
|
@@ -18838,6 +19133,7 @@ async function assertDmlWhereCapability(stmt, client, cacheContext) {
|
|
|
18838
19133
|
}
|
|
18839
19134
|
async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false, forLibraryCapture = false, windowWarningContext = "DIRECT") {
|
|
18840
19135
|
let result;
|
|
19136
|
+
const subqueryWarnings = /* @__PURE__ */ new Set();
|
|
18841
19137
|
await validateSelectGroupingPlanning(stmt, client, cacheContext, cteCache);
|
|
18842
19138
|
if (isNoFromSelect(stmt)) {
|
|
18843
19139
|
result = executeNoFromSelect(stmt);
|
|
@@ -18867,7 +19163,7 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
18867
19163
|
cacheContext,
|
|
18868
19164
|
cteCache
|
|
18869
19165
|
);
|
|
18870
|
-
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
19166
|
+
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, subqueryWarnings, cteCache);
|
|
18871
19167
|
const whereCapability = rememberSelectWhereCapability(
|
|
18872
19168
|
stmt,
|
|
18873
19169
|
classifyWhereCapability(stmt.where, fieldSemanticsResolver)
|
|
@@ -18958,7 +19254,11 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
18958
19254
|
await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache, forLibraryCapture)
|
|
18959
19255
|
);
|
|
18960
19256
|
}
|
|
18961
|
-
return mergeSelectWarnings(result, [
|
|
19257
|
+
return mergeSelectWarnings(result, [
|
|
19258
|
+
...subqueryWarnings,
|
|
19259
|
+
...defaultRangeWarnings,
|
|
19260
|
+
...subtableFieldWarnings
|
|
19261
|
+
]);
|
|
18962
19262
|
}
|
|
18963
19263
|
function subtableGroupingAdvice(fieldName, owners) {
|
|
18964
19264
|
if (owners.length === 1) {
|
|
@@ -20426,8 +20726,8 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
20426
20726
|
const warnings = /* @__PURE__ */ new Set();
|
|
20427
20727
|
const parallel = options.fetchParallel ?? 1;
|
|
20428
20728
|
await Promise.all([
|
|
20429
|
-
resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
|
|
20430
|
-
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache)
|
|
20729
|
+
resolveSubqueries(stmt.where, client, options, cacheContext, warnings, cteCache),
|
|
20730
|
+
resolveSubqueries(stmt.having, client, options, cacheContext, warnings, cteCache)
|
|
20431
20731
|
]);
|
|
20432
20732
|
const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
|
|
20433
20733
|
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
@@ -20461,7 +20761,14 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
20461
20761
|
const mainBoundQuery = boundServerFunctionPlan?.queriesByAlias.get(
|
|
20462
20762
|
stmt.from.alias
|
|
20463
20763
|
) ?? "";
|
|
20464
|
-
const scalarCache = await resolveScalarColumns(
|
|
20764
|
+
const scalarCache = await resolveScalarColumns(
|
|
20765
|
+
stmt.columns,
|
|
20766
|
+
client,
|
|
20767
|
+
options,
|
|
20768
|
+
cacheContext,
|
|
20769
|
+
warnings,
|
|
20770
|
+
cteCache
|
|
20771
|
+
);
|
|
20465
20772
|
const constantFalse = isConstantFalseWhere(stmt.where);
|
|
20466
20773
|
const mainFetch = constantFalse ? Promise.resolve([]) : fetchTableRecordsForFullScan(
|
|
20467
20774
|
stmt,
|
|
@@ -20565,7 +20872,8 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
20565
20872
|
appliedKlikes: prefilterPlan?.appliedKlikes ?? pushdownPlan.appliedKlikes,
|
|
20566
20873
|
...prefilterPlan ? { residualWhere: prefilterPlan.residualWhere } : boundServerFunctionPlan ? { residualWhere: boundServerFunctionPlan.joinPlan.residualWhere } : {},
|
|
20567
20874
|
resolvedGroupingSpec: resolvedGroupingSpecs.get(stmt),
|
|
20568
|
-
plainGroupByPlan
|
|
20875
|
+
plainGroupByPlan,
|
|
20876
|
+
warnings
|
|
20569
20877
|
});
|
|
20570
20878
|
const columns = await restoreEmptyWildcardColumns(
|
|
20571
20879
|
stmt,
|
|
@@ -20583,6 +20891,53 @@ function assertUnionColumnCount(leftColumns, rightColumns) {
|
|
|
20583
20891
|
UNION \u306F\u5217\u3092\u4F4D\u7F6E\u3067\u5BFE\u5FDC\u3055\u305B\u308B\u305F\u3081\u3001\u4E21\u8FBA\u306E\u5217\u6570\u3092\u63C3\u3048\u3066\u304F\u3060\u3055\u3044`
|
|
20584
20892
|
);
|
|
20585
20893
|
}
|
|
20894
|
+
function alignSelectResultByPosition(result, targetColumns, targetMeta) {
|
|
20895
|
+
assertUnionColumnCount(targetColumns, result.columns);
|
|
20896
|
+
const rows = result.rows.map((row) => {
|
|
20897
|
+
const mapped = {};
|
|
20898
|
+
targetColumns.forEach((column, index) => {
|
|
20899
|
+
mapped[column] = row[result.columns[index] ?? column] ?? "";
|
|
20900
|
+
});
|
|
20901
|
+
return mapped;
|
|
20902
|
+
});
|
|
20903
|
+
const aligned = {
|
|
20904
|
+
...result,
|
|
20905
|
+
rows,
|
|
20906
|
+
columns: [...targetColumns],
|
|
20907
|
+
rowCount: rows.length
|
|
20908
|
+
};
|
|
20909
|
+
const sourceMeta = materializedMetaBySelectResult.get(result);
|
|
20910
|
+
if (targetMeta || sourceMeta) {
|
|
20911
|
+
const meta = /* @__PURE__ */ new Map();
|
|
20912
|
+
targetColumns.forEach((column, index) => {
|
|
20913
|
+
const sourceColumn = result.columns[index];
|
|
20914
|
+
const inferred = targetMeta?.get(column) ?? (sourceColumn === void 0 ? void 0 : sourceMeta?.get(sourceColumn));
|
|
20915
|
+
if (inferred) meta.set(column, { ...inferred, displayName: column });
|
|
20916
|
+
});
|
|
20917
|
+
materializedMetaBySelectResult.set(aligned, meta);
|
|
20918
|
+
}
|
|
20919
|
+
return aligned;
|
|
20920
|
+
}
|
|
20921
|
+
function combineUnionResults(leftResult, rightResult, all, captureColumnMeta) {
|
|
20922
|
+
const alignedRight = alignSelectResultByPosition(rightResult, leftResult.columns);
|
|
20923
|
+
const combined = [...leftResult.rows, ...alignedRight.rows];
|
|
20924
|
+
const rows = all ? combined : deduplicateRows(combined, leftResult.columns);
|
|
20925
|
+
const warnings = [.../* @__PURE__ */ new Set([
|
|
20926
|
+
...leftResult.warnings ?? [],
|
|
20927
|
+
...rightResult.warnings ?? []
|
|
20928
|
+
])];
|
|
20929
|
+
const result = {
|
|
20930
|
+
type: "SELECT",
|
|
20931
|
+
rows,
|
|
20932
|
+
columns: [...leftResult.columns],
|
|
20933
|
+
rowCount: rows.length,
|
|
20934
|
+
warnings
|
|
20935
|
+
};
|
|
20936
|
+
if (captureColumnMeta) {
|
|
20937
|
+
materializedMetaBySelectResult.set(result, mergeUnionColumnMeta(leftResult, rightResult));
|
|
20938
|
+
}
|
|
20939
|
+
return result;
|
|
20940
|
+
}
|
|
20586
20941
|
async function executeUnion(stmt, client, options, cacheContext, captureColumnMeta = false, forLibraryCapture = false) {
|
|
20587
20942
|
const completePolicy = buildCompleteInputPolicy(stmt, options, null);
|
|
20588
20943
|
return withCompleteInputPolicy(completePolicy, async () => {
|
|
@@ -20616,33 +20971,7 @@ async function executeUnion(stmt, client, options, cacheContext, captureColumnMe
|
|
|
20616
20971
|
"DERIVED"
|
|
20617
20972
|
)
|
|
20618
20973
|
]);
|
|
20619
|
-
|
|
20620
|
-
const rightCols = rightResult.columns;
|
|
20621
|
-
assertUnionColumnCount(leftCols, rightCols);
|
|
20622
|
-
const remappedRight = rightResult.rows.map((row) => {
|
|
20623
|
-
const mapped = {};
|
|
20624
|
-
leftCols.forEach((col, i) => {
|
|
20625
|
-
mapped[col] = row[rightCols[i] ?? col] ?? "";
|
|
20626
|
-
});
|
|
20627
|
-
return mapped;
|
|
20628
|
-
});
|
|
20629
|
-
const combined = [...leftResult.rows, ...remappedRight];
|
|
20630
|
-
const rows = stmt.all ? combined : deduplicateRows(combined, leftCols);
|
|
20631
|
-
const warnings = [.../* @__PURE__ */ new Set([
|
|
20632
|
-
...leftResult.warnings ?? [],
|
|
20633
|
-
...rightResult.warnings ?? []
|
|
20634
|
-
])];
|
|
20635
|
-
const result = {
|
|
20636
|
-
type: "SELECT",
|
|
20637
|
-
rows,
|
|
20638
|
-
columns: leftCols,
|
|
20639
|
-
rowCount: rows.length,
|
|
20640
|
-
warnings
|
|
20641
|
-
};
|
|
20642
|
-
if (captureColumnMeta) {
|
|
20643
|
-
materializedMetaBySelectResult.set(result, mergeUnionColumnMeta(leftResult, rightResult));
|
|
20644
|
-
}
|
|
20645
|
-
return result;
|
|
20974
|
+
return combineUnionResults(leftResult, rightResult, stmt.all, captureColumnMeta);
|
|
20646
20975
|
});
|
|
20647
20976
|
}
|
|
20648
20977
|
function deduplicateRows(rows, columns) {
|
|
@@ -20654,6 +20983,442 @@ function deduplicateRows(rows, columns) {
|
|
|
20654
20983
|
return true;
|
|
20655
20984
|
});
|
|
20656
20985
|
}
|
|
20986
|
+
function recursiveSelectOutputName(column) {
|
|
20987
|
+
if ("alias" in column && typeof column.alias === "string") return column.alias;
|
|
20988
|
+
if (column.type === "FIELD") return column.field;
|
|
20989
|
+
return null;
|
|
20990
|
+
}
|
|
20991
|
+
function recursiveOutputColumns(cte) {
|
|
20992
|
+
const spec = cte.recursiveSpec;
|
|
20993
|
+
if (cte.columnAliases) return [...cte.columnAliases];
|
|
20994
|
+
const names = spec.seed.columns.map(recursiveSelectOutputName);
|
|
20995
|
+
if (names.some((name) => name === null)) {
|
|
20996
|
+
throw new Error(
|
|
20997
|
+
`PlanningError: \u518D\u5E30 CTE\u300C${cte.name}\u300D\u3067\u5217\u540D\u30EA\u30B9\u30C8\u3092\u7701\u7565\u3059\u308B\u5834\u5408\u3001seed \u306E\u5F0F\u306B\u306F AS \u5225\u540D\u304C\u5FC5\u8981\u3067\u3059`
|
|
20998
|
+
);
|
|
20999
|
+
}
|
|
21000
|
+
const columns = names;
|
|
21001
|
+
if (new Set(columns).size !== columns.length) {
|
|
21002
|
+
throw new Error(
|
|
21003
|
+
`PlanningError: \u518D\u5E30 CTE\u300C${cte.name}\u300D\u3067\u5217\u540D\u30EA\u30B9\u30C8\u3092\u7701\u7565\u3059\u308B\u5834\u5408\u3001seed \u306E\u51FA\u529B\u5217\u540D\u3092\u91CD\u8907\u3055\u305B\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093`
|
|
21004
|
+
);
|
|
21005
|
+
}
|
|
21006
|
+
return columns;
|
|
21007
|
+
}
|
|
21008
|
+
function recursivePlanningColumnNames(stmt) {
|
|
21009
|
+
return stmt.columns.map((column, index) => recursiveSelectOutputName(column) ?? `__b53_column_${index}`);
|
|
21010
|
+
}
|
|
21011
|
+
function recursiveMetaCompatible(left, right) {
|
|
21012
|
+
const a = left.semantics;
|
|
21013
|
+
const b = right.semantics;
|
|
21014
|
+
if (!a || !b || a.compareMode === "unsupported" || b.compareMode === "unsupported") return false;
|
|
21015
|
+
if (a.compareMode !== b.compareMode) return false;
|
|
21016
|
+
if (left.sortKind && right.sortKind && left.sortKind !== right.sortKind) return false;
|
|
21017
|
+
if (a.inSubtable !== b.inSubtable || a.requiresCollectionOperators !== b.requiresCollectionOperators) return false;
|
|
21018
|
+
const synthetic = (fieldType) => fieldType === void 0 || fieldType.startsWith("KSQL_");
|
|
21019
|
+
if (!synthetic(left.fieldType) && !synthetic(right.fieldType) && left.fieldType !== right.fieldType) return false;
|
|
21020
|
+
return true;
|
|
21021
|
+
}
|
|
21022
|
+
async function buildRecursiveFieldResolver(stmt, client, cacheContext, materializedTables) {
|
|
21023
|
+
const tables = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
21024
|
+
const physical = /* @__PURE__ */ new Map();
|
|
21025
|
+
await Promise.all(tables.filter((table) => table.cteName === null).map(async (table) => {
|
|
21026
|
+
if (physical.has(table.appId)) return;
|
|
21027
|
+
const infos = await getFieldsCached(table.appId, client, cacheContext);
|
|
21028
|
+
physical.set(table.appId, new Map(infos.map((info) => [info.code, info])));
|
|
21029
|
+
}));
|
|
21030
|
+
const resolveInTable = (table, field) => {
|
|
21031
|
+
if (table.cteName !== null) return materializedTables.get(table.cteName)?.columnMeta?.get(field);
|
|
21032
|
+
const info = physical.get(table.appId)?.get(fieldCodeForTypeLookup(table, field));
|
|
21033
|
+
return info ? materializedMetaFromFieldInfo(info, table.appId) : systemColumnMeta(field);
|
|
21034
|
+
};
|
|
21035
|
+
return (ref) => {
|
|
21036
|
+
if (ref.tableAlias !== null) {
|
|
21037
|
+
const table = tables.find((candidate) => effectiveTableAlias(candidate) === ref.tableAlias);
|
|
21038
|
+
return table ? resolveInTable(table, ref.field) : void 0;
|
|
21039
|
+
}
|
|
21040
|
+
if (tables.length === 1) return resolveInTable(tables[0], ref.field);
|
|
21041
|
+
const matches = tables.map((table) => resolveInTable(table, ref.field)).filter(
|
|
21042
|
+
(meta) => meta !== void 0
|
|
21043
|
+
);
|
|
21044
|
+
return matches.length === 1 ? matches[0] : void 0;
|
|
21045
|
+
};
|
|
21046
|
+
}
|
|
21047
|
+
function validateRecursiveProjectionNode(value, resolveField2, numeric = false) {
|
|
21048
|
+
if (value === null || typeof value !== "object") return;
|
|
21049
|
+
if (Array.isArray(value)) {
|
|
21050
|
+
value.forEach((item) => validateRecursiveProjectionNode(item, resolveField2, numeric));
|
|
21051
|
+
return;
|
|
21052
|
+
}
|
|
21053
|
+
const node = value;
|
|
21054
|
+
if (node.type === "FIELD") {
|
|
21055
|
+
const ref = typeof node.tableAlias === "string" || node.tableAlias === null ? node : aggregateFieldRef(String(node.field ?? ""));
|
|
21056
|
+
const meta = resolveField2(ref);
|
|
21057
|
+
if (!meta?.semantics || meta.semantics.compareMode === "unsupported") {
|
|
21058
|
+
throw new Error(`PlanningError: \u518D\u5E30 CTE \u306E\u5C04\u5F71\u5217 ${ref.tableAlias ? `${ref.tableAlias}.` : ""}${ref.field} \u306E\u578B\u3092\u8A3C\u660E\u3067\u304D\u307E\u305B\u3093`);
|
|
21059
|
+
}
|
|
21060
|
+
if (numeric && meta.semantics.compareMode !== "number" && meta.semantics.compareMode !== "recordNumber") {
|
|
21061
|
+
throw new Error(`PlanningError: \u518D\u5E30 CTE \u306E\u6570\u5024\u6F14\u7B97\u306B\u6570\u5024\u3067\u306A\u3044\u5217 ${ref.field} \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`);
|
|
21062
|
+
}
|
|
21063
|
+
return;
|
|
21064
|
+
}
|
|
21065
|
+
if (node.type === "FIELD_REF" && typeof node.field === "string") {
|
|
21066
|
+
const ref = aggregateFieldRef(node.field);
|
|
21067
|
+
const meta = resolveField2(ref);
|
|
21068
|
+
if (!meta?.semantics || meta.semantics.compareMode === "unsupported") {
|
|
21069
|
+
throw new Error(`PlanningError: \u518D\u5E30 CTE \u306E\u5C04\u5F71\u5217 ${node.field} \u306E\u578B\u3092\u8A3C\u660E\u3067\u304D\u307E\u305B\u3093`);
|
|
21070
|
+
}
|
|
21071
|
+
if (numeric && meta.semantics.compareMode !== "number" && meta.semantics.compareMode !== "recordNumber") {
|
|
21072
|
+
throw new Error(`PlanningError: \u518D\u5E30 CTE \u306E\u6570\u5024\u6F14\u7B97\u306B\u6570\u5024\u3067\u306A\u3044\u5217 ${node.field} \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`);
|
|
21073
|
+
}
|
|
21074
|
+
return;
|
|
21075
|
+
}
|
|
21076
|
+
if (node.type === "ARITH" || node.type === "SCALAR_ARITH") {
|
|
21077
|
+
validateRecursiveProjectionNode(node.left, resolveField2, true);
|
|
21078
|
+
validateRecursiveProjectionNode(node.right, resolveField2, true);
|
|
21079
|
+
return;
|
|
21080
|
+
}
|
|
21081
|
+
for (const child of Object.values(node)) validateRecursiveProjectionNode(child, resolveField2, numeric);
|
|
21082
|
+
}
|
|
21083
|
+
async function inferRecursiveProjectionMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
|
|
21084
|
+
const resolveField2 = await buildRecursiveFieldResolver(stmt, client, cacheContext, materializedTables);
|
|
21085
|
+
stmt.columns.forEach((column) => validateRecursiveProjectionNode(column, resolveField2));
|
|
21086
|
+
const inferred = await inferSelectColumnMeta(
|
|
21087
|
+
stmt,
|
|
21088
|
+
recursivePlanningColumnNames(stmt),
|
|
21089
|
+
client,
|
|
21090
|
+
cacheContext,
|
|
21091
|
+
materializedTables
|
|
21092
|
+
);
|
|
21093
|
+
const sourceNames = recursivePlanningColumnNames(stmt);
|
|
21094
|
+
const aligned = /* @__PURE__ */ new Map();
|
|
21095
|
+
outputColumns.forEach((column, index) => {
|
|
21096
|
+
const meta = inferred.get(sourceNames[index]);
|
|
21097
|
+
if (!meta?.semantics || meta.semantics.fieldType === "KSQL_UNKNOWN" || meta.semantics.compareMode === "unsupported") {
|
|
21098
|
+
throw new Error(`PlanningError: \u518D\u5E30 CTE \u306E\u7B2C ${index + 1} \u5217\u306E\u578B\u3092\u9759\u7684\u306B\u8A3C\u660E\u3067\u304D\u307E\u305B\u3093`);
|
|
21099
|
+
}
|
|
21100
|
+
aligned.set(column, { ...meta, displayName: column });
|
|
21101
|
+
});
|
|
21102
|
+
return aligned;
|
|
21103
|
+
}
|
|
21104
|
+
function recursivePhysicalSourceKey(table) {
|
|
21105
|
+
return `${table.appId}:${table.subtableCode ?? ""}`;
|
|
21106
|
+
}
|
|
21107
|
+
function recursivePhysicalTables(...queries) {
|
|
21108
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
21109
|
+
for (const query of queries) {
|
|
21110
|
+
for (const table of [query.from, ...query.joins.map((join2) => join2.table)]) {
|
|
21111
|
+
if (table.cteName === null && !byKey.has(recursivePhysicalSourceKey(table))) {
|
|
21112
|
+
byKey.set(recursivePhysicalSourceKey(table), table);
|
|
21113
|
+
}
|
|
21114
|
+
}
|
|
21115
|
+
}
|
|
21116
|
+
return [...byKey.values()];
|
|
21117
|
+
}
|
|
21118
|
+
function splitRecursiveFieldRef(field) {
|
|
21119
|
+
const dot = field.indexOf(".");
|
|
21120
|
+
return dot < 0 ? { alias: null, field } : { alias: field.slice(0, dot), field: field.slice(dot + 1) };
|
|
21121
|
+
}
|
|
21122
|
+
function collectRecursivePhysicalSourceFields(queries) {
|
|
21123
|
+
const result = /* @__PURE__ */ new Map();
|
|
21124
|
+
const markAll = (tables) => {
|
|
21125
|
+
for (const table of tables) result.set(recursivePhysicalSourceKey(table), null);
|
|
21126
|
+
};
|
|
21127
|
+
for (const query of queries) {
|
|
21128
|
+
const physical = physicalSelectTables(query);
|
|
21129
|
+
for (const table of physical) {
|
|
21130
|
+
const key = recursivePhysicalSourceKey(table);
|
|
21131
|
+
if (!result.has(key)) result.set(key, /* @__PURE__ */ new Set());
|
|
21132
|
+
}
|
|
21133
|
+
const addRef = (rawAlias, field) => {
|
|
21134
|
+
const table = rawAlias === null ? physical.length === 1 ? physical[0] : void 0 : [query.from, ...query.joins.map((join2) => join2.table)].find((candidate) => effectiveTableAlias(candidate)?.toLowerCase() === rawAlias.toLowerCase());
|
|
21135
|
+
if (!table) {
|
|
21136
|
+
markAll(physical);
|
|
21137
|
+
return;
|
|
21138
|
+
}
|
|
21139
|
+
if (table.cteName !== null) return;
|
|
21140
|
+
const current = result.get(recursivePhysicalSourceKey(table));
|
|
21141
|
+
if (current !== null) current?.add(field);
|
|
21142
|
+
};
|
|
21143
|
+
const visit = (node) => {
|
|
21144
|
+
if (node === null || node === void 0 || typeof node !== "object") return;
|
|
21145
|
+
if (Array.isArray(node)) {
|
|
21146
|
+
node.forEach(visit);
|
|
21147
|
+
return;
|
|
21148
|
+
}
|
|
21149
|
+
const value = node;
|
|
21150
|
+
if (value.type === "WILDCARD" || value.type === "PARENT_WILDCARD") {
|
|
21151
|
+
markAll(physical);
|
|
21152
|
+
return;
|
|
21153
|
+
}
|
|
21154
|
+
if ((value.type === "FIELD" || value.type === "FIELD_REF") && typeof value.field === "string") {
|
|
21155
|
+
const encoded = splitRecursiveFieldRef(value.field);
|
|
21156
|
+
const alias = typeof value.tableAlias === "string" ? value.tableAlias : value.tableAlias === null ? null : encoded.alias;
|
|
21157
|
+
addRef(alias, encoded.field);
|
|
21158
|
+
return;
|
|
21159
|
+
}
|
|
21160
|
+
if ((value.type === "FIELD_NAME" || value.type === "GROUPING_REF") && typeof value.name === "string") {
|
|
21161
|
+
markAll(physical);
|
|
21162
|
+
return;
|
|
21163
|
+
}
|
|
21164
|
+
Object.values(value).forEach(visit);
|
|
21165
|
+
};
|
|
21166
|
+
visit(query.columns);
|
|
21167
|
+
visit(query.where);
|
|
21168
|
+
visit(normalizeGroupingSpec(query));
|
|
21169
|
+
visit(query.having);
|
|
21170
|
+
visit(query.orderBy);
|
|
21171
|
+
for (const join2 of query.joins) {
|
|
21172
|
+
if (join2.on === null) {
|
|
21173
|
+
markAll(physical);
|
|
21174
|
+
continue;
|
|
21175
|
+
}
|
|
21176
|
+
addRef(join2.on.left.tableAlias, join2.on.left.field);
|
|
21177
|
+
addRef(join2.on.right.tableAlias, join2.on.right.field);
|
|
21178
|
+
}
|
|
21179
|
+
}
|
|
21180
|
+
return result;
|
|
21181
|
+
}
|
|
21182
|
+
function recursiveSourceSelect(table, fields) {
|
|
21183
|
+
const columns = fields !== null && fields.size > 0 ? [...fields].map((field) => ({ type: "FIELD", field, alias: null })) : [{ type: "WILDCARD" }];
|
|
21184
|
+
return {
|
|
21185
|
+
type: "SELECT",
|
|
21186
|
+
distinct: false,
|
|
21187
|
+
columns,
|
|
21188
|
+
from: { ...table, alias: null },
|
|
21189
|
+
joins: [],
|
|
21190
|
+
where: null,
|
|
21191
|
+
groupBy: [],
|
|
21192
|
+
having: null,
|
|
21193
|
+
orderMode: "CANONICAL",
|
|
21194
|
+
orderBy: [],
|
|
21195
|
+
limit: null,
|
|
21196
|
+
offset: null
|
|
21197
|
+
};
|
|
21198
|
+
}
|
|
21199
|
+
async function materializeRecursivePhysicalSources(queries, client, options, cacheContext) {
|
|
21200
|
+
const fieldsBySource = collectRecursivePhysicalSourceFields(queries);
|
|
21201
|
+
const entries = await Promise.all(recursivePhysicalTables(...queries).map(async (table, index) => {
|
|
21202
|
+
const result = await executeSelect(
|
|
21203
|
+
recursiveSourceSelect(table, fieldsBySource.get(recursivePhysicalSourceKey(table)) ?? null),
|
|
21204
|
+
client,
|
|
21205
|
+
{ ...options, onLimitReached: "error" },
|
|
21206
|
+
cacheContext,
|
|
21207
|
+
void 0,
|
|
21208
|
+
true,
|
|
21209
|
+
false,
|
|
21210
|
+
"DERIVED"
|
|
21211
|
+
);
|
|
21212
|
+
const name = `__b53_source_${index}`;
|
|
21213
|
+
return [recursivePhysicalSourceKey(table), {
|
|
21214
|
+
name,
|
|
21215
|
+
warnings: result.warnings ?? [],
|
|
21216
|
+
table: {
|
|
21217
|
+
rows: result.rows,
|
|
21218
|
+
columns: result.columns,
|
|
21219
|
+
columnMeta: materializedMetaBySelectResult.get(result)
|
|
21220
|
+
}
|
|
21221
|
+
}];
|
|
21222
|
+
}));
|
|
21223
|
+
return new Map(entries);
|
|
21224
|
+
}
|
|
21225
|
+
function rewriteRecursivePhysicalSources(stmt, sources) {
|
|
21226
|
+
const rewrite = (table) => {
|
|
21227
|
+
if (table.cteName !== null) return table;
|
|
21228
|
+
const source = sources.get(recursivePhysicalSourceKey(table));
|
|
21229
|
+
if (!source) throw new Error("PlanningError: \u518D\u5E30 CTE \u306E\u5B8C\u5168\u5B9F\u4F53\u5316 source \u3092\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093");
|
|
21230
|
+
return { appId: 0, alias: table.alias, cteName: source.name, subtableCode: null };
|
|
21231
|
+
};
|
|
21232
|
+
return {
|
|
21233
|
+
...stmt,
|
|
21234
|
+
from: rewrite(stmt.from),
|
|
21235
|
+
joins: stmt.joins.map((join2) => ({ ...join2, table: rewrite(join2.table) }))
|
|
21236
|
+
};
|
|
21237
|
+
}
|
|
21238
|
+
function tableMetaForJoinKey(table, field, cache) {
|
|
21239
|
+
return table.cteName === null ? void 0 : cache.get(table.cteName)?.columnMeta?.get(field);
|
|
21240
|
+
}
|
|
21241
|
+
function recursiveJoinKey(value, semantics) {
|
|
21242
|
+
if (semantics.compareMode !== "number" && semantics.compareMode !== "recordNumber") return value;
|
|
21243
|
+
const decimal = parseExactDecimal(value);
|
|
21244
|
+
return decimal === null ? `invalid:${value}` : `${decimal.sign}:${decimal.coefficient}:${decimal.scale}`;
|
|
21245
|
+
}
|
|
21246
|
+
function recursiveJoinSides(cteName, term) {
|
|
21247
|
+
const join2 = term.joins[0];
|
|
21248
|
+
if (!join2 || join2.type !== "INNER") throw new Error("PlanningError: \u518D\u5E30\u9805\u306E INNER JOIN \u3092\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093");
|
|
21249
|
+
const self = term.from.cteName === cteName ? term.from : join2.table;
|
|
21250
|
+
const source = self === term.from ? join2.table : term.from;
|
|
21251
|
+
const selfAlias = effectiveTableAlias(self);
|
|
21252
|
+
const leftIsSelf = join2.on.left.tableAlias === selfAlias;
|
|
21253
|
+
const rightIsSelf = join2.on.right.tableAlias === selfAlias;
|
|
21254
|
+
if (leftIsSelf === rightIsSelf) throw new Error("PlanningError: \u518D\u5E30\u9805\u306E\u81EA\u5DF1\u53C2\u7167 JOIN \u30AD\u30FC\u3092\u4E00\u610F\u306B\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093");
|
|
21255
|
+
return {
|
|
21256
|
+
self,
|
|
21257
|
+
source,
|
|
21258
|
+
selfField: leftIsSelf ? join2.on.left.field : join2.on.right.field,
|
|
21259
|
+
sourceField: leftIsSelf ? join2.on.right.field : join2.on.left.field
|
|
21260
|
+
};
|
|
21261
|
+
}
|
|
21262
|
+
async function executeRecursiveCte(cte, client, options, cteCache, cacheContext) {
|
|
21263
|
+
const spec = cte.recursiveSpec;
|
|
21264
|
+
const outputColumns = recursiveOutputColumns(cte);
|
|
21265
|
+
const seedMeta = await inferRecursiveProjectionMeta(
|
|
21266
|
+
spec.seed,
|
|
21267
|
+
outputColumns,
|
|
21268
|
+
client,
|
|
21269
|
+
cacheContext,
|
|
21270
|
+
cteCache
|
|
21271
|
+
);
|
|
21272
|
+
const planningCache = new Map(cteCache);
|
|
21273
|
+
planningCache.set(cte.name, { rows: [], columns: outputColumns, columnMeta: seedMeta });
|
|
21274
|
+
const termMeta = await inferRecursiveProjectionMeta(
|
|
21275
|
+
spec.recursiveTerm,
|
|
21276
|
+
outputColumns,
|
|
21277
|
+
client,
|
|
21278
|
+
cacheContext,
|
|
21279
|
+
planningCache
|
|
21280
|
+
);
|
|
21281
|
+
outputColumns.forEach((column, index) => {
|
|
21282
|
+
const left = seedMeta.get(column);
|
|
21283
|
+
const right = termMeta.get(column);
|
|
21284
|
+
if (!left || !right || !recursiveMetaCompatible(left, right)) {
|
|
21285
|
+
throw new Error(`PlanningError: \u518D\u5E30 CTE\u300C${cte.name}\u300D\u306E\u7B2C ${index + 1} \u5217\u3067 seed \u3068\u518D\u5E30\u9805\u306E\u578B\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093`);
|
|
21286
|
+
}
|
|
21287
|
+
});
|
|
21288
|
+
const planningSides = recursiveJoinSides(cte.name, spec.recursiveTerm);
|
|
21289
|
+
const termFieldResolver = await buildRecursiveFieldResolver(
|
|
21290
|
+
spec.recursiveTerm,
|
|
21291
|
+
client,
|
|
21292
|
+
cacheContext,
|
|
21293
|
+
planningCache
|
|
21294
|
+
);
|
|
21295
|
+
const selfJoinMeta = termFieldResolver({
|
|
21296
|
+
type: "FIELD",
|
|
21297
|
+
tableAlias: effectiveTableAlias(planningSides.self),
|
|
21298
|
+
field: planningSides.selfField
|
|
21299
|
+
});
|
|
21300
|
+
const sourceJoinMeta = termFieldResolver({
|
|
21301
|
+
type: "FIELD",
|
|
21302
|
+
tableAlias: effectiveTableAlias(planningSides.source),
|
|
21303
|
+
field: planningSides.sourceField
|
|
21304
|
+
});
|
|
21305
|
+
if (!selfJoinMeta || !sourceJoinMeta || !recursiveMetaCompatible(selfJoinMeta, sourceJoinMeta)) {
|
|
21306
|
+
throw new Error(`PlanningError: \u518D\u5E30 CTE\u300C${cte.name}\u300D\u306E\u81EA\u5DF1\u53C2\u7167 JOIN \u30AD\u30FC\u306E\u578B\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093`);
|
|
21307
|
+
}
|
|
21308
|
+
const sources = await materializeRecursivePhysicalSources(
|
|
21309
|
+
[spec.seed, spec.recursiveTerm],
|
|
21310
|
+
client,
|
|
21311
|
+
options,
|
|
21312
|
+
cacheContext
|
|
21313
|
+
);
|
|
21314
|
+
const runtimeCache = new Map(cteCache);
|
|
21315
|
+
for (const source of sources.values()) runtimeCache.set(source.name, source.table);
|
|
21316
|
+
const seedQuery = rewriteRecursivePhysicalSources(spec.seed, sources);
|
|
21317
|
+
const termQuery = rewriteRecursivePhysicalSources(spec.recursiveTerm, sources);
|
|
21318
|
+
const rawSeed = await executeQueryWithCte(seedQuery, client, options, runtimeCache, cacheContext, true, true);
|
|
21319
|
+
const seed = alignSelectResultByPosition(rawSeed, outputColumns, seedMeta);
|
|
21320
|
+
const cycle = spec.cycle;
|
|
21321
|
+
const cycleMeta = cycle ? seedMeta.get(cycle.column) : void 0;
|
|
21322
|
+
const resultMeta = new Map(seedMeta);
|
|
21323
|
+
if (cycle) resultMeta.set(cycle.markColumn, { ...syntheticColumnMeta("string"), displayName: cycle.markColumn });
|
|
21324
|
+
const resultColumns = cycle ? [...outputColumns, cycle.markColumn] : [...outputColumns];
|
|
21325
|
+
const rows = [];
|
|
21326
|
+
let frontier = [];
|
|
21327
|
+
const warnings = /* @__PURE__ */ new Set([
|
|
21328
|
+
...seed.warnings ?? [],
|
|
21329
|
+
...[...sources.values()].flatMap((source) => source.warnings)
|
|
21330
|
+
]);
|
|
21331
|
+
const limits = new RecursiveCteLimitCounter(cte.name, resolveRecursiveCteLimits(options));
|
|
21332
|
+
const append = (row) => {
|
|
21333
|
+
limits.addRow();
|
|
21334
|
+
rows.push(row);
|
|
21335
|
+
};
|
|
21336
|
+
for (const row of seed.rows) {
|
|
21337
|
+
const value = cycle ? String(row[cycle.column] ?? "") : "";
|
|
21338
|
+
const emitted = cycle ? { ...row, [cycle.markColumn]: cycle.defaultValue } : row;
|
|
21339
|
+
append(emitted);
|
|
21340
|
+
frontier.push({ row, path: cycle ? [value] : [] });
|
|
21341
|
+
}
|
|
21342
|
+
const sides = recursiveJoinSides(cte.name, termQuery);
|
|
21343
|
+
const sourceTable = sides.source.cteName === null ? void 0 : runtimeCache.get(sides.source.cteName);
|
|
21344
|
+
if (!sourceTable) throw new Error("PlanningError: \u518D\u5E30\u9805\u306E\u5B8C\u5168\u5B9F\u4F53\u5316 source \u304C\u3042\u308A\u307E\u305B\u3093");
|
|
21345
|
+
const joinMeta = tableMetaForJoinKey(sides.self, sides.selfField, planningCache) ?? tableMetaForJoinKey(sides.source, sides.sourceField, runtimeCache);
|
|
21346
|
+
if (!joinMeta?.semantics || joinMeta.semantics.compareMode === "unsupported") {
|
|
21347
|
+
throw new Error(`PlanningError: \u518D\u5E30\u9805\u306E JOIN \u30AD\u30FC ${sides.selfField} \u306E\u578B\u3092\u8A3C\u660E\u3067\u304D\u307E\u305B\u3093`);
|
|
21348
|
+
}
|
|
21349
|
+
const sourceRowsByKey = /* @__PURE__ */ new Map();
|
|
21350
|
+
for (const sourceRow of sourceTable.rows) {
|
|
21351
|
+
const value = String(sourceRow[sides.sourceField] ?? "");
|
|
21352
|
+
const key = recursiveJoinKey(value, joinMeta.semantics);
|
|
21353
|
+
const bucket = sourceRowsByKey.get(key);
|
|
21354
|
+
if (bucket) bucket.push(sourceRow);
|
|
21355
|
+
else sourceRowsByKey.set(key, [sourceRow]);
|
|
21356
|
+
}
|
|
21357
|
+
const sourceHasEmptyKey = sourceRowsByKey.has(recursiveJoinKey("", joinMeta.semantics));
|
|
21358
|
+
let depth = 0;
|
|
21359
|
+
let emptyKeyWarned = false;
|
|
21360
|
+
while (frontier.length > 0) {
|
|
21361
|
+
depth++;
|
|
21362
|
+
const next = [];
|
|
21363
|
+
for (const parent of frontier) {
|
|
21364
|
+
const parentKey = String(parent.row[sides.selfField] ?? "");
|
|
21365
|
+
if (!emptyKeyWarned && parentKey === "" && sourceHasEmptyKey) {
|
|
21366
|
+
warnings.add(
|
|
21367
|
+
`\u518D\u5E30 CTE\u300C${cte.name}\u300D\u306E JOIN ${sides.selfField} = ${sides.sourceField} \u3067\u7B2C ${depth} \u53CD\u5FA9\u306B\u4E21\u5074\u306E\u7A7A\u30AD\u30FC\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002\u7A7A\u30AD\u30FC\u3069\u3046\u3057\u306F\u4E00\u81F4\u3057\u3001\u30EB\u30FC\u30C8\u7FA4\u3092\u518D\u5C55\u958B\u3057\u5F97\u307E\u3059\u3002`
|
|
21368
|
+
);
|
|
21369
|
+
emptyKeyWarned = true;
|
|
21370
|
+
}
|
|
21371
|
+
const matchingSourceRows = sourceRowsByKey.get(recursiveJoinKey(parentKey, joinMeta.semantics)) ?? [];
|
|
21372
|
+
for (const sourceRow of matchingSourceRows) {
|
|
21373
|
+
const sourceKey = String(sourceRow[sides.sourceField] ?? "");
|
|
21374
|
+
if (!compareScalarValues("=", parentKey, sourceKey, joinMeta.semantics)) continue;
|
|
21375
|
+
limits.addExpansion();
|
|
21376
|
+
}
|
|
21377
|
+
if (matchingSourceRows.length === 0) continue;
|
|
21378
|
+
const iterationCache = new Map(runtimeCache);
|
|
21379
|
+
iterationCache.set(cte.name, {
|
|
21380
|
+
rows: [parent.row],
|
|
21381
|
+
columns: outputColumns,
|
|
21382
|
+
columnMeta: seedMeta
|
|
21383
|
+
});
|
|
21384
|
+
const rawCandidates = await executeQueryWithCte(
|
|
21385
|
+
termQuery,
|
|
21386
|
+
client,
|
|
21387
|
+
options,
|
|
21388
|
+
iterationCache,
|
|
21389
|
+
cacheContext,
|
|
21390
|
+
true,
|
|
21391
|
+
true
|
|
21392
|
+
);
|
|
21393
|
+
for (const warning of rawCandidates.warnings ?? []) warnings.add(warning);
|
|
21394
|
+
const candidates = alignSelectResultByPosition(rawCandidates, outputColumns, seedMeta);
|
|
21395
|
+
if (candidates.rows.length > 0) limits.observeDepth(depth);
|
|
21396
|
+
for (const candidate of candidates.rows) {
|
|
21397
|
+
if (!cycle) {
|
|
21398
|
+
append(candidate);
|
|
21399
|
+
next.push({ row: candidate, path: [] });
|
|
21400
|
+
continue;
|
|
21401
|
+
}
|
|
21402
|
+
const value = String(candidate[cycle.column] ?? "");
|
|
21403
|
+
const isCycle = parent.path.some(
|
|
21404
|
+
(seen) => compareScalarValues("=", seen, value, cycleMeta.semantics)
|
|
21405
|
+
);
|
|
21406
|
+
append({ ...candidate, [cycle.markColumn]: isCycle ? cycle.markValue : cycle.defaultValue });
|
|
21407
|
+
if (!isCycle) next.push({ row: candidate, path: [...parent.path, value] });
|
|
21408
|
+
}
|
|
21409
|
+
}
|
|
21410
|
+
frontier = next;
|
|
21411
|
+
}
|
|
21412
|
+
const result = {
|
|
21413
|
+
type: "SELECT",
|
|
21414
|
+
rows,
|
|
21415
|
+
columns: resultColumns,
|
|
21416
|
+
rowCount: rows.length,
|
|
21417
|
+
warnings: [...warnings]
|
|
21418
|
+
};
|
|
21419
|
+
materializedMetaBySelectResult.set(result, resultMeta);
|
|
21420
|
+
return result;
|
|
21421
|
+
}
|
|
20657
21422
|
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
20658
21423
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
20659
21424
|
return executeSelect(
|
|
@@ -20671,7 +21436,9 @@ async function executeWith(stmt, client, options, cacheContext, seed, captureCol
|
|
|
20671
21436
|
const warnings = /* @__PURE__ */ new Set();
|
|
20672
21437
|
for (const cte of stmt.ctes) {
|
|
20673
21438
|
let result2;
|
|
20674
|
-
if (cte.
|
|
21439
|
+
if (cte.recursiveSpec) {
|
|
21440
|
+
result2 = await executeRecursiveCte(cte, client, options, cteCache, cacheContext);
|
|
21441
|
+
} else if (cte.query.type === "SHOW_APPS") {
|
|
20675
21442
|
result2 = await executeShowApps(client);
|
|
20676
21443
|
} else if (cte.query.type === "DESCRIBE") {
|
|
20677
21444
|
result2 = await executeDescribe(cte.query, client, cacheContext);
|
|
@@ -20728,33 +21495,7 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
20728
21495
|
executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta, true),
|
|
20729
21496
|
executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta, true)
|
|
20730
21497
|
]);
|
|
20731
|
-
|
|
20732
|
-
const rightCols = rightResult.columns;
|
|
20733
|
-
assertUnionColumnCount(leftCols, rightCols);
|
|
20734
|
-
const remapped = rightResult.rows.map((row) => {
|
|
20735
|
-
const mapped = {};
|
|
20736
|
-
leftCols.forEach((col, i) => {
|
|
20737
|
-
mapped[col] = row[rightCols[i] ?? col] ?? "";
|
|
20738
|
-
});
|
|
20739
|
-
return mapped;
|
|
20740
|
-
});
|
|
20741
|
-
const combined = [...leftResult.rows, ...remapped];
|
|
20742
|
-
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
20743
|
-
const warnings = [.../* @__PURE__ */ new Set([
|
|
20744
|
-
...leftResult.warnings ?? [],
|
|
20745
|
-
...rightResult.warnings ?? []
|
|
20746
|
-
])];
|
|
20747
|
-
const result2 = {
|
|
20748
|
-
type: "SELECT",
|
|
20749
|
-
rows,
|
|
20750
|
-
columns: leftCols,
|
|
20751
|
-
rowCount: rows.length,
|
|
20752
|
-
warnings
|
|
20753
|
-
};
|
|
20754
|
-
if (captureColumnMeta) {
|
|
20755
|
-
materializedMetaBySelectResult.set(result2, mergeUnionColumnMeta(leftResult, rightResult));
|
|
20756
|
-
}
|
|
20757
|
-
return result2;
|
|
21498
|
+
return combineUnionResults(leftResult, rightResult, query.all, captureColumnMeta);
|
|
20758
21499
|
}
|
|
20759
21500
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
20760
21501
|
if (!hasCteRef) {
|
|
@@ -20832,9 +21573,9 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
20832
21573
|
const warnings = /* @__PURE__ */ new Set();
|
|
20833
21574
|
const parallel = options.fetchParallel ?? 1;
|
|
20834
21575
|
await Promise.all([
|
|
20835
|
-
resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
|
|
20836
|
-
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache),
|
|
20837
|
-
resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache)
|
|
21576
|
+
resolveSubqueries(stmt.where, client, options, cacheContext, warnings, cteCache),
|
|
21577
|
+
resolveSubqueries(stmt.having, client, options, cacheContext, warnings, cteCache),
|
|
21578
|
+
resolveSelectCaseSubqueries(stmt, client, options, cacheContext, warnings, cteCache)
|
|
20838
21579
|
]);
|
|
20839
21580
|
const whereCapability = classifyWhereCapability(stmt.where, choiceAndWindowResolver);
|
|
20840
21581
|
if (whereCapability.capability === "UNSUPPORTED") {
|
|
@@ -20874,6 +21615,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
20874
21615
|
client,
|
|
20875
21616
|
effectiveOptions,
|
|
20876
21617
|
cacheContext,
|
|
21618
|
+
warnings,
|
|
20877
21619
|
cteCache
|
|
20878
21620
|
);
|
|
20879
21621
|
const orderByMetaPromise = Promise.resolve(orderMeta);
|
|
@@ -24337,17 +25079,17 @@ function parseSql(sql, enableImport = false) {
|
|
|
24337
25079
|
throw e;
|
|
24338
25080
|
}
|
|
24339
25081
|
}
|
|
24340
|
-
async function resolveSubqueries(where, client, options, cacheContext, cteCache) {
|
|
25082
|
+
async function resolveSubqueries(where, client, options, cacheContext, warnings, cteCache) {
|
|
24341
25083
|
const tasks = [];
|
|
24342
|
-
collectSubqueryTasks(where, client, options, cacheContext, tasks, cteCache);
|
|
25084
|
+
collectSubqueryTasks(where, client, options, cacheContext, tasks, warnings, cteCache);
|
|
24343
25085
|
await Promise.all(tasks);
|
|
24344
25086
|
}
|
|
24345
|
-
async function resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache) {
|
|
25087
|
+
async function resolveSelectCaseSubqueries(stmt, client, options, cacheContext, warnings, cteCache) {
|
|
24346
25088
|
const tasks = [];
|
|
24347
25089
|
for (const column of stmt.columns) {
|
|
24348
25090
|
if (column.type !== "CASE_COL") continue;
|
|
24349
25091
|
for (const branch of column.expr.branches) {
|
|
24350
|
-
tasks.push(resolveSubqueries(branch.condition, client, options, cacheContext, cteCache));
|
|
25092
|
+
tasks.push(resolveSubqueries(branch.condition, client, options, cacheContext, warnings, cteCache));
|
|
24351
25093
|
}
|
|
24352
25094
|
}
|
|
24353
25095
|
await Promise.all(tasks);
|
|
@@ -24358,19 +25100,21 @@ function runSubquery(query, client, options, cacheContext, cteCache) {
|
|
|
24358
25100
|
}
|
|
24359
25101
|
return executeSelect(query, client, options, cacheContext);
|
|
24360
25102
|
}
|
|
24361
|
-
function collectSubqueryTasks(where, client, options, cacheContext, tasks, cteCache) {
|
|
25103
|
+
function collectSubqueryTasks(where, client, options, cacheContext, tasks, warnings, cteCache) {
|
|
24362
25104
|
if (where === null) return;
|
|
24363
25105
|
switch (where.type) {
|
|
24364
25106
|
case "BINARY": {
|
|
24365
25107
|
const right = where.right;
|
|
24366
25108
|
if (right.type === "SUBQUERY_IN_LIST") {
|
|
24367
25109
|
tasks.push(runSubquery(right.query, client, options, cacheContext, cteCache).then((result) => {
|
|
25110
|
+
for (const warning of result.warnings ?? []) warnings.add(warning);
|
|
24368
25111
|
const col = right.column ?? (result.columns[0] ?? "");
|
|
24369
25112
|
right.resolved = new Set(result.rows.map((r) => r[col] ?? ""));
|
|
24370
25113
|
}));
|
|
24371
25114
|
}
|
|
24372
25115
|
if (right.type === "SCALAR_SUBQUERY") {
|
|
24373
25116
|
tasks.push(runSubquery(right.query, client, options, cacheContext, cteCache).then((result) => {
|
|
25117
|
+
for (const warning of result.warnings ?? []) warnings.add(warning);
|
|
24374
25118
|
if (result.rowCount === 0) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u5024\u3092\u8FD4\u3057\u307E\u305B\u3093\u3067\u3057\u305F");
|
|
24375
25119
|
if (result.rowCount > 1) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u8907\u6570\u884C\u3092\u8FD4\u3057\u307E\u3057\u305F\uFF081\u884C\u306E\u307F\u8A31\u53EF\uFF09");
|
|
24376
25120
|
const col = result.columns[0] ?? "";
|
|
@@ -24380,16 +25124,17 @@ function collectSubqueryTasks(where, client, options, cacheContext, tasks, cteCa
|
|
|
24380
25124
|
break;
|
|
24381
25125
|
}
|
|
24382
25126
|
case "LOGICAL":
|
|
24383
|
-
collectSubqueryTasks(where.left, client, options, cacheContext, tasks, cteCache);
|
|
24384
|
-
collectSubqueryTasks(where.right, client, options, cacheContext, tasks, cteCache);
|
|
25127
|
+
collectSubqueryTasks(where.left, client, options, cacheContext, tasks, warnings, cteCache);
|
|
25128
|
+
collectSubqueryTasks(where.right, client, options, cacheContext, tasks, warnings, cteCache);
|
|
24385
25129
|
break;
|
|
24386
25130
|
case "NOT":
|
|
24387
25131
|
case "GROUP":
|
|
24388
|
-
collectSubqueryTasks(where.expr, client, options, cacheContext, tasks, cteCache);
|
|
25132
|
+
collectSubqueryTasks(where.expr, client, options, cacheContext, tasks, warnings, cteCache);
|
|
24389
25133
|
break;
|
|
24390
25134
|
case "EXISTS": {
|
|
24391
25135
|
const node = where;
|
|
24392
25136
|
tasks.push(runSubquery(node.query, client, options, cacheContext, cteCache).then((result) => {
|
|
25137
|
+
for (const warning of result.warnings ?? []) warnings.add(warning);
|
|
24393
25138
|
node.resolved = result.rowCount > 0;
|
|
24394
25139
|
}));
|
|
24395
25140
|
break;
|
|
@@ -24409,7 +25154,7 @@ async function resolveSetSubqueries(assignments, client, options, cacheContext)
|
|
|
24409
25154
|
a.value = { type: "STRING", value: resolved };
|
|
24410
25155
|
}
|
|
24411
25156
|
}
|
|
24412
|
-
async function resolveScalarColumns(columns, client, options, cacheContext, cteCache) {
|
|
25157
|
+
async function resolveScalarColumns(columns, client, options, cacheContext, warnings, cteCache) {
|
|
24413
25158
|
const byQuery = /* @__PURE__ */ new Map();
|
|
24414
25159
|
const pending = [];
|
|
24415
25160
|
for (let i = 0; i < columns.length; i++) {
|
|
@@ -24419,6 +25164,7 @@ async function resolveScalarColumns(columns, client, options, cacheContext, cteC
|
|
|
24419
25164
|
let promise = byQuery.get(key);
|
|
24420
25165
|
if (!promise) {
|
|
24421
25166
|
promise = runSubquery(col.query, client, options, cacheContext, cteCache).then((result) => {
|
|
25167
|
+
for (const warning of result.warnings ?? []) warnings.add(warning);
|
|
24422
25168
|
if (result.rowCount === 0) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u5024\u3092\u8FD4\u3057\u307E\u305B\u3093\u3067\u3057\u305F");
|
|
24423
25169
|
if (result.rowCount > 1) throw new Error("\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA\u304C\u8907\u6570\u884C\u3092\u8FD4\u3057\u307E\u3057\u305F\uFF081\u884C\u306E\u307F\u8A31\u53EF\uFF09");
|
|
24424
25170
|
const firstCol = result.columns[0] ?? "";
|
|
@@ -25286,7 +26032,12 @@ var EXPLAIN_FETCH_PLAN = /* @__PURE__ */ Symbol("ksql.explainFetchPlan");
|
|
|
25286
26032
|
function setExplainFetchPlan(result, plan) {
|
|
25287
26033
|
result[EXPLAIN_FETCH_PLAN] = plan;
|
|
25288
26034
|
}
|
|
25289
|
-
async function buildBatchExplainPlans(sql, client, injectedVariables, cacheContext = "batch-explain", maxRecords = 1e4, cursorMaxActive = 2, enableImport = false, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, resolveMetadata = true) {
|
|
26035
|
+
async function buildBatchExplainPlans(sql, client, injectedVariables, cacheContext = "batch-explain", maxRecords = 1e4, cursorMaxActive = 2, enableImport = false, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, resolveMetadata = true, recursiveCteMaxDepth, recursiveCteMaxRows, recursiveCteMaxExpansions) {
|
|
26036
|
+
const recursiveLimits = resolveRecursiveCteLimits({
|
|
26037
|
+
recursiveCteMaxDepth,
|
|
26038
|
+
recursiveCteMaxRows,
|
|
26039
|
+
recursiveCteMaxExpansions
|
|
26040
|
+
});
|
|
25290
26041
|
const invocationCacheContext = createInvocationCacheContext(cacheContext);
|
|
25291
26042
|
try {
|
|
25292
26043
|
const statements = parseSqlBatch(sql, enableImport);
|
|
@@ -25365,7 +26116,8 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
25365
26116
|
dmlMaxSubtableRows,
|
|
25366
26117
|
fetchCollector,
|
|
25367
26118
|
tempSchemaLedger,
|
|
25368
|
-
createdSchema
|
|
26119
|
+
createdSchema,
|
|
26120
|
+
{ maxRecords, recursiveLimits }
|
|
25369
26121
|
), cursorMaxActive)
|
|
25370
26122
|
];
|
|
25371
26123
|
const metadataPlan = explainMetadataLines(whereAnalysis);
|
|
@@ -25397,7 +26149,7 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
25397
26149
|
releaseMetadataCacheScope(invocationCacheContext);
|
|
25398
26150
|
}
|
|
25399
26151
|
}
|
|
25400
|
-
function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGroupByPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, collector = { sources: [] }, tempSchemaLedger = /* @__PURE__ */ new Map(), createdSchema) {
|
|
26152
|
+
function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGroupByPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, collector = { sources: [] }, tempSchemaLedger = /* @__PURE__ */ new Map(), createdSchema, explainContext = defaultRecursiveExplainContext()) {
|
|
25401
26153
|
if (stmt.type === "CREATE_TEMP_TABLE") {
|
|
25402
26154
|
return [
|
|
25403
26155
|
`CREATE TEMP TABLE ${stmt.name}`,
|
|
@@ -25418,7 +26170,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25418
26170
|
plainGroupByPlans,
|
|
25419
26171
|
collector,
|
|
25420
26172
|
"main",
|
|
25421
|
-
tempSchemaLedger
|
|
26173
|
+
tempSchemaLedger,
|
|
26174
|
+
explainContext
|
|
25422
26175
|
).map((l) => ` ${l}`)
|
|
25423
26176
|
];
|
|
25424
26177
|
}
|
|
@@ -25443,7 +26196,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25443
26196
|
plainGroupByPlans,
|
|
25444
26197
|
collector,
|
|
25445
26198
|
"main",
|
|
25446
|
-
tempSchemaLedger
|
|
26199
|
+
tempSchemaLedger,
|
|
26200
|
+
explainContext
|
|
25447
26201
|
).map((l) => ` ${l}`)
|
|
25448
26202
|
];
|
|
25449
26203
|
}
|
|
@@ -25475,7 +26229,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25475
26229
|
plainGroupByPlans,
|
|
25476
26230
|
collector,
|
|
25477
26231
|
"main",
|
|
25478
|
-
tempSchemaLedger
|
|
26232
|
+
tempSchemaLedger,
|
|
26233
|
+
explainContext
|
|
25479
26234
|
);
|
|
25480
26235
|
}
|
|
25481
26236
|
if (stmt.type === "ASSERT") {
|
|
@@ -25497,7 +26252,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25497
26252
|
plainGroupByPlans,
|
|
25498
26253
|
collector,
|
|
25499
26254
|
"main",
|
|
25500
|
-
tempSchemaLedger
|
|
26255
|
+
tempSchemaLedger,
|
|
26256
|
+
explainContext
|
|
25501
26257
|
).map((l) => ` ${l}`));
|
|
25502
26258
|
});
|
|
25503
26259
|
return lines;
|
|
@@ -25522,7 +26278,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25522
26278
|
plainGroupByPlans,
|
|
25523
26279
|
collector,
|
|
25524
26280
|
"main",
|
|
25525
|
-
tempSchemaLedger
|
|
26281
|
+
tempSchemaLedger,
|
|
26282
|
+
explainContext
|
|
25526
26283
|
);
|
|
25527
26284
|
}
|
|
25528
26285
|
function hasTempTableRef(node) {
|
|
@@ -25535,7 +26292,7 @@ function hasTempTableRef(node) {
|
|
|
25535
26292
|
}
|
|
25536
26293
|
return false;
|
|
25537
26294
|
}
|
|
25538
|
-
function buildPlanForBatchQuery(query, info, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }, sourceRole = "main", tempSchemaLedger = /* @__PURE__ */ new Map()) {
|
|
26295
|
+
function buildPlanForBatchQuery(query, info, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }, sourceRole = "main", tempSchemaLedger = /* @__PURE__ */ new Map(), explainContext = defaultRecursiveExplainContext()) {
|
|
25539
26296
|
if (info.tempTablesReferenced.length === 0) {
|
|
25540
26297
|
return buildExplainPlan(
|
|
25541
26298
|
query,
|
|
@@ -25544,11 +26301,12 @@ function buildPlanForBatchQuery(query, info, capabilities, orderPlans, plainGrou
|
|
|
25544
26301
|
orderPlans,
|
|
25545
26302
|
100,
|
|
25546
26303
|
DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
25547
|
-
|
|
26304
|
+
explainContext.maxRecords,
|
|
25548
26305
|
plainGroupByPlans,
|
|
25549
26306
|
true,
|
|
25550
26307
|
collector,
|
|
25551
|
-
sourceRole
|
|
26308
|
+
sourceRole,
|
|
26309
|
+
explainContext.recursiveLimits
|
|
25552
26310
|
);
|
|
25553
26311
|
}
|
|
25554
26312
|
const lines = [];
|
|
@@ -25595,7 +26353,15 @@ function buildPlanForBatchQuery(query, info, capabilities, orderPlans, plainGrou
|
|
|
25595
26353
|
return lines;
|
|
25596
26354
|
}
|
|
25597
26355
|
var explainMaterializedTables = /* @__PURE__ */ new WeakMap();
|
|
25598
|
-
|
|
26356
|
+
function defaultRecursiveExplainContext() {
|
|
26357
|
+
return { maxRecords: 1e4, recursiveLimits: resolveRecursiveCteLimits({}) };
|
|
26358
|
+
}
|
|
26359
|
+
async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxActive, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, relativeDatePlan, recursiveCteMaxDepth, recursiveCteMaxRows, recursiveCteMaxExpansions) {
|
|
26360
|
+
const recursiveLimits = resolveRecursiveCteLimits({
|
|
26361
|
+
recursiveCteMaxDepth,
|
|
26362
|
+
recursiveCteMaxRows,
|
|
26363
|
+
recursiveCteMaxExpansions
|
|
26364
|
+
});
|
|
25599
26365
|
const sharedPlan = relativeDatePlan ?? await resolveRelativeDateExecutionPlan(stmt.query, client, cacheContext);
|
|
25600
26366
|
const analysis = await buildExplainWhereAnalysis(
|
|
25601
26367
|
stmt.query,
|
|
@@ -25621,7 +26387,9 @@ async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxA
|
|
|
25621
26387
|
maxRecords,
|
|
25622
26388
|
analysis.plainGroupByPlans,
|
|
25623
26389
|
true,
|
|
25624
|
-
fetchCollector
|
|
26390
|
+
fetchCollector,
|
|
26391
|
+
"main",
|
|
26392
|
+
recursiveLimits
|
|
25625
26393
|
),
|
|
25626
26394
|
cursorMaxActive
|
|
25627
26395
|
)
|
|
@@ -25653,7 +26421,7 @@ function addCursorConcurrency(lines, cursorMaxActive) {
|
|
|
25653
26421
|
}
|
|
25654
26422
|
return result;
|
|
25655
26423
|
}
|
|
25656
|
-
function buildExplainPlan(query, label, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, maxRecords = 1e4, plainGroupByPlans, includeFetchSummary = true, collector, sourceRole = "main") {
|
|
26424
|
+
function buildExplainPlan(query, label, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, maxRecords = 1e4, plainGroupByPlans, includeFetchSummary = true, collector, sourceRole = "main", recursiveLimits = resolveRecursiveCteLimits({})) {
|
|
25657
26425
|
const fetchCollector = collector ?? { sources: [] };
|
|
25658
26426
|
if (query.type === "UNION") {
|
|
25659
26427
|
const lines2 = buildUnionPlan(
|
|
@@ -25671,7 +26439,9 @@ function buildExplainPlan(query, label, capabilities, orderPlans, dmlMaxRows = 1
|
|
|
25671
26439
|
capabilities,
|
|
25672
26440
|
orderPlans,
|
|
25673
26441
|
plainGroupByPlans,
|
|
25674
|
-
fetchCollector
|
|
26442
|
+
fetchCollector,
|
|
26443
|
+
maxRecords,
|
|
26444
|
+
recursiveLimits
|
|
25675
26445
|
);
|
|
25676
26446
|
return includeFetchSummary ? addFetchSummary(lines2, fetchCollector.sources) : lines2;
|
|
25677
26447
|
}
|
|
@@ -26268,11 +27038,30 @@ function populateWithCrossJoinExplain(stmt) {
|
|
|
26268
27038
|
}
|
|
26269
27039
|
analyzeQuery(stmt.query);
|
|
26270
27040
|
}
|
|
26271
|
-
function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }) {
|
|
27041
|
+
function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }, maxRecords = 1e4, recursiveLimits = resolveRecursiveCteLimits({})) {
|
|
26272
27042
|
populateWithCrossJoinExplain(stmt);
|
|
26273
27043
|
const lines = [];
|
|
26274
27044
|
for (const cte of stmt.ctes) {
|
|
26275
|
-
if (cte.
|
|
27045
|
+
if (cte.recursiveSpec) {
|
|
27046
|
+
const cycle = cte.recursiveSpec.cycle;
|
|
27047
|
+
lines.push(
|
|
27048
|
+
`recursive cte: ${cte.name}`,
|
|
27049
|
+
" strategy: B (materialize each source once, iterate in memory)",
|
|
27050
|
+
" union: UNION ALL",
|
|
27051
|
+
" self reference: once",
|
|
27052
|
+
cycle ? ` cycle: path-scoped on ${cycle.column}, mark ${cycle.markColumn} ('${cycle.markValue}'/'${cycle.defaultValue}'), cycle row emitted, expansion stopped` : " cycle: none (absolute limits still enforced)",
|
|
27053
|
+
` limits: depth=${recursiveLimits.depth}, rows=${recursiveLimits.rows}, expansions=${recursiveLimits.expansions} (always fail-closed)`,
|
|
27054
|
+
" complete input: required (onLimit=truncate disabled)",
|
|
27055
|
+
" empty-key recursive join: runtime checked"
|
|
27056
|
+
);
|
|
27057
|
+
for (const source of recursivePhysicalTables(cte.recursiveSpec.seed, cte.recursiveSpec.recursiveTerm)) {
|
|
27058
|
+
const sourceName = `APP${source.appId}${source.subtableCode ? `$${source.subtableCode}` : ""}`;
|
|
27059
|
+
lines.push(
|
|
27060
|
+
` source ${sourceName}: R unknown, pageSize=500, estimated calls=ceil(R/500), maxRecords=${maxRecords}`
|
|
27061
|
+
);
|
|
27062
|
+
}
|
|
27063
|
+
lines.push(" iteration rows: unknown until execution", " records API: none", "");
|
|
27064
|
+
} else if (cte.query.type === "SELECT") {
|
|
26276
27065
|
lines.push(...buildSelectPlan(
|
|
26277
27066
|
cte.query,
|
|
26278
27067
|
`[cte: ${cte.name}]`,
|
|
@@ -26338,10 +27127,12 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collec
|
|
|
26338
27127
|
orderPlans,
|
|
26339
27128
|
100,
|
|
26340
27129
|
DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
26341
|
-
|
|
27130
|
+
maxRecords,
|
|
26342
27131
|
plainGroupByPlans,
|
|
26343
27132
|
false,
|
|
26344
|
-
collector
|
|
27133
|
+
collector,
|
|
27134
|
+
"main",
|
|
27135
|
+
recursiveLimits
|
|
26345
27136
|
));
|
|
26346
27137
|
}
|
|
26347
27138
|
if (canInlineSingleCte(stmt)) {
|
|
@@ -28693,6 +29484,16 @@ Options:
|
|
|
28693
29484
|
-h, --help Show help
|
|
28694
29485
|
-v, --version Show version
|
|
28695
29486
|
`;
|
|
29487
|
+
var RECURSIVE_CTE_HELP_LINES = [
|
|
29488
|
+
" --recursive-cte-max-depth <n> Max recursive CTE depth (default: 100)",
|
|
29489
|
+
" --recursive-cte-max-rows <n> Max accumulated recursive CTE rows (default: 10000)",
|
|
29490
|
+
" --recursive-cte-max-expansions <n> Max recursive CTE candidate expansions (default: 100000)"
|
|
29491
|
+
].join("\n");
|
|
29492
|
+
var CLI_HELP_TEXT = HELP_TEXT.replace(
|
|
29493
|
+
" --max-records <n> Max records to fetch (default: 500)",
|
|
29494
|
+
` --max-records <n> Max records to fetch (default: 500)
|
|
29495
|
+
${RECURSIVE_CTE_HELP_LINES}`
|
|
29496
|
+
);
|
|
28696
29497
|
var CLI_IMPORT_SOURCE_REQUIRED_MESSAGE = "IMPORT \u306B\u306F\u30BD\u30FC\u30B9\u304C\u5FC5\u8981\u3067\u3059\u3002--import-csv <name=path> \u307E\u305F\u306F --import-json <name=path> \u3067\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
|
|
28697
29498
|
function toCliImportError(error, importEnabled) {
|
|
28698
29499
|
if (importEnabled || !isImportCapabilityGateError(error)) return error;
|
|
@@ -28712,6 +29513,9 @@ function parseArgs(argv) {
|
|
|
28712
29513
|
dryRun: false,
|
|
28713
29514
|
format: null,
|
|
28714
29515
|
maxRecords: null,
|
|
29516
|
+
recursiveCteMaxDepth: null,
|
|
29517
|
+
recursiveCteMaxRows: null,
|
|
29518
|
+
recursiveCteMaxExpansions: null,
|
|
28715
29519
|
fetchParallel: null,
|
|
28716
29520
|
onLimit: null,
|
|
28717
29521
|
tempTableMaxRows: null,
|
|
@@ -28978,6 +29782,17 @@ function parseArgs(argv) {
|
|
|
28978
29782
|
i++;
|
|
28979
29783
|
continue;
|
|
28980
29784
|
}
|
|
29785
|
+
if (a === "--recursive-cte-max-depth" || a === "--recursive-cte-max-rows" || a === "--recursive-cte-max-expansions") {
|
|
29786
|
+
const n = Number(v);
|
|
29787
|
+
if (!Number.isSafeInteger(n) || n <= 0) {
|
|
29788
|
+
throw new Error(`ArgumentError: ${a} must be a positive safe integer.`);
|
|
29789
|
+
}
|
|
29790
|
+
if (a === "--recursive-cte-max-depth") out.recursiveCteMaxDepth = n;
|
|
29791
|
+
else if (a === "--recursive-cte-max-rows") out.recursiveCteMaxRows = n;
|
|
29792
|
+
else out.recursiveCteMaxExpansions = n;
|
|
29793
|
+
i++;
|
|
29794
|
+
continue;
|
|
29795
|
+
}
|
|
28981
29796
|
if (a === "--temp-table-max-rows") {
|
|
28982
29797
|
const n = Number(v);
|
|
28983
29798
|
if (!Number.isInteger(n) || n <= 0) throw new Error("ArgumentError: --temp-table-max-rows must be a positive integer.");
|
|
@@ -29606,6 +30421,9 @@ function buildReplExecArgv(base, sql, dryRun, format) {
|
|
|
29606
30421
|
pushOpt(argv, "--token-file", base.tokenFile);
|
|
29607
30422
|
pushOpt(argv, "--app", base.app);
|
|
29608
30423
|
pushOpt(argv, "--max-records", base.maxRecords);
|
|
30424
|
+
pushOpt(argv, "--recursive-cte-max-depth", base.recursiveCteMaxDepth);
|
|
30425
|
+
pushOpt(argv, "--recursive-cte-max-rows", base.recursiveCteMaxRows);
|
|
30426
|
+
pushOpt(argv, "--recursive-cte-max-expansions", base.recursiveCteMaxExpansions);
|
|
29609
30427
|
pushOpt(argv, "--fetch-parallel", base.fetchParallel);
|
|
29610
30428
|
pushOpt(argv, "--on-limit", base.onLimit);
|
|
29611
30429
|
pushOpt(argv, "--temp-table-max-rows", base.tempTableMaxRows);
|
|
@@ -30086,7 +30904,7 @@ async function run() {
|
|
|
30086
30904
|
return 2;
|
|
30087
30905
|
}
|
|
30088
30906
|
if (args.help) {
|
|
30089
|
-
process.stdout.write(`${
|
|
30907
|
+
process.stdout.write(`${CLI_HELP_TEXT}
|
|
30090
30908
|
`);
|
|
30091
30909
|
return 0;
|
|
30092
30910
|
}
|
|
@@ -30204,6 +31022,20 @@ async function run() {
|
|
|
30204
31022
|
}
|
|
30205
31023
|
}
|
|
30206
31024
|
const maxRecords = args.maxRecords ?? envInt2("KSQL_MAX_RECORDS") ?? profile.query?.maxRecords ?? 500;
|
|
31025
|
+
const recursiveCteMaxDepth = args.recursiveCteMaxDepth ?? envInt2("KSQL_RECURSIVE_CTE_MAX_DEPTH") ?? profile.query?.recursiveCteMaxDepth ?? 100;
|
|
31026
|
+
const recursiveCteMaxRows = args.recursiveCteMaxRows ?? envInt2("KSQL_RECURSIVE_CTE_MAX_ROWS") ?? profile.query?.recursiveCteMaxRows ?? 1e4;
|
|
31027
|
+
const recursiveCteMaxExpansions = args.recursiveCteMaxExpansions ?? envInt2("KSQL_RECURSIVE_CTE_MAX_EXPANSIONS") ?? profile.query?.recursiveCteMaxExpansions ?? 1e5;
|
|
31028
|
+
for (const [name, value] of [
|
|
31029
|
+
["recursiveCteMaxDepth", recursiveCteMaxDepth],
|
|
31030
|
+
["recursiveCteMaxRows", recursiveCteMaxRows],
|
|
31031
|
+
["recursiveCteMaxExpansions", recursiveCteMaxExpansions]
|
|
31032
|
+
]) {
|
|
31033
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
31034
|
+
process.stderr.write(`ArgumentError: ${name} must be a positive safe integer.
|
|
31035
|
+
`);
|
|
31036
|
+
return 2;
|
|
31037
|
+
}
|
|
31038
|
+
}
|
|
30207
31039
|
const fetchParallel = args.fetchParallel ?? envInt2("KSQL_FETCH_PARALLEL") ?? profile.query?.fetchParallel ?? 3;
|
|
30208
31040
|
const onLimit = args.onLimit ?? envOnLimit2("KSQL_ON_LIMIT") ?? profile.query?.onLimit ?? "error";
|
|
30209
31041
|
const timeout = args.timeout ?? envInt2("KSQL_TIMEOUT") ?? profile.query?.timeout ?? 3e4;
|
|
@@ -30560,7 +31392,10 @@ async function run() {
|
|
|
30560
31392
|
Object.keys(args.importCsv).length > 0 || Object.keys(args.importJson).length > 0,
|
|
30561
31393
|
dmlMaxRows,
|
|
30562
31394
|
dmlMaxSubtableRows,
|
|
30563
|
-
!dryRunUsesStaticTypedPlan
|
|
31395
|
+
!dryRunUsesStaticTypedPlan,
|
|
31396
|
+
recursiveCteMaxDepth,
|
|
31397
|
+
recursiveCteMaxRows,
|
|
31398
|
+
recursiveCteMaxExpansions
|
|
30564
31399
|
);
|
|
30565
31400
|
const out = [];
|
|
30566
31401
|
const restoredStatements = sqlDiagnosticContext ? restoreSqlDiagnosticValue(plans.statements, sqlDiagnosticContext.appBindingByMappedApp) : plans.statements;
|
|
@@ -30650,6 +31485,9 @@ query=${label}`);
|
|
|
30650
31485
|
tempTableMaxRows,
|
|
30651
31486
|
timeoutMs: timeout,
|
|
30652
31487
|
cursorMaxActive,
|
|
31488
|
+
recursiveCteMaxDepth,
|
|
31489
|
+
recursiveCteMaxRows,
|
|
31490
|
+
recursiveCteMaxExpansions,
|
|
30653
31491
|
variables: args.variables,
|
|
30654
31492
|
enableImport: importEnabled,
|
|
30655
31493
|
importSource,
|
|
@@ -30701,7 +31539,10 @@ query=${label}`);
|
|
|
30701
31539
|
enableImport: importEnabled,
|
|
30702
31540
|
importSource,
|
|
30703
31541
|
dmlMaxRows,
|
|
30704
|
-
dmlMaxSubtableRows
|
|
31542
|
+
dmlMaxSubtableRows,
|
|
31543
|
+
recursiveCteMaxDepth,
|
|
31544
|
+
recursiveCteMaxRows,
|
|
31545
|
+
recursiveCteMaxExpansions
|
|
30705
31546
|
}) : await execute(sql, client, {
|
|
30706
31547
|
maxRecords,
|
|
30707
31548
|
fetchParallel,
|
|
@@ -30709,6 +31550,9 @@ query=${label}`);
|
|
|
30709
31550
|
confirm: isDmlStatement ? confirm : void 0,
|
|
30710
31551
|
cacheContext,
|
|
30711
31552
|
cursorMaxActive,
|
|
31553
|
+
recursiveCteMaxDepth,
|
|
31554
|
+
recursiveCteMaxRows,
|
|
31555
|
+
recursiveCteMaxExpansions,
|
|
30712
31556
|
enableImport: importEnabled,
|
|
30713
31557
|
importSource,
|
|
30714
31558
|
supportsImportConfirmDetail: true,
|
|
@@ -30792,6 +31636,7 @@ if (isDirectCliRun()) {
|
|
|
30792
31636
|
}
|
|
30793
31637
|
// Annotate the CommonJS export names for ESM import in node:
|
|
30794
31638
|
0 && (module.exports = {
|
|
31639
|
+
CLI_HELP_TEXT,
|
|
30795
31640
|
CLI_IMPORT_SOURCE_REQUIRED_MESSAGE,
|
|
30796
31641
|
HELP_TEXT,
|
|
30797
31642
|
buildBatchDmlConfirmMessage,
|