@rex0220/kintone-sql-tools 3.66.1 → 3.68.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 +1141 -250
- package/dist-engine/index.cjs +17 -13
- package/dist-engine/index.mjs +17 -13
- package/dist-engine/ksql-engine.umd.js +17 -13
- package/dist-engine/meta/bundle-baseline.json +10 -10
- package/dist-engine/meta/cjs.json +51 -24
- package/dist-engine/meta/esm.json +51 -24
- package/dist-engine/meta/umd.json +51 -24
- package/dist-mcp/ksql-mcp.js +1152 -252
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-cli/ksql.js
CHANGED
|
@@ -475,7 +475,7 @@ var Lexer = class {
|
|
|
475
475
|
// ヘルパー
|
|
476
476
|
// ----------------------------------------------------------
|
|
477
477
|
makeToken(kind, value, pos) {
|
|
478
|
-
return { kind, value, pos };
|
|
478
|
+
return { kind, value, pos, end: this.pos };
|
|
479
479
|
}
|
|
480
480
|
};
|
|
481
481
|
function isIdentStart(ch) {
|
|
@@ -1082,6 +1082,8 @@ var Parser = class {
|
|
|
1082
1082
|
this.allowRelativeDateFunctions = false;
|
|
1083
1083
|
/** WITH 句で定義された CTE 名のセット(parseTableRef で参照) */
|
|
1084
1084
|
this.cteNames = /* @__PURE__ */ new Set();
|
|
1085
|
+
/** dialect 1 の裸名で宣言された一時テーブル名(参照時に # 付きへ正規化) */
|
|
1086
|
+
this.bareTempTableNames = /* @__PURE__ */ new Set();
|
|
1085
1087
|
/** パース中に出現した一時テーブル参照(#name)のトークン。単文 API での拒否に使う */
|
|
1086
1088
|
this.tempTableRefs = [];
|
|
1087
1089
|
/** GROUP BY を読む前に作る B124 候補 leaf の診断位置。AST 公開型へ位置情報を足さない。 */
|
|
@@ -1120,7 +1122,12 @@ var Parser = class {
|
|
|
1120
1122
|
}
|
|
1121
1123
|
/** 複文(`;` 区切り)をパースする。空文はスキップする */
|
|
1122
1124
|
parseStatements() {
|
|
1125
|
+
return this.parseStatementsWithRanges().statements;
|
|
1126
|
+
}
|
|
1127
|
+
/** 複文と、原文上の文ごとの文字範囲を同時に返す。 */
|
|
1128
|
+
parseStatementsWithRanges() {
|
|
1123
1129
|
const stmts = [];
|
|
1130
|
+
const statementRanges = [];
|
|
1124
1131
|
while (true) {
|
|
1125
1132
|
while (this.peek().kind === ";" /* SEMICOLON */) this.advance();
|
|
1126
1133
|
if (this.peek().kind === "EOF" /* EOF */) break;
|
|
@@ -1136,9 +1143,11 @@ var Parser = class {
|
|
|
1136
1143
|
if (after.kind !== ";" /* SEMICOLON */ && after.kind !== "EOF" /* EOF */) {
|
|
1137
1144
|
throw new ParseError("\u6587\u306E\u533A\u5207\u308A\u306B\u306F ; \u304C\u5FC5\u8981\u3067\u3059", after);
|
|
1138
1145
|
}
|
|
1146
|
+
const lastTok = this.prev();
|
|
1147
|
+
statementRanges.push({ start: startTok.pos, end: lastTok.end ?? after.pos });
|
|
1139
1148
|
}
|
|
1140
1149
|
this.expect("EOF" /* EOF */);
|
|
1141
|
-
return stmts;
|
|
1150
|
+
return { statements: stmts, statementRanges };
|
|
1142
1151
|
}
|
|
1143
1152
|
// ----------------------------------------------------------
|
|
1144
1153
|
// Statement ディスパッチ
|
|
@@ -1177,6 +1186,13 @@ var Parser = class {
|
|
|
1177
1186
|
if (upper === "DROP") return this.parseDropTempTable();
|
|
1178
1187
|
if (upper === "DECLARE") return this.parseDeclareVariable();
|
|
1179
1188
|
if (upper === "VALIDATE") return this.parseValidate();
|
|
1189
|
+
if (upper === "EXIT") return this.parseExit();
|
|
1190
|
+
if (upper === "MERGE") {
|
|
1191
|
+
if (!this.capabilities.dialect1) {
|
|
1192
|
+
throw new ParseError("MERGE \u306B\u306F -- @ksql dialect: 1 \u306E\u5BA3\u8A00\u304C\u5FC5\u8981\u3067\u3059", tok);
|
|
1193
|
+
}
|
|
1194
|
+
return this.parseMergeAsUpsert();
|
|
1195
|
+
}
|
|
1180
1196
|
if (upper === "GENERATE_SERIES") {
|
|
1181
1197
|
throw new ParseError(
|
|
1182
1198
|
"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",
|
|
@@ -1195,7 +1211,7 @@ var Parser = class {
|
|
|
1195
1211
|
break;
|
|
1196
1212
|
}
|
|
1197
1213
|
throw new ParseError(
|
|
1198
|
-
"SELECT / INSERT / UPDATE / DELETE / REORDER / VALIDATE / WITH / SHOW / DESCRIBE / EXPLAIN / CREATE TEMP TABLE / DROP TEMP TABLE / SET / DECLARE / ASSERT \u306E\u3044\u305A\u308C\u304B\u3067\u59CB\u307E\u308B SQL \u6587\u304C\u5FC5\u8981\u3067\u3059",
|
|
1214
|
+
"SELECT / INSERT / UPDATE / DELETE / REORDER / VALIDATE / WITH / SHOW / DESCRIBE / EXPLAIN / CREATE TEMP TABLE / DROP TEMP TABLE / SET / DECLARE / ASSERT / EXIT \u306E\u3044\u305A\u308C\u304B\u3067\u59CB\u307E\u308B SQL \u6587\u304C\u5FC5\u8981\u3067\u3059",
|
|
1199
1215
|
tok
|
|
1200
1216
|
);
|
|
1201
1217
|
}
|
|
@@ -1323,6 +1339,7 @@ var Parser = class {
|
|
|
1323
1339
|
this.advance();
|
|
1324
1340
|
this.expectSoftKeyword("TEMP", "CREATE \u306E\u5F8C\u306B\u306F TEMP TABLE \u304C\u5FC5\u8981\u3067\u3059\uFF08\u4F8B: CREATE TEMP TABLE #temp AS SELECT ...\uFF09");
|
|
1325
1341
|
this.expectSoftKeyword("TABLE", "CREATE TEMP \u306E\u5F8C\u306B\u306F TABLE \u304C\u5FC5\u8981\u3067\u3059");
|
|
1342
|
+
const bareName = this.isDialect1BareTempTableName();
|
|
1326
1343
|
const name = this.parseTempTableName();
|
|
1327
1344
|
this.expect("AS" /* AS */, "CREATE TEMP TABLE \u306B\u306F AS SELECT \u304C\u5FC5\u8981\u3067\u3059");
|
|
1328
1345
|
const tok = this.peek();
|
|
@@ -1334,13 +1351,16 @@ var Parser = class {
|
|
|
1334
1351
|
} else {
|
|
1335
1352
|
throw new ParseError("CREATE TEMP TABLE ... AS \u306E\u5F8C\u306B\u306F SELECT / WITH \u304C\u5FC5\u8981\u3067\u3059", tok);
|
|
1336
1353
|
}
|
|
1354
|
+
if (bareName !== null) this.bareTempTableNames.add(bareName);
|
|
1337
1355
|
return { type: "CREATE_TEMP_TABLE", name, query };
|
|
1338
1356
|
}
|
|
1339
1357
|
parseDropTempTable() {
|
|
1340
1358
|
this.advance();
|
|
1341
1359
|
this.expectSoftKeyword("TEMP", "DROP \u306E\u5F8C\u306B\u306F TEMP TABLE \u304C\u5FC5\u8981\u3067\u3059\uFF08\u4F8B: DROP TEMP TABLE #temp\uFF09");
|
|
1342
1360
|
this.expectSoftKeyword("TABLE", "DROP TEMP \u306E\u5F8C\u306B\u306F TABLE \u304C\u5FC5\u8981\u3067\u3059");
|
|
1361
|
+
const bareName = this.isDialect1BareTempTableName();
|
|
1343
1362
|
const name = this.parseTempTableName();
|
|
1363
|
+
if (bareName !== null) this.bareTempTableNames.delete(bareName);
|
|
1344
1364
|
return { type: "DROP_TEMP_TABLE", name };
|
|
1345
1365
|
}
|
|
1346
1366
|
expectSoftKeyword(word, msg) {
|
|
@@ -1362,8 +1382,16 @@ var Parser = class {
|
|
|
1362
1382
|
this.advance();
|
|
1363
1383
|
return tok.value;
|
|
1364
1384
|
}
|
|
1385
|
+
if (this.capabilities.dialect1 && (tok.kind === "IDENT" /* IDENT */ || tok.kind === "BIDENT" /* BIDENT */)) {
|
|
1386
|
+
this.advance();
|
|
1387
|
+
return `#${tok.value}`;
|
|
1388
|
+
}
|
|
1365
1389
|
throw new ParseError("\u4E00\u6642\u30C6\u30FC\u30D6\u30EB\u540D\u306F # \u3067\u59CB\u307E\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08\u4F8B: #temp\uFF09", tok);
|
|
1366
1390
|
}
|
|
1391
|
+
isDialect1BareTempTableName() {
|
|
1392
|
+
const tok = this.peek();
|
|
1393
|
+
return this.capabilities.dialect1 && (tok.kind === "IDENT" /* IDENT */ || tok.kind === "BIDENT" /* BIDENT */) && !tok.value.startsWith("#") ? tok.value : null;
|
|
1394
|
+
}
|
|
1367
1395
|
parseShow() {
|
|
1368
1396
|
this.advance();
|
|
1369
1397
|
if (!this.consume("APPS" /* APPS */)) {
|
|
@@ -1691,6 +1719,41 @@ var Parser = class {
|
|
|
1691
1719
|
// ----------------------------------------------------------
|
|
1692
1720
|
parseAssert() {
|
|
1693
1721
|
this.expect("ASSERT" /* ASSERT */);
|
|
1722
|
+
const warnTok = this.peek();
|
|
1723
|
+
const warn = this.isSoftKeyword("WARN");
|
|
1724
|
+
if (warn) {
|
|
1725
|
+
this.requireDialect1(warnTok);
|
|
1726
|
+
this.advance();
|
|
1727
|
+
}
|
|
1728
|
+
const condition = this.parseAssertCondition();
|
|
1729
|
+
const message = this.parseFlowMessage();
|
|
1730
|
+
return {
|
|
1731
|
+
type: "ASSERT",
|
|
1732
|
+
...condition,
|
|
1733
|
+
...warn ? { warn: true } : {},
|
|
1734
|
+
...message !== void 0 ? { message } : {}
|
|
1735
|
+
};
|
|
1736
|
+
}
|
|
1737
|
+
/** EXIT SUCCESS IF <ASSERT と同じ条件>, '<message>' */
|
|
1738
|
+
parseExit() {
|
|
1739
|
+
const exitTok = this.advance();
|
|
1740
|
+
this.requireDialect1(exitTok);
|
|
1741
|
+
if (!this.isSoftKeyword("SUCCESS")) {
|
|
1742
|
+
throw new ParseError("EXIT \u306E\u5F8C\u306B\u306F SUCCESS \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
1743
|
+
}
|
|
1744
|
+
this.advance();
|
|
1745
|
+
if (this.peek().kind !== "IF" /* IF */ && !this.isSoftKeyword("IF")) {
|
|
1746
|
+
throw new ParseError("EXIT SUCCESS \u306E\u5F8C\u306B\u306F IF \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
1747
|
+
}
|
|
1748
|
+
this.advance();
|
|
1749
|
+
const condition = this.parseAssertCondition();
|
|
1750
|
+
if (!this.consume("," /* COMMA */)) {
|
|
1751
|
+
throw new ParseError("EXIT SUCCESS IF \u306B\u306F\u672B\u5C3E\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u6587\u5B57\u5217\u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
1752
|
+
}
|
|
1753
|
+
const message = this.expect("STRING" /* STRING */, "EXIT SUCCESS IF \u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
|
|
1754
|
+
return { type: "EXIT", ...condition, message: message.value };
|
|
1755
|
+
}
|
|
1756
|
+
parseAssertCondition() {
|
|
1694
1757
|
const condStart = this.pos;
|
|
1695
1758
|
const left = this.parseAssertOperand();
|
|
1696
1759
|
const opTok = this.peek();
|
|
@@ -1703,7 +1766,6 @@ var Parser = class {
|
|
|
1703
1766
|
const high = this.parseAssertOperand();
|
|
1704
1767
|
this.rejectAssertCompound();
|
|
1705
1768
|
return {
|
|
1706
|
-
type: "ASSERT",
|
|
1707
1769
|
left,
|
|
1708
1770
|
op: "BETWEEN",
|
|
1709
1771
|
right: null,
|
|
@@ -1722,7 +1784,6 @@ var Parser = class {
|
|
|
1722
1784
|
const right = this.parseAssertOperand();
|
|
1723
1785
|
this.rejectAssertCompound();
|
|
1724
1786
|
return {
|
|
1725
|
-
type: "ASSERT",
|
|
1726
1787
|
left,
|
|
1727
1788
|
op,
|
|
1728
1789
|
right,
|
|
@@ -1731,6 +1792,17 @@ var Parser = class {
|
|
|
1731
1792
|
text: this.renderTokenRange(condStart, this.pos)
|
|
1732
1793
|
};
|
|
1733
1794
|
}
|
|
1795
|
+
/** ASSERT の dialect 1 メッセージ。カンマが無ければ既存形式。 */
|
|
1796
|
+
parseFlowMessage() {
|
|
1797
|
+
if (!this.consume("," /* COMMA */)) return void 0;
|
|
1798
|
+
this.requireDialect1(this.prev());
|
|
1799
|
+
return this.expect("STRING" /* STRING */, "ASSERT \u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059").value;
|
|
1800
|
+
}
|
|
1801
|
+
requireDialect1(tok) {
|
|
1802
|
+
if (!this.capabilities.dialect1) {
|
|
1803
|
+
throw new ParseError("\u3053\u306E\u69CB\u6587\u306B\u306F -- @ksql dialect: 1 \u306E\u5BA3\u8A00\u304C\u5FC5\u8981\u3067\u3059", tok);
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1734
1806
|
/** ASSERT のオペランド: 文字列 / スカラーサブクエリ / 数値算術式 */
|
|
1735
1807
|
parseAssertOperand() {
|
|
1736
1808
|
const tok = this.peek();
|
|
@@ -3121,6 +3193,12 @@ var Parser = class {
|
|
|
3121
3193
|
);
|
|
3122
3194
|
}
|
|
3123
3195
|
const name = this.parseTableName();
|
|
3196
|
+
if (this.capabilities.dialect1 && this.bareTempTableNames.has(name)) {
|
|
3197
|
+
const normalizedName = `#${name}`;
|
|
3198
|
+
this.tempTableRefs.push({ ...this.prev(), value: normalizedName });
|
|
3199
|
+
const alias2 = this.consume("AS" /* AS */) ? this.parseTableAliasName() : this.tryParseImplicitAlias();
|
|
3200
|
+
return { appId: 0, alias: alias2, cteName: normalizedName };
|
|
3201
|
+
}
|
|
3124
3202
|
if (nameTok.kind === "IDENT" /* IDENT */ && name.startsWith("#")) {
|
|
3125
3203
|
this.tempTableRefs.push(this.prev());
|
|
3126
3204
|
const alias2 = this.consume("AS" /* AS */) ? this.parseTableAliasName() : this.tryParseImplicitAlias();
|
|
@@ -3161,6 +3239,7 @@ var Parser = class {
|
|
|
3161
3239
|
if (k === "IDENT" /* IDENT */ || k === "BIDENT" /* BIDENT */) {
|
|
3162
3240
|
if (k === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === "VALIDATE" && this.peekAt(1).kind === "IDENT" /* IDENT */ && this.peekAt(1).value.toUpperCase() === "ONLY") return null;
|
|
3163
3241
|
if (k === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === "CHECK" && this.peekAt(1).kind === "WHEN" /* WHEN */) return null;
|
|
3242
|
+
if (k === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === "KEY" && this.peekAt(1).kind === "(" /* LPAREN */) return null;
|
|
3164
3243
|
return this.parseTableAliasName();
|
|
3165
3244
|
}
|
|
3166
3245
|
return null;
|
|
@@ -4061,6 +4140,15 @@ var Parser = class {
|
|
|
4061
4140
|
};
|
|
4062
4141
|
}
|
|
4063
4142
|
parseOnDuplicate() {
|
|
4143
|
+
if (this.capabilities.dialect1 && this.consumeSoftKeyword("KEY")) {
|
|
4144
|
+
this.expect("(" /* LPAREN */, "KEY \u306E\u5F8C\u306B\u306F (\u30AD\u30FC\u30D5\u30A3\u30FC\u30EB\u30C9) \u304C\u5FC5\u8981\u3067\u3059");
|
|
4145
|
+
const keyFields2 = this.parseIdentList();
|
|
4146
|
+
this.expect(")" /* RPAREN */);
|
|
4147
|
+
if (keyFields2.length === 0) {
|
|
4148
|
+
throw new ParseError("KEY \u306B\u306F\u30AD\u30FC\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u6700\u4F4E 1 \u3064\u5FC5\u8981\u3067\u3059", this.prev());
|
|
4149
|
+
}
|
|
4150
|
+
return keyFields2;
|
|
4151
|
+
}
|
|
4064
4152
|
this.expectKeyword("ON" /* ON */, "UPSERT \u306B\u306F ON DUPLICATE (\u30AD\u30FC\u30D5\u30A3\u30FC\u30EB\u30C9) \u304C\u5FC5\u8981\u3067\u3059");
|
|
4065
4153
|
if (!this.consume("DUPLICATE" /* DUPLICATE */)) {
|
|
4066
4154
|
throw new ParseError("ON \u306E\u5F8C\u306B\u306F DUPLICATE \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
@@ -4073,6 +4161,238 @@ var Parser = class {
|
|
|
4073
4161
|
}
|
|
4074
4162
|
return keyFields;
|
|
4075
4163
|
}
|
|
4164
|
+
parseMergeAsUpsert() {
|
|
4165
|
+
const mergeToken = this.advance();
|
|
4166
|
+
this.expect("INTO" /* INTO */, "MERGE \u306E\u5F8C\u306B\u306F INTO \u304C\u5FC5\u8981\u3067\u3059");
|
|
4167
|
+
this.rejectTempTableDml();
|
|
4168
|
+
const targetName = this.parseIdentifier();
|
|
4169
|
+
const { appId, subtableCode } = extractTableRef(targetName, this.prev());
|
|
4170
|
+
if (subtableCode) {
|
|
4171
|
+
throw new ParseError("MERGE \u306F\u307E\u3060\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB\u4EEE\u60F3\u30C6\u30FC\u30D6\u30EB\u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093", this.prev());
|
|
4172
|
+
}
|
|
4173
|
+
this.expect("AS" /* AS */, "MERGE \u306E\u30BF\u30FC\u30B2\u30C3\u30C8\u306B\u306F AS alias \u304C\u5FC5\u8981\u3067\u3059");
|
|
4174
|
+
const targetAlias = this.parseTableAliasName();
|
|
4175
|
+
this.expectSoftKeyword("USING", "MERGE \u306B\u306F USING <source> AS alias \u304C\u5FC5\u8981\u3067\u3059");
|
|
4176
|
+
const sourceStart = this.pos;
|
|
4177
|
+
const source = this.parseTableRef();
|
|
4178
|
+
const explicitSourceAlias = this.tokens.slice(sourceStart, this.pos).some((token) => token.kind === "AS" /* AS */);
|
|
4179
|
+
if (!explicitSourceAlias || source.alias === null) {
|
|
4180
|
+
throw new ParseError("MERGE \u306E USING \u30BD\u30FC\u30B9\u306B\u306F AS alias \u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
4181
|
+
}
|
|
4182
|
+
const sourceAlias = source.alias;
|
|
4183
|
+
this.expect("ON" /* ON */, "MERGE \u306B\u306F ON t.key = s.key \u306E\u5358\u4E00\u30AD\u30FC\u7B49\u5024\u304C\u5FC5\u8981\u3067\u3059");
|
|
4184
|
+
const left = this.parseMergeQualifiedField("MERGE \u306E ON \u5DE6\u8FBA\u306F targetAlias.key \u306E\u5F62\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
4185
|
+
if (!this.consume("=" /* EQ */)) {
|
|
4186
|
+
throw new ParseError(
|
|
4187
|
+
"MERGE \u306E ON \u306F\u5358\u4E00\u30AD\u30FC\u306E\u7B49\u5024\uFF08t.key = s.key\uFF09\u306E\u307F\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u3059\u3002\u8907\u6570\u6761\u4EF6\u3084\u975E\u7B49\u5024\u306F\u9023\u7D50\u30AD\u30FC\u30D5\u30A3\u30FC\u30EB\u30C9\u3067\u7F6E\u304D\u63DB\u3048\u3066\u304F\u3060\u3055\u3044",
|
|
4188
|
+
this.peek()
|
|
4189
|
+
);
|
|
4190
|
+
}
|
|
4191
|
+
const right = this.parseMergeQualifiedField("MERGE \u306E ON \u53F3\u8FBA\u306F sourceAlias.key \u306E\u5F62\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
4192
|
+
if (left.alias.toLowerCase() !== targetAlias.toLowerCase() || right.alias.toLowerCase() !== sourceAlias.toLowerCase()) {
|
|
4193
|
+
throw new ParseError(
|
|
4194
|
+
`MERGE \u306E ON \u306F ${targetAlias}.key = ${sourceAlias}.key \u306E\u5225\u540D\u4FEE\u98FE\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
4195
|
+
mergeToken
|
|
4196
|
+
);
|
|
4197
|
+
}
|
|
4198
|
+
if (this.peek().kind === "AND" /* AND */ || this.peek().kind === "OR" /* OR */) {
|
|
4199
|
+
throw new ParseError(
|
|
4200
|
+
"MERGE \u306E ON \u306F\u5358\u4E00\u30AD\u30FC\u306E\u7B49\u5024\u306E\u307F\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u3059\u3002\u8907\u6570\u6761\u4EF6\u306F\u9023\u7D50\u30AD\u30FC\u30D5\u30A3\u30FC\u30EB\u30C9\u3067\u7F6E\u304D\u63DB\u3048\u3066\u304F\u3060\u3055\u3044",
|
|
4201
|
+
this.peek()
|
|
4202
|
+
);
|
|
4203
|
+
}
|
|
4204
|
+
let matched = null;
|
|
4205
|
+
let insertFields = null;
|
|
4206
|
+
let insertValues = null;
|
|
4207
|
+
while (this.peek().kind === "WHEN" /* WHEN */) {
|
|
4208
|
+
const whenToken = this.advance();
|
|
4209
|
+
if (this.consume("NOT" /* NOT */)) {
|
|
4210
|
+
this.expectSoftKeyword("MATCHED", "WHEN NOT \u306E\u5F8C\u306B\u306F MATCHED \u304C\u5FC5\u8981\u3067\u3059");
|
|
4211
|
+
if (insertFields !== null) throw new ParseError("WHEN NOT MATCHED \u53E5\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059", whenToken);
|
|
4212
|
+
this.expect("THEN" /* THEN */, "WHEN NOT MATCHED \u306E\u5F8C\u306B\u306F THEN \u304C\u5FC5\u8981\u3067\u3059");
|
|
4213
|
+
this.expect("INSERT" /* INSERT */, "WHEN NOT MATCHED THEN \u306E\u5F8C\u306B\u306F INSERT \u304C\u5FC5\u8981\u3067\u3059");
|
|
4214
|
+
this.expect("(" /* LPAREN */, "MERGE INSERT \u306B\u306F\u5217\u30EA\u30B9\u30C8\u304C\u5FC5\u8981\u3067\u3059");
|
|
4215
|
+
insertFields = this.parseIdentList();
|
|
4216
|
+
this.expect(")" /* RPAREN */);
|
|
4217
|
+
this.expect("VALUES" /* VALUES */, "MERGE INSERT \u306E\u5217\u30EA\u30B9\u30C8\u306E\u5F8C\u306B\u306F VALUES \u304C\u5FC5\u8981\u3067\u3059");
|
|
4218
|
+
this.expect("(" /* LPAREN */, "MERGE INSERT VALUES \u306F ( \u3067\u59CB\u3081\u3066\u304F\u3060\u3055\u3044");
|
|
4219
|
+
insertValues = this.parseMergeValueList();
|
|
4220
|
+
this.expect(")" /* RPAREN */);
|
|
4221
|
+
if (insertFields.length !== insertValues.length) {
|
|
4222
|
+
throw new ParseError("MERGE INSERT \u306E\u5217\u6570\u3068 VALUES \u306E\u5024\u6570\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093", whenToken);
|
|
4223
|
+
}
|
|
4224
|
+
} else {
|
|
4225
|
+
this.expectSoftKeyword("MATCHED", "WHEN \u306E\u5F8C\u306B\u306F MATCHED \u307E\u305F\u306F NOT MATCHED \u304C\u5FC5\u8981\u3067\u3059");
|
|
4226
|
+
if (matched !== null) throw new ParseError("WHEN MATCHED \u53E5\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059", whenToken);
|
|
4227
|
+
this.expect("THEN" /* THEN */, "WHEN MATCHED \u306E\u5F8C\u306B\u306F THEN \u304C\u5FC5\u8981\u3067\u3059");
|
|
4228
|
+
this.expect("UPDATE" /* UPDATE */, "WHEN MATCHED THEN \u306E\u5F8C\u306B\u306F UPDATE \u304C\u5FC5\u8981\u3067\u3059");
|
|
4229
|
+
this.expect("SET" /* SET */, "WHEN MATCHED THEN UPDATE \u306E\u5F8C\u306B\u306F SET \u304C\u5FC5\u8981\u3067\u3059");
|
|
4230
|
+
matched = this.parseMergeAssignments(targetAlias);
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
4233
|
+
if (matched === null || insertFields === null || insertValues === null) {
|
|
4234
|
+
throw new ParseError(
|
|
4235
|
+
"WHEN MATCHED / WHEN NOT MATCHED \u306E\u4E21\u53E5\u304C\u5FC5\u8981\u3067\u3059\uFF08\u66F4\u65B0\u306E\u307F\u306F UPDATE ... FROM\u3001\u633F\u5165\u306E\u307F\u306F INSERT ... SELECT \u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\uFF09",
|
|
4236
|
+
this.peek()
|
|
4237
|
+
);
|
|
4238
|
+
}
|
|
4239
|
+
if (!insertFields.some((field) => field.toLowerCase() === left.field.toLowerCase())) {
|
|
4240
|
+
throw new ParseError(
|
|
4241
|
+
`MERGE \u306E ON \u30AD\u30FC ${left.field} \u306F INSERT \u5217\u30EA\u30B9\u30C8\u306B\u542B\u3081\u3066\u304F\u3060\u3055\u3044`,
|
|
4242
|
+
mergeToken
|
|
4243
|
+
);
|
|
4244
|
+
}
|
|
4245
|
+
const expressions = /* @__PURE__ */ new Map();
|
|
4246
|
+
insertFields.forEach((field, index) => expressions.set(field.toLowerCase(), insertValues[index]));
|
|
4247
|
+
for (const assignment of matched) {
|
|
4248
|
+
const key = assignment.field.toLowerCase();
|
|
4249
|
+
const existing = expressions.get(key);
|
|
4250
|
+
if (existing !== void 0 && !this.mergeExpressionsEqual(existing, assignment.value, sourceAlias)) {
|
|
4251
|
+
throw new ParseError(
|
|
4252
|
+
`MERGE \u306E\u5217 ${assignment.field} \u306F\u4E21\u53E5\u306E\u5F0F\u304C\u4E00\u81F4\u3059\u308B\u5834\u5408\u306E\u307F MERGE \u3092 UPSERT \u3078\u6B63\u898F\u5316\u3067\u304D\u307E\u3059`,
|
|
4253
|
+
mergeToken
|
|
4254
|
+
);
|
|
4255
|
+
}
|
|
4256
|
+
if (existing === void 0) {
|
|
4257
|
+
insertFields.push(assignment.field);
|
|
4258
|
+
insertValues.push(assignment.value);
|
|
4259
|
+
expressions.set(key, assignment.value);
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
const columns = insertValues.map((value) => this.mergeValueToSelectColumn(value, sourceAlias, mergeToken));
|
|
4263
|
+
const normalizedSource = source.cteName !== null ? { ...source, alias: null } : { ...source, alias: `APP${source.appId}${source.subtableCode ? `$${source.subtableCode}` : ""}` };
|
|
4264
|
+
const select = {
|
|
4265
|
+
type: "SELECT",
|
|
4266
|
+
distinct: false,
|
|
4267
|
+
columns,
|
|
4268
|
+
from: normalizedSource,
|
|
4269
|
+
joins: [],
|
|
4270
|
+
where: null,
|
|
4271
|
+
groupBy: [],
|
|
4272
|
+
having: null,
|
|
4273
|
+
orderMode: "CANONICAL",
|
|
4274
|
+
orderBy: [],
|
|
4275
|
+
limit: null,
|
|
4276
|
+
offset: null
|
|
4277
|
+
};
|
|
4278
|
+
const checkGroups = this.parseCheckGroups();
|
|
4279
|
+
const validation = this.parseDmlControlSuffix();
|
|
4280
|
+
return {
|
|
4281
|
+
type: "UPSERT_SELECT",
|
|
4282
|
+
appId,
|
|
4283
|
+
fields: insertFields,
|
|
4284
|
+
select,
|
|
4285
|
+
keyFields: [left.field],
|
|
4286
|
+
...checkGroups,
|
|
4287
|
+
...validation
|
|
4288
|
+
};
|
|
4289
|
+
}
|
|
4290
|
+
parseMergeQualifiedField(message) {
|
|
4291
|
+
const token = this.peek();
|
|
4292
|
+
const path = this.parseFieldPath();
|
|
4293
|
+
const ref = this.splitQualifiedField(path);
|
|
4294
|
+
if (ref.alias === null) throw new ParseError(message, token);
|
|
4295
|
+
return { alias: ref.alias, field: ref.field };
|
|
4296
|
+
}
|
|
4297
|
+
parseMergeAssignments(targetAlias) {
|
|
4298
|
+
const assignments = [];
|
|
4299
|
+
do {
|
|
4300
|
+
const token = this.peek();
|
|
4301
|
+
const path = this.parseFieldPath();
|
|
4302
|
+
const ref = this.splitQualifiedField(path);
|
|
4303
|
+
if (ref.alias !== null && ref.alias.toLowerCase() !== targetAlias.toLowerCase()) {
|
|
4304
|
+
throw new ParseError(`MERGE UPDATE SET \u306E\u5DE6\u8FBA\u306F target alias ${targetAlias} \u3067\u4FEE\u98FE\u3057\u3066\u304F\u3060\u3055\u3044`, token);
|
|
4305
|
+
}
|
|
4306
|
+
this.expect("=" /* EQ */);
|
|
4307
|
+
assignments.push({ field: ref.field, value: this.parseAssignmentValue() });
|
|
4308
|
+
} while (this.consume("," /* COMMA */));
|
|
4309
|
+
return assignments;
|
|
4310
|
+
}
|
|
4311
|
+
parseMergeValueList() {
|
|
4312
|
+
const values = [];
|
|
4313
|
+
if (this.peek().kind === ")" /* RPAREN */) return values;
|
|
4314
|
+
do
|
|
4315
|
+
values.push(this.parseAssignmentValue());
|
|
4316
|
+
while (this.consume("," /* COMMA */));
|
|
4317
|
+
return values;
|
|
4318
|
+
}
|
|
4319
|
+
mergeExpressionsEqual(left, right, sourceAlias) {
|
|
4320
|
+
return this.mergeNormalizedValueEqual(
|
|
4321
|
+
this.normalizeMergeValue(left, sourceAlias, true),
|
|
4322
|
+
this.normalizeMergeValue(right, sourceAlias, true)
|
|
4323
|
+
);
|
|
4324
|
+
}
|
|
4325
|
+
normalizeMergeValue(value, sourceAlias, compareLiteralValues = false) {
|
|
4326
|
+
if (Array.isArray(value)) {
|
|
4327
|
+
return value.map((item) => this.normalizeMergeValue(item, sourceAlias, compareLiteralValues));
|
|
4328
|
+
}
|
|
4329
|
+
if (value === null || typeof value !== "object") return value;
|
|
4330
|
+
const obj = value;
|
|
4331
|
+
if (compareLiteralValues && obj["type"] === "NUMBER") {
|
|
4332
|
+
return { type: "NUMBER", value: obj["value"] };
|
|
4333
|
+
}
|
|
4334
|
+
if (obj["type"] === "SOURCE_FIELD") {
|
|
4335
|
+
if (String(obj["alias"]).toLowerCase() !== sourceAlias.toLowerCase()) return { type: "INVALID_SOURCE" };
|
|
4336
|
+
return { type: "FIELD_REF", field: obj["field"] };
|
|
4337
|
+
}
|
|
4338
|
+
if (obj["type"] === "FIELD_REF" && typeof obj["field"] === "string") {
|
|
4339
|
+
const ref = this.splitQualifiedField(obj["field"]);
|
|
4340
|
+
if (ref.alias !== null && ref.alias.toLowerCase() !== sourceAlias.toLowerCase()) return { type: "INVALID_SOURCE" };
|
|
4341
|
+
return { ...obj, field: ref.field };
|
|
4342
|
+
}
|
|
4343
|
+
if (obj["type"] === "FIELD" && typeof obj["tableAlias"] === "string") {
|
|
4344
|
+
if (obj["tableAlias"].toLowerCase() !== sourceAlias.toLowerCase()) return { type: "INVALID_SOURCE" };
|
|
4345
|
+
return { ...obj, tableAlias: null };
|
|
4346
|
+
}
|
|
4347
|
+
return Object.fromEntries(Object.entries(obj).map(([key, child]) => [
|
|
4348
|
+
key,
|
|
4349
|
+
this.normalizeMergeValue(child, sourceAlias, compareLiteralValues)
|
|
4350
|
+
]));
|
|
4351
|
+
}
|
|
4352
|
+
mergeNormalizedValueEqual(left, right) {
|
|
4353
|
+
if (left === right) return true;
|
|
4354
|
+
if (Array.isArray(left) || Array.isArray(right)) {
|
|
4355
|
+
return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((item, index) => this.mergeNormalizedValueEqual(item, right[index]));
|
|
4356
|
+
}
|
|
4357
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object") return false;
|
|
4358
|
+
const leftObj = left;
|
|
4359
|
+
const rightObj = right;
|
|
4360
|
+
const leftKeys = Object.keys(leftObj);
|
|
4361
|
+
const rightKeys = Object.keys(rightObj);
|
|
4362
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key) => Object.prototype.hasOwnProperty.call(rightObj, key) && this.mergeNormalizedValueEqual(leftObj[key], rightObj[key]));
|
|
4363
|
+
}
|
|
4364
|
+
mergeValueToSelectColumn(value, sourceAlias, token) {
|
|
4365
|
+
const normalized = this.normalizeMergeValue(value, sourceAlias);
|
|
4366
|
+
if (this.mergeValueContainsInvalidSource(normalized)) {
|
|
4367
|
+
throw new ParseError(`MERGE \u306E\u5F0F\u306F source alias ${sourceAlias} \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u3060\u3051\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044`, token);
|
|
4368
|
+
}
|
|
4369
|
+
const expr = normalized;
|
|
4370
|
+
switch (expr["type"]) {
|
|
4371
|
+
case "FIELD_REF":
|
|
4372
|
+
return { type: "FIELD", field: String(expr["field"]), alias: null };
|
|
4373
|
+
case "STRING":
|
|
4374
|
+
return { type: "LITERAL_COL", value: String(expr["value"]), alias: null };
|
|
4375
|
+
case "NUMBER":
|
|
4376
|
+
return { type: "ARITH_COL", expr, alias: null };
|
|
4377
|
+
case "ARITH":
|
|
4378
|
+
return { type: "ARITH_COL", expr, alias: null };
|
|
4379
|
+
case "STRING_FUNC":
|
|
4380
|
+
return { type: "STRFUNC_COL", expr, alias: null };
|
|
4381
|
+
case "CASE_VALUE":
|
|
4382
|
+
return { type: "CASE_COL", expr: expr["expr"], alias: null };
|
|
4383
|
+
default:
|
|
4384
|
+
throw new ParseError(
|
|
4385
|
+
"MERGE \u306E\u4EE3\u5165\u5F0F\u306F\u30BD\u30FC\u30B9\u30D5\u30A3\u30FC\u30EB\u30C9\u30FB\u30EA\u30C6\u30E9\u30EB\u30FB\u7B97\u8853\u5F0F\u30FB\u6587\u5B57\u5217\u95A2\u6570\u30FBCASE \u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
4386
|
+
token
|
|
4387
|
+
);
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4390
|
+
mergeValueContainsInvalidSource(value) {
|
|
4391
|
+
if (Array.isArray(value)) return value.some((item) => this.mergeValueContainsInvalidSource(item));
|
|
4392
|
+
if (value === null || typeof value !== "object") return false;
|
|
4393
|
+
const obj = value;
|
|
4394
|
+
return obj["type"] === "INVALID_SOURCE" || Object.values(obj).some((item) => this.mergeValueContainsInvalidSource(item));
|
|
4395
|
+
}
|
|
4076
4396
|
isUpsertApplyBranchStart() {
|
|
4077
4397
|
return this.peek().kind === "ON" /* ON */ && (this.peekAt(1).kind === "INSERT" /* INSERT */ || this.peekAt(1).kind === "UPDATE" /* UPDATE */);
|
|
4078
4398
|
}
|
|
@@ -4889,7 +5209,7 @@ function isDmlType(type) {
|
|
|
4889
5209
|
return type === "INSERT" || type === "INSERT_SELECT" || type === "UPDATE" || type === "DELETE" || type === "UPSERT" || type === "UPSERT_SELECT" || type === "REORDER" || type === "IMPORT";
|
|
4890
5210
|
}
|
|
4891
5211
|
function isReadOnlyType(type) {
|
|
4892
|
-
return type === "SELECT" || type === "VALIDATE" || type === "UNION" || type === "WITH" || type === "EXPLAIN" || type === "SHOW_APPS" || type === "DESCRIBE" || type === "CREATE_TEMP_TABLE" || type === "DROP_TEMP_TABLE" || type === "SET_VARIABLE" || type === "DECLARE_VARIABLE" || type === "ASSERT";
|
|
5212
|
+
return type === "SELECT" || type === "VALIDATE" || type === "UNION" || type === "WITH" || type === "EXPLAIN" || type === "SHOW_APPS" || type === "DESCRIBE" || type === "CREATE_TEMP_TABLE" || type === "DROP_TEMP_TABLE" || type === "SET_VARIABLE" || type === "DECLARE_VARIABLE" || type === "ASSERT" || type === "EXIT";
|
|
4893
5213
|
}
|
|
4894
5214
|
function writesKintone(stmt) {
|
|
4895
5215
|
return isDmlType(stmt.type) && !("validateOnly" in stmt && stmt.validateOnly === true);
|
|
@@ -8259,6 +8579,7 @@ function validateStatement(stmt) {
|
|
|
8259
8579
|
case "SET_VARIABLE":
|
|
8260
8580
|
case "DECLARE_VARIABLE":
|
|
8261
8581
|
case "ASSERT":
|
|
8582
|
+
case "EXIT":
|
|
8262
8583
|
validateNestedSelects(stmt);
|
|
8263
8584
|
return;
|
|
8264
8585
|
case "UPDATE":
|
|
@@ -9376,15 +9697,15 @@ function selectScalarExtreme(values, extreme) {
|
|
|
9376
9697
|
}
|
|
9377
9698
|
|
|
9378
9699
|
// src/engine/evalFunc.ts
|
|
9379
|
-
function evalArithExpr(expr, row) {
|
|
9700
|
+
function evalArithExpr(expr, row, context = {}) {
|
|
9380
9701
|
if (expr.type === "VARIABLE") throw new Error(
|
|
9381
9702
|
`InternalError: unresolved arithmetic variable @${expr.name} reached arithmetic evaluation.`
|
|
9382
9703
|
);
|
|
9383
9704
|
if (expr.type === "NUMBER") return expr.value;
|
|
9384
9705
|
if (expr.type === "FIELD_REF") return Number(resolveFieldRef(row, expr.field));
|
|
9385
|
-
if (expr.type === "STRING_FUNC") return Number(evalStringFunc(expr, row));
|
|
9386
|
-
const l = evalArithExpr(expr.left, row);
|
|
9387
|
-
const r = evalArithExpr(expr.right, row);
|
|
9706
|
+
if (expr.type === "STRING_FUNC") return Number(evalStringFunc(expr, row, void 0, void 0, context));
|
|
9707
|
+
const l = evalArithExpr(expr.left, row, context);
|
|
9708
|
+
const r = evalArithExpr(expr.right, row, context);
|
|
9388
9709
|
switch (expr.op) {
|
|
9389
9710
|
case "+":
|
|
9390
9711
|
return l + r;
|
|
@@ -9398,7 +9719,7 @@ function evalArithExpr(expr, row) {
|
|
|
9398
9719
|
return r !== 0 ? l % r : NaN;
|
|
9399
9720
|
}
|
|
9400
9721
|
}
|
|
9401
|
-
function evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
9722
|
+
function evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
9402
9723
|
switch (expr.type) {
|
|
9403
9724
|
case "STRING":
|
|
9404
9725
|
return expr.value;
|
|
@@ -9409,19 +9730,19 @@ function evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2
|
|
|
9409
9730
|
case "VARIABLE":
|
|
9410
9731
|
throw new Error(`ArgumentError: unresolved variable @${expr.name} reached scalar evaluator.`);
|
|
9411
9732
|
case "STRING_FUNC":
|
|
9412
|
-
return evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
9733
|
+
return evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9413
9734
|
case "CASE_WHEN":
|
|
9414
|
-
return evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
9735
|
+
return evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9415
9736
|
case "CONCAT_OP": {
|
|
9416
9737
|
return evalStringFunc({
|
|
9417
9738
|
type: "STRING_FUNC",
|
|
9418
9739
|
func: "CONCAT",
|
|
9419
9740
|
args: [expr.left, expr.right]
|
|
9420
|
-
}, row, resolveFieldType, resolveFieldSemantics2);
|
|
9741
|
+
}, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9421
9742
|
}
|
|
9422
9743
|
case "SCALAR_ARITH": {
|
|
9423
|
-
const left = Number(evalScalarValueExpr(expr.left, row, resolveFieldType, resolveFieldSemantics2));
|
|
9424
|
-
const right = Number(evalScalarValueExpr(expr.right, row, resolveFieldType, resolveFieldSemantics2));
|
|
9744
|
+
const left = Number(evalScalarValueExpr(expr.left, row, resolveFieldType, resolveFieldSemantics2, context));
|
|
9745
|
+
const right = Number(evalScalarValueExpr(expr.right, row, resolveFieldType, resolveFieldSemantics2, context));
|
|
9425
9746
|
switch (expr.op) {
|
|
9426
9747
|
case "+":
|
|
9427
9748
|
return left + right;
|
|
@@ -9437,13 +9758,13 @@ function evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2
|
|
|
9437
9758
|
}
|
|
9438
9759
|
}
|
|
9439
9760
|
}
|
|
9440
|
-
function evalScalarValueExprNullable(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
9761
|
+
function evalScalarValueExprNullable(expr, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
9441
9762
|
switch (expr.type) {
|
|
9442
9763
|
case "CASE_WHEN":
|
|
9443
|
-
return evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
9764
|
+
return evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9444
9765
|
case "SCALAR_ARITH": {
|
|
9445
|
-
const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2);
|
|
9446
|
-
const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2);
|
|
9766
|
+
const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9767
|
+
const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9447
9768
|
if (left === null || right === null) return null;
|
|
9448
9769
|
const l = Number(left);
|
|
9449
9770
|
const r = Number(right);
|
|
@@ -9461,12 +9782,12 @@ function evalScalarValueExprNullable(expr, row, resolveFieldType, resolveFieldSe
|
|
|
9461
9782
|
}
|
|
9462
9783
|
}
|
|
9463
9784
|
case "CONCAT_OP": {
|
|
9464
|
-
const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2);
|
|
9465
|
-
const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2);
|
|
9785
|
+
const left = evalScalarValueExprNullable(expr.left, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9786
|
+
const right = evalScalarValueExprNullable(expr.right, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9466
9787
|
return `${left ?? ""}${right ?? ""}`;
|
|
9467
9788
|
}
|
|
9468
9789
|
default:
|
|
9469
|
-
return evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
9790
|
+
return evalScalarValueExpr(expr, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
9470
9791
|
}
|
|
9471
9792
|
}
|
|
9472
9793
|
function applyRoundOp(op, num, digits) {
|
|
@@ -9618,9 +9939,9 @@ function replaceNthMatch(input, globalRe, replacement, n) {
|
|
|
9618
9939
|
return expandRegexpReplacement(replacement, match, captures, namedGroups);
|
|
9619
9940
|
});
|
|
9620
9941
|
}
|
|
9621
|
-
function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
9942
|
+
function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
9622
9943
|
assertStringFunctionArity(expr.func, expr.args);
|
|
9623
|
-
const args = expr.args.map((a) => evalStringFuncArg(a, row, resolveFieldType, resolveFieldSemantics2));
|
|
9944
|
+
const args = expr.args.map((a) => evalStringFuncArg(a, row, resolveFieldType, resolveFieldSemantics2, context));
|
|
9624
9945
|
switch (expr.func) {
|
|
9625
9946
|
case "UPPER":
|
|
9626
9947
|
return (args[0] ?? "").toUpperCase();
|
|
@@ -9768,14 +10089,14 @@ function evalStringFunc(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
9768
10089
|
case "SQRT":
|
|
9769
10090
|
return String(Math.sqrt(Number(args[0] ?? "0")));
|
|
9770
10091
|
case "CURRENT_DATE": {
|
|
9771
|
-
const now = /* @__PURE__ */ new Date();
|
|
10092
|
+
const now = context.statementInstant ?? /* @__PURE__ */ new Date();
|
|
9772
10093
|
const y = now.getFullYear();
|
|
9773
10094
|
const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
9774
10095
|
const d = String(now.getDate()).padStart(2, "0");
|
|
9775
10096
|
return `${y}-${m}-${d}`;
|
|
9776
10097
|
}
|
|
9777
10098
|
case "CURRENT_TIMESTAMP":
|
|
9778
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
10099
|
+
return (context.statementInstant ?? /* @__PURE__ */ new Date()).toISOString();
|
|
9779
10100
|
}
|
|
9780
10101
|
}
|
|
9781
10102
|
function parseDateParts(s) {
|
|
@@ -9937,12 +10258,12 @@ function formatWithComma(num, digits) {
|
|
|
9937
10258
|
const intFmt = intStr.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
9938
10259
|
return decStr ? `${intFmt}.${decStr}` : intFmt;
|
|
9939
10260
|
}
|
|
9940
|
-
function evalStringFuncArg(arg, row, resolveFieldType, resolveFieldSemantics2) {
|
|
10261
|
+
function evalStringFuncArg(arg, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
9941
10262
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH" || arg.type === "AGG_GROUP_KEY") {
|
|
9942
10263
|
return String(evalMaterializedAggregateOperand(arg, row));
|
|
9943
10264
|
}
|
|
9944
10265
|
if (arg.type === "NUMBER") return numberLiteralText(arg);
|
|
9945
|
-
return String(evalScalarValueExpr(arg, row, resolveFieldType, resolveFieldSemantics2));
|
|
10266
|
+
return String(evalScalarValueExpr(arg, row, resolveFieldType, resolveFieldSemantics2, context));
|
|
9946
10267
|
}
|
|
9947
10268
|
function evalMaterializedAggregateOperand(node, row) {
|
|
9948
10269
|
if (node.type === "NUMBER") return node.value;
|
|
@@ -9983,37 +10304,37 @@ function resolveFieldRef(row, field) {
|
|
|
9983
10304
|
}
|
|
9984
10305
|
|
|
9985
10306
|
// src/engine/evalWhere.ts
|
|
9986
|
-
function evalWhere(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2) {
|
|
10307
|
+
function evalWhere(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context = {}) {
|
|
9987
10308
|
switch (expr.type) {
|
|
9988
10309
|
case "BOOLEAN":
|
|
9989
10310
|
return expr.value;
|
|
9990
10311
|
case "BINARY":
|
|
9991
|
-
return evalBinary(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2);
|
|
10312
|
+
return evalBinary(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context);
|
|
9992
10313
|
case "NULL_CHECK":
|
|
9993
10314
|
return evalNullCheck(expr, row);
|
|
9994
10315
|
case "LOGICAL":
|
|
9995
|
-
return evalLogical(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2);
|
|
10316
|
+
return evalLogical(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context);
|
|
9996
10317
|
case "NOT":
|
|
9997
|
-
return !evalWhere(expr.expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2);
|
|
10318
|
+
return !evalWhere(expr.expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context);
|
|
9998
10319
|
case "GROUP":
|
|
9999
|
-
return evalWhere(expr.expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2);
|
|
10320
|
+
return evalWhere(expr.expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context);
|
|
10000
10321
|
case "EXISTS": {
|
|
10001
10322
|
const exists = expr.resolved;
|
|
10002
10323
|
return expr.not ? !exists : exists;
|
|
10003
10324
|
}
|
|
10004
10325
|
}
|
|
10005
10326
|
}
|
|
10006
|
-
function evalBinary(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2) {
|
|
10327
|
+
function evalBinary(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context = {}) {
|
|
10007
10328
|
if (expr.op === "KLIKE" || expr.op === "NOT_KLIKE") {
|
|
10008
10329
|
if (appliedKlikes?.has(expr)) return true;
|
|
10009
10330
|
throw new Error("KLIKE / NOT KLIKE \u306F\u62BC\u3057\u4E0B\u3052\u6E08\u307F\u96C6\u5408\u306B\u542B\u307E\u308C\u306A\u3044\u305F\u3081 JavaScript \u5074\u3067\u306F\u8A55\u4FA1\u3067\u304D\u307E\u305B\u3093");
|
|
10010
10331
|
}
|
|
10011
|
-
const left = resolveField(expr.left, row, resolveFieldType, resolveFieldSemantics2);
|
|
10332
|
+
const left = resolveField(expr.left, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10012
10333
|
const fieldType = expr.left.type === "FIELD" ? resolveFieldType?.(expr.left) : void 0;
|
|
10013
10334
|
const semantics = semanticsForLeft(expr.left, fieldType, resolveFieldSemantics2);
|
|
10014
|
-
return evalOp(expr.op, left, expr.right, row, fieldType, resolveFieldType, semantics, resolveFieldSemantics2);
|
|
10335
|
+
return evalOp(expr.op, left, expr.right, row, fieldType, resolveFieldType, semantics, resolveFieldSemantics2, context);
|
|
10015
10336
|
}
|
|
10016
|
-
function evalOp(op, leftStr, right, row, fieldType, resolveFieldType, semantics = syntheticSemantics("string"), resolveFieldSemantics2) {
|
|
10337
|
+
function evalOp(op, leftStr, right, row, fieldType, resolveFieldType, semantics = syntheticSemantics("string"), resolveFieldSemantics2, context = {}) {
|
|
10017
10338
|
if (op === "IN" || op === "NOT_IN") {
|
|
10018
10339
|
let values = null;
|
|
10019
10340
|
if (right.type === "IN_LIST") {
|
|
@@ -10028,17 +10349,17 @@ function evalOp(op, leftStr, right, row, fieldType, resolveFieldType, semantics
|
|
|
10028
10349
|
return op === "IN" ? contains : !contains;
|
|
10029
10350
|
}
|
|
10030
10351
|
if (op === "LIKE") {
|
|
10031
|
-
const pattern = resolveValue(right, row, resolveFieldType);
|
|
10352
|
+
const pattern = resolveValue(right, row, resolveFieldType, void 0, context);
|
|
10032
10353
|
return matchLike(leftStr, pattern);
|
|
10033
10354
|
}
|
|
10034
10355
|
if (op === "NOT_LIKE") {
|
|
10035
|
-
const pattern = resolveValue(right, row, resolveFieldType);
|
|
10356
|
+
const pattern = resolveValue(right, row, resolveFieldType, void 0, context);
|
|
10036
10357
|
return !matchLike(leftStr, pattern);
|
|
10037
10358
|
}
|
|
10038
10359
|
if (op === "KLIKE" || op === "NOT_KLIKE") {
|
|
10039
10360
|
throw new Error("KLIKE / NOT KLIKE \u306F JavaScript \u5074\u3067\u306F\u8A55\u4FA1\u3067\u304D\u307E\u305B\u3093\uFF08SIMPLE SELECT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059\uFF09");
|
|
10040
10361
|
}
|
|
10041
|
-
const rightStr = resolveValue(right, row, resolveFieldType, resolveFieldSemantics2);
|
|
10362
|
+
const rightStr = resolveValue(right, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10042
10363
|
return compareScalarValues(op, leftStr, rightStr, semantics);
|
|
10043
10364
|
}
|
|
10044
10365
|
var NUMERIC_STRING_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
@@ -10150,17 +10471,17 @@ function evalNullCheck(expr, row) {
|
|
|
10150
10471
|
const val = resolveField(expr.field, row);
|
|
10151
10472
|
return expr.not ? val !== "" : val === "";
|
|
10152
10473
|
}
|
|
10153
|
-
function evalLogical(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2) {
|
|
10474
|
+
function evalLogical(expr, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context = {}) {
|
|
10154
10475
|
if (expr.op === "AND") {
|
|
10155
|
-
return evalWhere(expr.left, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2) && evalWhere(expr.right, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2);
|
|
10476
|
+
return evalWhere(expr.left, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context) && evalWhere(expr.right, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context);
|
|
10156
10477
|
}
|
|
10157
|
-
return evalWhere(expr.left, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2) || evalWhere(expr.right, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2);
|
|
10478
|
+
return evalWhere(expr.left, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context) || evalWhere(expr.right, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2, context);
|
|
10158
10479
|
}
|
|
10159
|
-
function resolveField(field, row, resolveFieldType, resolveFieldSemantics2) {
|
|
10160
|
-
if (field.type === "FUNC_FIELD") return evalStringFunc(field.expr, row);
|
|
10480
|
+
function resolveField(field, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
10481
|
+
if (field.type === "FUNC_FIELD") return evalStringFunc(field.expr, row, void 0, void 0, context);
|
|
10161
10482
|
if (field.type === "AGG_FIELD") return String(evalMaterializedAggregateOperand(field.expr, row));
|
|
10162
|
-
if (field.type === "ARITH_FIELD") return String(evalArithExpr(field.expr, row));
|
|
10163
|
-
if (field.type === "CASE_FIELD") return evalCaseWhen(field.expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
10483
|
+
if (field.type === "ARITH_FIELD") return String(evalArithExpr(field.expr, row, context));
|
|
10484
|
+
if (field.type === "CASE_FIELD") return evalCaseWhen(field.expr, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10164
10485
|
if (field.type === "GROUPING_FIELD") return evalGroupingRef(field.ref, row);
|
|
10165
10486
|
if (field.aggregateRef) {
|
|
10166
10487
|
const ref = field.aggregateRef;
|
|
@@ -10169,7 +10490,7 @@ function resolveField(field, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
10169
10490
|
const key = field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
|
|
10170
10491
|
return resolveFieldRef(row, key);
|
|
10171
10492
|
}
|
|
10172
|
-
function resolveValue(value, row, resolveFieldType, resolveFieldSemantics2) {
|
|
10493
|
+
function resolveValue(value, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
10173
10494
|
switch (value.type) {
|
|
10174
10495
|
case "VARIABLE":
|
|
10175
10496
|
throw new Error(`ParseError: unresolved batch variable @${value.name}.`);
|
|
@@ -10191,44 +10512,44 @@ function resolveValue(value, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
10191
10512
|
return value.resolved;
|
|
10192
10513
|
case "ARITH_VALUE":
|
|
10193
10514
|
if (value.expr.type === "FIELD_REF") return resolveFieldRef(row, value.expr.field);
|
|
10194
|
-
if (value.expr.type === "STRING_FUNC") return evalStringFunc(value.expr, row);
|
|
10195
|
-
return String(evalArithExpr(value.expr, row));
|
|
10515
|
+
if (value.expr.type === "STRING_FUNC") return evalStringFunc(value.expr, row, void 0, void 0, context);
|
|
10516
|
+
return String(evalArithExpr(value.expr, row, context));
|
|
10196
10517
|
case "CASE_VALUE":
|
|
10197
|
-
return evalCaseWhen(value.expr, row, resolveFieldType, resolveFieldSemantics2);
|
|
10518
|
+
return evalCaseWhen(value.expr, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10198
10519
|
case "ARRAY":
|
|
10199
10520
|
return value.elements.map((e) => e.value).join(",");
|
|
10200
10521
|
}
|
|
10201
10522
|
}
|
|
10202
|
-
function evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
10523
|
+
function evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
10203
10524
|
for (const branch of expr.branches) {
|
|
10204
|
-
if (evalWhere(branch.condition, row, resolveFieldType, void 0, resolveFieldSemantics2)) {
|
|
10205
|
-
return evalCaseResult(branch.result, row, resolveFieldType, resolveFieldSemantics2);
|
|
10525
|
+
if (evalWhere(branch.condition, row, resolveFieldType, void 0, resolveFieldSemantics2, context)) {
|
|
10526
|
+
return evalCaseResult(branch.result, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10206
10527
|
}
|
|
10207
10528
|
}
|
|
10208
10529
|
if (expr.elseResult !== null) {
|
|
10209
|
-
return evalCaseResult(expr.elseResult, row, resolveFieldType, resolveFieldSemantics2);
|
|
10530
|
+
return evalCaseResult(expr.elseResult, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10210
10531
|
}
|
|
10211
10532
|
return "";
|
|
10212
10533
|
}
|
|
10213
|
-
function evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
10534
|
+
function evalCaseWhenNullable(expr, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
10214
10535
|
for (const branch of expr.branches) {
|
|
10215
|
-
if (evalWhere(branch.condition, row, resolveFieldType, void 0, resolveFieldSemantics2)) {
|
|
10216
|
-
return evalCaseResultNullable(branch.result, row, resolveFieldType, resolveFieldSemantics2);
|
|
10536
|
+
if (evalWhere(branch.condition, row, resolveFieldType, void 0, resolveFieldSemantics2, context)) {
|
|
10537
|
+
return evalCaseResultNullable(branch.result, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10217
10538
|
}
|
|
10218
10539
|
}
|
|
10219
|
-
return expr.elseResult === null ? null : evalCaseResultNullable(expr.elseResult, row, resolveFieldType, resolveFieldSemantics2);
|
|
10540
|
+
return expr.elseResult === null ? null : evalCaseResultNullable(expr.elseResult, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10220
10541
|
}
|
|
10221
|
-
function evalCaseResultNullable(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
10542
|
+
function evalCaseResultNullable(result, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
10222
10543
|
if (result.type === "ARRAY") return result.elements.map((entry) => entry.value).join(",");
|
|
10223
10544
|
if (result.type === "AGG_REF") {
|
|
10224
10545
|
return row[aggregateSyntheticName(result.func, result.distinct, result.arg)] ?? "";
|
|
10225
10546
|
}
|
|
10226
10547
|
if (result.type === "AGG_ARITH") return row[aggregateOperandLabel(result)] ?? "";
|
|
10227
10548
|
if (result.type === "FIELD_REF") return row[result.field] ?? "";
|
|
10228
|
-
if (result.type === "ARITH") return evalArithExpr(result, row);
|
|
10229
|
-
return evalScalarValueExprNullable(result, row, resolveFieldType, resolveFieldSemantics2);
|
|
10549
|
+
if (result.type === "ARITH") return evalArithExpr(result, row, context);
|
|
10550
|
+
return evalScalarValueExprNullable(result, row, resolveFieldType, resolveFieldSemantics2, context);
|
|
10230
10551
|
}
|
|
10231
|
-
function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
10552
|
+
function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2, context = {}) {
|
|
10232
10553
|
if (result.type === "ARRAY") return result.elements.map((e) => e.value).join(",");
|
|
10233
10554
|
if (result.type === "AGG_REF") {
|
|
10234
10555
|
return row[aggregateSyntheticName(result.func, result.distinct, result.arg)] ?? "";
|
|
@@ -10238,12 +10559,12 @@ function evalCaseResult(result, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
10238
10559
|
return row[result.field] ?? "";
|
|
10239
10560
|
}
|
|
10240
10561
|
if (result.type === "ARITH") {
|
|
10241
|
-
return String(evalArithExpr(result, row));
|
|
10562
|
+
return String(evalArithExpr(result, row, context));
|
|
10242
10563
|
}
|
|
10243
|
-
return String(evalScalarValueExpr(result, row, resolveFieldType, resolveFieldSemantics2));
|
|
10564
|
+
return String(evalScalarValueExpr(result, row, resolveFieldType, resolveFieldSemantics2, context));
|
|
10244
10565
|
}
|
|
10245
|
-
function resolveKintoneFunc(name) {
|
|
10246
|
-
const now = /* @__PURE__ */ new Date();
|
|
10566
|
+
function resolveKintoneFunc(name, context = {}) {
|
|
10567
|
+
const now = context.statementInstant ?? /* @__PURE__ */ new Date();
|
|
10247
10568
|
switch (name) {
|
|
10248
10569
|
case "TODAY": {
|
|
10249
10570
|
const y = now.getFullYear();
|
|
@@ -10367,21 +10688,21 @@ function assertDmlWhereIsSafe(where) {
|
|
|
10367
10688
|
}
|
|
10368
10689
|
var USER_TYPES = /* @__PURE__ */ new Set(["USER_SELECT", "ORGANIZATION_SELECT", "GROUP_SELECT"]);
|
|
10369
10690
|
var ARRAY_TYPES = /* @__PURE__ */ new Set(["CHECK_BOX", "MULTI_SELECT"]);
|
|
10370
|
-
function insertToPostBatches(stmt, fieldTypes = /* @__PURE__ */ new Map()) {
|
|
10691
|
+
function insertToPostBatches(stmt, fieldTypes = /* @__PURE__ */ new Map(), evaluationContext = {}) {
|
|
10371
10692
|
const allRecords = stmt.values.map(
|
|
10372
|
-
(row) => buildInsertRecord(stmt.fields, row, fieldTypes)
|
|
10693
|
+
(row) => buildInsertRecord(stmt.fields, row, fieldTypes, evaluationContext)
|
|
10373
10694
|
);
|
|
10374
10695
|
return chunk(allRecords, 100).map((records) => ({
|
|
10375
10696
|
app: stmt.appId,
|
|
10376
10697
|
records
|
|
10377
10698
|
}));
|
|
10378
10699
|
}
|
|
10379
|
-
function buildInsertRecord(fields, row, fieldTypes) {
|
|
10700
|
+
function buildInsertRecord(fields, row, fieldTypes, evaluationContext) {
|
|
10380
10701
|
const record = {};
|
|
10381
10702
|
fields.forEach((field, i) => {
|
|
10382
10703
|
const val = row[i];
|
|
10383
10704
|
if (val.type === "CASE_VALUE") {
|
|
10384
|
-
record[field] = { value: evalCaseWhenValue(val.expr, {}, fieldTypes.get(field)) };
|
|
10705
|
+
record[field] = { value: evalCaseWhenValue(val.expr, {}, fieldTypes.get(field), evaluationContext) };
|
|
10385
10706
|
} else {
|
|
10386
10707
|
record[field] = { value: toKintoneValue(val, fieldTypes.get(field)) };
|
|
10387
10708
|
}
|
|
@@ -10541,14 +10862,14 @@ function collectConditionFields(expr, out) {
|
|
|
10541
10862
|
break;
|
|
10542
10863
|
}
|
|
10543
10864
|
}
|
|
10544
|
-
function updateToPutBatchesArith(stmt, records, fieldTypes = /* @__PURE__ */ new Map()) {
|
|
10865
|
+
function updateToPutBatchesArith(stmt, records, fieldTypes = /* @__PURE__ */ new Map(), evaluationContext = {}) {
|
|
10545
10866
|
const updateRecords = records.map((raw) => {
|
|
10546
10867
|
const id = Number(raw["$id"].value);
|
|
10547
10868
|
const row = kintoneRecordToProcessRow(raw);
|
|
10548
10869
|
const record = {};
|
|
10549
10870
|
for (const { field, value } of stmt.assignments) {
|
|
10550
10871
|
record[field] = {
|
|
10551
|
-
value: evaluateUpdateAssignmentValue(value, row, fieldTypes.get(field), raw)
|
|
10872
|
+
value: evaluateUpdateAssignmentValue(value, row, fieldTypes.get(field), raw, evaluationContext)
|
|
10552
10873
|
};
|
|
10553
10874
|
}
|
|
10554
10875
|
return { id, record };
|
|
@@ -10558,25 +10879,31 @@ function updateToPutBatchesArith(stmt, records, fieldTypes = /* @__PURE__ */ new
|
|
|
10558
10879
|
records: batch
|
|
10559
10880
|
}));
|
|
10560
10881
|
}
|
|
10561
|
-
function evaluateUpdateAssignmentValue(value, row, fieldType, raw) {
|
|
10882
|
+
function evaluateUpdateAssignmentValue(value, row, fieldType, raw, evaluationContext = {}) {
|
|
10562
10883
|
if (value.type === "ARITH") {
|
|
10563
|
-
return String(raw ? evalArith(value, raw) : evalArithExpr(value, row));
|
|
10884
|
+
return String(raw ? evalArith(value, raw) : evalArithExpr(value, row, evaluationContext));
|
|
10564
10885
|
}
|
|
10565
10886
|
if (value.type === "SCALAR_ARITH" || value.type === "CONCAT_OP") {
|
|
10566
|
-
return String(evalScalarValueExpr(value, row));
|
|
10887
|
+
return String(evalScalarValueExpr(value, row, void 0, void 0, evaluationContext));
|
|
10567
10888
|
}
|
|
10568
|
-
if (value.type === "STRING_FUNC") return evalStringFunc(value, row);
|
|
10569
|
-
if (value.type === "CASE_VALUE") return evalCaseWhenValue(value.expr, row, fieldType);
|
|
10889
|
+
if (value.type === "STRING_FUNC") return evalStringFunc(value, row, void 0, void 0, evaluationContext);
|
|
10890
|
+
if (value.type === "CASE_VALUE") return evalCaseWhenValue(value.expr, row, fieldType, evaluationContext);
|
|
10570
10891
|
if (value.type === "SOURCE_FIELD") {
|
|
10571
10892
|
throw new DmlConvertError("SOURCE_FIELD \u306F UPDATE ... FROM \u5C02\u7528\u3067\u3059");
|
|
10572
10893
|
}
|
|
10573
10894
|
return toKintoneValue(value, fieldType);
|
|
10574
10895
|
}
|
|
10575
|
-
function evaluateSubtableAssignmentValue(value, row, resolveFieldType) {
|
|
10896
|
+
function evaluateSubtableAssignmentValue(value, row, resolveFieldType, evaluationContext = {}) {
|
|
10576
10897
|
if (value.type === "STRING") return value.value;
|
|
10577
10898
|
if (value.type === "NUMBER") return numberLiteralText(value);
|
|
10578
|
-
if (value.type === "ARITH") return String(evalArithExpr(value, row));
|
|
10579
|
-
if (value.type === "CASE_VALUE") return evalCaseWhen(
|
|
10899
|
+
if (value.type === "ARITH") return String(evalArithExpr(value, row, evaluationContext));
|
|
10900
|
+
if (value.type === "CASE_VALUE") return evalCaseWhen(
|
|
10901
|
+
value.expr,
|
|
10902
|
+
row,
|
|
10903
|
+
resolveFieldType,
|
|
10904
|
+
void 0,
|
|
10905
|
+
evaluationContext
|
|
10906
|
+
);
|
|
10580
10907
|
throw new Error(`${value.type} \u306F\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB UPDATE \u306E\u5024\u3068\u3057\u3066\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`);
|
|
10581
10908
|
}
|
|
10582
10909
|
var UPDATE_FROM_UNSUPPORTED_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -10587,7 +10914,7 @@ var UPDATE_FROM_UNSUPPORTED_TYPES = /* @__PURE__ */ new Set([
|
|
|
10587
10914
|
"GROUP_SELECT",
|
|
10588
10915
|
"FILE"
|
|
10589
10916
|
]);
|
|
10590
|
-
function updateFromToPutBatches(stmt, matched, fieldTypes = /* @__PURE__ */ new Map()) {
|
|
10917
|
+
function updateFromToPutBatches(stmt, matched, fieldTypes = /* @__PURE__ */ new Map(), evaluationContext = {}) {
|
|
10591
10918
|
const updateRecords = matched.map(({ target, source }) => {
|
|
10592
10919
|
const id = Number(target["$id"]?.value);
|
|
10593
10920
|
if (!Number.isSafeInteger(id) || id <= 0) {
|
|
@@ -10617,9 +10944,20 @@ function updateFromToPutBatches(stmt, matched, fieldTypes = /* @__PURE__ */ new
|
|
|
10617
10944
|
} else if (value.type === "ARITH") {
|
|
10618
10945
|
record[field] = { value: String(evalArith(value, target)) };
|
|
10619
10946
|
} else if (value.type === "SCALAR_ARITH" || value.type === "CONCAT_OP") {
|
|
10620
|
-
record[field] = { value: String(evalScalarValueExpr(
|
|
10947
|
+
record[field] = { value: String(evalScalarValueExpr(
|
|
10948
|
+
value,
|
|
10949
|
+
targetRow,
|
|
10950
|
+
void 0,
|
|
10951
|
+
void 0,
|
|
10952
|
+
evaluationContext
|
|
10953
|
+
)) };
|
|
10621
10954
|
} else if (value.type === "CASE_VALUE") {
|
|
10622
|
-
record[field] = { value: evalCaseWhenValue(
|
|
10955
|
+
record[field] = { value: evalCaseWhenValue(
|
|
10956
|
+
value.expr,
|
|
10957
|
+
targetRow,
|
|
10958
|
+
fieldType,
|
|
10959
|
+
evaluationContext
|
|
10960
|
+
) };
|
|
10623
10961
|
} else {
|
|
10624
10962
|
record[field] = { value: toKintoneValue(value, fieldType) };
|
|
10625
10963
|
}
|
|
@@ -10721,7 +11059,7 @@ function convertArray(elements, fieldType) {
|
|
|
10721
11059
|
if (isUserType(fieldType)) return elements.map((c) => ({ code: c }));
|
|
10722
11060
|
return elements;
|
|
10723
11061
|
}
|
|
10724
|
-
function evalCaseResultValue(result, row, fieldType) {
|
|
11062
|
+
function evalCaseResultValue(result, row, fieldType, evaluationContext) {
|
|
10725
11063
|
if (result.type === "ARRAY") {
|
|
10726
11064
|
return convertArray(result.elements.map((e) => e.value), fieldType);
|
|
10727
11065
|
}
|
|
@@ -10732,26 +11070,26 @@ function evalCaseResultValue(result, row, fieldType) {
|
|
|
10732
11070
|
return convertString2(result.value, fieldType);
|
|
10733
11071
|
}
|
|
10734
11072
|
if (result.type === "STRING_FUNC") {
|
|
10735
|
-
return evalStringFunc(result, row);
|
|
11073
|
+
return evalStringFunc(result, row, void 0, void 0, evaluationContext);
|
|
10736
11074
|
}
|
|
10737
11075
|
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
10738
|
-
return String(evalArithExpr(result, row));
|
|
11076
|
+
return String(evalArithExpr(result, row, evaluationContext));
|
|
10739
11077
|
}
|
|
10740
|
-
return String(evalScalarValueExpr(result, row));
|
|
11078
|
+
return String(evalScalarValueExpr(result, row, void 0, void 0, evaluationContext));
|
|
10741
11079
|
}
|
|
10742
11080
|
function collectUpdateCheckTargetFields(stmt) {
|
|
10743
11081
|
if (!stmt.checkGroups) return [];
|
|
10744
11082
|
const targetAlias = `app${stmt.appId}`.toLowerCase();
|
|
10745
11083
|
return [...new Set(collectCheckFieldRefs(stmt.checkGroups).filter((ref) => ref.tableAlias === null || ref.tableAlias.toLowerCase() === targetAlias).map((ref) => ref.field).filter((field) => field !== "$id"))];
|
|
10746
11084
|
}
|
|
10747
|
-
function evalCaseWhenValue(expr, row, fieldType) {
|
|
11085
|
+
function evalCaseWhenValue(expr, row, fieldType, evaluationContext = {}) {
|
|
10748
11086
|
for (const branch of expr.branches) {
|
|
10749
|
-
if (evalWhere(branch.condition, row)) {
|
|
10750
|
-
return evalCaseResultValue(branch.result, row, fieldType);
|
|
11087
|
+
if (evalWhere(branch.condition, row, void 0, void 0, void 0, evaluationContext)) {
|
|
11088
|
+
return evalCaseResultValue(branch.result, row, fieldType, evaluationContext);
|
|
10751
11089
|
}
|
|
10752
11090
|
}
|
|
10753
11091
|
if (expr.elseResult !== null) {
|
|
10754
|
-
return evalCaseResultValue(expr.elseResult, row, fieldType);
|
|
11092
|
+
return evalCaseResultValue(expr.elseResult, row, fieldType, evaluationContext);
|
|
10755
11093
|
}
|
|
10756
11094
|
return "";
|
|
10757
11095
|
}
|
|
@@ -11029,18 +11367,30 @@ function buildApplyPatchPlan(input) {
|
|
|
11029
11367
|
const parentId = requirePositiveInteger(snapshot["$id"]?.value, "APPLY snapshot $id");
|
|
11030
11368
|
const expectedParentId = getApplyParentId(statement);
|
|
11031
11369
|
if (parentId !== expectedParentId) argument2(`APPLY snapshot $id ${parentId} does not match requested $id ${expectedParentId}.`);
|
|
11032
|
-
return buildApplyPatchPlanForSnapshot(
|
|
11370
|
+
return buildApplyPatchPlanForSnapshot(
|
|
11371
|
+
statement,
|
|
11372
|
+
snapshot,
|
|
11373
|
+
metadata,
|
|
11374
|
+
parentId,
|
|
11375
|
+
input.evaluationContext
|
|
11376
|
+
);
|
|
11033
11377
|
}
|
|
11034
|
-
function buildApplyPatchPlans(statement, snapshots, fieldInfos, metadata = resolveApplyPatchMetadata(statement, fieldInfos)) {
|
|
11378
|
+
function buildApplyPatchPlans(statement, snapshots, fieldInfos, metadata = resolveApplyPatchMetadata(statement, fieldInfos), evaluationContext = {}) {
|
|
11035
11379
|
const parentIds = /* @__PURE__ */ new Set();
|
|
11036
11380
|
return snapshots.map((snapshot) => {
|
|
11037
11381
|
const parentId = requirePositiveInteger(snapshot["$id"]?.value, "APPLY snapshot $id");
|
|
11038
11382
|
if (parentIds.has(parentId)) argument2(`APPLY snapshots contain duplicate parentId ${parentId}.`);
|
|
11039
11383
|
parentIds.add(parentId);
|
|
11040
|
-
return buildApplyPatchPlanForSnapshot(
|
|
11384
|
+
return buildApplyPatchPlanForSnapshot(
|
|
11385
|
+
statement,
|
|
11386
|
+
snapshot,
|
|
11387
|
+
metadata,
|
|
11388
|
+
parentId,
|
|
11389
|
+
evaluationContext
|
|
11390
|
+
);
|
|
11041
11391
|
});
|
|
11042
11392
|
}
|
|
11043
|
-
function buildApplyPatchPlanForSnapshot(statement, snapshot, metadata, parentId) {
|
|
11393
|
+
function buildApplyPatchPlanForSnapshot(statement, snapshot, metadata, parentId, evaluationContext = {}) {
|
|
11044
11394
|
const revision = requirePositiveInteger(snapshot["$revision"]?.value, "APPLY snapshot $revision");
|
|
11045
11395
|
const tablePlans = [];
|
|
11046
11396
|
const multiValuePlans = [];
|
|
@@ -11069,13 +11419,24 @@ function buildApplyPatchPlanForSnapshot(statement, snapshot, metadata, parentId)
|
|
|
11069
11419
|
const hasRemove = block.operations.some((operation) => operation.kind === "REMOVE");
|
|
11070
11420
|
for (const [operationIndex, operation] of block.operations.entries()) {
|
|
11071
11421
|
if (operation.kind === "APPEND") {
|
|
11072
|
-
const rows = buildApplyAppendRows(
|
|
11422
|
+
const rows = buildApplyAppendRows(
|
|
11423
|
+
operation,
|
|
11424
|
+
targetChildren,
|
|
11425
|
+
block.field,
|
|
11426
|
+
evaluationContext
|
|
11427
|
+
);
|
|
11073
11428
|
operationPlans.push({ kind: "APPEND", addedRows: rows.length });
|
|
11074
11429
|
appended.push(...rows);
|
|
11075
11430
|
continue;
|
|
11076
11431
|
}
|
|
11077
11432
|
if (operation.kind === "REMOVE") {
|
|
11078
|
-
const indices2 = resolveRemoveTargets(
|
|
11433
|
+
const indices2 = resolveRemoveTargets(
|
|
11434
|
+
operation,
|
|
11435
|
+
snapshotRows,
|
|
11436
|
+
childTypeResolver,
|
|
11437
|
+
block.field,
|
|
11438
|
+
evaluationContext
|
|
11439
|
+
);
|
|
11079
11440
|
if (operation.expectRows) {
|
|
11080
11441
|
assertExpectRows(operation.expectRows, indices2.length, parentId, block.field, operationIndex, operation.kind);
|
|
11081
11442
|
}
|
|
@@ -11093,7 +11454,13 @@ function buildApplyPatchPlanForSnapshot(statement, snapshot, metadata, parentId)
|
|
|
11093
11454
|
continue;
|
|
11094
11455
|
}
|
|
11095
11456
|
if (operation.kind !== "PATCH") continue;
|
|
11096
|
-
const indices = resolvePatchTargets(
|
|
11457
|
+
const indices = resolvePatchTargets(
|
|
11458
|
+
operation,
|
|
11459
|
+
snapshotRows,
|
|
11460
|
+
childTypeResolver,
|
|
11461
|
+
block.field,
|
|
11462
|
+
evaluationContext
|
|
11463
|
+
);
|
|
11097
11464
|
if (operation.expectRows) {
|
|
11098
11465
|
assertExpectRows(operation.expectRows, indices.length, parentId, block.field, operationIndex, operation.kind);
|
|
11099
11466
|
}
|
|
@@ -11112,7 +11479,12 @@ function buildApplyPatchPlanForSnapshot(statement, snapshot, metadata, parentId)
|
|
|
11112
11479
|
resolved.push({
|
|
11113
11480
|
rowIndex,
|
|
11114
11481
|
field: assignment.field,
|
|
11115
|
-
value: evaluateSubtableAssignmentValue(
|
|
11482
|
+
value: evaluateSubtableAssignmentValue(
|
|
11483
|
+
assignment.value,
|
|
11484
|
+
flat,
|
|
11485
|
+
childTypeResolver,
|
|
11486
|
+
evaluationContext
|
|
11487
|
+
)
|
|
11116
11488
|
});
|
|
11117
11489
|
}
|
|
11118
11490
|
}
|
|
@@ -11164,7 +11536,13 @@ function buildApplyPatchPlanForSnapshot(statement, snapshot, metadata, parentId)
|
|
|
11164
11536
|
for (const assignment of statement.assignments) {
|
|
11165
11537
|
const fieldType = metadata.fieldsByCode.get(assignment.field)?.fieldType;
|
|
11166
11538
|
parentValues[assignment.field] = {
|
|
11167
|
-
value: evaluateUpdateAssignmentValue(
|
|
11539
|
+
value: evaluateUpdateAssignmentValue(
|
|
11540
|
+
assignment.value,
|
|
11541
|
+
parentRow,
|
|
11542
|
+
fieldType,
|
|
11543
|
+
snapshot,
|
|
11544
|
+
evaluationContext
|
|
11545
|
+
)
|
|
11168
11546
|
};
|
|
11169
11547
|
}
|
|
11170
11548
|
const postImage = { ...snapshot };
|
|
@@ -11234,12 +11612,12 @@ function normalizeApplyPatchPlan(plan, normalizedRecord) {
|
|
|
11234
11612
|
postImage: normalizedRecord
|
|
11235
11613
|
};
|
|
11236
11614
|
}
|
|
11237
|
-
function buildApplyAppendRows(operation, children, table) {
|
|
11615
|
+
function buildApplyAppendRows(operation, children, table, evaluationContext = {}) {
|
|
11238
11616
|
return operation.values.map((row) => ({
|
|
11239
|
-
value: buildAppendValue(operation, row, children, table)
|
|
11617
|
+
value: buildAppendValue(operation, row, children, table, evaluationContext)
|
|
11240
11618
|
}));
|
|
11241
11619
|
}
|
|
11242
|
-
function buildAppendValue(operation, row, children, table) {
|
|
11620
|
+
function buildAppendValue(operation, row, children, table, evaluationContext) {
|
|
11243
11621
|
if (row.length !== operation.fields.length) {
|
|
11244
11622
|
return argument2(`APPLY APPEND for ${table} has ${row.length} values for ${operation.fields.length} fields.`);
|
|
11245
11623
|
}
|
|
@@ -11248,7 +11626,7 @@ function buildAppendValue(operation, row, children, table) {
|
|
|
11248
11626
|
for (const field of children.values()) {
|
|
11249
11627
|
if (field.fieldType === "FILE" || field.writable === false) continue;
|
|
11250
11628
|
const sqlValue = specified.get(field.code);
|
|
11251
|
-
value[field.code] = { value: sqlValue === void 0 ? appendDefaultValue(field) : sqlValue.type === "CASE_VALUE" ? evalCaseWhenValue(sqlValue.expr, {}, field.fieldType) : toKintoneValue(sqlValue, field.fieldType) };
|
|
11629
|
+
value[field.code] = { value: sqlValue === void 0 ? appendDefaultValue(field) : sqlValue.type === "CASE_VALUE" ? evalCaseWhenValue(sqlValue.expr, {}, field.fieldType, evaluationContext) : toKintoneValue(sqlValue, field.fieldType) };
|
|
11252
11630
|
}
|
|
11253
11631
|
return value;
|
|
11254
11632
|
}
|
|
@@ -11256,17 +11634,36 @@ function appendDefaultValue(field) {
|
|
|
11256
11634
|
if (field.defaultValue !== void 0 && field.defaultValue !== null) return field.defaultValue;
|
|
11257
11635
|
return ["CHECK_BOX", "MULTI_SELECT", "USER_SELECT", "ORGANIZATION_SELECT", "GROUP_SELECT"].includes(field.fieldType) ? [] : "";
|
|
11258
11636
|
}
|
|
11259
|
-
function resolvePatchTargets(operation, rows, resolveFieldType, table) {
|
|
11260
|
-
return resolveSelectorTargets(
|
|
11637
|
+
function resolvePatchTargets(operation, rows, resolveFieldType, table, evaluationContext = {}) {
|
|
11638
|
+
return resolveSelectorTargets(
|
|
11639
|
+
operation.selector,
|
|
11640
|
+
rows,
|
|
11641
|
+
resolveFieldType,
|
|
11642
|
+
table,
|
|
11643
|
+
evaluationContext
|
|
11644
|
+
);
|
|
11261
11645
|
}
|
|
11262
|
-
function resolveRemoveTargets(operation, rows, resolveFieldType, table) {
|
|
11263
|
-
return resolveSelectorTargets(
|
|
11646
|
+
function resolveRemoveTargets(operation, rows, resolveFieldType, table, evaluationContext = {}) {
|
|
11647
|
+
return resolveSelectorTargets(
|
|
11648
|
+
operation.selector,
|
|
11649
|
+
rows,
|
|
11650
|
+
resolveFieldType,
|
|
11651
|
+
table,
|
|
11652
|
+
evaluationContext
|
|
11653
|
+
);
|
|
11264
11654
|
}
|
|
11265
|
-
function resolveSelectorTargets(selector, rows, resolveFieldType, table) {
|
|
11655
|
+
function resolveSelectorTargets(selector, rows, resolveFieldType, table, evaluationContext = {}) {
|
|
11266
11656
|
if (selector.kind === "ALL_ROWS") return rows.map((_, index) => index);
|
|
11267
11657
|
const where = selector.where;
|
|
11268
11658
|
const indices = rows.flatMap(
|
|
11269
|
-
(row, index) => evalWhere(
|
|
11659
|
+
(row, index) => evalWhere(
|
|
11660
|
+
where,
|
|
11661
|
+
flattenSubtableSnapshotRow(row, index),
|
|
11662
|
+
resolveFieldType,
|
|
11663
|
+
void 0,
|
|
11664
|
+
void 0,
|
|
11665
|
+
evaluationContext
|
|
11666
|
+
) ? [index] : []
|
|
11270
11667
|
);
|
|
11271
11668
|
const requestedRid = exactRidSelectorValue(where);
|
|
11272
11669
|
if (requestedRid !== null && indices.length === 0) {
|
|
@@ -14557,9 +14954,16 @@ function assertJoinKeyAvailable(rows, key, savedColumns) {
|
|
|
14557
14954
|
throw new Error(`ArgumentError: JOIN key ${key} is not available in the materialized table.`);
|
|
14558
14955
|
}
|
|
14559
14956
|
}
|
|
14560
|
-
function applyFilter(rows, where, resolveFieldType, appliedKlikes, resolveFieldSemantics2) {
|
|
14957
|
+
function applyFilter(rows, where, resolveFieldType, appliedKlikes, resolveFieldSemantics2, evaluationContext = {}) {
|
|
14561
14958
|
if (where === null) return rows;
|
|
14562
|
-
return rows.filter((row) => evalWhere(
|
|
14959
|
+
return rows.filter((row) => evalWhere(
|
|
14960
|
+
where,
|
|
14961
|
+
row,
|
|
14962
|
+
resolveFieldType,
|
|
14963
|
+
appliedKlikes,
|
|
14964
|
+
resolveFieldSemantics2,
|
|
14965
|
+
evaluationContext
|
|
14966
|
+
));
|
|
14563
14967
|
}
|
|
14564
14968
|
function hasAggregateColumns(columns) {
|
|
14565
14969
|
return columns.some(
|
|
@@ -14593,12 +14997,28 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind, resolution
|
|
|
14593
14997
|
const outRow = asProcessingRow({ ...groupRows[0] });
|
|
14594
14998
|
for (const k of groupByKeys) {
|
|
14595
14999
|
if (k.type === "ARITH_KEY") {
|
|
14596
|
-
outRow[arithColDefaultKey(k.expr)] = String(evalArithExpr(
|
|
15000
|
+
outRow[arithColDefaultKey(k.expr)] = String(evalArithExpr(
|
|
15001
|
+
k.expr,
|
|
15002
|
+
groupRows[0],
|
|
15003
|
+
aliasEvaluationContext.evaluationContext
|
|
15004
|
+
));
|
|
14597
15005
|
} else if (k.type === "FUNC_KEY") {
|
|
14598
|
-
outRow[stringFuncDefaultKey(k.expr)] = evalStringFunc(
|
|
15006
|
+
outRow[stringFuncDefaultKey(k.expr)] = evalStringFunc(
|
|
15007
|
+
k.expr,
|
|
15008
|
+
groupRows[0],
|
|
15009
|
+
void 0,
|
|
15010
|
+
void 0,
|
|
15011
|
+
aliasEvaluationContext.evaluationContext
|
|
15012
|
+
);
|
|
14599
15013
|
}
|
|
14600
15014
|
}
|
|
14601
|
-
materializeAggregateColumns(
|
|
15015
|
+
materializeAggregateColumns(
|
|
15016
|
+
outRow,
|
|
15017
|
+
groupRows,
|
|
15018
|
+
columns,
|
|
15019
|
+
resolveAggSortKind,
|
|
15020
|
+
aliasEvaluationContext.evaluationContext
|
|
15021
|
+
);
|
|
14602
15022
|
result.push(outRow);
|
|
14603
15023
|
}
|
|
14604
15024
|
return result;
|
|
@@ -14656,7 +15076,13 @@ function applyGroupingSets(rows, spec, columns, resolveAggSortKind, limits = {})
|
|
|
14656
15076
|
outRow[item.unqualifiedBridgeKey] = value;
|
|
14657
15077
|
}
|
|
14658
15078
|
}
|
|
14659
|
-
materializeAggregateColumns(
|
|
15079
|
+
materializeAggregateColumns(
|
|
15080
|
+
outRow,
|
|
15081
|
+
groupRows,
|
|
15082
|
+
columns,
|
|
15083
|
+
resolveAggSortKind,
|
|
15084
|
+
limits.evaluationContext
|
|
15085
|
+
);
|
|
14660
15086
|
attachGroupingRowMeta(outRow, includedCanonicalIds);
|
|
14661
15087
|
result.push(outRow);
|
|
14662
15088
|
}
|
|
@@ -14667,11 +15093,19 @@ function groupingItemValue(item, row) {
|
|
|
14667
15093
|
if (!row) return "";
|
|
14668
15094
|
return row[item.directKey] ?? (item.unqualifiedBridgeKey === null ? void 0 : row[item.unqualifiedBridgeKey]) ?? "";
|
|
14669
15095
|
}
|
|
14670
|
-
function materializeAggregateColumns(outRow, groupRows, columns, resolveAggSortKind) {
|
|
15096
|
+
function materializeAggregateColumns(outRow, groupRows, columns, resolveAggSortKind, evaluationContext = {}) {
|
|
14671
15097
|
for (const [columnIndex, col] of columns.entries()) {
|
|
14672
15098
|
if (col.type === "AGGREGATE") {
|
|
14673
15099
|
const syntheticKey = aggregateSyntheticName(col.func, col.distinct, col.arg);
|
|
14674
|
-
const value = String(evalAggregate(
|
|
15100
|
+
const value = String(evalAggregate(
|
|
15101
|
+
col.func,
|
|
15102
|
+
col.distinct,
|
|
15103
|
+
col.arg,
|
|
15104
|
+
col.separator,
|
|
15105
|
+
groupRows,
|
|
15106
|
+
resolveAggSortKind,
|
|
15107
|
+
evaluationContext
|
|
15108
|
+
));
|
|
14675
15109
|
setMaterializedSelectValue(
|
|
14676
15110
|
outRow,
|
|
14677
15111
|
columnIndex,
|
|
@@ -14679,38 +15113,44 @@ function materializeAggregateColumns(outRow, groupRows, columns, resolveAggSortK
|
|
|
14679
15113
|
col.alias ? [col.alias, syntheticKey] : [syntheticKey]
|
|
14680
15114
|
);
|
|
14681
15115
|
} else if (col.type === "ARITH_AGG_COL") {
|
|
14682
|
-
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
15116
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind, evaluationContext);
|
|
14683
15117
|
const outputKey = col.alias ?? aggArithDefaultKey(col.expr);
|
|
14684
15118
|
setMaterializedSelectValue(
|
|
14685
15119
|
outRow,
|
|
14686
15120
|
columnIndex,
|
|
14687
|
-
String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind)),
|
|
15121
|
+
String(evalAggArithExpr(col.expr, groupRows, resolveAggSortKind, evaluationContext)),
|
|
14688
15122
|
[outputKey]
|
|
14689
15123
|
);
|
|
14690
15124
|
} else if (col.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(col.expr)) {
|
|
14691
|
-
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
15125
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind, evaluationContext);
|
|
14692
15126
|
const outputKey = col.alias ?? stringFuncDefaultKey(col.expr);
|
|
14693
15127
|
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows, resolveAggSortKind);
|
|
14694
|
-
setMaterializedSelectValue(
|
|
15128
|
+
setMaterializedSelectValue(
|
|
15129
|
+
outRow,
|
|
15130
|
+
columnIndex,
|
|
15131
|
+
evalStringFunc(resolvedExpr, outRow, void 0, void 0, evaluationContext),
|
|
15132
|
+
[outputKey]
|
|
15133
|
+
);
|
|
14695
15134
|
} else if (col.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(col.expr)) {
|
|
14696
|
-
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
15135
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind, evaluationContext);
|
|
14697
15136
|
const outputKey = col.alias ?? scalarValueDefaultKey(col.expr);
|
|
14698
15137
|
const resolvedExpr = resolveAggInScalarValue(col.expr, groupRows, resolveAggSortKind);
|
|
14699
15138
|
setMaterializedSelectValue(
|
|
14700
15139
|
outRow,
|
|
14701
15140
|
columnIndex,
|
|
14702
|
-
String(evalScalarValueExpr(resolvedExpr, outRow)),
|
|
15141
|
+
String(evalScalarValueExpr(resolvedExpr, outRow, void 0, void 0, evaluationContext)),
|
|
14703
15142
|
[outputKey]
|
|
14704
15143
|
);
|
|
14705
15144
|
} else if (col.type === "CASE_COL" && containsAggregate2(col.expr)) {
|
|
14706
|
-
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind);
|
|
15145
|
+
materializeAggregateDependencies(outRow, groupRows, col.expr, resolveAggSortKind, evaluationContext);
|
|
14707
15146
|
const resolvedExpr = resolveAggInCaseExpr(col.expr, groupRows, resolveAggSortKind);
|
|
14708
15147
|
const resolveAggregateSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, resolveAggSortKind) : void 0;
|
|
14709
15148
|
const value = evalCaseWhen(
|
|
14710
15149
|
resolvedExpr,
|
|
14711
15150
|
outRow,
|
|
14712
15151
|
void 0,
|
|
14713
|
-
resolveAggregateSemantics
|
|
15152
|
+
resolveAggregateSemantics,
|
|
15153
|
+
evaluationContext
|
|
14714
15154
|
);
|
|
14715
15155
|
setMaterializedSelectValue(
|
|
14716
15156
|
outRow,
|
|
@@ -14738,7 +15178,7 @@ function collectAggregateRefs(node, out) {
|
|
|
14738
15178
|
if (value["type"] === "SELECT" || value["type"] === "SCALAR_SUBQUERY") return;
|
|
14739
15179
|
Object.values(value).forEach((child) => collectAggregateRefs(child, out));
|
|
14740
15180
|
}
|
|
14741
|
-
function materializeAggregateDependencies(outRow, rows, node, resolveAggSortKind) {
|
|
15181
|
+
function materializeAggregateDependencies(outRow, rows, node, resolveAggSortKind, evaluationContext = {}) {
|
|
14742
15182
|
const refs = [];
|
|
14743
15183
|
collectAggregateRefs(node, refs);
|
|
14744
15184
|
for (const ref of refs) {
|
|
@@ -14750,7 +15190,8 @@ function materializeAggregateDependencies(outRow, rows, node, resolveAggSortKind
|
|
|
14750
15190
|
ref.arg,
|
|
14751
15191
|
ref.separator,
|
|
14752
15192
|
rows,
|
|
14753
|
-
resolveAggSortKind
|
|
15193
|
+
resolveAggSortKind,
|
|
15194
|
+
evaluationContext
|
|
14754
15195
|
));
|
|
14755
15196
|
materializedValuesFor(outRow).byLookupKey.set(key, value);
|
|
14756
15197
|
}
|
|
@@ -14781,14 +15222,20 @@ function evalGroupByKey(key, row, resolution, columns, aliasEvaluationContext) {
|
|
|
14781
15222
|
`InternalError: unresolved plain GROUP BY item ${resolution.kind} reached evaluation.`
|
|
14782
15223
|
);
|
|
14783
15224
|
}
|
|
14784
|
-
if (key.type === "FUNC_KEY") return evalStringFunc(
|
|
14785
|
-
|
|
15225
|
+
if (key.type === "FUNC_KEY") return evalStringFunc(
|
|
15226
|
+
key.expr,
|
|
15227
|
+
row,
|
|
15228
|
+
void 0,
|
|
15229
|
+
void 0,
|
|
15230
|
+
aliasEvaluationContext.evaluationContext
|
|
15231
|
+
);
|
|
15232
|
+
return String(evalArithExpr(key.expr, row, aliasEvaluationContext.evaluationContext));
|
|
14786
15233
|
}
|
|
14787
|
-
function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind) {
|
|
15234
|
+
function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind, evaluationContext = {}) {
|
|
14788
15235
|
if (arg.type === "WILDCARD") {
|
|
14789
15236
|
return func === "COUNT" ? rows.length : 0;
|
|
14790
15237
|
}
|
|
14791
|
-
const strValues = aggregateRowValues(func, arg, rows).filter((value) => value !== null);
|
|
15238
|
+
const strValues = aggregateRowValues(func, arg, rows, evaluationContext).filter((value) => value !== null);
|
|
14792
15239
|
const statistical = func === "STDDEV_POP" || func === "STDDEV_SAMP" || func === "VAR_POP" || func === "VAR_SAMP" || func === "MEDIAN";
|
|
14793
15240
|
const numericValues = statistical ? strValues.map((value) => {
|
|
14794
15241
|
const numeric = Number(value);
|
|
@@ -14866,7 +15313,7 @@ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind)
|
|
|
14866
15313
|
}
|
|
14867
15314
|
}
|
|
14868
15315
|
}
|
|
14869
|
-
function aggregateRowValues(func, arg, rows) {
|
|
15316
|
+
function aggregateRowValues(func, arg, rows, evaluationContext = {}) {
|
|
14870
15317
|
return rows.map((processingRow) => {
|
|
14871
15318
|
const row = sourceRowForEvaluation(processingRow);
|
|
14872
15319
|
let strVal;
|
|
@@ -14875,11 +15322,11 @@ function aggregateRowValues(func, arg, rows) {
|
|
|
14875
15322
|
if (raw === void 0 || raw === "" && func !== "MIN" && func !== "MAX") return null;
|
|
14876
15323
|
strVal = raw;
|
|
14877
15324
|
} else if (arg.type === "ARITH" || arg.type === "NUMBER") {
|
|
14878
|
-
const n = evalArithExpr(arg, row);
|
|
15325
|
+
const n = evalArithExpr(arg, row, evaluationContext);
|
|
14879
15326
|
if (isNaN(n)) return null;
|
|
14880
15327
|
strVal = String(n);
|
|
14881
15328
|
} else {
|
|
14882
|
-
const value = evalScalarValueExprNullable(arg, row);
|
|
15329
|
+
const value = evalScalarValueExprNullable(arg, row, void 0, void 0, evaluationContext);
|
|
14883
15330
|
if (value === null) return null;
|
|
14884
15331
|
if (value === "" && func !== "MIN" && func !== "MAX") return null;
|
|
14885
15332
|
if (typeof value === "number" && Number.isNaN(value)) return null;
|
|
@@ -14892,9 +15339,17 @@ function toAggregateFieldRef(field) {
|
|
|
14892
15339
|
const dot = field.indexOf(".");
|
|
14893
15340
|
return dot > 0 ? { type: "FIELD", tableAlias: field.slice(0, dot), field: field.slice(dot + 1) } : { type: "FIELD", tableAlias: null, field };
|
|
14894
15341
|
}
|
|
14895
|
-
function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
15342
|
+
function evalAggArithExpr(node, rows, resolveAggSortKind, evaluationContext = {}) {
|
|
14896
15343
|
if (node.type === "NUMBER") return node.value;
|
|
14897
|
-
if (node.type === "AGG_REF") return Number(evalAggregate(
|
|
15344
|
+
if (node.type === "AGG_REF") return Number(evalAggregate(
|
|
15345
|
+
node.func,
|
|
15346
|
+
node.distinct,
|
|
15347
|
+
node.arg,
|
|
15348
|
+
node.separator,
|
|
15349
|
+
rows,
|
|
15350
|
+
resolveAggSortKind,
|
|
15351
|
+
evaluationContext
|
|
15352
|
+
));
|
|
14898
15353
|
if (node.type === "AGG_GROUP_KEY") {
|
|
14899
15354
|
const field = node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field;
|
|
14900
15355
|
return Number(resolveFieldRef(rows[0] ?? {}, field));
|
|
@@ -14902,8 +15357,8 @@ function evalAggArithExpr(node, rows, resolveAggSortKind) {
|
|
|
14902
15357
|
if (node.type === "VARIABLE") {
|
|
14903
15358
|
throw new Error(`InternalError: unresolved aggregate arithmetic variable @${node.name}.`);
|
|
14904
15359
|
}
|
|
14905
|
-
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
|
|
14906
|
-
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
|
|
15360
|
+
const l = evalAggArithExpr(node.left, rows, resolveAggSortKind, evaluationContext);
|
|
15361
|
+
const r = evalAggArithExpr(node.right, rows, resolveAggSortKind, evaluationContext);
|
|
14907
15362
|
switch (node.op) {
|
|
14908
15363
|
case "+":
|
|
14909
15364
|
return l + r;
|
|
@@ -14947,22 +15402,24 @@ function aggregateResultSemantics(ref, resolver) {
|
|
|
14947
15402
|
const semantics = ref.arg.type === "WILDCARD" ? "string" : resolveAggregateArgSemantics(ref.arg, resolver) ?? "string";
|
|
14948
15403
|
return typeof semantics === "string" ? syntheticSemantics(semantics) : semantics;
|
|
14949
15404
|
}
|
|
14950
|
-
function applyHaving(rows, having, resolveFieldType, resolveFieldSemantics2) {
|
|
15405
|
+
function applyHaving(rows, having, resolveFieldType, resolveFieldSemantics2, evaluationContext = {}) {
|
|
14951
15406
|
if (having === null) return rows;
|
|
14952
15407
|
return rows.filter((row) => evalWhere(
|
|
14953
15408
|
having,
|
|
14954
15409
|
havingEvaluationRow(row),
|
|
14955
15410
|
resolveFieldType,
|
|
14956
15411
|
void 0,
|
|
14957
|
-
resolveFieldSemantics2
|
|
15412
|
+
resolveFieldSemantics2,
|
|
15413
|
+
evaluationContext
|
|
14958
15414
|
));
|
|
14959
15415
|
}
|
|
14960
|
-
function applyDistinct(rows, columns, scalarCache, resolveFieldType, resolveFieldSemantics2) {
|
|
15416
|
+
function applyDistinct(rows, columns, scalarCache, resolveFieldType, resolveFieldSemantics2, evaluationContext = {}) {
|
|
14961
15417
|
if (rows.length === 0) return rows;
|
|
14962
15418
|
const keyFor = buildDistinctKeyBuilder(rows, columns, {
|
|
14963
15419
|
scalarCache,
|
|
14964
15420
|
resolveFieldType,
|
|
14965
|
-
resolveFieldSemantics: resolveFieldSemantics2
|
|
15421
|
+
resolveFieldSemantics: resolveFieldSemantics2,
|
|
15422
|
+
evaluationContext
|
|
14966
15423
|
});
|
|
14967
15424
|
const seen = /* @__PURE__ */ new Set();
|
|
14968
15425
|
return rows.filter((row) => {
|
|
@@ -14998,11 +15455,19 @@ function buildDistinctKeyBuilder(rows, columns, context) {
|
|
|
14998
15455
|
};
|
|
14999
15456
|
return (row) => JSON.stringify(buildDistinctTuple(columns, row, distinctContext));
|
|
15000
15457
|
}
|
|
15001
|
-
function applyOrderBy(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator) {
|
|
15458
|
+
function applyOrderBy(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator, evaluationContext = {}) {
|
|
15002
15459
|
if (orderBy.length === 0) return rows;
|
|
15003
|
-
return sortDecoratedRows(
|
|
15460
|
+
return sortDecoratedRows(
|
|
15461
|
+
rows,
|
|
15462
|
+
orderBy,
|
|
15463
|
+
optionOrders,
|
|
15464
|
+
sortKinds,
|
|
15465
|
+
fieldSemantics2,
|
|
15466
|
+
aliasEvaluator,
|
|
15467
|
+
evaluationContext
|
|
15468
|
+
).rows.map((item) => item.row);
|
|
15004
15469
|
}
|
|
15005
|
-
function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator) {
|
|
15470
|
+
function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator, evaluationContext = {}) {
|
|
15006
15471
|
const keyMeta = orderBy.map(({ key }) => {
|
|
15007
15472
|
if (key.type === "ARITH_KEY") return { semantics: syntheticSemantics("number") };
|
|
15008
15473
|
if (key.type === "FUNC_KEY") {
|
|
@@ -15028,7 +15493,7 @@ function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds, fieldSemantic
|
|
|
15028
15493
|
const decorated = rows.map((row) => ({
|
|
15029
15494
|
row,
|
|
15030
15495
|
keys: orderBy.map(({ key }, i) => {
|
|
15031
|
-
const s = evalOrderKey(key, row, aliasEvaluator);
|
|
15496
|
+
const s = evalOrderKey(key, row, aliasEvaluator, evaluationContext);
|
|
15032
15497
|
return { s };
|
|
15033
15498
|
})
|
|
15034
15499
|
}));
|
|
@@ -15066,20 +15531,20 @@ var NUMERIC_ORDER_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
15066
15531
|
"QUARTER",
|
|
15067
15532
|
"WEEK"
|
|
15068
15533
|
]);
|
|
15069
|
-
function evalOrderKey(key, row, aliasEvaluator) {
|
|
15534
|
+
function evalOrderKey(key, row, aliasEvaluator, evaluationContext = {}) {
|
|
15070
15535
|
const sourceRow = sourceRowForEvaluation(row);
|
|
15071
15536
|
switch (key.type) {
|
|
15072
15537
|
case "FIELD_NAME":
|
|
15073
15538
|
return aliasEvaluator?.(key.name, row) ?? getMaterializedLookupValue(row, key.name) ?? sourceRow[key.name] ?? "";
|
|
15074
15539
|
case "ARITH_KEY":
|
|
15075
|
-
return String(evalArithExpr(key.expr, sourceRow));
|
|
15540
|
+
return String(evalArithExpr(key.expr, sourceRow, evaluationContext));
|
|
15076
15541
|
case "FUNC_KEY":
|
|
15077
|
-
return evalStringFunc(key.expr, sourceRow);
|
|
15542
|
+
return evalStringFunc(key.expr, sourceRow, void 0, void 0, evaluationContext);
|
|
15078
15543
|
case "GROUPING_KEY":
|
|
15079
15544
|
return evalGroupingRef(key.ref, row);
|
|
15080
15545
|
}
|
|
15081
15546
|
}
|
|
15082
|
-
function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, resolveFieldSemantics2) {
|
|
15547
|
+
function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, resolveFieldSemantics2, evaluationContext = {}) {
|
|
15083
15548
|
const evaluators = /* @__PURE__ */ new Map();
|
|
15084
15549
|
for (const [columnIndex, column] of columns.entries()) {
|
|
15085
15550
|
if (!("alias" in column) || column.alias === null) continue;
|
|
@@ -15103,15 +15568,37 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
15103
15568
|
evaluators.set(alias, (row) => getMaterializedSelectValue(row, columnIndex) ?? "");
|
|
15104
15569
|
break;
|
|
15105
15570
|
case "ARITH_COL":
|
|
15106
|
-
evaluators.set(alias, (row) => String(evalArithExpr(
|
|
15571
|
+
evaluators.set(alias, (row) => String(evalArithExpr(
|
|
15572
|
+
column.expr,
|
|
15573
|
+
sourceRowForEvaluation(row),
|
|
15574
|
+
evaluationContext
|
|
15575
|
+
)));
|
|
15107
15576
|
break;
|
|
15108
15577
|
case "STRFUNC_COL": {
|
|
15109
15578
|
const source = stringFuncDefaultKey(column.expr);
|
|
15110
|
-
evaluators.set(alias, (row) => hasAggregateInStringFuncExpr2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, source) ?? evalStringFunc(
|
|
15579
|
+
evaluators.set(alias, (row) => hasAggregateInStringFuncExpr2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, source) ?? evalStringFunc(
|
|
15580
|
+
column.expr,
|
|
15581
|
+
sourceRowForEvaluation(row),
|
|
15582
|
+
resolveFieldType,
|
|
15583
|
+
resolveFieldSemantics2,
|
|
15584
|
+
evaluationContext
|
|
15585
|
+
) : evalStringFunc(
|
|
15586
|
+
column.expr,
|
|
15587
|
+
sourceRowForEvaluation(row),
|
|
15588
|
+
resolveFieldType,
|
|
15589
|
+
resolveFieldSemantics2,
|
|
15590
|
+
evaluationContext
|
|
15591
|
+
));
|
|
15111
15592
|
break;
|
|
15112
15593
|
}
|
|
15113
15594
|
case "CASE_COL":
|
|
15114
|
-
evaluators.set(alias, (row) => containsAggregate2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? "" : evalCaseWhen(
|
|
15595
|
+
evaluators.set(alias, (row) => containsAggregate2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? "" : evalCaseWhen(
|
|
15596
|
+
column.expr,
|
|
15597
|
+
sourceRowForEvaluation(row),
|
|
15598
|
+
resolveFieldType,
|
|
15599
|
+
resolveFieldSemantics2,
|
|
15600
|
+
evaluationContext
|
|
15601
|
+
));
|
|
15115
15602
|
break;
|
|
15116
15603
|
case "SCALAR_VALUE_COL": {
|
|
15117
15604
|
const source = scalarValueDefaultKey(column.expr);
|
|
@@ -15119,7 +15606,8 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
15119
15606
|
column.expr,
|
|
15120
15607
|
sourceRowForEvaluation(row),
|
|
15121
15608
|
resolveFieldType,
|
|
15122
|
-
resolveFieldSemantics2
|
|
15609
|
+
resolveFieldSemantics2,
|
|
15610
|
+
evaluationContext
|
|
15123
15611
|
)));
|
|
15124
15612
|
break;
|
|
15125
15613
|
}
|
|
@@ -15135,7 +15623,7 @@ function buildOrderByAliasEvaluator(columns, scalarCache, resolveFieldType, reso
|
|
|
15135
15623
|
}
|
|
15136
15624
|
return (name, row) => evaluators.get(name)?.(row);
|
|
15137
15625
|
}
|
|
15138
|
-
function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, resolveAggSortKind) {
|
|
15626
|
+
function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, resolveAggSortKind, evaluationContext = {}) {
|
|
15139
15627
|
const windows = columns.map((column, columnIndex) => ({ column, columnIndex })).filter((item) => item.column.type === "WINDOW_COL");
|
|
15140
15628
|
if (rows.length === 0 || windows.length === 0) return rows;
|
|
15141
15629
|
for (let index = 0; index < rows.length; index++) rows[index] = asProcessingRow(rows[index]);
|
|
@@ -15148,14 +15636,28 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, re
|
|
|
15148
15636
|
else partitions.set(key, [row]);
|
|
15149
15637
|
}
|
|
15150
15638
|
for (const partition of partitions.values()) {
|
|
15151
|
-
const sortedResult = sortDecoratedRows(
|
|
15639
|
+
const sortedResult = sortDecoratedRows(
|
|
15640
|
+
partition,
|
|
15641
|
+
window.orderBy,
|
|
15642
|
+
optionOrders,
|
|
15643
|
+
sortKinds,
|
|
15644
|
+
fieldSemantics2,
|
|
15645
|
+
void 0,
|
|
15646
|
+
evaluationContext
|
|
15647
|
+
);
|
|
15152
15648
|
const sorted = sortedResult.rows;
|
|
15153
15649
|
if (isAggregateWindow(window)) {
|
|
15154
|
-
applyAggregateWindow(
|
|
15650
|
+
applyAggregateWindow(
|
|
15651
|
+
window,
|
|
15652
|
+
columnIndex,
|
|
15653
|
+
sortedResult,
|
|
15654
|
+
resolveAggSortKind,
|
|
15655
|
+
evaluationContext
|
|
15656
|
+
);
|
|
15155
15657
|
continue;
|
|
15156
15658
|
}
|
|
15157
15659
|
if (isValueWindow(window)) {
|
|
15158
|
-
applyValueWindow(window, columnIndex, sorted);
|
|
15660
|
+
applyValueWindow(window, columnIndex, sorted, evaluationContext);
|
|
15159
15661
|
continue;
|
|
15160
15662
|
}
|
|
15161
15663
|
if (!isRankingWindow(window)) {
|
|
@@ -15175,14 +15677,24 @@ function applyWindow(rows, columns, optionOrders, sortKinds, fieldSemantics2, re
|
|
|
15175
15677
|
}
|
|
15176
15678
|
return rows;
|
|
15177
15679
|
}
|
|
15178
|
-
function evaluateValueWindowArg(arg, row) {
|
|
15179
|
-
const value = evalScalarValueExprNullable(
|
|
15680
|
+
function evaluateValueWindowArg(arg, row, evaluationContext = {}) {
|
|
15681
|
+
const value = evalScalarValueExprNullable(
|
|
15682
|
+
arg,
|
|
15683
|
+
sourceRowForEvaluation(row),
|
|
15684
|
+
void 0,
|
|
15685
|
+
void 0,
|
|
15686
|
+
evaluationContext
|
|
15687
|
+
);
|
|
15180
15688
|
if (value === null || value === void 0) return "";
|
|
15181
15689
|
if (typeof value === "number" && !Number.isFinite(value)) return "";
|
|
15182
15690
|
return String(value);
|
|
15183
15691
|
}
|
|
15184
|
-
function applyValueWindow(window, columnIndex, sorted) {
|
|
15185
|
-
const values = sorted.map((item) => evaluateValueWindowArg(
|
|
15692
|
+
function applyValueWindow(window, columnIndex, sorted, evaluationContext = {}) {
|
|
15693
|
+
const values = sorted.map((item) => evaluateValueWindowArg(
|
|
15694
|
+
window.arg,
|
|
15695
|
+
item.row,
|
|
15696
|
+
evaluationContext
|
|
15697
|
+
));
|
|
15186
15698
|
const direction = window.valueFunc === "LAG" ? -1 : 1;
|
|
15187
15699
|
for (let index = 0; index < sorted.length; index++) {
|
|
15188
15700
|
const target = index + direction * window.offset;
|
|
@@ -15194,9 +15706,14 @@ function applyValueWindow(window, columnIndex, sorted) {
|
|
|
15194
15706
|
);
|
|
15195
15707
|
}
|
|
15196
15708
|
}
|
|
15197
|
-
function applyAggregateWindow(window, columnIndex, sortedResult, resolveAggSortKind) {
|
|
15709
|
+
function applyAggregateWindow(window, columnIndex, sortedResult, resolveAggSortKind, evaluationContext = {}) {
|
|
15198
15710
|
const sorted = sortedResult.rows;
|
|
15199
|
-
const values = window.arg.type === "WILDCARD" ? null : aggregateRowValues(
|
|
15711
|
+
const values = window.arg.type === "WILDCARD" ? null : aggregateRowValues(
|
|
15712
|
+
window.aggFunc,
|
|
15713
|
+
window.arg,
|
|
15714
|
+
sorted.map((item) => item.row),
|
|
15715
|
+
evaluationContext
|
|
15716
|
+
);
|
|
15200
15717
|
const comparison = window.arg.type === "WILDCARD" ? void 0 : resolveAggregateArgSemantics(window.arg, resolveAggSortKind);
|
|
15201
15718
|
const semantics = typeof comparison === "string" ? syntheticSemantics(comparison) : comparison ?? syntheticSemantics("string");
|
|
15202
15719
|
const output = [];
|
|
@@ -15288,13 +15805,14 @@ function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
|
|
|
15288
15805
|
return getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, source) ?? getLegacyMaterializedValue(row, source) ?? "0";
|
|
15289
15806
|
}
|
|
15290
15807
|
case "ARITH_COL":
|
|
15291
|
-
return String(evalArithExpr(column.expr, sourceRow));
|
|
15808
|
+
return String(evalArithExpr(column.expr, sourceRow, context.evaluationContext));
|
|
15292
15809
|
case "CASE_COL":
|
|
15293
15810
|
return containsAggregate2(column.expr) ? getMaterializedSelectValue(row, columnIndex) ?? getMaterializedLookupValue(row, caseMaterializedKey(column.alias, columnIndex)) ?? getLegacyMaterializedValue(row, caseMaterializedKey(column.alias, columnIndex)) ?? "" : evalCaseWhen(
|
|
15294
15811
|
column.expr,
|
|
15295
15812
|
sourceRow,
|
|
15296
15813
|
context.resolveFieldType,
|
|
15297
|
-
context.resolveFieldSemantics
|
|
15814
|
+
context.resolveFieldSemantics,
|
|
15815
|
+
context.evaluationContext
|
|
15298
15816
|
);
|
|
15299
15817
|
case "GROUPING_COL":
|
|
15300
15818
|
return evalGroupingRef(column.ref, row);
|
|
@@ -15304,12 +15822,14 @@ function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
|
|
|
15304
15822
|
column.expr,
|
|
15305
15823
|
sourceRow,
|
|
15306
15824
|
context.resolveFieldType,
|
|
15307
|
-
context.resolveFieldSemantics
|
|
15825
|
+
context.resolveFieldSemantics,
|
|
15826
|
+
context.evaluationContext
|
|
15308
15827
|
) : evalStringFunc(
|
|
15309
15828
|
column.expr,
|
|
15310
15829
|
sourceRow,
|
|
15311
15830
|
context.resolveFieldType,
|
|
15312
|
-
context.resolveFieldSemantics
|
|
15831
|
+
context.resolveFieldSemantics,
|
|
15832
|
+
context.evaluationContext
|
|
15313
15833
|
);
|
|
15314
15834
|
}
|
|
15315
15835
|
case "SCALAR_VALUE_COL": {
|
|
@@ -15318,7 +15838,8 @@ function evaluateSelectColumnValue(column, row, columnIndex, context = {}) {
|
|
|
15318
15838
|
column.expr,
|
|
15319
15839
|
sourceRow,
|
|
15320
15840
|
context.resolveFieldType,
|
|
15321
|
-
context.resolveFieldSemantics
|
|
15841
|
+
context.resolveFieldSemantics,
|
|
15842
|
+
context.evaluationContext
|
|
15322
15843
|
));
|
|
15323
15844
|
}
|
|
15324
15845
|
case "SCALAR_SUBQUERY_COL":
|
|
@@ -15333,7 +15854,7 @@ function buildDistinctTuple(columns, row, context = {}) {
|
|
|
15333
15854
|
return typeof value === "string" ? value : value.entries.map(([, entryValue]) => entryValue);
|
|
15334
15855
|
});
|
|
15335
15856
|
}
|
|
15336
|
-
function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, resolveFieldSemantics2, hiddenQualifiedAliases) {
|
|
15857
|
+
function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, resolveFieldSemantics2, hiddenQualifiedAliases, evaluationContext = {}) {
|
|
15337
15858
|
if (columns.length === 1 && columns[0].type === "WILDCARD") {
|
|
15338
15859
|
const projected2 = rows.map((row) => {
|
|
15339
15860
|
const visible = stripHiddenQualifiedColumns(
|
|
@@ -15366,10 +15887,11 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
|
|
|
15366
15887
|
}
|
|
15367
15888
|
const projected = rows.map((row, rowIdx) => {
|
|
15368
15889
|
const out = {};
|
|
15369
|
-
const
|
|
15890
|
+
const columnEvaluationContext = {
|
|
15370
15891
|
scalarCache,
|
|
15371
15892
|
resolveFieldType,
|
|
15372
15893
|
resolveFieldSemantics: resolveFieldSemantics2,
|
|
15894
|
+
evaluationContext,
|
|
15373
15895
|
wildcardKeys: Object.keys(stripHiddenQualifiedColumns(
|
|
15374
15896
|
stripParentShortcutColumns(row),
|
|
15375
15897
|
hiddenQualifiedAliases
|
|
@@ -15377,7 +15899,7 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns2, r
|
|
|
15377
15899
|
parentWildcardKeys: Object.keys(row).filter((key) => key.startsWith("_p.")).sort()
|
|
15378
15900
|
};
|
|
15379
15901
|
for (const [colIdx, col] of columns.entries()) {
|
|
15380
|
-
const value = evaluateSelectColumnValue(col, row, colIdx,
|
|
15902
|
+
const value = evaluateSelectColumnValue(col, row, colIdx, columnEvaluationContext);
|
|
15381
15903
|
switch (col.type) {
|
|
15382
15904
|
case "VARIABLE_COL":
|
|
15383
15905
|
break;
|
|
@@ -15769,7 +16291,8 @@ function runFullScan(input) {
|
|
|
15769
16291
|
hiddenQualifiedAliases,
|
|
15770
16292
|
resolvedGroupingSpec,
|
|
15771
16293
|
plainGroupByPlan,
|
|
15772
|
-
warnings
|
|
16294
|
+
warnings,
|
|
16295
|
+
evaluationContext
|
|
15773
16296
|
} = input;
|
|
15774
16297
|
const effectiveOrderSemantics = deriveOutputOrderSemantics(stmt.columns, aggregateSortKindResolver);
|
|
15775
16298
|
for (const [key, value] of orderSemantics ?? []) effectiveOrderSemantics.set(key, value);
|
|
@@ -15798,7 +16321,14 @@ function runFullScan(input) {
|
|
|
15798
16321
|
knownColumns = mergeKnownColumns(knownColumns, rightColumns, rows);
|
|
15799
16322
|
}
|
|
15800
16323
|
const filterWhere = input.residualWhere !== void 0 ? input.residualWhere : stmt.where;
|
|
15801
|
-
rows = applyFilter(
|
|
16324
|
+
rows = applyFilter(
|
|
16325
|
+
rows,
|
|
16326
|
+
filterWhere,
|
|
16327
|
+
fieldTypeResolver,
|
|
16328
|
+
appliedKlikes,
|
|
16329
|
+
fieldSemanticsResolver,
|
|
16330
|
+
evaluationContext
|
|
16331
|
+
);
|
|
15802
16332
|
const grouping = normalizeGroupingSpec(stmt);
|
|
15803
16333
|
if (grouping.type === "GROUPING_SETS") {
|
|
15804
16334
|
if (!resolvedGroupingSpec) {
|
|
@@ -15809,7 +16339,7 @@ function runFullScan(input) {
|
|
|
15809
16339
|
resolvedGroupingSpec,
|
|
15810
16340
|
stmt.columns,
|
|
15811
16341
|
aggregateSortKindResolver,
|
|
15812
|
-
{ maxGeneratedRows: B65_MAX_GENERATED_ROWS }
|
|
16342
|
+
{ maxGeneratedRows: B65_MAX_GENERATED_ROWS, evaluationContext }
|
|
15813
16343
|
);
|
|
15814
16344
|
} else if (grouping.type === "PLAIN" || hasAggregateColumns(stmt.columns)) {
|
|
15815
16345
|
rows = applyGroupBy(
|
|
@@ -15821,21 +16351,29 @@ function runFullScan(input) {
|
|
|
15821
16351
|
{
|
|
15822
16352
|
scalarCache,
|
|
15823
16353
|
resolveFieldType: fieldTypeResolver,
|
|
15824
|
-
resolveFieldSemantics: fieldSemanticsResolver
|
|
16354
|
+
resolveFieldSemantics: fieldSemanticsResolver,
|
|
16355
|
+
evaluationContext
|
|
15825
16356
|
}
|
|
15826
16357
|
);
|
|
15827
16358
|
}
|
|
15828
16359
|
warnOnUnresolvedAggregateComparisons(stmt.columns, rows, warnings);
|
|
15829
16360
|
const resolveHavingSemantics = (field) => field.aggregateRef ? aggregateResultSemantics(field.aggregateRef, aggregateSortKindResolver) : havingFieldSemanticsResolver?.(field);
|
|
15830
16361
|
warnOnUnresolvedAggregateComparisons(stmt.having, rows, warnings);
|
|
15831
|
-
rows = applyHaving(
|
|
16362
|
+
rows = applyHaving(
|
|
16363
|
+
rows,
|
|
16364
|
+
stmt.having,
|
|
16365
|
+
havingFieldTypeResolver,
|
|
16366
|
+
resolveHavingSemantics,
|
|
16367
|
+
evaluationContext
|
|
16368
|
+
);
|
|
15832
16369
|
rows = applyWindow(
|
|
15833
16370
|
rows,
|
|
15834
16371
|
stmt.columns,
|
|
15835
16372
|
optionOrders,
|
|
15836
16373
|
sortKinds,
|
|
15837
16374
|
effectiveOrderSemantics,
|
|
15838
|
-
aggregateSortKindResolver
|
|
16375
|
+
aggregateSortKindResolver,
|
|
16376
|
+
evaluationContext
|
|
15839
16377
|
);
|
|
15840
16378
|
if (stmt.distinct) {
|
|
15841
16379
|
rows = applyDistinct(
|
|
@@ -15843,7 +16381,8 @@ function runFullScan(input) {
|
|
|
15843
16381
|
stmt.columns,
|
|
15844
16382
|
scalarCache,
|
|
15845
16383
|
fieldTypeResolver,
|
|
15846
|
-
fieldSemanticsResolver
|
|
16384
|
+
fieldSemanticsResolver,
|
|
16385
|
+
evaluationContext
|
|
15847
16386
|
);
|
|
15848
16387
|
}
|
|
15849
16388
|
rows = applyOrderBy(
|
|
@@ -15852,7 +16391,14 @@ function runFullScan(input) {
|
|
|
15852
16391
|
optionOrders,
|
|
15853
16392
|
sortKinds,
|
|
15854
16393
|
effectiveOrderSemantics,
|
|
15855
|
-
buildOrderByAliasEvaluator(
|
|
16394
|
+
buildOrderByAliasEvaluator(
|
|
16395
|
+
stmt.columns,
|
|
16396
|
+
scalarCache,
|
|
16397
|
+
fieldTypeResolver,
|
|
16398
|
+
fieldSemanticsResolver,
|
|
16399
|
+
evaluationContext
|
|
16400
|
+
),
|
|
16401
|
+
evaluationContext
|
|
15856
16402
|
);
|
|
15857
16403
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
15858
16404
|
return project(
|
|
@@ -15862,7 +16408,8 @@ function runFullScan(input) {
|
|
|
15862
16408
|
fieldTypeResolver,
|
|
15863
16409
|
sourceColumns2,
|
|
15864
16410
|
fieldSemanticsResolver,
|
|
15865
|
-
hiddenQualifiedAliases
|
|
16411
|
+
hiddenQualifiedAliases,
|
|
16412
|
+
evaluationContext
|
|
15866
16413
|
);
|
|
15867
16414
|
}
|
|
15868
16415
|
|
|
@@ -15908,6 +16455,147 @@ function toFlatString(value) {
|
|
|
15908
16455
|
}
|
|
15909
16456
|
}
|
|
15910
16457
|
|
|
16458
|
+
// src/core/diagnostics.ts
|
|
16459
|
+
var DiagnosticCodes = {
|
|
16460
|
+
HEADER_UNKNOWN_KEY: "KSQL1001",
|
|
16461
|
+
HEADER_DUPLICATE_KEY: "KSQL1002",
|
|
16462
|
+
HEADER_INVALID_NAME: "KSQL1003",
|
|
16463
|
+
HEADER_INVALID_DEPENDS_ON: "KSQL1004",
|
|
16464
|
+
HEADER_INVALID_TIMEOUT: "KSQL1005",
|
|
16465
|
+
HEADER_INVALID_DIALECT: "KSQL1006",
|
|
16466
|
+
LOGICAL_APP_UNRESOLVED: "KSQL1101",
|
|
16467
|
+
LEX_ERROR: "KSQL1201",
|
|
16468
|
+
PARSE_ERROR: "KSQL1202"
|
|
16469
|
+
};
|
|
16470
|
+
function sourceLocationAt(source, offset) {
|
|
16471
|
+
const target = Math.max(0, Math.min(offset, source.length));
|
|
16472
|
+
let line = 1;
|
|
16473
|
+
let column = 1;
|
|
16474
|
+
for (let i = 0; i < target; i++) {
|
|
16475
|
+
const ch = source[i];
|
|
16476
|
+
if (ch === "\r") {
|
|
16477
|
+
if (source[i + 1] === "\n" && i + 1 < target) i++;
|
|
16478
|
+
line++;
|
|
16479
|
+
column = 1;
|
|
16480
|
+
} else if (ch === "\n") {
|
|
16481
|
+
line++;
|
|
16482
|
+
column = 1;
|
|
16483
|
+
} else {
|
|
16484
|
+
column++;
|
|
16485
|
+
}
|
|
16486
|
+
}
|
|
16487
|
+
return { line, column };
|
|
16488
|
+
}
|
|
16489
|
+
function diagnosticAt(source, offset, diagnostic2) {
|
|
16490
|
+
return { ...diagnostic2, ...sourceLocationAt(source, offset) };
|
|
16491
|
+
}
|
|
16492
|
+
|
|
16493
|
+
// src/core/scriptHeader.ts
|
|
16494
|
+
var HEADER_LINE_RE = /^(\s*)--\s*@ksql\s+([^:\s]+)\s*:\s*(.*)$/i;
|
|
16495
|
+
function parseScriptHeader(source) {
|
|
16496
|
+
const meta = { name: null, dependsOn: [], timeout: null, dialect: 0 };
|
|
16497
|
+
const diagnostics = [];
|
|
16498
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16499
|
+
let hasDirectives = false;
|
|
16500
|
+
let offset = source.charCodeAt(0) === 65279 ? 1 : 0;
|
|
16501
|
+
let headerEnd = offset;
|
|
16502
|
+
while (offset < source.length) {
|
|
16503
|
+
const lineEnd = findLineEnd(source, offset);
|
|
16504
|
+
const line = source.slice(offset, lineEnd.contentEnd);
|
|
16505
|
+
if (!/^\s*--/.test(line)) break;
|
|
16506
|
+
headerEnd = lineEnd.next;
|
|
16507
|
+
const match = HEADER_LINE_RE.exec(line);
|
|
16508
|
+
if (match) {
|
|
16509
|
+
hasDirectives = true;
|
|
16510
|
+
const rawKey = match[2];
|
|
16511
|
+
const key = rawKey.toLowerCase();
|
|
16512
|
+
const rawValue = match[3];
|
|
16513
|
+
const commentAt = rawValue.indexOf("#");
|
|
16514
|
+
const valuePart = commentAt < 0 ? rawValue : rawValue.slice(0, commentAt);
|
|
16515
|
+
const leading = valuePart.match(/^\s*/)?.[0].length ?? 0;
|
|
16516
|
+
const value = valuePart.trim();
|
|
16517
|
+
const valueOffset = offset + match.index + match[0].length - rawValue.length + leading;
|
|
16518
|
+
if (!isHeaderKey(key)) {
|
|
16519
|
+
diagnostics.push(diagnosticAt(source, valueOffset, {
|
|
16520
|
+
severity: "warning",
|
|
16521
|
+
code: DiagnosticCodes.HEADER_UNKNOWN_KEY,
|
|
16522
|
+
message: `Unknown @ksql header key "${rawKey}" was ignored.`
|
|
16523
|
+
}));
|
|
16524
|
+
} else if (seen.has(key)) {
|
|
16525
|
+
diagnostics.push(diagnosticAt(source, valueOffset, {
|
|
16526
|
+
severity: "warning",
|
|
16527
|
+
code: DiagnosticCodes.HEADER_DUPLICATE_KEY,
|
|
16528
|
+
message: `Duplicate @ksql header key "${key}" was ignored; the first value is retained.`
|
|
16529
|
+
}));
|
|
16530
|
+
} else {
|
|
16531
|
+
seen.add(key);
|
|
16532
|
+
applyHeaderValue(meta, key, value, source, valueOffset, diagnostics);
|
|
16533
|
+
}
|
|
16534
|
+
}
|
|
16535
|
+
offset = lineEnd.next;
|
|
16536
|
+
}
|
|
16537
|
+
return { meta, diagnostics, hasDirectives, headerEnd };
|
|
16538
|
+
}
|
|
16539
|
+
function isHeaderKey(value) {
|
|
16540
|
+
return value === "name" || value === "depends_on" || value === "timeout" || value === "dialect";
|
|
16541
|
+
}
|
|
16542
|
+
function applyHeaderValue(meta, key, value, source, valueOffset, diagnostics) {
|
|
16543
|
+
if (key === "name") {
|
|
16544
|
+
if (!value) {
|
|
16545
|
+
diagnostics.push(diagnosticAt(source, valueOffset, {
|
|
16546
|
+
severity: "error",
|
|
16547
|
+
code: DiagnosticCodes.HEADER_INVALID_NAME,
|
|
16548
|
+
message: "@ksql name must not be empty."
|
|
16549
|
+
}));
|
|
16550
|
+
} else {
|
|
16551
|
+
meta.name = value;
|
|
16552
|
+
}
|
|
16553
|
+
return;
|
|
16554
|
+
}
|
|
16555
|
+
if (key === "depends_on") {
|
|
16556
|
+
const dependencies = value.split(",").map((item) => item.trim());
|
|
16557
|
+
if (!value || dependencies.some((item) => !item)) {
|
|
16558
|
+
diagnostics.push(diagnosticAt(source, valueOffset, {
|
|
16559
|
+
severity: "error",
|
|
16560
|
+
code: DiagnosticCodes.HEADER_INVALID_DEPENDS_ON,
|
|
16561
|
+
message: "@ksql depends_on must be a comma-separated list without empty items."
|
|
16562
|
+
}));
|
|
16563
|
+
} else {
|
|
16564
|
+
meta.dependsOn = dependencies;
|
|
16565
|
+
}
|
|
16566
|
+
return;
|
|
16567
|
+
}
|
|
16568
|
+
if (key === "timeout") {
|
|
16569
|
+
if (!/^[1-9]\d*$/.test(value) || !Number.isSafeInteger(Number(value))) {
|
|
16570
|
+
diagnostics.push(diagnosticAt(source, valueOffset, {
|
|
16571
|
+
severity: "error",
|
|
16572
|
+
code: DiagnosticCodes.HEADER_INVALID_TIMEOUT,
|
|
16573
|
+
message: "@ksql timeout must be a positive integer."
|
|
16574
|
+
}));
|
|
16575
|
+
} else {
|
|
16576
|
+
meta.timeout = Number(value);
|
|
16577
|
+
}
|
|
16578
|
+
return;
|
|
16579
|
+
}
|
|
16580
|
+
if (value !== "0" && value !== "1") {
|
|
16581
|
+
diagnostics.push(diagnosticAt(source, valueOffset, {
|
|
16582
|
+
severity: "error",
|
|
16583
|
+
code: DiagnosticCodes.HEADER_INVALID_DIALECT,
|
|
16584
|
+
message: "@ksql dialect must be 0 or 1."
|
|
16585
|
+
}));
|
|
16586
|
+
} else {
|
|
16587
|
+
meta.dialect = Number(value);
|
|
16588
|
+
}
|
|
16589
|
+
}
|
|
16590
|
+
function findLineEnd(source, start) {
|
|
16591
|
+
let i = start;
|
|
16592
|
+
while (i < source.length && source[i] !== "\r" && source[i] !== "\n") i++;
|
|
16593
|
+
const contentEnd = i;
|
|
16594
|
+
if (source[i] === "\r" && source[i + 1] === "\n") i += 2;
|
|
16595
|
+
else if (i < source.length) i++;
|
|
16596
|
+
return { contentEnd, next: i };
|
|
16597
|
+
}
|
|
16598
|
+
|
|
15911
16599
|
// src/core/dmlPrevalidation.ts
|
|
15912
16600
|
function collectDmlPrevalidationSnapshotFields(fieldIndex) {
|
|
15913
16601
|
return [
|
|
@@ -17572,6 +18260,18 @@ var SearchAbortedError = class extends Error {
|
|
|
17572
18260
|
var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
|
|
17573
18261
|
var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
|
|
17574
18262
|
var importSourceByDmlStatement = /* @__PURE__ */ new WeakMap();
|
|
18263
|
+
var statementEvaluationContextKey = /* @__PURE__ */ Symbol("statementEvaluationContext");
|
|
18264
|
+
function bindStatementEvaluationContext(options) {
|
|
18265
|
+
const internal = options;
|
|
18266
|
+
if (internal[statementEvaluationContextKey]) return options;
|
|
18267
|
+
return {
|
|
18268
|
+
...options,
|
|
18269
|
+
[statementEvaluationContextKey]: { statementInstant: /* @__PURE__ */ new Date() }
|
|
18270
|
+
};
|
|
18271
|
+
}
|
|
18272
|
+
function statementEvaluationContext(options) {
|
|
18273
|
+
return options[statementEvaluationContextKey] ?? {};
|
|
18274
|
+
}
|
|
17575
18275
|
var defaultCacheContextByClient = /* @__PURE__ */ new WeakMap();
|
|
17576
18276
|
var nextDefaultCacheContextId = 1;
|
|
17577
18277
|
var nextCacheInvocationId = 1;
|
|
@@ -17821,6 +18521,7 @@ async function resolveRelativeDateExecutionPlan(stmt, client, cacheContext) {
|
|
|
17821
18521
|
});
|
|
17822
18522
|
}
|
|
17823
18523
|
async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
18524
|
+
options = bindStatementEvaluationContext(options);
|
|
17824
18525
|
const relativeDatePlan = await resolveRelativeDateExecutionPlan(stmt, client, cacheContext);
|
|
17825
18526
|
if (stmt.type !== "EXPLAIN") assertRelativeDatePushdownPlan(relativeDatePlan);
|
|
17826
18527
|
const unresolved = findVariableRef(stmt);
|
|
@@ -17916,6 +18617,8 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
|
|
|
17916
18617
|
throw new Error("ArgumentError: DECLARE variable requires a batch.");
|
|
17917
18618
|
case "ASSERT":
|
|
17918
18619
|
return executeAssert(stmt, client, options, cacheContext);
|
|
18620
|
+
case "EXIT":
|
|
18621
|
+
throw new Error("ArgumentError: EXIT SUCCESS IF \u306F\u30D0\u30C3\u30C1\u5C02\u7528\u3067\u3059");
|
|
17919
18622
|
}
|
|
17920
18623
|
}
|
|
17921
18624
|
var EXISTING_VALIDATION_COLUMNS = [
|
|
@@ -18035,7 +18738,14 @@ async function executeExistingRecordValidationCore(stmt, client, options, cacheC
|
|
|
18035
18738
|
id: String(record["$id"]?.value ?? ""),
|
|
18036
18739
|
record,
|
|
18037
18740
|
flat: flatten(record, null)
|
|
18038
|
-
})).filter((row) => stmt.where === null || evalWhere(
|
|
18741
|
+
})).filter((row) => stmt.where === null || evalWhere(
|
|
18742
|
+
stmt.where,
|
|
18743
|
+
row.flat,
|
|
18744
|
+
(field) => evaluationTypes.get(field.field),
|
|
18745
|
+
void 0,
|
|
18746
|
+
void 0,
|
|
18747
|
+
statementEvaluationContext(options)
|
|
18748
|
+
));
|
|
18039
18749
|
const rows = [];
|
|
18040
18750
|
const detailRows = /* @__PURE__ */ new Map();
|
|
18041
18751
|
const summaryRows = /* @__PURE__ */ new Map();
|
|
@@ -18176,7 +18886,16 @@ var BatchTimeoutError = class extends Error {
|
|
|
18176
18886
|
};
|
|
18177
18887
|
async function executeBatch(sql, client, options = {}) {
|
|
18178
18888
|
resolveRecursiveCteLimits(options);
|
|
18179
|
-
const
|
|
18889
|
+
const header = parseScriptHeader(sql);
|
|
18890
|
+
const headerError = header.diagnostics.find((diagnostic2) => diagnostic2.severity === "error");
|
|
18891
|
+
if (header.hasDirectives && headerError) {
|
|
18892
|
+
throw new Error(`${headerError.code}: ${headerError.message} (${headerError.line}:${headerError.column})`);
|
|
18893
|
+
}
|
|
18894
|
+
const statements = parseSqlBatch(
|
|
18895
|
+
header.hasDirectives ? sql.slice(header.headerEnd) : sql,
|
|
18896
|
+
options.enableImport === true,
|
|
18897
|
+
header.hasDirectives && header.meta.dialect === 1
|
|
18898
|
+
);
|
|
18180
18899
|
const analysis = analyzeBatch(statements);
|
|
18181
18900
|
statements.forEach((statement) => assertApplyExecutionScope("phase15b", statement));
|
|
18182
18901
|
if (options.allowApplyMutation !== true && statements.some(
|
|
@@ -18218,7 +18937,7 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
18218
18937
|
const base = { index: i, type: info.statementType };
|
|
18219
18938
|
if (aborted) {
|
|
18220
18939
|
results.push({ ...base, status: "skipped", skippedReason: aborted });
|
|
18221
|
-
failed.add(i);
|
|
18940
|
+
if (aborted !== "exit") failed.add(i);
|
|
18222
18941
|
continue;
|
|
18223
18942
|
}
|
|
18224
18943
|
const brokenDep = info.dependsOn.find((d) => failed.has(d));
|
|
@@ -18256,24 +18975,29 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
18256
18975
|
info.statementType !== "SELECT" && info.statementType !== "UNION" && info.statementType !== "WITH" || statementContainsOuterJoin(statements[i])
|
|
18257
18976
|
);
|
|
18258
18977
|
const cursorScope = wrapClientWithCursorScope(statementClient);
|
|
18978
|
+
const boundOptions = bindStatementEvaluationContext(stmtOptions);
|
|
18979
|
+
const statementContext = {
|
|
18980
|
+
stmt: statements[i],
|
|
18981
|
+
info,
|
|
18982
|
+
client: cursorScope.client,
|
|
18983
|
+
options: boundOptions,
|
|
18984
|
+
cacheContext,
|
|
18985
|
+
tempTables,
|
|
18986
|
+
variables,
|
|
18987
|
+
relativeDateVariables,
|
|
18988
|
+
clock: statementEvaluationContext(boundOptions)
|
|
18989
|
+
};
|
|
18259
18990
|
const outcome = await runWithDeadline(
|
|
18260
|
-
executeBatchStatement(
|
|
18261
|
-
statements[i],
|
|
18262
|
-
info,
|
|
18263
|
-
cursorScope.client,
|
|
18264
|
-
stmtOptions,
|
|
18265
|
-
cacheContext,
|
|
18266
|
-
tempTables,
|
|
18267
|
-
variables,
|
|
18268
|
-
relativeDateVariables
|
|
18269
|
-
),
|
|
18991
|
+
executeBatchStatement(statementContext),
|
|
18270
18992
|
remaining,
|
|
18271
18993
|
cursorScope.closeActive
|
|
18272
18994
|
);
|
|
18273
18995
|
if (outcome.result) {
|
|
18274
18996
|
outcome.result = attachSearchAbortWarning(outcome.result, searchAbortCollector);
|
|
18275
18997
|
}
|
|
18276
|
-
|
|
18998
|
+
const { exitTriggered, ...statementOutcome } = outcome;
|
|
18999
|
+
results.push({ ...base, status: "success", ...statementOutcome });
|
|
19000
|
+
if (exitTriggered) aborted = "exit";
|
|
18277
19001
|
} catch (e) {
|
|
18278
19002
|
results.push({
|
|
18279
19003
|
...base,
|
|
@@ -18295,7 +19019,7 @@ async function executeBatch(sql, client, options = {}) {
|
|
|
18295
19019
|
}
|
|
18296
19020
|
metrics.elapsedMs = Date.now() - startedAt;
|
|
18297
19021
|
return {
|
|
18298
|
-
ok: results.every((r) => r.status === "success"),
|
|
19022
|
+
ok: results.every((r) => r.status === "success" || r.skippedReason === "exit"),
|
|
18299
19023
|
statementCount: statements.length,
|
|
18300
19024
|
statements: results,
|
|
18301
19025
|
analysis,
|
|
@@ -18311,7 +19035,18 @@ function statementHasApplyMutation(statement) {
|
|
|
18311
19035
|
}
|
|
18312
19036
|
return statement.type === "UPSERT" && statement.validateOnly !== true && Boolean(statement.onInsertApplyBlocks?.length || statement.onUpdateApplyBlocks?.length);
|
|
18313
19037
|
}
|
|
18314
|
-
async function executeBatchStatement(
|
|
19038
|
+
async function executeBatchStatement(context) {
|
|
19039
|
+
const {
|
|
19040
|
+
stmt,
|
|
19041
|
+
info,
|
|
19042
|
+
client,
|
|
19043
|
+
options,
|
|
19044
|
+
cacheContext,
|
|
19045
|
+
tempTables,
|
|
19046
|
+
variables,
|
|
19047
|
+
relativeDateVariables,
|
|
19048
|
+
clock
|
|
19049
|
+
} = context;
|
|
18315
19050
|
if (stmt.type === "SET_VARIABLE") {
|
|
18316
19051
|
const resolvedStmt2 = resolveBatchVariableReferences(stmt, variables);
|
|
18317
19052
|
validateStatementStatic(resolvedStmt2);
|
|
@@ -18351,7 +19086,7 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
18351
19086
|
throw e;
|
|
18352
19087
|
}
|
|
18353
19088
|
} else {
|
|
18354
|
-
variables.set(stmt.name, evaluateScalarExpr(resolvedStmt2.expr));
|
|
19089
|
+
variables.set(stmt.name, evaluateScalarExpr(resolvedStmt2.expr, clock));
|
|
18355
19090
|
}
|
|
18356
19091
|
return {};
|
|
18357
19092
|
}
|
|
@@ -18367,7 +19102,10 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
18367
19102
|
if (Object.prototype.hasOwnProperty.call(injected, stmt.name)) {
|
|
18368
19103
|
variables.set(stmt.name, { type: "string", value: injected[stmt.name] });
|
|
18369
19104
|
} else {
|
|
18370
|
-
const value = evaluateScalarExpr(
|
|
19105
|
+
const value = evaluateScalarExpr(
|
|
19106
|
+
stmt.default,
|
|
19107
|
+
clock
|
|
19108
|
+
);
|
|
18371
19109
|
variables.set(stmt.name, {
|
|
18372
19110
|
type: "string",
|
|
18373
19111
|
value: value.type === "number" ? value.raw ?? String(value.value) : value.value
|
|
@@ -18463,8 +19201,12 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
|
|
|
18463
19201
|
}
|
|
18464
19202
|
}
|
|
18465
19203
|
if (resolvedStmt.type === "ASSERT") {
|
|
18466
|
-
await executeAssert(resolvedStmt, client, options, cacheContext, tempTables);
|
|
18467
|
-
return {};
|
|
19204
|
+
const result = await executeAssert(resolvedStmt, client, options, cacheContext, tempTables);
|
|
19205
|
+
return result.warning !== void 0 ? { result } : {};
|
|
19206
|
+
}
|
|
19207
|
+
if (resolvedStmt.type === "EXIT") {
|
|
19208
|
+
const result = await executeExit(resolvedStmt, client, options, cacheContext, tempTables);
|
|
19209
|
+
return { result, ...result.exited ? { exitTriggered: true } : {} };
|
|
18468
19210
|
}
|
|
18469
19211
|
if (info.tempTablesReferenced.length > 0) {
|
|
18470
19212
|
if (resolvedStmt.type === "SELECT" || resolvedStmt.type === "UNION") {
|
|
@@ -18588,9 +19330,9 @@ function safeJsonStringify(v) {
|
|
|
18588
19330
|
return String(v);
|
|
18589
19331
|
}
|
|
18590
19332
|
}
|
|
18591
|
-
function parseSqlBatch(sql, enableImport = false) {
|
|
19333
|
+
function parseSqlBatch(sql, enableImport = false, dialect1 = false) {
|
|
18592
19334
|
const tokens = new Lexer(sql).tokenize();
|
|
18593
|
-
return new Parser(tokens, { import: enableImport }).parseStatements();
|
|
19335
|
+
return new Parser(tokens, { import: enableImport, dialect1 }).parseStatements();
|
|
18594
19336
|
}
|
|
18595
19337
|
function parseRelativeDateVariableValue(name, value) {
|
|
18596
19338
|
try {
|
|
@@ -18618,18 +19360,18 @@ function prepareRelativeDateVariables(statements, injectedVariables) {
|
|
|
18618
19360
|
}
|
|
18619
19361
|
return prepared;
|
|
18620
19362
|
}
|
|
18621
|
-
function evaluateScalarExpr(expr) {
|
|
19363
|
+
function evaluateScalarExpr(expr, evaluationContext = {}) {
|
|
18622
19364
|
switch (expr.type) {
|
|
18623
19365
|
case "STRING":
|
|
18624
19366
|
return { type: "string", value: expr.value };
|
|
18625
19367
|
case "NUMBER":
|
|
18626
19368
|
return { type: "number", value: expr.value, raw: numberLiteralText(expr) };
|
|
18627
19369
|
case "KINTONE_FUNC":
|
|
18628
|
-
return { type: "string", value: resolveKintoneFunc(expr.name) };
|
|
19370
|
+
return { type: "string", value: resolveKintoneFunc(expr.name, evaluationContext) };
|
|
18629
19371
|
case "STRING_FUNC":
|
|
18630
|
-
return { type: "string", value: evalStringFunc(expr, {}) };
|
|
19372
|
+
return { type: "string", value: evalStringFunc(expr, {}, void 0, void 0, evaluationContext) };
|
|
18631
19373
|
case "ARITH": {
|
|
18632
|
-
const value = evalArithExpr(expr, {});
|
|
19374
|
+
const value = evalArithExpr(expr, {}, evaluationContext);
|
|
18633
19375
|
if (!Number.isFinite(value)) {
|
|
18634
19376
|
throw new Error("ArgumentError: SET scalar arithmetic produced a non-finite number.");
|
|
18635
19377
|
}
|
|
@@ -18776,6 +19518,31 @@ var ScalarSubqueryError = class extends Error {
|
|
|
18776
19518
|
}
|
|
18777
19519
|
};
|
|
18778
19520
|
async function executeAssert(stmt, client, options, cacheContext, tempTables) {
|
|
19521
|
+
const evaluation = await evaluateAssertCondition(stmt, client, options, cacheContext, tempTables);
|
|
19522
|
+
if (!evaluation.passed) {
|
|
19523
|
+
if (stmt.warn === true) {
|
|
19524
|
+
return {
|
|
19525
|
+
type: "ASSERT",
|
|
19526
|
+
condition: stmt.text,
|
|
19527
|
+
passed: false,
|
|
19528
|
+
warning: stmt.message ?? `assertion failed: ${stmt.text} (actual: ${evaluation.actual}).`
|
|
19529
|
+
};
|
|
19530
|
+
}
|
|
19531
|
+
const suffix = stmt.message !== void 0 ? ` ${stmt.message}` : "";
|
|
19532
|
+
throw new AssertError(`assertion failed: ${stmt.text} (actual: ${evaluation.actual}).${suffix}`);
|
|
19533
|
+
}
|
|
19534
|
+
return { type: "ASSERT", condition: stmt.text };
|
|
19535
|
+
}
|
|
19536
|
+
async function executeExit(stmt, client, options, cacheContext, tempTables) {
|
|
19537
|
+
const evaluation = await evaluateAssertCondition(stmt, client, options, cacheContext, tempTables);
|
|
19538
|
+
return {
|
|
19539
|
+
type: "EXIT",
|
|
19540
|
+
condition: stmt.text,
|
|
19541
|
+
exited: evaluation.passed,
|
|
19542
|
+
message: stmt.message
|
|
19543
|
+
};
|
|
19544
|
+
}
|
|
19545
|
+
async function evaluateAssertCondition(stmt, client, options, cacheContext, tempTables) {
|
|
18779
19546
|
const left = await evalAssertOperand(stmt.left, client, options, cacheContext, tempTables);
|
|
18780
19547
|
const semantics = stmt.left.type === "NUMBER" || stmt.left.type === "ARITH" ? syntheticSemantics("number") : syntheticSemantics("string");
|
|
18781
19548
|
if (stmt.op === "BETWEEN") {
|
|
@@ -18784,19 +19551,16 @@ async function executeAssert(stmt, client, options, cacheContext, tempTables) {
|
|
|
18784
19551
|
}
|
|
18785
19552
|
const low = await evalAssertOperand(stmt.low, client, options, cacheContext, tempTables);
|
|
18786
19553
|
const high = await evalAssertOperand(stmt.high, client, options, cacheContext, tempTables);
|
|
18787
|
-
|
|
18788
|
-
|
|
18789
|
-
|
|
18790
|
-
|
|
19554
|
+
return {
|
|
19555
|
+
passed: compareScalarValues(">=", left, low, semantics) && compareScalarValues("<=", left, high, semantics),
|
|
19556
|
+
actual: left
|
|
19557
|
+
};
|
|
18791
19558
|
}
|
|
18792
19559
|
if (stmt.right === null) {
|
|
18793
19560
|
throw new Error("ArgumentError: malformed ASSERT statement.");
|
|
18794
19561
|
}
|
|
18795
19562
|
const right = await evalAssertOperand(stmt.right, client, options, cacheContext, tempTables);
|
|
18796
|
-
|
|
18797
|
-
throw new AssertError(`assertion failed: ${stmt.text} (actual: ${left}).`);
|
|
18798
|
-
}
|
|
18799
|
-
return { type: "ASSERT", condition: stmt.text };
|
|
19563
|
+
return { passed: compareScalarValues(stmt.op, left, right, semantics), actual: left };
|
|
18800
19564
|
}
|
|
18801
19565
|
async function evalAssertOperand(operand, client, options, cacheContext, tempTables) {
|
|
18802
19566
|
switch (operand.type) {
|
|
@@ -19136,7 +19900,7 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
|
|
|
19136
19900
|
const subqueryWarnings = /* @__PURE__ */ new Set();
|
|
19137
19901
|
await validateSelectGroupingPlanning(stmt, client, cacheContext, cteCache);
|
|
19138
19902
|
if (isNoFromSelect(stmt)) {
|
|
19139
|
-
result = executeNoFromSelect(stmt);
|
|
19903
|
+
result = executeNoFromSelect(stmt, options);
|
|
19140
19904
|
if (captureColumnMeta) {
|
|
19141
19905
|
materializedMetaBySelectResult.set(
|
|
19142
19906
|
result,
|
|
@@ -19617,13 +20381,30 @@ function validateNoFromColumns(stmt) {
|
|
|
19617
20381
|
}
|
|
19618
20382
|
}
|
|
19619
20383
|
}
|
|
19620
|
-
function executeNoFromSelect(stmt) {
|
|
20384
|
+
function executeNoFromSelect(stmt, options) {
|
|
19621
20385
|
if (stmt.joins.length > 0 || stmt.where || normalizeGroupingSpec(stmt).type !== "NONE" || stmt.having || stmt.orderBy.length > 0 || stmt.distinct) {
|
|
19622
20386
|
throw new Error("ArgumentError: JOIN/WHERE/GROUP BY/HAVING/ORDER BY/DISTINCT are not supported without FROM.");
|
|
19623
20387
|
}
|
|
19624
20388
|
validateNoFromColumns(stmt);
|
|
19625
|
-
const windowed = applyWindow(
|
|
19626
|
-
|
|
20389
|
+
const windowed = applyWindow(
|
|
20390
|
+
[{}],
|
|
20391
|
+
stmt.columns,
|
|
20392
|
+
void 0,
|
|
20393
|
+
void 0,
|
|
20394
|
+
void 0,
|
|
20395
|
+
void 0,
|
|
20396
|
+
statementEvaluationContext(options)
|
|
20397
|
+
);
|
|
20398
|
+
const { rows: projected, columns } = project(
|
|
20399
|
+
windowed,
|
|
20400
|
+
stmt.columns,
|
|
20401
|
+
void 0,
|
|
20402
|
+
void 0,
|
|
20403
|
+
void 0,
|
|
20404
|
+
void 0,
|
|
20405
|
+
void 0,
|
|
20406
|
+
statementEvaluationContext(options)
|
|
20407
|
+
);
|
|
19627
20408
|
const rows = applyLimit(projected, stmt.limit, stmt.offset);
|
|
19628
20409
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [] };
|
|
19629
20410
|
}
|
|
@@ -19699,8 +20480,10 @@ async function executeSimpleSelect(stmt, client, options, cacheContext, orderPla
|
|
|
19699
20480
|
stmt.columns,
|
|
19700
20481
|
void 0,
|
|
19701
20482
|
fieldTypeResolvers.row,
|
|
19702
|
-
projectionSemanticsResolver
|
|
19703
|
-
|
|
20483
|
+
projectionSemanticsResolver,
|
|
20484
|
+
statementEvaluationContext(options)
|
|
20485
|
+
),
|
|
20486
|
+
statementEvaluationContext(options)
|
|
19704
20487
|
);
|
|
19705
20488
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
19706
20489
|
}
|
|
@@ -19710,7 +20493,9 @@ async function executeSimpleSelect(stmt, client, options, cacheContext, orderPla
|
|
|
19710
20493
|
void 0,
|
|
19711
20494
|
fieldTypeResolvers.row,
|
|
19712
20495
|
void 0,
|
|
19713
|
-
projectionSemanticsResolver
|
|
20496
|
+
projectionSemanticsResolver,
|
|
20497
|
+
void 0,
|
|
20498
|
+
statementEvaluationContext(options)
|
|
19714
20499
|
);
|
|
19715
20500
|
const columns = await restoreEmptyWildcardColumns(
|
|
19716
20501
|
stmt,
|
|
@@ -20873,7 +21658,8 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
20873
21658
|
...prefilterPlan ? { residualWhere: prefilterPlan.residualWhere } : boundServerFunctionPlan ? { residualWhere: boundServerFunctionPlan.joinPlan.residualWhere } : {},
|
|
20874
21659
|
resolvedGroupingSpec: resolvedGroupingSpecs.get(stmt),
|
|
20875
21660
|
plainGroupByPlan,
|
|
20876
|
-
warnings
|
|
21661
|
+
warnings,
|
|
21662
|
+
evaluationContext: statementEvaluationContext(options)
|
|
20877
21663
|
});
|
|
20878
21664
|
const columns = await restoreEmptyWildcardColumns(
|
|
20879
21665
|
stmt,
|
|
@@ -21700,7 +22486,8 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
21700
22486
|
tableColumns,
|
|
21701
22487
|
hiddenQualifiedAliases,
|
|
21702
22488
|
resolvedGroupingSpec,
|
|
21703
|
-
plainGroupByPlan
|
|
22489
|
+
plainGroupByPlan,
|
|
22490
|
+
evaluationContext: statementEvaluationContext(options)
|
|
21704
22491
|
});
|
|
21705
22492
|
const columns = await restoreEmptyWildcardColumns(
|
|
21706
22493
|
stmt,
|
|
@@ -22826,7 +23613,12 @@ async function materializeValidationCandidates(stmt, operation, client, options,
|
|
|
22826
23613
|
evaluationTypes = new Map(stmt.fields.map((field) => [field, infoByCode.get(field)?.fieldType ?? ""]));
|
|
22827
23614
|
assertCheckComparisonTypes(stmt, evaluationTypes);
|
|
22828
23615
|
rows = stmt.values.map((row) => row.map(
|
|
22829
|
-
(value, i) => value.type === "CASE_VALUE" ? evalCaseWhenValue(
|
|
23616
|
+
(value, i) => value.type === "CASE_VALUE" ? evalCaseWhenValue(
|
|
23617
|
+
value.expr,
|
|
23618
|
+
{},
|
|
23619
|
+
infoByCode.get(stmt.fields[i])?.fieldType,
|
|
23620
|
+
statementEvaluationContext(options)
|
|
23621
|
+
) : value
|
|
22830
23622
|
));
|
|
22831
23623
|
} else {
|
|
22832
23624
|
const selectResult = await dmlSourceMaterializer.materialize(stmt, client, options, cacheContext, tempTables, [...infoByCode.values()]);
|
|
@@ -22957,7 +23749,12 @@ async function materializeUpdateValidationCandidates(stmt, client, options, cach
|
|
|
22957
23749
|
});
|
|
22958
23750
|
snapshotsById = indexDmlUpdateSnapshots(resolved.records);
|
|
22959
23751
|
evaluationById = snapshotsById;
|
|
22960
|
-
records = updateToPutBatchesArith(
|
|
23752
|
+
records = updateToPutBatchesArith(
|
|
23753
|
+
stmt,
|
|
23754
|
+
resolved.records,
|
|
23755
|
+
fieldTypes,
|
|
23756
|
+
statementEvaluationContext(options)
|
|
23757
|
+
).flatMap((batch) => batch.records);
|
|
22961
23758
|
} else {
|
|
22962
23759
|
const getParams = updateToGetQuery(stmt);
|
|
22963
23760
|
if (checkTargetFields.length > 0) {
|
|
@@ -23125,7 +23922,12 @@ async function materializeUpdateFromValidationCandidates(stmt, from, client, opt
|
|
|
23125
23922
|
snapshotFields
|
|
23126
23923
|
);
|
|
23127
23924
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
23128
|
-
const records = updateFromToPutBatches(
|
|
23925
|
+
const records = updateFromToPutBatches(
|
|
23926
|
+
stmt,
|
|
23927
|
+
matched,
|
|
23928
|
+
fieldTypes,
|
|
23929
|
+
statementEvaluationContext(options)
|
|
23930
|
+
).flatMap((batch) => batch.records);
|
|
23129
23931
|
const matchedById = new Map(matched.map((pair) => [Number(pair.target["$id"]?.value), pair]));
|
|
23130
23932
|
const snapshotsById = snapshotFields ? indexDmlUpdateSnapshots(matched.map((pair) => pair.target)) : /* @__PURE__ */ new Map();
|
|
23131
23933
|
return records.sort((a, b) => a.id - b.id).map((entry, index) => ({
|
|
@@ -23357,7 +24159,7 @@ async function executeInsert(stmt, client, options, cacheContext) {
|
|
|
23357
24159
|
const fieldInfos = await loadWritableTopLevelDmlFields(stmt.appId, stmt.fields, client, cacheContext);
|
|
23358
24160
|
const numberPrecision = await loadNumberPrecisionForTargets(stmt.appId, stmt.fields, fieldInfos, client, cacheContext);
|
|
23359
24161
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
23360
|
-
const batches = insertToPostBatches(stmt, fieldTypes);
|
|
24162
|
+
const batches = insertToPostBatches(stmt, fieldTypes, statementEvaluationContext(options));
|
|
23361
24163
|
assertValidDmlRecords(batches.flatMap((batch) => batch.records), stmt.fields, fieldInfos, numberPrecision);
|
|
23362
24164
|
const createdIds = [];
|
|
23363
24165
|
for (const batch of batches) {
|
|
@@ -23966,7 +24768,12 @@ async function executeUpdate(stmt, client, options, cacheContext, tempTables) {
|
|
|
23966
24768
|
{ maxRecords, parallel: options.fetchParallel ?? 1 }
|
|
23967
24769
|
);
|
|
23968
24770
|
const records = resolved2.records;
|
|
23969
|
-
const batches2 = updateToPutBatchesArith(
|
|
24771
|
+
const batches2 = updateToPutBatchesArith(
|
|
24772
|
+
stmt,
|
|
24773
|
+
records,
|
|
24774
|
+
fieldTypes,
|
|
24775
|
+
statementEvaluationContext(options)
|
|
24776
|
+
);
|
|
23970
24777
|
assertValidDmlRecords(batches2.flatMap((batch) => batch.records.map((entry) => entry.record)), targetFields, fieldInfos, numberPrecision);
|
|
23971
24778
|
if (options.confirm) {
|
|
23972
24779
|
const ok = await options.confirm(records.length, "UPDATE");
|
|
@@ -24023,7 +24830,13 @@ async function executeApplyPatchUpdate(stmt, client, options, cacheContext, stat
|
|
|
24023
24830
|
throw new Error(`ArgumentError: APPLY snapshot $id ${actualId} does not match requested $id ${requestedId}.`);
|
|
24024
24831
|
}
|
|
24025
24832
|
requireRevision(response.records[0]);
|
|
24026
|
-
const plan = buildApplyPatchPlan({
|
|
24833
|
+
const plan = buildApplyPatchPlan({
|
|
24834
|
+
statement: stmt,
|
|
24835
|
+
snapshot: response.records[0],
|
|
24836
|
+
fieldInfos,
|
|
24837
|
+
metadata,
|
|
24838
|
+
evaluationContext: statementEvaluationContext(options)
|
|
24839
|
+
});
|
|
24027
24840
|
const fieldIndex = buildPostImageFieldIndex(
|
|
24028
24841
|
fieldInfos,
|
|
24029
24842
|
stmt.assignments.map((assignment) => assignment.field)
|
|
@@ -24222,7 +25035,8 @@ async function selectApplyParentSnapshots(stmt, client, options, fieldInfos, cac
|
|
|
24222
25035
|
row,
|
|
24223
25036
|
resolvers.fieldTypeResolver,
|
|
24224
25037
|
selectionPlan.appliedKlikes,
|
|
24225
|
-
resolvers.fieldSemanticsResolver
|
|
25038
|
+
resolvers.fieldSemanticsResolver,
|
|
25039
|
+
statementEvaluationContext(options)
|
|
24226
25040
|
)).map(({ snapshot }) => snapshot);
|
|
24227
25041
|
}
|
|
24228
25042
|
function collectApplyParentWhereFields(where) {
|
|
@@ -24463,7 +25277,12 @@ function applyValidationColumnMeta(columns, fieldInfos, appId) {
|
|
|
24463
25277
|
async function executeUpdateFrom(stmt, from, client, options, cacheContext, tempTables) {
|
|
24464
25278
|
const matched = await resolveUpdateFromMatchedRecords(stmt, from, client, options, cacheContext, tempTables);
|
|
24465
25279
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
24466
|
-
const batches = updateFromToPutBatches(
|
|
25280
|
+
const batches = updateFromToPutBatches(
|
|
25281
|
+
stmt,
|
|
25282
|
+
matched,
|
|
25283
|
+
fieldTypes,
|
|
25284
|
+
statementEvaluationContext(options)
|
|
25285
|
+
);
|
|
24467
25286
|
const targetFields = stmt.assignments.map((assignment) => assignment.field);
|
|
24468
25287
|
const fieldInfos = await getFieldsCached(stmt.appId, client, cacheContext);
|
|
24469
25288
|
const numberPrecision = await loadNumberPrecisionForTargets(stmt.appId, targetFields, fieldInfos, client, cacheContext);
|
|
@@ -24537,7 +25356,12 @@ async function executeUpsert(stmt, client, options, cacheContext) {
|
|
|
24537
25356
|
stmt.fields.forEach((field, i) => {
|
|
24538
25357
|
const val = row[i];
|
|
24539
25358
|
if (val.type === "CASE_VALUE") {
|
|
24540
|
-
record[field] = { value: evalCaseWhenValue(
|
|
25359
|
+
record[field] = { value: evalCaseWhenValue(
|
|
25360
|
+
val.expr,
|
|
25361
|
+
{},
|
|
25362
|
+
fieldTypes.get(field),
|
|
25363
|
+
statementEvaluationContext(options)
|
|
25364
|
+
) };
|
|
24541
25365
|
} else {
|
|
24542
25366
|
record[field] = { value: toKintoneValue(val, fieldTypes.get(field)) };
|
|
24543
25367
|
}
|
|
@@ -24658,7 +25482,14 @@ async function executeUpdateSubtable(stmt, client, options, cacheContext) {
|
|
|
24658
25482
|
{ maxRecords: options.maxRecords ?? 1e4, parallel: options.fetchParallel ?? 1 }
|
|
24659
25483
|
);
|
|
24660
25484
|
const expanded = expandRowsForSubtableDml(parents, subtableCode);
|
|
24661
|
-
const targets = expanded.filter((r) => evalWhere(
|
|
25485
|
+
const targets = expanded.filter((r) => evalWhere(
|
|
25486
|
+
stmt.where,
|
|
25487
|
+
r.flat,
|
|
25488
|
+
resolveFieldType,
|
|
25489
|
+
void 0,
|
|
25490
|
+
void 0,
|
|
25491
|
+
statementEvaluationContext(options)
|
|
25492
|
+
));
|
|
24662
25493
|
if (options.confirm) {
|
|
24663
25494
|
const ok = await options.confirm(targets.length, "UPDATE");
|
|
24664
25495
|
if (!ok) throw new OperationCancelledError("UPDATE", targets.length);
|
|
@@ -24678,7 +25509,12 @@ async function executeUpdateSubtable(stmt, client, options, cacheContext) {
|
|
|
24678
25509
|
if (a.field.startsWith("_")) {
|
|
24679
25510
|
throw new Error(`\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB UPDATE \u3067\u30B7\u30B9\u30C6\u30E0\u5217\u300C${a.field}\u300D\u306F\u66F4\u65B0\u3067\u304D\u307E\u305B\u3093`);
|
|
24680
25511
|
}
|
|
24681
|
-
updates[a.field] = { value: evaluateSubtableAssignmentValue(
|
|
25512
|
+
updates[a.field] = { value: evaluateSubtableAssignmentValue(
|
|
25513
|
+
a.value,
|
|
25514
|
+
t.flat,
|
|
25515
|
+
resolveFieldType,
|
|
25516
|
+
statementEvaluationContext(options)
|
|
25517
|
+
) };
|
|
24682
25518
|
}
|
|
24683
25519
|
byRid.set(t.rowId, updates);
|
|
24684
25520
|
}
|
|
@@ -24721,7 +25557,14 @@ async function executeDeleteSubtable(stmt, client, options, cacheContext) {
|
|
|
24721
25557
|
{ maxRecords: options.maxRecords ?? 1e4, parallel: options.fetchParallel ?? 1 }
|
|
24722
25558
|
);
|
|
24723
25559
|
const expanded = expandRowsForSubtableDml(parents, subtableCode);
|
|
24724
|
-
const targets = expanded.filter((r) => evalWhere(
|
|
25560
|
+
const targets = expanded.filter((r) => evalWhere(
|
|
25561
|
+
stmt.where,
|
|
25562
|
+
r.flat,
|
|
25563
|
+
resolveFieldType,
|
|
25564
|
+
void 0,
|
|
25565
|
+
void 0,
|
|
25566
|
+
statementEvaluationContext(options)
|
|
25567
|
+
));
|
|
24725
25568
|
if (options.confirm) {
|
|
24726
25569
|
const ok = await options.confirm(targets.length, "DELETE");
|
|
24727
25570
|
if (!ok) throw new OperationCancelledError("DELETE", targets.length);
|
|
@@ -24896,7 +25739,8 @@ async function executeReorder(stmt, client, options, cacheContext) {
|
|
|
24896
25739
|
r.flat,
|
|
24897
25740
|
resolveFieldType,
|
|
24898
25741
|
void 0,
|
|
24899
|
-
resolveReorderSemantics
|
|
25742
|
+
resolveReorderSemantics,
|
|
25743
|
+
statementEvaluationContext(options)
|
|
24900
25744
|
)).map((r) => r.parentId));
|
|
24901
25745
|
if (options.confirm) {
|
|
24902
25746
|
const ok = await options.confirm(targetParentIds.size, "UPDATE");
|
|
@@ -24908,7 +25752,13 @@ async function executeReorder(stmt, client, options, cacheContext) {
|
|
|
24908
25752
|
if (!parent) continue;
|
|
24909
25753
|
const rows = getMutableTableRows(parent, stmt.subtableCode);
|
|
24910
25754
|
const sortable = rows.map((row, i) => ({ row, i, flat: buildFlatRowForSort(parent, stmt.subtableCode, row, i) }));
|
|
24911
|
-
sortable.sort((a, b) => compareByOrder(
|
|
25755
|
+
sortable.sort((a, b) => compareByOrder(
|
|
25756
|
+
a.flat,
|
|
25757
|
+
b.flat,
|
|
25758
|
+
stmt.by,
|
|
25759
|
+
resolveReorderSemantics,
|
|
25760
|
+
statementEvaluationContext(options)
|
|
25761
|
+
));
|
|
24912
25762
|
const orderedRowIds = sortable.map((x) => x.row.id ?? "");
|
|
24913
25763
|
await client.putRecords(buildSubtableReorderPutParams(stmt.appId, pid, getRevision(parent), stmt.subtableCode, orderedRowIds));
|
|
24914
25764
|
}
|
|
@@ -24929,24 +25779,24 @@ function buildFlatRowForSort(parent, subtableCode, row, idx) {
|
|
|
24929
25779
|
}
|
|
24930
25780
|
return flat;
|
|
24931
25781
|
}
|
|
24932
|
-
function compareByOrder(a, b, orderBy, resolveSemantics) {
|
|
25782
|
+
function compareByOrder(a, b, orderBy, resolveSemantics, evaluationContext = {}) {
|
|
24933
25783
|
for (const item of orderBy) {
|
|
24934
|
-
const av = evalOrderKeyForRow(item.key, a);
|
|
24935
|
-
const bv = evalOrderKeyForRow(item.key, b);
|
|
25784
|
+
const av = evalOrderKeyForRow(item.key, a, evaluationContext);
|
|
25785
|
+
const bv = evalOrderKeyForRow(item.key, b, evaluationContext);
|
|
24936
25786
|
const semantics = item.key.type === "FIELD_NAME" ? resolveSemantics(aggregateFieldRef(item.key.name)) : item.key.type === "ARITH_KEY" ? syntheticSemantics("number") : item.key.type === "FUNC_KEY" ? stringFunctionColumnMeta(item.key.expr).semantics ?? syntheticSemantics("string") : syntheticSemantics("number");
|
|
24937
25787
|
const cmp = compareCanonicalValues(av, bv, semantics ?? syntheticSemantics("string"));
|
|
24938
25788
|
if (cmp !== 0) return item.direction === "ASC" ? cmp : -cmp;
|
|
24939
25789
|
}
|
|
24940
25790
|
return 0;
|
|
24941
25791
|
}
|
|
24942
|
-
function evalOrderKeyForRow(key, row) {
|
|
25792
|
+
function evalOrderKeyForRow(key, row, evaluationContext = {}) {
|
|
24943
25793
|
switch (key.type) {
|
|
24944
25794
|
case "FIELD_NAME":
|
|
24945
25795
|
return row[key.name] ?? "";
|
|
24946
25796
|
case "ARITH_KEY":
|
|
24947
|
-
return String(evalArithExpr(key.expr, row));
|
|
25797
|
+
return String(evalArithExpr(key.expr, row, evaluationContext));
|
|
24948
25798
|
case "FUNC_KEY":
|
|
24949
|
-
return evalStringFunc(key.expr, row);
|
|
25799
|
+
return evalStringFunc(key.expr, row, void 0, void 0, evaluationContext);
|
|
24950
25800
|
case "GROUPING_KEY":
|
|
24951
25801
|
throw new Error("ArgumentError: GROUPING() is not supported in REORDER BY.");
|
|
24952
25802
|
}
|
|
@@ -26044,7 +26894,16 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
|
|
|
26044
26894
|
});
|
|
26045
26895
|
const invocationCacheContext = createInvocationCacheContext(cacheContext);
|
|
26046
26896
|
try {
|
|
26047
|
-
const
|
|
26897
|
+
const header = parseScriptHeader(sql);
|
|
26898
|
+
const headerError = header.diagnostics.find((diagnostic2) => diagnostic2.severity === "error");
|
|
26899
|
+
if (header.hasDirectives && headerError) {
|
|
26900
|
+
throw new Error(`${headerError.code}: ${headerError.message} (${headerError.line}:${headerError.column})`);
|
|
26901
|
+
}
|
|
26902
|
+
const statements = parseSqlBatch(
|
|
26903
|
+
header.hasDirectives ? sql.slice(header.headerEnd) : sql,
|
|
26904
|
+
enableImport,
|
|
26905
|
+
header.hasDirectives && header.meta.dialect === 1
|
|
26906
|
+
);
|
|
26048
26907
|
const analysis = analyzeBatch(statements);
|
|
26049
26908
|
const normalizedInjectedVariables = validateDeclaredBatchVariables(statements, injectedVariables);
|
|
26050
26909
|
const relativeDateVariables = prepareRelativeDateVariables(statements, normalizedInjectedVariables);
|
|
@@ -26239,8 +27098,8 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
26239
27098
|
}
|
|
26240
27099
|
if (stmt.type === "ASSERT") {
|
|
26241
27100
|
const lines = [
|
|
26242
|
-
`ASSERT ${stmt.text}`,
|
|
26243
|
-
" check: \u5B9F\u884C\u6642\u306B\u6761\u4EF6\u8A55\u4FA1\uFF08\u4E0D\u6210\u7ACB\u306F AssertError \u3067\u30D0\u30C3\u30C1\u505C\u6B62\u3001\u4EE5\u964D\u306E\u6587\u306F skipped\uFF09"
|
|
27101
|
+
`ASSERT${stmt.warn === true ? " WARN" : ""} ${stmt.text}${stmt.message !== void 0 ? `, '${stmt.message.replace(/'/g, "''")}'` : ""}`,
|
|
27102
|
+
stmt.warn === true ? " check: \u5B9F\u884C\u6642\u306B\u6761\u4EF6\u8A55\u4FA1\uFF08\u4E0D\u6210\u7ACB\u306F\u8B66\u544A\u3068\u3057\u3066\u8A18\u9332\u3057\u3001\u5F8C\u7D9A\u6587\u3092\u7D9A\u884C\uFF09" : " check: \u5B9F\u884C\u6642\u306B\u6761\u4EF6\u8A55\u4FA1\uFF08\u4E0D\u6210\u7ACB\u306F AssertError \u3067\u30D0\u30C3\u30C1\u505C\u6B62\u3001\u4EE5\u964D\u306E\u6587\u306F skipped\uFF09"
|
|
26244
27103
|
];
|
|
26245
27104
|
const subqueries = [stmt.left, stmt.right, stmt.low, stmt.high].filter(
|
|
26246
27105
|
(o) => o !== null && o.type === "SCALAR_SUBQUERY"
|
|
@@ -26262,6 +27121,31 @@ function buildBatchStatementPlan(stmt, info, capabilities, orderPlans, plainGrou
|
|
|
26262
27121
|
});
|
|
26263
27122
|
return lines;
|
|
26264
27123
|
}
|
|
27124
|
+
if (stmt.type === "EXIT") {
|
|
27125
|
+
const lines = [
|
|
27126
|
+
`EXIT SUCCESS IF ${stmt.text}, '${stmt.message.replace(/'/g, "''")}'`,
|
|
27127
|
+
" check: \u5B9F\u884C\u6642\u306B\u6761\u4EF6\u8A55\u4FA1\uFF08\u6210\u7ACB\u6642\u306F\u6B63\u5E38\u7D42\u4E86\u3057\u3001\u4EE5\u964D\u306E\u6587\u306F skippedReason: exit\uFF09"
|
|
27128
|
+
];
|
|
27129
|
+
const subqueries = [stmt.left, stmt.right, stmt.low, stmt.high].filter(
|
|
27130
|
+
(o) => o !== null && o.type === "SCALAR_SUBQUERY"
|
|
27131
|
+
);
|
|
27132
|
+
subqueries.forEach((sq, i) => {
|
|
27133
|
+
lines.push(subqueries.length > 1 ? ` subquery[${i + 1}]:` : " subquery:");
|
|
27134
|
+
const subInfo = hasTempTableRef(sq.query) ? info : { ...info, tempTablesReferenced: [] };
|
|
27135
|
+
lines.push(...buildPlanForBatchQuery(
|
|
27136
|
+
sq.query,
|
|
27137
|
+
subInfo,
|
|
27138
|
+
capabilities,
|
|
27139
|
+
orderPlans,
|
|
27140
|
+
plainGroupByPlans,
|
|
27141
|
+
collector,
|
|
27142
|
+
"main",
|
|
27143
|
+
tempSchemaLedger,
|
|
27144
|
+
explainContext
|
|
27145
|
+
).map((line) => ` ${line}`));
|
|
27146
|
+
});
|
|
27147
|
+
return lines;
|
|
27148
|
+
}
|
|
26265
27149
|
if (stmt.type === "UPDATE" && (stmt.applyBlocks?.length ?? 0) > 0) {
|
|
26266
27150
|
return buildExplainPlan(
|
|
26267
27151
|
stmt,
|
|
@@ -27749,6 +28633,9 @@ function toMutationSummary(result) {
|
|
|
27749
28633
|
...result.errTable !== void 0 ? { errTable: result.errTable } : {}
|
|
27750
28634
|
};
|
|
27751
28635
|
}
|
|
28636
|
+
if (result.type === "EXIT") {
|
|
28637
|
+
return { condition: result.condition, exited: result.exited, message: result.message };
|
|
28638
|
+
}
|
|
27752
28639
|
return { reorderedParentCount: result.reorderedParentCount };
|
|
27753
28640
|
}
|
|
27754
28641
|
function buildBatchEnvelope(batch, options = {}) {
|
|
@@ -27806,6 +28693,10 @@ function buildBatchEnvelope(batch, options = {}) {
|
|
|
27806
28693
|
...s.result.deletedRows ? { deletedRows: s.result.deletedRows } : {},
|
|
27807
28694
|
...s.result.diagnostic ? { diagnostic: s.result.diagnostic } : {}
|
|
27808
28695
|
});
|
|
28696
|
+
} else if (s.status === "success" && s.result?.type === "ASSERT") {
|
|
28697
|
+
entry.condition = s.result.condition;
|
|
28698
|
+
if (s.result.passed !== void 0) entry.passed = s.result.passed;
|
|
28699
|
+
if (s.result.warning !== void 0) entry.warning = s.result.warning;
|
|
27809
28700
|
} else if (s.status === "success" && s.result && s.result.type !== "SELECT" && s.result.type !== "ASSERT") {
|
|
27810
28701
|
Object.assign(entry, toMutationSummary(s.result));
|
|
27811
28702
|
}
|