@rex0220/kintone-sql-tools 3.58.0 → 3.60.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 +454 -60
- package/dist-engine/index.cjs +13 -13
- package/dist-engine/index.mjs +13 -13
- package/dist-engine/ksql-engine.umd.js +13 -13
- package/dist-engine/meta/bundle-baseline.json +10 -10
- package/dist-engine/meta/cjs.json +87 -21
- package/dist-engine/meta/esm.json +87 -21
- package/dist-engine/meta/umd.json +87 -21
- package/dist-mcp/ksql-mcp.js +472 -72
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -1169,6 +1169,12 @@ var Parser = class {
|
|
|
1169
1169
|
if (upper === "DROP") return this.parseDropTempTable();
|
|
1170
1170
|
if (upper === "DECLARE") return this.parseDeclareVariable();
|
|
1171
1171
|
if (upper === "VALIDATE") return this.parseValidate();
|
|
1172
|
+
if (upper === "GENERATE_SERIES") {
|
|
1173
|
+
throw new ParseError(
|
|
1174
|
+
"GENERATE_SERIES \u306F WITH \u306E CTE \u672C\u4F53\u306B\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\u3002\u4F8B: WITH s AS (GENERATE_SERIES(1, 5)) SELECT generate_series FROM s",
|
|
1175
|
+
tok
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1172
1178
|
if (upper === "IMPORT") {
|
|
1173
1179
|
if (!this.capabilities.import) {
|
|
1174
1180
|
throw new ParseError("IMPORT is not supported (capability is disabled).", tok);
|
|
@@ -1928,6 +1934,8 @@ var Parser = class {
|
|
|
1928
1934
|
query2 = this.parseShow();
|
|
1929
1935
|
} else if (inner === "DESCRIBE" /* DESCRIBE */ || inner === "DESC" /* DESC */) {
|
|
1930
1936
|
query2 = this.parseDescribe();
|
|
1937
|
+
} else if (inner === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === "GENERATE_SERIES") {
|
|
1938
|
+
query2 = this.parseGenerateSeries();
|
|
1931
1939
|
} else {
|
|
1932
1940
|
query2 = this.tryParseUnionChain(this.parseSelect());
|
|
1933
1941
|
}
|
|
@@ -1939,6 +1947,43 @@ var Parser = class {
|
|
|
1939
1947
|
this.cteNames.clear();
|
|
1940
1948
|
return { type: "WITH", ctes, query };
|
|
1941
1949
|
}
|
|
1950
|
+
parseGenerateSeries() {
|
|
1951
|
+
const name = this.advance();
|
|
1952
|
+
if (name.kind !== "IDENT" /* IDENT */ || name.value.toUpperCase() !== "GENERATE_SERIES") {
|
|
1953
|
+
throw new ParseError("GENERATE_SERIES \u304C\u5FC5\u8981\u3067\u3059", name);
|
|
1954
|
+
}
|
|
1955
|
+
this.expect("(" /* LPAREN */);
|
|
1956
|
+
const args = [];
|
|
1957
|
+
if (this.peek().kind !== ")" /* RPAREN */) {
|
|
1958
|
+
do {
|
|
1959
|
+
const tok = this.peek();
|
|
1960
|
+
if (tok.kind === "STRING" /* STRING */) {
|
|
1961
|
+
this.advance();
|
|
1962
|
+
args.push({ type: "STRING", value: tok.value });
|
|
1963
|
+
continue;
|
|
1964
|
+
}
|
|
1965
|
+
if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
1966
|
+
this.advance();
|
|
1967
|
+
args.push({ type: "VARIABLE", name: tok.value.slice(1).toLowerCase() });
|
|
1968
|
+
continue;
|
|
1969
|
+
}
|
|
1970
|
+
let sign = "";
|
|
1971
|
+
if (tok.kind === "+" /* PLUS */ || tok.kind === "-" /* MINUS */) {
|
|
1972
|
+
sign = tok.kind === "-" /* MINUS */ ? "-" : "+";
|
|
1973
|
+
this.advance();
|
|
1974
|
+
}
|
|
1975
|
+
const number = this.peek();
|
|
1976
|
+
if (number.kind !== "NUMBER" /* NUMBER */) {
|
|
1977
|
+
throw new ParseError("GENERATE_SERIES \u306E\u5F15\u6570\u306B\u306F\u6570\u5024\u3001\u6587\u5B57\u5217\u3001\u307E\u305F\u306F\u30D0\u30C3\u30C1\u5909\u6570\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", number);
|
|
1978
|
+
}
|
|
1979
|
+
this.advance();
|
|
1980
|
+
args.push(makeNumberLiteral(`${sign}${number.value}`));
|
|
1981
|
+
} while (this.consume("," /* COMMA */));
|
|
1982
|
+
}
|
|
1983
|
+
this.expect(")" /* RPAREN */);
|
|
1984
|
+
const columnAlias = this.consume("AS" /* AS */) ? this.parseIdentifier() : "generate_series";
|
|
1985
|
+
return { type: "GENERATE_SERIES", args, columnAlias };
|
|
1986
|
+
}
|
|
1942
1987
|
// ----------------------------------------------------------
|
|
1943
1988
|
// UNION / UNION ALL チェーン
|
|
1944
1989
|
// ----------------------------------------------------------
|
|
@@ -2923,6 +2968,12 @@ var Parser = class {
|
|
|
2923
2968
|
// ----------------------------------------------------------
|
|
2924
2969
|
parseTableRef() {
|
|
2925
2970
|
const nameTok = this.peek();
|
|
2971
|
+
if (nameTok.kind === "IDENT" /* IDENT */ && nameTok.value.toUpperCase() === "GENERATE_SERIES" && this.peekAt(1).kind === "(" /* LPAREN */) {
|
|
2972
|
+
throw new ParseError(
|
|
2973
|
+
"GENERATE_SERIES \u306F WITH \u306E CTE \u672C\u4F53\u306B\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\u3002\u4F8B: WITH s AS (GENERATE_SERIES(1, 5)) SELECT generate_series FROM s",
|
|
2974
|
+
nameTok
|
|
2975
|
+
);
|
|
2976
|
+
}
|
|
2926
2977
|
const name = this.parseTableName();
|
|
2927
2978
|
if (nameTok.kind === "IDENT" /* IDENT */ && name.startsWith("#")) {
|
|
2928
2979
|
this.tempTableRefs.push(this.prev());
|
|
@@ -3136,7 +3187,7 @@ var Parser = class {
|
|
|
3136
3187
|
return { type: "BINARY", op: "KLIKE", left: field, right: pattern };
|
|
3137
3188
|
}
|
|
3138
3189
|
const op = this.parseCompareOp();
|
|
3139
|
-
const right = this.parseWhereSqlValue();
|
|
3190
|
+
const right = this.parseWhereSqlValue(op !== "LIKE");
|
|
3140
3191
|
return { type: "BINARY", op, left: field, right };
|
|
3141
3192
|
}
|
|
3142
3193
|
parseCompareOp() {
|
|
@@ -3259,8 +3310,13 @@ var Parser = class {
|
|
|
3259
3310
|
return { type: "FIELD", tableAlias: qi.tableAlias, field: qi.field };
|
|
3260
3311
|
}
|
|
3261
3312
|
// 右辺の値
|
|
3262
|
-
parseWhereSqlValue() {
|
|
3313
|
+
parseWhereSqlValue(allowUnaryPlusNumberLiteral = true) {
|
|
3263
3314
|
const tok = this.peek();
|
|
3315
|
+
if (allowUnaryPlusNumberLiteral && tok.kind === "+" /* PLUS */) {
|
|
3316
|
+
this.advance();
|
|
3317
|
+
const number = this.expect("NUMBER" /* NUMBER */, "\u5358\u9805 + \u306E\u76F4\u5F8C\u306B\u306F\u6570\u5024\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
3318
|
+
return makeNumberLiteral(`+${number.value}`);
|
|
3319
|
+
}
|
|
3264
3320
|
if (this.allowRelativeDateFunctions && tok.kind === "IDENT" /* IDENT */ && this.peekAt(1).kind === "(" /* LPAREN */ && isRelativeDateFunctionName(tok.value.toUpperCase())) {
|
|
3265
3321
|
return this.parseRelativeDateFunction();
|
|
3266
3322
|
}
|
|
@@ -4698,7 +4754,9 @@ function completeInputReasons(stmt) {
|
|
|
4698
4754
|
break;
|
|
4699
4755
|
case "WITH":
|
|
4700
4756
|
for (const cte of stmt.ctes) {
|
|
4701
|
-
|
|
4757
|
+
if (cte.query.type !== "GENERATE_SERIES") {
|
|
4758
|
+
addReasons(reasons, completeInputReasons(cte.query));
|
|
4759
|
+
}
|
|
4702
4760
|
}
|
|
4703
4761
|
addReasons(reasons, completeInputReasons(stmt.query));
|
|
4704
4762
|
break;
|
|
@@ -7649,11 +7707,231 @@ function assertStringFunctionArity(func, args) {
|
|
|
7649
7707
|
}
|
|
7650
7708
|
}
|
|
7651
7709
|
|
|
7710
|
+
// src/core/generateSeries.ts
|
|
7711
|
+
var GENERATE_SERIES_MAX_ROWS = 1e4;
|
|
7712
|
+
var argumentError = (message) => new Error(`ArgumentError: ${message}`);
|
|
7713
|
+
var isVariable = (arg) => arg.type === "VARIABLE";
|
|
7714
|
+
var isResolvedVariable = (arg) => arg?.type === "STRING" && arg.fromVariable === true;
|
|
7715
|
+
function literalValue(arg) {
|
|
7716
|
+
return arg.type === "NUMBER" ? Number(numberLiteralText(arg)) : arg.value;
|
|
7717
|
+
}
|
|
7718
|
+
function dateParts(value) {
|
|
7719
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
7720
|
+
if (!match) return null;
|
|
7721
|
+
const year = Number(match[1]);
|
|
7722
|
+
const month = Number(match[2]);
|
|
7723
|
+
const day = Number(match[3]);
|
|
7724
|
+
if (year < 1 || year > 9999 || month < 1 || month > 12 || day < 1 || day > 31) return null;
|
|
7725
|
+
const date = /* @__PURE__ */ new Date(0);
|
|
7726
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
7727
|
+
date.setUTCFullYear(year, month - 1, day);
|
|
7728
|
+
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day ? { year, month, day } : null;
|
|
7729
|
+
}
|
|
7730
|
+
function dateOrdinal(value) {
|
|
7731
|
+
const parts = dateParts(value);
|
|
7732
|
+
const date = /* @__PURE__ */ new Date(0);
|
|
7733
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
7734
|
+
date.setUTCFullYear(parts.year, parts.month - 1, parts.day);
|
|
7735
|
+
return Math.trunc(date.getTime() / 864e5);
|
|
7736
|
+
}
|
|
7737
|
+
function dateFromOrdinal(ordinal) {
|
|
7738
|
+
const date = new Date(ordinal * 864e5);
|
|
7739
|
+
const year = date.getUTCFullYear();
|
|
7740
|
+
if (year < 1 || year > 9999) {
|
|
7741
|
+
throw argumentError("GENERATE_SERIES \u306E\u65E5\u4ED8\u5F15\u6570\u306B\u306F\u5B9F\u5728\u3059\u308B YYYY-MM-DD \u5F62\u5F0F\u306E DATE \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7742
|
+
}
|
|
7743
|
+
return `${String(year).padStart(4, "0")}-${String(date.getUTCMonth() + 1).padStart(2, "0")}-${String(date.getUTCDate()).padStart(2, "0")}`;
|
|
7744
|
+
}
|
|
7745
|
+
function parseDateStep(value) {
|
|
7746
|
+
const trimmed = value.trim();
|
|
7747
|
+
const match = /^([+-]?\d+)\s+(day|days)$/i.exec(trimmed);
|
|
7748
|
+
if (!match) {
|
|
7749
|
+
if (/^[+-]?\d+\s+\S+$/i.test(trimmed)) {
|
|
7750
|
+
throw argumentError("GENERATE_SERIES \u306E\u65E5\u4ED8 step \u306F day \u307E\u305F\u306F days \u306E\u307F\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u3059\u3002");
|
|
7751
|
+
}
|
|
7752
|
+
throw argumentError("GENERATE_SERIES \u306E step \u304C\u7CFB\u5217\u306E\u578B\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002\u6574\u6570\u7CFB\u5217\u306B\u306F\u6574\u6570\u3001DATE \u7CFB\u5217\u306B\u306F day \u5358\u4F4D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7753
|
+
}
|
|
7754
|
+
const step = Number(match[1]);
|
|
7755
|
+
if (!Number.isSafeInteger(step)) {
|
|
7756
|
+
throw argumentError("GENERATE_SERIES \u306E\u6570\u5024\u7CFB\u5217\u306F\u6574\u6570\u306E start\u3001stop\u3001step \u306E\u307F\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7757
|
+
}
|
|
7758
|
+
if (step === 0) throw argumentError("GENERATE_SERIES \u306E\u65E5\u4ED8 step \u306B 0 day \u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002");
|
|
7759
|
+
return step;
|
|
7760
|
+
}
|
|
7761
|
+
function integerValue(value) {
|
|
7762
|
+
if (typeof value === "number") return Number.isSafeInteger(value) ? value : null;
|
|
7763
|
+
if (!/^[+-]?\d+$/.test(value)) return null;
|
|
7764
|
+
const parsed = Number(value);
|
|
7765
|
+
return Number.isSafeInteger(parsed) ? parsed : null;
|
|
7766
|
+
}
|
|
7767
|
+
function integerNumberLiteral(arg) {
|
|
7768
|
+
const decimal = parseExactDecimal(arg.raw ?? String(arg.value));
|
|
7769
|
+
if (decimal === null || decimal.scale > 0) return null;
|
|
7770
|
+
if (decimal.sign === 0) return 0;
|
|
7771
|
+
const digits = decimal.coefficient.length - decimal.scale;
|
|
7772
|
+
if (digits > 16) return null;
|
|
7773
|
+
const magnitude = `${decimal.coefficient}${"0".repeat(-decimal.scale)}`;
|
|
7774
|
+
if (magnitude.length === 16 && magnitude > "9007199254740991") return null;
|
|
7775
|
+
const value = Number(magnitude) * decimal.sign;
|
|
7776
|
+
return Number.isSafeInteger(value) ? value : null;
|
|
7777
|
+
}
|
|
7778
|
+
function isUnsupportedTemporal(value) {
|
|
7779
|
+
return typeof value === "string" && (/^\d{4}-\d{2}-\d{2}T/.test(value) || /^\d{2}:\d{2}(?::\d{2})?$/.test(value));
|
|
7780
|
+
}
|
|
7781
|
+
function countRows(start, stop, step) {
|
|
7782
|
+
if (start === stop) return 1;
|
|
7783
|
+
if (start < stop && step < 0 || start > stop && step > 0) return 0;
|
|
7784
|
+
const distance = step > 0 ? BigInt(stop) - BigInt(start) : BigInt(start) - BigInt(stop);
|
|
7785
|
+
return Number(distance / BigInt(Math.abs(step)) + 1n);
|
|
7786
|
+
}
|
|
7787
|
+
function planResolved(stmt) {
|
|
7788
|
+
if (stmt.args.length < 2 || stmt.args.length > 3) {
|
|
7789
|
+
throw argumentError("GENERATE_SERIES \u306F start\u3001stop \u3068\u7701\u7565\u53EF\u80FD\u306A step \u306E2\u500B\u307E\u305F\u306F3\u500B\u306E\u5F15\u6570\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7790
|
+
}
|
|
7791
|
+
const values = stmt.args.map((arg) => literalValue(arg));
|
|
7792
|
+
["start", "stop", "step"].forEach((name, index) => {
|
|
7793
|
+
if (values[index] === "") throw argumentError(`GENERATE_SERIES \u306E ${name} \u306B\u7A7A\u6587\u5B57\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002`);
|
|
7794
|
+
});
|
|
7795
|
+
const [startRaw, stopRaw, stepRaw] = values;
|
|
7796
|
+
const [startArg, stopArg, stepArg] = stmt.args;
|
|
7797
|
+
const startDate = typeof startRaw === "string" ? dateParts(startRaw) : null;
|
|
7798
|
+
const stopDate = typeof stopRaw === "string" ? dateParts(stopRaw) : null;
|
|
7799
|
+
const dateLikeStart = typeof startRaw === "string" && /^\d{4}-/.test(startRaw);
|
|
7800
|
+
const dateLikeStop = typeof stopRaw === "string" && /^\d{4}-/.test(stopRaw);
|
|
7801
|
+
if ([startRaw, stopRaw].some(isUnsupportedTemporal)) {
|
|
7802
|
+
throw argumentError("GENERATE_SERIES \u306F Phase 1 \u3067\u306F\u6574\u6570\u3068 DATE \u306E\u307F\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u3059\u3002DATETIME \u3068 TIME \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002");
|
|
7803
|
+
}
|
|
7804
|
+
if (startDate || stopDate || dateLikeStart || dateLikeStop || typeof startRaw === "string" && typeof stopRaw === "string" && !(isResolvedVariable(startArg) && isResolvedVariable(stopArg) && integerValue(startRaw) !== null && integerValue(stopRaw) !== null)) {
|
|
7805
|
+
if (!startDate || !stopDate) {
|
|
7806
|
+
if (startDate && typeof stopRaw !== "string" || stopDate && typeof startRaw !== "string") {
|
|
7807
|
+
throw argumentError("GENERATE_SERIES \u306E start \u3068 stop \u306F\u3001\u4E21\u65B9\u3092\u6574\u6570\u307E\u305F\u306F\u4E21\u65B9\u3092 DATE \u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7808
|
+
}
|
|
7809
|
+
throw argumentError("GENERATE_SERIES \u306E\u65E5\u4ED8\u5F15\u6570\u306B\u306F\u5B9F\u5728\u3059\u308B YYYY-MM-DD \u5F62\u5F0F\u306E DATE \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7810
|
+
}
|
|
7811
|
+
if (stepRaw !== void 0 && typeof stepRaw !== "string") {
|
|
7812
|
+
throw argumentError("GENERATE_SERIES \u306E step \u304C\u7CFB\u5217\u306E\u578B\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002\u6574\u6570\u7CFB\u5217\u306B\u306F\u6574\u6570\u3001DATE \u7CFB\u5217\u306B\u306F day \u5358\u4F4D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7813
|
+
}
|
|
7814
|
+
const step2 = stepRaw === void 0 ? 1 : parseDateStep(stepRaw);
|
|
7815
|
+
const start2 = startRaw;
|
|
7816
|
+
const stop2 = stopRaw;
|
|
7817
|
+
return { kind: "DATE", start: start2, stop: stop2, step: step2, rowCount: countRows(dateOrdinal(start2), dateOrdinal(stop2), step2) };
|
|
7818
|
+
}
|
|
7819
|
+
const startInteger = startArg.type === "NUMBER" ? integerNumberLiteral(startArg) : isResolvedVariable(startArg) ? integerValue(startRaw) : null;
|
|
7820
|
+
const stopInteger = stopArg.type === "NUMBER" ? integerNumberLiteral(stopArg) : isResolvedVariable(stopArg) ? integerValue(stopRaw) : null;
|
|
7821
|
+
if (startInteger === null || stopInteger === null) {
|
|
7822
|
+
if ((startArg.type === "NUMBER" || isResolvedVariable(startArg)) && (stopArg.type === "NUMBER" || isResolvedVariable(stopArg))) {
|
|
7823
|
+
throw argumentError("GENERATE_SERIES \u306E\u6570\u5024\u7CFB\u5217\u306F\u6574\u6570\u306E start\u3001stop\u3001step \u306E\u307F\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7824
|
+
}
|
|
7825
|
+
throw argumentError("GENERATE_SERIES \u306E start \u3068 stop \u306F\u3001\u4E21\u65B9\u3092\u6574\u6570\u307E\u305F\u306F\u4E21\u65B9\u3092 DATE \u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7826
|
+
}
|
|
7827
|
+
const resolvedStep = stepRaw === void 0 ? 1 : stepArg?.type === "NUMBER" ? integerNumberLiteral(stepArg) : isResolvedVariable(stepArg) ? integerValue(stepRaw) : null;
|
|
7828
|
+
if (resolvedStep === null) {
|
|
7829
|
+
if (stepArg?.type === "NUMBER" || isResolvedVariable(stepArg)) {
|
|
7830
|
+
throw argumentError("GENERATE_SERIES \u306E\u6570\u5024\u7CFB\u5217\u306F\u6574\u6570\u306E start\u3001stop\u3001step \u306E\u307F\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7831
|
+
}
|
|
7832
|
+
throw argumentError("GENERATE_SERIES \u306E step \u304C\u7CFB\u5217\u306E\u578B\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002\u6574\u6570\u7CFB\u5217\u306B\u306F\u6574\u6570\u3001DATE \u7CFB\u5217\u306B\u306F day \u5358\u4F4D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7833
|
+
}
|
|
7834
|
+
const start = startInteger;
|
|
7835
|
+
const stop = stopInteger;
|
|
7836
|
+
const step = resolvedStep;
|
|
7837
|
+
if (step === 0) throw argumentError("GENERATE_SERIES \u306E step \u306B 0 \u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002");
|
|
7838
|
+
return { kind: "INTEGER", start, stop, step, rowCount: countRows(start, stop, step) };
|
|
7839
|
+
}
|
|
7840
|
+
function validateGenerateSeriesStatement(stmt) {
|
|
7841
|
+
if (stmt.args.length < 2 || stmt.args.length > 3) {
|
|
7842
|
+
throw argumentError("GENERATE_SERIES \u306F start\u3001stop \u3068\u7701\u7565\u53EF\u80FD\u306A step \u306E2\u500B\u307E\u305F\u306F3\u500B\u306E\u5F15\u6570\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7843
|
+
}
|
|
7844
|
+
if (stmt.args.some(isVariable)) {
|
|
7845
|
+
["start", "stop", "step"].forEach((name, index) => {
|
|
7846
|
+
const arg = stmt.args[index];
|
|
7847
|
+
if (arg?.type === "STRING" && arg.value === "") {
|
|
7848
|
+
throw argumentError(`GENERATE_SERIES \u306E ${name} \u306B\u7A7A\u6587\u5B57\u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002`);
|
|
7849
|
+
}
|
|
7850
|
+
if (arg?.type === "NUMBER" && integerNumberLiteral(arg) === null) {
|
|
7851
|
+
throw argumentError("GENERATE_SERIES \u306E\u6570\u5024\u7CFB\u5217\u306F\u6574\u6570\u306E start\u3001stop\u3001step \u306E\u307F\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7852
|
+
}
|
|
7853
|
+
if (index < 2 && arg?.type === "STRING") {
|
|
7854
|
+
if (isUnsupportedTemporal(arg.value)) {
|
|
7855
|
+
throw argumentError("GENERATE_SERIES \u306F Phase 1 \u3067\u306F\u6574\u6570\u3068 DATE \u306E\u307F\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u3059\u3002DATETIME \u3068 TIME \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002");
|
|
7856
|
+
}
|
|
7857
|
+
if (/^\d{4}-/.test(arg.value) && dateParts(arg.value) === null) {
|
|
7858
|
+
throw argumentError("GENERATE_SERIES \u306E\u65E5\u4ED8\u5F15\u6570\u306B\u306F\u5B9F\u5728\u3059\u308B YYYY-MM-DD \u5F62\u5F0F\u306E DATE \u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
7859
|
+
}
|
|
7860
|
+
}
|
|
7861
|
+
});
|
|
7862
|
+
const step = stmt.args[2];
|
|
7863
|
+
if (step?.type === "NUMBER") {
|
|
7864
|
+
const value = integerNumberLiteral(step);
|
|
7865
|
+
if (value === null) throw argumentError("GENERATE_SERIES \u306E\u6570\u5024\u7CFB\u5217\u306F\u6574\u6570\u306E start\u3001stop\u3001step \u306E\u307F\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7866
|
+
if (value === 0) throw argumentError("GENERATE_SERIES \u306E step \u306B 0 \u306F\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093\u3002");
|
|
7867
|
+
} else if (step?.type === "STRING") {
|
|
7868
|
+
parseDateStep(step.value);
|
|
7869
|
+
}
|
|
7870
|
+
return null;
|
|
7871
|
+
}
|
|
7872
|
+
const plan = planResolved(stmt);
|
|
7873
|
+
if (plan.rowCount > GENERATE_SERIES_MAX_ROWS) {
|
|
7874
|
+
throw argumentError(`GENERATE_SERIES \u306E\u751F\u6210\u4EF6\u6570 ${plan.rowCount} \u884C\u304C\u4E0A\u9650 ${GENERATE_SERIES_MAX_ROWS} \u884C\u3092\u8D85\u3048\u3066\u3044\u307E\u3059\u3002`);
|
|
7875
|
+
}
|
|
7876
|
+
return plan.rowCount;
|
|
7877
|
+
}
|
|
7878
|
+
function validateGenerateSeriesInStatement(node) {
|
|
7879
|
+
const visit = (value) => {
|
|
7880
|
+
if (value === null || typeof value !== "object") return;
|
|
7881
|
+
if (Array.isArray(value)) {
|
|
7882
|
+
value.forEach(visit);
|
|
7883
|
+
return;
|
|
7884
|
+
}
|
|
7885
|
+
const obj = value;
|
|
7886
|
+
if (obj.type === "WITH") {
|
|
7887
|
+
let total = 0;
|
|
7888
|
+
let complete = true;
|
|
7889
|
+
for (const cte of obj.ctes) {
|
|
7890
|
+
if (cte.query.type === "GENERATE_SERIES") {
|
|
7891
|
+
const count = validateGenerateSeriesStatement(cte.query);
|
|
7892
|
+
if (count === null) complete = false;
|
|
7893
|
+
else total += count;
|
|
7894
|
+
} else visit(cte.query);
|
|
7895
|
+
}
|
|
7896
|
+
if (complete && total > GENERATE_SERIES_MAX_ROWS) {
|
|
7897
|
+
throw argumentError(`\u3053\u306E WITH \u6587\u306E GENERATE_SERIES \u751F\u6210\u4EF6\u6570\u5408\u8A08 ${total} \u884C\u304C\u4E0A\u9650 ${GENERATE_SERIES_MAX_ROWS} \u884C\u3092\u8D85\u3048\u3066\u3044\u307E\u3059\u3002`);
|
|
7898
|
+
}
|
|
7899
|
+
visit(obj.query);
|
|
7900
|
+
return;
|
|
7901
|
+
}
|
|
7902
|
+
Object.values(obj).forEach(visit);
|
|
7903
|
+
};
|
|
7904
|
+
visit(node);
|
|
7905
|
+
}
|
|
7906
|
+
function resolveGenerateSeries(stmt) {
|
|
7907
|
+
const plan = planResolved(stmt);
|
|
7908
|
+
if (plan.rowCount > GENERATE_SERIES_MAX_ROWS) {
|
|
7909
|
+
throw argumentError(`GENERATE_SERIES \u306E\u751F\u6210\u4EF6\u6570 ${plan.rowCount} \u884C\u304C\u4E0A\u9650 ${GENERATE_SERIES_MAX_ROWS} \u884C\u3092\u8D85\u3048\u3066\u3044\u307E\u3059\u3002`);
|
|
7910
|
+
}
|
|
7911
|
+
const values = [];
|
|
7912
|
+
if (plan.kind === "INTEGER") {
|
|
7913
|
+
let current = plan.start;
|
|
7914
|
+
for (let index = 0; index < plan.rowCount; index++) {
|
|
7915
|
+
values.push(String(current));
|
|
7916
|
+
if (index + 1 < plan.rowCount) {
|
|
7917
|
+
const next = current + plan.step;
|
|
7918
|
+
if (!Number.isSafeInteger(next)) throw argumentError("GENERATE_SERIES \u306E\u6570\u5024\u7CFB\u5217\u306F\u6574\u6570\u306E start\u3001stop\u3001step \u306E\u307F\u3092\u53D7\u3051\u4ED8\u3051\u307E\u3059\u3002");
|
|
7919
|
+
current = next;
|
|
7920
|
+
}
|
|
7921
|
+
}
|
|
7922
|
+
} else {
|
|
7923
|
+
const startOrdinal = dateOrdinal(plan.start);
|
|
7924
|
+
for (let index = 0; index < plan.rowCount; index++) values.push(dateFromOrdinal(startOrdinal + index * plan.step));
|
|
7925
|
+
}
|
|
7926
|
+
return { ...plan, values };
|
|
7927
|
+
}
|
|
7928
|
+
|
|
7652
7929
|
// src/core/statementValidation.ts
|
|
7653
7930
|
function validateStatementStatic(stmt) {
|
|
7654
7931
|
validateStringFunctionArities(stmt);
|
|
7655
7932
|
validatePrimaryOrganizationDmlStatement(stmt);
|
|
7656
7933
|
validateKlikeStatement(stmt);
|
|
7934
|
+
validateGenerateSeriesInStatement(stmt);
|
|
7657
7935
|
}
|
|
7658
7936
|
function validateStringFunctionArities(stmt) {
|
|
7659
7937
|
const visit = (value) => {
|
|
@@ -12057,7 +12335,8 @@ var NATIVE_OPERATORS = /* @__PURE__ */ new Map([
|
|
|
12057
12335
|
["USER_SELECT", /* @__PURE__ */ new Set(["in", "not in"])],
|
|
12058
12336
|
["ORGANIZATION_SELECT", /* @__PURE__ */ new Set(["in", "not in"])],
|
|
12059
12337
|
["GROUP_SELECT", /* @__PURE__ */ new Set(["in", "not in"])],
|
|
12060
|
-
["STATUS", new Set(EQUALITY_IN)]
|
|
12338
|
+
["STATUS", new Set(EQUALITY_IN)],
|
|
12339
|
+
["STATUS_ASSIGNEE", /* @__PURE__ */ new Set(["in", "not in"])]
|
|
12061
12340
|
]);
|
|
12062
12341
|
var LOCAL_VALID_OPERATORS = /* @__PURE__ */ new Map([
|
|
12063
12342
|
["CREATOR", /* @__PURE__ */ new Set(["in", "not in"])],
|
|
@@ -12511,6 +12790,44 @@ function requireExactFunctionPushdown(result) {
|
|
|
12511
12790
|
);
|
|
12512
12791
|
}
|
|
12513
12792
|
|
|
12793
|
+
// src/core/optimization/joinDateTimeLiteralPolicy.ts
|
|
12794
|
+
function isCanonicalJoinDate(value) {
|
|
12795
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
12796
|
+
if (!match) return false;
|
|
12797
|
+
const year = Number(match[1]);
|
|
12798
|
+
const month = Number(match[2]);
|
|
12799
|
+
const day = Number(match[3]);
|
|
12800
|
+
if (year < 1 || year > 9999) return false;
|
|
12801
|
+
const date = /* @__PURE__ */ new Date(0);
|
|
12802
|
+
date.setUTCFullYear(year, month - 1, day);
|
|
12803
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
12804
|
+
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
|
|
12805
|
+
}
|
|
12806
|
+
function isCanonicalJoinTime(value) {
|
|
12807
|
+
const match = /^(\d{2}):(\d{2})$/.exec(value);
|
|
12808
|
+
return match !== null && Number(match[1]) <= 23 && Number(match[2]) <= 59;
|
|
12809
|
+
}
|
|
12810
|
+
function isCanonicalJoinDateTime(value) {
|
|
12811
|
+
const match = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/.exec(value);
|
|
12812
|
+
if (!match || !isCanonicalJoinDate(match[1])) return false;
|
|
12813
|
+
return Number(match[2]) <= 23 && Number(match[3]) <= 59 && Number(match[4]) <= 59;
|
|
12814
|
+
}
|
|
12815
|
+
|
|
12816
|
+
// src/core/optimization/joinNumberLiteralPolicy.ts
|
|
12817
|
+
function isJoinNumberLiteralSupported(literal) {
|
|
12818
|
+
const source = literal.raw ?? String(literal.value);
|
|
12819
|
+
const decimal = parseExactDecimal(source);
|
|
12820
|
+
if (decimal === null) return false;
|
|
12821
|
+
if (decimal.sign === 0) return numberLiteralText(literal) === "0";
|
|
12822
|
+
const fractionDigits = Math.max(decimal.scale, 0);
|
|
12823
|
+
const integerDigits = Math.max(decimal.coefficient.length - decimal.scale, 0);
|
|
12824
|
+
if (fractionDigits > 10 || integerDigits + fractionDigits > 30) {
|
|
12825
|
+
return false;
|
|
12826
|
+
}
|
|
12827
|
+
const canonical = formatPlainDecimal(decimal);
|
|
12828
|
+
return numberLiteralText(literal) === canonical;
|
|
12829
|
+
}
|
|
12830
|
+
|
|
12514
12831
|
// src/core/optimization/joinPredicatePushdown.ts
|
|
12515
12832
|
var SELECTION_TYPES = /* @__PURE__ */ new Set([
|
|
12516
12833
|
"DROP_DOWN",
|
|
@@ -12519,6 +12836,14 @@ var SELECTION_TYPES = /* @__PURE__ */ new Set([
|
|
|
12519
12836
|
"MULTI_SELECT",
|
|
12520
12837
|
"STATUS"
|
|
12521
12838
|
]);
|
|
12839
|
+
var USER_CODE_TYPES = /* @__PURE__ */ new Set([
|
|
12840
|
+
"CREATOR",
|
|
12841
|
+
"MODIFIER",
|
|
12842
|
+
"USER_SELECT",
|
|
12843
|
+
"ORGANIZATION_SELECT",
|
|
12844
|
+
"GROUP_SELECT",
|
|
12845
|
+
"STATUS_ASSIGNEE"
|
|
12846
|
+
]);
|
|
12522
12847
|
var KLIKE_TYPES = /* @__PURE__ */ new Set([
|
|
12523
12848
|
"SINGLE_LINE_TEXT",
|
|
12524
12849
|
"LINK",
|
|
@@ -12526,7 +12851,7 @@ var KLIKE_TYPES = /* @__PURE__ */ new Set([
|
|
|
12526
12851
|
"RICH_TEXT",
|
|
12527
12852
|
"FILE"
|
|
12528
12853
|
]);
|
|
12529
|
-
var
|
|
12854
|
+
var DATETIME_TYPES = /* @__PURE__ */ new Set([
|
|
12530
12855
|
"DATETIME",
|
|
12531
12856
|
"CREATED_TIME",
|
|
12532
12857
|
"UPDATED_TIME"
|
|
@@ -13122,21 +13447,45 @@ function classifySupportedLeaf(predicate, owner, fieldType) {
|
|
|
13122
13447
|
return isPositiveSafeInteger(predicate.right) && (predicate.op === "=" || predicate.op === "<" || predicate.op === ">" || predicate.op === "<=" || predicate.op === ">=") ? "exact" : "unsafe";
|
|
13123
13448
|
}
|
|
13124
13449
|
if (fieldType === "RECORD_NUMBER") {
|
|
13125
|
-
return
|
|
13450
|
+
return classifySupersetScalarOrListLiteral(predicate);
|
|
13126
13451
|
}
|
|
13127
13452
|
if (fieldType === "NUMBER") {
|
|
13128
|
-
if (predicate.
|
|
13129
|
-
|
|
13130
|
-
|
|
13453
|
+
if ((predicate.op === "IN" || predicate.op === "NOT_IN") && predicate.right.type === "IN_LIST" && predicate.right.values.length > 0 && predicate.right.values.every(
|
|
13454
|
+
(value) => value.type === "NUMBER" && isJoinNumberLiteralSupported(value)
|
|
13455
|
+
)) {
|
|
13456
|
+
return "exact";
|
|
13457
|
+
}
|
|
13458
|
+
if ((predicate.op === "=" || predicate.op === "!=" || predicate.op === "<>" || predicate.op === "<" || predicate.op === ">" || predicate.op === "<=" || predicate.op === ">=") && predicate.right.type === "NUMBER" && isJoinNumberLiteralSupported(predicate.right)) {
|
|
13459
|
+
return "exact";
|
|
13460
|
+
}
|
|
13461
|
+
return "unsafe";
|
|
13131
13462
|
}
|
|
13132
|
-
if (fieldType === "
|
|
13133
|
-
return predicate
|
|
13463
|
+
if (fieldType === "CALC") {
|
|
13464
|
+
return classifySupersetScalarOrListLiteral(predicate);
|
|
13134
13465
|
}
|
|
13135
|
-
if (
|
|
13136
|
-
if (predicate.op !== "
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13466
|
+
if (USER_CODE_TYPES.has(fieldType)) {
|
|
13467
|
+
if (predicate.op !== "IN" && predicate.op !== "NOT_IN" || predicate.right.type !== "IN_LIST" || predicate.right.values.length === 0) return "unsafe";
|
|
13468
|
+
return predicate.right.values.every(
|
|
13469
|
+
(value) => value.type === "STRING" && value.value !== ""
|
|
13470
|
+
) ? "exact" : "unsafe";
|
|
13471
|
+
}
|
|
13472
|
+
if (fieldType === "SINGLE_LINE_TEXT" || fieldType === "LINK") {
|
|
13473
|
+
if ((predicate.op === "IN" || predicate.op === "NOT_IN") && predicate.right.type === "IN_LIST" && predicate.right.values.length > 0 && predicate.right.values.every(
|
|
13474
|
+
(value) => value.type === "STRING" && value.value !== ""
|
|
13475
|
+
)) {
|
|
13476
|
+
return "exact";
|
|
13477
|
+
}
|
|
13478
|
+
return (predicate.op === "=" || predicate.op === "!=" || predicate.op === "<>") && predicate.right.type === "STRING" && predicate.right.value !== "" ? "exact" : "unsafe";
|
|
13479
|
+
}
|
|
13480
|
+
if (fieldType === "DATE" || fieldType === "TIME" || DATETIME_TYPES.has(fieldType)) {
|
|
13481
|
+
if (predicate.op !== "=" && predicate.op !== "!=" && predicate.op !== "<>" && predicate.op !== "<" && predicate.op !== ">" && predicate.op !== "<=" && predicate.op !== ">=" || predicate.right.type !== "STRING") return "unsafe";
|
|
13482
|
+
if (fieldType === "DATE") {
|
|
13483
|
+
return isCanonicalJoinDate(predicate.right.value) ? "exact" : "unsafe";
|
|
13484
|
+
}
|
|
13485
|
+
if (fieldType === "TIME") {
|
|
13486
|
+
return isCanonicalJoinTime(predicate.right.value) ? "exact" : "unsafe";
|
|
13487
|
+
}
|
|
13488
|
+
return isCanonicalJoinDateTime(predicate.right.value) ? "exact" : "unsafe";
|
|
13140
13489
|
}
|
|
13141
13490
|
if (SELECTION_TYPES.has(fieldType)) {
|
|
13142
13491
|
if (predicate.op !== "IN" && predicate.op !== "NOT_IN" || predicate.right.type !== "IN_LIST" || predicate.right.values.length === 0) return "unsafe";
|
|
@@ -13148,6 +13497,19 @@ function classifySupportedLeaf(predicate, owner, fieldType) {
|
|
|
13148
13497
|
}
|
|
13149
13498
|
return "unsafe";
|
|
13150
13499
|
}
|
|
13500
|
+
function classifySupersetScalarOrListLiteral(predicate) {
|
|
13501
|
+
const supportedLiteral = (value) => value.type === "NUMBER" && isJoinNumberLiteralSupported(value) || value.type === "STRING" && value.value !== "";
|
|
13502
|
+
if ((predicate.op === "IN" || predicate.op === "NOT_IN") && predicate.right.type === "IN_LIST") {
|
|
13503
|
+
const values = predicate.right.values;
|
|
13504
|
+
if (values.length > 0 && values.every(supportedLiteral) && values.every((value) => value.type === values[0].type)) {
|
|
13505
|
+
return "superset";
|
|
13506
|
+
}
|
|
13507
|
+
}
|
|
13508
|
+
if ((predicate.op === "=" || predicate.op === "!=" || predicate.op === "<>" || predicate.op === "<" || predicate.op === ">" || predicate.op === "<=" || predicate.op === ">=") && supportedLiteral(predicate.right)) {
|
|
13509
|
+
return "superset";
|
|
13510
|
+
}
|
|
13511
|
+
return "unsafe";
|
|
13512
|
+
}
|
|
13151
13513
|
function owned(source, fieldCode) {
|
|
13152
13514
|
return Object.freeze({
|
|
13153
13515
|
status: "OWNED",
|
|
@@ -13172,24 +13534,6 @@ function isPositiveSafeInteger(value) {
|
|
|
13172
13534
|
function isSafeIntegerLiteral(value) {
|
|
13173
13535
|
return /^-?\d+$/.test(numberLiteralText(value)) && Number.isSafeInteger(value.value);
|
|
13174
13536
|
}
|
|
13175
|
-
function isCanonicalDate(value) {
|
|
13176
|
-
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
13177
|
-
if (!match) return false;
|
|
13178
|
-
const year = Number(match[1]);
|
|
13179
|
-
const month = Number(match[2]);
|
|
13180
|
-
const day = Number(match[3]);
|
|
13181
|
-
const date = new Date(Date.UTC(year, month - 1, day));
|
|
13182
|
-
return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
|
|
13183
|
-
}
|
|
13184
|
-
function isCanonicalTime(value) {
|
|
13185
|
-
const match = /^(\d{2}):(\d{2})$/.exec(value);
|
|
13186
|
-
return match !== null && Number(match[1]) <= 23 && Number(match[2]) <= 59;
|
|
13187
|
-
}
|
|
13188
|
-
function isCanonicalDateTime(value) {
|
|
13189
|
-
const match = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/.exec(value);
|
|
13190
|
-
if (!match || !isCanonicalDate(match[1])) return false;
|
|
13191
|
-
return Number(match[2]) <= 23 && Number(match[3]) <= 59 && Number(match[4]) <= 59;
|
|
13192
|
-
}
|
|
13193
13537
|
function collectKlikes2(where, out) {
|
|
13194
13538
|
if (where === null) return;
|
|
13195
13539
|
if (isKlike(where)) {
|
|
@@ -17767,7 +18111,7 @@ function resolveBatchVariableReferencesInternal(node, variables, numericArithmet
|
|
|
17767
18111
|
type: "NUMBER",
|
|
17768
18112
|
value: value.value,
|
|
17769
18113
|
raw: numericArithmeticOperand === "AGG_ARITH" ? `@${obj["name"]}` : value.raw ?? String(value.value)
|
|
17770
|
-
} : { type: "STRING", value: value.value };
|
|
18114
|
+
} : { type: "STRING", value: value.value, fromVariable: true };
|
|
17771
18115
|
}
|
|
17772
18116
|
if (obj["type"] === "VARIABLE_COL" && typeof obj["name"] === "string" && typeof obj["alias"] === "string") {
|
|
17773
18117
|
const value = variables.get(obj["name"]);
|
|
@@ -18083,10 +18427,16 @@ function hasDefaultRangeAggregateWindow(stmt) {
|
|
|
18083
18427
|
function hasWindowNeedingOrderProof(stmt) {
|
|
18084
18428
|
return hasDefaultRangeAggregateWindow(stmt) || stmt.columns.some((column) => column.type === "WINDOW_COL" && column.windowKind === "VALUE");
|
|
18085
18429
|
}
|
|
18086
|
-
function canProveTotalWindowOrder(stmt, orderBy, resolveField2, context) {
|
|
18087
|
-
if (
|
|
18088
|
-
return
|
|
18430
|
+
function canProveTotalWindowOrder(stmt, orderBy, resolveField2, context, generatedColumn) {
|
|
18431
|
+
if (generatedColumn !== void 0 && stmt.joins.length === 0 && stmt.from.cteName !== null) {
|
|
18432
|
+
return orderBy.some((item) => {
|
|
18433
|
+
if (item.key.type !== "FIELD_NAME") return false;
|
|
18434
|
+
const ref = aggregateFieldRef(item.key.name);
|
|
18435
|
+
if (ref.field !== generatedColumn) return false;
|
|
18436
|
+
return ref.tableAlias === null || ref.tableAlias === effectiveTableAlias(stmt.from);
|
|
18437
|
+
});
|
|
18089
18438
|
}
|
|
18439
|
+
if (context !== "DIRECT" || stmt.joins.length > 0 || stmt.from.cteName !== null || stmt.from.subtableCode != null) return false;
|
|
18090
18440
|
return orderBy.some((item) => {
|
|
18091
18441
|
if (item.key.type !== "FIELD_NAME") return false;
|
|
18092
18442
|
const ref = aggregateFieldRef(item.key.name);
|
|
@@ -18099,18 +18449,18 @@ function tieBreakAdvice(context, kind) {
|
|
|
18099
18449
|
}
|
|
18100
18450
|
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";
|
|
18101
18451
|
}
|
|
18102
|
-
function collectDefaultRangeWindowWarnings(stmt, resolveField2, context) {
|
|
18452
|
+
function collectDefaultRangeWindowWarnings(stmt, resolveField2, context, generatedColumn) {
|
|
18103
18453
|
const warnings = [];
|
|
18104
18454
|
for (const column of stmt.columns) {
|
|
18105
18455
|
if (column.type !== "WINDOW_COL" || column.windowKind !== "AGGREGATE" || column.orderBy.length === 0 || column.frame?.source !== "DEFAULT") continue;
|
|
18106
|
-
if (canProveTotalWindowOrder(stmt, column.orderBy, resolveField2, context)) continue;
|
|
18456
|
+
if (canProveTotalWindowOrder(stmt, column.orderBy, resolveField2, context, generatedColumn)) continue;
|
|
18107
18457
|
warnings.push(
|
|
18108
18458
|
`${column.alias} \u306F\u65E2\u5B9A\u30D5\u30EC\u30FC\u30E0\uFF08RANGE\uFF09\u3067\u8A55\u4FA1\u3055\u308C\u307E\u3059\u3002ORDER BY \u306E\u5024\u304C\u540C\u3058\u884C\u306F\u3059\u3079\u3066\u540C\u3058\u5024\u306B\u306A\u308A\u307E\u3059\u3002\u884C\u3054\u3068\u306E\u5024\u304C\u5FC5\u8981\u306A\u3089 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW \u3092\u660E\u793A\u3059\u308B\u304B\u3001` + tieBreakAdvice(context, "RANGE")
|
|
18109
18459
|
);
|
|
18110
18460
|
}
|
|
18111
18461
|
for (const column of stmt.columns) {
|
|
18112
18462
|
if (column.type !== "WINDOW_COL" || column.windowKind !== "VALUE") continue;
|
|
18113
|
-
if (canProveTotalWindowOrder(stmt, column.orderBy, resolveField2, context)) continue;
|
|
18463
|
+
if (canProveTotalWindowOrder(stmt, column.orderBy, resolveField2, context, generatedColumn)) continue;
|
|
18114
18464
|
warnings.push(
|
|
18115
18465
|
`${column.alias} \u306E ORDER BY \u306F\u5168\u9806\u5E8F\u3067\u306A\u3044\u305F\u3081\u3001\u540C\u9806\u5185\u306E\u524D\u5F8C\u95A2\u4FC2\u306F\u672A\u898F\u5B9A\u3067\u3059\u3002` + tieBreakAdvice(context, "VALUE")
|
|
18116
18466
|
);
|
|
@@ -20041,6 +20391,8 @@ async function executeWith(stmt, client, options, cacheContext, seed, captureCol
|
|
|
20041
20391
|
result2 = await executeShowApps(client);
|
|
20042
20392
|
} else if (cte.query.type === "DESCRIBE") {
|
|
20043
20393
|
result2 = await executeDescribe(cte.query, client, cacheContext);
|
|
20394
|
+
} else if (cte.query.type === "GENERATE_SERIES") {
|
|
20395
|
+
result2 = executeGenerateSeries(cte.query);
|
|
20044
20396
|
} else {
|
|
20045
20397
|
result2 = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
|
|
20046
20398
|
}
|
|
@@ -20048,7 +20400,8 @@ async function executeWith(stmt, client, options, cacheContext, seed, captureCol
|
|
|
20048
20400
|
cteCache.set(cte.name, {
|
|
20049
20401
|
rows: result2.rows,
|
|
20050
20402
|
columns: result2.columns,
|
|
20051
|
-
columnMeta: materializedMetaBySelectResult.get(result2)
|
|
20403
|
+
columnMeta: materializedMetaBySelectResult.get(result2),
|
|
20404
|
+
...cte.query.type === "GENERATE_SERIES" ? { uniqueGeneratedColumn: cte.query.columnAlias } : {}
|
|
20052
20405
|
});
|
|
20053
20406
|
}
|
|
20054
20407
|
const result = await executeQueryWithCte(
|
|
@@ -20061,6 +20414,27 @@ async function executeWith(stmt, client, options, cacheContext, seed, captureCol
|
|
|
20061
20414
|
);
|
|
20062
20415
|
return mergeSelectWarnings(result, [...warnings]);
|
|
20063
20416
|
}
|
|
20417
|
+
function executeGenerateSeries(stmt) {
|
|
20418
|
+
const series = resolveGenerateSeries(stmt);
|
|
20419
|
+
const result = {
|
|
20420
|
+
type: "SELECT",
|
|
20421
|
+
columns: [stmt.columnAlias],
|
|
20422
|
+
rows: series.values.map((value) => ({ [stmt.columnAlias]: value })),
|
|
20423
|
+
rowCount: series.rowCount,
|
|
20424
|
+
warnings: []
|
|
20425
|
+
};
|
|
20426
|
+
const meta = series.kind === "INTEGER" ? {
|
|
20427
|
+
sortKind: "number",
|
|
20428
|
+
fieldType: "NUMBER",
|
|
20429
|
+
semantics: resolveFieldSemantics({ fieldType: "NUMBER" })
|
|
20430
|
+
} : {
|
|
20431
|
+
sortKind: "string",
|
|
20432
|
+
fieldType: "DATE",
|
|
20433
|
+
semantics: resolveFieldSemantics({ fieldType: "DATE" })
|
|
20434
|
+
};
|
|
20435
|
+
materializedMetaBySelectResult.set(result, /* @__PURE__ */ new Map([[stmt.columnAlias, meta]]));
|
|
20436
|
+
return result;
|
|
20437
|
+
}
|
|
20064
20438
|
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false, b86PreflightComplete = false) {
|
|
20065
20439
|
if (!b86PreflightComplete) {
|
|
20066
20440
|
await preflightB86QueryWithCte(query, client, cteCache, cacheContext);
|
|
@@ -20167,7 +20541,8 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
20167
20541
|
const defaultRangeWarnings = collectDefaultRangeWindowWarnings(
|
|
20168
20542
|
stmt,
|
|
20169
20543
|
choiceAndWindowResolver,
|
|
20170
|
-
"DERIVED"
|
|
20544
|
+
"DERIVED",
|
|
20545
|
+
stmt.joins.length === 0 && stmt.from.cteName !== null ? cteCache.get(stmt.from.cteName)?.uniqueGeneratedColumn : void 0
|
|
20171
20546
|
);
|
|
20172
20547
|
const maxRecords = options.maxRecords ?? 1e4;
|
|
20173
20548
|
const warnings = /* @__PURE__ */ new Set();
|
|
@@ -23840,6 +24215,9 @@ async function buildExplainWhereAnalysis(query, client, cacheContext, maxRecords
|
|
|
23840
24215
|
}
|
|
23841
24216
|
if (typed["type"] === "SHOW_APPS") return [...SHOW_APPS_COLUMNS];
|
|
23842
24217
|
if (typed["type"] === "DESCRIBE") return [...DESCRIBE_COLUMNS];
|
|
24218
|
+
if (typed["type"] === "GENERATE_SERIES") {
|
|
24219
|
+
return [node.columnAlias];
|
|
24220
|
+
}
|
|
23843
24221
|
throw new Error("ArgumentError: EXPLAIN could not determine the relation output schema.");
|
|
23844
24222
|
};
|
|
23845
24223
|
const preflightExplainRelations = async (node) => {
|
|
@@ -25133,6 +25511,22 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans, collec
|
|
|
25133
25511
|
"cte"
|
|
25134
25512
|
));
|
|
25135
25513
|
lines.push("");
|
|
25514
|
+
} else if (cte.query.type === "GENERATE_SERIES") {
|
|
25515
|
+
const series = resolveGenerateSeries(cte.query);
|
|
25516
|
+
const step = series.kind === "DATE" ? `${series.step} ${Math.abs(series.step) === 1 ? "day" : "days"}` : String(series.step);
|
|
25517
|
+
lines.push(
|
|
25518
|
+
`[cte: ${cte.name}]`,
|
|
25519
|
+
" source: GENERATE_SERIES",
|
|
25520
|
+
` column: ${cte.query.columnAlias}`,
|
|
25521
|
+
` series type: ${series.kind}`,
|
|
25522
|
+
` start: ${series.start}`,
|
|
25523
|
+
` stop: ${series.stop}`,
|
|
25524
|
+
` step: ${step}`,
|
|
25525
|
+
` rows: ${series.rowCount}`,
|
|
25526
|
+
` row guard: ${series.rowCount} / ${GENERATE_SERIES_MAX_ROWS}`,
|
|
25527
|
+
" records API: none",
|
|
25528
|
+
""
|
|
25529
|
+
);
|
|
25136
25530
|
}
|
|
25137
25531
|
}
|
|
25138
25532
|
if (stmt.query.type === "SELECT" || stmt.query.type === "UNION") {
|
|
@@ -26083,19 +26477,19 @@ function normalizeSqlAppProfiles(sql, defaultProfile = "dev", resolutionContext)
|
|
|
26083
26477
|
var PHYSICAL_APP_KEY_RE = /^APP\d+$/i;
|
|
26084
26478
|
var NUMERIC_APP_KEY_RE = /^\d+$/;
|
|
26085
26479
|
var LOGICAL_SQL_KEY_RE = /^LAPP_/i;
|
|
26086
|
-
function
|
|
26480
|
+
function argumentError2(message) {
|
|
26087
26481
|
return new Error(`ArgumentError: ${message}`);
|
|
26088
26482
|
}
|
|
26089
26483
|
function normalizeLogicalApps(profileName, value) {
|
|
26090
26484
|
if (value === void 0) return void 0;
|
|
26091
26485
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
26092
|
-
throw
|
|
26486
|
+
throw argumentError2(`logicalApps for profile "${profileName}" must be an object.`);
|
|
26093
26487
|
}
|
|
26094
26488
|
const normalized = {};
|
|
26095
26489
|
const physicalIdOwners = /* @__PURE__ */ new Map();
|
|
26096
26490
|
for (const [rawName, rawAppId] of Object.entries(value)) {
|
|
26097
26491
|
if (PHYSICAL_APP_KEY_RE.test(rawName) || NUMERIC_APP_KEY_RE.test(rawName) || LOGICAL_SQL_KEY_RE.test(rawName)) {
|
|
26098
|
-
throw
|
|
26492
|
+
throw argumentError2(
|
|
26099
26493
|
`logical app key "${rawName}" in profile "${profileName}" must be a logical name without APP, numeric, or LAPP_ syntax.`
|
|
26100
26494
|
);
|
|
26101
26495
|
}
|
|
@@ -26103,23 +26497,23 @@ function normalizeLogicalApps(profileName, value) {
|
|
|
26103
26497
|
try {
|
|
26104
26498
|
logicalName = canonicalizeLogicalAppName(rawName);
|
|
26105
26499
|
} catch {
|
|
26106
|
-
throw
|
|
26500
|
+
throw argumentError2(
|
|
26107
26501
|
`logical app key "${rawName}" in profile "${profileName}" must match the logical app name rules.`
|
|
26108
26502
|
);
|
|
26109
26503
|
}
|
|
26110
26504
|
if (Object.prototype.hasOwnProperty.call(normalized, logicalName)) {
|
|
26111
|
-
throw
|
|
26505
|
+
throw argumentError2(
|
|
26112
26506
|
`logical app name "${logicalName}" is duplicated after case normalization in profile "${profileName}".`
|
|
26113
26507
|
);
|
|
26114
26508
|
}
|
|
26115
26509
|
if (typeof rawAppId !== "number" || !Number.isSafeInteger(rawAppId) || rawAppId <= 0) {
|
|
26116
|
-
throw
|
|
26510
|
+
throw argumentError2(
|
|
26117
26511
|
`physical app ID for logical app "${logicalName}" in profile "${profileName}" must be a positive safe integer.`
|
|
26118
26512
|
);
|
|
26119
26513
|
}
|
|
26120
26514
|
const existingName = physicalIdOwners.get(rawAppId);
|
|
26121
26515
|
if (existingName !== void 0) {
|
|
26122
|
-
throw
|
|
26516
|
+
throw argumentError2(
|
|
26123
26517
|
`logical apps "${existingName}" and "${logicalName}" in profile "${profileName}" map to the same physical app ID ${rawAppId}; physical app aliases are not supported yet.`
|
|
26124
26518
|
);
|
|
26125
26519
|
}
|
|
@@ -26130,31 +26524,31 @@ function normalizeLogicalApps(profileName, value) {
|
|
|
26130
26524
|
}
|
|
26131
26525
|
function validateKsqlConfig(config) {
|
|
26132
26526
|
if (config === null || typeof config !== "object" || Array.isArray(config)) {
|
|
26133
|
-
throw
|
|
26527
|
+
throw argumentError2("config must be an object.");
|
|
26134
26528
|
}
|
|
26135
26529
|
if (config.profiles === void 0) return config;
|
|
26136
26530
|
if (config.profiles === null || typeof config.profiles !== "object" || Array.isArray(config.profiles)) {
|
|
26137
|
-
throw
|
|
26531
|
+
throw argumentError2("profiles must be an object.");
|
|
26138
26532
|
}
|
|
26139
26533
|
for (const [profileName, profile] of Object.entries(config.profiles)) {
|
|
26140
26534
|
if (profile === null || typeof profile !== "object" || Array.isArray(profile)) {
|
|
26141
|
-
throw
|
|
26535
|
+
throw argumentError2(`profile "${profileName}" must be an object.`);
|
|
26142
26536
|
}
|
|
26143
26537
|
if (profile.allowPhysicalAppRefs !== void 0 && typeof profile.allowPhysicalAppRefs !== "boolean") {
|
|
26144
|
-
throw
|
|
26538
|
+
throw argumentError2(`allowPhysicalAppRefs for profile "${profileName}" must be boolean.`);
|
|
26145
26539
|
}
|
|
26146
26540
|
const logicalApps = normalizeLogicalApps(profileName, profile.logicalApps);
|
|
26147
26541
|
if (logicalApps !== void 0) profile.logicalApps = logicalApps;
|
|
26148
26542
|
if (profile.query?.cursorMaxActive !== void 0) {
|
|
26149
26543
|
const value = profile.query.cursorMaxActive;
|
|
26150
26544
|
if (!Number.isSafeInteger(value) || value < 1 || value > 5) {
|
|
26151
|
-
throw
|
|
26545
|
+
throw argumentError2(`query.cursorMaxActive for profile "${profileName}" must be an integer from 1 to 5.`);
|
|
26152
26546
|
}
|
|
26153
26547
|
}
|
|
26154
26548
|
if (profile.query?.dmlMaxSubtableRows !== void 0) {
|
|
26155
26549
|
const value = profile.query.dmlMaxSubtableRows;
|
|
26156
26550
|
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
26157
|
-
throw
|
|
26551
|
+
throw argumentError2(`query.dmlMaxSubtableRows for profile "${profileName}" must be a positive safe integer.`);
|
|
26158
26552
|
}
|
|
26159
26553
|
}
|
|
26160
26554
|
}
|
|
@@ -26174,7 +26568,7 @@ function createAppResolutionContext(config, defaultProfile) {
|
|
|
26174
26568
|
function requireProfile(profileName) {
|
|
26175
26569
|
const profile = profiles[profileName];
|
|
26176
26570
|
if (!profile && profileName === defaultProfile) return implicitDefaultProfile;
|
|
26177
|
-
if (!profile) throw
|
|
26571
|
+
if (!profile) throw argumentError2(`profile "${profileName}" is not defined.`);
|
|
26178
26572
|
return profile;
|
|
26179
26573
|
}
|
|
26180
26574
|
return {
|
|
@@ -26184,11 +26578,11 @@ function createAppResolutionContext(config, defaultProfile) {
|
|
|
26184
26578
|
try {
|
|
26185
26579
|
logicalName = canonicalizeLogicalAppName(name);
|
|
26186
26580
|
} catch {
|
|
26187
|
-
throw
|
|
26581
|
+
throw argumentError2(`logical app name "${name}" must match the logical app name rules.`);
|
|
26188
26582
|
}
|
|
26189
26583
|
const appId = requireProfile(profileName).logicalApps?.[logicalName];
|
|
26190
26584
|
if (appId === void 0) {
|
|
26191
|
-
throw
|
|
26585
|
+
throw argumentError2(`logical app LAPP_${logicalName}@${profileName} is not defined.`);
|
|
26192
26586
|
}
|
|
26193
26587
|
return appId;
|
|
26194
26588
|
},
|
|
@@ -26196,7 +26590,7 @@ function createAppResolutionContext(config, defaultProfile) {
|
|
|
26196
26590
|
const profileName = profile || defaultProfile;
|
|
26197
26591
|
if (!profiles[profileName]) return;
|
|
26198
26592
|
if (requireProfile(profileName).allowPhysicalAppRefs === false) {
|
|
26199
|
-
throw
|
|
26593
|
+
throw argumentError2(
|
|
26200
26594
|
`physical app references are not allowed for profile "${profileName}"; use LAPP_<NAME>.`
|
|
26201
26595
|
);
|
|
26202
26596
|
}
|