prisma-sql 1.48.0 → 1.49.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.
@@ -56,7 +56,7 @@ var require_package = __commonJS({
56
56
  "package.json"(exports$1, module) {
57
57
  module.exports = {
58
58
  name: "prisma-sql",
59
- version: "1.48.0",
59
+ version: "1.49.0",
60
60
  description: "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
61
61
  main: "dist/index.cjs",
62
62
  module: "dist/index.js",
@@ -95,7 +95,7 @@ var require_package = __commonJS({
95
95
  "prisma:reset": "npx prisma db push --force-reset --skip-generate --schema=tests/prisma/schema.prisma",
96
96
  prepublishOnly: "npm run build",
97
97
  "sonar-cli": "sonar-scanner -Dsonar.projectKey=prisma-sql -Dsonar.sources=./src -Dsonar.host.url=http://localhost:9000 -Dsonar.login=sqp_9fe07460d0aa83f711d0edf4f317f05019d0613b",
98
- sonar: "yarn sonar-cli && npx tsx scripts/sonar.ts"
98
+ sonar: "npm run sonar-cli && npx tsx scripts/sonar.ts"
99
99
  },
100
100
  keywords: [
101
101
  "prisma",
@@ -153,6 +153,7 @@ var require_package = __commonJS({
153
153
  });
154
154
 
155
155
  // src/builder/shared/constants.ts
156
+ var IS_PRODUCTION = process.env.NODE_ENV === "production";
156
157
  var SQL_SEPARATORS = Object.freeze({
157
158
  FIELD_LIST: ", ",
158
159
  CONDITION_AND: " AND ",
@@ -595,6 +596,15 @@ function createError(message, ctx, code = "VALIDATION_ERROR") {
595
596
 
596
597
  // src/builder/shared/model-field-cache.ts
597
598
  var MODEL_CACHE = /* @__PURE__ */ new WeakMap();
599
+ function quote(id) {
600
+ const needsQuoting2 = !/^[a-z_][a-z0-9_]*$/.test(id) || /^(select|from|where|having|order|group|limit|offset|join|inner|left|right|outer|cross|full|and|or|not|by|as|on|union|intersect|except|case|when|then|else|end|user|users|table|column|index|values|in|like|between|is|exists|null|true|false|all|any|some|update|insert|delete|create|drop|alter|truncate|grant|revoke|exec|execute)$/i.test(
601
+ id
602
+ );
603
+ if (needsQuoting2) {
604
+ return `"${id.replace(/"/g, '""')}"`;
605
+ }
606
+ return id;
607
+ }
598
608
  function ensureFullCache(model) {
599
609
  let cache = MODEL_CACHE.get(model);
600
610
  if (!cache) {
@@ -602,6 +612,8 @@ function ensureFullCache(model) {
602
612
  const scalarFields = /* @__PURE__ */ new Set();
603
613
  const relationFields = /* @__PURE__ */ new Set();
604
614
  const columnMap = /* @__PURE__ */ new Map();
615
+ const fieldByName = /* @__PURE__ */ new Map();
616
+ const quotedColumns = /* @__PURE__ */ new Map();
605
617
  for (const f of model.fields) {
606
618
  const info = {
607
619
  name: f.name,
@@ -611,14 +623,24 @@ function ensureFullCache(model) {
611
623
  isRequired: !!f.isRequired
612
624
  };
613
625
  fieldInfo.set(f.name, info);
626
+ fieldByName.set(f.name, f);
614
627
  if (info.isRelation) {
615
628
  relationFields.add(f.name);
616
629
  } else {
617
630
  scalarFields.add(f.name);
618
- columnMap.set(f.name, info.dbName);
631
+ const dbName = info.dbName;
632
+ columnMap.set(f.name, dbName);
633
+ quotedColumns.set(f.name, quote(dbName));
619
634
  }
620
635
  }
621
- cache = { fieldInfo, scalarFields, relationFields, columnMap };
636
+ cache = {
637
+ fieldInfo,
638
+ scalarFields,
639
+ relationFields,
640
+ columnMap,
641
+ fieldByName,
642
+ quotedColumns
643
+ };
622
644
  MODEL_CACHE.set(model, cache);
623
645
  }
624
646
  return cache;
@@ -635,6 +657,9 @@ function getRelationFieldSet(model) {
635
657
  function getColumnMap(model) {
636
658
  return ensureFullCache(model).columnMap;
637
659
  }
660
+ function getQuotedColumn(model, fieldName) {
661
+ return ensureFullCache(model).quotedColumns.get(fieldName);
662
+ }
638
663
 
639
664
  // src/builder/shared/validators/sql-validators.ts
640
665
  function isValidWhereClause(clause) {
@@ -650,6 +675,7 @@ function sqlPreview(sql) {
650
675
  return `${s.slice(0, 160)}...`;
651
676
  }
652
677
  function validateSelectQuery(sql) {
678
+ if (IS_PRODUCTION) return;
653
679
  if (!hasValidContent(sql)) {
654
680
  throw new Error("CRITICAL: Generated empty SQL query");
655
681
  }
@@ -708,6 +734,7 @@ function assertNoGapsDollar(scan, rangeMin, rangeMax, sql) {
708
734
  }
709
735
  }
710
736
  function validateParamConsistency(sql, params) {
737
+ if (IS_PRODUCTION) return;
711
738
  const paramLen = params.length;
712
739
  const scan = scanDollarPlaceholders(sql, paramLen);
713
740
  if (paramLen === 0) {
@@ -744,6 +771,7 @@ function countQuestionMarkPlaceholders(sql) {
744
771
  return count;
745
772
  }
746
773
  function validateQuestionMarkConsistency(sql, params) {
774
+ if (IS_PRODUCTION) return;
747
775
  const expected = params.length;
748
776
  const found = countQuestionMarkPlaceholders(sql);
749
777
  if (expected !== found) {
@@ -753,6 +781,7 @@ function validateQuestionMarkConsistency(sql, params) {
753
781
  }
754
782
  }
755
783
  function validateParamConsistencyByDialect(sql, params, dialect) {
784
+ if (IS_PRODUCTION) return;
756
785
  if (dialect === "postgres") {
757
786
  validateParamConsistency(sql, params);
758
787
  return;
@@ -914,7 +943,7 @@ function assertSafeQualifiedName(tableRef) {
914
943
  }
915
944
  }
916
945
  }
917
- function quote(id) {
946
+ function quote2(id) {
918
947
  if (isEmptyString(id)) {
919
948
  throw new Error("quote: identifier is required and cannot be empty");
920
949
  }
@@ -934,17 +963,14 @@ function resolveColumnName(model, fieldName) {
934
963
  return columnMap.get(fieldName) || fieldName;
935
964
  }
936
965
  function quoteColumn(model, fieldName) {
937
- return quote(resolveColumnName(model, fieldName));
966
+ if (!model) return quote2(fieldName);
967
+ const cached = getQuotedColumn(model, fieldName);
968
+ return cached || quote2(fieldName);
938
969
  }
939
970
  function col(alias, field, model) {
940
- if (isEmptyString(alias)) {
941
- throw new Error("col: alias is required and cannot be empty");
942
- }
943
- if (isEmptyString(field)) {
944
- throw new Error("col: field is required and cannot be empty");
945
- }
946
- const columnName = resolveColumnName(model, field);
947
- return `${alias}.${quote(columnName)}`;
971
+ const columnName = model ? getColumnMap(model).get(field) || field : field;
972
+ const quoted = model ? getQuotedColumn(model, field) || quote2(columnName) : quote2(columnName);
973
+ return alias + "." + quoted;
948
974
  }
949
975
  function colWithAlias(alias, field, model) {
950
976
  if (isEmptyString(alias)) {
@@ -954,9 +980,9 @@ function colWithAlias(alias, field, model) {
954
980
  throw new Error("colWithAlias: field is required and cannot be empty");
955
981
  }
956
982
  const columnName = resolveColumnName(model, field);
957
- const columnRef = `${alias}.${quote(columnName)}`;
983
+ const columnRef = alias + "." + (model ? getQuotedColumn(model, field) || quote2(columnName) : quote2(columnName));
958
984
  if (columnName !== field) {
959
- return `${columnRef} AS ${quote(field)}`;
985
+ return columnRef + " AS " + quote2(field);
960
986
  }
961
987
  return columnRef;
962
988
  }
@@ -979,7 +1005,7 @@ function buildTableReference(schemaName, tableName, dialect) {
979
1005
  }
980
1006
  const d = dialect != null ? dialect : "postgres";
981
1007
  if (d === "sqlite") {
982
- return quote(tableName);
1008
+ return quote2(tableName);
983
1009
  }
984
1010
  if (isEmptyString(schemaName)) {
985
1011
  throw new Error(
@@ -1307,6 +1333,7 @@ function assertNumericField(model, fieldName, context) {
1307
1333
 
1308
1334
  // src/builder/pagination.ts
1309
1335
  var MAX_LIMIT_OFFSET = 2147483647;
1336
+ var ORDER_BY_ALLOWED_KEYS = /* @__PURE__ */ new Set(["sort", "nulls"]);
1310
1337
  function parseDirectionRaw(raw, errorLabel) {
1311
1338
  const s = String(raw).toLowerCase();
1312
1339
  if (s === "asc" || s === "desc") return s;
@@ -1325,9 +1352,8 @@ function requireOrderByObject(v, errorPrefix) {
1325
1352
  return v;
1326
1353
  }
1327
1354
  function assertAllowedOrderByKeys(obj, fieldName) {
1328
- const allowed = /* @__PURE__ */ new Set(["sort", "nulls"]);
1329
1355
  for (const k of Object.keys(obj)) {
1330
- if (!allowed.has(k)) {
1356
+ if (!ORDER_BY_ALLOWED_KEYS.has(k)) {
1331
1357
  throw new Error(
1332
1358
  fieldName ? `Unsupported orderBy key '${k}' for field '${fieldName}'` : `Unsupported orderBy key '${k}'`
1333
1359
  );
@@ -1394,17 +1420,17 @@ function buildOrderByFragment(entries, alias, dialect, model) {
1394
1420
  const c = col(alias, e.field, model);
1395
1421
  if (dialect === "postgres") {
1396
1422
  const nulls = isNotNullish(e.nulls) ? ` NULLS ${e.nulls.toUpperCase()}` : "";
1397
- out.push(`${c} ${dir}${nulls}`);
1423
+ out.push(c + " " + dir + nulls);
1398
1424
  continue;
1399
1425
  }
1400
1426
  if (isNotNullish(e.nulls)) {
1401
1427
  const isNullExpr = `(${c} IS NULL)`;
1402
1428
  const nullRankDir = e.nulls === "first" ? "DESC" : "ASC";
1403
- out.push(`${isNullExpr} ${nullRankDir}`);
1404
- out.push(`${c} ${dir}`);
1429
+ out.push(isNullExpr + " " + nullRankDir);
1430
+ out.push(c + " " + dir);
1405
1431
  continue;
1406
1432
  }
1407
- out.push(`${c} ${dir}`);
1433
+ out.push(c + " " + dir);
1408
1434
  }
1409
1435
  return out.join(SQL_SEPARATORS.ORDER_BY);
1410
1436
  }
@@ -1413,79 +1439,47 @@ function defaultNullsFor(dialect, direction) {
1413
1439
  return direction === "asc" ? "first" : "last";
1414
1440
  }
1415
1441
  function ensureCursorFieldsInOrder(orderEntries, cursorEntries) {
1416
- const existing = /* @__PURE__ */ new Map();
1417
- for (const e of orderEntries) existing.set(e.field, e);
1418
- const out = [...orderEntries];
1419
- for (const [field] of cursorEntries) {
1442
+ if (cursorEntries.length === 0) return orderEntries;
1443
+ const existing = /* @__PURE__ */ new Set();
1444
+ for (let i = 0; i < orderEntries.length; i++)
1445
+ existing.add(orderEntries[i].field);
1446
+ let out = null;
1447
+ for (let i = 0; i < cursorEntries.length; i++) {
1448
+ const field = cursorEntries[i][0];
1420
1449
  if (!existing.has(field)) {
1450
+ if (!out) out = orderEntries.slice();
1421
1451
  out.push({ field, direction: "asc" });
1422
- existing.set(field, out[out.length - 1]);
1452
+ existing.add(field);
1423
1453
  }
1424
1454
  }
1425
- return out;
1455
+ return out != null ? out : orderEntries;
1426
1456
  }
1427
1457
  function buildCursorFilterParts(cursor, cursorAlias, params, model) {
1428
- const entries = Object.entries(cursor);
1429
- if (entries.length === 0)
1430
- throw new Error("cursor must have at least one field");
1431
- const placeholdersByField = /* @__PURE__ */ new Map();
1432
1458
  const parts = [];
1433
- for (const [field, value] of entries) {
1434
- const c = `${cursorAlias}.${quoteColumn(model, field)}`;
1459
+ for (const field in cursor) {
1460
+ if (!Object.prototype.hasOwnProperty.call(cursor, field)) continue;
1461
+ const value = cursor[field];
1462
+ const c = cursorAlias + "." + quoteColumn(model, field);
1435
1463
  if (value === null) {
1436
- parts.push(`${c} IS NULL`);
1464
+ parts.push(c + " IS NULL");
1437
1465
  continue;
1438
1466
  }
1439
1467
  const ph = addAutoScoped(params, value, `cursor.filter.${field}`);
1440
- placeholdersByField.set(field, ph);
1441
- parts.push(`${c} = ${ph}`);
1468
+ parts.push(c + " = " + ph);
1442
1469
  }
1443
1470
  return {
1444
- whereSql: parts.length === 1 ? parts[0] : `(${parts.join(" AND ")})`,
1445
- placeholdersByField
1471
+ whereSql: parts.length === 1 ? parts[0] : "(" + parts.join(" AND ") + ")"
1446
1472
  };
1447
1473
  }
1448
- function buildCursorEqualityExpr(columnExpr, valueExpr) {
1449
- return `((${valueExpr} IS NULL AND ${columnExpr} IS NULL) OR (${valueExpr} IS NOT NULL AND ${columnExpr} = ${valueExpr}))`;
1474
+ function buildCursorEqualityExpr(columnExpr, cursorField) {
1475
+ return `((${cursorField} IS NULL AND ${columnExpr} IS NULL) OR (${cursorField} IS NOT NULL AND ${columnExpr} = ${cursorField}))`;
1450
1476
  }
1451
- function buildCursorInequalityExpr(columnExpr, direction, nulls, valueExpr) {
1477
+ function buildCursorInequalityExpr(columnExpr, direction, nulls, cursorField) {
1452
1478
  const op = direction === "asc" ? ">" : "<";
1453
1479
  if (nulls === "first") {
1454
- return `(CASE WHEN ${valueExpr} IS NULL THEN (${columnExpr} IS NOT NULL) ELSE (${columnExpr} ${op} ${valueExpr}) END)`;
1455
- }
1456
- return `(CASE WHEN ${valueExpr} IS NULL THEN 0=1 ELSE ((${columnExpr} ${op} ${valueExpr}) OR (${columnExpr} IS NULL)) END)`;
1457
- }
1458
- function buildOuterCursorMatch(cursor, outerAlias, placeholdersByField, params, model) {
1459
- const parts = [];
1460
- for (const [field, value] of Object.entries(cursor)) {
1461
- const c = col(outerAlias, field, model);
1462
- if (value === null) {
1463
- parts.push(`${c} IS NULL`);
1464
- continue;
1465
- }
1466
- const existing = placeholdersByField.get(field);
1467
- if (typeof existing === "string" && existing.length > 0) {
1468
- parts.push(`${c} = ${existing}`);
1469
- continue;
1470
- }
1471
- const ph = addAutoScoped(params, value, `cursor.outerMatch.${field}`);
1472
- parts.push(`${c} = ${ph}`);
1473
- }
1474
- return parts.length === 1 ? parts[0] : `(${parts.join(" AND ")})`;
1475
- }
1476
- function buildOrderEntries(orderBy) {
1477
- const normalized = normalizeOrderByInput(orderBy, parseOrderByValue);
1478
- const entries = [];
1479
- for (const item of normalized) {
1480
- for (const [field, value] of Object.entries(item)) {
1481
- if (typeof value === "string") {
1482
- entries.push({ field, direction: value });
1483
- } else {
1484
- entries.push({ field, direction: value.direction, nulls: value.nulls });
1485
- }
1486
- }
1480
+ return `(CASE WHEN ${cursorField} IS NULL THEN (${columnExpr} IS NOT NULL) ELSE (${columnExpr} ${op} ${cursorField}) END)`;
1487
1481
  }
1488
- return entries;
1482
+ return `(CASE WHEN ${cursorField} IS NULL THEN 0=1 ELSE ((${columnExpr} ${op} ${cursorField}) OR (${columnExpr} IS NULL)) END)`;
1489
1483
  }
1490
1484
  function buildCursorCteSelectList(cursorEntries, orderEntries, model) {
1491
1485
  const seen = /* @__PURE__ */ new Set();
@@ -1507,8 +1501,7 @@ function buildCursorCteSelectList(cursorEntries, orderEntries, model) {
1507
1501
  }
1508
1502
  function truncateIdent(name, maxLen) {
1509
1503
  const s = String(name);
1510
- if (s.length <= maxLen) return s;
1511
- return s.slice(0, maxLen);
1504
+ return s.length <= maxLen ? s : s.slice(0, maxLen);
1512
1505
  }
1513
1506
  function buildCursorNames(outerAlias) {
1514
1507
  const maxLen = 63;
@@ -1525,15 +1518,25 @@ function buildCursorNames(outerAlias) {
1525
1518
  }
1526
1519
  function assertCursorAndOrderFieldsScalar(model, cursor, orderEntries) {
1527
1520
  if (!model) return;
1528
- for (const k of Object.keys(cursor)) assertScalarField(model, k, "cursor");
1529
- for (const e of orderEntries) assertScalarField(model, e.field, "orderBy");
1521
+ for (const k in cursor) {
1522
+ if (!Object.prototype.hasOwnProperty.call(cursor, k)) continue;
1523
+ assertScalarField(model, k, "cursor");
1524
+ }
1525
+ for (const e of orderEntries) {
1526
+ assertScalarField(model, e.field, "orderBy");
1527
+ }
1530
1528
  }
1531
1529
  function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect, model) {
1532
1530
  var _a;
1533
1531
  assertSafeTableRef(tableName);
1534
1532
  assertSafeAlias(alias);
1535
1533
  const d = dialect != null ? dialect : getGlobalDialect();
1536
- const cursorEntries = Object.entries(cursor);
1534
+ const cursorEntries = [];
1535
+ for (const k in cursor) {
1536
+ if (Object.prototype.hasOwnProperty.call(cursor, k)) {
1537
+ cursorEntries.push([k, cursor[k]]);
1538
+ }
1539
+ }
1537
1540
  if (cursorEntries.length === 0)
1538
1541
  throw new Error("cursor must have at least one field");
1539
1542
  const { cteName, srcAlias } = buildCursorNames(alias);
@@ -1554,48 +1557,51 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
1554
1557
  orderEntries = ensureCursorFieldsInOrder(orderEntries, cursorEntries);
1555
1558
  }
1556
1559
  assertCursorAndOrderFieldsScalar(model, cursor, orderEntries);
1557
- const { whereSql: cursorWhereSql, placeholdersByField } = buildCursorFilterParts(cursor, srcAlias, params, model);
1560
+ const { whereSql: cursorWhereSql } = buildCursorFilterParts(
1561
+ cursor,
1562
+ srcAlias,
1563
+ params,
1564
+ model
1565
+ );
1558
1566
  const cursorOrderBy = orderEntries.map(
1559
- (e) => `${srcAlias}.${quoteColumn(model, e.field)} ${e.direction.toUpperCase()}`
1567
+ (e) => srcAlias + "." + quoteColumn(model, e.field) + " " + e.direction.toUpperCase()
1560
1568
  ).join(", ");
1561
1569
  const selectList = buildCursorCteSelectList(
1562
1570
  cursorEntries,
1563
1571
  orderEntries,
1564
1572
  model
1565
1573
  );
1566
- const cte = `${cteName} AS (
1567
- SELECT ${selectList} FROM ${tableName} ${srcAlias}
1568
- WHERE ${cursorWhereSql}
1569
- ORDER BY ${cursorOrderBy}
1570
- LIMIT 1
1571
- )`;
1572
- const existsExpr = `EXISTS (SELECT 1 FROM ${cteName})`;
1573
- const outerCursorMatch = buildOuterCursorMatch(
1574
- cursor,
1575
- alias,
1576
- placeholdersByField,
1577
- params,
1578
- model
1579
- );
1580
- const getValueExpr = (field) => `(SELECT ${quoteColumn(model, field)} FROM ${cteName})`;
1574
+ const cte = cteName + " AS (\n SELECT " + selectList + " FROM " + tableName + " " + srcAlias + "\n WHERE " + cursorWhereSql + "\n ORDER BY " + cursorOrderBy + "\n LIMIT 1\n )";
1575
+ const existsExpr = "EXISTS (SELECT 1 FROM " + cteName + ")";
1581
1576
  const orClauses = [];
1582
1577
  for (let level = 0; level < orderEntries.length; level++) {
1583
1578
  const andParts = [];
1584
1579
  for (let i = 0; i < level; i++) {
1585
1580
  const e2 = orderEntries[i];
1586
1581
  const c2 = col(alias, e2.field, model);
1587
- const v2 = getValueExpr(e2.field);
1588
- andParts.push(buildCursorEqualityExpr(c2, v2));
1582
+ const cursorField2 = cteName + "." + quoteColumn(model, e2.field);
1583
+ andParts.push(buildCursorEqualityExpr(c2, cursorField2));
1589
1584
  }
1590
1585
  const e = orderEntries[level];
1591
1586
  const c = col(alias, e.field, model);
1592
- const v = getValueExpr(e.field);
1587
+ const cursorField = cteName + "." + quoteColumn(model, e.field);
1593
1588
  const nulls = (_a = e.nulls) != null ? _a : defaultNullsFor(d, e.direction);
1594
- andParts.push(buildCursorInequalityExpr(c, e.direction, nulls, v));
1595
- orClauses.push(`(${andParts.join(SQL_SEPARATORS.CONDITION_AND)})`);
1589
+ andParts.push(buildCursorInequalityExpr(c, e.direction, nulls, cursorField));
1590
+ orClauses.push("(" + andParts.join(SQL_SEPARATORS.CONDITION_AND) + ")");
1596
1591
  }
1597
1592
  const exclusive = orClauses.join(SQL_SEPARATORS.CONDITION_OR);
1598
- const condition = `(${existsExpr} ${SQL_SEPARATORS.CONDITION_AND} ((${exclusive})${SQL_SEPARATORS.CONDITION_OR}(${outerCursorMatch})))`;
1593
+ const outerMatchParts = [];
1594
+ for (const [field, value] of cursorEntries) {
1595
+ const c = col(alias, field, model);
1596
+ if (value === null) {
1597
+ outerMatchParts.push(c + " IS NULL");
1598
+ continue;
1599
+ }
1600
+ const ph = addAutoScoped(params, value, `cursor.outerMatch.${field}`);
1601
+ outerMatchParts.push(c + " = " + ph);
1602
+ }
1603
+ const outerCursorMatch = outerMatchParts.length === 1 ? outerMatchParts[0] : "(" + outerMatchParts.join(SQL_SEPARATORS.CONDITION_AND) + ")";
1604
+ const condition = "(" + existsExpr + SQL_SEPARATORS.CONDITION_AND + "((" + exclusive + ")" + SQL_SEPARATORS.CONDITION_OR + "(" + outerCursorMatch + ")))";
1599
1605
  return { cte, condition };
1600
1606
  }
1601
1607
  function buildOrderBy(orderBy, alias, dialect, model) {
@@ -1648,6 +1654,22 @@ function getPaginationParams(method, args) {
1648
1654
  }
1649
1655
  return {};
1650
1656
  }
1657
+ function buildOrderEntries(orderBy) {
1658
+ const normalized = normalizeOrderByInput(orderBy, parseOrderByValue);
1659
+ const entries = [];
1660
+ for (const item of normalized) {
1661
+ for (const field in item) {
1662
+ if (!Object.prototype.hasOwnProperty.call(item, field)) continue;
1663
+ const value = item[field];
1664
+ if (typeof value === "string") {
1665
+ entries.push({ field, direction: value });
1666
+ } else {
1667
+ entries.push({ field, direction: value.direction, nulls: value.nulls });
1668
+ }
1669
+ }
1670
+ }
1671
+ return entries;
1672
+ }
1651
1673
  function buildNotComposite(expr, val, params, dialect, buildOp, separator) {
1652
1674
  const entries = Object.entries(val).filter(
1653
1675
  ([k, v]) => k !== "mode" && v !== void 0
@@ -2118,7 +2140,7 @@ function buildListRelationFilters(args) {
2118
2140
  ) || relModel.fields.find((f) => !f.isRelation && f.name === "id");
2119
2141
  if (checkField) {
2120
2142
  const leftJoinSql = `LEFT JOIN ${relTable} ${relAlias} ON ${join3}`;
2121
- const whereClause = `${relAlias}.${quote(checkField.name)} IS NULL`;
2143
+ const whereClause = `${relAlias}.${quote2(checkField.name)} IS NULL`;
2122
2144
  return Object.freeze({
2123
2145
  clause: whereClause,
2124
2146
  joins: freezeJoins([leftJoinSql])
@@ -2569,11 +2591,24 @@ function buildOperator(expr, op, val, ctx, mode, fieldType) {
2569
2591
  // src/builder/shared/alias-generator.ts
2570
2592
  function toSafeSqlIdentifier(input) {
2571
2593
  const raw = String(input);
2572
- const cleaned = raw.replace(/\W/g, "_");
2573
- const startsOk = /^[a-zA-Z_]/.test(cleaned);
2574
- const base = startsOk ? cleaned : `_${cleaned}`;
2575
- const fallback = base.length > 0 ? base : "_t";
2576
- const lowered = fallback.toLowerCase();
2594
+ const n = raw.length;
2595
+ let out = "";
2596
+ for (let i = 0; i < n; i++) {
2597
+ const c = raw.charCodeAt(i);
2598
+ const isAZ = c >= 65 && c <= 90 || c >= 97 && c <= 122;
2599
+ const is09 = c >= 48 && c <= 57;
2600
+ const isUnderscore = c === 95;
2601
+ if (isAZ || is09 || isUnderscore) {
2602
+ out += raw[i];
2603
+ } else {
2604
+ out += "_";
2605
+ }
2606
+ }
2607
+ if (out.length === 0) out = "_t";
2608
+ const c0 = out.charCodeAt(0);
2609
+ const startsOk = c0 >= 65 && c0 <= 90 || c0 >= 97 && c0 <= 122 || c0 === 95;
2610
+ if (!startsOk) out = `_${out}`;
2611
+ const lowered = out.toLowerCase();
2577
2612
  return ALIAS_FORBIDDEN_KEYWORDS.has(lowered) ? `_${lowered}` : lowered;
2578
2613
  }
2579
2614
  function createAliasGenerator(maxAliases = 1e4) {
@@ -2676,14 +2711,16 @@ function validateState(params, mappings, index) {
2676
2711
  }
2677
2712
  function createStoreInternal(startIndex, initialParams = [], initialMappings = []) {
2678
2713
  let index = startIndex;
2679
- const params = [...initialParams];
2680
- const mappings = [...initialMappings];
2714
+ const params = initialParams.length > 0 ? [...initialParams] : [];
2715
+ const mappings = initialMappings.length > 0 ? [...initialMappings] : [];
2681
2716
  const dynamicNameToIndex = /* @__PURE__ */ new Map();
2682
- for (const m of initialMappings) {
2717
+ for (const m of mappings) {
2683
2718
  if (typeof m.dynamicName === "string") {
2684
2719
  dynamicNameToIndex.set(m.dynamicName.trim(), m.index);
2685
2720
  }
2686
2721
  }
2722
+ let dirty = true;
2723
+ let cachedSnapshot = null;
2687
2724
  function assertCanAdd() {
2688
2725
  if (index > MAX_PARAM_INDEX) {
2689
2726
  throw new Error(
@@ -2691,6 +2728,9 @@ function createStoreInternal(startIndex, initialParams = [], initialMappings = [
2691
2728
  );
2692
2729
  }
2693
2730
  }
2731
+ function format(position) {
2732
+ return `$${position}`;
2733
+ }
2694
2734
  function normalizeDynamicName(dynamicName) {
2695
2735
  const dn = dynamicName.trim();
2696
2736
  if (dn.length === 0) {
@@ -2698,20 +2738,16 @@ function createStoreInternal(startIndex, initialParams = [], initialMappings = [
2698
2738
  }
2699
2739
  return dn;
2700
2740
  }
2701
- function format(position) {
2702
- return `$${position}`;
2703
- }
2704
2741
  function addDynamic(dynamicName) {
2705
2742
  const dn = normalizeDynamicName(dynamicName);
2706
2743
  const existing = dynamicNameToIndex.get(dn);
2707
- if (existing !== void 0) {
2708
- return format(existing);
2709
- }
2744
+ if (existing !== void 0) return format(existing);
2710
2745
  const position = index;
2711
2746
  dynamicNameToIndex.set(dn, position);
2712
2747
  params.push(void 0);
2713
2748
  mappings.push({ index: position, dynamicName: dn });
2714
2749
  index++;
2750
+ dirty = true;
2715
2751
  return format(position);
2716
2752
  }
2717
2753
  function addStatic(value) {
@@ -2720,6 +2756,7 @@ function createStoreInternal(startIndex, initialParams = [], initialMappings = [
2720
2756
  params.push(normalizedValue);
2721
2757
  mappings.push({ index: position, value: normalizedValue });
2722
2758
  index++;
2759
+ dirty = true;
2723
2760
  return format(position);
2724
2761
  }
2725
2762
  function add(value, dynamicName) {
@@ -2734,11 +2771,15 @@ function createStoreInternal(startIndex, initialParams = [], initialMappings = [
2734
2771
  return add(value);
2735
2772
  }
2736
2773
  function snapshot() {
2737
- return Object.freeze({
2774
+ if (!dirty && cachedSnapshot) return cachedSnapshot;
2775
+ const snap = {
2738
2776
  index,
2739
- params: Object.freeze([...params]),
2740
- mappings: Object.freeze([...mappings])
2741
- });
2777
+ params,
2778
+ mappings
2779
+ };
2780
+ cachedSnapshot = snap;
2781
+ dirty = false;
2782
+ return snap;
2742
2783
  }
2743
2784
  return {
2744
2785
  add,
@@ -2947,7 +2988,7 @@ function getRelationTableReference(relModel, dialect) {
2947
2988
  dialect
2948
2989
  );
2949
2990
  }
2950
- function resolveRelationOrThrow(model, schemas, relName) {
2991
+ function resolveRelationOrThrow(model, schemas, schemaByName, relName) {
2951
2992
  const field = model.fields.find((f) => f.name === relName);
2952
2993
  if (!isNotNullish(field)) {
2953
2994
  throw new Error(
@@ -2959,10 +3000,16 @@ function resolveRelationOrThrow(model, schemas, relName) {
2959
3000
  `Invalid relation metadata for '${relName}' on model ${model.name}. This usually indicates a schema parsing error (missing foreignKey/references).`
2960
3001
  );
2961
3002
  }
2962
- const relModel = schemas.find((m) => m.name === field.relatedModel);
3003
+ const relatedModelName = field.relatedModel;
3004
+ if (!isNotNullish(relatedModelName) || String(relatedModelName).trim().length === 0) {
3005
+ throw new Error(
3006
+ `Relation '${relName}' on model ${model.name} is missing relatedModel metadata.`
3007
+ );
3008
+ }
3009
+ const relModel = schemaByName.get(relatedModelName);
2963
3010
  if (!isNotNullish(relModel)) {
2964
3011
  throw new Error(
2965
- `Relation '${relName}' on model ${model.name} references missing model '${field.relatedModel}'.`
3012
+ `Relation '${relName}' on model ${model.name} references missing model '${relatedModelName}'.`
2966
3013
  );
2967
3014
  }
2968
3015
  return { field, relModel };
@@ -3081,6 +3128,7 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
3081
3128
  relArgs,
3082
3129
  relModel,
3083
3130
  ctx.schemas,
3131
+ ctx.schemaByName,
3084
3132
  relAlias,
3085
3133
  ctx.aliasGen,
3086
3134
  ctx.params,
@@ -3269,7 +3317,7 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
3269
3317
  ctx
3270
3318
  });
3271
3319
  }
3272
- function buildIncludeSqlInternal(args, model, schemas, parentAlias, aliasGen, params, dialect, visitPath = [], depth = 0, stats) {
3320
+ function buildIncludeSqlInternal(args, model, schemas, schemaByName, parentAlias, aliasGen, params, dialect, visitPath = [], depth = 0, stats) {
3273
3321
  if (!stats) stats = { totalIncludes: 0, totalSubqueries: 0, maxDepth: 0 };
3274
3322
  if (depth > MAX_INCLUDE_DEPTH) {
3275
3323
  throw new Error(
@@ -3293,7 +3341,12 @@ function buildIncludeSqlInternal(args, model, schemas, parentAlias, aliasGen, pa
3293
3341
  `Query complexity limit exceeded: ${stats.totalSubqueries} subqueries generated. Maximum allowed: ${MAX_TOTAL_SUBQUERIES}. This indicates exponential include nesting. Stats: depth=${stats.maxDepth}, includes=${stats.totalIncludes}. Path: ${visitPath.join(" -> ")}. Simplify your include structure or split into multiple queries.`
3294
3342
  );
3295
3343
  }
3296
- const resolved = resolveRelationOrThrow(model, schemas, relName);
3344
+ const resolved = resolveRelationOrThrow(
3345
+ model,
3346
+ schemas,
3347
+ schemaByName,
3348
+ relName
3349
+ );
3297
3350
  const relationPath = `${model.name}.${relName}`;
3298
3351
  const currentPath = [...visitPath, relationPath];
3299
3352
  if (visitPath.includes(relationPath)) {
@@ -3313,6 +3366,7 @@ function buildIncludeSqlInternal(args, model, schemas, parentAlias, aliasGen, pa
3313
3366
  buildSingleInclude(relName, relArgs, resolved.field, resolved.relModel, {
3314
3367
  model,
3315
3368
  schemas,
3369
+ schemaByName,
3316
3370
  parentAlias,
3317
3371
  aliasGen,
3318
3372
  dialect,
@@ -3332,10 +3386,13 @@ function buildIncludeSql(args, model, schemas, parentAlias, params, dialect) {
3332
3386
  totalSubqueries: 0,
3333
3387
  maxDepth: 0
3334
3388
  };
3389
+ const schemaByName = /* @__PURE__ */ new Map();
3390
+ for (const m of schemas) schemaByName.set(m.name, m);
3335
3391
  return buildIncludeSqlInternal(
3336
3392
  args,
3337
3393
  model,
3338
3394
  schemas,
3395
+ schemaByName,
3339
3396
  parentAlias,
3340
3397
  aliasGen,
3341
3398
  params,
@@ -3345,7 +3402,7 @@ function buildIncludeSql(args, model, schemas, parentAlias, params, dialect) {
3345
3402
  stats
3346
3403
  );
3347
3404
  }
3348
- function resolveCountRelationOrThrow(relName, model, schemas) {
3405
+ function resolveCountRelationOrThrow(relName, model, schemas, schemaByName) {
3349
3406
  const relationSet = getRelationFieldSet(model);
3350
3407
  if (!relationSet.has(relName)) {
3351
3408
  throw new Error(
@@ -3362,10 +3419,16 @@ function resolveCountRelationOrThrow(relName, model, schemas) {
3362
3419
  `_count.${relName} has invalid relation metadata on model ${model.name}`
3363
3420
  );
3364
3421
  }
3365
- const relModel = schemas.find((m) => m.name === field.relatedModel);
3422
+ const relatedModelName = field.relatedModel;
3423
+ if (!isNotNullish(relatedModelName) || String(relatedModelName).trim().length === 0) {
3424
+ throw new Error(
3425
+ `_count.${relName} is missing relatedModel metadata on model ${model.name}`
3426
+ );
3427
+ }
3428
+ const relModel = schemaByName.get(relatedModelName);
3366
3429
  if (!relModel) {
3367
3430
  throw new Error(
3368
- `Related model '${field.relatedModel}' not found for _count.${relName}`
3431
+ `Related model '${relatedModelName}' not found for _count.${relName}`
3369
3432
  );
3370
3433
  }
3371
3434
  return { field, relModel };
@@ -3451,9 +3514,16 @@ function buildRelationCountSql(countSelect, model, schemas, parentAlias, _params
3451
3514
  const joins = [];
3452
3515
  const pairs = [];
3453
3516
  const aliasGen = createAliasGenerator();
3517
+ const schemaByName = /* @__PURE__ */ new Map();
3518
+ for (const m of schemas) schemaByName.set(m.name, m);
3454
3519
  for (const [relName, shouldCount] of Object.entries(countSelect)) {
3455
3520
  if (!shouldCount) continue;
3456
- const resolved = resolveCountRelationOrThrow(relName, model, schemas);
3521
+ const resolved = resolveCountRelationOrThrow(
3522
+ relName,
3523
+ model,
3524
+ schemas,
3525
+ schemaByName
3526
+ );
3457
3527
  const built = buildCountJoinAndPair({
3458
3528
  relName,
3459
3529
  field: resolved.field,
@@ -3469,35 +3539,36 @@ function buildRelationCountSql(countSelect, model, schemas, parentAlias, _params
3469
3539
  return { joins, jsonPairs: pairs.join(SQL_SEPARATORS.FIELD_LIST) };
3470
3540
  }
3471
3541
 
3472
- // src/builder/select/assembly.ts
3473
- var ALIAS_CAPTURE = "([A-Za-z_][A-Za-z0-9_]*)";
3474
- var COLUMN_PART = '(?:"([^"]+)"|([a-z_][a-z0-9_]*))';
3475
- var AS_PART = `(?:\\s+AS\\s+${COLUMN_PART})?`;
3476
- var SIMPLE_COLUMN_PATTERN = `^${ALIAS_CAPTURE}\\.${COLUMN_PART}${AS_PART}$`;
3477
- var SIMPLE_COLUMN_RE = new RegExp(SIMPLE_COLUMN_PATTERN, "i");
3542
+ // src/builder/shared/string-builder.ts
3478
3543
  function joinNonEmpty(parts, sep) {
3479
- return parts.filter((s) => s.trim().length > 0).join(sep);
3544
+ let result = "";
3545
+ for (const p of parts) {
3546
+ if (p) {
3547
+ if (result) result += sep;
3548
+ result += p;
3549
+ }
3550
+ }
3551
+ return result;
3480
3552
  }
3481
3553
  function buildWhereSql(conditions) {
3482
3554
  if (!isNonEmptyArray(conditions)) return "";
3483
- const parts = [
3484
- SQL_TEMPLATES.WHERE,
3485
- conditions.join(SQL_SEPARATORS.CONDITION_AND)
3486
- ];
3487
- return ` ${parts.join(" ")}`;
3555
+ return " " + SQL_TEMPLATES.WHERE + " " + conditions.join(SQL_SEPARATORS.CONDITION_AND);
3488
3556
  }
3489
3557
  function buildJoinsSql(...joinGroups) {
3490
3558
  const all = [];
3491
3559
  for (const g of joinGroups) {
3492
- if (isNonEmptyArray(g)) all.push(...g);
3560
+ if (isNonEmptyArray(g)) {
3561
+ for (const j of g) all.push(j);
3562
+ }
3493
3563
  }
3494
- return all.length > 0 ? ` ${all.join(" ")}` : "";
3564
+ return all.length > 0 ? " " + all.join(" ") : "";
3495
3565
  }
3496
3566
  function buildSelectList(baseSelect, extraCols) {
3497
3567
  const base = baseSelect.trim();
3498
3568
  const extra = extraCols.trim();
3499
- if (base && extra) return `${base}${SQL_SEPARATORS.FIELD_LIST}${extra}`;
3500
- return base || extra;
3569
+ if (!base) return extra;
3570
+ if (!extra) return base;
3571
+ return base + SQL_SEPARATORS.FIELD_LIST + extra;
3501
3572
  }
3502
3573
  function finalizeSql(sql, params, dialect) {
3503
3574
  const snapshot = params.snapshot();
@@ -3507,38 +3578,128 @@ function finalizeSql(sql, params, dialect) {
3507
3578
  snapshot.params,
3508
3579
  dialect === "sqlite" ? "postgres" : dialect
3509
3580
  );
3510
- return Object.freeze({
3581
+ return {
3511
3582
  sql,
3512
3583
  params: snapshot.params,
3513
- paramMappings: Object.freeze(snapshot.mappings)
3514
- });
3584
+ paramMappings: snapshot.mappings
3585
+ };
3515
3586
  }
3516
3587
  function parseSimpleScalarSelect(select, fromAlias) {
3517
- var _a, _b, _c, _d;
3518
3588
  const raw = select.trim();
3519
3589
  if (raw.length === 0) return [];
3590
+ const fromLower = fromAlias.toLowerCase();
3520
3591
  const parts = raw.split(SQL_SEPARATORS.FIELD_LIST);
3521
3592
  const names = [];
3522
- for (const part of parts) {
3523
- const p = part.trim();
3524
- const m = p.match(SIMPLE_COLUMN_RE);
3525
- if (!m) {
3593
+ const isIdent = (s) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(s);
3594
+ const readIdentOrQuoted = (s, start) => {
3595
+ const n = s.length;
3596
+ if (start >= n) return { text: "", next: start, quoted: false };
3597
+ if (s.charCodeAt(start) === 34) {
3598
+ let i2 = start + 1;
3599
+ let out = "";
3600
+ let saw = false;
3601
+ while (i2 < n) {
3602
+ const c = s.charCodeAt(i2);
3603
+ if (c === 34) {
3604
+ const next = i2 + 1;
3605
+ if (next < n && s.charCodeAt(next) === 34) {
3606
+ out += '"';
3607
+ saw = true;
3608
+ i2 += 2;
3609
+ continue;
3610
+ }
3611
+ if (!saw)
3612
+ throw new Error(
3613
+ `sqlite distinct emulation: empty quoted identifier in: ${s}`
3614
+ );
3615
+ return { text: out, next: i2 + 1, quoted: true };
3616
+ }
3617
+ out += s[i2];
3618
+ saw = true;
3619
+ i2++;
3620
+ }
3526
3621
  throw new Error(
3527
- `sqlite distinct emulation requires scalar select fields to be simple columns (optionally with AS). Got: ${p}`
3622
+ `sqlite distinct emulation: unterminated quoted identifier in: ${s}`
3528
3623
  );
3529
3624
  }
3530
- const actualAlias = m[1];
3531
- if (actualAlias.toLowerCase() !== fromAlias.toLowerCase()) {
3625
+ let i = start;
3626
+ while (i < n) {
3627
+ const c = s.charCodeAt(i);
3628
+ if (c === 32 || c === 9) break;
3629
+ if (c === 46) break;
3630
+ i++;
3631
+ }
3632
+ return { text: s.slice(start, i), next: i, quoted: false };
3633
+ };
3634
+ const skipSpaces = (s, i) => {
3635
+ while (i < s.length) {
3636
+ const c = s.charCodeAt(i);
3637
+ if (c !== 32 && c !== 9) break;
3638
+ i++;
3639
+ }
3640
+ return i;
3641
+ };
3642
+ for (let idx = 0; idx < parts.length; idx++) {
3643
+ const p = parts[idx].trim();
3644
+ if (p.length === 0) continue;
3645
+ let i = 0;
3646
+ i = skipSpaces(p, i);
3647
+ const a = readIdentOrQuoted(p, i);
3648
+ const actualAlias = a.text.toLowerCase();
3649
+ if (!isIdent(a.text)) {
3532
3650
  throw new Error(
3533
- `Expected alias '${fromAlias}', got '${actualAlias}' in: ${p}`
3651
+ `sqlite distinct emulation requires scalar select fields to be simple columns (alias.column). Got: ${p}`
3534
3652
  );
3535
3653
  }
3536
- const columnName = ((_b = (_a = m[2]) != null ? _a : m[3]) != null ? _b : "").trim();
3537
- const outAlias = ((_d = (_c = m[4]) != null ? _c : m[5]) != null ? _d : "").trim();
3538
- const name = outAlias.length > 0 ? outAlias : columnName;
3539
- if (name.length === 0) {
3654
+ if (actualAlias !== fromLower) {
3655
+ throw new Error(`Expected alias '${fromAlias}', got '${a.text}' in: ${p}`);
3656
+ }
3657
+ i = a.next;
3658
+ if (i >= p.length || p.charCodeAt(i) !== 46) {
3659
+ throw new Error(
3660
+ `sqlite distinct emulation requires scalar select fields to be simple columns (alias.column). Got: ${p}`
3661
+ );
3662
+ }
3663
+ i++;
3664
+ i = skipSpaces(p, i);
3665
+ const colPart = readIdentOrQuoted(p, i);
3666
+ const columnName = colPart.text.trim();
3667
+ if (columnName.length === 0) {
3540
3668
  throw new Error(`Failed to parse selected column name from: ${p}`);
3541
3669
  }
3670
+ i = colPart.next;
3671
+ i = skipSpaces(p, i);
3672
+ let outAlias = "";
3673
+ if (i < p.length) {
3674
+ const rest = p.slice(i).trim();
3675
+ if (rest.length > 0) {
3676
+ const m = rest.match(/^AS\s+/i);
3677
+ if (!m) {
3678
+ throw new Error(
3679
+ `sqlite distinct emulation requires scalar select fields to be simple columns (optionally with AS). Got: ${p}`
3680
+ );
3681
+ }
3682
+ let j = i;
3683
+ j = skipSpaces(p, j);
3684
+ if (!/^AS\b/i.test(p.slice(j))) {
3685
+ throw new Error(`Failed to parse AS in: ${p}`);
3686
+ }
3687
+ j += 2;
3688
+ j = skipSpaces(p, j);
3689
+ const out = readIdentOrQuoted(p, j);
3690
+ outAlias = out.text.trim();
3691
+ if (outAlias.length === 0) {
3692
+ throw new Error(`Failed to parse output alias from: ${p}`);
3693
+ }
3694
+ j = skipSpaces(p, out.next);
3695
+ if (j !== p.length) {
3696
+ throw new Error(
3697
+ `sqlite distinct emulation requires scalar select fields to be simple columns (optionally with AS). Got: ${p}`
3698
+ );
3699
+ }
3700
+ }
3701
+ }
3702
+ const name = outAlias.length > 0 ? outAlias : columnName;
3542
3703
  names.push(name);
3543
3704
  }
3544
3705
  return names;
@@ -3548,15 +3709,14 @@ function replaceOrderByAlias(orderBy, fromAlias, outerAlias) {
3548
3709
  if (src.length === 0) return orderBy;
3549
3710
  const escaped = src.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3550
3711
  const re = new RegExp(`\\b${escaped}\\.`, "gi");
3551
- return orderBy.replace(re, `${outerAlias}.`);
3712
+ return orderBy.replace(re, outerAlias + ".");
3552
3713
  }
3553
3714
  function buildDistinctColumns(distinct, fromAlias, model) {
3554
3715
  return distinct.map((f) => col(fromAlias, f, model)).join(SQL_SEPARATORS.FIELD_LIST);
3555
3716
  }
3556
3717
  function buildOutputColumns(scalarNames, includeNames, hasCount) {
3557
- const outputCols = [...scalarNames, ...includeNames];
3558
- if (hasCount) outputCols.push("_count");
3559
- const formatted = outputCols.map((n) => quote(n)).join(SQL_SEPARATORS.FIELD_LIST);
3718
+ const outputCols = hasCount ? [...scalarNames, ...includeNames, "_count"] : [...scalarNames, ...includeNames];
3719
+ const formatted = outputCols.map((n) => quote2(n)).join(SQL_SEPARATORS.FIELD_LIST);
3560
3720
  if (!isNonEmptyString(formatted)) {
3561
3721
  throw new Error("distinct emulation requires at least one output column");
3562
3722
  }
@@ -3567,11 +3727,11 @@ function buildWindowOrder(args) {
3567
3727
  const fromLower = String(fromAlias).toLowerCase();
3568
3728
  const orderFields = baseOrder.split(SQL_SEPARATORS.ORDER_BY).map((s) => s.trim().toLowerCase());
3569
3729
  const hasIdInOrder = orderFields.some(
3570
- (f) => f.startsWith(`${fromLower}.id `) || f.startsWith(`${fromLower}."id" `)
3730
+ (f) => f.startsWith(fromLower + ".id ") || f.startsWith(fromLower + '."id" ')
3571
3731
  );
3572
3732
  if (hasIdInOrder) return baseOrder;
3573
- const idTiebreaker = idField ? `, ${col(fromAlias, "id", model)} ASC` : "";
3574
- return `${baseOrder}${idTiebreaker}`;
3733
+ const idTiebreaker = idField ? ", " + col(fromAlias, "id", model) + " ASC" : "";
3734
+ return baseOrder + idTiebreaker;
3575
3735
  }
3576
3736
  function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
3577
3737
  var _a, _b;
@@ -3588,7 +3748,7 @@ function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
3588
3748
  hasCount
3589
3749
  );
3590
3750
  const distinctCols = buildDistinctColumns([...distinct], from.alias, model);
3591
- const fallbackOrder = [...distinct].map((f) => `${col(from.alias, f, model)} ASC`).join(SQL_SEPARATORS.FIELD_LIST);
3751
+ const fallbackOrder = [...distinct].map((f) => col(from.alias, f, model) + " ASC").join(SQL_SEPARATORS.FIELD_LIST);
3592
3752
  const idField = model.fields.find(
3593
3753
  (f) => f.name === "id" && !f.isRelation
3594
3754
  );
@@ -3599,7 +3759,7 @@ function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
3599
3759
  fromAlias: from.alias,
3600
3760
  model
3601
3761
  });
3602
- const outerOrder = isNonEmptyString(orderBy) ? replaceOrderByAlias(orderBy, from.alias, `"__tp_distinct"`) : replaceOrderByAlias(fallbackOrder, from.alias, `"__tp_distinct"`);
3762
+ const outerOrder = isNonEmptyString(orderBy) ? replaceOrderByAlias(orderBy, from.alias, '"__tp_distinct"') : replaceOrderByAlias(fallbackOrder, from.alias, '"__tp_distinct"');
3603
3763
  const joins = buildJoinsSql(whereJoins, countJoins);
3604
3764
  const conditions = [];
3605
3765
  if (whereClause && whereClause !== "1=1") conditions.push(whereClause);
@@ -3609,7 +3769,7 @@ function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
3609
3769
  const innerParts = [
3610
3770
  SQL_TEMPLATES.SELECT,
3611
3771
  innerSelectList + innerComma,
3612
- `ROW_NUMBER() OVER (PARTITION BY ${distinctCols} ORDER BY ${windowOrder})`,
3772
+ "ROW_NUMBER() OVER (PARTITION BY " + distinctCols + " ORDER BY " + windowOrder + ")",
3613
3773
  SQL_TEMPLATES.AS,
3614
3774
  '"__tp_rn"',
3615
3775
  SQL_TEMPLATES.FROM,
@@ -3618,12 +3778,12 @@ function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
3618
3778
  ];
3619
3779
  if (joins) innerParts.push(joins);
3620
3780
  if (whereSql) innerParts.push(whereSql);
3621
- const inner = innerParts.filter(Boolean).join(" ");
3781
+ const inner = innerParts.join(" ");
3622
3782
  const outerParts = [
3623
3783
  SQL_TEMPLATES.SELECT,
3624
3784
  outerSelectCols,
3625
3785
  SQL_TEMPLATES.FROM,
3626
- `(${inner})`,
3786
+ "(" + inner + ")",
3627
3787
  SQL_TEMPLATES.AS,
3628
3788
  '"__tp_distinct"',
3629
3789
  SQL_TEMPLATES.WHERE,
@@ -3632,7 +3792,7 @@ function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
3632
3792
  if (isNonEmptyString(outerOrder)) {
3633
3793
  outerParts.push(SQL_TEMPLATES.ORDER_BY, outerOrder);
3634
3794
  }
3635
- return outerParts.filter(Boolean).join(" ");
3795
+ return outerParts.join(" ");
3636
3796
  }
3637
3797
  function buildIncludeColumns(spec) {
3638
3798
  var _a, _b;
@@ -3652,7 +3812,7 @@ function buildIncludeColumns(spec) {
3652
3812
  dialect
3653
3813
  );
3654
3814
  if (countBuild.jsonPairs) {
3655
- countCols = `${jsonBuildObject(countBuild.jsonPairs, dialect)} ${SQL_TEMPLATES.AS} ${quote("_count")}`;
3815
+ countCols = jsonBuildObject(countBuild.jsonPairs, dialect) + " " + SQL_TEMPLATES.AS + " " + quote2("_count");
3656
3816
  }
3657
3817
  countJoins = countBuild.joins;
3658
3818
  }
@@ -3664,8 +3824,8 @@ function buildIncludeColumns(spec) {
3664
3824
  }
3665
3825
  const emptyJson = dialect === "postgres" ? `'[]'::json` : `json('[]')`;
3666
3826
  const includeCols = hasIncludes ? includes.map((inc) => {
3667
- const expr = inc.isOneToOne ? `(${inc.sql})` : `COALESCE((${inc.sql}), ${emptyJson})`;
3668
- return `${expr} ${SQL_TEMPLATES.AS} ${quote(inc.name)}`;
3827
+ const expr = inc.isOneToOne ? "(" + inc.sql + ")" : "COALESCE((" + inc.sql + "), " + emptyJson + ")";
3828
+ return expr + " " + SQL_TEMPLATES.AS + " " + quote2(inc.name);
3669
3829
  }).join(SQL_SEPARATORS.FIELD_LIST) : "";
3670
3830
  const allCols = joinNonEmpty(
3671
3831
  [includeCols, countCols],
@@ -3733,7 +3893,7 @@ function withCountJoins(spec, countJoins, whereJoins) {
3733
3893
  function buildPostgresDistinctOnClause(fromAlias, distinct, model) {
3734
3894
  if (!isNonEmptyArray(distinct)) return null;
3735
3895
  const distinctCols = buildDistinctColumns([...distinct], fromAlias, model);
3736
- return `${SQL_TEMPLATES.DISTINCT_ON} (${distinctCols})`;
3896
+ return SQL_TEMPLATES.DISTINCT_ON + " (" + distinctCols + ")";
3737
3897
  }
3738
3898
  function pushJoinGroups(parts, ...groups) {
3739
3899
  for (const g of groups) {
@@ -3778,9 +3938,7 @@ function constructFinalSql(spec) {
3778
3938
  return finalizeSql(sql2, params, dialect);
3779
3939
  }
3780
3940
  const parts = [];
3781
- if (cursorCte) {
3782
- parts.push(`WITH ${cursorCte}`);
3783
- }
3941
+ if (cursorCte) parts.push("WITH " + cursorCte);
3784
3942
  parts.push(SQL_TEMPLATES.SELECT);
3785
3943
  const distinctOn = dialect === "postgres" ? buildPostgresDistinctOnClause(from.alias, distinct, model) : null;
3786
3944
  if (distinctOn) parts.push(distinctOn);
@@ -3791,6 +3949,10 @@ function constructFinalSql(spec) {
3791
3949
  }
3792
3950
  parts.push(fullSelectList);
3793
3951
  parts.push(SQL_TEMPLATES.FROM, from.table, from.alias);
3952
+ if (cursorCte) {
3953
+ const cteName = cursorCte.split(" AS ")[0].trim();
3954
+ parts.push("CROSS JOIN", cteName);
3955
+ }
3794
3956
  pushJoinGroups(parts, whereJoins, countJoins);
3795
3957
  const conditions = buildConditions(whereClause, cursorClause);
3796
3958
  pushWhere(parts, conditions);
@@ -4013,14 +4175,16 @@ function buildSelectSql(input) {
4013
4175
  }
4014
4176
 
4015
4177
  // src/builder/shared/comparison-builder.ts
4016
- function buildComparisons(expr, filter, params, dialect, builder, excludeKeys = /* @__PURE__ */ new Set(["mode"])) {
4178
+ var DEFAULT_EXCLUDE_KEYS = /* @__PURE__ */ new Set(["mode"]);
4179
+ function buildComparisons(expr, filter, params, dialect, builder, excludeKeys = DEFAULT_EXCLUDE_KEYS) {
4017
4180
  const out = [];
4018
- for (const [op, val] of Object.entries(filter)) {
4019
- if (excludeKeys.has(op) || val === void 0) continue;
4181
+ for (const op in filter) {
4182
+ if (!Object.prototype.hasOwnProperty.call(filter, op)) continue;
4183
+ if (excludeKeys.has(op)) continue;
4184
+ const val = filter[op];
4185
+ if (val === void 0) continue;
4020
4186
  const built = builder(expr, op, val, params, dialect);
4021
- if (built && built.trim().length > 0) {
4022
- out.push(built);
4023
- }
4187
+ if (built && built.trim().length > 0) out.push(built);
4024
4188
  }
4025
4189
  return out;
4026
4190
  }
@@ -4050,6 +4214,13 @@ var HAVING_ALLOWED_OPS = /* @__PURE__ */ new Set([
4050
4214
  Ops.IN,
4051
4215
  Ops.NOT_IN
4052
4216
  ]);
4217
+ var HAVING_FIELD_FIRST_AGG_KEYS = Object.freeze([
4218
+ "_count",
4219
+ "_sum",
4220
+ "_avg",
4221
+ "_min",
4222
+ "_max"
4223
+ ]);
4053
4224
  function isTruthySelection(v) {
4054
4225
  return v === true;
4055
4226
  }
@@ -4068,15 +4239,15 @@ function assertHavingOp(op) {
4068
4239
  }
4069
4240
  function aggExprForField(aggKey, field, alias, model) {
4070
4241
  if (aggKey === "_count") {
4071
- return field === "_all" ? `COUNT(*)` : `COUNT(${col(alias, field, model)})`;
4242
+ return field === "_all" ? "COUNT(*)" : "COUNT(" + col(alias, field, model) + ")";
4072
4243
  }
4073
4244
  if (field === "_all") {
4074
4245
  throw new Error(`'${aggKey}' does not support '_all'`);
4075
4246
  }
4076
- if (aggKey === "_sum") return `SUM(${col(alias, field, model)})`;
4077
- if (aggKey === "_avg") return `AVG(${col(alias, field, model)})`;
4078
- if (aggKey === "_min") return `MIN(${col(alias, field, model)})`;
4079
- return `MAX(${col(alias, field, model)})`;
4247
+ if (aggKey === "_sum") return "SUM(" + col(alias, field, model) + ")";
4248
+ if (aggKey === "_avg") return "AVG(" + col(alias, field, model) + ")";
4249
+ if (aggKey === "_min") return "MIN(" + col(alias, field, model) + ")";
4250
+ return "MAX(" + col(alias, field, model) + ")";
4080
4251
  }
4081
4252
  function buildComparisonOp(op) {
4082
4253
  const sqlOp = COMPARISON_OPS[op];
@@ -4103,8 +4274,8 @@ function normalizeLogicalValue2(operator, value) {
4103
4274
  throw new Error(`${operator} must be an object or array of objects in HAVING`);
4104
4275
  }
4105
4276
  function buildNullComparison(expr, op) {
4106
- if (op === Ops.EQUALS) return `${expr} ${SQL_TEMPLATES.IS_NULL}`;
4107
- if (op === Ops.NOT) return `${expr} ${SQL_TEMPLATES.IS_NOT_NULL}`;
4277
+ if (op === Ops.EQUALS) return expr + " " + SQL_TEMPLATES.IS_NULL;
4278
+ if (op === Ops.NOT) return expr + " " + SQL_TEMPLATES.IS_NOT_NULL;
4108
4279
  throw new Error(`Operator '${op}' doesn't support null in HAVING`);
4109
4280
  }
4110
4281
  function buildInComparison(expr, op, val, params, dialect) {
@@ -4125,7 +4296,7 @@ function buildInComparison(expr, op, val, params, dialect) {
4125
4296
  function buildBinaryComparison(expr, op, val, params) {
4126
4297
  const sqlOp = buildComparisonOp(op);
4127
4298
  const placeholder = addHavingParam(params, op, val);
4128
- return `${expr} ${sqlOp} ${placeholder}`;
4299
+ return expr + " " + sqlOp + " " + placeholder;
4129
4300
  }
4130
4301
  function buildSimpleComparison(expr, op, val, params, dialect) {
4131
4302
  assertHavingOp(op);
@@ -4146,20 +4317,21 @@ function buildSimpleComparison(expr, op, val, params, dialect) {
4146
4317
  return buildBinaryComparison(expr, op, val, params);
4147
4318
  }
4148
4319
  function negateClauses(subClauses) {
4149
- if (subClauses.length === 1) return `${SQL_TEMPLATES.NOT} ${subClauses[0]}`;
4150
- return `${SQL_TEMPLATES.NOT} (${subClauses.join(SQL_SEPARATORS.CONDITION_AND)})`;
4320
+ if (subClauses.length === 1) return SQL_TEMPLATES.NOT + " " + subClauses[0];
4321
+ return SQL_TEMPLATES.NOT + " (" + subClauses.join(SQL_SEPARATORS.CONDITION_AND) + ")";
4151
4322
  }
4152
4323
  function combineLogical(key, subClauses) {
4153
4324
  if (key === LogicalOps.NOT) return negateClauses(subClauses);
4154
- return subClauses.join(` ${key} `);
4325
+ return subClauses.join(" " + key + " ");
4155
4326
  }
4156
4327
  function buildHavingNode(node, alias, params, dialect, model) {
4157
4328
  const clauses = [];
4158
- const entries = Object.entries(node);
4159
- for (const [key, value] of entries) {
4329
+ for (const key in node) {
4330
+ if (!Object.prototype.hasOwnProperty.call(node, key)) continue;
4331
+ const value = node[key];
4160
4332
  const built = buildHavingEntry(key, value, alias, params, dialect, model);
4161
4333
  for (const c of built) {
4162
- if (c && c.trim().length > 0) clauses.push(c);
4334
+ if (c && c.length > 0) clauses.push(c);
4163
4335
  }
4164
4336
  }
4165
4337
  return clauses.join(SQL_SEPARATORS.CONDITION_AND);
@@ -4169,7 +4341,7 @@ function buildLogicalClause2(key, value, alias, params, dialect, model) {
4169
4341
  const subClauses = [];
4170
4342
  for (const it of items) {
4171
4343
  const c = buildHavingNode(it, alias, params, dialect, model);
4172
- if (c && c.trim().length > 0) subClauses.push(`(${c})`);
4344
+ if (c && c.length > 0) subClauses.push("(" + c + ")");
4173
4345
  }
4174
4346
  if (subClauses.length === 0) return "";
4175
4347
  return combineLogical(key, subClauses);
@@ -4194,11 +4366,23 @@ function buildHavingForAggregateFirstShape(aggKey, target, alias, params, dialec
4194
4366
  throw new Error(`HAVING '${aggKey}' must be an object`);
4195
4367
  }
4196
4368
  const out = [];
4197
- for (const [field, filter] of Object.entries(target)) {
4369
+ const targetObj = target;
4370
+ for (const field in targetObj) {
4371
+ if (!Object.prototype.hasOwnProperty.call(targetObj, field)) continue;
4198
4372
  assertHavingAggTarget(aggKey, field, model);
4199
- if (!isPlainObject(filter) || Object.keys(filter).length === 0) continue;
4373
+ const filter = targetObj[field];
4374
+ if (!isPlainObject(filter)) continue;
4375
+ const filterObj = filter;
4376
+ let hasAny = false;
4377
+ for (const k in filterObj) {
4378
+ if (Object.prototype.hasOwnProperty.call(filterObj, k)) {
4379
+ hasAny = true;
4380
+ break;
4381
+ }
4382
+ }
4383
+ if (!hasAny) continue;
4200
4384
  const expr = aggExprForField(aggKey, field, alias, model);
4201
- out.push(...buildHavingOpsForExpr(expr, filter, params, dialect));
4385
+ out.push(...buildHavingOpsForExpr(expr, filterObj, params, dialect));
4202
4386
  }
4203
4387
  return out;
4204
4388
  }
@@ -4209,16 +4393,23 @@ function buildHavingForFieldFirstShape(fieldName, target, alias, params, dialect
4209
4393
  assertScalarField(model, fieldName, "HAVING");
4210
4394
  const out = [];
4211
4395
  const obj = target;
4212
- const keys = ["_count", "_sum", "_avg", "_min", "_max"];
4213
- for (const aggKey of keys) {
4396
+ for (const aggKey of HAVING_FIELD_FIRST_AGG_KEYS) {
4214
4397
  const aggFilter = obj[aggKey];
4215
4398
  if (!isPlainObject(aggFilter)) continue;
4216
- if (Object.keys(aggFilter).length === 0) continue;
4399
+ const aggFilterObj = aggFilter;
4400
+ let hasAny = false;
4401
+ for (const k in aggFilterObj) {
4402
+ if (Object.prototype.hasOwnProperty.call(aggFilterObj, k)) {
4403
+ hasAny = true;
4404
+ break;
4405
+ }
4406
+ }
4407
+ if (!hasAny) continue;
4217
4408
  if (aggKey === "_sum" || aggKey === "_avg") {
4218
4409
  assertNumericField(model, fieldName, "HAVING");
4219
4410
  }
4220
4411
  const expr = aggExprForField(aggKey, fieldName, alias, model);
4221
- out.push(...buildHavingOpsForExpr(expr, aggFilter, params, dialect));
4412
+ out.push(...buildHavingOpsForExpr(expr, aggFilterObj, params, dialect));
4222
4413
  }
4223
4414
  return out;
4224
4415
  }
@@ -4267,13 +4458,13 @@ function normalizeCountArg(v) {
4267
4458
  }
4268
4459
  function pushCountAllField(fields) {
4269
4460
  fields.push(
4270
- `${SQL_TEMPLATES.COUNT_ALL} ${SQL_TEMPLATES.AS} ${quote("_count._all")}`
4461
+ SQL_TEMPLATES.COUNT_ALL + " " + SQL_TEMPLATES.AS + " " + quote2("_count._all")
4271
4462
  );
4272
4463
  }
4273
4464
  function pushCountField(fields, alias, fieldName, model) {
4274
- const outAlias = `_count.${fieldName}`;
4465
+ const outAlias = "_count." + fieldName;
4275
4466
  fields.push(
4276
- `COUNT(${col(alias, fieldName, model)}) ${SQL_TEMPLATES.AS} ${quote(outAlias)}`
4467
+ "COUNT(" + col(alias, fieldName, model) + ") " + SQL_TEMPLATES.AS + " " + quote2(outAlias)
4277
4468
  );
4278
4469
  }
4279
4470
  function addCountFields(fields, countArg, alias, model) {
@@ -4286,12 +4477,14 @@ function addCountFields(fields, countArg, alias, model) {
4286
4477
  if (countArg._all === true) {
4287
4478
  pushCountAllField(fields);
4288
4479
  }
4289
- const selected = Object.entries(countArg).filter(
4290
- ([f, v]) => f !== "_all" && isTruthySelection(v)
4291
- );
4292
- for (const [f] of selected) {
4293
- assertScalarField(model, f, "_count");
4294
- pushCountField(fields, alias, f, model);
4480
+ for (const f in countArg) {
4481
+ if (!Object.prototype.hasOwnProperty.call(countArg, f)) continue;
4482
+ if (f === "_all") continue;
4483
+ const v = countArg[f];
4484
+ if (isTruthySelection(v)) {
4485
+ assertScalarField(model, f, "_count");
4486
+ pushCountField(fields, alias, f, model);
4487
+ }
4295
4488
  }
4296
4489
  }
4297
4490
  function getAggregateSelectionObject(args, agg) {
@@ -4306,16 +4499,18 @@ function assertAggregatableScalarField(model, agg, fieldName) {
4306
4499
  }
4307
4500
  }
4308
4501
  function pushAggregateFieldSql(fields, aggFn, alias, agg, fieldName, model) {
4309
- const outAlias = `${agg}.${fieldName}`;
4502
+ const outAlias = agg + "." + fieldName;
4310
4503
  fields.push(
4311
- `${aggFn}(${col(alias, fieldName, model)}) ${SQL_TEMPLATES.AS} ${quote(outAlias)}`
4504
+ aggFn + "(" + col(alias, fieldName, model) + ") " + SQL_TEMPLATES.AS + " " + quote2(outAlias)
4312
4505
  );
4313
4506
  }
4314
4507
  function addAggregateFields(fields, args, alias, model) {
4315
4508
  for (const [agg, aggFn] of AGGREGATES) {
4316
4509
  const obj = getAggregateSelectionObject(args, agg);
4317
4510
  if (!obj) continue;
4318
- for (const [fieldName, selection] of Object.entries(obj)) {
4511
+ for (const fieldName in obj) {
4512
+ if (!Object.prototype.hasOwnProperty.call(obj, fieldName)) continue;
4513
+ const selection = obj[fieldName];
4319
4514
  if (fieldName === "_all")
4320
4515
  throw new Error(`'${agg}' does not support '_all'`);
4321
4516
  if (!isTruthySelection(selection)) continue;
@@ -4339,22 +4534,23 @@ function buildAggregateSql(args, whereResult, tableName, alias, model) {
4339
4534
  throw new Error("buildAggregateSql requires at least one aggregate field");
4340
4535
  }
4341
4536
  const selectClause = aggFields.join(SQL_SEPARATORS.FIELD_LIST);
4342
- const whereClause = isValidWhereClause(whereResult.clause) ? `${SQL_TEMPLATES.WHERE} ${whereResult.clause}` : "";
4343
- const sql = [
4537
+ const whereClause = isValidWhereClause(whereResult.clause) ? SQL_TEMPLATES.WHERE + " " + whereResult.clause : "";
4538
+ const parts = [
4344
4539
  SQL_TEMPLATES.SELECT,
4345
4540
  selectClause,
4346
4541
  SQL_TEMPLATES.FROM,
4347
4542
  tableName,
4348
- alias,
4349
- whereClause
4350
- ].filter((x) => x && String(x).trim().length > 0).join(" ").trim();
4543
+ alias
4544
+ ];
4545
+ if (whereClause) parts.push(whereClause);
4546
+ const sql = parts.join(" ").trim();
4351
4547
  validateSelectQuery(sql);
4352
4548
  validateParamConsistency(sql, whereResult.params);
4353
- return Object.freeze({
4549
+ return {
4354
4550
  sql,
4355
- params: Object.freeze([...whereResult.params]),
4356
- paramMappings: Object.freeze([...whereResult.paramMappings])
4357
- });
4551
+ params: whereResult.params,
4552
+ paramMappings: whereResult.paramMappings
4553
+ };
4358
4554
  }
4359
4555
  function assertGroupByBy(args, model) {
4360
4556
  if (!isNotNullish(args.by) || !isNonEmptyArray(args.by)) {
@@ -4382,8 +4578,8 @@ function buildGroupByHaving(args, alias, params, model, dialect) {
4382
4578
  if (!isNotNullish(args.having)) return "";
4383
4579
  if (!isPlainObject(args.having)) throw new Error("having must be an object");
4384
4580
  const h = buildHavingClause(args.having, alias, params, model, dialect);
4385
- if (!h || h.trim().length === 0) return "";
4386
- return `${SQL_TEMPLATES.HAVING} ${h}`;
4581
+ if (!h || h.length === 0) return "";
4582
+ return SQL_TEMPLATES.HAVING + " " + h;
4387
4583
  }
4388
4584
  function buildGroupBySql(args, whereResult, tableName, alias, model, dialect) {
4389
4585
  assertSafeAlias(alias);
@@ -4398,29 +4594,28 @@ function buildGroupBySql(args, whereResult, tableName, alias, model, dialect) {
4398
4594
  byFields
4399
4595
  );
4400
4596
  const havingClause = buildGroupByHaving(args, alias, params, model, d);
4401
- const whereClause = isValidWhereClause(whereResult.clause) ? `${SQL_TEMPLATES.WHERE} ${whereResult.clause}` : "";
4402
- const sql = [
4597
+ const whereClause = isValidWhereClause(whereResult.clause) ? SQL_TEMPLATES.WHERE + " " + whereResult.clause : "";
4598
+ const parts = [
4403
4599
  SQL_TEMPLATES.SELECT,
4404
4600
  selectFields,
4405
4601
  SQL_TEMPLATES.FROM,
4406
4602
  tableName,
4407
- alias,
4408
- whereClause,
4409
- SQL_TEMPLATES.GROUP_BY,
4410
- groupFields,
4411
- havingClause
4412
- ].filter((x) => x && String(x).trim().length > 0).join(" ").trim();
4603
+ alias
4604
+ ];
4605
+ if (whereClause) parts.push(whereClause);
4606
+ parts.push(SQL_TEMPLATES.GROUP_BY, groupFields);
4607
+ if (havingClause) parts.push(havingClause);
4608
+ const sql = parts.join(" ").trim();
4413
4609
  const snapshot = params.snapshot();
4610
+ const allParams = [...whereResult.params, ...snapshot.params];
4611
+ const allMappings = [...whereResult.paramMappings, ...snapshot.mappings];
4414
4612
  validateSelectQuery(sql);
4415
- validateParamConsistency(sql, [...whereResult.params, ...snapshot.params]);
4416
- return Object.freeze({
4613
+ validateParamConsistency(sql, allParams);
4614
+ return {
4417
4615
  sql,
4418
- params: Object.freeze([...whereResult.params, ...snapshot.params]),
4419
- paramMappings: Object.freeze([
4420
- ...whereResult.paramMappings,
4421
- ...snapshot.mappings
4422
- ])
4423
- });
4616
+ params: allParams,
4617
+ paramMappings: allMappings
4618
+ };
4424
4619
  }
4425
4620
  function buildCountSql(whereResult, tableName, alias, skip, _dialect) {
4426
4621
  assertSafeAlias(alias);
@@ -4448,24 +4643,25 @@ function buildCountSql(whereResult, tableName, alias, skip, _dialect) {
4448
4643
  );
4449
4644
  }
4450
4645
  }
4451
- const whereClause = isValidWhereClause(whereResult.clause) ? `${SQL_TEMPLATES.WHERE} ${whereResult.clause}` : "";
4452
- const sql = [
4646
+ const whereClause = isValidWhereClause(whereResult.clause) ? SQL_TEMPLATES.WHERE + " " + whereResult.clause : "";
4647
+ const parts = [
4453
4648
  SQL_TEMPLATES.SELECT,
4454
4649
  SQL_TEMPLATES.COUNT_ALL,
4455
4650
  SQL_TEMPLATES.AS,
4456
- quote("_count._all"),
4651
+ quote2("_count._all"),
4457
4652
  SQL_TEMPLATES.FROM,
4458
4653
  tableName,
4459
- alias,
4460
- whereClause
4461
- ].filter((x) => x && String(x).trim().length > 0).join(" ").trim();
4654
+ alias
4655
+ ];
4656
+ if (whereClause) parts.push(whereClause);
4657
+ const sql = parts.join(" ").trim();
4462
4658
  validateSelectQuery(sql);
4463
4659
  validateParamConsistency(sql, whereResult.params);
4464
- return Object.freeze({
4660
+ return {
4465
4661
  sql,
4466
- params: Object.freeze([...whereResult.params]),
4467
- paramMappings: Object.freeze([...whereResult.paramMappings])
4468
- });
4662
+ params: whereResult.params,
4663
+ paramMappings: whereResult.paramMappings
4664
+ };
4469
4665
  }
4470
4666
  function safeAlias(input) {
4471
4667
  const raw = String(input).toLowerCase();
@@ -4907,7 +5103,7 @@ function transformEnumValues(modelName: string, obj: any, currentPath: string[]
4907
5103
  const enumType = modelFields[key]
4908
5104
 
4909
5105
  if (enumType) {
4910
- if (value && typeof value === 'object' && !Array.isArray(value)) {
5106
+ if (value && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)) {
4911
5107
  const transformedOperators: any = {}
4912
5108
  for (const [op, opValue] of Object.entries(value)) {
4913
5109
  transformedOperators[op] = transformEnumInValue(opValue, enumType)
@@ -4916,6 +5112,8 @@ function transformEnumValues(modelName: string, obj: any, currentPath: string[]
4916
5112
  } else {
4917
5113
  transformed[key] = transformEnumInValue(value, enumType)
4918
5114
  }
5115
+ } else if (value instanceof Date) {
5116
+ transformed[key] = value
4919
5117
  } else if (typeof value === 'object' && value !== null) {
4920
5118
  transformed[key] = transformEnumValues(modelName, value, newPath)
4921
5119
  } else {