@rex0220/kintone-sql-tools 2.14.1 → 2.16.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.
@@ -30999,6 +30999,10 @@ var KEYWORDS = /* @__PURE__ */ new Map([
30999
30999
  ["AVG", "AVG" /* AVG */],
31000
31000
  ["MAX", "MAX" /* MAX */],
31001
31001
  ["MIN", "MIN" /* MIN */],
31002
+ ["GROUP_CONCAT", "GROUP_CONCAT" /* GROUP_CONCAT */],
31003
+ ["ROW_NUMBER", "ROW_NUMBER" /* ROW_NUMBER */],
31004
+ ["RANK", "RANK" /* RANK */],
31005
+ ["DENSE_RANK", "DENSE_RANK" /* DENSE_RANK */],
31002
31006
  ["ASSERT", "ASSERT" /* ASSERT */],
31003
31007
  ["AND", "AND" /* AND */],
31004
31008
  ["OR", "OR" /* OR */],
@@ -31375,6 +31379,9 @@ var FUNC_CALL_PREFIX_KINDS = /* @__PURE__ */ new Set([
31375
31379
  "AVG" /* AVG */,
31376
31380
  "MAX" /* MAX */,
31377
31381
  "MIN" /* MIN */,
31382
+ "ROW_NUMBER" /* ROW_NUMBER */,
31383
+ "RANK" /* RANK */,
31384
+ "DENSE_RANK" /* DENSE_RANK */,
31378
31385
  "TODAY" /* TODAY */,
31379
31386
  "NOW" /* NOW */,
31380
31387
  "LOGINUSER" /* LOGINUSER */,
@@ -31893,6 +31900,11 @@ var Parser = class {
31893
31900
  const orderBy = this.consume("ORDER" /* ORDER */) ? (this.expect("BY" /* BY */), this.parseOrderBy()) : [];
31894
31901
  const limit = this.consume("LIMIT" /* LIMIT */) ? this.parseUnsignedInt() : null;
31895
31902
  const offset = this.consume("OFFSET" /* OFFSET */) ? this.parseUnsignedInt() : null;
31903
+ const hasWindow = columns.some((column) => column.type === "WINDOW_COL");
31904
+ const hasAggregate = columns.some((column) => this.selectColumnHasAggregate(column));
31905
+ if (hasWindow && (groupBy.length > 0 || hasAggregate)) {
31906
+ throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306F GROUP BY / \u96C6\u8A08\u95A2\u6570\u3068\u540C\u3058 SELECT \u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093", this.peek());
31907
+ }
31896
31908
  return {
31897
31909
  type: "SELECT",
31898
31910
  distinct,
@@ -31957,6 +31969,10 @@ var Parser = class {
31957
31969
  if (this.consume("*" /* STAR */)) {
31958
31970
  return { type: "WILDCARD" };
31959
31971
  }
31972
+ const windowFunc = this.tryWindowFunc();
31973
+ if (windowFunc !== null) {
31974
+ return this.parseWindowColumn(windowFunc);
31975
+ }
31960
31976
  if (this.peek().kind === "CASE" /* CASE */) {
31961
31977
  const expr = this.parseCaseWhenExpr();
31962
31978
  const alias2 = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
@@ -31991,6 +32007,7 @@ var Parser = class {
31991
32007
  func: ref.func,
31992
32008
  distinct: ref.distinct,
31993
32009
  arg: ref.arg,
32010
+ ...ref.separator !== void 0 ? { separator: ref.separator } : {},
31994
32011
  alias: alias2
31995
32012
  };
31996
32013
  }
@@ -32027,6 +32044,56 @@ var Parser = class {
32027
32044
  const alias = this.consume("AS" /* AS */) ? this.parseAliasName() : null;
32028
32045
  return { type: "FIELD", field, alias };
32029
32046
  }
32047
+ tryWindowFunc() {
32048
+ switch (this.peek().kind) {
32049
+ case "ROW_NUMBER" /* ROW_NUMBER */:
32050
+ return "ROW_NUMBER";
32051
+ case "RANK" /* RANK */:
32052
+ return "RANK";
32053
+ case "DENSE_RANK" /* DENSE_RANK */:
32054
+ return "DENSE_RANK";
32055
+ default:
32056
+ return null;
32057
+ }
32058
+ }
32059
+ parseWindowColumn(func) {
32060
+ this.advance();
32061
+ this.expect("(" /* LPAREN */);
32062
+ if (this.peek().kind !== ")" /* RPAREN */) {
32063
+ throw new ParseError(`${func} \u306F\u5F15\u6570\u3092\u53D7\u3051\u4ED8\u3051\u307E\u305B\u3093`, this.peek());
32064
+ }
32065
+ this.expect(")" /* RPAREN */);
32066
+ this.expectSoftKeyword("OVER", `${func} \u306B\u306F OVER (...) \u304C\u5FC5\u8981\u3067\u3059`);
32067
+ this.expect("(" /* LPAREN */);
32068
+ const partitionBy = [];
32069
+ if (this.isSoftKeyword("PARTITION")) {
32070
+ this.advance();
32071
+ this.expect("BY" /* BY */, "PARTITION \u306E\u5F8C\u306B\u306F BY \u304C\u5FC5\u8981\u3067\u3059");
32072
+ do {
32073
+ const ref = this.parseQualifiedIdent();
32074
+ partitionBy.push({ type: "FIELD", tableAlias: ref.tableAlias, field: ref.field });
32075
+ } while (this.consume("," /* COMMA */));
32076
+ }
32077
+ const orderBy = this.consume("ORDER" /* ORDER */) ? (this.expect("BY" /* BY */), this.parseOrderBy()) : [];
32078
+ this.expect(")" /* RPAREN */);
32079
+ if (!this.consume("AS" /* AS */)) {
32080
+ throw new ParseError("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u306B\u306F AS alias \u304C\u5FC5\u8981\u3067\u3059", this.peek());
32081
+ }
32082
+ const alias = this.parseAliasName();
32083
+ return { type: "WINDOW_COL", func, partitionBy, orderBy, alias };
32084
+ }
32085
+ selectColumnHasAggregate(column) {
32086
+ if (column.type === "AGGREGATE" || column.type === "ARITH_AGG_COL") return true;
32087
+ if (column.type !== "STRFUNC_COL") return false;
32088
+ return column.expr.args.some((arg) => this.stringFuncArgHasAggregate(arg));
32089
+ }
32090
+ stringFuncArgHasAggregate(arg) {
32091
+ if (arg.type === "AGG_REF" || arg.type === "AGG_ARITH") return true;
32092
+ if (arg.type === "STRING_FUNC") {
32093
+ return arg.args.some((nested) => this.stringFuncArgHasAggregate(nested));
32094
+ }
32095
+ return false;
32096
+ }
32030
32097
  isArithOp(kind) {
32031
32098
  return kind === "+" /* PLUS */ || kind === "-" /* MINUS */ || kind === "*" /* STAR */ || kind === "/" /* SLASH */ || kind === "%" /* PERCENT */;
32032
32099
  }
@@ -32362,7 +32429,8 @@ var Parser = class {
32362
32429
  ["SUM" /* SUM */]: "SUM",
32363
32430
  ["AVG" /* AVG */]: "AVG",
32364
32431
  ["MAX" /* MAX */]: "MAX",
32365
- ["MIN" /* MIN */]: "MIN"
32432
+ ["MIN" /* MIN */]: "MIN",
32433
+ ["GROUP_CONCAT" /* GROUP_CONCAT */]: "GROUP_CONCAT"
32366
32434
  };
32367
32435
  const kind = this.peek().kind;
32368
32436
  return map2[kind] ?? null;
@@ -32374,12 +32442,29 @@ var Parser = class {
32374
32442
  const distinct = this.consume("DISTINCT" /* DISTINCT */);
32375
32443
  let arg;
32376
32444
  if (this.consume("*" /* STAR */)) {
32445
+ if (func === "GROUP_CONCAT") {
32446
+ throw new ParseError("GROUP_CONCAT(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
32447
+ }
32377
32448
  arg = { type: "WILDCARD" };
32378
32449
  } else {
32379
32450
  arg = this.parseArithAddSub();
32380
32451
  }
32452
+ let separator;
32453
+ if (this.isSoftKeyword("SEPARATOR")) {
32454
+ const separatorToken = this.advance();
32455
+ if (func !== "GROUP_CONCAT") {
32456
+ throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
32457
+ }
32458
+ separator = this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059").value;
32459
+ }
32381
32460
  this.expect(")" /* RPAREN */);
32382
- return { type: "AGG_REF", func, distinct, arg };
32461
+ return {
32462
+ type: "AGG_REF",
32463
+ func,
32464
+ distinct,
32465
+ arg,
32466
+ ...separator !== void 0 ? { separator } : {}
32467
+ };
32383
32468
  }
32384
32469
  // ----------------------------------------------------------
32385
32470
  // FROM / JOIN
@@ -32657,10 +32742,20 @@ var Parser = class {
32657
32742
  const distinct = this.consume("DISTINCT" /* DISTINCT */);
32658
32743
  let argStr;
32659
32744
  if (this.consume("*" /* STAR */)) {
32745
+ if (aggFunc === "GROUP_CONCAT") {
32746
+ throw new ParseError("GROUP_CONCAT(*) \u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u30D5\u30A3\u30FC\u30EB\u30C9\u307E\u305F\u306F\u5F0F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044", this.prev());
32747
+ }
32660
32748
  argStr = "*";
32661
32749
  } else {
32662
32750
  argStr = this.parseIdentifier();
32663
32751
  }
32752
+ if (this.isSoftKeyword("SEPARATOR")) {
32753
+ const separatorToken = this.advance();
32754
+ if (aggFunc !== "GROUP_CONCAT") {
32755
+ throw new ParseError("SEPARATOR \u306F GROUP_CONCAT \u3067\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059", separatorToken);
32756
+ }
32757
+ this.expect("STRING" /* STRING */, "SEPARATOR \u306E\u5F8C\u306B\u306F\u6587\u5B57\u5217\u30EA\u30C6\u30E9\u30EB\u304C\u5FC5\u8981\u3067\u3059");
32758
+ }
32664
32759
  this.expect(")" /* RPAREN */);
32665
32760
  const syntheticName = distinct ? `${aggFunc}(DISTINCT ${argStr})` : `${aggFunc}(${argStr})`;
32666
32761
  return { type: "FIELD", tableAlias: null, field: syntheticName };
@@ -33768,12 +33863,16 @@ var KintoneQueryError = class extends Error {
33768
33863
  };
33769
33864
 
33770
33865
  // src/converter/selectToKintone.ts
33866
+ function hasWindowColumns(columns) {
33867
+ return columns.some((column) => column.type === "WINDOW_COL");
33868
+ }
33771
33869
  function resolveSelectMode(stmt) {
33772
33870
  if (stmt.from.subtableCode) return "FULL_SCAN";
33773
33871
  if (stmt.joins.some((j) => j.table.subtableCode)) return "FULL_SCAN";
33774
33872
  if (stmt.joins.length > 0) return "FULL_SCAN";
33775
33873
  if (stmt.groupBy.length > 0) return "FULL_SCAN";
33776
33874
  if (stmt.distinct) return "FULL_SCAN";
33875
+ if (hasWindowColumns(stmt.columns)) return "FULL_SCAN";
33777
33876
  if (stmt.columns.some(
33778
33877
  (c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL" || c.type === "SCALAR_SUBQUERY_COL" || c.type === "STRFUNC_COL" && hasAggregateInStringFuncExpr(c.expr)
33779
33878
  )) return "FULL_SCAN";
@@ -34145,16 +34244,16 @@ function collectRequiredFieldsByTable(stmt) {
34145
34244
  }
34146
34245
  walkStringFunc(k.expr, "groupBy");
34147
34246
  };
34148
- const walkOrderByKey = (k) => {
34247
+ const walkOrderByKey = (k, phase = "orderBy") => {
34149
34248
  if (k.type === "FIELD_NAME") {
34150
- addFieldName(k.name, "orderBy");
34249
+ addFieldName(k.name, phase);
34151
34250
  return;
34152
34251
  }
34153
34252
  if (k.type === "ARITH_KEY") {
34154
- walkArith(k.expr, "orderBy");
34253
+ walkArith(k.expr, phase);
34155
34254
  return;
34156
34255
  }
34157
- walkStringFunc(k.expr, "orderBy");
34256
+ walkStringFunc(k.expr, phase);
34158
34257
  };
34159
34258
  for (const col of stmt.columns) {
34160
34259
  switch (col.type) {
@@ -34186,6 +34285,10 @@ function collectRequiredFieldsByTable(stmt) {
34186
34285
  break;
34187
34286
  case "SCALAR_SUBQUERY_COL":
34188
34287
  break;
34288
+ case "WINDOW_COL":
34289
+ for (const ref of col.partitionBy) addFieldRef(ref.field, ref.tableAlias, "select");
34290
+ for (const item of col.orderBy) walkOrderByKey(item.key, "select");
34291
+ break;
34189
34292
  }
34190
34293
  }
34191
34294
  for (const join of stmt.joins) {
@@ -34232,6 +34335,10 @@ function collectSelectOutputNames(columns) {
34232
34335
  }
34233
34336
  if (col.type === "SCALAR_SUBQUERY_COL") {
34234
34337
  names.add(col.alias ?? "(subquery)");
34338
+ continue;
34339
+ }
34340
+ if (col.type === "WINDOW_COL") {
34341
+ names.add(col.alias);
34235
34342
  }
34236
34343
  }
34237
34344
  return names;
@@ -34257,7 +34364,7 @@ function stringFuncLabel(expr) {
34257
34364
  return `${expr.func}(${args.join(",")})`;
34258
34365
  }
34259
34366
  function isAggregateSyntheticName(name) {
34260
- return /^(COUNT|SUM|AVG|MAX|MIN)\(/i.test(name);
34367
+ return /^(COUNT|SUM|AVG|MAX|MIN|GROUP_CONCAT)\(/i.test(name);
34261
34368
  }
34262
34369
 
34263
34370
  // src/core/cteInlining.ts
@@ -36023,7 +36130,7 @@ function applyGroupBy(rows, groupByKeys, columns, resolveAggSortKind) {
36023
36130
  for (const col of columns) {
36024
36131
  if (col.type === "AGGREGATE") {
36025
36132
  const syntheticKey = aggregateSyntheticName2(col.func, col.distinct, col.arg);
36026
- const value = String(evalAggregate(col.func, col.distinct, col.arg, groupRows, resolveAggSortKind));
36133
+ const value = String(evalAggregate(col.func, col.distinct, col.arg, col.separator, groupRows, resolveAggSortKind));
36027
36134
  outRow[col.alias ?? syntheticKey] = value;
36028
36135
  if (col.alias) outRow[syntheticKey] = value;
36029
36136
  } else if (col.type === "ARITH_AGG_COL") {
@@ -36044,7 +36151,7 @@ function evalGroupByKey(key, row) {
36044
36151
  if (key.type === "FUNC_KEY") return evalStringFunc(key.expr, row);
36045
36152
  return String(evalArithExpr(key.expr, row));
36046
36153
  }
36047
- function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
36154
+ function evalAggregate(func, distinct, arg, separator, rows, resolveAggSortKind) {
36048
36155
  if (arg.type === "WILDCARD") {
36049
36156
  return func === "COUNT" ? rows.length : 0;
36050
36157
  }
@@ -36064,6 +36171,7 @@ function evalAggregate(func, distinct, arg, rows, resolveAggSortKind) {
36064
36171
  }
36065
36172
  const eff = distinct ? [...new Set(strValues)] : strValues;
36066
36173
  if (func === "COUNT") return eff.length;
36174
+ if (func === "GROUP_CONCAT") return eff.join(separator ?? ",");
36067
36175
  const sortKind = (func === "MIN" || func === "MAX") && arg.type === "FIELD_REF" ? resolveAggSortKind?.(toAggregateFieldRef(arg.field)) : void 0;
36068
36176
  if (sortKind === "string") {
36069
36177
  if (eff.length === 0) return "";
@@ -36108,7 +36216,7 @@ function minOf(nums) {
36108
36216
  }
36109
36217
  function evalAggArithExpr(node, rows, resolveAggSortKind) {
36110
36218
  if (node.type === "NUMBER") return node.value;
36111
- if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, rows, resolveAggSortKind));
36219
+ if (node.type === "AGG_REF") return Number(evalAggregate(node.func, node.distinct, node.arg, node.separator, rows, resolveAggSortKind));
36112
36220
  const l = evalAggArithExpr(node.left, rows, resolveAggSortKind);
36113
36221
  const r = evalAggArithExpr(node.right, rows, resolveAggSortKind);
36114
36222
  switch (node.op) {
@@ -36178,6 +36286,10 @@ function buildDistinctKeyBuilder(rows, columns) {
36178
36286
  values.push(row[col.field] ?? "");
36179
36287
  continue;
36180
36288
  }
36289
+ if (col.type === "WINDOW_COL") {
36290
+ values.push(row[col.alias] ?? "");
36291
+ continue;
36292
+ }
36181
36293
  if (col.type === "PARENT_WILDCARD") {
36182
36294
  for (const k of sortedParentKeys) {
36183
36295
  values.push(row[k] !== void 0 ? row[k] : null);
@@ -36189,6 +36301,9 @@ function buildDistinctKeyBuilder(rows, columns) {
36189
36301
  }
36190
36302
  function applyOrderBy(rows, orderBy, optionOrders, sortKinds) {
36191
36303
  if (orderBy.length === 0) return rows;
36304
+ return sortDecoratedRows(rows, orderBy, optionOrders, sortKinds).rows.map((item) => item.row);
36305
+ }
36306
+ function sortDecoratedRows(rows, orderBy, optionOrders, sortKinds) {
36192
36307
  const keyMeta = orderBy.map(({ key }) => ({
36193
36308
  orderMap: key.type === "FIELD_NAME" ? optionOrders?.get(key.name) : void 0,
36194
36309
  sortKind: key.type === "FIELD_NAME" ? sortKinds?.get(key.name) : void 0
@@ -36207,14 +36322,16 @@ function applyOrderBy(rows, orderBy, optionOrders, sortKinds) {
36207
36322
  };
36208
36323
  })
36209
36324
  }));
36210
- decorated.sort((a, b) => {
36211
- for (let i = 0; i < orderBy.length; i++) {
36212
- const cmp = compareSortKeys(a.keys[i], b.keys[i], keyMeta[i]);
36213
- if (cmp !== 0) return orderBy[i].direction === "ASC" ? cmp : -cmp;
36214
- }
36215
- return 0;
36216
- });
36217
- return decorated.map((d) => d.row);
36325
+ const compare = (a, b) => compareDecoratedRows(a, b, orderBy, keyMeta);
36326
+ decorated.sort(compare);
36327
+ return { rows: decorated, compare };
36328
+ }
36329
+ function compareDecoratedRows(a, b, orderBy, keyMeta) {
36330
+ for (let i = 0; i < orderBy.length; i++) {
36331
+ const cmp = compareSortKeys(a.keys[i], b.keys[i], keyMeta[i]);
36332
+ if (cmp !== 0) return orderBy[i].direction === "ASC" ? cmp : -cmp;
36333
+ }
36334
+ return 0;
36218
36335
  }
36219
36336
  function compareSortKeys(a, b, meta3) {
36220
36337
  if (meta3.orderMap) {
@@ -36259,6 +36376,38 @@ function minChoiceIndex(values, orderMap) {
36259
36376
  }
36260
36377
  return min;
36261
36378
  }
36379
+ function applyWindow(rows, columns, optionOrders, sortKinds) {
36380
+ const windows = columns.filter((column) => column.type === "WINDOW_COL");
36381
+ if (rows.length === 0 || windows.length === 0) return rows;
36382
+ for (const window of windows) {
36383
+ const partitions = /* @__PURE__ */ new Map();
36384
+ for (const row of rows) {
36385
+ const key = JSON.stringify(window.partitionBy.map((ref) => resolveWindowField(row, ref)));
36386
+ const partition = partitions.get(key);
36387
+ if (partition) partition.push(row);
36388
+ else partitions.set(key, [row]);
36389
+ }
36390
+ for (const partition of partitions.values()) {
36391
+ const sortedResult = sortDecoratedRows(partition, window.orderBy, optionOrders, sortKinds);
36392
+ const sorted = sortedResult.rows;
36393
+ let rank = 1;
36394
+ let denseRank = 1;
36395
+ for (let index = 0; index < sorted.length; index++) {
36396
+ if (index > 0 && sortedResult.compare(sorted[index - 1], sorted[index]) !== 0) {
36397
+ rank = index + 1;
36398
+ denseRank++;
36399
+ }
36400
+ const value = window.func === "ROW_NUMBER" ? index + 1 : window.func === "RANK" ? rank : denseRank;
36401
+ sorted[index].row[window.alias] = String(value);
36402
+ }
36403
+ }
36404
+ }
36405
+ return rows;
36406
+ }
36407
+ function resolveWindowField(row, ref) {
36408
+ const name = ref.tableAlias ? `${ref.tableAlias}.${ref.field}` : ref.field;
36409
+ return resolveFieldRef(row, name);
36410
+ }
36262
36411
  function applyLimit(rows, limit, offset) {
36263
36412
  const start = offset ?? 0;
36264
36413
  if (limit === null) return rows.slice(start);
@@ -36349,6 +36498,12 @@ function project(rows, columns, scalarCache, resolveFieldType, sourceColumns) {
36349
36498
  if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
36350
36499
  break;
36351
36500
  }
36501
+ case "WINDOW_COL": {
36502
+ const key = outputKeys?.[colIdx] ?? col.alias;
36503
+ out[key] = row[col.alias] ?? "";
36504
+ if (outputKeys === null && rowIdx === 0) orderedKeys.push(key);
36505
+ break;
36506
+ }
36352
36507
  }
36353
36508
  }
36354
36509
  return out;
@@ -36389,6 +36544,8 @@ function computeOutputKey(col, colIdx, defaultFieldKeys) {
36389
36544
  return col.alias ?? stringFuncDefaultKey(col.expr);
36390
36545
  case "SCALAR_SUBQUERY_COL":
36391
36546
  return col.alias ?? "(subquery)";
36547
+ case "WINDOW_COL":
36548
+ return col.alias;
36392
36549
  case "WILDCARD":
36393
36550
  case "PARENT_WILDCARD":
36394
36551
  throw new Error("internal: computeOutputKey received a wildcard column");
@@ -36457,7 +36614,7 @@ function hasAggregateInStringFuncExpr2(expr) {
36457
36614
  }
36458
36615
  function resolveAggInStringFuncArg(arg, rows, resolveAggSortKind) {
36459
36616
  if (arg.type === "AGG_REF") {
36460
- const value = evalAggregate(arg.func, arg.distinct, arg.arg, rows, resolveAggSortKind);
36617
+ const value = evalAggregate(arg.func, arg.distinct, arg.arg, arg.separator, rows, resolveAggSortKind);
36461
36618
  return typeof value === "number" ? { type: "NUMBER", value } : { type: "STRING", value };
36462
36619
  }
36463
36620
  if (arg.type === "AGG_ARITH") {
@@ -36503,6 +36660,7 @@ function runFullScan(input) {
36503
36660
  rows = applyGroupBy(rows, stmt.groupBy, stmt.columns, aggregateSortKindResolver);
36504
36661
  }
36505
36662
  rows = applyHaving(rows, stmt.having, havingFieldTypeResolver);
36663
+ rows = applyWindow(rows, stmt.columns, optionOrders, sortKinds);
36506
36664
  if (stmt.distinct) {
36507
36665
  rows = applyDistinct(rows, stmt.columns);
36508
36666
  }
@@ -36703,7 +36861,8 @@ function isValidTemporal(value, type) {
36703
36861
  const date5 = new Date(Date.UTC(year, month - 1, day));
36704
36862
  if (date5.getUTCFullYear() !== year || date5.getUTCMonth() !== month - 1 || date5.getUTCDate() !== day) return false;
36705
36863
  if (type === "DATE") return true;
36706
- return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && isValidTemporal(value.slice(11, value.endsWith("Z") ? -1 : value.length - 6), "TIME");
36864
+ const timePart = value.slice(11, value.endsWith("Z") ? -1 : value.length - 6).replace(/\.\d+$/, "");
36865
+ return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && isValidTemporal(timePart, "TIME");
36707
36866
  }
36708
36867
 
36709
36868
  // src/core/dmlValidationCandidates.ts
@@ -36783,6 +36942,8 @@ var SearchAbortedError = class extends Error {
36783
36942
  this.name = "SearchAbortedError";
36784
36943
  }
36785
36944
  };
36945
+ var materializedMetaBySelectResult = /* @__PURE__ */ new WeakMap();
36946
+ var materializedMetaByValidationResult = /* @__PURE__ */ new WeakMap();
36786
36947
  async function execute(sql, client, options = {}) {
36787
36948
  const startedAt = Date.now();
36788
36949
  const stmt = parseSql(sql);
@@ -36928,16 +37089,25 @@ async function executeParsedStatement(stmt, client, options, cacheContext) {
36928
37089
  }
36929
37090
  }
36930
37091
  var TEMP_TABLE_MAX_ROWS = 1e4;
36931
- function appendValidationErrors(tempTables, name, columns, rows, maxRows) {
37092
+ function appendValidationErrors(tempTables, name, columns, rows, maxRows, columnMeta) {
36932
37093
  const current = tempTables.get(name);
36933
- if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]))) {
37094
+ if (current && (current.columns.length !== columns.length || current.columns.some((c, i) => c !== columns[i]) || !materializedColumnMetaEqual(current.columnMeta, columnMeta))) {
36934
37095
  throw new Error(`ArgumentError: validation error table ${name} has a different schema.`);
36935
37096
  }
36936
37097
  const existingRows = current?.rows ?? [];
36937
37098
  if (existingRows.length + rows.length > maxRows) {
36938
37099
  throw new Error(`ArgumentError: temp table ${name} exceeds max rows (${maxRows}).`);
36939
37100
  }
36940
- tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows] });
37101
+ tempTables.set(name, { columns: [...columns], rows: [...existingRows, ...rows], columnMeta });
37102
+ }
37103
+ function materializedColumnMetaEqual(left, right) {
37104
+ if (left === right) return true;
37105
+ if (!left || !right || left.size !== right.size) return false;
37106
+ for (const [column, meta3] of left) {
37107
+ const candidate = right.get(column);
37108
+ if (!candidate || candidate.sortKind !== meta3.sortKind || candidate.fieldType !== meta3.fieldType) return false;
37109
+ }
37110
+ return true;
36941
37111
  }
36942
37112
  var BatchTimeoutError = class extends Error {
36943
37113
  constructor() {
@@ -37099,7 +37269,8 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
37099
37269
  resolvedStmt.validationErrorTable,
37100
37270
  result.columns,
37101
37271
  result.errors,
37102
- options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
37272
+ options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
37273
+ materializedMetaByValidationResult.get(result) ?? /* @__PURE__ */ new Map()
37103
37274
  );
37104
37275
  }
37105
37276
  return { result };
@@ -37123,7 +37294,11 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
37123
37294
  onLimitReached: "error"
37124
37295
  };
37125
37296
  const result = await runSelectLike(resolvedStmt.query, client, materializeOptions, cacheContext, tempTables);
37126
- tempTables.set(resolvedStmt.name, { rows: result.rows, columns: result.columns });
37297
+ tempTables.set(resolvedStmt.name, {
37298
+ rows: result.rows,
37299
+ columns: result.columns,
37300
+ columnMeta: materializedMetaBySelectResult.get(result)
37301
+ });
37127
37302
  return { tempTable: resolvedStmt.name, rowCount: result.rows.length };
37128
37303
  }
37129
37304
  if (stmt.type === "DROP_TEMP_TABLE") {
@@ -37159,9 +37334,9 @@ async function executeBatchStatement(stmt, info, client, options, cacheContext,
37159
37334
  }
37160
37335
  async function runSelectLike(query, client, options, cacheContext, tempTables) {
37161
37336
  if (query.type === "WITH") {
37162
- return executeWith(query, client, options, cacheContext, tempTables);
37337
+ return executeWith(query, client, options, cacheContext, tempTables, true);
37163
37338
  }
37164
- return executeQueryWithCte(query, client, options, tempTables, cacheContext);
37339
+ return executeQueryWithCte(query, client, options, tempTables, cacheContext, true);
37165
37340
  }
37166
37341
  async function runWithDeadline(work, remainingMs) {
37167
37342
  if (remainingMs === null) return work;
@@ -37374,18 +37549,27 @@ function evalAssertArith(node) {
37374
37549
  }
37375
37550
  throw new Error(`ArgumentError: unsupported operand in ASSERT expression: ${node.type}`);
37376
37551
  }
37377
- async function executeSelect(stmt, client, options, cacheContext, cteCache) {
37552
+ async function executeSelect(stmt, client, options, cacheContext, cteCache, captureColumnMeta = false) {
37553
+ let result;
37378
37554
  if (isNoFromSelect(stmt)) {
37379
- return executeNoFromSelect(stmt);
37555
+ result = executeNoFromSelect(stmt);
37556
+ if (captureColumnMeta) {
37557
+ materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
37558
+ }
37559
+ return result;
37380
37560
  }
37381
37561
  await resolveSelectCaseSubqueries(stmt, client, options, cacheContext, cteCache);
37382
37562
  const mode = resolveSelectMode(stmt);
37383
37563
  await validateSelectFieldCodes(stmt, mode, client, cacheContext);
37384
37564
  if (mode === "SIMPLE") {
37385
- return executeSimpleSelect(stmt, client, options, cacheContext);
37565
+ result = await executeSimpleSelect(stmt, client, options, cacheContext);
37386
37566
  } else {
37387
- return executeFullScanSelect(stmt, client, options, cacheContext, cteCache);
37567
+ result = await executeFullScanSelect(stmt, client, options, cacheContext, cteCache);
37388
37568
  }
37569
+ if (captureColumnMeta) {
37570
+ materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(stmt, result.columns, client, cacheContext, cteCache));
37571
+ }
37572
+ return result;
37389
37573
  }
37390
37574
  function isNoFromSelect(stmt) {
37391
37575
  return stmt.from.appId === 0 && stmt.from.cteName === NO_FROM_CTE_NAME;
@@ -37421,6 +37605,11 @@ function validateNoFromColumns(stmt) {
37421
37605
  throw new Error("ArgumentError: field reference is not allowed without FROM.");
37422
37606
  }
37423
37607
  break;
37608
+ case "WINDOW_COL":
37609
+ if (col.partitionBy.length > 0 || col.orderBy.length > 0) {
37610
+ throw new Error("ArgumentError: field reference is not allowed without FROM.");
37611
+ }
37612
+ break;
37424
37613
  default:
37425
37614
  throw new Error(`ArgumentError: ${col.type} is not supported without FROM.`);
37426
37615
  }
@@ -37431,7 +37620,8 @@ function executeNoFromSelect(stmt) {
37431
37620
  throw new Error("ArgumentError: JOIN/WHERE/GROUP BY/HAVING/ORDER BY/DISTINCT are not supported without FROM.");
37432
37621
  }
37433
37622
  validateNoFromColumns(stmt);
37434
- const { rows: projected, columns } = project([{}], stmt.columns);
37623
+ const windowed = applyWindow([{}], stmt.columns);
37624
+ const { rows: projected, columns } = project(windowed, stmt.columns);
37435
37625
  const rows = applyLimit(projected, stmt.limit, stmt.offset);
37436
37626
  return { type: "SELECT", rows, columns, rowCount: rows.length, warnings: [] };
37437
37627
  }
@@ -37709,7 +37899,7 @@ function aggregateSortKind(info) {
37709
37899
  if (info.fieldType === "NUMBER" || info.fieldType === "RECORD_NUMBER") return "number";
37710
37900
  return AGGREGATE_STRING_FIELD_TYPES.has(info.fieldType) ? "string" : void 0;
37711
37901
  }
37712
- async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
37902
+ async function loadAggregateSortKindResolver(stmt, client, cacheContext, materializedTables) {
37713
37903
  const refs = collectSelectAggregateSortRefs(stmt.columns);
37714
37904
  if (refs.length === 0) return void 0;
37715
37905
  const appIds = /* @__PURE__ */ new Set();
@@ -37725,11 +37915,9 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
37725
37915
  } else if (stmt.joins.length === 0) {
37726
37916
  if (stmt.from.cteName === null) appIds.add(stmt.from.appId);
37727
37917
  } else {
37728
- if ([stmt.from, ...stmt.joins.map((join) => join.table)].some((table) => table.cteName !== null)) continue;
37729
37918
  for (const table of physicalTables) appIds.add(table.appId);
37730
37919
  }
37731
37920
  }
37732
- if (appIds.size === 0) return void 0;
37733
37921
  const fieldInfosByApp = new Map(
37734
37922
  await Promise.all([...appIds].map(async (appId) => {
37735
37923
  const infos = await getFieldsCached(appId, client, cacheContext);
@@ -37744,17 +37932,28 @@ async function loadAggregateSortKindResolver(stmt, client, cacheContext) {
37744
37932
  info = fieldInfosByApp.get(stmt.from.appId)?.get(ref.field);
37745
37933
  } else {
37746
37934
  const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
37747
- if (!table || table.cteName !== null) return void 0;
37935
+ if (!table) return void 0;
37936
+ if (table.cteName !== null) {
37937
+ return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field)?.sortKind;
37938
+ }
37748
37939
  info = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
37749
37940
  }
37750
37941
  } else if (stmt.joins.length === 0) {
37751
- if (stmt.from.cteName !== null) return void 0;
37942
+ if (stmt.from.cteName !== null) {
37943
+ return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field)?.sortKind;
37944
+ }
37752
37945
  info = fieldInfosByApp.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
37753
37946
  } else {
37754
- if (tables.some((table) => table.cteName !== null)) return void 0;
37755
- const matches = physicalTables.map((table) => fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field))).filter((candidate) => candidate !== void 0);
37947
+ const matches = tables.flatMap((table) => {
37948
+ if (table.cteName !== null) {
37949
+ const materialized = materializedTables?.get(table.cteName);
37950
+ return materialized?.columns.includes(ref.field) ? [materialized.columnMeta?.get(ref.field)?.sortKind] : [];
37951
+ }
37952
+ const candidate = fieldInfosByApp.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
37953
+ return candidate ? [aggregateSortKind(candidate)] : [];
37954
+ });
37756
37955
  if (matches.length !== 1) return void 0;
37757
- info = matches[0];
37956
+ return matches[0];
37758
37957
  }
37759
37958
  return info ? aggregateSortKind(info) : void 0;
37760
37959
  };
@@ -37763,6 +37962,108 @@ function fieldCodeForTypeLookup(table, field) {
37763
37962
  if (table.subtableCode && field.startsWith("_p.")) return field.slice(3);
37764
37963
  return field;
37765
37964
  }
37965
+ function materializedMetaFromFieldInfo(info) {
37966
+ return { sortKind: aggregateSortKind(info), fieldType: info.fieldType };
37967
+ }
37968
+ function selectNeedsSourceColumnMeta(stmt) {
37969
+ return stmt.columns.some(
37970
+ (column) => column.type === "FIELD" || column.type === "WILDCARD" || column.type === "PARENT_WILDCARD" || column.type === "AGGREGATE" && (column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF"
37971
+ );
37972
+ }
37973
+ async function inferSelectColumnMeta(stmt, outputColumns, client, cacheContext, materializedTables) {
37974
+ const physicalInfos = /* @__PURE__ */ new Map();
37975
+ if (selectNeedsSourceColumnMeta(stmt)) {
37976
+ await Promise.all(physicalSelectTables(stmt).map(async (table) => {
37977
+ if (physicalInfos.has(table.appId)) return;
37978
+ const infos = await getFieldsCached(table.appId, client, cacheContext);
37979
+ physicalInfos.set(table.appId, new Map(infos.map((info) => [info.code, info])));
37980
+ }));
37981
+ }
37982
+ const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
37983
+ const resolveField2 = (ref) => {
37984
+ if (ref.tableAlias !== null) {
37985
+ if (ref.tableAlias === "_p" && stmt.from.subtableCode && stmt.from.cteName === null) {
37986
+ const info2 = physicalInfos.get(stmt.from.appId)?.get(ref.field);
37987
+ return info2 ? materializedMetaFromFieldInfo(info2) : void 0;
37988
+ }
37989
+ const table = tables.find((candidate) => candidate.alias === ref.tableAlias);
37990
+ if (!table) return void 0;
37991
+ if (table.cteName !== null) return materializedTables?.get(table.cteName)?.columnMeta?.get(ref.field);
37992
+ const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
37993
+ return info ? materializedMetaFromFieldInfo(info) : void 0;
37994
+ }
37995
+ if (stmt.joins.length === 0) {
37996
+ if (stmt.from.cteName !== null) return materializedTables?.get(stmt.from.cteName)?.columnMeta?.get(ref.field);
37997
+ const info = physicalInfos.get(stmt.from.appId)?.get(fieldCodeForTypeLookup(stmt.from, ref.field));
37998
+ return info ? materializedMetaFromFieldInfo(info) : void 0;
37999
+ }
38000
+ const matches = tables.flatMap((table) => {
38001
+ if (table.cteName !== null) {
38002
+ const materialized = materializedTables?.get(table.cteName);
38003
+ if (!materialized?.columns.includes(ref.field)) return [];
38004
+ return [materialized.columnMeta?.get(ref.field)];
38005
+ }
38006
+ const info = physicalInfos.get(table.appId)?.get(fieldCodeForTypeLookup(table, ref.field));
38007
+ return info ? [materializedMetaFromFieldInfo(info)] : [];
38008
+ });
38009
+ return matches.length === 1 ? matches[0] : void 0;
38010
+ };
38011
+ const inferred = /* @__PURE__ */ new Map();
38012
+ const hasWildcard = stmt.columns.some((column) => column.type === "WILDCARD" || column.type === "PARENT_WILDCARD");
38013
+ if (stmt.columns.length === 1 && (stmt.columns[0].type === "WILDCARD" || stmt.columns[0].type === "PARENT_WILDCARD")) {
38014
+ for (const output of outputColumns) {
38015
+ const meta3 = resolveField2(aggregateFieldRef(output));
38016
+ if (meta3) inferred.set(output, meta3);
38017
+ }
38018
+ return inferred;
38019
+ }
38020
+ if (hasWildcard) {
38021
+ for (const output of outputColumns) {
38022
+ const meta3 = resolveField2(aggregateFieldRef(output));
38023
+ if (meta3) inferred.set(output, meta3);
38024
+ }
38025
+ }
38026
+ const explicitColumns = stmt.columns.filter(
38027
+ (column) => column.type !== "WILDCARD" && column.type !== "PARENT_WILDCARD"
38028
+ );
38029
+ explicitColumns.forEach((column, index) => {
38030
+ const output = hasWildcard ? "alias" in column && column.alias ? column.alias : void 0 : outputColumns[index];
38031
+ if (!output) return;
38032
+ let meta3;
38033
+ if (column.type === "FIELD") {
38034
+ meta3 = resolveField2(aggregateFieldRef(column.field));
38035
+ } else if (column.type === "AGGREGATE") {
38036
+ if (column.func === "GROUP_CONCAT") {
38037
+ meta3 = { sortKind: "string" };
38038
+ } else if (column.func === "COUNT" || column.func === "SUM" || column.func === "AVG") {
38039
+ meta3 = { sortKind: "number" };
38040
+ } else if ((column.func === "MIN" || column.func === "MAX") && column.arg.type === "FIELD_REF") {
38041
+ const source = resolveField2(aggregateFieldRef(column.arg.field));
38042
+ if (source?.sortKind) meta3 = { sortKind: source.sortKind };
38043
+ }
38044
+ } else if (column.type === "ARITH_AGG_COL" || column.type === "ARITH_COL") {
38045
+ meta3 = { sortKind: "number" };
38046
+ } else if (column.type === "LITERAL_COL") {
38047
+ meta3 = { sortKind: "string" };
38048
+ } else if (column.type === "WINDOW_COL") {
38049
+ meta3 = { sortKind: "number" };
38050
+ }
38051
+ if (meta3) inferred.set(output, meta3);
38052
+ });
38053
+ return inferred;
38054
+ }
38055
+ function mergeUnionColumnMeta(left, right) {
38056
+ const leftMeta = materializedMetaBySelectResult.get(left);
38057
+ const rightMeta = materializedMetaBySelectResult.get(right);
38058
+ const merged = /* @__PURE__ */ new Map();
38059
+ left.columns.forEach((column, index) => {
38060
+ const a = leftMeta?.get(column);
38061
+ const rightColumn = right.columns[index];
38062
+ const b = rightColumn === void 0 ? void 0 : rightMeta?.get(rightColumn);
38063
+ if (a && b && a.sortKind === b.sortKind && a.fieldType === b.fieldType) merged.set(column, a);
38064
+ });
38065
+ return merged;
38066
+ }
37766
38067
  function buildSelectFieldTypeResolvers(stmt, fieldTypesByApp) {
37767
38068
  const tables = [stmt.from, ...stmt.joins.map((join) => join.table)];
37768
38069
  const physicalTables = tables.filter((table) => table.cteName === null);
@@ -37807,7 +38108,7 @@ async function executeFullScanSelect(stmt, client, options, cacheContext, cteCac
37807
38108
  const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
37808
38109
  loadTypedPushdownMeta(stmt, client, cacheContext),
37809
38110
  loadTypedInFieldTypes(stmt, client, cacheContext),
37810
- loadAggregateSortKindResolver(stmt, client, cacheContext)
38111
+ loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
37811
38112
  ]);
37812
38113
  const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
37813
38114
  const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
@@ -37927,9 +38228,9 @@ function deduplicateRows(rows, columns) {
37927
38228
  return true;
37928
38229
  });
37929
38230
  }
37930
- async function executeWith(stmt, client, options, cacheContext, seed) {
38231
+ async function executeWith(stmt, client, options, cacheContext, seed, captureColumnMeta = false) {
37931
38232
  if ((seed == null || seed.size === 0) && canInlineSingleCte(stmt)) {
37932
- return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext);
38233
+ return executeSelect(buildInlinedQuery(stmt), client, options, cacheContext, void 0, captureColumnMeta);
37933
38234
  }
37934
38235
  const cteCache = new Map(seed ?? []);
37935
38236
  for (const cte of stmt.ctes) {
@@ -37939,17 +38240,21 @@ async function executeWith(stmt, client, options, cacheContext, seed) {
37939
38240
  } else if (cte.query.type === "DESCRIBE") {
37940
38241
  result = await executeDescribe(cte.query, client, cacheContext);
37941
38242
  } else {
37942
- result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext);
38243
+ result = await executeQueryWithCte(cte.query, client, options, cteCache, cacheContext, true);
37943
38244
  }
37944
- cteCache.set(cte.name, { rows: result.rows, columns: result.columns });
38245
+ cteCache.set(cte.name, {
38246
+ rows: result.rows,
38247
+ columns: result.columns,
38248
+ columnMeta: materializedMetaBySelectResult.get(result)
38249
+ });
37945
38250
  }
37946
- return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext);
38251
+ return executeQueryWithCte(stmt.query, client, options, cteCache, cacheContext, captureColumnMeta);
37947
38252
  }
37948
- async function executeQueryWithCte(query, client, options, cteCache, cacheContext) {
38253
+ async function executeQueryWithCte(query, client, options, cteCache, cacheContext, captureColumnMeta = false) {
37949
38254
  if (query.type === "UNION") {
37950
38255
  const [leftResult, rightResult] = await Promise.all([
37951
- executeQueryWithCte(query.left, client, options, cteCache, cacheContext),
37952
- executeQueryWithCte(query.right, client, options, cteCache, cacheContext)
38256
+ executeQueryWithCte(query.left, client, options, cteCache, cacheContext, captureColumnMeta),
38257
+ executeQueryWithCte(query.right, client, options, cteCache, cacheContext, captureColumnMeta)
37953
38258
  ]);
37954
38259
  const leftCols = leftResult.columns;
37955
38260
  const rightCols = rightResult.columns;
@@ -37962,13 +38267,21 @@ async function executeQueryWithCte(query, client, options, cteCache, cacheContex
37962
38267
  });
37963
38268
  const combined = [...leftResult.rows, ...remapped];
37964
38269
  const rows = query.all ? combined : deduplicateRows(combined, leftCols);
37965
- return { type: "SELECT", rows, columns: leftCols, rowCount: rows.length };
38270
+ const result2 = { type: "SELECT", rows, columns: leftCols, rowCount: rows.length };
38271
+ if (captureColumnMeta) {
38272
+ materializedMetaBySelectResult.set(result2, mergeUnionColumnMeta(leftResult, rightResult));
38273
+ }
38274
+ return result2;
37966
38275
  }
37967
38276
  const hasCteRef = query.from.cteName != null && query.from.cteName !== NO_FROM_CTE_NAME || query.joins.some((j) => j.table.cteName != null);
37968
38277
  if (!hasCteRef) {
37969
- return executeSelect(query, client, options, cacheContext, cteCache);
38278
+ return executeSelect(query, client, options, cacheContext, cteCache, captureColumnMeta);
37970
38279
  }
37971
- return executeFullScanWithCte(query, client, options, cteCache, cacheContext);
38280
+ const result = await executeFullScanWithCte(query, client, options, cteCache, cacheContext);
38281
+ if (captureColumnMeta) {
38282
+ materializedMetaBySelectResult.set(result, await inferSelectColumnMeta(query, result.columns, client, cacheContext, cteCache));
38283
+ }
38284
+ return result;
37972
38285
  }
37973
38286
  async function executeFullScanWithCte(stmt, client, options, cteCache, cacheContext) {
37974
38287
  const maxRecords2 = options.maxRecords ?? 1e4;
@@ -37982,7 +38295,7 @@ async function executeFullScanWithCte(stmt, client, options, cteCache, cacheCont
37982
38295
  const [pushdownMeta, typedInFieldTypes, aggregateSortKindResolver] = await Promise.all([
37983
38296
  loadTypedPushdownMeta(stmt, client, cacheContext),
37984
38297
  loadTypedInFieldTypes(stmt, client, cacheContext),
37985
- loadAggregateSortKindResolver(stmt, client, cacheContext)
38298
+ loadAggregateSortKindResolver(stmt, client, cacheContext, cteCache)
37986
38299
  ]);
37987
38300
  const fieldTypeResolvers = buildSelectFieldTypeResolvers(stmt, typedInFieldTypes);
37988
38301
  const pushdownPlan = buildKlikePushdownPlan(stmt, pushdownMeta);
@@ -38319,7 +38632,10 @@ async function getSortKindMapByApp(appId, client, cacheContext) {
38319
38632
  return map2;
38320
38633
  }
38321
38634
  async function buildOrderByMetaForSelect(stmt, client, cacheContext) {
38322
- if (stmt.orderBy.length === 0) {
38635
+ const hasWindowOrderBy = stmt.columns.some(
38636
+ (column) => column.type === "WINDOW_COL" && column.orderBy.length > 0
38637
+ );
38638
+ if (stmt.orderBy.length === 0 && !hasWindowOrderBy) {
38323
38639
  return { optionOrders: /* @__PURE__ */ new Map(), sortKinds: /* @__PURE__ */ new Map() };
38324
38640
  }
38325
38641
  const [optionOrders, sortKinds] = await Promise.all([
@@ -38460,7 +38776,23 @@ async function prepareDmlValidation(stmt, client, options, cacheContext, tempTab
38460
38776
  errors,
38461
38777
  ...stmt.validationErrorTable ? { errTable: stmt.validationErrorTable } : stmt.onErrorSkip && stmt.errorTable ? { errTable: stmt.errorTable } : {}
38462
38778
  };
38463
- return { result, candidates, invalidRowNumbers };
38779
+ const columnMeta = /* @__PURE__ */ new Map();
38780
+ for (const column of payloadFields) {
38781
+ if (column === "$id") {
38782
+ columnMeta.set(column, { sortKind: "number", fieldType: "RECORD_NUMBER" });
38783
+ continue;
38784
+ }
38785
+ const info = infoByCode.get(column);
38786
+ if (info) columnMeta.set(column, materializedMetaFromFieldInfo(info));
38787
+ }
38788
+ columnMeta.set("$err_statement", { sortKind: "number" });
38789
+ columnMeta.set("$err_operation", { sortKind: "string" });
38790
+ columnMeta.set("$err_row", { sortKind: "number" });
38791
+ columnMeta.set("$err_field", { sortKind: "string" });
38792
+ columnMeta.set("$err_code", { sortKind: "string" });
38793
+ columnMeta.set("$err_message", { sortKind: "string" });
38794
+ materializedMetaByValidationResult.set(result, columnMeta);
38795
+ return { result, candidates, invalidRowNumbers, columnMeta };
38464
38796
  }
38465
38797
  async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTables, statementNumber) {
38466
38798
  const prepared = await prepareDmlValidation(
@@ -38478,7 +38810,8 @@ async function executeOnErrorSkip(stmt, client, options, cacheContext, tempTable
38478
38810
  errTable,
38479
38811
  prepared.result.columns,
38480
38812
  prepared.result.errors,
38481
- options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS
38813
+ options.tempTableMaxRows ?? TEMP_TABLE_MAX_ROWS,
38814
+ prepared.columnMeta
38482
38815
  );
38483
38816
  const rejectLimit = stmt.rejectLimit ?? null;
38484
38817
  if (rejectLimit !== null && prepared.result.invalidRows > rejectLimit) {
@@ -39764,6 +40097,8 @@ function collectFullScanReasons(stmt) {
39764
40097
  r.push("DISTINCT \u3042\u308A");
39765
40098
  if (stmt.columns.some((c) => c.type === "AGGREGATE" || c.type === "ARITH_AGG_COL"))
39766
40099
  r.push("\u96C6\u8A08\u95A2\u6570\uFF08COUNT / SUM \u7B49\uFF09\u3042\u308A");
40100
+ if (stmt.columns.some((c) => c.type === "WINDOW_COL"))
40101
+ r.push("\u30A6\u30A3\u30F3\u30C9\u30A6\u95A2\u6570\u3042\u308A");
39767
40102
  if (stmt.columns.some((c) => c.type === "SCALAR_SUBQUERY_COL"))
39768
40103
  r.push("SELECT \u5217\u306B\u30B9\u30AB\u30E9\u30FC\u30B5\u30D6\u30AF\u30A8\u30EA");
39769
40104
  if (whereRequiresJsEval(stmt.where))
@@ -42219,7 +42554,7 @@ Options:
42219
42554
  -h, --help Show help
42220
42555
  `);
42221
42556
  }
42222
- var SERVER_VERSION = true ? "2.14.1" : "0.0.0-dev";
42557
+ var SERVER_VERSION = true ? "2.16.0" : "0.0.0-dev";
42223
42558
  function createServer(args) {
42224
42559
  const server = new McpServer({
42225
42560
  name: "ksql-mcp",