@rex0220/kintone-sql-tools 3.70.0 → 3.71.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 CHANGED
@@ -267,7 +267,7 @@ npm パッケージは 2 つのサブパスを **semver 対象の公開 API**
267
267
  | サブパス | 用途 | 主な export |
268
268
  |---|---|---|
269
269
  | `@rex0220/kintone-sql-tools/engine` | **read-only** のクエリ実行(ダッシュボード等)。書込 API は構造的に遮断 | `runQuery` / `runBatch` / `explainQuery` / `createReadonlyKintoneClient` / `KsqlEngineError` / `version` |
270
- | `@rex0220/kintone-sql-tools/flow` | **Flow dialect 1**(→ [言語リファレンス §27](docs/ksql_language_reference.md))のスクリプト解析・検証・**文単位実行**(バッチランナー向け・書込可能) | `parseScript` / `validateScript` / `explainScript`(`asOf`/`timezone` 注入可) / `createExecutionContext`(`onChunkWritten` 書込チャンク通知) / `executeStatement` / `disposeExecutionContext` / `createKintoneClient` / `isDmlResult`(`FlowDmlResult` 型ガード) / `version` |
270
+ | `@rex0220/kintone-sql-tools/flow` | **Flow dialect 1**(→ [言語リファレンス §27](docs/ksql_language_reference.md))のスクリプト解析・検証・**文単位実行**(バッチランナー向け・書込可能) | `parseScript` / `validateScript` / `explainScript`(`asOf`/`timezone` 注入可) / `createExecutionContext`(`onChunkWritten` 書込チャンク通知) / `executeStatement` / `previewStatement`(dry-run 差分プレビュー・書込 0 回) / `disposeExecutionContext` / `createKintoneClient` / `isDmlResult`(`FlowDmlResult` 型ガード) / `version` |
271
271
 
272
272
  `/flow` の典型的な使い方(1 文ずつ実行して結果で継続判断する):
273
273
 
package/dist-cli/ksql.js CHANGED
@@ -22791,11 +22791,16 @@ function lookupUpsertTarget(index, keyParts) {
22791
22791
  if (!index.numericKey.some(Boolean)) return void 0;
22792
22792
  return index.normalized.get(upsertNormalizedKey(keyParts, index.numericKey));
22793
22793
  }
22794
- async function resolveUpsertTargets(appId, keyFields, rowKeyValues, client, options, fieldTypes) {
22794
+ async function resolveUpsertTargets(appId, keyFields, rowKeyValues, client, options, fieldTypes, previewFields) {
22795
22795
  const maxRecords = options.maxRecords ?? 1e4;
22796
22796
  const parallel = options.fetchParallel ?? 1;
22797
22797
  const numericKey = keyFields.map((f) => fieldTypes.get(f) === "NUMBER");
22798
- const index = { raw: /* @__PURE__ */ new Map(), normalized: /* @__PURE__ */ new Map(), numericKey };
22798
+ const index = {
22799
+ raw: /* @__PURE__ */ new Map(),
22800
+ normalized: /* @__PURE__ */ new Map(),
22801
+ numericKey,
22802
+ ...previewFields ? { snapshots: /* @__PURE__ */ new Map() } : {}
22803
+ };
22799
22804
  const setMax = (map, key, id) => {
22800
22805
  const cur = map.get(key);
22801
22806
  if (cur === void 0 || id > cur) map.set(key, id);
@@ -22816,20 +22821,26 @@ async function resolveUpsertTargets(appId, keyFields, rowKeyValues, client, opti
22816
22821
  if (parts.some((p) => p === "")) perRowKeys.push(parts);
22817
22822
  else batchFirstKeys.add(parts[0]);
22818
22823
  }
22819
- const fields = ["$id", ...keyFields];
22824
+ const fields = previewFields ? [.../* @__PURE__ */ new Set(["$id", ...keyFields, ...previewFields])] : ["$id", ...keyFields];
22820
22825
  for (const chunk3 of splitChunks([...batchFirstKeys], UPSERT_IN_CHUNK_SIZE)) {
22821
22826
  const query = `${keyFields[0]} in (${chunk3.map(sqlQuote).join(",")})`;
22822
22827
  const records = await fetchAll(client.getRecords, appId, query, fields, { maxRecords, parallel });
22823
22828
  for (const rec of records) {
22824
22829
  const id = Number(rec["$id"]?.value);
22825
22830
  if (!Number.isFinite(id)) continue;
22831
+ index.snapshots?.set(id, rec);
22826
22832
  addRecordToIndex(keyFields.map((f) => toScalarText(rec[f]?.value)), id);
22827
22833
  }
22828
22834
  }
22829
22835
  for (const parts of perRowKeys) {
22830
22836
  const query = keyFields.map((f, i) => `${f} = ${sqlQuote(parts[i])}`).join(" and ");
22831
- const existing = await fetchAll(client.getRecords, appId, query, ["$id"], { maxRecords, parallel });
22837
+ const perRowFields = previewFields ? [.../* @__PURE__ */ new Set(["$id", ...previewFields])] : ["$id"];
22838
+ const existing = await fetchAll(client.getRecords, appId, query, perRowFields, { maxRecords, parallel });
22832
22839
  if (existing.length === 0) continue;
22840
+ for (const rec of existing) {
22841
+ const id = Number(rec["$id"]?.value);
22842
+ if (Number.isFinite(id)) index.snapshots?.set(id, rec);
22843
+ }
22833
22844
  addRecordToIndex(parts, maxRecordId(existing));
22834
22845
  }
22835
22846
  return index;