@rex0220/kintone-sql-tools 3.31.0 → 3.32.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.
@@ -1,11 +1,11 @@
1
1
  {
2
- "generatedAt": "2026-07-28T06:21:20.309Z",
2
+ "generatedAt": "2026-07-28T12:26:58.193Z",
3
3
  "baseline": "B66 Phase1 initial measured values; no arbitrary size ceiling",
4
4
  "bundles": {
5
5
  "index.cjs": {
6
6
  "inputCount": 97,
7
- "minifiedBytes": 536649,
8
- "gzipBytes": 146374,
7
+ "minifiedBytes": 538854,
8
+ "gzipBytes": 147160,
9
9
  "forbidden": {
10
10
  "mcp-instructions": [],
11
11
  "src-mcp": [],
@@ -24,8 +24,8 @@
24
24
  },
25
25
  "index.mjs": {
26
26
  "inputCount": 97,
27
- "minifiedBytes": 536104,
28
- "gzipBytes": 146091,
27
+ "minifiedBytes": 538309,
28
+ "gzipBytes": 146871,
29
29
  "forbidden": {
30
30
  "mcp-instructions": [],
31
31
  "src-mcp": [],
@@ -44,8 +44,8 @@
44
44
  },
45
45
  "ksql-engine.umd.js": {
46
46
  "inputCount": 99,
47
- "minifiedBytes": 537128,
48
- "gzipBytes": 146426,
47
+ "minifiedBytes": 539333,
48
+ "gzipBytes": 147231,
49
49
  "forbidden": {
50
50
  "mcp-instructions": [],
51
51
  "src-mcp": [],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "inputs": {
3
3
  "src/api/fetchAll.ts": {
4
- "bytes": 12389,
4
+ "bytes": 12571,
5
5
  "imports": [],
6
6
  "format": "esm"
7
7
  },
@@ -886,7 +886,7 @@
886
886
  "format": "esm"
887
887
  },
888
888
  "src/core/emptyWildcardSchema.ts": {
889
- "bytes": 2525,
889
+ "bytes": 3248,
890
890
  "imports": [],
891
891
  "format": "esm"
892
892
  },
@@ -1166,7 +1166,7 @@
1166
1166
  "format": "esm"
1167
1167
  },
1168
1168
  "src/execute.ts": {
1169
- "bytes": 466368,
1169
+ "bytes": 471132,
1170
1170
  "imports": [
1171
1171
  {
1172
1172
  "path": "src/lexer/lexer.ts",
@@ -1575,7 +1575,7 @@
1575
1575
  "format": "esm"
1576
1576
  },
1577
1577
  "src/engine-library/browserClient.ts": {
1578
- "bytes": 11329,
1578
+ "bytes": 11422,
1579
1579
  "imports": [
1580
1580
  {
1581
1581
  "path": "src/api/cursorLeaseManager.ts",
@@ -1643,7 +1643,7 @@
1643
1643
  "format": "esm"
1644
1644
  },
1645
1645
  "src/engine-library/resultMapping.ts": {
1646
- "bytes": 1867,
1646
+ "bytes": 2033,
1647
1647
  "imports": [
1648
1648
  {
1649
1649
  "path": "src/execute.ts",
@@ -1886,7 +1886,7 @@
1886
1886
  "bytesInOutput": 5175
1887
1887
  },
1888
1888
  "src/core/batch.ts": {
1889
- "bytesInOutput": 5518
1889
+ "bytesInOutput": 5499
1890
1890
  },
1891
1891
  "src/lexer/tokens.ts": {
1892
1892
  "bytesInOutput": 2262
@@ -2003,7 +2003,7 @@
2003
2003
  "bytesInOutput": 2656
2004
2004
  },
2005
2005
  "src/core/emptyWildcardSchema.ts": {
2006
- "bytesInOutput": 1068
2006
+ "bytesInOutput": 1223
2007
2007
  },
2008
2008
  "src/engine/process.ts": {
2009
2009
  "bytesInOutput": 20100
@@ -2066,10 +2066,10 @@
2066
2066
  "bytesInOutput": 412
2067
2067
  },
2068
2068
  "src/execute.ts": {
2069
- "bytesInOutput": 182489
2069
+ "bytesInOutput": 184454
2070
2070
  },
2071
2071
  "src/engine-library/errors.ts": {
2072
- "bytesInOutput": 1441
2072
+ "bytesInOutput": 1440
2073
2073
  },
2074
2074
  "src/api/cursorLeaseManager.ts": {
2075
2075
  "bytesInOutput": 1777
@@ -2087,7 +2087,7 @@
2087
2087
  "bytesInOutput": 102
2088
2088
  },
2089
2089
  "src/engine-library/browserClient.ts": {
2090
- "bytesInOutput": 4301
2090
+ "bytesInOutput": 4310
2091
2091
  },
2092
2092
  "src/engine-library/readonlyClient.ts": {
2093
2093
  "bytesInOutput": 1111
@@ -2099,7 +2099,7 @@
2099
2099
  "bytesInOutput": 2212
2100
2100
  },
2101
2101
  "src/engine-library/resultMapping.ts": {
2102
- "bytesInOutput": 777
2102
+ "bytesInOutput": 873
2103
2103
  },
2104
2104
  "src/core/sql.ts": {
2105
2105
  "bytesInOutput": 186
@@ -2117,7 +2117,7 @@
2117
2117
  "bytesInOutput": 950
2118
2118
  }
2119
2119
  },
2120
- "bytes": 536649
2120
+ "bytes": 538854
2121
2121
  }
2122
2122
  }
2123
2123
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "inputs": {
3
3
  "src/api/fetchAll.ts": {
4
- "bytes": 12389,
4
+ "bytes": 12571,
5
5
  "imports": [],
6
6
  "format": "esm"
7
7
  },
@@ -886,7 +886,7 @@
886
886
  "format": "esm"
887
887
  },
888
888
  "src/core/emptyWildcardSchema.ts": {
889
- "bytes": 2525,
889
+ "bytes": 3248,
890
890
  "imports": [],
891
891
  "format": "esm"
892
892
  },
@@ -1166,7 +1166,7 @@
1166
1166
  "format": "esm"
1167
1167
  },
1168
1168
  "src/execute.ts": {
1169
- "bytes": 466368,
1169
+ "bytes": 471132,
1170
1170
  "imports": [
1171
1171
  {
1172
1172
  "path": "src/lexer/lexer.ts",
@@ -1575,7 +1575,7 @@
1575
1575
  "format": "esm"
1576
1576
  },
1577
1577
  "src/engine-library/browserClient.ts": {
1578
- "bytes": 11329,
1578
+ "bytes": 11422,
1579
1579
  "imports": [
1580
1580
  {
1581
1581
  "path": "src/api/cursorLeaseManager.ts",
@@ -1643,7 +1643,7 @@
1643
1643
  "format": "esm"
1644
1644
  },
1645
1645
  "src/engine-library/resultMapping.ts": {
1646
- "bytes": 1867,
1646
+ "bytes": 2033,
1647
1647
  "imports": [
1648
1648
  {
1649
1649
  "path": "src/execute.ts",
@@ -1890,7 +1890,7 @@
1890
1890
  "bytesInOutput": 5175
1891
1891
  },
1892
1892
  "src/core/batch.ts": {
1893
- "bytesInOutput": 5518
1893
+ "bytesInOutput": 5499
1894
1894
  },
1895
1895
  "src/lexer/tokens.ts": {
1896
1896
  "bytesInOutput": 2262
@@ -2007,7 +2007,7 @@
2007
2007
  "bytesInOutput": 2656
2008
2008
  },
2009
2009
  "src/core/emptyWildcardSchema.ts": {
2010
- "bytesInOutput": 1068
2010
+ "bytesInOutput": 1223
2011
2011
  },
2012
2012
  "src/engine/process.ts": {
2013
2013
  "bytesInOutput": 20100
@@ -2070,10 +2070,10 @@
2070
2070
  "bytesInOutput": 412
2071
2071
  },
2072
2072
  "src/execute.ts": {
2073
- "bytesInOutput": 182489
2073
+ "bytesInOutput": 184454
2074
2074
  },
2075
2075
  "src/engine-library/errors.ts": {
2076
- "bytesInOutput": 1441
2076
+ "bytesInOutput": 1440
2077
2077
  },
2078
2078
  "src/api/cursorLeaseManager.ts": {
2079
2079
  "bytesInOutput": 1777
@@ -2091,7 +2091,7 @@
2091
2091
  "bytesInOutput": 102
2092
2092
  },
2093
2093
  "src/engine-library/browserClient.ts": {
2094
- "bytesInOutput": 4304
2094
+ "bytesInOutput": 4313
2095
2095
  },
2096
2096
  "src/engine-library/readonlyClient.ts": {
2097
2097
  "bytesInOutput": 1111
@@ -2103,7 +2103,7 @@
2103
2103
  "bytesInOutput": 2212
2104
2104
  },
2105
2105
  "src/engine-library/resultMapping.ts": {
2106
- "bytesInOutput": 777
2106
+ "bytesInOutput": 873
2107
2107
  },
2108
2108
  "src/core/sql.ts": {
2109
2109
  "bytesInOutput": 186
@@ -2124,7 +2124,7 @@
2124
2124
  "bytesInOutput": 16
2125
2125
  }
2126
2126
  },
2127
- "bytes": 536104
2127
+ "bytes": 538309
2128
2128
  }
2129
2129
  }
2130
2130
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "inputs": {
3
3
  "src/api/fetchAll.ts": {
4
- "bytes": 12389,
4
+ "bytes": 12571,
5
5
  "imports": [],
6
6
  "format": "esm"
7
7
  },
@@ -886,7 +886,7 @@
886
886
  "format": "esm"
887
887
  },
888
888
  "src/core/emptyWildcardSchema.ts": {
889
- "bytes": 2525,
889
+ "bytes": 3248,
890
890
  "imports": [],
891
891
  "format": "esm"
892
892
  },
@@ -1166,7 +1166,7 @@
1166
1166
  "format": "esm"
1167
1167
  },
1168
1168
  "src/execute.ts": {
1169
- "bytes": 466368,
1169
+ "bytes": 471132,
1170
1170
  "imports": [
1171
1171
  {
1172
1172
  "path": "src/lexer/lexer.ts",
@@ -1575,7 +1575,7 @@
1575
1575
  "format": "esm"
1576
1576
  },
1577
1577
  "src/engine-library/browserClient.ts": {
1578
- "bytes": 11329,
1578
+ "bytes": 11422,
1579
1579
  "imports": [
1580
1580
  {
1581
1581
  "path": "src/api/cursorLeaseManager.ts",
@@ -1643,7 +1643,7 @@
1643
1643
  "format": "esm"
1644
1644
  },
1645
1645
  "src/engine-library/resultMapping.ts": {
1646
- "bytes": 1867,
1646
+ "bytes": 2033,
1647
1647
  "imports": [
1648
1648
  {
1649
1649
  "path": "src/execute.ts",
@@ -1904,7 +1904,7 @@
1904
1904
  "bytesInOutput": 5175
1905
1905
  },
1906
1906
  "src/core/batch.ts": {
1907
- "bytesInOutput": 5518
1907
+ "bytesInOutput": 5499
1908
1908
  },
1909
1909
  "src/lexer/tokens.ts": {
1910
1910
  "bytesInOutput": 2262
@@ -2021,7 +2021,7 @@
2021
2021
  "bytesInOutput": 2656
2022
2022
  },
2023
2023
  "src/core/emptyWildcardSchema.ts": {
2024
- "bytesInOutput": 1068
2024
+ "bytesInOutput": 1223
2025
2025
  },
2026
2026
  "src/engine/process.ts": {
2027
2027
  "bytesInOutput": 20100
@@ -2084,10 +2084,10 @@
2084
2084
  "bytesInOutput": 412
2085
2085
  },
2086
2086
  "src/execute.ts": {
2087
- "bytesInOutput": 182489
2087
+ "bytesInOutput": 184454
2088
2088
  },
2089
2089
  "src/engine-library/errors.ts": {
2090
- "bytesInOutput": 1441
2090
+ "bytesInOutput": 1440
2091
2091
  },
2092
2092
  "src/api/cursorLeaseManager.ts": {
2093
2093
  "bytesInOutput": 1777
@@ -2105,7 +2105,7 @@
2105
2105
  "bytesInOutput": 102
2106
2106
  },
2107
2107
  "src/engine-library/browserClient.ts": {
2108
- "bytesInOutput": 4304
2108
+ "bytesInOutput": 4313
2109
2109
  },
2110
2110
  "src/engine-library/readonlyClient.ts": {
2111
2111
  "bytesInOutput": 1111
@@ -2117,7 +2117,7 @@
2117
2117
  "bytesInOutput": 2212
2118
2118
  },
2119
2119
  "src/engine-library/resultMapping.ts": {
2120
- "bytesInOutput": 777
2120
+ "bytesInOutput": 873
2121
2121
  },
2122
2122
  "src/core/sql.ts": {
2123
2123
  "bytesInOutput": 186
@@ -2144,7 +2144,7 @@
2144
2144
  "bytesInOutput": 127
2145
2145
  }
2146
2146
  },
2147
- "bytes": 537128
2147
+ "bytes": 539333
2148
2148
  }
2149
2149
  }
2150
2150
  }
@@ -6,9 +6,11 @@ export interface ReadonlyGetRecordsParams {
6
6
  app: number;
7
7
  query: string;
8
8
  fields: string[];
9
+ totalCount?: boolean;
9
10
  }
10
11
  export interface ReadonlyGetRecordsResult {
11
12
  records: ReadonlyKintoneRecord[];
13
+ totalCount?: string;
12
14
  searchAborted?: boolean;
13
15
  }
14
16
  export interface ReadonlyCursorOpenParams {
@@ -128,6 +130,10 @@ export interface QueryMetrics {
128
130
  fetchedRows: number;
129
131
  elapsedMs: number;
130
132
  cursorRecordsScanned: number;
133
+ /** 取得上限に達したか。true なら結果は全件ではない。 */
134
+ limitReached?: boolean;
135
+ /** 上限に達したアプリ ID(判明した範囲・重複なし・昇順)。 */
136
+ limitReachedApps?: readonly number[];
131
137
  }
132
138
  export type ValidateConstraintCategory = "required" | "length" | "range" | "choice";
133
139
  export interface ValidateConstraintMetadata {
@@ -44415,11 +44415,11 @@ var EMPTY_WILDCARD_FIELD_TYPE_POLICY = {
44415
44415
  UPDATED_TIME: "RECORD",
44416
44416
  USER_SELECT: "RECORD"
44417
44417
  };
44418
- function fieldPolicy(fieldType) {
44418
+ function fieldPolicy(fieldType, fieldCode) {
44419
44419
  const policy = EMPTY_WILDCARD_FIELD_TYPE_POLICY[fieldType];
44420
44420
  if (policy === void 0) {
44421
44421
  throw new Error(
44422
- `InternalError: empty SELECT * schema policy is not defined for field type ${fieldType}.`
44422
+ `ArgumentError: getFields returned unknown fieldType "${fieldType}" for field "${fieldCode}". getFields must return only the fields from /k/v1/app/form/fields.json; $id and $revision are synthesized by the engine and must not be added.`
44423
44423
  );
44424
44424
  }
44425
44425
  return policy;
@@ -44434,10 +44434,10 @@ async function deriveEmptyWildcardColumns(fields, subtableCode, loadProcessStatu
44434
44434
  ];
44435
44435
  }
44436
44436
  const topLevel = fields.filter((field) => !field.inSubtable);
44437
- const needsProcessSettings = topLevel.some((field) => fieldPolicy(field.fieldType) === "PROCESS");
44437
+ const needsProcessSettings = topLevel.some((field) => fieldPolicy(field.fieldType, field.code) === "PROCESS");
44438
44438
  const processEnabled = needsProcessSettings ? (await loadProcessStatuses()).enable : false;
44439
44439
  const columns = topLevel.filter((field) => {
44440
- const policy = fieldPolicy(field.fieldType);
44440
+ const policy = fieldPolicy(field.fieldType, field.code);
44441
44441
  return policy === "RECORD" || policy === "PROCESS" && processEnabled;
44442
44442
  }).map((field) => field.code);
44443
44443
  return [...columns, "$revision", "$id"];
@@ -47359,11 +47359,21 @@ function createEmptyMetrics() {
47359
47359
  cursorCreateOutcomeUnknown: 0,
47360
47360
  cursorQuarantinedCurrent: 0,
47361
47361
  fetchedRows: 0,
47362
+ limitReached: false,
47363
+ limitReachedApps: [],
47362
47364
  elapsedMs: 0
47363
47365
  };
47364
47366
  }
47367
+ var LIMIT_METRICS_SINK = /* @__PURE__ */ Symbol("limitMetricsSink");
47368
+ function markLimitReached(client, appId) {
47369
+ const metrics = client[LIMIT_METRICS_SINK];
47370
+ if (!metrics) return;
47371
+ metrics.limitReached = true;
47372
+ if (!metrics.limitReachedApps.includes(appId)) metrics.limitReachedApps.push(appId);
47373
+ }
47365
47374
  function wrapClientWithMetrics(client, metrics) {
47366
47375
  return {
47376
+ [LIMIT_METRICS_SINK]: metrics,
47367
47377
  getRecords: async (params) => {
47368
47378
  metrics.getCalls += 1;
47369
47379
  const res = await client.getRecords(params);
@@ -47563,7 +47573,7 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
47563
47573
  return executeExistingRecordValidation(stmt, client, options, cacheContext);
47564
47574
  case "SELECT":
47565
47575
  return executeSelect(
47566
- stmt,
47576
+ markCountTotalCountRoot(stmt),
47567
47577
  client,
47568
47578
  options,
47569
47579
  cacheContext,
@@ -48301,12 +48311,12 @@ function resolveBatchVariableReferencesInternal(node, variables, numericArithmet
48301
48311
  if (value.type === "array") {
48302
48312
  throw new Error(`ParseError: array variable @${obj["name"]} can only be used as IN @${obj["name"]}.`);
48303
48313
  }
48304
- if (numericArithmeticOperand && value.type !== "number") {
48314
+ if (numericArithmeticOperand && value.type !== "number" && value.placeholder !== true) {
48305
48315
  throw new Error(
48306
48316
  `ArgumentError: variable @${obj["name"]} is not numeric and cannot be used in arithmetic.`
48307
48317
  );
48308
48318
  }
48309
- return value.type === "number" ? { type: "NUMBER", value: value.value, raw: value.raw ?? String(value.value) } : { type: "STRING", value: value.value };
48319
+ return numericArithmeticOperand && value.type === "string" && value.placeholder === true ? { type: "NUMBER", value: 0, raw: value.value } : value.type === "number" ? { type: "NUMBER", value: value.value, raw: value.raw ?? String(value.value) } : { type: "STRING", value: value.value };
48310
48320
  }
48311
48321
  if (obj["type"] === "VARIABLE_COL" && typeof obj["name"] === "string" && typeof obj["alias"] === "string") {
48312
48322
  const value = variables.get(obj["name"]);
@@ -48699,7 +48709,7 @@ async function executeSelect(stmt, client, options, cacheContext, cteCache, capt
48699
48709
  cteCache
48700
48710
  );
48701
48711
  await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
48702
- const whereCapability = await resolveSelectWhereCapability(stmt, client, cacheContext, cteCache);
48712
+ const whereCapability = rememberSelectWhereCapability(stmt, await resolveSelectWhereCapability(stmt, client, cacheContext, cteCache));
48703
48713
  if (whereCapability.capability === "UNSUPPORTED") {
48704
48714
  throw new Error(`ArgumentError: WHERE predicate is unsupported (${formatWhereCapabilityFailure(whereCapability)}).`);
48705
48715
  }
@@ -49125,6 +49135,7 @@ async function executeSimpleSelect(stmt, client, options, cacheContext, orderPla
49125
49135
  onLimit: onLimit2,
49126
49136
  onTruncate: (max) => {
49127
49137
  warnings.add(`\u53D6\u5F97\u4E0A\u9650\uFF08${max} \u4EF6\uFF09\u306B\u9054\u3057\u305F\u305F\u3081\u3001${max} \u4EF6\u3067\u6253\u3061\u5207\u3063\u3066\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002`);
49138
+ markLimitReached(client, stmt.from.appId);
49128
49139
  }
49129
49140
  }
49130
49141
  );
@@ -50010,7 +50021,55 @@ function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
50010
50021
  };
50011
50022
  return { row, having };
50012
50023
  }
50024
+ var countTotalCountRootSelects = /* @__PURE__ */ new WeakSet();
50025
+ var resolvedWhereCapabilities = /* @__PURE__ */ new WeakMap();
50026
+ function markCountTotalCountRoot(stmt) {
50027
+ countTotalCountRootSelects.add(stmt);
50028
+ return stmt;
50029
+ }
50030
+ function rememberSelectWhereCapability(stmt, capability) {
50031
+ resolvedWhereCapabilities.set(stmt, capability);
50032
+ return capability;
50033
+ }
50034
+ function isCountStarTotalCountEligible(stmt, whereCapability) {
50035
+ if (whereCapability.capability !== "EXACT_PUSHDOWN") return false;
50036
+ if (stmt.columns.length !== 1) return false;
50037
+ const column = stmt.columns[0];
50038
+ if (column?.type !== "AGGREGATE" || column.func !== "COUNT" || column.distinct || column.arg.type !== "WILDCARD") {
50039
+ return false;
50040
+ }
50041
+ return !stmt.distinct && normalizeGroupingSpec(stmt).type === "NONE" && stmt.having === null && stmt.joins.length === 0 && stmt.from.cteName === null && !stmt.from.subtableCode && stmt.limit === null && stmt.offset === null;
50042
+ }
50043
+ function isValidTotalCount(value) {
50044
+ return typeof value === "string" && /^(?:0|[1-9]\d*)$/.test(value);
50045
+ }
50046
+ async function tryCountStarWithTotalCount(stmt, client) {
50047
+ const countColumn = stmt.columns[0];
50048
+ if (countColumn?.type !== "AGGREGATE") return null;
50049
+ const baseQuery = stmt.where === null ? "" : whereToKintone(stmt.where);
50050
+ const response = await client.getRecords({
50051
+ app: stmt.from.appId,
50052
+ query: `${baseQuery}${baseQuery ? " " : ""}limit 1`,
50053
+ fields: ["$id"],
50054
+ totalCount: true
50055
+ });
50056
+ if (response.searchAborted) throw new SearchAbortedError();
50057
+ if (!isValidTotalCount(response.totalCount)) return null;
50058
+ const column = countColumn.alias ?? "COUNT(*)";
50059
+ return {
50060
+ type: "SELECT",
50061
+ rows: [{ [column]: response.totalCount }],
50062
+ columns: [column],
50063
+ rowCount: 1,
50064
+ warnings: []
50065
+ };
50066
+ }
50013
50067
  async function executeFullScanSelect(stmt, client, options, cacheContext, cteCache, allowOriginalWherePushdown = true, preloadedOrderMeta, prefilterPlan, plainGroupByPlan) {
50068
+ const whereCapability = resolvedWhereCapabilities.get(stmt);
50069
+ if (countTotalCountRootSelects.has(stmt) && whereCapability !== void 0 && isCountStarTotalCountEligible(stmt, whereCapability)) {
50070
+ const totalCountResult = await tryCountStarWithTotalCount(stmt, client);
50071
+ if (totalCountResult !== null) return totalCountResult;
50072
+ }
50014
50073
  const maxRecords2 = options.maxRecords ?? 1e4;
50015
50074
  const warnings = /* @__PURE__ */ new Set();
50016
50075
  const parallel = options.fetchParallel ?? 1;
@@ -50451,6 +50510,7 @@ async function fetchTableRecordsForFullScan(stmt, table, client, maxRecords2, pa
50451
50510
  const fields = selectToFetchAllFields(stmt, table, plainGroupByPlan);
50452
50511
  const onTruncate = (max) => {
50453
50512
  warnings.add(`\u53D6\u5F97\u4E0A\u9650\uFF08${max} \u4EF6\uFF09\u306B\u9054\u3057\u305F\u305F\u3081\u3001${max} \u4EF6\u3067\u6253\u3061\u5207\u3063\u3066\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002`);
50513
+ markLimitReached(client, table.appId);
50454
50514
  };
50455
50515
  if (!table.subtableCode) {
50456
50516
  const baseQuery = isMainTable && allowOriginalWherePushdown ? selectToFetchAllParams(stmt, table.appId).query : "";
@@ -50606,6 +50666,7 @@ async function tryFetchJoinRecordsBySourceKeys(stmt, join, tables, client, maxRe
50606
50666
  const fields = selectToFetchAllFields(stmt, join.table, plainGroupByPlan);
50607
50667
  const onTruncate = (max) => {
50608
50668
  warnings.add(`\u53D6\u5F97\u4E0A\u9650\uFF08${max} \u4EF6\uFF09\u306B\u9054\u3057\u305F\u305F\u3081\u3001${max} \u4EF6\u3067\u6253\u3061\u5207\u3063\u3066\u8868\u793A\u3057\u3066\u3044\u307E\u3059\u3002`);
50669
+ markLimitReached(client, join.table.appId);
50609
50670
  };
50610
50671
  const chunks = splitChunks(values, JOIN_IN_CHUNK_SIZE);
50611
50672
  const merged = [];
@@ -54357,7 +54418,7 @@ async function buildBatchExplainPlans(sql, client, injectedVariables, cacheConte
54357
54418
  plan: statementPlan.length === 0 ? metadataPlan : [statementPlan[0], ...metadataPlan, ...statementPlan.slice(1)]
54358
54419
  });
54359
54420
  if (stmt.type === "SET_VARIABLE" || stmt.type === "DECLARE_VARIABLE") {
54360
- variables.set(stmt.name, stmt.type === "SET_VARIABLE" && stmt.expr.type === "ARRAY" ? { type: "array", elements: stmt.expr.elements.map((element) => ({ type: "string", value: element.value })) } : { type: "string", value: `@${stmt.name}` });
54421
+ variables.set(stmt.name, stmt.type === "SET_VARIABLE" && stmt.expr.type === "ARRAY" ? { type: "array", elements: stmt.expr.elements.map((element) => ({ type: "string", value: element.value })) } : { type: "string", value: `@${stmt.name}`, placeholder: true });
54361
54422
  }
54362
54423
  }
54363
54424
  return { statementCount: statements.length, statements: plans };
@@ -54625,11 +54686,12 @@ function buildValidatePlan(stmt, label) {
54625
54686
  lines.push(" records/mutation API during EXPLAIN: none; violation count unavailable");
54626
54687
  return lines;
54627
54688
  }
54628
- function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlans) {
54689
+ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlans, allowTotalCountPlan = true) {
54629
54690
  const whereCapability = capabilities?.get(stmt) ?? (capabilities ? [...capabilities].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
54630
54691
  const orderPlan = orderPlans?.get(stmt) ?? (orderPlans ? [...orderPlans].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
54631
54692
  const plainGroupByPlan = plainGroupByPlans?.get(stmt) ?? (plainGroupByPlans ? [...plainGroupByPlans].find(([candidate]) => JSON.stringify(candidate) === JSON.stringify(stmt))?.[1] : void 0);
54632
- const mode = orderPlan?.kind === "CANONICAL_LOCAL" ? "FULL_SCAN" : whereCapability && whereCapability.capability !== "EXACT_PUSHDOWN" ? "FULL_SCAN" : resolveSelectMode(stmt);
54693
+ const totalCountPlan = allowTotalCountPlan && whereCapability !== void 0 && isCountStarTotalCountEligible(stmt, whereCapability);
54694
+ const mode = totalCountPlan ? "COUNT_TOTAL_COUNT" : orderPlan?.kind === "CANONICAL_LOCAL" ? "FULL_SCAN" : whereCapability && whereCapability.capability !== "EXACT_PUSHDOWN" ? "FULL_SCAN" : resolveSelectMode(stmt);
54633
54695
  const reasons = collectFullScanReasons(stmt);
54634
54696
  if (whereCapability && whereCapability.capability !== "EXACT_PUSHDOWN") {
54635
54697
  reasons.push(...whereCapability.reasons.map((reason) => reason.code));
@@ -54676,6 +54738,20 @@ function buildSelectPlan(stmt, label, capabilities, orderPlans, plainGroupByPlan
54676
54738
  }
54677
54739
  }
54678
54740
  }
54741
+ if (totalCountPlan) {
54742
+ const baseQuery = stmt.where === null ? "" : whereToKintone(stmt.where);
54743
+ lines.push(` app: APP${stmt.from.appId} (${stmt.from.appId})`);
54744
+ lines.push(
54745
+ ` kintone query: ${baseQuery}${baseQuery ? " " : ""}limit 1`
54746
+ );
54747
+ lines.push(" fields: $id");
54748
+ lines.push(" fetch API: GET records.json (totalCount=true)");
54749
+ lines.push(" REST execution: single GET");
54750
+ lines.push(" record limit: maxRecords/onLimitReached not applied");
54751
+ lines.push(" fallback: full record scan when totalCount is missing or invalid");
54752
+ lines.push(" search abort: fail-closed (SearchAbortedError)");
54753
+ return lines;
54754
+ }
54679
54755
  if (orderPlan) {
54680
54756
  lines.push(` order plan: ${orderPlan.kind}`);
54681
54757
  if (orderPlan.reasonCodes.length > 0) lines.push(` order reason: ${orderPlan.reasonCodes.join(", ")}`);
@@ -54812,7 +54888,7 @@ function buildUnionPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
54812
54888
  const lines = [];
54813
54889
  selects.forEach((sel, i) => {
54814
54890
  if (i > 0) lines.push("");
54815
- lines.push(...buildSelectPlan(sel, `[union:${i + 1}]`, capabilities, orderPlans, plainGroupByPlans));
54891
+ lines.push(...buildSelectPlan(sel, `[union:${i + 1}]`, capabilities, orderPlans, plainGroupByPlans, false));
54816
54892
  });
54817
54893
  return lines;
54818
54894
  }
@@ -54820,7 +54896,7 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
54820
54896
  const lines = [];
54821
54897
  for (const cte of stmt.ctes) {
54822
54898
  if (cte.query.type === "SELECT") {
54823
- lines.push(...buildSelectPlan(cte.query, `[cte: ${cte.name}]`, capabilities, orderPlans, plainGroupByPlans));
54899
+ lines.push(...buildSelectPlan(cte.query, `[cte: ${cte.name}]`, capabilities, orderPlans, plainGroupByPlans, false));
54824
54900
  lines.push("");
54825
54901
  }
54826
54902
  }
@@ -54839,7 +54915,7 @@ function buildWithPlan(stmt, capabilities, orderPlans, plainGroupByPlans) {
54839
54915
  if (canInlineSingleCte(stmt)) {
54840
54916
  lines.push("");
54841
54917
  const inlined = buildInlinedQuery(stmt);
54842
- lines.push(...buildSelectPlan(inlined, "[effective: inlined CTE]", capabilities, orderPlans, plainGroupByPlans));
54918
+ lines.push(...buildSelectPlan(inlined, "[effective: inlined CTE]", capabilities, orderPlans, plainGroupByPlans, false));
54843
54919
  }
54844
54920
  return lines;
54845
54921
  }
@@ -54881,16 +54957,16 @@ function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans)
54881
54957
  case "BINARY":
54882
54958
  if (w.right.type === "SCALAR_SUBQUERY") {
54883
54959
  lines.push("");
54884
- lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
54960
+ lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
54885
54961
  }
54886
54962
  if (w.right.type === "SUBQUERY_IN_LIST") {
54887
54963
  lines.push("");
54888
- lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
54964
+ lines.push(...buildSelectPlan(w.right.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
54889
54965
  }
54890
54966
  break;
54891
54967
  case "EXISTS":
54892
54968
  lines.push("");
54893
- lines.push(...buildSelectPlan(w.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
54969
+ lines.push(...buildSelectPlan(w.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
54894
54970
  break;
54895
54971
  case "LOGICAL":
54896
54972
  visitWhere(w.left);
@@ -54910,7 +54986,7 @@ function collectSubqueryPlans(stmt, capabilities, orderPlans, plainGroupByPlans)
54910
54986
  for (const col of stmt.columns) {
54911
54987
  if (col.type === "SCALAR_SUBQUERY_COL") {
54912
54988
  lines.push("");
54913
- lines.push(...buildSelectPlan(col.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans));
54989
+ lines.push(...buildSelectPlan(col.query, `[subquery:${idx++}]`, capabilities, orderPlans, plainGroupByPlans, false));
54914
54990
  }
54915
54991
  }
54916
54992
  if (stmt.having) visitWhere(stmt.having);
@@ -54936,7 +55012,7 @@ function buildInsertSelectPlan(stmt, label, capabilities, orderPlans, plainGroup
54936
55012
  lines.push(` fields: ${stmt.fields.join(", ")}`);
54937
55013
  lines.push(` api: POST /k/v1/records.json\uFF08\u4EF6\u6570\u306F SELECT \u7D50\u679C\u306B\u4F9D\u5B58\u3001100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`);
54938
55014
  lines.push("");
54939
- lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans));
55015
+ lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans, false));
54940
55016
  return lines;
54941
55017
  }
54942
55018
  function buildUpdatePlan(stmt, label, capabilities, orderPlans, dmlMaxRows = 100, dmlMaxSubtableRows = DEFAULT_APPLY_MAX_SUBTABLE_ROWS, maxRecords2 = 1e4) {
@@ -54983,7 +55059,7 @@ function buildUpdatePlan(stmt, label, capabilities, orderPlans, dmlMaxRows = 100
54983
55059
  for (const a of stmt.assignments) {
54984
55060
  if (a.value.type === "SCALAR_SUBQUERY") {
54985
55061
  lines.push("");
54986
- lines.push(...buildSelectPlan(a.value.query, `[subquery: ${a.field}]`, capabilities, orderPlans));
55062
+ lines.push(...buildSelectPlan(a.value.query, `[subquery: ${a.field}]`, capabilities, orderPlans, void 0, false));
54987
55063
  }
54988
55064
  }
54989
55065
  return lines;
@@ -55100,7 +55176,7 @@ function buildUpsertSelectPlan(stmt, label, capabilities, orderPlans, plainGroup
55100
55176
  ` api: GET /k/v1/records.json\uFF08\u91CD\u8907\u5224\u5B9A\uFF09\u2192 POST \u307E\u305F\u306F PUT /k/v1/records.json\uFF08100 \u4EF6\u3054\u3068\u306B\u30D0\u30C3\u30C1\uFF09`,
55101
55177
  ``
55102
55178
  ];
55103
- lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans));
55179
+ lines.push(...buildSelectPlan(stmt.select, "[source SELECT]", capabilities, orderPlans, plainGroupByPlans, false));
55104
55180
  return lines;
55105
55181
  }
55106
55182
  function buildReorderPlan(stmt, label) {
@@ -56441,7 +56517,8 @@ function createNodeKintoneConnection(baseUrl, tokenResolver) {
56441
56517
  const queryPart = `query=${encodeURIComponent(params.query)}`;
56442
56518
  const appPart = `app=${encodeURIComponent(String(params.app))}`;
56443
56519
  const fieldParts = params.fields.map((f) => `fields[]=${encodeURIComponent(f)}`);
56444
- const qs = [appPart, queryPart, ...fieldParts].join("&");
56520
+ const totalCountPart = params.totalCount === true ? ["totalCount=true"] : [];
56521
+ const qs = [appPart, queryPart, ...fieldParts, ...totalCountPart].join("&");
56445
56522
  if (tokenResolver.debug) {
56446
56523
  tokenResolver.log?.(
56447
56524
  `[debug] getRecords app=${params.app} query="${params.query}" fields=${params.fields.length > 0 ? params.fields.join(",") : "(all)"} auth=${tokenResolver.auth.type}`
@@ -58656,7 +58733,7 @@ Nested JSON/CSV subtable mutation is fail-closed on MCP: use VALIDATE ONLY/EXPLA
58656
58733
  JSON child IDs are rejected and replacement renumbers all rows.
58657
58734
  `);
58658
58735
  }
58659
- var SERVER_VERSION = true ? "3.31.0" : "0.0.0-dev";
58736
+ var SERVER_VERSION = true ? "3.32.0" : "0.0.0-dev";
58660
58737
  var FUNCTION_CATALOG_PARAGRAPH = `Complete function catalog \u2014 Scalar: ${KSQL_FUNCTION_CATALOG.scalar.join(" ")}. Aggregate: ${KSQL_FUNCTION_CATALOG.aggregate.join(" ")}. Variance and standard-deviation aggregates use explicit POP/SAMP names; unqualified STDDEV and VARIANCE are unsupported. Window: ${KSQL_FUNCTION_CATALOG.window.join(" ")} (OVER and AS alias required). Contextual: ${KSQL_FUNCTION_CATALOG.contextual.join(" ")} (kintone predicates; WHERE server-only/fail-closed; INNER JOIN direct-APP exact pushdown supported; local LOGINUSER is empty on all surfaces). Aliases: ${KSQL_FUNCTION_CATALOG.aliases.join(" ")}. Syntax: ${KSQL_FUNCTION_CATALOG.syntax.join(" ")}. This list is complete; functions from other dialects such as IFNULL do not exist. Use ksql_docs for arguments and constraints.`;
58661
58738
  var KSQL_MCP_INSTRUCTIONS = `kSQL is a SQL-like dialect for kintone, not generic SQL. Supports cataloged families plus JOIN, aggregates, windows, subtable virtual tables, CHECK, KLIKE, KORDER BY, @variables, and LAPP_<NAME>.
58662
58739
 
Binary file