@rex0220/kintone-sql-tools 3.3.0 → 3.4.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 +803 -113
- package/dist-mcp/ksql-mcp.js +804 -114
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -31219,6 +31219,10 @@ var Lexer = class {
|
|
|
31219
31219
|
this.pos += 2;
|
|
31220
31220
|
return this.makeToken("<=" /* LTE */, "<=", start);
|
|
31221
31221
|
}
|
|
31222
|
+
if (ch === "|" && ch2 === "|") {
|
|
31223
|
+
this.pos += 2;
|
|
31224
|
+
return this.makeToken("||" /* CONCAT_OP */, "||", start);
|
|
31225
|
+
}
|
|
31222
31226
|
switch (ch) {
|
|
31223
31227
|
case "=":
|
|
31224
31228
|
this.pos++;
|
|
@@ -31562,6 +31566,8 @@ var Parser = class {
|
|
|
31562
31566
|
constructor(tokens) {
|
|
31563
31567
|
this.tokens = tokens;
|
|
31564
31568
|
this.allowUnaryPlusNumber = false;
|
|
31569
|
+
this.scalarAllowsAggregateArgs = true;
|
|
31570
|
+
this.scalarAllowsCase = true;
|
|
31565
31571
|
this.pos = 0;
|
|
31566
31572
|
/** WITH 句で定義された CTE 名のセット(parseTableRef で参照) */
|
|
31567
31573
|
this.cteNames = /* @__PURE__ */ new Set();
|
|
@@ -31730,17 +31736,19 @@ var Parser = class {
|
|
|
31730
31736
|
}
|
|
31731
31737
|
rejectNonScalarExpr(node, tok, context) {
|
|
31732
31738
|
if (node.type === "STRING" || node.type === "NUMBER") return;
|
|
31733
|
-
if (node.type === "FIELD_REF" || node.type === "AGG_REF") {
|
|
31739
|
+
if (node.type === "FIELD_REF" || node.type === "FIELD" || node.type === "VARIABLE" || node.type === "AGG_REF") {
|
|
31734
31740
|
throw new ParseError(`${context} \u306E\u53F3\u8FBA\u3067\u306F\u30D5\u30A3\u30FC\u30EB\u30C9\u53C2\u7167\u30FB\u96C6\u8A08\u95A2\u6570\u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`, tok);
|
|
31735
31741
|
}
|
|
31736
|
-
if (node.type === "ARITH" || node.type === "AGG_ARITH") {
|
|
31742
|
+
if (node.type === "ARITH" || node.type === "SCALAR_ARITH" || node.type === "CONCAT_OP" || node.type === "AGG_ARITH") {
|
|
31737
31743
|
this.rejectNonScalarExpr(node.left, tok, context);
|
|
31738
31744
|
this.rejectNonScalarExpr(node.right, tok, context);
|
|
31739
31745
|
return;
|
|
31740
31746
|
}
|
|
31741
31747
|
if (node.type === "STRING_FUNC") {
|
|
31742
31748
|
for (const arg of node.args) this.rejectNonScalarExpr(arg, tok, context);
|
|
31749
|
+
return;
|
|
31743
31750
|
}
|
|
31751
|
+
throw new ParseError(`${context} \u306E\u53F3\u8FBA\u3067\u306F CASE \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`, tok);
|
|
31744
31752
|
}
|
|
31745
31753
|
// ----------------------------------------------------------
|
|
31746
31754
|
// CREATE TEMP TABLE / DROP TEMP TABLE(バッチ内一時テーブル)
|
|
@@ -32111,6 +32119,11 @@ var Parser = class {
|
|
|
32111
32119
|
if (this.consume("*" /* STAR */)) {
|
|
32112
32120
|
return { type: "WILDCARD" };
|
|
32113
32121
|
}
|
|
32122
|
+
if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
32123
|
+
const expr = this.parseScalarValueExpr({ allowAggregateArgs: true });
|
|
32124
|
+
const alias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
|
|
32125
|
+
return { type: "SCALAR_VALUE_COL", expr, alias: alias2 };
|
|
32126
|
+
}
|
|
32114
32127
|
const windowFunc = this.tryWindowFunc();
|
|
32115
32128
|
if (windowFunc !== null) {
|
|
32116
32129
|
return this.parseWindowColumn(windowFunc);
|
|
@@ -32226,13 +32239,25 @@ var Parser = class {
|
|
|
32226
32239
|
}
|
|
32227
32240
|
selectColumnHasAggregate(column) {
|
|
32228
32241
|
if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
|
|
32229
|
-
if (column.type
|
|
32230
|
-
|
|
32242
|
+
if (column.type === "STRFUNC_COL") return column.expr.args.some((arg) => this.stringFuncArgHasAggregate(arg));
|
|
32243
|
+
if (column.type === "SCALAR_VALUE_COL") return this.scalarValueHasAggregate(column.expr);
|
|
32244
|
+
return false;
|
|
32231
32245
|
}
|
|
32232
32246
|
stringFuncArgHasAggregate(arg) {
|
|
32233
32247
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
32234
|
-
|
|
32235
|
-
|
|
32248
|
+
return this.scalarValueHasAggregate(arg);
|
|
32249
|
+
}
|
|
32250
|
+
scalarValueHasAggregate(expr) {
|
|
32251
|
+
if (expr.type === "STRING_FUNC") return expr.args.some((arg) => this.stringFuncArgHasAggregate(arg));
|
|
32252
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
32253
|
+
return this.scalarValueHasAggregate(expr.left) || this.scalarValueHasAggregate(expr.right);
|
|
32254
|
+
}
|
|
32255
|
+
if (expr.type === "CASE_WHEN") {
|
|
32256
|
+
const results = [...expr.branches.map((b) => b.result), ...expr.elseResult ? [expr.elseResult] : []];
|
|
32257
|
+
return results.some((result) => {
|
|
32258
|
+
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
|
|
32259
|
+
return this.scalarValueHasAggregate(result);
|
|
32260
|
+
});
|
|
32236
32261
|
}
|
|
32237
32262
|
return false;
|
|
32238
32263
|
}
|
|
@@ -32290,6 +32315,105 @@ var Parser = class {
|
|
|
32290
32315
|
throw new ParseError("\u96C6\u8A08\u7B97\u8853\u5F0F\u306B\u306F\u96C6\u8A08\u95A2\u6570\u307E\u305F\u306F\u6570\u5024\u304C\u5FC5\u8981\u3067\u3059", this.peek());
|
|
32291
32316
|
}
|
|
32292
32317
|
// ──────────────────────────────────────────────────
|
|
32318
|
+
// 汎用スカラー値式パーサー(B38)
|
|
32319
|
+
// ──────────────────────────────────────────────────
|
|
32320
|
+
/** 比較・述語・集約・サブクエリを含まない値式の公開入口。 */
|
|
32321
|
+
parseScalarValueExpr(options = {}) {
|
|
32322
|
+
const previousAggregateArgs = this.scalarAllowsAggregateArgs;
|
|
32323
|
+
const previousCase = this.scalarAllowsCase;
|
|
32324
|
+
this.scalarAllowsAggregateArgs = options.allowAggregateArgs === true;
|
|
32325
|
+
this.scalarAllowsCase = options.allowCase !== false;
|
|
32326
|
+
let expr;
|
|
32327
|
+
try {
|
|
32328
|
+
expr = this.parseScalarAddSubConcat(this.scalarAllowsCase);
|
|
32329
|
+
} finally {
|
|
32330
|
+
this.scalarAllowsAggregateArgs = previousAggregateArgs;
|
|
32331
|
+
this.scalarAllowsCase = previousCase;
|
|
32332
|
+
}
|
|
32333
|
+
const next = this.peek();
|
|
32334
|
+
if (next.kind === "IS" /* IS */ || next.kind === "=" /* EQ */ || next.kind === "!=" /* NEQ */ || next.kind === "<>" /* LT_GT */ || next.kind === ">" /* GT */ || next.kind === "<" /* LT */ || next.kind === ">=" /* GTE */ || next.kind === "<=" /* LTE */ || next.kind === "LIKE" /* LIKE */ || next.kind === "KLIKE" /* KLIKE */ || next.kind === "IN" /* IN */ || next.kind === "BETWEEN" /* BETWEEN */) throw new ParseError("\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u306B\u6BD4\u8F03\u30FB\u8FF0\u8A9E\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", next);
|
|
32335
|
+
return expr;
|
|
32336
|
+
}
|
|
32337
|
+
parseScalarAddSubConcat(allowCase) {
|
|
32338
|
+
let left = this.parseScalarMulDiv(allowCase);
|
|
32339
|
+
while (this.peek().kind === "+" /* PLUS */ || this.peek().kind === "-" /* MINUS */ || this.peek().kind === "||" /* CONCAT_OP */) {
|
|
32340
|
+
const token = this.advance();
|
|
32341
|
+
const right = this.parseScalarMulDiv(allowCase);
|
|
32342
|
+
left = token.kind === "||" /* CONCAT_OP */ ? { type: "CONCAT_OP", left, right } : { type: "SCALAR_ARITH", left, op: token.kind === "+" /* PLUS */ ? "+" : "-", right };
|
|
32343
|
+
}
|
|
32344
|
+
return left;
|
|
32345
|
+
}
|
|
32346
|
+
parseScalarMulDiv(allowCase) {
|
|
32347
|
+
let left = this.parseScalarPrimary(allowCase);
|
|
32348
|
+
while (this.peek().kind === "*" /* STAR */ || this.peek().kind === "/" /* SLASH */ || this.peek().kind === "%" /* PERCENT */) {
|
|
32349
|
+
const token = this.advance();
|
|
32350
|
+
const op = token.kind === "*" /* STAR */ ? "*" : token.kind === "/" /* SLASH */ ? "/" : "%";
|
|
32351
|
+
left = { type: "SCALAR_ARITH", left, op, right: this.parseScalarPrimary(allowCase) };
|
|
32352
|
+
}
|
|
32353
|
+
return left;
|
|
32354
|
+
}
|
|
32355
|
+
parseScalarPrimary(allowCase) {
|
|
32356
|
+
const tok = this.peek();
|
|
32357
|
+
if (tok.kind === "(" /* LPAREN */) {
|
|
32358
|
+
if (this.peekAt(1).kind === "SELECT" /* SELECT */) throw new ParseError("\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u306B\u30B5\u30D6\u30AF\u30A8\u30EA\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
|
|
32359
|
+
this.advance();
|
|
32360
|
+
const expr = this.parseScalarAddSubConcat(allowCase);
|
|
32361
|
+
this.expect(")" /* RPAREN */);
|
|
32362
|
+
return expr;
|
|
32363
|
+
}
|
|
32364
|
+
if (tok.kind === "+" /* PLUS */ || tok.kind === "-" /* MINUS */) {
|
|
32365
|
+
this.advance();
|
|
32366
|
+
if (this.peek().kind === "+" /* PLUS */ || this.peek().kind === "-" /* MINUS */) {
|
|
32367
|
+
throw new ParseError("\u5358\u9805\u7B26\u53F7\u3092\u91CD\u306D\u3066\u6307\u5B9A\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093", this.peek());
|
|
32368
|
+
}
|
|
32369
|
+
const operand = this.parseScalarPrimary(allowCase);
|
|
32370
|
+
if (operand.type === "NUMBER") {
|
|
32371
|
+
return makeNumberLiteral(`${tok.kind === "-" /* MINUS */ ? "-" : "+"}${numberLiteralText(operand)}`);
|
|
32372
|
+
}
|
|
32373
|
+
if (tok.kind === "+" /* PLUS */) throw new ParseError("\u5358\u9805 + \u306E\u76F4\u5F8C\u306B\u306F\u6570\u5024\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059", tok);
|
|
32374
|
+
return { type: "SCALAR_ARITH", left: makeNumberLiteral("0"), op: "-", right: operand };
|
|
32375
|
+
}
|
|
32376
|
+
if (tok.kind === "STRING" /* STRING */) {
|
|
32377
|
+
this.advance();
|
|
32378
|
+
return { type: "STRING", value: tok.value };
|
|
32379
|
+
}
|
|
32380
|
+
if (tok.kind === "NUMBER" /* NUMBER */) {
|
|
32381
|
+
this.advance();
|
|
32382
|
+
return makeNumberLiteral(tok.value);
|
|
32383
|
+
}
|
|
32384
|
+
if (tok.kind === "VARIABLE" /* VARIABLE */) {
|
|
32385
|
+
this.advance();
|
|
32386
|
+
return { type: "VARIABLE", name: tok.value.slice(1).toLowerCase() };
|
|
32387
|
+
}
|
|
32388
|
+
if (tok.kind === "CASE" /* CASE */) {
|
|
32389
|
+
if (!allowCase) throw new ParseError("\u3053\u306E\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u3067\u306F CASE \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
|
|
32390
|
+
return this.parseCaseWhenExpr();
|
|
32391
|
+
}
|
|
32392
|
+
if (this.tryAggregateFunc() !== null) throw new ParseError("\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u306B\u96C6\u7D04\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", tok);
|
|
32393
|
+
if (this.tryStringFuncName() !== null) return this.parseStringFuncExpr();
|
|
32394
|
+
if (tok.kind === "IDENT" /* IDENT */ || tok.kind === "BIDENT" /* BIDENT */) {
|
|
32395
|
+
this.advance();
|
|
32396
|
+
if (this.consume("." /* DOT */)) return { type: "FIELD", tableAlias: tok.value, field: this.parseIdentifier() };
|
|
32397
|
+
return { type: "FIELD", tableAlias: null, field: tok.value };
|
|
32398
|
+
}
|
|
32399
|
+
throw new ParseError("\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u306E\u30AA\u30DA\u30E9\u30F3\u30C9\u304C\u5FC5\u8981\u3067\u3059", tok);
|
|
32400
|
+
}
|
|
32401
|
+
/** 現在の値の終端までに指定トークンがあるか(括弧内も対象)。 */
|
|
32402
|
+
hasTopLevelTokenBeforeValueEnd(target) {
|
|
32403
|
+
let depth = 0;
|
|
32404
|
+
for (let i = this.pos; i < this.tokens.length; i++) {
|
|
32405
|
+
const kind = this.tokens[i].kind;
|
|
32406
|
+
if (kind === "(" /* LPAREN */ || kind === "[" /* LBRACKET */) depth++;
|
|
32407
|
+
else if (kind === ")" /* RPAREN */ || kind === "]" /* RBRACKET */) {
|
|
32408
|
+
if (depth === 0) break;
|
|
32409
|
+
depth--;
|
|
32410
|
+
}
|
|
32411
|
+
if (kind === target) return true;
|
|
32412
|
+
if (depth === 0 && (kind === "," /* COMMA */ || kind === "AS" /* AS */ || kind === "FROM" /* FROM */ || kind === "WHERE" /* WHERE */ || kind === "WHEN" /* WHEN */ || kind === "THEN" /* THEN */ || kind === "ELSE" /* ELSE */ || kind === "END" /* END */ || kind === ";" /* SEMICOLON */ || kind === "EOF" /* EOF */)) break;
|
|
32413
|
+
}
|
|
32414
|
+
return false;
|
|
32415
|
+
}
|
|
32416
|
+
// ──────────────────────────────────────────────────
|
|
32293
32417
|
// 算術式パーサー(演算子優先順位: * / > + -)
|
|
32294
32418
|
//
|
|
32295
32419
|
// parseArithAddSub : + -(左結合・低優先度)
|
|
@@ -32411,12 +32535,15 @@ var Parser = class {
|
|
|
32411
32535
|
this.expect("END" /* END */);
|
|
32412
32536
|
return { type: "CASE_WHEN", branches, elseResult };
|
|
32413
32537
|
}
|
|
32414
|
-
/** THEN / ELSE
|
|
32538
|
+
/** THEN / ELSE の結果値。`||` を含む場合だけ新スカラー文法へ渡す。 */
|
|
32415
32539
|
parseCaseResult() {
|
|
32416
32540
|
const tok = this.peek();
|
|
32417
32541
|
if (tok.kind === "[" /* LBRACKET */) {
|
|
32418
32542
|
return this.parseArrayLiteral();
|
|
32419
32543
|
}
|
|
32544
|
+
if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
32545
|
+
return this.parseScalarValueExpr({ allowAggregateArgs: true });
|
|
32546
|
+
}
|
|
32420
32547
|
if (tok.kind === "STRING" /* STRING */) {
|
|
32421
32548
|
this.advance();
|
|
32422
32549
|
return { type: "STRING", value: tok.value };
|
|
@@ -32564,25 +32691,19 @@ var Parser = class {
|
|
|
32564
32691
|
}
|
|
32565
32692
|
return { type: "STRING", value: normalized };
|
|
32566
32693
|
}
|
|
32567
|
-
/** 文字列関数の引数:
|
|
32694
|
+
/** 文字列関数の引数: ScalarValueExpr / 集計算術式 */
|
|
32568
32695
|
parseStringFuncArg() {
|
|
32569
|
-
|
|
32570
|
-
|
|
32571
|
-
|
|
32572
|
-
|
|
32573
|
-
|
|
32574
|
-
|
|
32575
|
-
|
|
32576
|
-
|
|
32577
|
-
|
|
32578
|
-
try {
|
|
32579
|
-
const left = this.parseAggPrimary();
|
|
32580
|
-
const expr = this.continueAggArith(left);
|
|
32581
|
-
if (this.hasAggregateOperand(expr)) return expr;
|
|
32582
|
-
} catch {
|
|
32696
|
+
if (this.scalarAllowsAggregateArgs) {
|
|
32697
|
+
const startPos = this.pos;
|
|
32698
|
+
try {
|
|
32699
|
+
const left = this.parseAggPrimary();
|
|
32700
|
+
const expr = this.continueAggArith(left);
|
|
32701
|
+
if (this.hasAggregateOperand(expr)) return expr;
|
|
32702
|
+
} catch {
|
|
32703
|
+
}
|
|
32704
|
+
this.pos = startPos;
|
|
32583
32705
|
}
|
|
32584
|
-
this.
|
|
32585
|
-
return this.parseArithAddSub();
|
|
32706
|
+
return this.parseScalarAddSubConcat(this.scalarAllowsCase);
|
|
32586
32707
|
}
|
|
32587
32708
|
hasAggregateOperand(node) {
|
|
32588
32709
|
if (node.type === "AGG_REF") return true;
|
|
@@ -32670,6 +32791,7 @@ var Parser = class {
|
|
|
32670
32791
|
const k = this.peek().kind;
|
|
32671
32792
|
if (k === "IDENT" /* IDENT */ || k === "BIDENT" /* BIDENT */) {
|
|
32672
32793
|
if (k === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === "VALIDATE" && this.peekAt(1).kind === "IDENT" /* IDENT */ && this.peekAt(1).value.toUpperCase() === "ONLY") return null;
|
|
32794
|
+
if (k === "IDENT" /* IDENT */ && this.peek().value.toUpperCase() === "CHECK" && this.peekAt(1).kind === "WHEN" /* WHEN */) return null;
|
|
32673
32795
|
return this.parseTableAliasName();
|
|
32674
32796
|
}
|
|
32675
32797
|
return null;
|
|
@@ -33135,8 +33257,9 @@ var Parser = class {
|
|
|
33135
33257
|
if (subtableCode) {
|
|
33136
33258
|
throw new ParseError("INSERT INTO ... SELECT \u306F\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB\u4EEE\u60F3\u30C6\u30FC\u30D6\u30EB\u3067\u306F\u672A\u5BFE\u5FDC\u3067\u3059", this.prev());
|
|
33137
33259
|
}
|
|
33260
|
+
const checkGroups2 = this.parseCheckGroups();
|
|
33138
33261
|
const validation2 = this.parseDmlControlSuffix();
|
|
33139
|
-
return { type: "INSERT_SELECT", appId, fields, select, ...validation2 };
|
|
33262
|
+
return { type: "INSERT_SELECT", appId, fields, select, ...checkGroups2, ...validation2 };
|
|
33140
33263
|
}
|
|
33141
33264
|
this.expect("VALUES" /* VALUES */);
|
|
33142
33265
|
const values = [];
|
|
@@ -33146,11 +33269,15 @@ var Parser = class {
|
|
|
33146
33269
|
this.expect(")" /* RPAREN */);
|
|
33147
33270
|
values.push(row);
|
|
33148
33271
|
} while (this.consume("," /* COMMA */));
|
|
33272
|
+
const checkGroups = this.parseCheckGroups();
|
|
33149
33273
|
const validation = this.parseDmlControlSuffix();
|
|
33274
|
+
if (subtableCode && checkGroups.checkGroups) {
|
|
33275
|
+
throw new ParseError("CHECK \u306F\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB INSERT \u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093", this.prev());
|
|
33276
|
+
}
|
|
33150
33277
|
if (subtableCode && (validation.validateOnly || validation.onErrorSkip)) {
|
|
33151
33278
|
throw new ParseError("VALIDATE ONLY / ON ERROR SKIP \u306F\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB INSERT \u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093", this.prev());
|
|
33152
33279
|
}
|
|
33153
|
-
return subtableCode ? { type: "INSERT", appId, subtableCode, fields, values, ...validation } : { type: "INSERT", appId, fields, values, ...validation };
|
|
33280
|
+
return subtableCode ? { type: "INSERT", appId, subtableCode, fields, values, ...checkGroups, ...validation } : { type: "INSERT", appId, fields, values, ...checkGroups, ...validation };
|
|
33154
33281
|
}
|
|
33155
33282
|
parseUpsert() {
|
|
33156
33283
|
this.expect("UPSERT" /* UPSERT */);
|
|
@@ -33167,8 +33294,9 @@ var Parser = class {
|
|
|
33167
33294
|
if (this.peek().kind === "SELECT" /* SELECT */) {
|
|
33168
33295
|
const select = this.parseSelect();
|
|
33169
33296
|
const keyFields2 = this.parseOnDuplicate();
|
|
33297
|
+
const checkGroups2 = this.parseCheckGroups();
|
|
33170
33298
|
const validation2 = this.parseDmlControlSuffix();
|
|
33171
|
-
return { type: "UPSERT_SELECT", appId, fields, select, keyFields: keyFields2, ...validation2 };
|
|
33299
|
+
return { type: "UPSERT_SELECT", appId, fields, select, keyFields: keyFields2, ...checkGroups2, ...validation2 };
|
|
33172
33300
|
}
|
|
33173
33301
|
this.expect("VALUES" /* VALUES */);
|
|
33174
33302
|
const values = [];
|
|
@@ -33178,8 +33306,9 @@ var Parser = class {
|
|
|
33178
33306
|
this.expect(")" /* RPAREN */);
|
|
33179
33307
|
} while (this.consume("," /* COMMA */));
|
|
33180
33308
|
const keyFields = this.parseOnDuplicate();
|
|
33309
|
+
const checkGroups = this.parseCheckGroups();
|
|
33181
33310
|
const validation = this.parseDmlControlSuffix();
|
|
33182
|
-
return { type: "UPSERT", appId, fields, values, keyFields, ...validation };
|
|
33311
|
+
return { type: "UPSERT", appId, fields, values, keyFields, ...checkGroups, ...validation };
|
|
33183
33312
|
}
|
|
33184
33313
|
parseOnDuplicate() {
|
|
33185
33314
|
this.expectKeyword("ON" /* ON */, "UPSERT \u306B\u306F ON DUPLICATE (\u30AD\u30FC\u30D5\u30A3\u30FC\u30EB\u30C9) \u304C\u5FC5\u8981\u3067\u3059");
|
|
@@ -33311,12 +33440,33 @@ var Parser = class {
|
|
|
33311
33440
|
whereTok
|
|
33312
33441
|
);
|
|
33313
33442
|
}
|
|
33443
|
+
const checkGroups = this.parseCheckGroups();
|
|
33314
33444
|
const validation = this.parseDmlControlSuffix();
|
|
33445
|
+
if (subtableCode && checkGroups.checkGroups) {
|
|
33446
|
+
throw new ParseError("CHECK \u306F\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB UPDATE \u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093", this.prev());
|
|
33447
|
+
}
|
|
33315
33448
|
if (subtableCode && (validation.validateOnly || validation.onErrorSkip)) {
|
|
33316
33449
|
throw new ParseError("VALIDATE ONLY / ON ERROR SKIP \u306F\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB UPDATE \u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093", this.prev());
|
|
33317
33450
|
}
|
|
33318
|
-
if (from !== null) return { type: "UPDATE", appId, assignments, where, from, ...validation };
|
|
33319
|
-
return subtableCode ? { type: "UPDATE", appId, subtableCode, assignments, where, ...validation } : { type: "UPDATE", appId, assignments, where, ...validation };
|
|
33451
|
+
if (from !== null) return { type: "UPDATE", appId, assignments, where, from, ...checkGroups, ...validation };
|
|
33452
|
+
return subtableCode ? { type: "UPDATE", appId, subtableCode, assignments, where, ...checkGroups, ...validation } : { type: "UPDATE", appId, assignments, where, ...checkGroups, ...validation };
|
|
33453
|
+
}
|
|
33454
|
+
/** CHECK WHEN ... THEN ... blocks. CHECK is a soft keyword. */
|
|
33455
|
+
parseCheckGroups() {
|
|
33456
|
+
const groups = [];
|
|
33457
|
+
while (this.isSoftKeyword("CHECK") && this.peekAt(1).kind === "WHEN" /* WHEN */) {
|
|
33458
|
+
const check2 = this.advance();
|
|
33459
|
+
const rules = [];
|
|
33460
|
+
while (this.consume("WHEN" /* WHEN */)) {
|
|
33461
|
+
const condition = this.parseWhereExpr();
|
|
33462
|
+
this.expect("THEN" /* THEN */, "CHECK WHEN \u306E\u6761\u4EF6\u306E\u5F8C\u306B\u306F THEN \u304C\u5FC5\u8981\u3067\u3059");
|
|
33463
|
+
const message = this.parseScalarValueExpr({ allowCase: false });
|
|
33464
|
+
rules.push({ condition, message });
|
|
33465
|
+
}
|
|
33466
|
+
if (rules.length === 0) throw new ParseError("CHECK \u306E\u5F8C\u306B\u306F WHEN \u304C\u6700\u4F4E 1 \u3064\u5FC5\u8981\u3067\u3059", check2);
|
|
33467
|
+
groups.push({ rules });
|
|
33468
|
+
}
|
|
33469
|
+
return groups.length > 0 ? { checkGroups: groups } : {};
|
|
33320
33470
|
}
|
|
33321
33471
|
/** DML末尾の VALIDATE ONLY または ON ERROR SKIP。各語はsoft keyword。 */
|
|
33322
33472
|
parseDmlControlSuffix() {
|
|
@@ -33505,6 +33655,12 @@ var Parser = class {
|
|
|
33505
33655
|
*/
|
|
33506
33656
|
parseAssignmentValue() {
|
|
33507
33657
|
const tok = this.peek();
|
|
33658
|
+
if (this.hasTopLevelTokenBeforeValueEnd("||" /* CONCAT_OP */)) {
|
|
33659
|
+
const expr = this.parseScalarValueExpr();
|
|
33660
|
+
if (expr.type === "CONCAT_OP" || expr.type === "SCALAR_ARITH" || expr.type === "STRING_FUNC") return expr;
|
|
33661
|
+
if (expr.type === "CASE_WHEN") return { type: "CASE_VALUE", expr };
|
|
33662
|
+
throw new ParseError("SET \u306E\u5024\u306B\u306F\u9023\u7D50\u3092\u542B\u3080\u30B9\u30AB\u30E9\u30FC\u5024\u5F0F\u304C\u5FC5\u8981\u3067\u3059", tok);
|
|
33663
|
+
}
|
|
33508
33664
|
if (tok.kind === "VARIABLE" /* VARIABLE */) return this.parseSqlValue();
|
|
33509
33665
|
if (tok.kind === "STRING" /* STRING */) return this.parseSqlValue();
|
|
33510
33666
|
if (tok.kind === "TODAY" /* TODAY */ || tok.kind === "NOW" /* NOW */ || tok.kind === "LOGINUSER" /* LOGINUSER */) return this.parseSqlValue();
|
|
@@ -34116,7 +34272,7 @@ function resolveSelectMode(stmt) {
|
|
|
34116
34272
|
if (stmt.distinct) return "FULL_SCAN";
|
|
34117
34273
|
if (hasWindowColumns(stmt.columns)) return "FULL_SCAN";
|
|
34118
34274
|
if (stmt.columns.some(
|
|
34119
|
-
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr)
|
|
34275
|
+
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr) || c.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate(c.expr)
|
|
34120
34276
|
)) return "FULL_SCAN";
|
|
34121
34277
|
if (whereRequiresJsEval(stmt.where)) return "FULL_SCAN";
|
|
34122
34278
|
if (stmt.orderBy.some((o) => o.key.type !== "FIELD_NAME")) return "FULL_SCAN";
|
|
@@ -34211,6 +34367,8 @@ function extractFields(columns) {
|
|
|
34211
34367
|
collectArithNode(col.expr, fields);
|
|
34212
34368
|
} else if (col.type === "STRFUNC_COL") {
|
|
34213
34369
|
collectStringFuncFields(col.expr, fields);
|
|
34370
|
+
} else if (col.type === "SCALAR_VALUE_COL") {
|
|
34371
|
+
collectScalarValueFields(col.expr, fields);
|
|
34214
34372
|
}
|
|
34215
34373
|
}
|
|
34216
34374
|
return [...new Set(fields)];
|
|
@@ -34236,16 +34394,38 @@ function collectStringFuncFields(expr, out) {
|
|
|
34236
34394
|
}
|
|
34237
34395
|
}
|
|
34238
34396
|
function collectStringFuncArgFields(arg, out) {
|
|
34239
|
-
if (arg.type === "STRING") return;
|
|
34240
|
-
if (arg.type === "STRING_FUNC") {
|
|
34241
|
-
collectStringFuncFields(arg, out);
|
|
34242
|
-
return;
|
|
34243
|
-
}
|
|
34244
34397
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
34245
34398
|
collectAggOperandFields(arg, out);
|
|
34246
34399
|
return;
|
|
34247
34400
|
}
|
|
34248
|
-
|
|
34401
|
+
collectScalarValueFields(arg, out);
|
|
34402
|
+
}
|
|
34403
|
+
function collectScalarValueFields(expr, out) {
|
|
34404
|
+
if (expr.type === "FIELD") {
|
|
34405
|
+
out.push(normalizeSimpleFieldRef(expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field));
|
|
34406
|
+
return;
|
|
34407
|
+
}
|
|
34408
|
+
if (expr.type === "STRING_FUNC") {
|
|
34409
|
+
collectStringFuncFields(expr, out);
|
|
34410
|
+
return;
|
|
34411
|
+
}
|
|
34412
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
34413
|
+
collectScalarValueFields(expr.left, out);
|
|
34414
|
+
collectScalarValueFields(expr.right, out);
|
|
34415
|
+
return;
|
|
34416
|
+
}
|
|
34417
|
+
if (expr.type === "CASE_WHEN") {
|
|
34418
|
+
for (const branch of expr.branches) collectCaseResultScalarFields(branch.result, out);
|
|
34419
|
+
if (expr.elseResult) collectCaseResultScalarFields(expr.elseResult, out);
|
|
34420
|
+
}
|
|
34421
|
+
}
|
|
34422
|
+
function collectCaseResultScalarFields(result, out) {
|
|
34423
|
+
if (result.type === "ARRAY") return;
|
|
34424
|
+
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
34425
|
+
collectArithNode(result, out);
|
|
34426
|
+
return;
|
|
34427
|
+
}
|
|
34428
|
+
collectScalarValueFields(result, out);
|
|
34249
34429
|
}
|
|
34250
34430
|
function collectAggOperandFields(node, out) {
|
|
34251
34431
|
if (node.type === "AGG_REF") {
|
|
@@ -34260,10 +34440,23 @@ function collectAggOperandFields(node, out) {
|
|
|
34260
34440
|
function hasAggregateInStringFuncExpr(expr) {
|
|
34261
34441
|
return expr.args.some((arg) => {
|
|
34262
34442
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
34263
|
-
|
|
34264
|
-
return false;
|
|
34443
|
+
return scalarValueHasAggregate(arg);
|
|
34265
34444
|
});
|
|
34266
34445
|
}
|
|
34446
|
+
function scalarValueHasAggregate(expr) {
|
|
34447
|
+
if (expr.type === "STRING_FUNC") return hasAggregateInStringFuncExpr(expr);
|
|
34448
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
34449
|
+
return scalarValueHasAggregate(expr.left) || scalarValueHasAggregate(expr.right);
|
|
34450
|
+
}
|
|
34451
|
+
if (expr.type === "CASE_WHEN") {
|
|
34452
|
+
return expr.branches.some((b) => caseResultHasAggregate(b.result)) || expr.elseResult !== null && caseResultHasAggregate(expr.elseResult);
|
|
34453
|
+
}
|
|
34454
|
+
return false;
|
|
34455
|
+
}
|
|
34456
|
+
function caseResultHasAggregate(result) {
|
|
34457
|
+
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
|
|
34458
|
+
return scalarValueHasAggregate(result);
|
|
34459
|
+
}
|
|
34267
34460
|
function collectRequiredFieldsByTable(stmt) {
|
|
34268
34461
|
const physicalTables = [stmt.from, ...stmt.joins.map((j) => j.table)].filter((t) => t.cteName === null);
|
|
34269
34462
|
const states = /* @__PURE__ */ new Map();
|
|
@@ -34398,28 +34591,38 @@ function collectRequiredFieldsByTable(stmt) {
|
|
|
34398
34591
|
}
|
|
34399
34592
|
};
|
|
34400
34593
|
const walkStringArg = (arg, phase = "select") => {
|
|
34401
|
-
if (arg.type === "STRING") return;
|
|
34402
|
-
if (arg.type === "STRING_FUNC") {
|
|
34403
|
-
walkStringFunc(arg, phase);
|
|
34404
|
-
return;
|
|
34405
|
-
}
|
|
34406
34594
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
34407
34595
|
walkAgg(arg, phase);
|
|
34408
34596
|
return;
|
|
34409
34597
|
}
|
|
34410
|
-
|
|
34598
|
+
walkScalar(arg, phase);
|
|
34411
34599
|
};
|
|
34412
34600
|
const walkStringFunc = (expr, phase = "select") => {
|
|
34413
34601
|
for (const arg of expr.args) walkStringArg(arg, phase);
|
|
34414
34602
|
};
|
|
34603
|
+
const walkScalar = (expr, phase = "select") => {
|
|
34604
|
+
if (expr.type === "FIELD") {
|
|
34605
|
+
addFieldRef(expr.field, expr.tableAlias, phase);
|
|
34606
|
+
return;
|
|
34607
|
+
}
|
|
34608
|
+
if (expr.type === "STRING_FUNC") {
|
|
34609
|
+
walkStringFunc(expr, phase);
|
|
34610
|
+
return;
|
|
34611
|
+
}
|
|
34612
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
34613
|
+
walkScalar(expr.left, phase);
|
|
34614
|
+
walkScalar(expr.right, phase);
|
|
34615
|
+
return;
|
|
34616
|
+
}
|
|
34617
|
+
if (expr.type === "CASE_WHEN") walkCase(expr, phase);
|
|
34618
|
+
};
|
|
34415
34619
|
const walkCaseResult = (result, phase = "select") => {
|
|
34416
|
-
if (result.type === "STRING") return;
|
|
34417
34620
|
if (result.type === "ARRAY") return;
|
|
34418
|
-
if (result.type === "
|
|
34419
|
-
|
|
34621
|
+
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
34622
|
+
walkArith(result, phase);
|
|
34420
34623
|
return;
|
|
34421
34624
|
}
|
|
34422
|
-
|
|
34625
|
+
walkScalar(result, phase);
|
|
34423
34626
|
};
|
|
34424
34627
|
const walkCase = (expr, phase = "select") => {
|
|
34425
34628
|
for (const b of expr.branches) {
|
|
@@ -34525,6 +34728,9 @@ function collectRequiredFieldsByTable(stmt) {
|
|
|
34525
34728
|
case "STRFUNC_COL":
|
|
34526
34729
|
walkStringFunc(col.expr, "select");
|
|
34527
34730
|
break;
|
|
34731
|
+
case "SCALAR_VALUE_COL":
|
|
34732
|
+
walkScalar(col.expr, "select");
|
|
34733
|
+
break;
|
|
34528
34734
|
case "SCALAR_SUBQUERY_COL":
|
|
34529
34735
|
break;
|
|
34530
34736
|
case "WINDOW_COL":
|
|
@@ -34575,6 +34781,10 @@ function collectSelectOutputNames(columns) {
|
|
|
34575
34781
|
if (col.alias) names.add(col.alias);
|
|
34576
34782
|
continue;
|
|
34577
34783
|
}
|
|
34784
|
+
if (col.type === "SCALAR_VALUE_COL") {
|
|
34785
|
+
if (col.alias) names.add(col.alias);
|
|
34786
|
+
continue;
|
|
34787
|
+
}
|
|
34578
34788
|
if (col.type === "SCALAR_SUBQUERY_COL") {
|
|
34579
34789
|
names.add(col.alias ?? "(subquery)");
|
|
34580
34790
|
continue;
|
|
@@ -34597,14 +34807,32 @@ function arithNodeLabel(node) {
|
|
|
34597
34807
|
}
|
|
34598
34808
|
function stringFuncLabel(expr) {
|
|
34599
34809
|
const args = expr.args.map((a) => {
|
|
34600
|
-
if (a.type === "STRING") return `'${a.value}'`;
|
|
34601
|
-
if (a.type === "STRING_FUNC") return stringFuncLabel(a);
|
|
34602
34810
|
if (a.type === "AGG_REF") return aggregateSyntheticName(a.func, a.distinct, a.arg);
|
|
34603
34811
|
if (a.type === "AGG_ARITH") return "agg_arith";
|
|
34604
|
-
return
|
|
34812
|
+
return scalarValueLabel(a);
|
|
34605
34813
|
});
|
|
34606
34814
|
return `${expr.func}(${args.join(",")})`;
|
|
34607
34815
|
}
|
|
34816
|
+
function scalarValueLabel(expr) {
|
|
34817
|
+
switch (expr.type) {
|
|
34818
|
+
case "STRING":
|
|
34819
|
+
return `'${expr.value}'`;
|
|
34820
|
+
case "NUMBER":
|
|
34821
|
+
return numberLiteralText(expr);
|
|
34822
|
+
case "VARIABLE":
|
|
34823
|
+
return `@${expr.name}`;
|
|
34824
|
+
case "FIELD":
|
|
34825
|
+
return expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field;
|
|
34826
|
+
case "STRING_FUNC":
|
|
34827
|
+
return stringFuncLabel(expr);
|
|
34828
|
+
case "CASE_WHEN":
|
|
34829
|
+
return "case";
|
|
34830
|
+
case "SCALAR_ARITH":
|
|
34831
|
+
return `(${scalarValueLabel(expr.left)}${expr.op}${scalarValueLabel(expr.right)})`;
|
|
34832
|
+
case "CONCAT_OP":
|
|
34833
|
+
return `(${scalarValueLabel(expr.left)}||${scalarValueLabel(expr.right)})`;
|
|
34834
|
+
}
|
|
34835
|
+
}
|
|
34608
34836
|
function isAggregateSyntheticName(name) {
|
|
34609
34837
|
return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
|
|
34610
34838
|
}
|
|
@@ -35547,6 +35775,45 @@ function evalArithExpr(expr, row) {
|
|
|
35547
35775
|
return r !== 0 ? l % r : NaN;
|
|
35548
35776
|
}
|
|
35549
35777
|
}
|
|
35778
|
+
function evalScalarValueExpr(expr, row) {
|
|
35779
|
+
switch (expr.type) {
|
|
35780
|
+
case "STRING":
|
|
35781
|
+
return expr.value;
|
|
35782
|
+
case "NUMBER":
|
|
35783
|
+
return expr.value;
|
|
35784
|
+
case "FIELD":
|
|
35785
|
+
return resolveFieldRef(row, expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field);
|
|
35786
|
+
case "VARIABLE":
|
|
35787
|
+
throw new Error(`ArgumentError: unresolved variable @${expr.name} reached scalar evaluator.`);
|
|
35788
|
+
case "STRING_FUNC":
|
|
35789
|
+
return evalStringFunc(expr, row);
|
|
35790
|
+
case "CASE_WHEN":
|
|
35791
|
+
return evalCaseWhen(expr, row);
|
|
35792
|
+
case "CONCAT_OP": {
|
|
35793
|
+
return evalStringFunc({
|
|
35794
|
+
type: "STRING_FUNC",
|
|
35795
|
+
func: "CONCAT",
|
|
35796
|
+
args: [expr.left, expr.right]
|
|
35797
|
+
}, row);
|
|
35798
|
+
}
|
|
35799
|
+
case "SCALAR_ARITH": {
|
|
35800
|
+
const left = Number(evalScalarValueExpr(expr.left, row));
|
|
35801
|
+
const right = Number(evalScalarValueExpr(expr.right, row));
|
|
35802
|
+
switch (expr.op) {
|
|
35803
|
+
case "+":
|
|
35804
|
+
return left + right;
|
|
35805
|
+
case "-":
|
|
35806
|
+
return left - right;
|
|
35807
|
+
case "*":
|
|
35808
|
+
return left * right;
|
|
35809
|
+
case "/":
|
|
35810
|
+
return right !== 0 ? left / right : NaN;
|
|
35811
|
+
case "%":
|
|
35812
|
+
return right !== 0 ? left % right : NaN;
|
|
35813
|
+
}
|
|
35814
|
+
}
|
|
35815
|
+
}
|
|
35816
|
+
}
|
|
35550
35817
|
function applyRoundOp(op, num, digits) {
|
|
35551
35818
|
const factor = Math.pow(10, digits);
|
|
35552
35819
|
const raw = Math[op](num * factor) / factor;
|
|
@@ -35949,12 +36216,9 @@ function formatWithComma(num, digits) {
|
|
|
35949
36216
|
return decStr ? `${intFmt}.${decStr}` : intFmt;
|
|
35950
36217
|
}
|
|
35951
36218
|
function evalStringFuncArg(arg, row) {
|
|
35952
|
-
if (arg.type === "STRING") return arg.value;
|
|
35953
|
-
if (arg.type === "STRING_FUNC") return evalStringFunc(arg, row);
|
|
35954
|
-
if (arg.type === "FIELD_REF") return resolveFieldRef(row, arg.field);
|
|
35955
|
-
if (arg.type === "NUMBER") return numberLiteralText(arg);
|
|
35956
36219
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return "";
|
|
35957
|
-
|
|
36220
|
+
if (arg.type === "NUMBER") return numberLiteralText(arg);
|
|
36221
|
+
return String(evalScalarValueExpr(arg, row));
|
|
35958
36222
|
}
|
|
35959
36223
|
function resolveFieldRef(row, field) {
|
|
35960
36224
|
const direct = row[field];
|
|
@@ -36177,10 +36441,13 @@ function evalCaseWhen(expr, row, resolveFieldType, resolveFieldSemantics2) {
|
|
|
36177
36441
|
}
|
|
36178
36442
|
function evalCaseResult(result, row) {
|
|
36179
36443
|
if (result.type === "ARRAY") return result.elements.map((e) => e.value).join(",");
|
|
36180
|
-
if (result.type === "
|
|
36181
|
-
|
|
36182
|
-
|
|
36183
|
-
|
|
36444
|
+
if (result.type === "FIELD_REF") {
|
|
36445
|
+
return row[result.field] ?? "";
|
|
36446
|
+
}
|
|
36447
|
+
if (result.type === "ARITH") {
|
|
36448
|
+
return String(evalArithExpr(result, row));
|
|
36449
|
+
}
|
|
36450
|
+
return String(evalScalarValueExpr(result, row));
|
|
36184
36451
|
}
|
|
36185
36452
|
function resolveKintoneFunc(name) {
|
|
36186
36453
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -36224,6 +36491,63 @@ function matchLike(value, pattern) {
|
|
|
36224
36491
|
return regex.test(value);
|
|
36225
36492
|
}
|
|
36226
36493
|
|
|
36494
|
+
// src/core/dmlCustomCheck.ts
|
|
36495
|
+
function collectCheckFieldRefs(groups) {
|
|
36496
|
+
return collectRefs2(groups);
|
|
36497
|
+
}
|
|
36498
|
+
function collectCheckComparisonFieldRefs(groups) {
|
|
36499
|
+
return collectRefs2(groups.flatMap((group) => group.rules.map((rule) => rule.condition)));
|
|
36500
|
+
}
|
|
36501
|
+
function collectRefs2(root) {
|
|
36502
|
+
const refs = [];
|
|
36503
|
+
const seen = /* @__PURE__ */ new Set();
|
|
36504
|
+
const visit = (node) => {
|
|
36505
|
+
if (Array.isArray(node)) {
|
|
36506
|
+
node.forEach(visit);
|
|
36507
|
+
return;
|
|
36508
|
+
}
|
|
36509
|
+
if (node === null || typeof node !== "object") return;
|
|
36510
|
+
const obj = node;
|
|
36511
|
+
if (obj.type === "EXISTS" || obj.type === "SUBQUERY_IN_LIST" || obj.type === "SCALAR_SUBQUERY") {
|
|
36512
|
+
throw customCheckParseError("CHECK \u306B\u30B5\u30D6\u30AF\u30A8\u30EA\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093");
|
|
36513
|
+
}
|
|
36514
|
+
if (obj.type === "FIELD" && typeof obj.field === "string") {
|
|
36515
|
+
add(typeof obj.tableAlias === "string" ? obj.tableAlias : null, obj.field);
|
|
36516
|
+
} else if (obj.type === "FIELD_REF" && typeof obj.field === "string") {
|
|
36517
|
+
const dot = obj.field.indexOf(".");
|
|
36518
|
+
add(dot > 0 ? obj.field.slice(0, dot) : null, dot > 0 ? obj.field.slice(dot + 1) : obj.field);
|
|
36519
|
+
}
|
|
36520
|
+
for (const value of Object.values(obj)) visit(value);
|
|
36521
|
+
};
|
|
36522
|
+
const add = (tableAlias, field) => {
|
|
36523
|
+
if (/^(COUNT|SUM|AVG|MIN|MAX|GROUP_CONCAT)\(/i.test(field)) {
|
|
36524
|
+
throw customCheckParseError("CHECK \u306B\u96C6\u7D04\u95A2\u6570\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093");
|
|
36525
|
+
}
|
|
36526
|
+
const key = `${tableAlias ?? ""}\0${field}`;
|
|
36527
|
+
if (!seen.has(key)) {
|
|
36528
|
+
seen.add(key);
|
|
36529
|
+
refs.push({ tableAlias, field });
|
|
36530
|
+
}
|
|
36531
|
+
};
|
|
36532
|
+
visit(root);
|
|
36533
|
+
return refs;
|
|
36534
|
+
}
|
|
36535
|
+
function customCheckParseError(message) {
|
|
36536
|
+
return new ParseError(message, { kind: "EOF" /* EOF */, value: "CHECK", pos: 0 });
|
|
36537
|
+
}
|
|
36538
|
+
function evaluateCustomChecks(groups, row, resolveFieldType) {
|
|
36539
|
+
const errors = [];
|
|
36540
|
+
groups.forEach((group, groupIndex) => {
|
|
36541
|
+
for (const rule of group.rules) {
|
|
36542
|
+
if (!evalWhere(rule.condition, row, resolveFieldType)) continue;
|
|
36543
|
+
const value = evalScalarValueExpr(rule.message, row);
|
|
36544
|
+
errors.push({ groupIndex, message: value == null ? "" : String(value) });
|
|
36545
|
+
break;
|
|
36546
|
+
}
|
|
36547
|
+
});
|
|
36548
|
+
return errors;
|
|
36549
|
+
}
|
|
36550
|
+
|
|
36227
36551
|
// src/converter/dmlToKintone.ts
|
|
36228
36552
|
function assertDmlWhereIsSafe(where) {
|
|
36229
36553
|
if (whereHasKlike(where)) {
|
|
@@ -36261,10 +36585,11 @@ function buildInsertRecord(fields, row, fieldTypes) {
|
|
|
36261
36585
|
}
|
|
36262
36586
|
function updateToGetQuery(stmt) {
|
|
36263
36587
|
assertDmlWhereIsSafe(stmt.where);
|
|
36588
|
+
const checkFields = collectUpdateCheckTargetFields(stmt);
|
|
36264
36589
|
return {
|
|
36265
36590
|
app: stmt.appId,
|
|
36266
36591
|
query: whereToKintone(stmt.where),
|
|
36267
|
-
fields: ["$id"],
|
|
36592
|
+
fields: ["$id", ...checkFields],
|
|
36268
36593
|
totalCount: false
|
|
36269
36594
|
};
|
|
36270
36595
|
}
|
|
@@ -36278,19 +36603,19 @@ function updateToPutBatches(stmt, ids, fieldTypes = /* @__PURE__ */ new Map()) {
|
|
|
36278
36603
|
function buildUpdateRecord(assignments, fieldTypes) {
|
|
36279
36604
|
const record2 = {};
|
|
36280
36605
|
for (const { field, value } of assignments) {
|
|
36281
|
-
if (value.type === "ARITH" || value.type === "CASE_VALUE" || value.type === "STRING_FUNC" || value.type === "SOURCE_FIELD") continue;
|
|
36606
|
+
if (value.type === "ARITH" || value.type === "SCALAR_ARITH" || value.type === "CONCAT_OP" || value.type === "CASE_VALUE" || value.type === "STRING_FUNC" || value.type === "SOURCE_FIELD") continue;
|
|
36282
36607
|
record2[field] = { value: toKintoneValue(value, fieldTypes.get(field)) };
|
|
36283
36608
|
}
|
|
36284
36609
|
return record2;
|
|
36285
36610
|
}
|
|
36286
36611
|
function hasArithAssignment(stmt) {
|
|
36287
36612
|
return stmt.assignments.some(
|
|
36288
|
-
(a) => a.value.type === "ARITH" || a.value.type === "CASE_VALUE"
|
|
36613
|
+
(a) => a.value.type === "ARITH" || a.value.type === "SCALAR_ARITH" || a.value.type === "CONCAT_OP" || a.value.type === "CASE_VALUE"
|
|
36289
36614
|
);
|
|
36290
36615
|
}
|
|
36291
36616
|
function hasRowDependentAssignment(stmt) {
|
|
36292
36617
|
return stmt.assignments.some(
|
|
36293
|
-
(a) => a.value.type === "ARITH" || a.value.type === "CASE_VALUE" || a.value.type === "STRING_FUNC"
|
|
36618
|
+
(a) => a.value.type === "ARITH" || a.value.type === "SCALAR_ARITH" || a.value.type === "CONCAT_OP" || a.value.type === "CASE_VALUE" || a.value.type === "STRING_FUNC"
|
|
36294
36619
|
);
|
|
36295
36620
|
}
|
|
36296
36621
|
function updateToGetQueryForArith(stmt) {
|
|
@@ -36299,12 +36624,15 @@ function updateToGetQueryForArith(stmt) {
|
|
|
36299
36624
|
for (const { value } of stmt.assignments) {
|
|
36300
36625
|
if (value.type === "ARITH") {
|
|
36301
36626
|
collectArithFields2(value, refFields);
|
|
36627
|
+
} else if (value.type === "SCALAR_ARITH" || value.type === "CONCAT_OP") {
|
|
36628
|
+
collectScalarValueFields2(value, refFields);
|
|
36302
36629
|
} else if (value.type === "STRING_FUNC") {
|
|
36303
36630
|
collectStringFuncFields2(value, refFields);
|
|
36304
36631
|
} else if (value.type === "CASE_VALUE") {
|
|
36305
36632
|
collectCaseFields(value.expr, refFields);
|
|
36306
36633
|
}
|
|
36307
36634
|
}
|
|
36635
|
+
collectUpdateCheckTargetFields(stmt).forEach((field) => refFields.add(field));
|
|
36308
36636
|
return {
|
|
36309
36637
|
app: stmt.appId,
|
|
36310
36638
|
query: whereToKintone(stmt.where),
|
|
@@ -36325,16 +36653,27 @@ function collectStringFuncFields2(expr, out) {
|
|
|
36325
36653
|
for (const arg of expr.args) collectStringFuncArgFields2(arg, out);
|
|
36326
36654
|
}
|
|
36327
36655
|
function collectStringFuncArgFields2(arg, out) {
|
|
36328
|
-
if (arg.type === "STRING") return;
|
|
36329
|
-
if (arg.type === "STRING_FUNC") {
|
|
36330
|
-
collectStringFuncFields2(arg, out);
|
|
36331
|
-
return;
|
|
36332
|
-
}
|
|
36333
36656
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
36334
36657
|
collectAggOperandFields2(arg, out);
|
|
36335
36658
|
return;
|
|
36336
36659
|
}
|
|
36337
|
-
|
|
36660
|
+
collectScalarValueFields2(arg, out);
|
|
36661
|
+
}
|
|
36662
|
+
function collectScalarValueFields2(expr, out) {
|
|
36663
|
+
if (expr.type === "FIELD") {
|
|
36664
|
+
out.add(expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field);
|
|
36665
|
+
return;
|
|
36666
|
+
}
|
|
36667
|
+
if (expr.type === "STRING_FUNC") {
|
|
36668
|
+
collectStringFuncFields2(expr, out);
|
|
36669
|
+
return;
|
|
36670
|
+
}
|
|
36671
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
36672
|
+
collectScalarValueFields2(expr.left, out);
|
|
36673
|
+
collectScalarValueFields2(expr.right, out);
|
|
36674
|
+
return;
|
|
36675
|
+
}
|
|
36676
|
+
if (expr.type === "CASE_WHEN") collectCaseFields(expr, out);
|
|
36338
36677
|
}
|
|
36339
36678
|
function collectAggOperandFields2(node, out) {
|
|
36340
36679
|
if (node.type === "AGG_REF") {
|
|
@@ -36347,9 +36686,12 @@ function collectAggOperandFields2(node, out) {
|
|
|
36347
36686
|
}
|
|
36348
36687
|
}
|
|
36349
36688
|
function collectCaseResultFields(result, out) {
|
|
36350
|
-
if (result.type === "STRING") return;
|
|
36351
36689
|
if (result.type === "ARRAY") return;
|
|
36352
|
-
|
|
36690
|
+
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
36691
|
+
collectArithNode2(result, out);
|
|
36692
|
+
return;
|
|
36693
|
+
}
|
|
36694
|
+
collectScalarValueFields2(result, out);
|
|
36353
36695
|
}
|
|
36354
36696
|
function collectCaseFields(expr, out) {
|
|
36355
36697
|
for (const branch of expr.branches) {
|
|
@@ -36387,6 +36729,8 @@ function updateToPutBatchesArith(stmt, records, fieldTypes = /* @__PURE__ */ new
|
|
|
36387
36729
|
for (const { field, value } of stmt.assignments) {
|
|
36388
36730
|
if (value.type === "ARITH") {
|
|
36389
36731
|
record2[field] = { value: String(evalArith(value, raw)) };
|
|
36732
|
+
} else if (value.type === "SCALAR_ARITH" || value.type === "CONCAT_OP") {
|
|
36733
|
+
record2[field] = { value: String(evalScalarValueExpr(value, row)) };
|
|
36390
36734
|
} else if (value.type === "STRING_FUNC") {
|
|
36391
36735
|
record2[field] = { value: evalStringFunc(value, row) };
|
|
36392
36736
|
} else if (value.type === "CASE_VALUE") {
|
|
@@ -36441,6 +36785,8 @@ function updateFromToPutBatches(stmt, matched, fieldTypes = /* @__PURE__ */ new
|
|
|
36441
36785
|
throw new DmlConvertError("UPDATE ... FROM \u306E SET \u3067\u306F\u6587\u5B57\u5217\u95A2\u6570\u3092\u76F4\u63A5\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093");
|
|
36442
36786
|
} else if (value.type === "ARITH") {
|
|
36443
36787
|
record2[field] = { value: String(evalArith(value, target)) };
|
|
36788
|
+
} else if (value.type === "SCALAR_ARITH" || value.type === "CONCAT_OP") {
|
|
36789
|
+
record2[field] = { value: String(evalScalarValueExpr(value, targetRow)) };
|
|
36444
36790
|
} else if (value.type === "CASE_VALUE") {
|
|
36445
36791
|
record2[field] = { value: evalCaseWhenValue(value.expr, targetRow, fieldType) };
|
|
36446
36792
|
} else {
|
|
@@ -36551,7 +36897,15 @@ function evalCaseResultValue(result, row, fieldType) {
|
|
|
36551
36897
|
if (result.type === "STRING_FUNC") {
|
|
36552
36898
|
return evalStringFunc(result, row);
|
|
36553
36899
|
}
|
|
36554
|
-
|
|
36900
|
+
if (result.type === "FIELD_REF" || result.type === "ARITH") {
|
|
36901
|
+
return String(evalArithExpr(result, row));
|
|
36902
|
+
}
|
|
36903
|
+
return String(evalScalarValueExpr(result, row));
|
|
36904
|
+
}
|
|
36905
|
+
function collectUpdateCheckTargetFields(stmt) {
|
|
36906
|
+
if (!stmt.checkGroups) return [];
|
|
36907
|
+
const targetAlias = `app${stmt.appId}`.toLowerCase();
|
|
36908
|
+
return [...new Set(collectCheckFieldRefs(stmt.checkGroups).filter((ref) => ref.tableAlias === null || ref.tableAlias.toLowerCase() === targetAlias).map((ref) => ref.field).filter((field) => field !== "$id"))];
|
|
36555
36909
|
}
|
|
36556
36910
|
function evalCaseWhenValue(expr, row, fieldType) {
|
|
36557
36911
|
for (const branch of expr.branches) {
|
|
@@ -37104,7 +37458,7 @@ function applyFilter(rows, where, resolveFieldType, appliedKlikes, resolveFieldS
|
|
|
37104
37458
|
}
|
|
37105
37459
|
function hasAggregateColumns(columns) {
|
|
37106
37460
|
return columns.some(
|
|
37107
|
-
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(c.expr)
|
|
37461
|
+
(c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr2(c.expr) || c.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(c.expr)
|
|
37108
37462
|
);
|
|
37109
37463
|
}
|
|
37110
37464
|
function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
@@ -37141,6 +37495,10 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
|
|
|
37141
37495
|
const outputKey = col.alias ?? stringFuncDefaultKey(col.expr);
|
|
37142
37496
|
const resolvedExpr = resolveAggInStringFuncExpr(col.expr, groupRows, resolveAggSortKind);
|
|
37143
37497
|
outRow[outputKey] = evalStringFunc(resolvedExpr, outRow);
|
|
37498
|
+
} else if (col.type === "SCALAR_VALUE_COL" && scalarValueHasAggregate2(col.expr)) {
|
|
37499
|
+
const outputKey = col.alias ?? scalarValueDefaultKey(col.expr);
|
|
37500
|
+
const resolvedExpr = resolveAggInScalarValue(col.expr, groupRows, resolveAggSortKind);
|
|
37501
|
+
outRow[outputKey] = String(evalScalarValueExpr(resolvedExpr, outRow));
|
|
37144
37502
|
}
|
|
37145
37503
|
}
|
|
37146
37504
|
result.push(outRow);
|
|
@@ -37471,6 +37829,13 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns, re
|
|
|
37471
37829
|
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
37472
37830
|
break;
|
|
37473
37831
|
}
|
|
37832
|
+
case "SCALAR_VALUE_COL": {
|
|
37833
|
+
const key = outputKeys?.[colIdx] ?? col.alias ?? scalarValueDefaultKey(col.expr);
|
|
37834
|
+
const srcKey = scalarValueDefaultKey(col.expr);
|
|
37835
|
+
out[key] = scalarValueHasAggregate2(col.expr) ? row[col.alias ?? srcKey] ?? row[srcKey] ?? "" : String(evalScalarValueExpr(col.expr, row));
|
|
37836
|
+
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
37837
|
+
break;
|
|
37838
|
+
}
|
|
37474
37839
|
case "SCALAR_SUBQUERY_COL": {
|
|
37475
37840
|
const key = outputKeys?.[colIdx] ?? col.alias ?? "(subquery)";
|
|
37476
37841
|
out[key] = scalarCache?.get(colIdx) ?? "";
|
|
@@ -37521,6 +37886,8 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
|
|
|
37521
37886
|
return col.alias ?? "case";
|
|
37522
37887
|
case "STRFUNC_COL":
|
|
37523
37888
|
return col.alias ?? stringFuncDefaultKey(col.expr);
|
|
37889
|
+
case "SCALAR_VALUE_COL":
|
|
37890
|
+
return col.alias ?? scalarValueDefaultKey(col.expr);
|
|
37524
37891
|
case "SCALAR_SUBQUERY_COL":
|
|
37525
37892
|
return col.alias ?? "(subquery)";
|
|
37526
37893
|
case "WINDOW_COL":
|
|
@@ -37576,18 +37943,49 @@ function arithColDefaultKey(expr) {
|
|
|
37576
37943
|
}
|
|
37577
37944
|
function stringFuncDefaultKey(expr) {
|
|
37578
37945
|
const argStrs = expr.args.map((a) => {
|
|
37579
|
-
if (a.type === "STRING") return `'${a.value}'`;
|
|
37580
|
-
if (a.type === "STRING_FUNC") return stringFuncDefaultKey(a);
|
|
37581
37946
|
if (a.type === "AGG_REF" || a.type === "AGG_ARITH") return aggArithDefaultKey(a);
|
|
37582
|
-
return
|
|
37947
|
+
return scalarValueDefaultKey(a);
|
|
37583
37948
|
});
|
|
37584
37949
|
return `${expr.func}(${argStrs.join(",")})`;
|
|
37585
37950
|
}
|
|
37951
|
+
function scalarValueDefaultKey(expr) {
|
|
37952
|
+
switch (expr.type) {
|
|
37953
|
+
case "STRING":
|
|
37954
|
+
return `'${expr.value}'`;
|
|
37955
|
+
case "NUMBER":
|
|
37956
|
+
return numberLiteralText(expr);
|
|
37957
|
+
case "VARIABLE":
|
|
37958
|
+
return `@${expr.name}`;
|
|
37959
|
+
case "FIELD":
|
|
37960
|
+
return expr.tableAlias ? `${expr.tableAlias}.${expr.field}` : expr.field;
|
|
37961
|
+
case "STRING_FUNC":
|
|
37962
|
+
return stringFuncDefaultKey(expr);
|
|
37963
|
+
case "CASE_WHEN":
|
|
37964
|
+
return "case";
|
|
37965
|
+
case "SCALAR_ARITH":
|
|
37966
|
+
return `${scalarValueDefaultKey(expr.left)}${expr.op}${scalarValueDefaultKey(expr.right)}`;
|
|
37967
|
+
case "CONCAT_OP":
|
|
37968
|
+
return `${scalarValueDefaultKey(expr.left)}||${scalarValueDefaultKey(expr.right)}`;
|
|
37969
|
+
}
|
|
37970
|
+
}
|
|
37586
37971
|
function hasAggregateInStringFuncArg(arg) {
|
|
37587
37972
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
37588
|
-
|
|
37973
|
+
return scalarValueHasAggregate2(arg);
|
|
37974
|
+
}
|
|
37975
|
+
function scalarValueHasAggregate2(expr) {
|
|
37976
|
+
if (expr.type === "STRING_FUNC") return hasAggregateInStringFuncExpr2(expr);
|
|
37977
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
37978
|
+
return scalarValueHasAggregate2(expr.left) || scalarValueHasAggregate2(expr.right);
|
|
37979
|
+
}
|
|
37980
|
+
if (expr.type === "CASE_WHEN") {
|
|
37981
|
+
return expr.branches.some((branch) => caseResultHasAggregate2(branch.result)) || expr.elseResult !== null && caseResultHasAggregate2(expr.elseResult);
|
|
37982
|
+
}
|
|
37589
37983
|
return false;
|
|
37590
37984
|
}
|
|
37985
|
+
function caseResultHasAggregate2(result) {
|
|
37986
|
+
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
|
|
37987
|
+
return scalarValueHasAggregate2(result);
|
|
37988
|
+
}
|
|
37591
37989
|
function hasAggregateInStringFuncExpr2(expr) {
|
|
37592
37990
|
return expr.args.some((arg) => hasAggregateInStringFuncArg(arg));
|
|
37593
37991
|
}
|
|
@@ -37603,7 +38001,18 @@ function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
|
|
|
37603
38001
|
if (arg.type === "STRING_FUNC") {
|
|
37604
38002
|
return resolveAggInStringFuncExpr(arg, rows, resolveAggSortKind);
|
|
37605
38003
|
}
|
|
37606
|
-
return arg;
|
|
38004
|
+
return resolveAggInScalarValue(arg, rows, resolveAggSortKind);
|
|
38005
|
+
}
|
|
38006
|
+
function resolveAggInScalarValue(expr, rows, resolveAggSortKind) {
|
|
38007
|
+
if (expr.type === "STRING_FUNC") return resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind);
|
|
38008
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
38009
|
+
return {
|
|
38010
|
+
...expr,
|
|
38011
|
+
left: resolveAggInScalarValue(expr.left, rows, resolveAggSortKind),
|
|
38012
|
+
right: resolveAggInScalarValue(expr.right, rows, resolveAggSortKind)
|
|
38013
|
+
};
|
|
38014
|
+
}
|
|
38015
|
+
return expr;
|
|
37607
38016
|
}
|
|
37608
38017
|
function resolveAggInStringFuncExpr(expr, rows, resolveAggSortKind) {
|
|
37609
38018
|
return {
|
|
@@ -37624,7 +38033,7 @@ function deriveOutputOrderSemantics(columns) {
|
|
|
37624
38033
|
} else if (column.func === "GROUP_CONCAT") {
|
|
37625
38034
|
result.set(column.alias, syntheticSemantics("string"));
|
|
37626
38035
|
}
|
|
37627
|
-
} else if (column.type === "LITERAL_COL" || column.type === "CASE_COL" || column.type === "SCALAR_SUBQUERY_COL") {
|
|
38036
|
+
} else if (column.type === "LITERAL_COL" || column.type === "CASE_COL" || column.type === "SCALAR_SUBQUERY_COL" || column.type === "SCALAR_VALUE_COL") {
|
|
37628
38037
|
result.set(column.alias, syntheticSemantics("string"));
|
|
37629
38038
|
} else if (column.type === "STRFUNC_COL") {
|
|
37630
38039
|
result.set(column.alias, syntheticSemantics(NUMERIC_ORDER_FUNCTIONS.has(column.expr.func) ? "number" : "string"));
|
|
@@ -37897,19 +38306,20 @@ var VALIDATION_META_COLUMNS = [
|
|
|
37897
38306
|
"$err_code",
|
|
37898
38307
|
"$err_message"
|
|
37899
38308
|
];
|
|
37900
|
-
function validateDmlCandidates(candidates, operation, payloadFields, targetFields, fieldInfos, statementNumber, numberPrecision) {
|
|
38309
|
+
function validateDmlCandidates(candidates, operation, payloadFields, targetFields, fieldInfos, statementNumber, numberPrecision, checkGroups = [], validateMissingCreateFields = true, includePreErrors = true) {
|
|
37901
38310
|
const infoByCode = new Map(fieldInfos.map((field) => [field.code, field]));
|
|
37902
38311
|
const errors = [];
|
|
37903
38312
|
const invalid = /* @__PURE__ */ new Set();
|
|
38313
|
+
let firstEvaluationError;
|
|
37904
38314
|
for (const candidate of candidates) {
|
|
37905
38315
|
candidate.record ??= {};
|
|
37906
|
-
const rowErrors = [...candidate.preErrors];
|
|
38316
|
+
const rowErrors = includePreErrors ? [...candidate.preErrors] : [];
|
|
37907
38317
|
for (const code of targetFields) {
|
|
37908
38318
|
const result = validateAndNormalizeDmlValue(candidate.payload.get(code), infoByCode.get(code), numberPrecision);
|
|
37909
38319
|
if (!result.ok) rowErrors.push({ field: code, code: result.code, message: result.message });
|
|
37910
38320
|
else candidate.record[code] = { value: result.value };
|
|
37911
38321
|
}
|
|
37912
|
-
if (candidate.mode === "create") {
|
|
38322
|
+
if (validateMissingCreateFields && candidate.mode === "create") {
|
|
37913
38323
|
for (const info of fieldInfos) {
|
|
37914
38324
|
if (info.inSubtable) continue;
|
|
37915
38325
|
if (candidate.payload.has(info.code)) continue;
|
|
@@ -37931,6 +38341,23 @@ function validateDmlCandidates(candidates, operation, payloadFields, targetField
|
|
|
37931
38341
|
}
|
|
37932
38342
|
}
|
|
37933
38343
|
}
|
|
38344
|
+
if (checkGroups.length > 0) {
|
|
38345
|
+
const row = candidate.evaluationRow ?? Object.fromEntries(
|
|
38346
|
+
[...candidate.payload].map(([field, value]) => [field, renderValidationValue(value)])
|
|
38347
|
+
);
|
|
38348
|
+
const types = candidate.evaluationFieldTypes;
|
|
38349
|
+
const resolveType = (field) => {
|
|
38350
|
+
const qualified = field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
|
|
38351
|
+
return types?.get(qualified) ?? types?.get(field.field);
|
|
38352
|
+
};
|
|
38353
|
+
try {
|
|
38354
|
+
for (const custom2 of evaluateCustomChecks(checkGroups, row, resolveType)) {
|
|
38355
|
+
rowErrors.push({ field: "", code: "ERR_CHECK", message: custom2.message });
|
|
38356
|
+
}
|
|
38357
|
+
} catch (error51) {
|
|
38358
|
+
firstEvaluationError ??= error51;
|
|
38359
|
+
}
|
|
38360
|
+
}
|
|
37934
38361
|
if (rowErrors.length > 0) invalid.add(candidate.rowNumber);
|
|
37935
38362
|
for (const error51 of rowErrors) {
|
|
37936
38363
|
const row = {};
|
|
@@ -37944,6 +38371,7 @@ function validateDmlCandidates(candidates, operation, payloadFields, targetField
|
|
|
37944
38371
|
errors.push(row);
|
|
37945
38372
|
}
|
|
37946
38373
|
}
|
|
38374
|
+
if (firstEvaluationError !== void 0) throw firstEvaluationError;
|
|
37947
38375
|
return { errors, invalidRows: invalid.size, invalidRowNumbers: invalid };
|
|
37948
38376
|
}
|
|
37949
38377
|
function renderValidationValue(value) {
|
|
@@ -39000,7 +39428,7 @@ function buildHavingFieldSemanticsResolver(stmt, rowResolver) {
|
|
|
39000
39428
|
}
|
|
39001
39429
|
} else if (column.type === "STRFUNC_COL") {
|
|
39002
39430
|
semantics = stringFunctionColumnMeta(column.expr).semantics;
|
|
39003
|
-
} else if (column.type === "LITERAL_COL" || column.type === "SCALAR_SUBQUERY_COL" || column.type === "CASE_COL") {
|
|
39431
|
+
} else if (column.type === "LITERAL_COL" || column.type === "SCALAR_SUBQUERY_COL" || column.type === "CASE_COL" || column.type === "SCALAR_VALUE_COL") {
|
|
39004
39432
|
semantics = syntheticSemantics("string");
|
|
39005
39433
|
}
|
|
39006
39434
|
if (semantics) aliases.set(column.alias, semantics);
|
|
@@ -39115,10 +39543,19 @@ function arithHasFieldRef(node) {
|
|
|
39115
39543
|
return false;
|
|
39116
39544
|
}
|
|
39117
39545
|
function stringFuncArgHasFieldRef(arg) {
|
|
39118
|
-
if (arg.type === "FIELD_REF") return true;
|
|
39119
|
-
if (arg.type === "ARITH") return arithHasFieldRef(arg);
|
|
39120
|
-
if (arg.type === "STRING_FUNC") return stringFuncHasFieldRef(arg);
|
|
39121
39546
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
|
|
39547
|
+
return scalarValueHasFieldRef(arg);
|
|
39548
|
+
}
|
|
39549
|
+
function scalarValueHasFieldRef(expr) {
|
|
39550
|
+
if (expr.type === "FIELD") return true;
|
|
39551
|
+
if (expr.type === "STRING_FUNC") return stringFuncHasFieldRef(expr);
|
|
39552
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
39553
|
+
return scalarValueHasFieldRef(expr.left) || scalarValueHasFieldRef(expr.right);
|
|
39554
|
+
}
|
|
39555
|
+
if (expr.type === "CASE_WHEN") {
|
|
39556
|
+
const results = [...expr.branches.map((branch) => branch.result), ...expr.elseResult ? [expr.elseResult] : []];
|
|
39557
|
+
return results.some((result) => result.type !== "ARRAY" && (result.type === "FIELD_REF" || result.type === "ARITH" ? arithHasFieldRef(result) : scalarValueHasFieldRef(result)));
|
|
39558
|
+
}
|
|
39122
39559
|
return false;
|
|
39123
39560
|
}
|
|
39124
39561
|
function stringFuncHasFieldRef(expr) {
|
|
@@ -39139,6 +39576,11 @@ function validateNoFromColumns(stmt) {
|
|
|
39139
39576
|
throw new Error("ArgumentError: field reference is not allowed without FROM.");
|
|
39140
39577
|
}
|
|
39141
39578
|
break;
|
|
39579
|
+
case "SCALAR_VALUE_COL":
|
|
39580
|
+
if (scalarValueHasFieldRef(col.expr)) {
|
|
39581
|
+
throw new Error("ArgumentError: field reference is not allowed without FROM.");
|
|
39582
|
+
}
|
|
39583
|
+
break;
|
|
39142
39584
|
case "WINDOW_COL":
|
|
39143
39585
|
if (col.partitionBy.length > 0 || col.orderBy.length > 0) {
|
|
39144
39586
|
throw new Error("ArgumentError: field reference is not allowed without FROM.");
|
|
@@ -39425,8 +39867,26 @@ function collectStringFuncAggregateRefs(expr, out) {
|
|
|
39425
39867
|
for (const arg of expr.args) {
|
|
39426
39868
|
if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") {
|
|
39427
39869
|
collectAggregateOperandRefs(arg, out);
|
|
39428
|
-
} else
|
|
39429
|
-
|
|
39870
|
+
} else {
|
|
39871
|
+
collectScalarAggregateRefs(arg, out);
|
|
39872
|
+
}
|
|
39873
|
+
}
|
|
39874
|
+
}
|
|
39875
|
+
function collectScalarAggregateRefs(expr, out) {
|
|
39876
|
+
if (expr.type === "STRING_FUNC") {
|
|
39877
|
+
collectStringFuncAggregateRefs(expr, out);
|
|
39878
|
+
return;
|
|
39879
|
+
}
|
|
39880
|
+
if (expr.type === "SCALAR_ARITH" || expr.type === "CONCAT_OP") {
|
|
39881
|
+
collectScalarAggregateRefs(expr.left, out);
|
|
39882
|
+
collectScalarAggregateRefs(expr.right, out);
|
|
39883
|
+
return;
|
|
39884
|
+
}
|
|
39885
|
+
if (expr.type === "CASE_WHEN") {
|
|
39886
|
+
const results = [...expr.branches.map((branch) => branch.result), ...expr.elseResult ? [expr.elseResult] : []];
|
|
39887
|
+
for (const result of results) {
|
|
39888
|
+
if (result.type === "STRING_FUNC") collectStringFuncAggregateRefs(result, out);
|
|
39889
|
+
else if (result.type !== "ARRAY" && result.type !== "FIELD_REF" && result.type !== "ARITH") collectScalarAggregateRefs(result, out);
|
|
39430
39890
|
}
|
|
39431
39891
|
}
|
|
39432
39892
|
}
|
|
@@ -39439,6 +39899,8 @@ function collectSelectAggregateSortRefs(columns) {
|
|
|
39439
39899
|
collectAggregateOperandRefs(column.expr, refs);
|
|
39440
39900
|
} else if (column.type === "STRFUNC_COL") {
|
|
39441
39901
|
collectStringFuncAggregateRefs(column.expr, refs);
|
|
39902
|
+
} else if (column.type === "SCALAR_VALUE_COL") {
|
|
39903
|
+
collectScalarAggregateRefs(column.expr, refs);
|
|
39442
39904
|
}
|
|
39443
39905
|
}
|
|
39444
39906
|
return refs;
|
|
@@ -39604,10 +40066,11 @@ function stringFunctionColumnMeta(expr) {
|
|
|
39604
40066
|
function caseResultColumnMeta(result, resolveField2) {
|
|
39605
40067
|
if (result.type === "STRING") return syntheticColumnMeta("string");
|
|
39606
40068
|
if (result.type === "ARRAY") return unsupportedColumnMeta();
|
|
39607
|
-
if (result.type === "NUMBER" || result.type === "ARITH") return syntheticColumnMeta("number");
|
|
40069
|
+
if (result.type === "NUMBER" || result.type === "ARITH" || result.type === "SCALAR_ARITH") return syntheticColumnMeta("number");
|
|
39608
40070
|
if (result.type === "STRING_FUNC") return stringFunctionColumnMeta(result);
|
|
39609
|
-
|
|
39610
|
-
return
|
|
40071
|
+
if (result.type === "FIELD_REF") return resolveField2(aggregateFieldRef(result.field)) ?? unknownStringColumnMeta();
|
|
40072
|
+
if (result.type === "FIELD") return resolveField2(result) ?? unknownStringColumnMeta();
|
|
40073
|
+
return unknownStringColumnMeta();
|
|
39611
40074
|
}
|
|
39612
40075
|
function mergeExpressionColumnMeta(candidates) {
|
|
39613
40076
|
if (candidates.length === 0) return unknownStringColumnMeta();
|
|
@@ -39709,7 +40172,7 @@ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext,
|
|
|
39709
40172
|
}
|
|
39710
40173
|
} else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
|
|
39711
40174
|
meta3 = syntheticColumnMeta("number");
|
|
39712
|
-
} else if (column.type === "LITERAL_COL") {
|
|
40175
|
+
} else if (column.type === "LITERAL_COL" || column.type === "SCALAR_VALUE_COL") {
|
|
39713
40176
|
meta3 = syntheticColumnMeta("string");
|
|
39714
40177
|
} else if (column.type === "STRFUNC_COL") {
|
|
39715
40178
|
meta3 = stringFunctionColumnMeta(column.expr);
|
|
@@ -40416,7 +40879,7 @@ async function buildOrderSemanticsForSelect(stmt, client, cacheContext, material
|
|
|
40416
40879
|
if (column.type === "FIELD") meta3 = resolveField2(aggregateFieldRef(column.field));
|
|
40417
40880
|
else if (column.type === "ARITH_COL" || column.type === "ARITH_AGG_COL" || column.type === "WINDOW_COL") {
|
|
40418
40881
|
meta3 = syntheticColumnMeta("number");
|
|
40419
|
-
} else if (column.type === "LITERAL_COL") meta3 = syntheticColumnMeta("string");
|
|
40882
|
+
} else if (column.type === "LITERAL_COL" || column.type === "SCALAR_VALUE_COL") meta3 = syntheticColumnMeta("string");
|
|
40420
40883
|
else if (column.type === "STRFUNC_COL") meta3 = stringFunctionColumnMeta(column.expr);
|
|
40421
40884
|
else if (column.type === "SCALAR_SUBQUERY_COL") meta3 = unknownStringColumnMeta();
|
|
40422
40885
|
else if (column.type === "CASE_COL") {
|
|
@@ -40604,7 +41067,7 @@ var RejectLimitExceededError = class extends Error {
|
|
|
40604
41067
|
this.name = "RejectLimitExceededError";
|
|
40605
41068
|
}
|
|
40606
41069
|
};
|
|
40607
|
-
async function prepareDmlValidation(stmt, client, options, cacheContext, tempTables, statementNumber) {
|
|
41070
|
+
async function prepareDmlValidation(stmt, client, options, cacheContext, tempTables, statementNumber, validateMissingCreateFields = true, includePreErrors = true) {
|
|
40608
41071
|
const operation = stmt.type === "UPDATE" ? "UPDATE" : stmt.type.startsWith("UPSERT") ? "UPSERT" : "INSERT";
|
|
40609
41072
|
const payloadFields = stmt.type === "UPDATE" ? ["$id", ...stmt.assignments.map((a) => a.field)] : [...stmt.fields];
|
|
40610
41073
|
if (new Set(payloadFields).size !== payloadFields.length) {
|
|
@@ -40636,7 +41099,10 @@ async function prepareDmlValidation(stmt, client, options, cacheContext, tempTab
|
|
|
40636
41099
|
targetFields,
|
|
40637
41100
|
fieldInfos,
|
|
40638
41101
|
statementNumber,
|
|
40639
|
-
numberPrecision
|
|
41102
|
+
numberPrecision,
|
|
41103
|
+
stmt.checkGroups ?? [],
|
|
41104
|
+
validateMissingCreateFields,
|
|
41105
|
+
includePreErrors
|
|
40640
41106
|
);
|
|
40641
41107
|
const columns = [...payloadFields, ...VALIDATION_META_COLUMNS];
|
|
40642
41108
|
const result = {
|
|
@@ -40746,15 +41212,33 @@ async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTable
|
|
|
40746
41212
|
async function materializeValidationCandidates(stmt, operation, client, options, cacheContext, tempTables, infoByCode) {
|
|
40747
41213
|
if (stmt.type === "UPDATE") return materializeUpdateValidationCandidates(stmt, client, options, cacheContext, tempTables);
|
|
40748
41214
|
let rows;
|
|
41215
|
+
let sourceRows;
|
|
41216
|
+
let evaluationTypes;
|
|
40749
41217
|
if (stmt.type === "INSERT" || stmt.type === "UPSERT") {
|
|
41218
|
+
assertInsertCheckRefs(stmt, stmt.fields);
|
|
41219
|
+
evaluationTypes = new Map(stmt.fields.map((field) => [field, infoByCode.get(field)?.fieldType ?? ""]));
|
|
41220
|
+
assertCheckComparisonTypes(stmt, evaluationTypes);
|
|
40750
41221
|
rows = stmt.values.map((row) => row.map(
|
|
40751
41222
|
(value, i) => value.type === "CASE_VALUE" ? evalCaseWhenValue(value.expr, {}, infoByCode.get(stmt.fields[i])?.fieldType) : value
|
|
40752
41223
|
));
|
|
40753
41224
|
} else {
|
|
40754
|
-
const selectResult = tempTables && tempTables.size > 0 ? await executeQueryWithCte(stmt.select, client, { ...options, onLimitReached: "error" }, tempTables, cacheContext) : await executeSelect(stmt.select, client, { ...options, onLimitReached: "error" }, cacheContext);
|
|
40755
|
-
|
|
41225
|
+
const selectResult = tempTables && tempTables.size > 0 ? await executeQueryWithCte(stmt.select, client, { ...options, onLimitReached: "error" }, tempTables, cacheContext) : await executeSelect(stmt.select, client, { ...options, onLimitReached: "error" }, cacheContext, void 0, true);
|
|
41226
|
+
const hasChecks = (stmt.checkGroups?.length ?? 0) > 0;
|
|
41227
|
+
if (selectResult.columns.length < stmt.fields.length || !hasChecks && selectResult.columns.length !== stmt.fields.length) {
|
|
40756
41228
|
throw new Error(`SELECT \u306E\u5217\u6570\uFF08${selectResult.columns.length}\uFF09\u3068 DML \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u6570\uFF08${stmt.fields.length}\uFF09\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093`);
|
|
40757
41229
|
}
|
|
41230
|
+
if (hasChecks && new Set(selectResult.columns).size !== selectResult.columns.length) {
|
|
41231
|
+
throw customCheckParseError("CHECK \u4ED8\u304D DML \u30BD\u30FC\u30B9 SELECT \u306E\u51FA\u529B\u540D\u306F\u4E00\u610F\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");
|
|
41232
|
+
}
|
|
41233
|
+
assertInsertCheckRefs(stmt, selectResult.columns);
|
|
41234
|
+
sourceRows = selectResult.rows;
|
|
41235
|
+
const meta3 = materializedMetaBySelectResult.get(selectResult);
|
|
41236
|
+
evaluationTypes = new Map(selectResult.columns.map((column) => {
|
|
41237
|
+
const columnMeta = meta3?.get(column);
|
|
41238
|
+
const type = columnMeta?.fieldType ?? (columnMeta?.semantics?.compareMode === "number" || columnMeta?.sortKind === "number" ? "NUMBER" : "SINGLE_LINE_TEXT");
|
|
41239
|
+
return [column, type];
|
|
41240
|
+
}));
|
|
41241
|
+
assertCheckComparisonTypes(stmt, evaluationTypes);
|
|
40758
41242
|
rows = selectResult.rows.map((row) => selectResult.columns.map((column) => row[column] ?? ""));
|
|
40759
41243
|
}
|
|
40760
41244
|
const candidates = rows.map((values, index) => ({
|
|
@@ -40763,7 +41247,11 @@ async function materializeValidationCandidates(stmt, operation, client, options,
|
|
|
40763
41247
|
mode: "create",
|
|
40764
41248
|
payload: new Map(stmt.fields.map((field, i) => [field, values[i]])),
|
|
40765
41249
|
preErrors: [],
|
|
40766
|
-
record: {}
|
|
41250
|
+
record: {},
|
|
41251
|
+
evaluationRow: sourceRows?.[index] ?? Object.fromEntries(
|
|
41252
|
+
stmt.fields.map((field, i) => [field, renderValidationValue(values[i])])
|
|
41253
|
+
),
|
|
41254
|
+
evaluationFieldTypes: evaluationTypes
|
|
40767
41255
|
}));
|
|
40768
41256
|
if (stmt.type !== "UPSERT" && stmt.type !== "UPSERT_SELECT") return candidates;
|
|
40769
41257
|
for (const key of stmt.keyFields) {
|
|
@@ -40792,26 +41280,74 @@ async function materializeValidationCandidates(stmt, operation, client, options,
|
|
|
40792
41280
|
});
|
|
40793
41281
|
return candidates;
|
|
40794
41282
|
}
|
|
41283
|
+
function checkRefs(stmt) {
|
|
41284
|
+
return stmt.checkGroups ? collectCheckFieldRefs(stmt.checkGroups) : [];
|
|
41285
|
+
}
|
|
41286
|
+
function assertInsertCheckRefs(stmt, available) {
|
|
41287
|
+
const names = new Set(available);
|
|
41288
|
+
for (const ref of checkRefs(stmt)) {
|
|
41289
|
+
if (ref.tableAlias !== null) {
|
|
41290
|
+
throw customCheckParseError(`CHECK \u306E\u30D5\u30A3\u30FC\u30EB\u30C9 ${ref.tableAlias}.${ref.field} \u306F\u3053\u306E\u8A55\u4FA1\u884C\u3067\u306F\u4FEE\u98FE\u3067\u304D\u307E\u305B\u3093`);
|
|
41291
|
+
}
|
|
41292
|
+
if (!names.has(ref.field)) {
|
|
41293
|
+
throw customCheckParseError(`CHECK \u306E\u30D5\u30A3\u30FC\u30EB\u30C9 ${ref.field} \u306F\u8A55\u4FA1\u884C\u306B\u5B58\u5728\u3057\u307E\u305B\u3093`);
|
|
41294
|
+
}
|
|
41295
|
+
}
|
|
41296
|
+
}
|
|
41297
|
+
var CHECK_UNSUPPORTED_COMPARISON_TYPES = /* @__PURE__ */ new Set([
|
|
41298
|
+
"CHECK_BOX",
|
|
41299
|
+
"MULTI_SELECT",
|
|
41300
|
+
"USER_SELECT",
|
|
41301
|
+
"ORGANIZATION_SELECT",
|
|
41302
|
+
"GROUP_SELECT",
|
|
41303
|
+
"FILE",
|
|
41304
|
+
"KSQL_ARRAY"
|
|
41305
|
+
]);
|
|
41306
|
+
function assertCheckComparisonTypes(stmt, types) {
|
|
41307
|
+
if (!stmt.checkGroups) return;
|
|
41308
|
+
for (const ref of collectCheckComparisonFieldRefs(stmt.checkGroups)) {
|
|
41309
|
+
const key = ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
|
|
41310
|
+
const type = types.get(key) ?? types.get(ref.field);
|
|
41311
|
+
if (CHECK_UNSUPPORTED_COMPARISON_TYPES.has(type ?? "")) {
|
|
41312
|
+
throw customCheckParseError(`CHECK \u306E\u6BD4\u8F03\u3067\u306F ${type} \u30D5\u30A3\u30FC\u30EB\u30C9 ${key} \u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`);
|
|
41313
|
+
}
|
|
41314
|
+
}
|
|
41315
|
+
}
|
|
40795
41316
|
async function materializeUpdateValidationCandidates(stmt, client, options, cacheContext, tempTables) {
|
|
40796
41317
|
if (stmt.from) return materializeUpdateFromValidationCandidates(stmt, stmt.from, client, options, cacheContext, tempTables);
|
|
40797
41318
|
await resolveSetSubqueries(stmt.assignments, client, options, cacheContext);
|
|
40798
41319
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
41320
|
+
const checkTargetFields = assertUpdateCheckRefs(stmt, fieldTypes);
|
|
41321
|
+
assertCheckComparisonTypes(stmt, updateEvaluationTypes(fieldTypes, stmt.appId));
|
|
40799
41322
|
let records;
|
|
41323
|
+
let evaluationById = /* @__PURE__ */ new Map();
|
|
40800
41324
|
if (hasRowDependentAssignment(stmt)) {
|
|
40801
41325
|
const getParams = updateToGetQueryForArith(stmt);
|
|
40802
|
-
const
|
|
41326
|
+
const fields = [.../* @__PURE__ */ new Set([...getParams.fields, ...checkTargetFields])];
|
|
41327
|
+
const resolved = await fetchRecordsForSharedPlan(client.getRecords, getParams.app, getParams.query, fields, {
|
|
40803
41328
|
maxRecords: options.maxRecords ?? 1e4,
|
|
40804
41329
|
parallel: options.fetchParallel ?? 1,
|
|
40805
41330
|
onLimit: "error"
|
|
40806
41331
|
});
|
|
41332
|
+
evaluationById = new Map(resolved.records.map((record2) => [Number(record2["$id"]?.value), record2]));
|
|
40807
41333
|
records = updateToPutBatchesArith(stmt, resolved.records, fieldTypes).flatMap((batch) => batch.records);
|
|
40808
41334
|
} else {
|
|
40809
41335
|
const getParams = updateToGetQuery(stmt);
|
|
40810
|
-
|
|
40811
|
-
|
|
40812
|
-
|
|
40813
|
-
|
|
40814
|
-
|
|
41336
|
+
if (checkTargetFields.length > 0) {
|
|
41337
|
+
const resolved = await fetchRecordsForSharedPlan(client.getRecords, getParams.app, getParams.query, [.../* @__PURE__ */ new Set(["$id", ...checkTargetFields])], {
|
|
41338
|
+
maxRecords: options.maxRecords ?? 1e4,
|
|
41339
|
+
parallel: options.fetchParallel ?? 1,
|
|
41340
|
+
onLimit: "error"
|
|
41341
|
+
});
|
|
41342
|
+
evaluationById = new Map(resolved.records.map((record2) => [Number(record2["$id"]?.value), record2]));
|
|
41343
|
+
records = updateToPutBatches(stmt, [...evaluationById.keys()], fieldTypes).flatMap((batch) => batch.records);
|
|
41344
|
+
} else {
|
|
41345
|
+
const resolved = await resolveDmlTargetIds(client.getRecords, getParams.app, getParams.query, {
|
|
41346
|
+
maxRecords: options.maxRecords ?? 1e4,
|
|
41347
|
+
parallel: options.fetchParallel ?? 1
|
|
41348
|
+
});
|
|
41349
|
+
records = updateToPutBatches(stmt, resolved.ids, fieldTypes).flatMap((batch) => batch.records);
|
|
41350
|
+
}
|
|
40815
41351
|
}
|
|
40816
41352
|
return records.sort((a, b) => a.id - b.id).map((entry, index) => ({
|
|
40817
41353
|
rowNumber: index + 1,
|
|
@@ -40820,13 +41356,48 @@ async function materializeUpdateValidationCandidates(stmt, client, options, cach
|
|
|
40820
41356
|
payload: new Map([["$id", String(entry.id)], ...stmt.assignments.map((a) => [a.field, entry.record[a.field]?.value ?? ""])]),
|
|
40821
41357
|
preErrors: [],
|
|
40822
41358
|
record: entry.record,
|
|
40823
|
-
targetId: entry.id
|
|
41359
|
+
targetId: entry.id,
|
|
41360
|
+
evaluationRow: updateEvaluationRow(evaluationById.get(entry.id), stmt.appId),
|
|
41361
|
+
evaluationFieldTypes: updateEvaluationTypes(fieldTypes, stmt.appId)
|
|
40824
41362
|
}));
|
|
40825
41363
|
}
|
|
41364
|
+
function assertUpdateCheckRefs(stmt, targetTypes) {
|
|
41365
|
+
if (stmt.from) return [];
|
|
41366
|
+
const fields = /* @__PURE__ */ new Set();
|
|
41367
|
+
for (const ref of checkRefs(stmt)) {
|
|
41368
|
+
if (ref.tableAlias !== null && ref.tableAlias.toLowerCase() !== `app${stmt.appId}`.toLowerCase()) {
|
|
41369
|
+
throw customCheckParseError(`CHECK \u306E\u4FEE\u98FE\u5B50 ${ref.tableAlias} \u306F\u66F4\u65B0\u5148 APP${stmt.appId} \u3067\u306F\u3042\u308A\u307E\u305B\u3093`);
|
|
41370
|
+
}
|
|
41371
|
+
if (ref.field !== "$id" && !targetTypes.has(ref.field)) {
|
|
41372
|
+
throw customCheckParseError(`CHECK \u306E\u30BF\u30FC\u30B2\u30C3\u30C8\u30D5\u30A3\u30FC\u30EB\u30C9 ${ref.field} \u306F\u5B58\u5728\u3057\u307E\u305B\u3093`);
|
|
41373
|
+
}
|
|
41374
|
+
fields.add(ref.field);
|
|
41375
|
+
}
|
|
41376
|
+
return [...fields];
|
|
41377
|
+
}
|
|
41378
|
+
function updateEvaluationRow(record2, appId) {
|
|
41379
|
+
if (!record2) return {};
|
|
41380
|
+
const plain = flatten(record2, null);
|
|
41381
|
+
return Object.fromEntries([
|
|
41382
|
+
...Object.entries(plain),
|
|
41383
|
+
...Object.entries(plain).map(([field, value]) => [`APP${appId}.${field}`, value])
|
|
41384
|
+
]);
|
|
41385
|
+
}
|
|
41386
|
+
function updateEvaluationTypes(types, appId) {
|
|
41387
|
+
return new Map([
|
|
41388
|
+
...types,
|
|
41389
|
+
...[...types].map(([field, type]) => [`APP${appId}.${field}`, type]),
|
|
41390
|
+
["$id", "RECORD_NUMBER"],
|
|
41391
|
+
[`APP${appId}.$id`, "RECORD_NUMBER"]
|
|
41392
|
+
]);
|
|
41393
|
+
}
|
|
40826
41394
|
async function materializeUpdateFromValidationCandidates(stmt, from, client, options, cacheContext, tempTables) {
|
|
41395
|
+
const scope = await resolveUpdateFromCheckScope(stmt, from, client, cacheContext, tempTables);
|
|
41396
|
+
assertCheckComparisonTypes(stmt, scope.evaluationTypes);
|
|
40827
41397
|
const matched = await resolveUpdateFromMatchedRecords(stmt, from, client, options, cacheContext, tempTables);
|
|
40828
41398
|
const fieldTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
40829
41399
|
const records = updateFromToPutBatches(stmt, matched, fieldTypes).flatMap((batch) => batch.records);
|
|
41400
|
+
const matchedById = new Map(matched.map((pair) => [Number(pair.target["$id"]?.value), pair]));
|
|
40830
41401
|
return records.sort((a, b) => a.id - b.id).map((entry, index) => ({
|
|
40831
41402
|
rowNumber: index + 1,
|
|
40832
41403
|
operation: "UPDATE",
|
|
@@ -40834,7 +41405,9 @@ async function materializeUpdateFromValidationCandidates(stmt, from, client, opt
|
|
|
40834
41405
|
payload: new Map([["$id", String(entry.id)], ...stmt.assignments.map((a) => [a.field, entry.record[a.field]?.value ?? ""])]),
|
|
40835
41406
|
preErrors: [],
|
|
40836
41407
|
record: entry.record,
|
|
40837
|
-
targetId: entry.id
|
|
41408
|
+
targetId: entry.id,
|
|
41409
|
+
evaluationRow: updateFromEvaluationRow(matchedById.get(entry.id), stmt.appId, from.alias),
|
|
41410
|
+
evaluationFieldTypes: scope.evaluationTypes
|
|
40838
41411
|
}));
|
|
40839
41412
|
}
|
|
40840
41413
|
var UPDATE_FROM_KEY_CHUNK_SIZE = UPSERT_IN_CHUNK_SIZE;
|
|
@@ -40848,7 +41421,8 @@ var UPDATE_FROM_UNSUPPORTED_SOURCE_TYPES = /* @__PURE__ */ new Set([
|
|
|
40848
41421
|
]);
|
|
40849
41422
|
async function resolveUpdateFromMatchedRecords(stmt, from, client, options, cacheContext, tempTables) {
|
|
40850
41423
|
const joinKind = await resolveUpdateFromTargetJoinKind(stmt, from, client, cacheContext);
|
|
40851
|
-
const
|
|
41424
|
+
const checkScope = await resolveUpdateFromCheckScope(stmt, from, client, cacheContext, tempTables);
|
|
41425
|
+
const sourceFields = [...new Set(stmt.assignments.filter((a) => a.value.type === "SOURCE_FIELD").map((a) => a.value.type === "SOURCE_FIELD" ? a.value.field : "").concat(checkScope.sourceFields))];
|
|
40852
41426
|
const requiredSourceFields = [.../* @__PURE__ */ new Set([from.joinKeyField, ...sourceFields])];
|
|
40853
41427
|
const sourceRows = await loadUpdateFromSourceRows(
|
|
40854
41428
|
from,
|
|
@@ -40874,8 +41448,8 @@ async function resolveUpdateFromMatchedRecords(stmt, from, client, options, cach
|
|
|
40874
41448
|
}
|
|
40875
41449
|
if (sourceByKey.size === 0) return [];
|
|
40876
41450
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
40877
|
-
const targetFields = collectUpdateFromTargetFields(stmt);
|
|
40878
|
-
const filterQuery = from.targetFilter === null ? "" : updateToGetQuery({ ...stmt, from: null, where: from.targetFilter }).query;
|
|
41451
|
+
const targetFields = [.../* @__PURE__ */ new Set([...collectUpdateFromTargetFields(stmt), ...checkScope.targetFields])];
|
|
41452
|
+
const filterQuery = from.targetFilter === null ? "" : updateToGetQuery({ ...stmt, from: null, where: from.targetFilter, checkGroups: void 0 }).query;
|
|
40879
41453
|
const targetRecords = [];
|
|
40880
41454
|
const seenTargetIds = /* @__PURE__ */ new Set();
|
|
40881
41455
|
let fetchedTargetCount = 0;
|
|
@@ -40993,7 +41567,54 @@ function normalizeUpdateFromJoinKey(raw, kind, side) {
|
|
|
40993
41567
|
}
|
|
40994
41568
|
return JSON.stringify(decimal);
|
|
40995
41569
|
}
|
|
41570
|
+
async function executeCheckedPlainDml(stmt, client, options, cacheContext, tempTables) {
|
|
41571
|
+
const prepared = await prepareDmlValidation(
|
|
41572
|
+
stmt,
|
|
41573
|
+
client,
|
|
41574
|
+
options,
|
|
41575
|
+
cacheContext,
|
|
41576
|
+
tempTables,
|
|
41577
|
+
1,
|
|
41578
|
+
false,
|
|
41579
|
+
false
|
|
41580
|
+
);
|
|
41581
|
+
if (prepared.result.errors.length > 0) {
|
|
41582
|
+
const first = prepared.result.errors[0];
|
|
41583
|
+
throw new Error(
|
|
41584
|
+
`DmlValidationError: ${first["$err_code"]} ${first["$err_message"]} (row=${first["$err_row"]}, field=${first["$err_field"]})`
|
|
41585
|
+
);
|
|
41586
|
+
}
|
|
41587
|
+
const candidates = prepared.candidates;
|
|
41588
|
+
const confirmOperation = stmt.type.startsWith("INSERT") ? "INSERT" : "UPDATE";
|
|
41589
|
+
if (options.confirm && candidates.length > 0) {
|
|
41590
|
+
const ok = await options.confirm(candidates.length, confirmOperation);
|
|
41591
|
+
if (!ok) throw new OperationCancelledError(confirmOperation, candidates.length);
|
|
41592
|
+
}
|
|
41593
|
+
if (stmt.type === "INSERT" || stmt.type === "INSERT_SELECT") {
|
|
41594
|
+
const createdIds = [];
|
|
41595
|
+
for (let i = 0; i < candidates.length; i += 100) {
|
|
41596
|
+
const response = await client.postRecords({ app: stmt.appId, records: candidates.slice(i, i + 100).map((c) => c.record) });
|
|
41597
|
+
createdIds.push(response.ids);
|
|
41598
|
+
}
|
|
41599
|
+
return { type: "INSERT", createdIds, insertedCount: createdIds.flat().length };
|
|
41600
|
+
}
|
|
41601
|
+
if (stmt.type === "UPDATE") {
|
|
41602
|
+
const updates2 = candidates.map((candidate) => ({ id: candidate.targetId, record: candidate.record }));
|
|
41603
|
+
for (let i = 0; i < updates2.length; i += 100) await client.putRecords({ app: stmt.appId, records: updates2.slice(i, i + 100) });
|
|
41604
|
+
return { type: "UPDATE", updatedCount: updates2.length };
|
|
41605
|
+
}
|
|
41606
|
+
const inserts = candidates.filter((candidate) => candidate.mode === "create");
|
|
41607
|
+
const updates = candidates.filter((candidate) => candidate.mode === "update").map((candidate) => ({ id: candidate.targetId, record: candidate.record }));
|
|
41608
|
+
let insertedCount = 0;
|
|
41609
|
+
for (let i = 0; i < inserts.length; i += 100) {
|
|
41610
|
+
const response = await client.postRecords({ app: stmt.appId, records: inserts.slice(i, i + 100).map((c) => c.record) });
|
|
41611
|
+
insertedCount += response.ids.length;
|
|
41612
|
+
}
|
|
41613
|
+
for (let i = 0; i < updates.length; i += 100) await client.putRecords({ app: stmt.appId, records: updates.slice(i, i + 100) });
|
|
41614
|
+
return { type: "UPSERT", insertedCount, updatedCount: updates.length };
|
|
41615
|
+
}
|
|
40996
41616
|
async function executeInsert(stmt, client, options, cacheContext) {
|
|
41617
|
+
if (stmt.checkGroups?.length) return executeCheckedPlainDml(stmt, client, options, cacheContext);
|
|
40997
41618
|
if (stmt.subtableCode) {
|
|
40998
41619
|
return executeInsertSubtable(stmt, client, options, cacheContext);
|
|
40999
41620
|
}
|
|
@@ -41014,6 +41635,7 @@ async function executeInsert(stmt, client, options, cacheContext) {
|
|
|
41014
41635
|
};
|
|
41015
41636
|
}
|
|
41016
41637
|
async function executeInsertSelect(stmt, client, options, cacheContext, cteCache) {
|
|
41638
|
+
if (stmt.checkGroups?.length) return executeCheckedPlainDml(stmt, client, options, cacheContext, cteCache);
|
|
41017
41639
|
const fieldInfos = await loadWritableTopLevelDmlFields(stmt.appId, stmt.fields, client, cacheContext);
|
|
41018
41640
|
const numberPrecision = await loadNumberPrecisionForTargets(stmt.appId, stmt.fields, fieldInfos, client, cacheContext);
|
|
41019
41641
|
const selectResult = cteCache !== void 0 && cteCache.size > 0 ? await executeQueryWithCte(stmt.select, client, options, cteCache, cacheContext) : await executeSelect(stmt.select, client, options, cacheContext);
|
|
@@ -41051,6 +41673,7 @@ async function executeInsertSelect(stmt, client, options, cacheContext, cteCache
|
|
|
41051
41673
|
};
|
|
41052
41674
|
}
|
|
41053
41675
|
async function executeUpdate(stmt, client, options, cacheContext, tempTables) {
|
|
41676
|
+
if (stmt.checkGroups?.length) return executeCheckedPlainDml(stmt, client, options, cacheContext, tempTables);
|
|
41054
41677
|
if (stmt.subtableCode) {
|
|
41055
41678
|
await assertDmlWhereCapability(stmt, client, cacheContext);
|
|
41056
41679
|
return executeUpdateSubtable(stmt, client, options, cacheContext);
|
|
@@ -41176,6 +41799,7 @@ async function executeDelete(stmt, client, options, cacheContext) {
|
|
|
41176
41799
|
return { type: "DELETE", deletedCount: ids.length };
|
|
41177
41800
|
}
|
|
41178
41801
|
async function executeUpsert(stmt, client, options, cacheContext) {
|
|
41802
|
+
if (stmt.checkGroups?.length) return executeCheckedPlainDml(stmt, client, options, cacheContext);
|
|
41179
41803
|
const fieldInfos = await loadWritableTopLevelDmlFields(stmt.appId, stmt.fields, client, cacheContext);
|
|
41180
41804
|
const numberPrecision = await loadNumberPrecisionForTargets(stmt.appId, stmt.fields, fieldInfos, client, cacheContext);
|
|
41181
41805
|
const toInsert = [];
|
|
@@ -41610,6 +42234,7 @@ function evalOrderKeyForRow(key, row) {
|
|
|
41610
42234
|
}
|
|
41611
42235
|
}
|
|
41612
42236
|
async function executeUpsertSelect(stmt, client, options, cacheContext, cteCache) {
|
|
42237
|
+
if (stmt.checkGroups?.length) return executeCheckedPlainDml(stmt, client, options, cacheContext, cteCache);
|
|
41613
42238
|
const fieldInfos = await loadWritableTopLevelDmlFields(stmt.appId, stmt.fields, client, cacheContext);
|
|
41614
42239
|
const numberPrecision = await loadNumberPrecisionForTargets(stmt.appId, stmt.fields, fieldInfos, client, cacheContext);
|
|
41615
42240
|
const selectResult = cteCache !== void 0 && cteCache.size > 0 ? await executeQueryWithCte(stmt.select, client, options, cteCache, cacheContext) : await executeSelect(stmt.select, client, options, cacheContext);
|
|
@@ -42357,6 +42982,7 @@ function collectArithRefFields(stmt) {
|
|
|
42357
42982
|
for (const { value } of stmt.assignments) {
|
|
42358
42983
|
if (value.type === "ARITH") collectArithNodeRefs(value, refs);
|
|
42359
42984
|
if (value.type === "STRING_FUNC") collectArithNodeRefs(value, refs);
|
|
42985
|
+
if (value.type === "SCALAR_ARITH" || value.type === "CONCAT_OP") collectScalarNodeRefs(value, refs);
|
|
42360
42986
|
}
|
|
42361
42987
|
return [...refs];
|
|
42362
42988
|
}
|
|
@@ -42371,10 +42997,74 @@ function collectArithNodeRefs(node, out) {
|
|
|
42371
42997
|
}
|
|
42372
42998
|
if (node.type === "STRING_FUNC") {
|
|
42373
42999
|
for (const arg of node.args) {
|
|
42374
|
-
if (arg.type !== "
|
|
42375
|
-
|
|
43000
|
+
if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH") collectScalarNodeRefs(arg, out);
|
|
43001
|
+
}
|
|
43002
|
+
}
|
|
43003
|
+
}
|
|
43004
|
+
async function resolveUpdateFromCheckScope(stmt, from, client, cacheContext, tempTables) {
|
|
43005
|
+
const refs = checkRefs(stmt);
|
|
43006
|
+
const targetTypes = await getFieldTypeMap(stmt.appId, client, cacheContext);
|
|
43007
|
+
const sourceTableName = from.cteName;
|
|
43008
|
+
const sourceTypes = sourceTableName !== null ? new Map((tempTables?.get(sourceTableName)?.columns ?? []).map((column) => [
|
|
43009
|
+
column,
|
|
43010
|
+
tempTables?.get(sourceTableName)?.columnMeta?.get(column)?.fieldType ?? (tempTables?.get(sourceTableName)?.columnMeta?.get(column)?.semantics?.compareMode === "number" ? "NUMBER" : "SINGLE_LINE_TEXT")
|
|
43011
|
+
])) : await getFieldTypeMap(from.appId, client, cacheContext);
|
|
43012
|
+
const targetFields = /* @__PURE__ */ new Set();
|
|
43013
|
+
const sourceFields = /* @__PURE__ */ new Set();
|
|
43014
|
+
for (const ref of refs) {
|
|
43015
|
+
if (ref.tableAlias !== null) {
|
|
43016
|
+
if (ref.tableAlias.toLowerCase() === `app${stmt.appId}`.toLowerCase()) {
|
|
43017
|
+
if (ref.field !== "$id" && !targetTypes.has(ref.field)) throw customCheckParseError(`CHECK \u306E\u30BF\u30FC\u30B2\u30C3\u30C8\u30D5\u30A3\u30FC\u30EB\u30C9 ${ref.field} \u306F\u5B58\u5728\u3057\u307E\u305B\u3093`);
|
|
43018
|
+
targetFields.add(ref.field);
|
|
43019
|
+
} else if (ref.tableAlias.toLowerCase() === from.alias.toLowerCase()) {
|
|
43020
|
+
if (ref.field !== "$id" && !sourceTypes.has(ref.field)) throw customCheckParseError(`CHECK \u306E\u30BD\u30FC\u30B9\u30D5\u30A3\u30FC\u30EB\u30C9 ${ref.field} \u306F\u5B58\u5728\u3057\u307E\u305B\u3093`);
|
|
43021
|
+
sourceFields.add(ref.field);
|
|
43022
|
+
} else {
|
|
43023
|
+
throw customCheckParseError(`CHECK \u306E\u4FEE\u98FE\u5B50 ${ref.tableAlias} \u306F\u66F4\u65B0\u5148\u307E\u305F\u306F FROM alias \u3067\u306F\u3042\u308A\u307E\u305B\u3093`);
|
|
42376
43024
|
}
|
|
43025
|
+
continue;
|
|
42377
43026
|
}
|
|
43027
|
+
const inTarget = ref.field === "$id" || targetTypes.has(ref.field);
|
|
43028
|
+
const inSource = ref.field === "$id" || sourceTypes.has(ref.field);
|
|
43029
|
+
if (!inTarget) {
|
|
43030
|
+
throw customCheckParseError(`UPDATE FROM \u306E CHECK \u3067\u306F\u30BD\u30FC\u30B9\u5217 ${ref.field} \u3092\u4FEE\u98FE\u3057\u3066\u304F\u3060\u3055\u3044`);
|
|
43031
|
+
}
|
|
43032
|
+
if (inSource) {
|
|
43033
|
+
throw customCheckParseError(`UPDATE FROM \u306E CHECK \u306E\u975E\u4FEE\u98FE\u30D5\u30A3\u30FC\u30EB\u30C9 ${ref.field} \u306F\u66D6\u6627\u3067\u3059`);
|
|
43034
|
+
}
|
|
43035
|
+
targetFields.add(ref.field);
|
|
43036
|
+
}
|
|
43037
|
+
const evaluationTypes = /* @__PURE__ */ new Map();
|
|
43038
|
+
for (const [field, type] of targetTypes) {
|
|
43039
|
+
evaluationTypes.set(field, type);
|
|
43040
|
+
evaluationTypes.set(`APP${stmt.appId}.${field}`, type);
|
|
43041
|
+
}
|
|
43042
|
+
evaluationTypes.set("$id", "RECORD_NUMBER");
|
|
43043
|
+
evaluationTypes.set(`APP${stmt.appId}.$id`, "RECORD_NUMBER");
|
|
43044
|
+
for (const [field, type] of sourceTypes) evaluationTypes.set(`${from.alias}.${field}`, type);
|
|
43045
|
+
return { targetFields: [...targetFields], sourceFields: [...sourceFields], evaluationTypes };
|
|
43046
|
+
}
|
|
43047
|
+
function updateFromEvaluationRow(pair, appId, sourceAlias) {
|
|
43048
|
+
if (!pair) return {};
|
|
43049
|
+
const target = flatten(pair.target, null);
|
|
43050
|
+
return Object.fromEntries([
|
|
43051
|
+
...Object.entries(target),
|
|
43052
|
+
...Object.entries(target).map(([field, value]) => [`APP${appId}.${field}`, value]),
|
|
43053
|
+
...Object.entries(pair.source).map(([field, value]) => [`${sourceAlias}.${field}`, value])
|
|
43054
|
+
]);
|
|
43055
|
+
}
|
|
43056
|
+
function collectScalarNodeRefs(node, out) {
|
|
43057
|
+
if (node.type === "FIELD") {
|
|
43058
|
+
out.add(node.tableAlias ? `${node.tableAlias}.${node.field}` : node.field);
|
|
43059
|
+
return;
|
|
43060
|
+
}
|
|
43061
|
+
if (node.type === "STRING_FUNC") {
|
|
43062
|
+
for (const arg of node.args) if (arg.type !== "AGG_REF" && arg.type !== "AGG_ARITH") collectScalarNodeRefs(arg, out);
|
|
43063
|
+
return;
|
|
43064
|
+
}
|
|
43065
|
+
if (node.type === "SCALAR_ARITH" || node.type === "CONCAT_OP") {
|
|
43066
|
+
collectScalarNodeRefs(node.left, out);
|
|
43067
|
+
collectScalarNodeRefs(node.right, out);
|
|
42378
43068
|
}
|
|
42379
43069
|
}
|
|
42380
43070
|
function formatAssignment(a) {
|
|
@@ -44998,7 +45688,7 @@ Options:
|
|
|
44998
45688
|
-h, --help Show help
|
|
44999
45689
|
`);
|
|
45000
45690
|
}
|
|
45001
|
-
var SERVER_VERSION = true ? "3.
|
|
45691
|
+
var SERVER_VERSION = true ? "3.4.0" : "0.0.0-dev";
|
|
45002
45692
|
function createServer(args) {
|
|
45003
45693
|
const server = new McpServer({
|
|
45004
45694
|
name: "ksql-mcp",
|