@rex0220/kintone-sql-tools 2.4.0 → 2.6.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 +392 -97
- package/dist-mcp/ksql-mcp.js +393 -98
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +1 -1
package/dist-mcp/ksql-mcp.js
CHANGED
|
@@ -34409,52 +34409,93 @@ function resolveFieldRef(row, field) {
|
|
|
34409
34409
|
}
|
|
34410
34410
|
|
|
34411
34411
|
// src/engine/evalWhere.ts
|
|
34412
|
-
function evalWhere(expr, row) {
|
|
34412
|
+
function evalWhere(expr, row, resolveFieldType) {
|
|
34413
34413
|
switch (expr.type) {
|
|
34414
34414
|
case "BINARY":
|
|
34415
|
-
return evalBinary(expr, row);
|
|
34415
|
+
return evalBinary(expr, row, resolveFieldType);
|
|
34416
34416
|
case "NULL_CHECK":
|
|
34417
34417
|
return evalNullCheck(expr, row);
|
|
34418
34418
|
case "LOGICAL":
|
|
34419
|
-
return evalLogical(expr, row);
|
|
34419
|
+
return evalLogical(expr, row, resolveFieldType);
|
|
34420
34420
|
case "NOT":
|
|
34421
|
-
return !evalWhere(expr.expr, row);
|
|
34421
|
+
return !evalWhere(expr.expr, row, resolveFieldType);
|
|
34422
34422
|
case "GROUP":
|
|
34423
|
-
return evalWhere(expr.expr, row);
|
|
34423
|
+
return evalWhere(expr.expr, row, resolveFieldType);
|
|
34424
34424
|
case "EXISTS": {
|
|
34425
34425
|
const exists = expr.resolved;
|
|
34426
34426
|
return expr.not ? !exists : exists;
|
|
34427
34427
|
}
|
|
34428
34428
|
}
|
|
34429
34429
|
}
|
|
34430
|
-
function evalBinary(expr, row) {
|
|
34431
|
-
const left = resolveField(expr.left, row);
|
|
34432
|
-
|
|
34430
|
+
function evalBinary(expr, row, resolveFieldType) {
|
|
34431
|
+
const left = resolveField(expr.left, row, resolveFieldType);
|
|
34432
|
+
const fieldType = expr.left.type === "FIELD" ? resolveFieldType?.(expr.left) : void 0;
|
|
34433
|
+
return evalOp(expr.op, left, expr.right, row, fieldType, resolveFieldType);
|
|
34433
34434
|
}
|
|
34434
|
-
function evalOp(op, leftStr, right, row) {
|
|
34435
|
+
function evalOp(op, leftStr, right, row, fieldType, resolveFieldType) {
|
|
34435
34436
|
if (op === "IN" || op === "NOT_IN") {
|
|
34437
|
+
let values = null;
|
|
34436
34438
|
if (right.type === "IN_LIST") {
|
|
34437
34439
|
assertResolvedInListValues2(right.values);
|
|
34438
|
-
|
|
34439
|
-
return op === "IN" ? contains : !contains;
|
|
34440
|
+
values = new Set(right.values.map((v) => String(v.value)));
|
|
34440
34441
|
}
|
|
34441
34442
|
if (right.type === "SUBQUERY_IN_LIST") {
|
|
34442
|
-
|
|
34443
|
-
return op === "IN" ? contains : !contains;
|
|
34443
|
+
values = right.resolved;
|
|
34444
34444
|
}
|
|
34445
|
-
return op === "NOT_IN";
|
|
34445
|
+
if (values === null) return op === "NOT_IN";
|
|
34446
|
+
const contains = typedInContains(leftStr, values, fieldType);
|
|
34447
|
+
return op === "IN" ? contains : !contains;
|
|
34446
34448
|
}
|
|
34447
34449
|
if (op === "LIKE") {
|
|
34448
|
-
const pattern = resolveValue(right, row);
|
|
34450
|
+
const pattern = resolveValue(right, row, resolveFieldType);
|
|
34449
34451
|
return matchLike(leftStr, pattern);
|
|
34450
34452
|
}
|
|
34451
34453
|
if (op === "NOT_LIKE") {
|
|
34452
|
-
const pattern = resolveValue(right, row);
|
|
34454
|
+
const pattern = resolveValue(right, row, resolveFieldType);
|
|
34453
34455
|
return !matchLike(leftStr, pattern);
|
|
34454
34456
|
}
|
|
34455
|
-
const rightStr = resolveValue(right, row);
|
|
34457
|
+
const rightStr = resolveValue(right, row, resolveFieldType);
|
|
34456
34458
|
return compareScalarValues(op, leftStr, rightStr);
|
|
34457
34459
|
}
|
|
34460
|
+
var STRING_ARRAY_FIELD_TYPES = /* @__PURE__ */ new Set(["CHECK_BOX", "MULTI_SELECT"]);
|
|
34461
|
+
var OBJECT_ARRAY_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
34462
|
+
"USER_SELECT",
|
|
34463
|
+
"ORGANIZATION_SELECT",
|
|
34464
|
+
"GROUP_SELECT",
|
|
34465
|
+
"STATUS_ASSIGNEE"
|
|
34466
|
+
]);
|
|
34467
|
+
var SINGLE_OBJECT_FIELD_TYPES = /* @__PURE__ */ new Set(["CREATOR", "MODIFIER"]);
|
|
34468
|
+
function typedInContains(leftStr, values, fieldType) {
|
|
34469
|
+
const fallback = () => values.has(leftStr);
|
|
34470
|
+
if (fieldType === void 0) return fallback();
|
|
34471
|
+
let parsed;
|
|
34472
|
+
if (STRING_ARRAY_FIELD_TYPES.has(fieldType) || OBJECT_ARRAY_FIELD_TYPES.has(fieldType) || SINGLE_OBJECT_FIELD_TYPES.has(fieldType)) {
|
|
34473
|
+
try {
|
|
34474
|
+
parsed = JSON.parse(leftStr);
|
|
34475
|
+
} catch {
|
|
34476
|
+
return fallback();
|
|
34477
|
+
}
|
|
34478
|
+
} else {
|
|
34479
|
+
return fallback();
|
|
34480
|
+
}
|
|
34481
|
+
if (STRING_ARRAY_FIELD_TYPES.has(fieldType)) {
|
|
34482
|
+
if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
|
|
34483
|
+
return fallback();
|
|
34484
|
+
}
|
|
34485
|
+
if (parsed.length === 0 && values.has("")) return true;
|
|
34486
|
+
return parsed.some((item) => values.has(item));
|
|
34487
|
+
}
|
|
34488
|
+
if (OBJECT_ARRAY_FIELD_TYPES.has(fieldType)) {
|
|
34489
|
+
if (!Array.isArray(parsed) || !parsed.every(hasStringCode)) return fallback();
|
|
34490
|
+
if (parsed.length === 0 && values.has("")) return true;
|
|
34491
|
+
return parsed.some((item) => values.has(item.code));
|
|
34492
|
+
}
|
|
34493
|
+
if (!hasStringCode(parsed)) return fallback();
|
|
34494
|
+
return values.has(parsed.code);
|
|
34495
|
+
}
|
|
34496
|
+
function hasStringCode(value) {
|
|
34497
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && typeof value.code === "string";
|
|
34498
|
+
}
|
|
34458
34499
|
function assertResolvedInListValues2(values) {
|
|
34459
34500
|
const unresolved = values.find((item) => item.type === "VARIABLE");
|
|
34460
34501
|
if (unresolved?.type === "VARIABLE") {
|
|
@@ -34465,20 +34506,20 @@ function evalNullCheck(expr, row) {
|
|
|
34465
34506
|
const val = resolveField(expr.field, row);
|
|
34466
34507
|
return expr.not ? val !== "" : val === "";
|
|
34467
34508
|
}
|
|
34468
|
-
function evalLogical(expr, row) {
|
|
34509
|
+
function evalLogical(expr, row, resolveFieldType) {
|
|
34469
34510
|
if (expr.op === "AND") {
|
|
34470
|
-
return evalWhere(expr.left, row) && evalWhere(expr.right, row);
|
|
34511
|
+
return evalWhere(expr.left, row, resolveFieldType) && evalWhere(expr.right, row, resolveFieldType);
|
|
34471
34512
|
}
|
|
34472
|
-
return evalWhere(expr.left, row) || evalWhere(expr.right, row);
|
|
34513
|
+
return evalWhere(expr.left, row, resolveFieldType) || evalWhere(expr.right, row, resolveFieldType);
|
|
34473
34514
|
}
|
|
34474
|
-
function resolveField(field, row) {
|
|
34515
|
+
function resolveField(field, row, resolveFieldType) {
|
|
34475
34516
|
if (field.type === "FUNC_FIELD") return evalStringFunc(field.expr, row);
|
|
34476
34517
|
if (field.type === "ARITH_FIELD") return String(evalArithExpr(field.expr, row));
|
|
34477
|
-
if (field.type === "CASE_FIELD") return evalCaseWhen(field.expr, row);
|
|
34518
|
+
if (field.type === "CASE_FIELD") return evalCaseWhen(field.expr, row, resolveFieldType);
|
|
34478
34519
|
const key = field.tableAlias ? `${field.tableAlias}.${field.field}` : field.field;
|
|
34479
34520
|
return resolveFieldRef(row, key);
|
|
34480
34521
|
}
|
|
34481
|
-
function resolveValue(value, row) {
|
|
34522
|
+
function resolveValue(value, row, resolveFieldType) {
|
|
34482
34523
|
switch (value.type) {
|
|
34483
34524
|
case "VARIABLE":
|
|
34484
34525
|
throw new Error(`ParseError: unresolved batch variable @${value.name}.`);
|
|
@@ -34501,14 +34542,14 @@ function resolveValue(value, row) {
|
|
|
34501
34542
|
if (value.expr.type === "STRING_FUNC") return evalStringFunc(value.expr, row);
|
|
34502
34543
|
return String(evalArithExpr(value.expr, row));
|
|
34503
34544
|
case "CASE_VALUE":
|
|
34504
|
-
return evalCaseWhen(value.expr, row);
|
|
34545
|
+
return evalCaseWhen(value.expr, row, resolveFieldType);
|
|
34505
34546
|
case "ARRAY":
|
|
34506
34547
|
return value.elements.map((e) => e.value).join(",");
|
|
34507
34548
|
}
|
|
34508
34549
|
}
|
|
34509
|
-
function evalCaseWhen(expr, row) {
|
|
34550
|
+
function evalCaseWhen(expr, row, resolveFieldType) {
|
|
34510
34551
|
for (const branch of expr.branches) {
|
|
34511
|
-
if (evalWhere(branch.condition, row)) {
|
|
34552
|
+
if (evalWhere(branch.condition, row, resolveFieldType)) {
|
|
34512
34553
|
return evalCaseResult(branch.result, row);
|
|
34513
34554
|
}
|
|
34514
34555
|
}
|
|
@@ -35059,8 +35100,11 @@ async function resolveDmlTargetIds(getRecords, app, query, options) {
|
|
|
35059
35100
|
function extractSafePushdownLeaves(where, options = {}) {
|
|
35060
35101
|
return extractAndLeaves(where, (expr) => isSafeComparison(expr, options));
|
|
35061
35102
|
}
|
|
35062
|
-
function
|
|
35063
|
-
return extractAndLeaves(
|
|
35103
|
+
function extractTypedPushdownCandidates(where, options = {}) {
|
|
35104
|
+
return extractAndLeaves(
|
|
35105
|
+
where,
|
|
35106
|
+
(expr) => isNumericCandidate(expr, options) || isSelectionInCandidate(expr, options)
|
|
35107
|
+
);
|
|
35064
35108
|
}
|
|
35065
35109
|
function extractAndLeaves(where, accept) {
|
|
35066
35110
|
switch (where.type) {
|
|
@@ -35084,8 +35128,27 @@ function extractAndLeaves(where, accept) {
|
|
|
35084
35128
|
}
|
|
35085
35129
|
function isSafeComparison(expr, options) {
|
|
35086
35130
|
if (isSafeIdComparison(expr, options)) return true;
|
|
35087
|
-
if (
|
|
35088
|
-
|
|
35131
|
+
if (isNumericCandidate(expr, options)) {
|
|
35132
|
+
return options.fieldTypes?.get(expr.left.field) === "NUMBER";
|
|
35133
|
+
}
|
|
35134
|
+
return isSelectionInComparison(expr, options);
|
|
35135
|
+
}
|
|
35136
|
+
var SELECTION_IN_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
35137
|
+
"DROP_DOWN",
|
|
35138
|
+
"RADIO_BUTTON",
|
|
35139
|
+
"CHECK_BOX",
|
|
35140
|
+
"MULTI_SELECT"
|
|
35141
|
+
]);
|
|
35142
|
+
function isSelectionInComparison(expr, options) {
|
|
35143
|
+
if (!isSelectionInCandidate(expr, options)) return false;
|
|
35144
|
+
if (expr.left.type !== "FIELD" || expr.right.type !== "IN_LIST") return false;
|
|
35145
|
+
const fieldType = options.fieldTypes?.get(expr.left.field);
|
|
35146
|
+
if (fieldType === void 0 || !SELECTION_IN_FIELD_TYPES.has(fieldType)) return false;
|
|
35147
|
+
const validOptions = options.fieldOptions?.get(expr.left.field);
|
|
35148
|
+
if (validOptions === void 0) return false;
|
|
35149
|
+
return expr.right.values.every(
|
|
35150
|
+
(value) => value.type === "STRING" && value.value !== "" && validOptions.has(value.value)
|
|
35151
|
+
);
|
|
35089
35152
|
}
|
|
35090
35153
|
function isSafeIdComparison(expr, options) {
|
|
35091
35154
|
if (!isTargetIdField(expr.left, options)) return false;
|
|
@@ -35105,6 +35168,13 @@ function isNumericCandidate(expr, options) {
|
|
|
35105
35168
|
if (expr.op === "=") return true;
|
|
35106
35169
|
return (expr.op === "<" || expr.op === ">") && Number.isSafeInteger(expr.right.value);
|
|
35107
35170
|
}
|
|
35171
|
+
function isSelectionInCandidate(expr, options) {
|
|
35172
|
+
if (expr.left.type !== "FIELD" || expr.left.field === "$id") return false;
|
|
35173
|
+
if (!isTargetField(expr.left, options)) return false;
|
|
35174
|
+
if (expr.op !== "IN" && expr.op !== "NOT_IN") return false;
|
|
35175
|
+
if (expr.right.type !== "IN_LIST" || expr.right.values.length === 0) return false;
|
|
35176
|
+
return expr.right.values.every((value) => value.type === "STRING" && value.value !== "");
|
|
35177
|
+
}
|
|
35108
35178
|
function isTargetField(field, options) {
|
|
35109
35179
|
const targetAlias = options.tableAlias ?? null;
|
|
35110
35180
|
if (field.tableAlias === targetAlias) return true;
|
|
@@ -35116,7 +35186,7 @@ function flatten(record2, alias) {
|
|
|
35116
35186
|
const row = {};
|
|
35117
35187
|
for (const [field, fv] of Object.entries(record2)) {
|
|
35118
35188
|
const val = fv.value;
|
|
35119
|
-
const strVal = typeof val === "string" ? val : JSON.stringify(val
|
|
35189
|
+
const strVal = val == null ? "" : typeof val === "string" ? val : JSON.stringify(val);
|
|
35120
35190
|
if (alias) {
|
|
35121
35191
|
row[`${alias}.${field}`] = strVal;
|
|
35122
35192
|
row[field] = strVal;
|
|
@@ -35175,9 +35245,9 @@ function applyJoin(leftRows, rightRows, join) {
|
|
|
35175
35245
|
}
|
|
35176
35246
|
return result;
|
|
35177
35247
|
}
|
|
35178
|
-
function applyFilter(rows, where) {
|
|
35248
|
+
function applyFilter(rows, where, resolveFieldType) {
|
|
35179
35249
|
if (where === null) return rows;
|
|
35180
|
-
return rows.filter((row) => evalWhere(where, row));
|
|
35250
|
+
return rows.filter((row) => evalWhere(where, row, resolveFieldType));
|
|
35181
35251
|
}
|
|
35182
35252
|
function hasAggregateColumns(columns) {
|
|
35183
35253
|
return columns.some(
|
|
@@ -35303,9 +35373,9 @@ function aggregateSyntheticName2(func, distinct, arg) {
|
|
|
35303
35373
|
const argStr = aggregateArgLabel(arg);
|
|
35304
35374
|
return distinct ? `${func}(DISTINCT ${argStr})` : `${func}(${argStr})`;
|
|
35305
35375
|
}
|
|
35306
|
-
function applyHaving(rows, having) {
|
|
35376
|
+
function applyHaving(rows, having, resolveFieldType) {
|
|
35307
35377
|
if (having === null) return rows;
|
|
35308
|
-
return rows.filter((row) => evalWhere(having, row));
|
|
35378
|
+
return rows.filter((row) => evalWhere(having, row, resolveFieldType));
|
|
35309
35379
|
}
|
|
35310
35380
|
function applyDistinct(rows, columns) {
|
|
35311
35381
|
if (rows.length === 0) return rows;
|
|
@@ -35430,7 +35500,7 @@ function applyLimit(rows, limit, offset) {
|
|
|
35430
35500
|
if (limit === null) return rows.slice(start);
|
|
35431
35501
|
return rows.slice(start, start + limit);
|
|
35432
35502
|
}
|
|
35433
|
-
function project(rows, columns, scalarCache) {
|
|
35503
|
+
function project(rows, columns, scalarCache, resolveFieldType) {
|
|
35434
35504
|
if (columns.length === 1 && columns[0].type === "WILDCARD") {
|
|
35435
35505
|
const projected2 = rows.map((row) => stripParentShortcutColumns(row));
|
|
35436
35506
|
const cols = projected2.length > 0 ? Object.keys(projected2[0]) : [];
|
|
@@ -35491,7 +35561,7 @@ function project(rows, columns, scalarCache) {
|
|
|
35491
35561
|
}
|
|
35492
35562
|
case "CASE_COL": {
|
|
35493
35563
|
const key = outputKeys?.[colIdx] ?? col.alias ?? "case";
|
|
35494
|
-
out[key] = evalCaseWhen(col.expr, row);
|
|
35564
|
+
out[key] = evalCaseWhen(col.expr, row, resolveFieldType);
|
|
35495
35565
|
if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
|
|
35496
35566
|
break;
|
|
35497
35567
|
}
|
|
@@ -35627,7 +35697,15 @@ function resolveAggInStringFuncExpr(expr, rows) {
|
|
|
35627
35697
|
};
|
|
35628
35698
|
}
|
|
35629
35699
|
function runFullScan(input) {
|
|
35630
|
-
const {
|
|
35700
|
+
const {
|
|
35701
|
+
stmt,
|
|
35702
|
+
tables,
|
|
35703
|
+
scalarCache,
|
|
35704
|
+
optionOrders,
|
|
35705
|
+
sortKinds,
|
|
35706
|
+
fieldTypeResolver,
|
|
35707
|
+
havingFieldTypeResolver
|
|
35708
|
+
} = input;
|
|
35631
35709
|
let rows = [];
|
|
35632
35710
|
const mainAlias = stmt.from.alias;
|
|
35633
35711
|
const mainRecords = tables.get(mainAlias) ?? tables.get(null) ?? [];
|
|
@@ -35638,17 +35716,17 @@ function runFullScan(input) {
|
|
|
35638
35716
|
const rightRows = rightRecords.map((r) => flatten(r, rightAlias));
|
|
35639
35717
|
rows = applyJoin(rows, rightRows, join);
|
|
35640
35718
|
}
|
|
35641
|
-
rows = applyFilter(rows, stmt.where);
|
|
35719
|
+
rows = applyFilter(rows, stmt.where, fieldTypeResolver);
|
|
35642
35720
|
if (stmt.groupBy.length > 0 || hasAggregateColumns(stmt.columns)) {
|
|
35643
35721
|
rows = applyGroupBy(rows, stmt.groupBy, stmt.columns);
|
|
35644
35722
|
}
|
|
35645
|
-
rows = applyHaving(rows, stmt.having);
|
|
35723
|
+
rows = applyHaving(rows, stmt.having, havingFieldTypeResolver);
|
|
35646
35724
|
if (stmt.distinct) {
|
|
35647
35725
|
rows = applyDistinct(rows, stmt.columns);
|
|
35648
35726
|
}
|
|
35649
35727
|
rows = applyOrderBy(rows, stmt.orderBy, optionOrders, sortKinds);
|
|
35650
35728
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
35651
|
-
return project(rows, stmt.columns, scalarCache);
|
|
35729
|
+
return project(rows, stmt.columns, scalarCache, fieldTypeResolver);
|
|
35652
35730
|
}
|
|
35653
35731
|
|
|
35654
35732
|
// src/converter/subtableAdapter.ts
|
|
@@ -36181,6 +36259,7 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache) {
|
|
|
36181
36259
|
if (isNoFromSelect(stmt)) {
|
|
36182
36260
|
return executeNoFromSelect(stmt);
|
|
36183
36261
|
}
|
|
36262
|
+
await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
|
|
36184
36263
|
const mode = resolveSelectMode(stmt);
|
|
36185
36264
|
await validateSelectFieldCodes(stmt, mode, client, cacheContext);
|
|
36186
36265
|
if (mode === "SIMPLE") {
|
|
@@ -36239,6 +36318,8 @@ function executeNoFromSelect(stmt) {
|
|
|
36239
36318
|
}
|
|
36240
36319
|
async function executeSimpleSelect(stmt, client, options, cacheContext) {
|
|
36241
36320
|
const params = selectToKintoneParams(stmt);
|
|
36321
|
+
const typedInFieldTypes = await loadTypedInFieldTypes(stmt, client, cacheContext);
|
|
36322
|
+
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
36242
36323
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
36243
36324
|
const warnings = /* @__PURE__ */ new Set();
|
|
36244
36325
|
const onLimit2 = options.onLimitReached ?? "error";
|
|
@@ -36275,7 +36356,12 @@ async function executeSimpleSelect(stmt, client, options, cacheContext) {
|
|
|
36275
36356
|
rows = applyOrderBy(rows, stmt.orderBy, optionOrders, sortKinds);
|
|
36276
36357
|
rows = applyLimit(rows, stmt.limit, stmt.offset);
|
|
36277
36358
|
}
|
|
36278
|
-
const { rows: projected, columns } = project(
|
|
36359
|
+
const { rows: projected, columns } = project(
|
|
36360
|
+
rows,
|
|
36361
|
+
stmt.columns,
|
|
36362
|
+
void 0,
|
|
36363
|
+
fieldTypeResolvers.row
|
|
36364
|
+
);
|
|
36279
36365
|
return { type: "SELECT", rows: projected, columns, rowCount: projected.length, warnings: [...warnings] };
|
|
36280
36366
|
}
|
|
36281
36367
|
async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
|
|
@@ -36310,44 +36396,160 @@ async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
|
|
|
36310
36396
|
}
|
|
36311
36397
|
}
|
|
36312
36398
|
}
|
|
36313
|
-
function extractMainSafePushdown(stmt, fieldTypes) {
|
|
36399
|
+
function extractMainSafePushdown(stmt, fieldTypes, fieldOptions) {
|
|
36314
36400
|
if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
|
|
36315
36401
|
if (stmt.joins.length === 0) {
|
|
36316
36402
|
return extractSafePushdownLeaves(stmt.where, {
|
|
36317
36403
|
tableAlias: stmt.from.alias ?? void 0,
|
|
36318
36404
|
allowUnqualifiedFields: true,
|
|
36319
|
-
fieldTypes
|
|
36405
|
+
fieldTypes,
|
|
36406
|
+
fieldOptions
|
|
36320
36407
|
});
|
|
36321
36408
|
}
|
|
36322
36409
|
if (!stmt.from.alias) return null;
|
|
36323
|
-
return extractSafePushdownLeaves(stmt.where, {
|
|
36410
|
+
return extractSafePushdownLeaves(stmt.where, {
|
|
36411
|
+
tableAlias: stmt.from.alias,
|
|
36412
|
+
fieldTypes,
|
|
36413
|
+
fieldOptions
|
|
36414
|
+
});
|
|
36324
36415
|
}
|
|
36325
|
-
function
|
|
36416
|
+
function extractMainTypedPushdownCandidate(stmt) {
|
|
36326
36417
|
if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
|
|
36327
36418
|
if (stmt.joins.length === 0) {
|
|
36328
|
-
return
|
|
36419
|
+
return extractTypedPushdownCandidates(stmt.where, {
|
|
36329
36420
|
tableAlias: stmt.from.alias ?? void 0,
|
|
36330
36421
|
allowUnqualifiedFields: true
|
|
36331
36422
|
});
|
|
36332
36423
|
}
|
|
36333
36424
|
if (!stmt.from.alias) return null;
|
|
36334
|
-
return
|
|
36425
|
+
return extractTypedPushdownCandidates(stmt.where, { tableAlias: stmt.from.alias });
|
|
36335
36426
|
}
|
|
36336
|
-
async function
|
|
36427
|
+
async function loadTypedPushdownMeta(stmt, client, cacheContext) {
|
|
36337
36428
|
const appIds = /* @__PURE__ */ new Set();
|
|
36338
|
-
if (
|
|
36429
|
+
if (extractMainTypedPushdownCandidate(stmt) !== null) appIds.add(stmt.from.appId);
|
|
36339
36430
|
if (stmt.where !== null) {
|
|
36340
36431
|
for (const join of stmt.joins) {
|
|
36341
36432
|
if (!join.table.alias || join.table.subtableCode || join.table.cteName !== null) continue;
|
|
36342
|
-
const candidate =
|
|
36433
|
+
const candidate = extractTypedPushdownCandidates(stmt.where, {
|
|
36343
36434
|
tableAlias: join.table.alias
|
|
36344
36435
|
});
|
|
36345
36436
|
if (candidate !== null) appIds.add(join.table.appId);
|
|
36346
36437
|
}
|
|
36347
36438
|
}
|
|
36439
|
+
const entries = await Promise.all([...appIds].map(async (appId) => {
|
|
36440
|
+
const [fieldTypes, fieldOptions] = await Promise.all([
|
|
36441
|
+
getFieldTypeMap(appId, client, cacheContext),
|
|
36442
|
+
getFieldOptionSetMapByApp(appId, client, cacheContext)
|
|
36443
|
+
]);
|
|
36444
|
+
return [appId, fieldTypes, fieldOptions];
|
|
36445
|
+
}));
|
|
36446
|
+
return {
|
|
36447
|
+
fieldTypesByApp: new Map(entries.map(([appId, fieldTypes]) => [appId, fieldTypes])),
|
|
36448
|
+
fieldOptionsByApp: new Map(entries.map(([appId, , fieldOptions]) => [appId, fieldOptions]))
|
|
36449
|
+
};
|
|
36450
|
+
}
|
|
36451
|
+
function collectTypedInFieldRefs(expr, out) {
|
|
36452
|
+
if (expr === null) return;
|
|
36453
|
+
switch (expr.type) {
|
|
36454
|
+
case "BINARY":
|
|
36455
|
+
if ((expr.op === "IN" || expr.op === "NOT_IN") && expr.left.type === "FIELD") {
|
|
36456
|
+
out.push(expr.left);
|
|
36457
|
+
}
|
|
36458
|
+
if (expr.left.type === "CASE_FIELD") collectCaseTypedInFieldRefs(expr.left.expr, out);
|
|
36459
|
+
if (expr.right.type === "CASE_VALUE") collectCaseTypedInFieldRefs(expr.right.expr, out);
|
|
36460
|
+
return;
|
|
36461
|
+
case "LOGICAL":
|
|
36462
|
+
collectTypedInFieldRefs(expr.left, out);
|
|
36463
|
+
collectTypedInFieldRefs(expr.right, out);
|
|
36464
|
+
return;
|
|
36465
|
+
case "NOT":
|
|
36466
|
+
case "GROUP":
|
|
36467
|
+
collectTypedInFieldRefs(expr.expr, out);
|
|
36468
|
+
return;
|
|
36469
|
+
case "NULL_CHECK":
|
|
36470
|
+
case "EXISTS":
|
|
36471
|
+
return;
|
|
36472
|
+
}
|
|
36473
|
+
}
|
|
36474
|
+
function collectCaseTypedInFieldRefs(expr, out) {
|
|
36475
|
+
for (const branch of expr.branches) collectTypedInFieldRefs(branch.condition, out);
|
|
36476
|
+
}
|
|
36477
|
+
function collectSelectTypedInFieldRefs(stmt) {
|
|
36478
|
+
const refs = [];
|
|
36479
|
+
collectTypedInFieldRefs(stmt.where, refs);
|
|
36480
|
+
collectTypedInFieldRefs(stmt.having, refs);
|
|
36481
|
+
for (const column of stmt.columns) {
|
|
36482
|
+
if (column.type === "CASE_COL") collectCaseTypedInFieldRefs(column.expr, refs);
|
|
36483
|
+
}
|
|
36484
|
+
return refs;
|
|
36485
|
+
}
|
|
36486
|
+
function findTableForAlias(stmt, alias) {
|
|
36487
|
+
return [stmt.from, ...stmt.joins.map((join) => join.table)].find((table) => table.alias === alias);
|
|
36488
|
+
}
|
|
36489
|
+
function physicalSelectTables(stmt) {
|
|
36490
|
+
return [stmt.from, ...stmt.joins.map((join) => join.table)].filter((table) => table.cteName === null);
|
|
36491
|
+
}
|
|
36492
|
+
async function loadTypedInFieldTypes(stmt, client, cacheContext) {
|
|
36493
|
+
const refs = collectSelectTypedInFieldRefs(stmt);
|
|
36494
|
+
if (refs.length === 0) return /* @__PURE__ */ new Map();
|
|
36495
|
+
const appIds = /* @__PURE__ */ new Set();
|
|
36496
|
+
const physicalTables = physicalSelectTables(stmt);
|
|
36497
|
+
for (const ref of refs) {
|
|
36498
|
+
if (ref.tableAlias !== null) {
|
|
36499
|
+
if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
36500
|
+
appIds.add(stmt.from.appId);
|
|
36501
|
+
continue;
|
|
36502
|
+
}
|
|
36503
|
+
const table = findTableForAlias(stmt, ref.tableAlias);
|
|
36504
|
+
if (table && table.cteName === null) appIds.add(table.appId);
|
|
36505
|
+
continue;
|
|
36506
|
+
}
|
|
36507
|
+
if (stmt.joins.length === 0) {
|
|
36508
|
+
if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
|
|
36509
|
+
continue;
|
|
36510
|
+
}
|
|
36511
|
+
for (const table of physicalTables) appIds.add(table.appId);
|
|
36512
|
+
}
|
|
36348
36513
|
const entries = await Promise.all([...appIds].map(async (appId) => [appId, await getFieldTypeMap(appId, client, cacheContext)]));
|
|
36349
36514
|
return new Map(entries);
|
|
36350
36515
|
}
|
|
36516
|
+
function fieldCodeForTypeLookup(table, field) {
|
|
36517
|
+
if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
|
|
36518
|
+
return field;
|
|
36519
|
+
}
|
|
36520
|
+
function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
|
|
36521
|
+
const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
|
|
36522
|
+
const physicalTables = tables.filter((table) => table.cteName === null);
|
|
36523
|
+
const outputAliases = new Set(
|
|
36524
|
+
stmt.columns.map((column) => "alias" in column ? column.alias : null).filter((alias) => alias !== null)
|
|
36525
|
+
);
|
|
36526
|
+
const row = (field) => {
|
|
36527
|
+
if (field.tableAlias !== null) {
|
|
36528
|
+
if (field.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
|
|
36529
|
+
return fieldTypesByApp.get(stmt.from.appId)?.get(field.field);
|
|
36530
|
+
}
|
|
36531
|
+
const table2 = tables.find((candidate) => candidate.alias === field.tableAlias);
|
|
36532
|
+
if (!table2 || table2.cteName !== null) return void 0;
|
|
36533
|
+
return fieldTypesByApp.get(table2.appId)?.get(fieldCodeForTypeLookup(table2, field.field));
|
|
36534
|
+
}
|
|
36535
|
+
if (stmt.joins.length === 0) {
|
|
36536
|
+
if (stmt.from.cteName !== null) return void 0;
|
|
36537
|
+
return fieldTypesByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, field.field));
|
|
36538
|
+
}
|
|
36539
|
+
if (tables.some((table2) => table2.cteName !== null)) return void 0;
|
|
36540
|
+
const matches = physicalTables.filter(
|
|
36541
|
+
(table2) => fieldTypesByApp.get(table2.appId)?.has(fieldCodeForTypeLookup(table2, field.field))
|
|
36542
|
+
);
|
|
36543
|
+
if (matches.length !== 1) return void 0;
|
|
36544
|
+
const table = matches[0];
|
|
36545
|
+
return fieldTypesByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, field.field));
|
|
36546
|
+
};
|
|
36547
|
+
const having = (field) => {
|
|
36548
|
+
if (field.tableAlias === null && outputAliases.has(field.field)) return void 0;
|
|
36549
|
+
return row(field);
|
|
36550
|
+
};
|
|
36551
|
+
return { row, having };
|
|
36552
|
+
}
|
|
36351
36553
|
async function executeFullScanSelect(stmt, client, options, cacheContext, cteCache) {
|
|
36352
36554
|
const maxRecords2 = options.maxRecords ?? 1e4;
|
|
36353
36555
|
const warnings = /* @__PURE__ */ new Set();
|
|
@@ -36356,10 +36558,15 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
36356
36558
|
resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
|
|
36357
36559
|
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache)
|
|
36358
36560
|
]);
|
|
36359
|
-
const
|
|
36561
|
+
const [pushdownMeta, typedInFieldTypes] = await Promise.all([
|
|
36562
|
+
loadTypedPushdownMeta(stmt, client, cacheContext),
|
|
36563
|
+
loadTypedInFieldTypes(stmt, client, cacheContext)
|
|
36564
|
+
]);
|
|
36565
|
+
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
36360
36566
|
const mainPushDown = extractMainSafePushdown(
|
|
36361
36567
|
stmt,
|
|
36362
|
-
|
|
36568
|
+
pushdownMeta.fieldTypesByApp.get(stmt.from.appId),
|
|
36569
|
+
pushdownMeta.fieldOptionsByApp.get(stmt.from.appId)
|
|
36363
36570
|
);
|
|
36364
36571
|
const tableConditions = /* @__PURE__ */ new Map();
|
|
36365
36572
|
if (stmt.where !== null) {
|
|
@@ -36367,7 +36574,8 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
36367
36574
|
if (!join.table.alias || join.table.subtableCode || join.table.cteName !== null) continue;
|
|
36368
36575
|
const cond = extractSafePushdownLeaves(stmt.where, {
|
|
36369
36576
|
tableAlias: join.table.alias,
|
|
36370
|
-
fieldTypes:
|
|
36577
|
+
fieldTypes: pushdownMeta.fieldTypesByApp.get(join.table.appId),
|
|
36578
|
+
fieldOptions: pushdownMeta.fieldOptionsByApp.get(join.table.appId)
|
|
36371
36579
|
});
|
|
36372
36580
|
if (cond) tableConditions.set(join.table.alias, cond);
|
|
36373
36581
|
}
|
|
@@ -36445,7 +36653,15 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
|
|
|
36445
36653
|
}));
|
|
36446
36654
|
const scalarCache = await scalarCachePromise;
|
|
36447
36655
|
const { optionOrders, sortKinds } = await orderByMetaPromise;
|
|
36448
|
-
const { rows, columns } = runFullScan({
|
|
36656
|
+
const { rows, columns } = runFullScan({
|
|
36657
|
+
tables,
|
|
36658
|
+
stmt,
|
|
36659
|
+
scalarCache,
|
|
36660
|
+
optionOrders,
|
|
36661
|
+
sortKinds,
|
|
36662
|
+
fieldTypeResolver: fieldTypeResolvers.row,
|
|
36663
|
+
havingFieldTypeResolver: fieldTypeResolvers.having
|
|
36664
|
+
});
|
|
36449
36665
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
36450
36666
|
}
|
|
36451
36667
|
async function executeUnion(stmt, client, options, cacheContext) {
|
|
@@ -36601,8 +36817,11 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
36601
36817
|
const parallel = options.fetchParallel ?? 1;
|
|
36602
36818
|
await Promise.all([
|
|
36603
36819
|
resolveSubqueries(stmt.where, client, options, cacheContext, cteCache),
|
|
36604
|
-
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache)
|
|
36820
|
+
resolveSubqueries(stmt.having, client, options, cacheContext, cteCache),
|
|
36821
|
+
resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache)
|
|
36605
36822
|
]);
|
|
36823
|
+
const typedInFieldTypes = await loadTypedInFieldTypes(stmt, client, cacheContext);
|
|
36824
|
+
const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
|
|
36606
36825
|
const scalarCachePromise = resolveScalarColumns(stmt.columns, client, options, cacheContext, cteCache);
|
|
36607
36826
|
const orderByMetaPromise = buildOrderByMetaForSelect(stmt, client, cacheContext);
|
|
36608
36827
|
scalarCachePromise.catch(() => {
|
|
@@ -36657,7 +36876,15 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
|
|
|
36657
36876
|
await Promise.all(joinFetches);
|
|
36658
36877
|
const scalarCache = await scalarCachePromise;
|
|
36659
36878
|
const { optionOrders, sortKinds } = await orderByMetaPromise;
|
|
36660
|
-
const { rows, columns } = runFullScan({
|
|
36879
|
+
const { rows, columns } = runFullScan({
|
|
36880
|
+
tables,
|
|
36881
|
+
stmt,
|
|
36882
|
+
scalarCache,
|
|
36883
|
+
optionOrders,
|
|
36884
|
+
sortKinds,
|
|
36885
|
+
fieldTypeResolver: fieldTypeResolvers.row,
|
|
36886
|
+
havingFieldTypeResolver: fieldTypeResolvers.having
|
|
36887
|
+
});
|
|
36661
36888
|
return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [...warnings] };
|
|
36662
36889
|
}
|
|
36663
36890
|
function processRowToKintoneRecord(row) {
|
|
@@ -36889,6 +37116,15 @@ async function getOptionOrderMapByApp(appId, client, cacheContext) {
|
|
|
36889
37116
|
setScopedCacheValue(optionOrderCache, cacheContext, appId, map2);
|
|
36890
37117
|
return map2;
|
|
36891
37118
|
}
|
|
37119
|
+
async function getFieldOptionSetMapByApp(appId, client, cacheContext) {
|
|
37120
|
+
const optionOrders = await getOptionOrderMapByApp(appId, client, cacheContext);
|
|
37121
|
+
return new Map(
|
|
37122
|
+
[...optionOrders.entries()].map(([fieldCode, order]) => [
|
|
37123
|
+
fieldCode,
|
|
37124
|
+
new Set(order.keys())
|
|
37125
|
+
])
|
|
37126
|
+
);
|
|
37127
|
+
}
|
|
36892
37128
|
async function getSortKindMapByApp(appId, client, cacheContext) {
|
|
36893
37129
|
const cached2 = getScopedCacheValue(sortKindCache, cacheContext, appId);
|
|
36894
37130
|
if (cached2) return cached2;
|
|
@@ -37154,6 +37390,16 @@ async function executeUpsert(stmt, client, options, cacheContext) {
|
|
|
37154
37390
|
updatedCount: toUpdate.length
|
|
37155
37391
|
};
|
|
37156
37392
|
}
|
|
37393
|
+
async function buildSubtableFieldTypeResolver(appId, typedInRefs, client, cacheContext) {
|
|
37394
|
+
if (typedInRefs.length === 0) return void 0;
|
|
37395
|
+
const fieldTypes = await getFieldTypeMap(appId, client, cacheContext);
|
|
37396
|
+
return (field) => {
|
|
37397
|
+
if (field.tableAlias !== null && field.tableAlias !== "_p") return void 0;
|
|
37398
|
+
if (field.tableAlias === "_p") return fieldTypes.get(field.field);
|
|
37399
|
+
const code = field.field.startsWith("_p.") ? field.field.slice(3) : field.field;
|
|
37400
|
+
return fieldTypes.get(code);
|
|
37401
|
+
};
|
|
37402
|
+
}
|
|
37157
37403
|
async function executeInsertSubtable(stmt, client, options, _cacheContext) {
|
|
37158
37404
|
const subtableCode = stmt.subtableCode;
|
|
37159
37405
|
const pidIndex = stmt.fields.indexOf("_pid");
|
|
@@ -37194,11 +37440,24 @@ async function executeInsertSubtable(stmt, client, options, _cacheContext) {
|
|
|
37194
37440
|
}
|
|
37195
37441
|
return { type: "INSERT", createdIds: [], insertedCount: stmt.values.length };
|
|
37196
37442
|
}
|
|
37197
|
-
async function executeUpdateSubtable(stmt, client, options,
|
|
37443
|
+
async function executeUpdateSubtable(stmt, client, options, cacheContext) {
|
|
37198
37444
|
const subtableCode = stmt.subtableCode;
|
|
37199
37445
|
if (!hasRidCondition(stmt.where)) {
|
|
37200
37446
|
throw new Error("\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB UPDATE \u306B\u306F _rid \u6761\u4EF6\u304C\u5FC5\u9808\u3067\u3059");
|
|
37201
37447
|
}
|
|
37448
|
+
const typedInRefs = [];
|
|
37449
|
+
collectTypedInFieldRefs(stmt.where, typedInRefs);
|
|
37450
|
+
for (const assignment of stmt.assignments) {
|
|
37451
|
+
if (assignment.value.type === "CASE_VALUE") {
|
|
37452
|
+
collectCaseTypedInFieldRefs(assignment.value.expr, typedInRefs);
|
|
37453
|
+
}
|
|
37454
|
+
}
|
|
37455
|
+
const resolveFieldType = await buildSubtableFieldTypeResolver(
|
|
37456
|
+
stmt.appId,
|
|
37457
|
+
typedInRefs,
|
|
37458
|
+
client,
|
|
37459
|
+
cacheContext
|
|
37460
|
+
);
|
|
37202
37461
|
const parents = await fetchAll(
|
|
37203
37462
|
client.getRecords,
|
|
37204
37463
|
stmt.appId,
|
|
@@ -37207,7 +37466,7 @@ async function executeUpdateSubtable(stmt, client, options, _cacheContext) {
|
|
|
37207
37466
|
{ maxRecords: options.maxRecords ?? 1e4, parallel: options.fetchParallel ?? 1 }
|
|
37208
37467
|
);
|
|
37209
37468
|
const expanded = expandRowsForSubtableDml(parents, subtableCode);
|
|
37210
|
-
const targets = expanded.filter((r) => evalWhere(stmt.where, r.flat));
|
|
37469
|
+
const targets = expanded.filter((r) => evalWhere(stmt.where, r.flat, resolveFieldType));
|
|
37211
37470
|
if (options.confirm) {
|
|
37212
37471
|
const ok = await options.confirm(targets.length, "UPDATE");
|
|
37213
37472
|
if (!ok) throw new OperationCancelledError("UPDATE", targets.length);
|
|
@@ -37227,7 +37486,7 @@ async function executeUpdateSubtable(stmt, client, options, _cacheContext) {
|
|
|
37227
37486
|
if (a.field.startsWith("_")) {
|
|
37228
37487
|
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`);
|
|
37229
37488
|
}
|
|
37230
|
-
updates[a.field] = { value: evalAssignmentValueForSubtable(a.value, t.flat) };
|
|
37489
|
+
updates[a.field] = { value: evalAssignmentValueForSubtable(a.value, t.flat, resolveFieldType) };
|
|
37231
37490
|
}
|
|
37232
37491
|
byRid.set(t.rowId, updates);
|
|
37233
37492
|
}
|
|
@@ -37249,11 +37508,19 @@ async function executeUpdateSubtable(stmt, client, options, _cacheContext) {
|
|
|
37249
37508
|
}
|
|
37250
37509
|
return { type: "UPDATE", updatedCount: targets.length };
|
|
37251
37510
|
}
|
|
37252
|
-
async function executeDeleteSubtable(stmt, client, options,
|
|
37511
|
+
async function executeDeleteSubtable(stmt, client, options, cacheContext) {
|
|
37253
37512
|
const subtableCode = stmt.subtableCode;
|
|
37254
37513
|
if (!hasRidCondition(stmt.where)) {
|
|
37255
37514
|
throw new Error("\u30B5\u30D6\u30C6\u30FC\u30D6\u30EB DELETE \u306B\u306F _rid \u6761\u4EF6\u304C\u5FC5\u9808\u3067\u3059");
|
|
37256
37515
|
}
|
|
37516
|
+
const typedInRefs = [];
|
|
37517
|
+
collectTypedInFieldRefs(stmt.where, typedInRefs);
|
|
37518
|
+
const resolveFieldType = await buildSubtableFieldTypeResolver(
|
|
37519
|
+
stmt.appId,
|
|
37520
|
+
typedInRefs,
|
|
37521
|
+
client,
|
|
37522
|
+
cacheContext
|
|
37523
|
+
);
|
|
37257
37524
|
const parents = await fetchAll(
|
|
37258
37525
|
client.getRecords,
|
|
37259
37526
|
stmt.appId,
|
|
@@ -37262,7 +37529,7 @@ async function executeDeleteSubtable(stmt, client, options, _cacheContext) {
|
|
|
37262
37529
|
{ maxRecords: options.maxRecords ?? 1e4, parallel: options.fetchParallel ?? 1 }
|
|
37263
37530
|
);
|
|
37264
37531
|
const expanded = expandRowsForSubtableDml(parents, subtableCode);
|
|
37265
|
-
const targets = expanded.filter((r) => evalWhere(stmt.where, r.flat));
|
|
37532
|
+
const targets = expanded.filter((r) => evalWhere(stmt.where, r.flat, resolveFieldType));
|
|
37266
37533
|
if (options.confirm) {
|
|
37267
37534
|
const ok = await options.confirm(targets.length, "DELETE");
|
|
37268
37535
|
if (!ok) throw new OperationCancelledError("DELETE", targets.length);
|
|
@@ -37377,11 +37644,11 @@ function buildSubtableReorderPutParams(appId, parentId, revision, subtableCode,
|
|
|
37377
37644
|
]
|
|
37378
37645
|
};
|
|
37379
37646
|
}
|
|
37380
|
-
function evalAssignmentValueForSubtable(value, row) {
|
|
37647
|
+
function evalAssignmentValueForSubtable(value, row, resolveFieldType) {
|
|
37381
37648
|
if (value.type === "STRING") return value.value;
|
|
37382
37649
|
if (value.type === "NUMBER") return String(value.value);
|
|
37383
37650
|
if (value.type === "ARITH") return String(evalArithExpr(value, row));
|
|
37384
|
-
if (value.type === "CASE_VALUE") return evalCaseWhen(value.expr, row);
|
|
37651
|
+
if (value.type === "CASE_VALUE") return evalCaseWhen(value.expr, row, resolveFieldType);
|
|
37385
37652
|
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`);
|
|
37386
37653
|
}
|
|
37387
37654
|
function valueToString(value) {
|
|
@@ -37413,7 +37680,15 @@ function hasRidCondition(where) {
|
|
|
37413
37680
|
return false;
|
|
37414
37681
|
}
|
|
37415
37682
|
}
|
|
37416
|
-
async function executeReorder(stmt, client, options,
|
|
37683
|
+
async function executeReorder(stmt, client, options, cacheContext) {
|
|
37684
|
+
const typedInRefs = [];
|
|
37685
|
+
collectTypedInFieldRefs(stmt.where, typedInRefs);
|
|
37686
|
+
const resolveFieldType = await buildSubtableFieldTypeResolver(
|
|
37687
|
+
stmt.appId,
|
|
37688
|
+
typedInRefs,
|
|
37689
|
+
client,
|
|
37690
|
+
cacheContext
|
|
37691
|
+
);
|
|
37417
37692
|
const parents = await fetchAll(
|
|
37418
37693
|
client.getRecords,
|
|
37419
37694
|
stmt.appId,
|
|
@@ -37422,7 +37697,7 @@ async function executeReorder(stmt, client, options, _cacheContext) {
|
|
|
37422
37697
|
{ maxRecords: options.maxRecords ?? 1e4, parallel: options.fetchParallel ?? 1 }
|
|
37423
37698
|
);
|
|
37424
37699
|
const expanded = expandRowsForSubtableDml(parents, stmt.subtableCode);
|
|
37425
|
-
const targetParentIds = stmt.all ? new Set(parents.map((p) => String(p["$id"]?.value ?? "")).filter((id) => id !== "")) : new Set(expanded.filter((r) => stmt.where && evalWhere(stmt.where, r.flat)).map((r) => r.parentId));
|
|
37700
|
+
const targetParentIds = stmt.all ? new Set(parents.map((p) => String(p["$id"]?.value ?? "")).filter((id) => id !== "")) : new Set(expanded.filter((r) => stmt.where && evalWhere(stmt.where, r.flat, resolveFieldType)).map((r) => r.parentId));
|
|
37426
37701
|
if (options.confirm) {
|
|
37427
37702
|
const ok = await options.confirm(targetParentIds.size, "UPDATE");
|
|
37428
37703
|
if (!ok) throw new OperationCancelledError("UPDATE", targetParentIds.size);
|
|
@@ -37567,6 +37842,16 @@ async function resolveSubqueries(where, client, options, cacheContext, cteCache)
|
|
|
37567
37842
|
collectSubqueryTasks(where, client, options, cacheContext, tasks, cteCache);
|
|
37568
37843
|
await Promise.all(tasks);
|
|
37569
37844
|
}
|
|
37845
|
+
async function resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache) {
|
|
37846
|
+
const tasks = [];
|
|
37847
|
+
for (const column of stmt.columns) {
|
|
37848
|
+
if (column.type !== "CASE_COL") continue;
|
|
37849
|
+
for (const branch of column.expr.branches) {
|
|
37850
|
+
tasks.push(resolveSubqueries(branch.condition, client, options, cacheContext, cteCache));
|
|
37851
|
+
}
|
|
37852
|
+
}
|
|
37853
|
+
await Promise.all(tasks);
|
|
37854
|
+
}
|
|
37570
37855
|
function runSubquery(query, client, options, cacheContext, cteCache) {
|
|
37571
37856
|
if (cteCache !== void 0 && cteCache.size > 0) {
|
|
37572
37857
|
return executeQueryWithCte(query, client, options, cteCache, cacheContext);
|
|
@@ -37799,12 +38084,12 @@ function buildSelectPlan(stmt, label) {
|
|
|
37799
38084
|
const mainFields = selectToFetchAllFields(stmt, stmt.from);
|
|
37800
38085
|
const mainAliasStr = stmt.from.alias ? ` AS ${stmt.from.alias}` : "";
|
|
37801
38086
|
const mainPushDown = extractMainSafePushdown(stmt);
|
|
37802
|
-
const mainCandidate =
|
|
38087
|
+
const mainCandidate = extractMainTypedPushdownCandidate(stmt);
|
|
37803
38088
|
const mainQ = mainPushDown !== null ? whereToKintone(mainPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
|
|
37804
38089
|
lines.push(` app: APP${stmt.from.appId}${mainAliasStr} (${stmt.from.appId})`);
|
|
37805
38090
|
lines.push(` kintone query: ${mainQ}`);
|
|
37806
38091
|
if (mainCandidate !== null) {
|
|
37807
|
-
lines.push(` pushdown candidate: ${whereToKintone(mainCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u78BA\u8A8D\u5F85\u3061\uFF09`);
|
|
38092
|
+
lines.push(` pushdown candidate: ${whereToKintone(mainCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u30FB\u5B9F\u5728\u78BA\u8A8D\u5F85\u3061\uFF09`);
|
|
37808
38093
|
}
|
|
37809
38094
|
lines.push(` fields: ${mainFields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : mainFields.join(", ")}`);
|
|
37810
38095
|
for (const join of stmt.joins) {
|
|
@@ -37812,12 +38097,12 @@ function buildSelectPlan(stmt, label) {
|
|
|
37812
38097
|
const joinAliasStr = join.table.alias ? ` AS ${join.table.alias}` : "";
|
|
37813
38098
|
const joinType = join.type === "INNER" ? "JOIN" : `${join.type} JOIN`;
|
|
37814
38099
|
const joinPushDown = join.table.alias && !join.table.subtableCode && join.table.cteName === null && stmt.where ? extractSafePushdownLeaves(stmt.where, { tableAlias: join.table.alias }) : null;
|
|
37815
|
-
const joinCandidate = join.table.alias && !join.table.subtableCode && join.table.cteName === null && stmt.where ?
|
|
38100
|
+
const joinCandidate = join.table.alias && !join.table.subtableCode && join.table.cteName === null && stmt.where ? extractTypedPushdownCandidates(stmt.where, { tableAlias: join.table.alias }) : null;
|
|
37816
38101
|
const joinQ = joinPushDown !== null ? whereToKintone(joinPushDown) : "(\u5168\u4EF6\u53D6\u5F97)";
|
|
37817
38102
|
lines.push(` ${joinType}: APP${join.table.appId}${joinAliasStr} (${join.table.appId})`);
|
|
37818
38103
|
lines.push(` kintone query: ${joinQ}`);
|
|
37819
38104
|
if (joinCandidate !== null) {
|
|
37820
|
-
lines.push(` pushdown candidate: ${whereToKintone(joinCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u78BA\u8A8D\u5F85\u3061\uFF09`);
|
|
38105
|
+
lines.push(` pushdown candidate: ${whereToKintone(joinCandidate)}\uFF08\u5B9F\u884C\u6642\u306E\u578B\u30FB\u5B9F\u5728\u78BA\u8A8D\u5F85\u3061\uFF09`);
|
|
37821
38106
|
}
|
|
37822
38107
|
lines.push(` fields: ${joinFields.length === 0 ? "(\u5168\u30D5\u30A3\u30FC\u30EB\u30C9)" : joinFields.join(", ")}`);
|
|
37823
38108
|
}
|
|
@@ -38489,6 +38774,42 @@ function clampInt(v, min, max) {
|
|
|
38489
38774
|
return Math.max(min, Math.min(max, Math.trunc(v)));
|
|
38490
38775
|
}
|
|
38491
38776
|
|
|
38777
|
+
// src/core/formFieldInfo.ts
|
|
38778
|
+
function flattenFormFieldProperties(properties) {
|
|
38779
|
+
const out = [];
|
|
38780
|
+
for (const field of Object.values(properties)) {
|
|
38781
|
+
out.push({
|
|
38782
|
+
code: field.code,
|
|
38783
|
+
label: field.label,
|
|
38784
|
+
fieldType: field.type,
|
|
38785
|
+
optionOrder: toOptionOrderMap(field.options),
|
|
38786
|
+
sortKind: detectSortKind(field.type, field.format)
|
|
38787
|
+
});
|
|
38788
|
+
if (field.fields) out.push(...flattenFormFieldProperties(field.fields));
|
|
38789
|
+
}
|
|
38790
|
+
return out;
|
|
38791
|
+
}
|
|
38792
|
+
function toOptionOrderMap(options) {
|
|
38793
|
+
if (!options || typeof options !== "object") return void 0;
|
|
38794
|
+
const order = {};
|
|
38795
|
+
let hasAny = false;
|
|
38796
|
+
for (const [label, meta3] of Object.entries(options)) {
|
|
38797
|
+
const n = Number(meta3?.index);
|
|
38798
|
+
if (!Number.isFinite(n)) continue;
|
|
38799
|
+
order[label] = n;
|
|
38800
|
+
hasAny = true;
|
|
38801
|
+
}
|
|
38802
|
+
return hasAny ? order : void 0;
|
|
38803
|
+
}
|
|
38804
|
+
function detectSortKind(fieldType, calcFormat) {
|
|
38805
|
+
if (fieldType === "NUMBER" || fieldType === "RECORD_NUMBER") return "number";
|
|
38806
|
+
if (fieldType === "CALC") {
|
|
38807
|
+
if (calcFormat === "NUMBER" || calcFormat === "NUMBER_DIGIT") return "number";
|
|
38808
|
+
return "string";
|
|
38809
|
+
}
|
|
38810
|
+
return void 0;
|
|
38811
|
+
}
|
|
38812
|
+
|
|
38492
38813
|
// src/cli/nodeKintoneClient.ts
|
|
38493
38814
|
function createNodeKintoneClient(baseUrl, tokenResolver) {
|
|
38494
38815
|
const normalizedBaseUrl = baseUrl.replace(/\/+$/, "");
|
|
@@ -38667,36 +38988,10 @@ function createNodeKintoneClient(baseUrl, tokenResolver) {
|
|
|
38667
38988
|
{ method: "GET" },
|
|
38668
38989
|
appId
|
|
38669
38990
|
);
|
|
38670
|
-
return
|
|
38671
|
-
code: f.code,
|
|
38672
|
-
label: f.label,
|
|
38673
|
-
fieldType: f.type,
|
|
38674
|
-
optionOrder: toOptionOrderMap(f.options),
|
|
38675
|
-
sortKind: detectSortKind(f.type, f.format)
|
|
38676
|
-
}));
|
|
38991
|
+
return flattenFormFieldProperties(res.properties);
|
|
38677
38992
|
}
|
|
38678
38993
|
};
|
|
38679
38994
|
}
|
|
38680
|
-
function toOptionOrderMap(options) {
|
|
38681
|
-
if (!options || typeof options !== "object") return void 0;
|
|
38682
|
-
const order = {};
|
|
38683
|
-
let hasAny = false;
|
|
38684
|
-
for (const [label, meta3] of Object.entries(options)) {
|
|
38685
|
-
const n = Number(meta3?.index);
|
|
38686
|
-
if (!Number.isFinite(n)) continue;
|
|
38687
|
-
order[label] = n;
|
|
38688
|
-
hasAny = true;
|
|
38689
|
-
}
|
|
38690
|
-
return hasAny ? order : void 0;
|
|
38691
|
-
}
|
|
38692
|
-
function detectSortKind(fieldType, calcFormat) {
|
|
38693
|
-
if (fieldType === "NUMBER" || fieldType === "RECORD_NUMBER") return "number";
|
|
38694
|
-
if (fieldType === "CALC") {
|
|
38695
|
-
if (calcFormat === "NUMBER" || calcFormat === "NUMBER_DIGIT") return "number";
|
|
38696
|
-
return "string";
|
|
38697
|
-
}
|
|
38698
|
-
return void 0;
|
|
38699
|
-
}
|
|
38700
38995
|
|
|
38701
38996
|
// src/node/appProfiles.ts
|
|
38702
38997
|
function parseTokenMap(raw) {
|
|
@@ -40156,7 +40451,7 @@ Options:
|
|
|
40156
40451
|
-h, --help Show help
|
|
40157
40452
|
`);
|
|
40158
40453
|
}
|
|
40159
|
-
var SERVER_VERSION = true ? "2.
|
|
40454
|
+
var SERVER_VERSION = true ? "2.6.0" : "0.0.0-dev";
|
|
40160
40455
|
function createServer(args) {
|
|
40161
40456
|
const server = new McpServer({
|
|
40162
40457
|
name: "ksql-mcp",
|