@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 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(value.expr, row, resolveFieldType);
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(value, targetRow)) };
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(value.expr, targetRow, fieldType) };
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(statement, snapshot, metadata, parentId);
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(statement, snapshot, metadata, parentId);
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(operation, targetChildren, block.field);
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(operation, snapshotRows, childTypeResolver, block.field);
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(operation, snapshotRows, childTypeResolver, block.field);
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(assignment.value, flat, childTypeResolver)
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(assignment.value, parentRow, fieldType, snapshot)
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(operation.selector, rows, resolveFieldType, table);
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(operation.selector, rows, resolveFieldType, table);
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(where, flattenSubtableSnapshotRow(row, index), resolveFieldType) ? [index] : []
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(where, row, resolveFieldType, appliedKlikes, resolveFieldSemantics2));
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(k.expr, groupRows[0]));
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(k.expr, groupRows[0]);
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(outRow, groupRows, columns, resolveAggSortKind);
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(outRow, groupRows, columns, resolveAggSortKind);
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(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
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(outRow, columnIndex, evalStringFunc(resolvedExpr, outRow), [outputKey]);
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(key.expr, row);
14785
- return String(evalArithExpr(key.expr, row));
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(node.func, node.distinct, node.arg, node.separator, rows, resolveAggSortKind));
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(rows, orderBy, optionOrders, sortKinds, fieldSemantics2, aliasEvaluator).rows.map((item) => item.row);
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(column.expr, sourceRowForEvaluation(row))));
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(column.expr, sourceRowForEvaluation(row), resolveFieldType, resolveFieldSemantics2) : evalStringFunc(column.expr, sourceRowForEvaluation(row), resolveFieldType, resolveFieldSemantics2));
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(column.expr, sourceRowForEvaluation(row), resolveFieldType, resolveFieldSemantics2));
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(partition, window.orderBy, optionOrders, sortKinds, fieldSemantics2);
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(window, columnIndex, sortedResult, resolveAggSortKind);
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(arg, sourceRowForEvaluation(row));
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(window.arg, item.row));
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(window.aggFunc, window.arg, sorted.map((item) => item.row));
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 evaluationContext = {
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, evaluationContext);
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(rows, filterWhere, fieldTypeResolver, appliedKlikes, fieldSemanticsResolver);
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(rows, stmt.having, havingFieldTypeResolver, resolveHavingSemantics);
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(stmt.columns, scalarCache, fieldTypeResolver, fieldSemanticsResolver)
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(stmt.where, row.flat, (field) => evaluationTypes.get(field.field)));
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 statements = parseSqlBatch(sql, options.enableImport === true);
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
- results.push({ ...base, status: "success", ...outcome });
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(stmt, info, client, options, cacheContext, tempTables, variables, relativeDateVariables) {
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(stmt.default);
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
- if (!compareScalarValues(">=", left, low, semantics) || !compareScalarValues("<=", left, high, semantics)) {
18788
- throw new AssertError(`assertion failed: ${stmt.text} (actual: ${left}).`);
18789
- }
18790
- return { type: "ASSERT", condition: stmt.text };
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
- if (!compareScalarValues(stmt.op, left, right, semantics)) {
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([{}], stmt.columns);
19626
- const { rows: projected, columns } = project(windowed, stmt.columns);
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(value.expr, {}, infoByCode.get(stmt.fields[i])?.fieldType) : value
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(stmt, resolved.records, fieldTypes).flatMap((batch) => batch.records);
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(stmt, matched, fieldTypes).flatMap((batch) => batch.records);
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(stmt, records, fieldTypes);
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({ statement: stmt, snapshot: response.records[0], fieldInfos, metadata });
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(stmt, matched, fieldTypes);
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(val.expr, {}, fieldTypes.get(field)) };
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(stmt.where, r.flat, resolveFieldType));
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(a.value, t.flat, resolveFieldType) };
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(stmt.where, r.flat, resolveFieldType));
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(a.flat, b.flat, stmt.by, resolveReorderSemantics));
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 statements = parseSqlBatch(sql, enableImport);
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
  }