@rex0220/kintone-sql-tools 3.65.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 +899 -105
- 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 +25 -12
- package/dist-engine/meta/esm.json +25 -12
- package/dist-engine/meta/umd.json +25 -12
- package/dist-engine/publicTypes.d.ts +6 -0
- package/dist-mcp/ksql-mcp.js +912 -117
- 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();
|
|
@@ -12804,6 +12958,71 @@ function isOuterJoinNonPreservedTable(statement, table, isMainTable) {
|
|
|
12804
12958
|
return false;
|
|
12805
12959
|
}
|
|
12806
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
|
+
|
|
12807
13026
|
// src/core/optimization/joinKeyPrefilter.ts
|
|
12808
13027
|
var JOIN_KEY_IN_CHUNK_SIZE = 50;
|
|
12809
13028
|
function buildJoinKeyPrefilterQueries(plan, field, quoteValue) {
|
|
@@ -14245,8 +14464,15 @@ function applyJoin(leftRows, rightRows, join2, columns = {}) {
|
|
|
14245
14464
|
return result2;
|
|
14246
14465
|
}
|
|
14247
14466
|
const { on, type: joinType } = join2;
|
|
14248
|
-
const
|
|
14249
|
-
|
|
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);
|
|
14250
14476
|
assertJoinKeyAvailable(leftRows, leftKey, columns.leftColumns);
|
|
14251
14477
|
assertJoinKeyAvailable(rightRows, rightKey, columns.rightColumns);
|
|
14252
14478
|
if (joinType === "RIGHT") {
|
|
@@ -14294,6 +14520,37 @@ function applyJoin(leftRows, rightRows, join2, columns = {}) {
|
|
|
14294
14520
|
}
|
|
14295
14521
|
return result;
|
|
14296
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
|
+
}
|
|
14297
14554
|
function assertJoinKeyAvailable(rows, key, savedColumns) {
|
|
14298
14555
|
const missing = rows.length > 0 ? rows.some((row) => !Object.prototype.hasOwnProperty.call(row, key)) : savedColumns !== void 0 && !savedColumns.includes(key);
|
|
14299
14556
|
if (missing) {
|
|
@@ -17331,6 +17588,7 @@ function createInvocationCacheContext(cacheContext) {
|
|
|
17331
17588
|
return `${cacheContext}\0inv:${nextCacheInvocationId++}`;
|
|
17332
17589
|
}
|
|
17333
17590
|
async function execute(sql, client, options = {}) {
|
|
17591
|
+
resolveRecursiveCteLimits(options);
|
|
17334
17592
|
const startedAt = Date.now();
|
|
17335
17593
|
const cacheContext = createInvocationCacheContext(
|
|
17336
17594
|
resolveCacheContext(client, options.cacheContext)
|
|
@@ -17642,7 +17900,10 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
17642
17900
|
options.cursorMaxActive ?? 2,
|
|
17643
17901
|
stmt.query.type === "UPDATE" && stmt.query.applyBlocks?.length ? resolveApplyGuardLimit(options.dmlMaxRows, "dmlMaxRows", DEFAULT_APPLY_MAX_ROWS) : DEFAULT_APPLY_MAX_ROWS,
|
|
17644
17902
|
stmt.query.type === "UPDATE" && stmt.query.applyBlocks?.length ? resolveApplyGuardLimit(options.dmlMaxSubtableRows, "dmlMaxSubtableRows", DEFAULT_APPLY_MAX_SUBTABLE_ROWS) : DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
17645
|
-
relativeDatePlan
|
|
17903
|
+
relativeDatePlan,
|
|
17904
|
+
options.recursiveCteMaxDepth,
|
|
17905
|
+
options.recursiveCteMaxRows,
|
|
17906
|
+
options.recursiveCteMaxExpansions
|
|
17646
17907
|
);
|
|
17647
17908
|
// 一時テーブルはバッチスコープのため単文実行では拒否する(executeBatch を使う)
|
|
17648
17909
|
case "CREATE_TEMP_TABLE":
|
|
@@ -17914,6 +18175,7 @@ var BatchTimeoutError = class extends Error {
|
|
|
17914
18175
|
}
|
|
17915
18176
|
};
|
|
17916
18177
|
async function executeBatch(sql, client, options = {}) {
|
|
18178
|
+
resolveRecursiveCteLimits(options);
|
|
17917
18179
|
const statements = parseSqlBatch(sql, options.enableImport === true);
|
|
17918
18180
|
const analysis = analyzeBatch(statements);
|
|
17919
18181
|
statements.forEach((statement) => assertApplyExecutionScope("phase15b", statement));
|
|
@@ -18740,7 +19002,7 @@ function canProveTotalWindowOrder(stmt, orderBy, resolveField2, context, generat
|
|
|
18740
19002
|
}
|
|
18741
19003
|
function tieBreakAdvice(context, kind) {
|
|
18742
19004
|
if (context !== "DIRECT") {
|
|
18743
|
-
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";
|
|
18744
19006
|
}
|
|
18745
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";
|
|
18746
19008
|
}
|
|
@@ -20629,6 +20891,53 @@ function assertUnionColumnCount(leftColumns, rightColumns) {
|
|
|
20629
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`
|
|
20630
20892
|
);
|
|
20631
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
|
+
}
|
|
20632
20941
|
async function executeUnion(stmt, client, options, cacheContext, captureColumnMeta = false, forLibraryCapture = false) {
|
|
20633
20942
|
const completePolicy = buildCompleteInputPolicy(stmt, options, null);
|
|
20634
20943
|
return withCompleteInputPolicy(completePolicy, async () => {
|
|
@@ -20662,33 +20971,7 @@ async function executeUnion(stmt, client, options, cacheContext, captureColumnMe
|
|
|
20662
20971
|
"DERIVED"
|
|
20663
20972
|
)
|
|
20664
20973
|
]);
|
|
20665
|
-
|
|
20666
|
-
const rightCols = rightResult.columns;
|
|
20667
|
-
assertUnionColumnCount(leftCols, rightCols);
|
|
20668
|
-
const remappedRight = rightResult.rows.map((row) => {
|
|
20669
|
-
const mapped = {};
|
|
20670
|
-
leftCols.forEach((col, i) => {
|
|
20671
|
-
mapped[col] = row[rightCols[i] ?? col] ?? "";
|
|
20672
|
-
});
|
|
20673
|
-
return mapped;
|
|
20674
|
-
});
|
|
20675
|
-
const combined = [...leftResult.rows, ...remappedRight];
|
|
20676
|
-
const rows = stmt.all ? combined : deduplicateRows(combined, leftCols);
|
|
20677
|
-
const warnings = [.../* @__PURE__ */ new Set([
|
|
20678
|
-
...leftResult.warnings ?? [],
|
|
20679
|
-
...rightResult.warnings ?? []
|
|
20680
|
-
])];
|
|
20681
|
-
const result = {
|
|
20682
|
-
type: "SELECT",
|
|
20683
|
-
rows,
|
|
20684
|
-
columns: leftCols,
|
|
20685
|
-
rowCount: rows.length,
|
|
20686
|
-
warnings
|
|
20687
|
-
};
|
|
20688
|
-
if (captureColumnMeta) {
|
|
20689
|
-
materializedMetaBySelectResult.set(result, mergeUnionColumnMeta(leftResult, rightResult));
|
|
20690
|
-
}
|
|
20691
|
-
return result;
|
|
20974
|
+
return combineUnionResults(leftResult, rightResult, stmt.all, captureColumnMeta);
|
|
20692
20975
|
});
|
|
20693
20976
|
}
|
|
20694
20977
|
function deduplicateRows(rows, columns) {
|
|
@@ -20700,6 +20983,442 @@ function deduplicateRows(rows, columns) {
|
|
|
20700
20983
|
return true;
|
|
20701
20984
|
});
|
|
20702
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
|
+
}
|
|
20703
21422
|
async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
|
|
20704
21423
|
if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
|
|
20705
21424
|
return executeSelect(
|
|
@@ -20717,7 +21436,9 @@ async function executeWith(stmt, client, options, cacheContext, seed, captureCol
|
|
|
20717
21436
|
const warnings = /* @__PURE__ */ new Set();
|
|
20718
21437
|
for (const cte of stmt.ctes) {
|
|
20719
21438
|
let result2;
|
|
20720
|
-
if (cte.
|
|
21439
|
+
if (cte.recursiveSpec) {
|
|
21440
|
+
result2 = await executeRecursiveCte(cte, client, options, cteCache, cacheContext);
|
|
21441
|
+
} else if (cte.query.type === "SHOW_APPS") {
|
|
20721
21442
|
result2 = await executeShowApps(client);
|
|
20722
21443
|
} else if (cte.query.type === "DESCRIBE") {
|
|
20723
21444
|
result2 = await executeDescribe(cte.query, client, cacheContext);
|
|
@@ -20774,33 +21495,7 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
|
|
|
20774
21495
|
executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta, true),
|
|
20775
21496
|
executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta, true)
|
|
20776
21497
|
]);
|
|
20777
|
-
|
|
20778
|
-
const rightCols = rightResult.columns;
|
|
20779
|
-
assertUnionColumnCount(leftCols, rightCols);
|
|
20780
|
-
const remapped = rightResult.rows.map((row) => {
|
|
20781
|
-
const mapped = {};
|
|
20782
|
-
leftCols.forEach((col, i) => {
|
|
20783
|
-
mapped[col] = row[rightCols[i] ?? col] ?? "";
|
|
20784
|
-
});
|
|
20785
|
-
return mapped;
|
|
20786
|
-
});
|
|
20787
|
-
const combined = [...leftResult.rows, ...remapped];
|
|
20788
|
-
const rows = query.all ? combined : deduplicateRows(combined, leftCols);
|
|
20789
|
-
const warnings = [.../* @__PURE__ */ new Set([
|
|
20790
|
-
...leftResult.warnings ?? [],
|
|
20791
|
-
...rightResult.warnings ?? []
|
|
20792
|
-
])];
|
|
20793
|
-
const result2 = {
|
|
20794
|
-
type: "SELECT",
|
|
20795
|
-
rows,
|
|
20796
|
-
columns: leftCols,
|
|
20797
|
-
rowCount: rows.length,
|
|
20798
|
-
warnings
|
|
20799
|
-
};
|
|
20800
|
-
if (captureColumnMeta) {
|
|
20801
|
-
materializedMetaBySelectResult.set(result2, mergeUnionColumnMeta(leftResult, rightResult));
|
|
20802
|
-
}
|
|
20803
|
-
return result2;
|
|
21498
|
+
return combineUnionResults(leftResult, rightResult, query.all, captureColumnMeta);
|
|
20804
21499
|
}
|
|
20805
21500
|
const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
|
|
20806
21501
|
if (!hasCteRef) {
|
|
@@ -25337,7 +26032,12 @@ var EXPLAIN_FETCH_PLAN = /* @__PURE__ */ Symbol("ksql.explainFetchPlan");
|
|
|
25337
26032
|
function setExplainFetchPlan(result, plan) {
|
|
25338
26033
|
result[EXPLAIN_FETCH_PLAN] = plan;
|
|
25339
26034
|
}
|
|
25340
|
-
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
|
+
});
|
|
25341
26041
|
const invocationCacheContext = createInvocationCacheContext(cacheContext);
|
|
25342
26042
|
try {
|
|
25343
26043
|
const statements = parseSqlBatch(sql, enableImport);
|
|
@@ -25416,7 +26116,8 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
25416
26116
|
dmlMaxSubtableRows,
|
|
25417
26117
|
fetchCollector,
|
|
25418
26118
|
tempSchemaLedger,
|
|
25419
|
-
createdSchema
|
|
26119
|
+
createdSchema,
|
|
26120
|
+
{ maxRecords, recursiveLimits }
|
|
25420
26121
|
), cursorMaxActive)
|
|
25421
26122
|
];
|
|
25422
26123
|
const metadataPlan = explainMetadataLines(whereAnalysis);
|
|
@@ -25448,7 +26149,7 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
25448
26149
|
releaseMetadataCacheScope(invocationCacheContext);
|
|
25449
26150
|
}
|
|
25450
26151
|
}
|
|
25451
|
-
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()) {
|
|
25452
26153
|
if (stmt.type === "CREATE_TEMP_TABLE") {
|
|
25453
26154
|
return [
|
|
25454
26155
|
`CREATE TEMP TABLE ${stmt.name}`,
|
|
@@ -25469,7 +26170,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25469
26170
|
plainGroupByPlans,
|
|
25470
26171
|
collector,
|
|
25471
26172
|
"main",
|
|
25472
|
-
tempSchemaLedger
|
|
26173
|
+
tempSchemaLedger,
|
|
26174
|
+
explainContext
|
|
25473
26175
|
).map((l) => ` ${l}`)
|
|
25474
26176
|
];
|
|
25475
26177
|
}
|
|
@@ -25494,7 +26196,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25494
26196
|
plainGroupByPlans,
|
|
25495
26197
|
collector,
|
|
25496
26198
|
"main",
|
|
25497
|
-
tempSchemaLedger
|
|
26199
|
+
tempSchemaLedger,
|
|
26200
|
+
explainContext
|
|
25498
26201
|
).map((l) => ` ${l}`)
|
|
25499
26202
|
];
|
|
25500
26203
|
}
|
|
@@ -25526,7 +26229,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25526
26229
|
plainGroupByPlans,
|
|
25527
26230
|
collector,
|
|
25528
26231
|
"main",
|
|
25529
|
-
tempSchemaLedger
|
|
26232
|
+
tempSchemaLedger,
|
|
26233
|
+
explainContext
|
|
25530
26234
|
);
|
|
25531
26235
|
}
|
|
25532
26236
|
if (stmt.type === "ASSERT") {
|
|
@@ -25548,7 +26252,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25548
26252
|
plainGroupByPlans,
|
|
25549
26253
|
collector,
|
|
25550
26254
|
"main",
|
|
25551
|
-
tempSchemaLedger
|
|
26255
|
+
tempSchemaLedger,
|
|
26256
|
+
explainContext
|
|
25552
26257
|
).map((l) => ` ${l}`));
|
|
25553
26258
|
});
|
|
25554
26259
|
return lines;
|
|
@@ -25573,7 +26278,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
25573
26278
|
plainGroupByPlans,
|
|
25574
26279
|
collector,
|
|
25575
26280
|
"main",
|
|
25576
|
-
tempSchemaLedger
|
|
26281
|
+
tempSchemaLedger,
|
|
26282
|
+
explainContext
|
|
25577
26283
|
);
|
|
25578
26284
|
}
|
|
25579
26285
|
function hasTempTableRef(node) {
|
|
@@ -25586,7 +26292,7 @@ function hasTempTableRef(node) {
|
|
|
25586
26292
|
}
|
|
25587
26293
|
return false;
|
|
25588
26294
|
}
|
|
25589
|
-
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()) {
|
|
25590
26296
|
if (info.tempTablesReferenced.length === 0) {
|
|
25591
26297
|
return buildExplainPlan(
|
|
25592
26298
|
query,
|
|
@@ -25595,11 +26301,12 @@ function buildPlanForBatchQuery(query, info, capabilities, orderPlans, plainGrou
|
|
|
25595
26301
|
orderPlans,
|
|
25596
26302
|
100,
|
|
25597
26303
|
DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
25598
|
-
|
|
26304
|
+
explainContext.maxRecords,
|
|
25599
26305
|
plainGroupByPlans,
|
|
25600
26306
|
true,
|
|
25601
26307
|
collector,
|
|
25602
|
-
sourceRole
|
|
26308
|
+
sourceRole,
|
|
26309
|
+
explainContext.recursiveLimits
|
|
25603
26310
|
);
|
|
25604
26311
|
}
|
|
25605
26312
|
const lines = [];
|
|
@@ -25646,7 +26353,15 @@ function buildPlanForBatchQuery(query, info, capabilities, orderPlans, plainGrou
|
|
|
25646
26353
|
return lines;
|
|
25647
26354
|
}
|
|
25648
26355
|
var explainMaterializedTables = /* @__PURE__ */ new WeakMap();
|
|
25649
|
-
|
|
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
|
+
});
|
|
25650
26365
|
const sharedPlan = relativeDatePlan ?? await resolveRelativeDateExecutionPlan(stmt.query, client, cacheContext);
|
|
25651
26366
|
const analysis = await buildExplainWhereAnalysis(
|
|
25652
26367
|
stmt.query,
|
|
@@ -25672,7 +26387,9 @@ async function executeExplain(stmt, client, cacheContext, maxRecords, cursorMaxA
|
|
|
25672
26387
|
maxRecords,
|
|
25673
26388
|
analysis.plainGroupByPlans,
|
|
25674
26389
|
true,
|
|
25675
|
-
fetchCollector
|
|
26390
|
+
fetchCollector,
|
|
26391
|
+
"main",
|
|
26392
|
+
recursiveLimits
|
|
25676
26393
|
),
|
|
25677
26394
|
cursorMaxActive
|
|
25678
26395
|
)
|
|
@@ -25704,7 +26421,7 @@ function addCursorConcurrency(lines, cursorMaxActive) {
|
|
|
25704
26421
|
}
|
|
25705
26422
|
return result;
|
|
25706
26423
|
}
|
|
25707
|
-
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({})) {
|
|
25708
26425
|
const fetchCollector = collector ?? { sources: [] };
|
|
25709
26426
|
if (query.type === "UNION") {
|
|
25710
26427
|
const lines2 = buildUnionPlan(
|
|
@@ -25722,7 +26439,9 @@ function buildExplainPlan(query, label, capabilities, orderPlans, dmlMaxRows = 1
|
|
|
25722
26439
|
capabilities,
|
|
25723
26440
|
orderPlans,
|
|
25724
26441
|
plainGroupByPlans,
|
|
25725
|
-
fetchCollector
|
|
26442
|
+
fetchCollector,
|
|
26443
|
+
maxRecords,
|
|
26444
|
+
recursiveLimits
|
|
25726
26445
|
);
|
|
25727
26446
|
return includeFetchSummary ? addFetchSummary(lines2, fetchCollector.sources) : lines2;
|
|
25728
26447
|
}
|
|
@@ -26319,11 +27038,30 @@ function populateWithCrossJoinExplain(stmt) {
|
|
|
26319
27038
|
}
|
|
26320
27039
|
analyzeQuery(stmt.query);
|
|
26321
27040
|
}
|
|
26322
|
-
function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }) {
|
|
27041
|
+
function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collector = { sources: [] }, maxRecords = 1e4, recursiveLimits = resolveRecursiveCteLimits({})) {
|
|
26323
27042
|
populateWithCrossJoinExplain(stmt);
|
|
26324
27043
|
const lines = [];
|
|
26325
27044
|
for (const cte of stmt.ctes) {
|
|
26326
|
-
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") {
|
|
26327
27065
|
lines.push(...buildSelectPlan(
|
|
26328
27066
|
cte.query,
|
|
26329
27067
|
`[cte: ${cte.name}]`,
|
|
@@ -26389,10 +27127,12 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collec
|
|
|
26389
27127
|
orderPlans,
|
|
26390
27128
|
100,
|
|
26391
27129
|
DEFAULT_APPLY_MAX_SUBTABLE_ROWS,
|
|
26392
|
-
|
|
27130
|
+
maxRecords,
|
|
26393
27131
|
plainGroupByPlans,
|
|
26394
27132
|
false,
|
|
26395
|
-
collector
|
|
27133
|
+
collector,
|
|
27134
|
+
"main",
|
|
27135
|
+
recursiveLimits
|
|
26396
27136
|
));
|
|
26397
27137
|
}
|
|
26398
27138
|
if (canInlineSingleCte(stmt)) {
|
|
@@ -28744,6 +29484,16 @@ Options:
|
|
|
28744
29484
|
-h, --help Show help
|
|
28745
29485
|
-v, --version Show version
|
|
28746
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
|
+
);
|
|
28747
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";
|
|
28748
29498
|
function toCliImportError(error, importEnabled) {
|
|
28749
29499
|
if (importEnabled || !isImportCapabilityGateError(error)) return error;
|
|
@@ -28763,6 +29513,9 @@ function parseArgs(argv) {
|
|
|
28763
29513
|
dryRun: false,
|
|
28764
29514
|
format: null,
|
|
28765
29515
|
maxRecords: null,
|
|
29516
|
+
recursiveCteMaxDepth: null,
|
|
29517
|
+
recursiveCteMaxRows: null,
|
|
29518
|
+
recursiveCteMaxExpansions: null,
|
|
28766
29519
|
fetchParallel: null,
|
|
28767
29520
|
onLimit: null,
|
|
28768
29521
|
tempTableMaxRows: null,
|
|
@@ -29029,6 +29782,17 @@ function parseArgs(argv) {
|
|
|
29029
29782
|
i++;
|
|
29030
29783
|
continue;
|
|
29031
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
|
+
}
|
|
29032
29796
|
if (a === "--temp-table-max-rows") {
|
|
29033
29797
|
const n = Number(v);
|
|
29034
29798
|
if (!Number.isInteger(n) || n <= 0) throw new Error("ArgumentError: --temp-table-max-rows must be a positive integer.");
|
|
@@ -29657,6 +30421,9 @@ function buildReplExecArgv(base, sql, dryRun, format) {
|
|
|
29657
30421
|
pushOpt(argv, "--token-file", base.tokenFile);
|
|
29658
30422
|
pushOpt(argv, "--app", base.app);
|
|
29659
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);
|
|
29660
30427
|
pushOpt(argv, "--fetch-parallel", base.fetchParallel);
|
|
29661
30428
|
pushOpt(argv, "--on-limit", base.onLimit);
|
|
29662
30429
|
pushOpt(argv, "--temp-table-max-rows", base.tempTableMaxRows);
|
|
@@ -30137,7 +30904,7 @@ async function run() {
|
|
|
30137
30904
|
return 2;
|
|
30138
30905
|
}
|
|
30139
30906
|
if (args.help) {
|
|
30140
|
-
process.stdout.write(`${
|
|
30907
|
+
process.stdout.write(`${CLI_HELP_TEXT}
|
|
30141
30908
|
`);
|
|
30142
30909
|
return 0;
|
|
30143
30910
|
}
|
|
@@ -30255,6 +31022,20 @@ async function run() {
|
|
|
30255
31022
|
}
|
|
30256
31023
|
}
|
|
30257
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
|
+
}
|
|
30258
31039
|
const fetchParallel = args.fetchParallel ?? envInt2("KSQL_FETCH_PARALLEL") ?? profile.query?.fetchParallel ?? 3;
|
|
30259
31040
|
const onLimit = args.onLimit ?? envOnLimit2("KSQL_ON_LIMIT") ?? profile.query?.onLimit ?? "error";
|
|
30260
31041
|
const timeout = args.timeout ?? envInt2("KSQL_TIMEOUT") ?? profile.query?.timeout ?? 3e4;
|
|
@@ -30611,7 +31392,10 @@ async function run() {
|
|
|
30611
31392
|
Object.keys(args.importCsv).length > 0 || Object.keys(args.importJson).length > 0,
|
|
30612
31393
|
dmlMaxRows,
|
|
30613
31394
|
dmlMaxSubtableRows,
|
|
30614
|
-
!dryRunUsesStaticTypedPlan
|
|
31395
|
+
!dryRunUsesStaticTypedPlan,
|
|
31396
|
+
recursiveCteMaxDepth,
|
|
31397
|
+
recursiveCteMaxRows,
|
|
31398
|
+
recursiveCteMaxExpansions
|
|
30615
31399
|
);
|
|
30616
31400
|
const out = [];
|
|
30617
31401
|
const restoredStatements = sqlDiagnosticContext ? restoreSqlDiagnosticValue(plans.statements, sqlDiagnosticContext.appBindingByMappedApp) : plans.statements;
|
|
@@ -30701,6 +31485,9 @@ query=${label}`);
|
|
|
30701
31485
|
tempTableMaxRows,
|
|
30702
31486
|
timeoutMs: timeout,
|
|
30703
31487
|
cursorMaxActive,
|
|
31488
|
+
recursiveCteMaxDepth,
|
|
31489
|
+
recursiveCteMaxRows,
|
|
31490
|
+
recursiveCteMaxExpansions,
|
|
30704
31491
|
variables: args.variables,
|
|
30705
31492
|
enableImport: importEnabled,
|
|
30706
31493
|
importSource,
|
|
@@ -30752,7 +31539,10 @@ query=${label}`);
|
|
|
30752
31539
|
enableImport: importEnabled,
|
|
30753
31540
|
importSource,
|
|
30754
31541
|
dmlMaxRows,
|
|
30755
|
-
dmlMaxSubtableRows
|
|
31542
|
+
dmlMaxSubtableRows,
|
|
31543
|
+
recursiveCteMaxDepth,
|
|
31544
|
+
recursiveCteMaxRows,
|
|
31545
|
+
recursiveCteMaxExpansions
|
|
30756
31546
|
}) : await execute(sql, client, {
|
|
30757
31547
|
maxRecords,
|
|
30758
31548
|
fetchParallel,
|
|
@@ -30760,6 +31550,9 @@ query=${label}`);
|
|
|
30760
31550
|
confirm: isDmlStatement ? confirm : void 0,
|
|
30761
31551
|
cacheContext,
|
|
30762
31552
|
cursorMaxActive,
|
|
31553
|
+
recursiveCteMaxDepth,
|
|
31554
|
+
recursiveCteMaxRows,
|
|
31555
|
+
recursiveCteMaxExpansions,
|
|
30763
31556
|
enableImport: importEnabled,
|
|
30764
31557
|
importSource,
|
|
30765
31558
|
supportsImportConfirmDetail: true,
|
|
@@ -30843,6 +31636,7 @@ if (isDirectCliRun()) {
|
|
|
30843
31636
|
}
|
|
30844
31637
|
// Annotate the CommonJS export names for ESM import in node:
|
|
30845
31638
|
0 && (module.exports = {
|
|
31639
|
+
CLI_HELP_TEXT,
|
|
30846
31640
|
CLI_IMPORT_SOURCE_REQUIRED_MESSAGE,
|
|
30847
31641
|
HELP_TEXT,
|
|
30848
31642
|
buildBatchDmlConfirmMessage,
|