@rex0220/kintone-sql-tools 3.28.0 → 3.30.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/README.md +8 -2
- package/dist-cli/ksql.js +239 -29
- package/dist-engine/batch.d.ts +13 -0
- package/dist-engine/errors.d.ts +5 -0
- package/dist-engine/index.cjs +10 -10
- package/dist-engine/index.d.ts +3 -2
- package/dist-engine/index.mjs +10 -10
- package/dist-engine/ksql-engine.umd.js +10 -10
- package/dist-engine/meta/bundle-baseline.json +10 -10
- package/dist-engine/meta/cjs.json +118 -26
- package/dist-engine/meta/esm.json +118 -25
- package/dist-engine/meta/umd.json +120 -28
- package/dist-engine/publicTypes.d.ts +98 -0
- package/dist-engine/query.d.ts +8 -0
- package/dist-mcp/ksql-mcp.js +254 -40
- package/dist-mcpb/ksql-mcp.mcpb +0 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -7,8 +7,14 @@ kintone アプリを SQL 風の構文で操作するツールセットです。
|
|
|
7
7
|
- MCP サーバー(AI クライアントから kintone を SQL 操作。Claude Desktop 用 MCPB 同梱)
|
|
8
8
|
- read-only エンジン・ライブラリ(ESM / CJS / UMD)
|
|
9
9
|
|
|
10
|
-
他の kintone プラグインやカスタマイズへ read-only kSQL エンジンを組み込む場合は、
|
|
11
|
-
[エンジン・ライブラリ利用ガイド](docs/ksql_engine_library.md)を参照してください。
|
|
10
|
+
他の kintone プラグインやカスタマイズへ read-only kSQL エンジンを組み込む場合は、
|
|
11
|
+
[エンジン・ライブラリ利用ガイド](docs/ksql_engine_library.md)を参照してください。
|
|
12
|
+
|
|
13
|
+
engine ライブラリでは、`runQuery()` が単文の `SELECT` / `WITH` / `UNION` /
|
|
14
|
+
`SHOW APPS` / `DESCRIBE` / 既存レコード `VALIDATE` を、`runBatch()` がそれらに加えて
|
|
15
|
+
`CREATE` / `DROP TEMP TABLE`、`SET` / `DECLARE`、`ASSERT`、`EXPLAIN` を実行します。
|
|
16
|
+
書き込み DML、DML `VALIDATE ONLY`、`IMPORT`、`APPLY` は対象外です。
|
|
17
|
+
生成 AI が MCP で作った SQL を library で実行する場合は、この API 別の境界を確認してください。
|
|
12
18
|
|
|
13
19
|
## 機能概要
|
|
14
20
|
|
package/dist-cli/ksql.js
CHANGED
|
@@ -5341,20 +5341,36 @@ function caseResultHasAggregate(result) {
|
|
|
5341
5341
|
if (result.type === "ARRAY" || result.type === "FIELD_REF" || result.type === "ARITH") return false;
|
|
5342
5342
|
return scalarValueHasAggregate(result);
|
|
5343
5343
|
}
|
|
5344
|
-
function
|
|
5344
|
+
function collectSelectFieldReferencesBySource(stmt, plainGroupByPlan) {
|
|
5345
|
+
const unqualified = /* @__PURE__ */ new Set();
|
|
5346
|
+
const states = collectRequiredFieldsByTable(stmt, plainGroupByPlan, {
|
|
5347
|
+
includeMaterialized: true,
|
|
5348
|
+
unqualified
|
|
5349
|
+
});
|
|
5350
|
+
return {
|
|
5351
|
+
bySource: new Map(
|
|
5352
|
+
[...states.entries()].map(([table, state]) => [table, new Set(state.fields)])
|
|
5353
|
+
),
|
|
5354
|
+
unqualified
|
|
5355
|
+
};
|
|
5356
|
+
}
|
|
5357
|
+
function collectRequiredFieldsByTable(stmt, plainGroupByPlan, sourceAware) {
|
|
5345
5358
|
const allTables = [stmt.from, ...stmt.joins.map((j) => j.table)];
|
|
5346
5359
|
const physicalTables = [stmt.from, ...stmt.joins.map((j) => j.table)].filter((t) => t.cteName === null);
|
|
5360
|
+
const targetTables = sourceAware ? allTables : physicalTables;
|
|
5347
5361
|
const states = /* @__PURE__ */ new Map();
|
|
5348
|
-
for (const table of
|
|
5362
|
+
for (const table of targetTables) {
|
|
5349
5363
|
states.set(table, { table, allFields: false, fields: /* @__PURE__ */ new Set() });
|
|
5350
5364
|
}
|
|
5351
5365
|
if (states.size === 0) return states;
|
|
5352
|
-
const
|
|
5353
|
-
const subtableTable =
|
|
5366
|
+
const firstTargetTable = targetTables[0] ?? null;
|
|
5367
|
+
const subtableTable = targetTables.find((t) => !!t.subtableCode) ?? null;
|
|
5354
5368
|
const aliasToTable = /* @__PURE__ */ new Map();
|
|
5355
|
-
for (const table of
|
|
5369
|
+
for (const table of targetTables) {
|
|
5356
5370
|
if (table.alias) aliasToTable.set(table.alias, table);
|
|
5357
|
-
if (
|
|
5371
|
+
if (table.cteName !== null) {
|
|
5372
|
+
aliasToTable.set(table.cteName, table);
|
|
5373
|
+
} else if (!table.subtableCode) {
|
|
5358
5374
|
aliasToTable.set(`APP${table.appId}`, table);
|
|
5359
5375
|
aliasToTable.set(`app${table.appId}`, table);
|
|
5360
5376
|
}
|
|
@@ -5366,11 +5382,11 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan) {
|
|
|
5366
5382
|
st.allFields = true;
|
|
5367
5383
|
st.fields.clear();
|
|
5368
5384
|
};
|
|
5369
|
-
const
|
|
5370
|
-
for (const t of
|
|
5385
|
+
const markAllTargetTables = () => {
|
|
5386
|
+
for (const t of targetTables) markAll(t);
|
|
5371
5387
|
};
|
|
5372
5388
|
const markAllSubtableTables = () => {
|
|
5373
|
-
for (const t of
|
|
5389
|
+
for (const t of targetTables) {
|
|
5374
5390
|
if (t.subtableCode) markAll(t);
|
|
5375
5391
|
}
|
|
5376
5392
|
};
|
|
@@ -5400,7 +5416,7 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan) {
|
|
|
5400
5416
|
if (rawName.endsWith(".*")) {
|
|
5401
5417
|
const qualifier = rawName.slice(0, -2);
|
|
5402
5418
|
if (!qualifier) {
|
|
5403
|
-
|
|
5419
|
+
markAllTargetTables();
|
|
5404
5420
|
return;
|
|
5405
5421
|
}
|
|
5406
5422
|
if (qualifier === "_p") {
|
|
@@ -5417,7 +5433,7 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan) {
|
|
|
5417
5433
|
if (phase === "groupBy" && groupResolution !== void 0) {
|
|
5418
5434
|
if (groupResolution.kind === "PHYSICAL") {
|
|
5419
5435
|
const source = allTables[groupResolution.sourceIndex];
|
|
5420
|
-
if (source
|
|
5436
|
+
if (source && (sourceAware || source.cteName === null)) {
|
|
5421
5437
|
addFieldToTable(source, groupResolution.fieldCode);
|
|
5422
5438
|
}
|
|
5423
5439
|
}
|
|
@@ -5442,8 +5458,13 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan) {
|
|
|
5442
5458
|
addFieldToTable(target, field);
|
|
5443
5459
|
return;
|
|
5444
5460
|
}
|
|
5461
|
+
if (sourceAware) return;
|
|
5462
|
+
}
|
|
5463
|
+
if (sourceAware) {
|
|
5464
|
+
sourceAware.unqualified.add(rawName);
|
|
5465
|
+
} else if (firstTargetTable) {
|
|
5466
|
+
addFieldToTable(firstTargetTable, rawName);
|
|
5445
5467
|
}
|
|
5446
|
-
if (firstPhysicalTable) addFieldToTable(firstPhysicalTable, rawName);
|
|
5447
5468
|
};
|
|
5448
5469
|
const addFieldRef = (field, tableAlias, phase = "select") => {
|
|
5449
5470
|
if (tableAlias) {
|
|
@@ -5456,6 +5477,7 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan) {
|
|
|
5456
5477
|
addFieldToTable(target, field);
|
|
5457
5478
|
return;
|
|
5458
5479
|
}
|
|
5480
|
+
if (sourceAware) return;
|
|
5459
5481
|
}
|
|
5460
5482
|
addFieldName(field, phase);
|
|
5461
5483
|
};
|
|
@@ -5611,7 +5633,7 @@ function collectRequiredFieldsByTable(stmt, plainGroupByPlan) {
|
|
|
5611
5633
|
for (const col of stmt.columns) {
|
|
5612
5634
|
switch (col.type) {
|
|
5613
5635
|
case "WILDCARD":
|
|
5614
|
-
|
|
5636
|
+
markAllTargetTables();
|
|
5615
5637
|
break;
|
|
5616
5638
|
case "PARENT_WILDCARD":
|
|
5617
5639
|
markAllSubtableTables();
|
|
@@ -9490,6 +9512,20 @@ function renderValidationValue(value) {
|
|
|
9490
9512
|
}
|
|
9491
9513
|
|
|
9492
9514
|
// src/core/existingRecordValidation.ts
|
|
9515
|
+
var VALIDATE_CONSTRAINT_CATEGORIES = [
|
|
9516
|
+
"required",
|
|
9517
|
+
"length",
|
|
9518
|
+
"range",
|
|
9519
|
+
"choice"
|
|
9520
|
+
];
|
|
9521
|
+
function getAuditableConstraintCategories(field) {
|
|
9522
|
+
return [
|
|
9523
|
+
...field.required === true ? ["required"] : [],
|
|
9524
|
+
...field.minLength !== void 0 || field.maxLength !== void 0 ? ["length"] : [],
|
|
9525
|
+
...field.minValue !== void 0 || field.maxValue !== void 0 ? ["range"] : [],
|
|
9526
|
+
...field.optionOrder !== void 0 ? ["choice"] : []
|
|
9527
|
+
];
|
|
9528
|
+
}
|
|
9493
9529
|
function buildValidationFieldMetadataIndex(fieldInfos) {
|
|
9494
9530
|
const topLevel = fieldInfos.filter((field) => !field.inSubtable);
|
|
9495
9531
|
const childrenByTable = /* @__PURE__ */ new Map();
|
|
@@ -9506,7 +9542,7 @@ function buildValidationFieldMetadataIndex(fieldInfos) {
|
|
|
9506
9542
|
};
|
|
9507
9543
|
}
|
|
9508
9544
|
function hasAuditableConstraint(field) {
|
|
9509
|
-
return field.
|
|
9545
|
+
return getAuditableConstraintCategories(field).length > 0;
|
|
9510
9546
|
}
|
|
9511
9547
|
function isExistingValidationAuditable(field) {
|
|
9512
9548
|
return field.fieldType === "NUMBER" || hasAuditableConstraint(field);
|
|
@@ -15629,6 +15665,13 @@ async function executeExistingRecordValidationCore(stmt, client, options, cacheC
|
|
|
15629
15665
|
const infoByCode = new Map(fieldInfos.filter((field) => !field.inSubtable).map((field) => [field.code, field]));
|
|
15630
15666
|
const childCodes = new Set(fieldInfos.filter((field) => field.inSubtable).map((field) => field.code));
|
|
15631
15667
|
const targets = resolveExistingValidationTargets(stmt, fieldInfos);
|
|
15668
|
+
const presentConstraintCategories = new Set(
|
|
15669
|
+
targets.flatMap((target) => getAuditableConstraintCategories(target.field))
|
|
15670
|
+
);
|
|
15671
|
+
const constraintMetadata = {
|
|
15672
|
+
present: VALIDATE_CONSTRAINT_CATEGORIES.filter((category) => presentConstraintCategories.has(category)),
|
|
15673
|
+
absent: VALIDATE_CONSTRAINT_CATEGORIES.filter((category) => !presentConstraintCategories.has(category))
|
|
15674
|
+
};
|
|
15632
15675
|
const checkGroups = stmt.checkGroups ?? [];
|
|
15633
15676
|
const checkRefs2 = collectCheckFieldRefs(checkGroups);
|
|
15634
15677
|
for (const ref of checkRefs2) {
|
|
@@ -15785,7 +15828,11 @@ async function executeExistingRecordValidationCore(stmt, client, options, cacheC
|
|
|
15785
15828
|
columns: [...columns],
|
|
15786
15829
|
rows,
|
|
15787
15830
|
rowCount: rows.length,
|
|
15788
|
-
validateStats: {
|
|
15831
|
+
validateStats: {
|
|
15832
|
+
errorRecords: errorRecordIds.size,
|
|
15833
|
+
errorCount,
|
|
15834
|
+
constraintMetadata
|
|
15835
|
+
}
|
|
15789
15836
|
};
|
|
15790
15837
|
materializedMetaBySelectResult.set(result, existingValidationColumnMeta(stmt.summary === true));
|
|
15791
15838
|
return result;
|
|
@@ -16158,21 +16205,28 @@ async function runWithDeadline(work, remainingMs, onTimeout) {
|
|
|
16158
16205
|
}
|
|
16159
16206
|
}
|
|
16160
16207
|
function toBatchStatementError(e) {
|
|
16208
|
+
let error;
|
|
16161
16209
|
if (e instanceof ApplyWritePartialFailureError) {
|
|
16162
|
-
|
|
16163
|
-
}
|
|
16164
|
-
if (e instanceof Error) {
|
|
16210
|
+
error = { code: e.name, message: e.message, partialSuccess: e.partialSuccess };
|
|
16211
|
+
} else if (e instanceof Error) {
|
|
16165
16212
|
const name = e.name !== "Error" ? e.name : null;
|
|
16166
|
-
|
|
16167
|
-
}
|
|
16168
|
-
if (e !== null && typeof e === "object") {
|
|
16213
|
+
error = { code: name ?? codeFromMessagePrefix(e.message), message: e.message };
|
|
16214
|
+
} else if (e !== null && typeof e === "object") {
|
|
16169
16215
|
const obj = e;
|
|
16170
|
-
const
|
|
16171
|
-
const code = typeof obj.code === "string" && obj.code.length > 0 ? obj.code : codeFromMessagePrefix(
|
|
16172
|
-
|
|
16216
|
+
const message = typeof obj.message === "string" && obj.message.length > 0 ? obj.message : safeJsonStringify(e);
|
|
16217
|
+
const code = typeof obj.code === "string" && obj.code.length > 0 ? obj.code : codeFromMessagePrefix(message);
|
|
16218
|
+
error = { code, message };
|
|
16219
|
+
} else {
|
|
16220
|
+
const message = String(e);
|
|
16221
|
+
error = { code: codeFromMessagePrefix(message), message };
|
|
16173
16222
|
}
|
|
16174
|
-
|
|
16175
|
-
|
|
16223
|
+
Object.defineProperty(error, "cause", {
|
|
16224
|
+
value: e,
|
|
16225
|
+
enumerable: false,
|
|
16226
|
+
configurable: false,
|
|
16227
|
+
writable: false
|
|
16228
|
+
});
|
|
16229
|
+
return error;
|
|
16176
16230
|
}
|
|
16177
16231
|
function codeFromMessagePrefix(message) {
|
|
16178
16232
|
return message.match(/^([A-Za-z]+Error):/)?.[1] ?? "Error";
|
|
@@ -17086,6 +17140,159 @@ async function validateSelectFieldCodes(stmt, mode, client, cacheContext) {
|
|
|
17086
17140
|
}
|
|
17087
17141
|
}
|
|
17088
17142
|
}
|
|
17143
|
+
function b86SourceLabel(table) {
|
|
17144
|
+
return table.cteName ?? `APP${table.appId}`;
|
|
17145
|
+
}
|
|
17146
|
+
function b86SourceAliases(table) {
|
|
17147
|
+
if (table.alias) return [table.alias];
|
|
17148
|
+
if (table.cteName !== null) return [table.cteName];
|
|
17149
|
+
return [`APP${table.appId}`, `app${table.appId}`];
|
|
17150
|
+
}
|
|
17151
|
+
function b86PhysicalFieldExists(schema, field) {
|
|
17152
|
+
return isSystemLikeFieldCode(field) || schema.validCodes.has(field);
|
|
17153
|
+
}
|
|
17154
|
+
function b86FieldExists(schema, field) {
|
|
17155
|
+
if (schema.table.cteName !== null) return schema.validCodes.has(field);
|
|
17156
|
+
return b86PhysicalFieldExists(schema, field);
|
|
17157
|
+
}
|
|
17158
|
+
function collectB86Subqueries(stmt) {
|
|
17159
|
+
const queries = [];
|
|
17160
|
+
const visitWhere = (where) => {
|
|
17161
|
+
if (where === null) return;
|
|
17162
|
+
switch (where.type) {
|
|
17163
|
+
case "BINARY":
|
|
17164
|
+
if (where.right.type === "SUBQUERY_IN_LIST" || where.right.type === "SCALAR_SUBQUERY") {
|
|
17165
|
+
queries.push(where.right.query);
|
|
17166
|
+
}
|
|
17167
|
+
return;
|
|
17168
|
+
case "EXISTS":
|
|
17169
|
+
queries.push(where.query);
|
|
17170
|
+
return;
|
|
17171
|
+
case "LOGICAL":
|
|
17172
|
+
visitWhere(where.left);
|
|
17173
|
+
visitWhere(where.right);
|
|
17174
|
+
return;
|
|
17175
|
+
case "NOT":
|
|
17176
|
+
case "GROUP":
|
|
17177
|
+
visitWhere(where.expr);
|
|
17178
|
+
return;
|
|
17179
|
+
case "NULL_CHECK":
|
|
17180
|
+
case "BOOLEAN":
|
|
17181
|
+
return;
|
|
17182
|
+
}
|
|
17183
|
+
};
|
|
17184
|
+
visitWhere(stmt.where);
|
|
17185
|
+
visitWhere(stmt.having);
|
|
17186
|
+
for (const column of stmt.columns) {
|
|
17187
|
+
if (column.type === "SCALAR_SUBQUERY_COL") {
|
|
17188
|
+
queries.push(column.query);
|
|
17189
|
+
} else if (column.type === "CASE_COL") {
|
|
17190
|
+
for (const branch of column.expr.branches) visitWhere(branch.condition);
|
|
17191
|
+
}
|
|
17192
|
+
}
|
|
17193
|
+
return queries;
|
|
17194
|
+
}
|
|
17195
|
+
async function validateB86SelectFieldCodes(stmt, client, cteCache, cacheContext) {
|
|
17196
|
+
const tables = [stmt.from, ...stmt.joins.map((join2) => join2.table)];
|
|
17197
|
+
const materializedByTable = /* @__PURE__ */ new Map();
|
|
17198
|
+
const effectiveAliases = /* @__PURE__ */ new Set();
|
|
17199
|
+
for (const table of tables) {
|
|
17200
|
+
const alias = effectiveTableAlias(table);
|
|
17201
|
+
if (alias === null) continue;
|
|
17202
|
+
if (effectiveAliases.has(alias)) {
|
|
17203
|
+
throw new Error(`ArgumentError: effective alias ${alias} is used by multiple tables.`);
|
|
17204
|
+
}
|
|
17205
|
+
effectiveAliases.add(alias);
|
|
17206
|
+
}
|
|
17207
|
+
for (const table of tables) {
|
|
17208
|
+
if (table.cteName === null || table.cteName === NO_FROM_CTE_NAME) continue;
|
|
17209
|
+
const materialized = cteCache.get(table.cteName);
|
|
17210
|
+
if (!materialized) {
|
|
17211
|
+
throw new Error(`ArgumentError: materialized source ${table.cteName} is not available.`);
|
|
17212
|
+
}
|
|
17213
|
+
if (materialized.rows.length > 0 && materialized.columns.length === 0) {
|
|
17214
|
+
throw new Error(
|
|
17215
|
+
`InternalError: materialized source ${table.cteName} has rows but no column schema.`
|
|
17216
|
+
);
|
|
17217
|
+
}
|
|
17218
|
+
if (stmt.joins.length > 0 && materialized.rows.length === 0 && materialized.columns.length === 0) {
|
|
17219
|
+
throw new Error(
|
|
17220
|
+
`ArgumentError: column schema is unavailable for materialized JOIN source ${table.cteName}.`
|
|
17221
|
+
);
|
|
17222
|
+
}
|
|
17223
|
+
materializedByTable.set(table, materialized);
|
|
17224
|
+
}
|
|
17225
|
+
const schemas = /* @__PURE__ */ new Map();
|
|
17226
|
+
await Promise.all(tables.map(async (table) => {
|
|
17227
|
+
const materialized = materializedByTable.get(table);
|
|
17228
|
+
if (materialized) {
|
|
17229
|
+
schemas.set(table, {
|
|
17230
|
+
table,
|
|
17231
|
+
label: b86SourceLabel(table),
|
|
17232
|
+
validCodes: new Set(materialized.columns),
|
|
17233
|
+
authoritative: true,
|
|
17234
|
+
schemaUnavailable: materialized.rows.length === 0 && materialized.columns.length === 0
|
|
17235
|
+
});
|
|
17236
|
+
return;
|
|
17237
|
+
}
|
|
17238
|
+
if (table.cteName === NO_FROM_CTE_NAME) return;
|
|
17239
|
+
const defs = await getFieldsCached(table.appId, client, cacheContext);
|
|
17240
|
+
schemas.set(table, {
|
|
17241
|
+
table,
|
|
17242
|
+
label: b86SourceLabel(table),
|
|
17243
|
+
validCodes: new Set(defs.map((def) => def.code)),
|
|
17244
|
+
authoritative: defs.length > 0,
|
|
17245
|
+
schemaUnavailable: false
|
|
17246
|
+
});
|
|
17247
|
+
}));
|
|
17248
|
+
const sourceByAlias = /* @__PURE__ */ new Map();
|
|
17249
|
+
for (const schema of schemas.values()) {
|
|
17250
|
+
for (const alias of b86SourceAliases(schema.table)) sourceByAlias.set(alias, schema);
|
|
17251
|
+
}
|
|
17252
|
+
for (const join2 of stmt.joins) {
|
|
17253
|
+
for (const ref of [join2.on.left, join2.on.right]) {
|
|
17254
|
+
if (!ref.tableAlias) continue;
|
|
17255
|
+
const schema = sourceByAlias.get(ref.tableAlias);
|
|
17256
|
+
if (schema && schema.table.cteName !== null && !schema.schemaUnavailable && !b86FieldExists(schema, ref.field)) {
|
|
17257
|
+
throw new Error(
|
|
17258
|
+
`ArgumentError: JOIN key ${ref.tableAlias}.${ref.field} is not available in the materialized table.`
|
|
17259
|
+
);
|
|
17260
|
+
}
|
|
17261
|
+
}
|
|
17262
|
+
}
|
|
17263
|
+
const references = collectSelectFieldReferencesBySource(stmt);
|
|
17264
|
+
for (const [table, fields] of references.bySource) {
|
|
17265
|
+
const schema = schemas.get(table);
|
|
17266
|
+
if (!schema || schema.schemaUnavailable || !schema.authoritative) continue;
|
|
17267
|
+
const unknown = [...fields].filter((field) => !b86FieldExists(schema, field));
|
|
17268
|
+
if (unknown.length > 0) {
|
|
17269
|
+
throw new Error(
|
|
17270
|
+
`ArgumentError: unknown field code(s): ${unknown.join(", ")} (${schema.label})`
|
|
17271
|
+
);
|
|
17272
|
+
}
|
|
17273
|
+
}
|
|
17274
|
+
for (const field of references.unqualified) {
|
|
17275
|
+
const candidates = [...schemas.values()].filter((schema) => !schema.schemaUnavailable);
|
|
17276
|
+
if (candidates.some((schema) => b86FieldExists(schema, field))) continue;
|
|
17277
|
+
if ([...schemas.values()].some((schema) => schema.schemaUnavailable)) continue;
|
|
17278
|
+
if (candidates.some((schema) => schema.table.cteName === null && !schema.authoritative)) continue;
|
|
17279
|
+
const labels = candidates.map((schema) => schema.label).join(", ");
|
|
17280
|
+
throw new Error(`ArgumentError: unknown field code(s): ${field} (${labels})`);
|
|
17281
|
+
}
|
|
17282
|
+
}
|
|
17283
|
+
async function preflightB86QueryWithCte(query, client, cteCache, cacheContext, seen = /* @__PURE__ */ new Set()) {
|
|
17284
|
+
if (seen.has(query)) return;
|
|
17285
|
+
seen.add(query);
|
|
17286
|
+
if (query.type === "UNION") {
|
|
17287
|
+
await preflightB86QueryWithCte(query.left, client, cteCache, cacheContext, seen);
|
|
17288
|
+
await preflightB86QueryWithCte(query.right, client, cteCache, cacheContext, seen);
|
|
17289
|
+
return;
|
|
17290
|
+
}
|
|
17291
|
+
await validateB86SelectFieldCodes(query, client, cteCache, cacheContext);
|
|
17292
|
+
for (const subquery of collectB86Subqueries(query)) {
|
|
17293
|
+
await preflightB86QueryWithCte(subquery, client, cteCache, cacheContext, seen);
|
|
17294
|
+
}
|
|
17295
|
+
}
|
|
17089
17296
|
function extractMainTypedPushdownCandidate(stmt) {
|
|
17090
17297
|
if (stmt.where === null || stmt.from.subtableCode || stmt.from.cteName !== null) return null;
|
|
17091
17298
|
if (stmt.joins.length === 0) {
|
|
@@ -17947,11 +18154,14 @@ async function executeWith(stmt, client, options, cacheContext, seed, captureCol
|
|
|
17947
18154
|
}
|
|
17948
18155
|
return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext, captureColumnMeta);
|
|
17949
18156
|
}
|
|
17950
|
-
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false) {
|
|
18157
|
+
async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false, b86PreflightComplete = false) {
|
|
18158
|
+
if (!b86PreflightComplete) {
|
|
18159
|
+
await preflightB86QueryWithCte(query, client, cteCache, cacheContext);
|
|
18160
|
+
}
|
|
17951
18161
|
if (query.type === "UNION") {
|
|
17952
18162
|
const [leftResult, rightResult] = await Promise.all([
|
|
17953
|
-
executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta),
|
|
17954
|
-
executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta)
|
|
18163
|
+
executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta, true),
|
|
18164
|
+
executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta, true)
|
|
17955
18165
|
]);
|
|
17956
18166
|
const leftCols = leftResult.columns;
|
|
17957
18167
|
const rightCols = rightResult.columns;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BatchResult, RunBatchOptions } from "./publicTypes";
|
|
2
|
+
/**
|
|
3
|
+
* Executes a read-only multi-statement batch.
|
|
4
|
+
*
|
|
5
|
+
* In addition to the row-returning statements accepted by runQuery, this API
|
|
6
|
+
* accepts CREATE/DROP TEMP TABLE, SET, DECLARE, ASSERT, and EXPLAIN. IMPORT,
|
|
7
|
+
* APPLY, DML VALIDATE ONLY, and writing DML remain outside the library boundary.
|
|
8
|
+
*
|
|
9
|
+
* If any statement fails, this function throws KsqlEngineError without
|
|
10
|
+
* returning partial results. statementIndex and statementType identify the
|
|
11
|
+
* failed statement.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runBatch(sql: string, options: RunBatchOptions): Promise<BatchResult>;
|
package/dist-engine/errors.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export declare class KsqlEngineError extends Error {
|
|
2
2
|
readonly code: "PARSE_ERROR" | "READ_ONLY_VIOLATION" | "SEARCH_ABORTED" | "FETCH_LIMIT_EXCEEDED" | "CLIENT_ERROR" | "EXECUTION_ERROR";
|
|
3
3
|
readonly cause?: unknown;
|
|
4
|
+
/** Zero-based index of the failed statement when raised by runBatch. */
|
|
5
|
+
readonly statementIndex?: number;
|
|
6
|
+
/** Parser statement type of the failed statement when raised by runBatch. */
|
|
7
|
+
readonly statementType?: string;
|
|
4
8
|
constructor(code: KsqlEngineError["code"], message: string, cause?: unknown);
|
|
5
9
|
}
|
|
10
|
+
export declare function withStatementDiagnostic(error: KsqlEngineError, statementIndex: number, statementType: string): KsqlEngineError;
|
|
6
11
|
export declare function readOnlyViolation(message: string): KsqlEngineError;
|
|
7
12
|
export declare function parseError(message: string, cause?: unknown): KsqlEngineError;
|
|
8
13
|
export declare function searchAborted(): KsqlEngineError;
|