prisma-sql 1.45.0 → 1.47.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.45.0",
59
+ version: "1.47.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",
@@ -644,20 +644,21 @@ function isEmptyWhere(where) {
644
644
  if (!isNotNullish(where)) return true;
645
645
  return Object.keys(where).length === 0;
646
646
  }
647
+ function sqlPreview(sql) {
648
+ const s = String(sql);
649
+ if (s.length <= 160) return s;
650
+ return `${s.slice(0, 160)}...`;
651
+ }
647
652
  function validateSelectQuery(sql) {
648
653
  if (!hasValidContent(sql)) {
649
654
  throw new Error("CRITICAL: Generated empty SQL query");
650
655
  }
651
656
  if (!hasRequiredKeywords(sql)) {
652
- throw new Error(
653
- `CRITICAL: Invalid SQL structure. SQL: ${sql.substring(0, 100)}...`
654
- );
657
+ throw new Error(`CRITICAL: Invalid SQL structure. SQL: ${sqlPreview(sql)}`);
655
658
  }
656
659
  }
657
- function sqlPreview(sql) {
658
- return `${sql.substring(0, 100)}...`;
659
- }
660
- function parseDollarNumber(sql, start, n) {
660
+ function parseDollarNumber(sql, start) {
661
+ const n = sql.length;
661
662
  let i = start;
662
663
  let num = 0;
663
664
  let hasDigit = false;
@@ -668,14 +669,14 @@ function parseDollarNumber(sql, start, n) {
668
669
  num = num * 10 + (c - 48);
669
670
  i++;
670
671
  }
671
- if (!hasDigit || num <= 0) return { next: i, num: 0, ok: false };
672
- return { next: i, num, ok: true };
672
+ if (!hasDigit || num <= 0) return { next: i, num: 0 };
673
+ return { next: i, num };
673
674
  }
674
675
  function scanDollarPlaceholders(sql, markUpTo) {
675
676
  const seen = new Uint8Array(markUpTo + 1);
676
- let count = 0;
677
677
  let min = Number.POSITIVE_INFINITY;
678
678
  let max = 0;
679
+ let sawAny = false;
679
680
  const n = sql.length;
680
681
  let i = 0;
681
682
  while (i < n) {
@@ -683,15 +684,19 @@ function scanDollarPlaceholders(sql, markUpTo) {
683
684
  i++;
684
685
  continue;
685
686
  }
686
- const { next, num, ok } = parseDollarNumber(sql, i + 1, n);
687
- i = next;
688
- if (!ok) continue;
689
- count++;
687
+ const parsed = parseDollarNumber(sql, i + 1);
688
+ i = parsed.next;
689
+ const num = parsed.num;
690
+ if (num === 0) continue;
691
+ sawAny = true;
690
692
  if (num < min) min = num;
691
693
  if (num > max) max = num;
692
694
  if (num <= markUpTo) seen[num] = 1;
693
695
  }
694
- return { count, min, max, seen };
696
+ if (!sawAny) {
697
+ return { min: 0, max: 0, seen, sawAny: false };
698
+ }
699
+ return { min, max, seen, sawAny: true };
695
700
  }
696
701
  function assertNoGapsDollar(scan, rangeMin, rangeMax, sql) {
697
702
  for (let k = rangeMin; k <= rangeMax; k++) {
@@ -704,124 +709,70 @@ function assertNoGapsDollar(scan, rangeMin, rangeMax, sql) {
704
709
  }
705
710
  function validateParamConsistency(sql, params) {
706
711
  const paramLen = params.length;
707
- if (paramLen === 0) {
708
- if (sql.indexOf("$") === -1) return;
709
- }
710
712
  const scan = scanDollarPlaceholders(sql, paramLen);
711
- if (scan.count === 0) {
712
- if (paramLen !== 0) {
713
+ if (paramLen === 0) {
714
+ if (scan.sawAny) {
713
715
  throw new Error(
714
- `CRITICAL: Parameter mismatch - SQL has no placeholders but ${paramLen} params provided.`
716
+ `CRITICAL: SQL contains placeholders but params is empty. SQL: ${sqlPreview(sql)}`
715
717
  );
716
718
  }
717
719
  return;
718
720
  }
719
- if (scan.max !== paramLen) {
721
+ if (!scan.sawAny) {
720
722
  throw new Error(
721
- `CRITICAL: Parameter mismatch - SQL max placeholder is $${scan.max} but ${paramLen} params provided. This will cause SQL execution to fail. SQL: ${sqlPreview(sql)}`
723
+ `CRITICAL: SQL is missing placeholders ($1..$${paramLen}) but params has length ${paramLen}. SQL: ${sqlPreview(sql)}`
722
724
  );
723
725
  }
724
- assertNoGapsDollar(scan, 1, scan.max, sql);
725
- }
726
- function needsQuoting(id) {
727
- if (!isNonEmptyString(id)) return true;
728
- const isKeyword = SQL_KEYWORDS.has(id.toLowerCase());
729
- if (isKeyword) return true;
730
- const isValidIdentifier = REGEX_CACHE.VALID_IDENTIFIER.test(id);
731
- return !isValidIdentifier;
732
- }
733
- function validateParamConsistencyFragment(sql, params) {
734
- const paramLen = params.length;
735
- const scan = scanDollarPlaceholders(sql, paramLen);
736
- if (scan.max === 0) return;
737
- if (scan.max > paramLen) {
726
+ if (scan.min !== 1) {
738
727
  throw new Error(
739
- `CRITICAL: Parameter mismatch - SQL references $${scan.max} but only ${paramLen} params provided. SQL: ${sqlPreview(sql)}`
728
+ `CRITICAL: Placeholder range must start at $1, got min=$${scan.min}. SQL: ${sqlPreview(sql)}`
740
729
  );
741
730
  }
742
- assertNoGapsDollar(scan, scan.min, scan.max, sql);
743
- }
744
- function assertOrThrow(condition, message) {
745
- if (!condition) throw new Error(message);
746
- }
747
- function parseSqlitePlaceholderIndices(sql) {
748
- const re = /\?(?:(\d+))?/g;
749
- const indices = [];
750
- let anonCount = 0;
751
- let sawNumbered = false;
752
- let sawAnonymous = false;
753
- for (const m of sql.matchAll(re)) {
754
- const n = m[1];
755
- if (n) {
756
- sawNumbered = true;
757
- indices.push(parseInt(n, 10));
758
- } else {
759
- sawAnonymous = true;
760
- anonCount += 1;
761
- indices.push(anonCount);
762
- }
731
+ if (scan.max !== paramLen) {
732
+ throw new Error(
733
+ `CRITICAL: Placeholder max must match params length. max=$${scan.max}, params=${paramLen}. SQL: ${sqlPreview(sql)}`
734
+ );
763
735
  }
764
- return { indices, sawNumbered, sawAnonymous };
736
+ assertNoGapsDollar(scan, 1, paramLen, sql);
765
737
  }
766
- function maxIndex(indices) {
767
- return indices.length > 0 ? Math.max(...indices) : 0;
738
+ function countQuestionMarkPlaceholders(sql) {
739
+ const s = String(sql);
740
+ let count = 0;
741
+ for (let i = 0; i < s.length; i++) {
742
+ if (s.charCodeAt(i) === 63) count++;
743
+ }
744
+ return count;
768
745
  }
769
- function ensureSequentialIndices(seen, max, prefix) {
770
- for (let i = 1; i <= max; i++) {
771
- assertOrThrow(
772
- seen.has(i),
773
- `CRITICAL: Missing SQL placeholder ${prefix}${i} - placeholders must be sequential 1..${max}.`
746
+ function validateQuestionMarkConsistency(sql, params) {
747
+ const expected = params.length;
748
+ const found = countQuestionMarkPlaceholders(sql);
749
+ if (expected !== found) {
750
+ throw new Error(
751
+ `CRITICAL: Parameter mismatch - expected ${expected} '?' placeholders, found ${found}. SQL: ${sqlPreview(sql)}`
774
752
  );
775
753
  }
776
754
  }
777
- function validateSqlitePlaceholders(sql, params) {
778
- const paramLen = params.length;
779
- const { indices, sawNumbered, sawAnonymous } = parseSqlitePlaceholderIndices(sql);
780
- if (indices.length === 0) {
781
- if (paramLen !== 0) {
782
- throw new Error(
783
- `CRITICAL: Parameter mismatch - SQL has no sqlite placeholders but ${paramLen} params provided. SQL: ${sqlPreview(sql)}`
784
- );
785
- }
755
+ function validateParamConsistencyByDialect(sql, params, dialect) {
756
+ if (dialect === "postgres") {
757
+ validateParamConsistency(sql, params);
786
758
  return;
787
759
  }
788
- assertOrThrow(
789
- !(sawNumbered && sawAnonymous),
790
- `CRITICAL: Mixed sqlite placeholders ('?' and '?NNN') are not supported.`
791
- );
792
- const max = maxIndex(indices);
793
- assertOrThrow(
794
- max === paramLen,
795
- `CRITICAL: SQL placeholder max mismatch - max is ?${max}, but params length is ${paramLen}. SQL: ${sqlPreview(sql)}`
796
- );
797
- const set = new Set(indices);
798
- ensureSequentialIndices(set, max, "?");
799
- }
800
- function validateDollarPlaceholders(sql, params) {
801
- validateParamConsistency(sql, params);
802
- }
803
- function detectPlaceholderStyle(sql) {
804
- const hasDollar = /\$\d+/.test(sql);
805
- const hasSqliteQ = /\?(?:\d+)?/.test(sql);
806
- return { hasDollar, hasSqliteQ };
807
- }
808
- function validateParamConsistencyByDialect(sql, params, dialect) {
809
- const { hasDollar, hasSqliteQ } = detectPlaceholderStyle(sql);
810
- if (dialect !== "sqlite") {
811
- if (hasSqliteQ && !hasDollar) {
812
- throw new Error(
813
- `CRITICAL: Non-sqlite dialect query contains sqlite '?' placeholders. SQL: ${sqlPreview(sql)}`
814
- );
815
- }
816
- return validateDollarPlaceholders(sql, params);
760
+ if (dialect === "sqlite") {
761
+ validateQuestionMarkConsistency(sql, params);
762
+ return;
817
763
  }
818
- if (hasDollar && hasSqliteQ) {
819
- throw new Error(
820
- `CRITICAL: Mixed placeholder styles ($N and ?/ ?NNN) are not supported. SQL: ${sqlPreview(sql)}`
821
- );
764
+ if (dialect === "mysql" || dialect === "mariadb") {
765
+ validateQuestionMarkConsistency(sql, params);
766
+ return;
822
767
  }
823
- if (hasSqliteQ) return validateSqlitePlaceholders(sql, params);
824
- return validateDollarPlaceholders(sql, params);
768
+ validateParamConsistency(sql, params);
769
+ }
770
+ function needsQuoting(identifier) {
771
+ const s = String(identifier);
772
+ if (!REGEX_CACHE.VALID_IDENTIFIER.test(s)) return true;
773
+ const lowered = s.toLowerCase();
774
+ if (SQL_KEYWORDS.has(lowered)) return true;
775
+ return false;
825
776
  }
826
777
 
827
778
  // src/builder/shared/sql-utils.ts
@@ -1320,6 +1271,40 @@ function ensureDeterministicOrderByInput(args) {
1320
1271
  return addIdTiebreaker(orderBy);
1321
1272
  }
1322
1273
 
1274
+ // src/builder/shared/validators/field-assertions.ts
1275
+ var NUMERIC_TYPES = /* @__PURE__ */ new Set(["Int", "Float", "Decimal", "BigInt"]);
1276
+ function assertScalarField(model, fieldName, context) {
1277
+ const field = getFieldInfo(model, fieldName);
1278
+ if (!field) {
1279
+ throw createError(
1280
+ `${context} references unknown field '${fieldName}' on model ${model.name}`,
1281
+ {
1282
+ field: fieldName,
1283
+ modelName: model.name,
1284
+ availableFields: model.fields.map((f) => f.name)
1285
+ }
1286
+ );
1287
+ }
1288
+ if (field.isRelation) {
1289
+ throw createError(
1290
+ `${context} does not support relation field '${fieldName}'`,
1291
+ { field: fieldName, modelName: model.name }
1292
+ );
1293
+ }
1294
+ return field;
1295
+ }
1296
+ function assertNumericField(model, fieldName, context) {
1297
+ const field = assertScalarField(model, fieldName, context);
1298
+ const baseType = field.type.replace(/\[\]|\?/g, "");
1299
+ if (!NUMERIC_TYPES.has(baseType)) {
1300
+ throw createError(
1301
+ `${context} requires numeric field, got '${field.type}'`,
1302
+ { field: fieldName, modelName: model.name }
1303
+ );
1304
+ }
1305
+ return field;
1306
+ }
1307
+
1323
1308
  // src/builder/pagination.ts
1324
1309
  var MAX_LIMIT_OFFSET = 2147483647;
1325
1310
  function parseDirectionRaw(raw, errorLabel) {
@@ -1360,38 +1345,31 @@ function parseOrderByValue(v, fieldName) {
1360
1345
  assertAllowedOrderByKeys(obj, fieldName);
1361
1346
  return { direction, nulls };
1362
1347
  }
1363
- function normalizeFiniteInteger(name, v) {
1364
- if (typeof v !== "number" || !Number.isFinite(v) || !Number.isInteger(v)) {
1365
- throw new Error(`${name} must be an integer`);
1366
- }
1367
- return v;
1368
- }
1369
1348
  function normalizeNonNegativeInt(name, v) {
1370
1349
  if (schemaParser.isDynamicParameter(v)) return v;
1371
- const n = normalizeFiniteInteger(name, v);
1372
- if (n < 0) {
1373
- throw new Error(`${name} must be >= 0`);
1374
- }
1375
- if (n > MAX_LIMIT_OFFSET) {
1376
- throw new Error(`${name} must be <= ${MAX_LIMIT_OFFSET}`);
1377
- }
1378
- return n;
1379
- }
1380
- function hasNonNullishProp(v, key) {
1381
- return isPlainObject(v) && key in v && isNotNullish(v[key]);
1350
+ const result = normalizeIntLike(name, v, {
1351
+ min: 0,
1352
+ max: MAX_LIMIT_OFFSET,
1353
+ allowZero: true
1354
+ });
1355
+ if (result === void 0)
1356
+ throw new Error(`${name} normalization returned undefined`);
1357
+ return result;
1382
1358
  }
1383
- function normalizeIntegerOrDynamic(name, v) {
1359
+ function normalizeIntAllowNegative(name, v) {
1384
1360
  if (schemaParser.isDynamicParameter(v)) return v;
1385
1361
  const result = normalizeIntLike(name, v, {
1386
1362
  min: Number.MIN_SAFE_INTEGER,
1387
1363
  max: MAX_LIMIT_OFFSET,
1388
1364
  allowZero: true
1389
1365
  });
1390
- if (result === void 0) {
1366
+ if (result === void 0)
1391
1367
  throw new Error(`${name} normalization returned undefined`);
1392
- }
1393
1368
  return result;
1394
1369
  }
1370
+ function hasNonNullishProp(v, key) {
1371
+ return isPlainObject(v) && key in v && isNotNullish(v[key]);
1372
+ }
1395
1373
  function readSkipTake(relArgs) {
1396
1374
  const hasSkip = hasNonNullishProp(relArgs, "skip");
1397
1375
  const hasTake = hasNonNullishProp(relArgs, "take");
@@ -1405,7 +1383,7 @@ function readSkipTake(relArgs) {
1405
1383
  }
1406
1384
  const obj = relArgs;
1407
1385
  const skipVal = hasSkip ? normalizeNonNegativeInt("skip", obj.skip) : void 0;
1408
- const takeVal = hasTake ? normalizeIntegerOrDynamic("take", obj.take) : void 0;
1386
+ const takeVal = hasTake ? normalizeIntAllowNegative("take", obj.take) : void 0;
1409
1387
  return { hasSkip, hasTake, skipVal, takeVal };
1410
1388
  }
1411
1389
  function buildOrderByFragment(entries, alias, dialect, model) {
@@ -1431,9 +1409,7 @@ function buildOrderByFragment(entries, alias, dialect, model) {
1431
1409
  return out.join(SQL_SEPARATORS.ORDER_BY);
1432
1410
  }
1433
1411
  function defaultNullsFor(dialect, direction) {
1434
- if (dialect === "postgres") {
1435
- return direction === "asc" ? "last" : "first";
1436
- }
1412
+ if (dialect === "postgres") return direction === "asc" ? "last" : "first";
1437
1413
  return direction === "asc" ? "first" : "last";
1438
1414
  }
1439
1415
  function ensureCursorFieldsInOrder(orderEntries, cursorEntries) {
@@ -1450,9 +1426,8 @@ function ensureCursorFieldsInOrder(orderEntries, cursorEntries) {
1450
1426
  }
1451
1427
  function buildCursorFilterParts(cursor, cursorAlias, params, model) {
1452
1428
  const entries = Object.entries(cursor);
1453
- if (entries.length === 0) {
1429
+ if (entries.length === 0)
1454
1430
  throw new Error("cursor must have at least one field");
1455
- }
1456
1431
  const placeholdersByField = /* @__PURE__ */ new Map();
1457
1432
  const parts = [];
1458
1433
  for (const [field, value] of entries) {
@@ -1506,25 +1481,29 @@ function buildOrderEntries(orderBy) {
1506
1481
  if (typeof value === "string") {
1507
1482
  entries.push({ field, direction: value });
1508
1483
  } else {
1509
- entries.push({
1510
- field,
1511
- direction: value.direction,
1512
- nulls: value.nulls
1513
- });
1484
+ entries.push({ field, direction: value.direction, nulls: value.nulls });
1514
1485
  }
1515
1486
  }
1516
1487
  }
1517
1488
  return entries;
1518
1489
  }
1519
1490
  function buildCursorCteSelectList(cursorEntries, orderEntries, model) {
1520
- const set = /* @__PURE__ */ new Set();
1521
- for (const [f] of cursorEntries) set.add(f);
1522
- for (const e of orderEntries) set.add(e.field);
1523
- const cols = [...set].map((f) => quoteColumn(model, f));
1524
- if (cols.length === 0) {
1525
- throw new Error("cursor cte select list is empty");
1491
+ const seen = /* @__PURE__ */ new Set();
1492
+ const ordered = [];
1493
+ for (const [f] of cursorEntries) {
1494
+ if (!seen.has(f)) {
1495
+ seen.add(f);
1496
+ ordered.push(f);
1497
+ }
1526
1498
  }
1527
- return cols.join(SQL_SEPARATORS.FIELD_LIST);
1499
+ for (const e of orderEntries) {
1500
+ if (!seen.has(e.field)) {
1501
+ seen.add(e.field);
1502
+ ordered.push(e.field);
1503
+ }
1504
+ }
1505
+ if (ordered.length === 0) throw new Error("cursor cte select list is empty");
1506
+ return ordered.map((f) => quoteColumn(model, f)).join(SQL_SEPARATORS.FIELD_LIST);
1528
1507
  }
1529
1508
  function truncateIdent(name, maxLen) {
1530
1509
  const s = String(name);
@@ -1544,19 +1523,22 @@ function buildCursorNames(outerAlias) {
1544
1523
  }
1545
1524
  return { cteName, srcAlias };
1546
1525
  }
1526
+ function assertCursorAndOrderFieldsScalar(model, cursor, orderEntries) {
1527
+ 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");
1530
+ }
1547
1531
  function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect, model) {
1548
1532
  var _a;
1549
1533
  assertSafeTableRef(tableName);
1550
1534
  assertSafeAlias(alias);
1551
1535
  const d = dialect != null ? dialect : getGlobalDialect();
1552
1536
  const cursorEntries = Object.entries(cursor);
1553
- if (cursorEntries.length === 0) {
1537
+ if (cursorEntries.length === 0)
1554
1538
  throw new Error("cursor must have at least one field");
1555
- }
1556
1539
  const { cteName, srcAlias } = buildCursorNames(alias);
1557
1540
  assertSafeAlias(cteName);
1558
1541
  assertSafeAlias(srcAlias);
1559
- const { whereSql: cursorWhereSql, placeholdersByField } = buildCursorFilterParts(cursor, srcAlias, params, model);
1560
1542
  const deterministicOrderBy = ensureDeterministicOrderByInput({
1561
1543
  orderBy,
1562
1544
  model,
@@ -1571,6 +1553,8 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
1571
1553
  } else {
1572
1554
  orderEntries = ensureCursorFieldsInOrder(orderEntries, cursorEntries);
1573
1555
  }
1556
+ assertCursorAndOrderFieldsScalar(model, cursor, orderEntries);
1557
+ const { whereSql: cursorWhereSql, placeholdersByField } = buildCursorFilterParts(cursor, srcAlias, params, model);
1574
1558
  const cursorOrderBy = orderEntries.map(
1575
1559
  (e) => `${srcAlias}.${quoteColumn(model, e.field)} ${e.direction.toUpperCase()}`
1576
1560
  ).join(", ");
@@ -1593,9 +1577,7 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
1593
1577
  params,
1594
1578
  model
1595
1579
  );
1596
- const getValueExpr = (field) => {
1597
- return `(SELECT ${quoteColumn(model, field)} FROM ${cteName})`;
1598
- };
1580
+ const getValueExpr = (field) => `(SELECT ${quoteColumn(model, field)} FROM ${cteName})`;
1599
1581
  const orClauses = [];
1600
1582
  for (let level = 0; level < orderEntries.length; level++) {
1601
1583
  const andParts = [];
@@ -1639,9 +1621,7 @@ function normalizeTakeLike(v) {
1639
1621
  max: MAX_LIMIT_OFFSET,
1640
1622
  allowZero: true
1641
1623
  });
1642
- if (typeof n === "number") {
1643
- if (n === 0) return 0;
1644
- }
1624
+ if (typeof n === "number" && n === 0) return 0;
1645
1625
  return n;
1646
1626
  }
1647
1627
  function normalizeSkipLike(v) {
@@ -2820,22 +2800,6 @@ function buildWhereClause(where, options) {
2820
2800
  };
2821
2801
  const result = whereBuilderInstance.build(where, ctx);
2822
2802
  const publicResult = toPublicResult(result.clause, result.joins, params);
2823
- if (!options.isSubquery) {
2824
- const nums = [...publicResult.clause.matchAll(/\$(\d+)/g)].map(
2825
- (m) => parseInt(m[1], 10)
2826
- );
2827
- if (nums.length > 0) {
2828
- const min = Math.min(...nums);
2829
- if (min === 1) {
2830
- validateParamConsistency(publicResult.clause, publicResult.params);
2831
- } else {
2832
- validateParamConsistencyFragment(
2833
- publicResult.clause,
2834
- publicResult.params
2835
- );
2836
- }
2837
- }
2838
- }
2839
2803
  return publicResult;
2840
2804
  }
2841
2805
 
@@ -3031,9 +2995,8 @@ function validateOrderByForModel(model, orderBy) {
3031
2995
  throw new Error("orderBy array entries must have exactly one field");
3032
2996
  }
3033
2997
  const fieldName = String(entries[0][0]).trim();
3034
- if (fieldName.length === 0) {
2998
+ if (fieldName.length === 0)
3035
2999
  throw new Error("orderBy field name cannot be empty");
3036
- }
3037
3000
  if (!scalarSet.has(fieldName)) {
3038
3001
  throw new Error(
3039
3002
  `orderBy references unknown or non-scalar field '${fieldName}' on model ${model.name}`
@@ -3092,33 +3055,22 @@ function extractRelationPaginationConfig(relArgs) {
3092
3055
  function maybeReverseNegativeTake(takeVal, hasOrderBy, orderByInput) {
3093
3056
  if (typeof takeVal !== "number") return { takeVal, orderByInput };
3094
3057
  if (takeVal >= 0) return { takeVal, orderByInput };
3095
- if (!hasOrderBy) {
3058
+ if (!hasOrderBy)
3096
3059
  throw new Error("Negative take requires orderBy for deterministic results");
3097
- }
3098
3060
  return {
3099
3061
  takeVal: Math.abs(takeVal),
3100
3062
  orderByInput: reverseOrderByInput(orderByInput)
3101
3063
  };
3102
3064
  }
3103
- function ensureDeterministicOrderByForInclude(args) {
3065
+ function finalizeOrderByForInclude(args) {
3066
+ if (args.hasOrderBy && isNotNullish(args.orderByInput)) {
3067
+ validateOrderByForModel(args.relModel, args.orderByInput);
3068
+ }
3104
3069
  if (!args.hasPagination) {
3105
- if (args.hasOrderBy && isNotNullish(args.orderByInput)) {
3106
- validateOrderByForModel(args.relModel, args.orderByInput);
3107
- }
3108
3070
  return args.orderByInput;
3109
3071
  }
3110
- if (!args.hasOrderBy) {
3111
- return ensureDeterministicOrderByInput({
3112
- orderBy: void 0,
3113
- model: args.relModel,
3114
- parseValue: parseOrderByValue
3115
- });
3116
- }
3117
- if (isNotNullish(args.orderByInput)) {
3118
- validateOrderByForModel(args.relModel, args.orderByInput);
3119
- }
3120
3072
  return ensureDeterministicOrderByInput({
3121
- orderBy: args.orderByInput,
3073
+ orderBy: args.hasOrderBy ? args.orderByInput : void 0,
3122
3074
  model: args.relModel,
3123
3075
  parseValue: parseOrderByValue
3124
3076
  });
@@ -3222,11 +3174,7 @@ function buildListIncludeSpec(args) {
3222
3174
  joinPredicate: args.joinPredicate,
3223
3175
  whereClause: args.whereClause
3224
3176
  });
3225
- return Object.freeze({
3226
- name: args.relName,
3227
- sql: sql2,
3228
- isOneToOne: false
3229
- });
3177
+ return Object.freeze({ name: args.relName, sql: sql2, isOneToOne: false });
3230
3178
  }
3231
3179
  const rowAlias = args.ctx.aliasGen.next(`${args.relName}_row`);
3232
3180
  let base = buildBaseSql({
@@ -3237,9 +3185,7 @@ function buildListIncludeSpec(args) {
3237
3185
  joinPredicate: args.joinPredicate,
3238
3186
  whereClause: args.whereClause
3239
3187
  });
3240
- if (args.orderBySql) {
3241
- base += ` ${SQL_TEMPLATES.ORDER_BY} ${args.orderBySql}`;
3242
- }
3188
+ if (args.orderBySql) base += ` ${SQL_TEMPLATES.ORDER_BY} ${args.orderBySql}`;
3243
3189
  base = appendLimitOffset(
3244
3190
  base,
3245
3191
  args.ctx.dialect,
@@ -3250,11 +3196,7 @@ function buildListIncludeSpec(args) {
3250
3196
  );
3251
3197
  const selectExpr = jsonAgg("row", args.ctx.dialect);
3252
3198
  const sql = `${SQL_TEMPLATES.SELECT} ${selectExpr} ${SQL_TEMPLATES.FROM} (${base}) ${rowAlias}`;
3253
- return Object.freeze({
3254
- name: args.relName,
3255
- sql,
3256
- isOneToOne: false
3257
- });
3199
+ return Object.freeze({ name: args.relName, sql, isOneToOne: false });
3258
3200
  }
3259
3201
  function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
3260
3202
  const relTable = getRelationTableReference(relModel, ctx.dialect);
@@ -3285,7 +3227,7 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
3285
3227
  paginationConfig.orderBy
3286
3228
  );
3287
3229
  const hasPagination = paginationConfig.hasSkip || paginationConfig.hasTake;
3288
- const finalOrderByInput = ensureDeterministicOrderByForInclude({
3230
+ const finalOrderByInput = finalizeOrderByForInclude({
3289
3231
  relModel,
3290
3232
  hasOrderBy: paginationConfig.hasOrderBy,
3291
3233
  orderByInput: adjusted.orderByInput,
@@ -3311,11 +3253,7 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
3311
3253
  skipVal: paginationConfig.skipVal,
3312
3254
  ctx
3313
3255
  });
3314
- return Object.freeze({
3315
- name: relName,
3316
- sql,
3317
- isOneToOne: true
3318
- });
3256
+ return Object.freeze({ name: relName, sql, isOneToOne: true });
3319
3257
  }
3320
3258
  return buildListIncludeSpec({
3321
3259
  relName,
@@ -3332,9 +3270,7 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
3332
3270
  });
3333
3271
  }
3334
3272
  function buildIncludeSqlInternal(args, model, schemas, parentAlias, aliasGen, params, dialect, visitPath = [], depth = 0, stats) {
3335
- if (!stats) {
3336
- stats = { totalIncludes: 0, totalSubqueries: 0, maxDepth: 0 };
3337
- }
3273
+ if (!stats) stats = { totalIncludes: 0, totalSubqueries: 0, maxDepth: 0 };
3338
3274
  if (depth > MAX_INCLUDE_DEPTH) {
3339
3275
  throw new Error(
3340
3276
  `Maximum include depth of ${MAX_INCLUDE_DEPTH} exceeded. Path: ${visitPath.join(" -> ")}. Deep includes cause exponential SQL complexity and performance issues.`
@@ -3373,12 +3309,8 @@ function buildIncludeSqlInternal(args, model, schemas, parentAlias, aliasGen, pa
3373
3309
  `Include too deeply nested: model '${resolved.relModel.name}' appears ${modelOccurrences} times in path: ${currentPath.join(" -> ")}`
3374
3310
  );
3375
3311
  }
3376
- const include = buildSingleInclude(
3377
- relName,
3378
- relArgs,
3379
- resolved.field,
3380
- resolved.relModel,
3381
- {
3312
+ includes.push(
3313
+ buildSingleInclude(relName, relArgs, resolved.field, resolved.relModel, {
3382
3314
  model,
3383
3315
  schemas,
3384
3316
  parentAlias,
@@ -3388,9 +3320,8 @@ function buildIncludeSqlInternal(args, model, schemas, parentAlias, aliasGen, pa
3388
3320
  visitPath: currentPath,
3389
3321
  depth: depth + 1,
3390
3322
  stats
3391
- }
3323
+ })
3392
3324
  );
3393
- includes.push(include);
3394
3325
  }
3395
3326
  return includes;
3396
3327
  }
@@ -3422,11 +3353,10 @@ function resolveCountRelationOrThrow(relName, model, schemas) {
3422
3353
  );
3423
3354
  }
3424
3355
  const field = model.fields.find((f) => f.name === relName);
3425
- if (!field) {
3356
+ if (!field)
3426
3357
  throw new Error(
3427
3358
  `_count.${relName} references unknown relation on model ${model.name}`
3428
3359
  );
3429
- }
3430
3360
  if (!isValidRelationField(field)) {
3431
3361
  throw new Error(
3432
3362
  `_count.${relName} has invalid relation metadata on model ${model.name}`
@@ -3448,9 +3378,8 @@ function defaultReferencesForCount(fkCount) {
3448
3378
  }
3449
3379
  function resolveCountKeyPairs(field) {
3450
3380
  const fkFields = normalizeKeyList(field.foreignKey);
3451
- if (fkFields.length === 0) {
3381
+ if (fkFields.length === 0)
3452
3382
  throw new Error("Relation count requires foreignKey");
3453
- }
3454
3383
  const refsRaw = field.references;
3455
3384
  const refs = normalizeKeyList(refsRaw);
3456
3385
  const refFields = refs.length > 0 ? refs : defaultReferencesForCount(fkFields.length);
@@ -3482,9 +3411,7 @@ function leftJoinOnForCount(args) {
3482
3411
  }
3483
3412
  function nextAliasAvoiding(aliasGen, base, forbidden) {
3484
3413
  let a = aliasGen.next(base);
3485
- while (forbidden.has(a)) {
3486
- a = aliasGen.next(base);
3487
- }
3414
+ while (forbidden.has(a)) a = aliasGen.next(base);
3488
3415
  return a;
3489
3416
  }
3490
3417
  function buildCountJoinAndPair(args) {
@@ -3539,10 +3466,7 @@ function buildRelationCountSql(countSelect, model, schemas, parentAlias, _params
3539
3466
  joins.push(built.joinSql);
3540
3467
  pairs.push(built.pairSql);
3541
3468
  }
3542
- return {
3543
- joins,
3544
- jsonPairs: pairs.join(SQL_SEPARATORS.FIELD_LIST)
3545
- };
3469
+ return { joins, jsonPairs: pairs.join(SQL_SEPARATORS.FIELD_LIST) };
3546
3470
  }
3547
3471
 
3548
3472
  // src/builder/select/assembly.ts
@@ -3578,7 +3502,11 @@ function buildSelectList(baseSelect, extraCols) {
3578
3502
  function finalizeSql(sql, params, dialect) {
3579
3503
  const snapshot = params.snapshot();
3580
3504
  validateSelectQuery(sql);
3581
- validateParamConsistencyByDialect(sql, snapshot.params, dialect);
3505
+ validateParamConsistencyByDialect(
3506
+ sql,
3507
+ snapshot.params,
3508
+ dialect === "sqlite" ? "postgres" : dialect
3509
+ );
3582
3510
  return Object.freeze({
3583
3511
  sql,
3584
3512
  params: snapshot.params,
@@ -3872,40 +3800,6 @@ function constructFinalSql(spec) {
3872
3800
  return finalizeSql(sql, params, dialect);
3873
3801
  }
3874
3802
 
3875
- // src/builder/shared/validators/field-assertions.ts
3876
- var NUMERIC_TYPES = /* @__PURE__ */ new Set(["Int", "Float", "Decimal", "BigInt"]);
3877
- function assertScalarField(model, fieldName, context) {
3878
- const field = getFieldInfo(model, fieldName);
3879
- if (!field) {
3880
- throw createError(
3881
- `${context} references unknown field '${fieldName}' on model ${model.name}`,
3882
- {
3883
- field: fieldName,
3884
- modelName: model.name,
3885
- availableFields: model.fields.map((f) => f.name)
3886
- }
3887
- );
3888
- }
3889
- if (field.isRelation) {
3890
- throw createError(
3891
- `${context} does not support relation field '${fieldName}'`,
3892
- { field: fieldName, modelName: model.name }
3893
- );
3894
- }
3895
- return field;
3896
- }
3897
- function assertNumericField(model, fieldName, context) {
3898
- const field = assertScalarField(model, fieldName, context);
3899
- const baseType = field.type.replace(/\[\]|\?/g, "");
3900
- if (!NUMERIC_TYPES.has(baseType)) {
3901
- throw createError(
3902
- `${context} requires numeric field, got '${field.type}'`,
3903
- { field: fieldName, modelName: model.name }
3904
- );
3905
- }
3906
- return field;
3907
- }
3908
-
3909
3803
  // src/builder/select.ts
3910
3804
  function normalizeOrderByInput2(orderBy) {
3911
3805
  return normalizeOrderByInput(orderBy, parseOrderByValue);
@@ -4159,6 +4053,19 @@ var HAVING_ALLOWED_OPS = /* @__PURE__ */ new Set([
4159
4053
  function isTruthySelection(v) {
4160
4054
  return v === true;
4161
4055
  }
4056
+ function isLogicalKey(key) {
4057
+ return key === LogicalOps.AND || key === LogicalOps.OR || key === LogicalOps.NOT;
4058
+ }
4059
+ function isAggregateKey(key) {
4060
+ return key === "_count" || key === "_sum" || key === "_avg" || key === "_min" || key === "_max";
4061
+ }
4062
+ function assertHavingOp(op) {
4063
+ if (!HAVING_ALLOWED_OPS.has(op)) {
4064
+ throw new Error(
4065
+ `Unsupported HAVING operator '${op}'. Allowed: ${[...HAVING_ALLOWED_OPS].join(", ")}`
4066
+ );
4067
+ }
4068
+ }
4162
4069
  function aggExprForField(aggKey, field, alias, model) {
4163
4070
  if (aggKey === "_count") {
4164
4071
  return field === "_all" ? `COUNT(*)` : `COUNT(${col(alias, field, model)})`;
@@ -4192,18 +4099,9 @@ function normalizeLogicalValue2(operator, value) {
4192
4099
  }
4193
4100
  return out;
4194
4101
  }
4195
- if (isPlainObject(value)) {
4196
- return [value];
4197
- }
4102
+ if (isPlainObject(value)) return [value];
4198
4103
  throw new Error(`${operator} must be an object or array of objects in HAVING`);
4199
4104
  }
4200
- function assertHavingOp(op) {
4201
- if (!HAVING_ALLOWED_OPS.has(op)) {
4202
- throw new Error(
4203
- `Unsupported HAVING operator '${op}'. Allowed: ${[...HAVING_ALLOWED_OPS].join(", ")}`
4204
- );
4205
- }
4206
- }
4207
4105
  function buildNullComparison(expr, op) {
4208
4106
  if (op === Ops.EQUALS) return `${expr} ${SQL_TEMPLATES.IS_NULL}`;
4209
4107
  if (op === Ops.NOT) return `${expr} ${SQL_TEMPLATES.IS_NOT_NULL}`;
@@ -4247,12 +4145,6 @@ function buildSimpleComparison(expr, op, val, params, dialect) {
4247
4145
  }
4248
4146
  return buildBinaryComparison(expr, op, val, params);
4249
4147
  }
4250
- function isLogicalKey(key) {
4251
- return key === LogicalOps.AND || key === LogicalOps.OR || key === LogicalOps.NOT;
4252
- }
4253
- function isAggregateKey(key) {
4254
- return key === "_count" || key === "_sum" || key === "_avg" || key === "_min" || key === "_max";
4255
- }
4256
4148
  function negateClauses(subClauses) {
4257
4149
  if (subClauses.length === 1) return `${SQL_TEMPLATES.NOT} ${subClauses[0]}`;
4258
4150
  return `${SQL_TEMPLATES.NOT} (${subClauses.join(SQL_SEPARATORS.CONDITION_AND)})`;
@@ -4261,50 +4153,10 @@ function combineLogical(key, subClauses) {
4261
4153
  if (key === LogicalOps.NOT) return negateClauses(subClauses);
4262
4154
  return subClauses.join(` ${key} `);
4263
4155
  }
4264
- function buildLogicalClause2(key, value, alias, params, dialect, model) {
4265
- const items = normalizeLogicalValue2(key, value);
4266
- const subClauses = [];
4267
- for (const it of items) {
4268
- const c = buildHavingNode(it, alias, params, dialect, model);
4269
- if (c && c !== "") subClauses.push(`(${c})`);
4270
- }
4271
- if (subClauses.length === 0) return "";
4272
- return combineLogical(key, subClauses);
4273
- }
4274
- function buildHavingEntry(key, value, alias, params, dialect, model) {
4275
- if (isLogicalKey(key)) {
4276
- const logical = buildLogicalClause2(
4277
- key,
4278
- value,
4279
- alias,
4280
- params,
4281
- dialect,
4282
- model
4283
- );
4284
- return logical ? [logical] : [];
4285
- }
4286
- if (isAggregateKey(key)) {
4287
- return buildHavingForAggregateFirstShape(
4288
- key,
4289
- value,
4290
- alias,
4291
- params,
4292
- dialect,
4293
- model
4294
- );
4295
- }
4296
- return buildHavingForFieldFirstShape(
4297
- key,
4298
- value,
4299
- alias,
4300
- params,
4301
- dialect,
4302
- model
4303
- );
4304
- }
4305
4156
  function buildHavingNode(node, alias, params, dialect, model) {
4306
4157
  const clauses = [];
4307
- for (const [key, value] of Object.entries(node)) {
4158
+ const entries = Object.entries(node);
4159
+ for (const [key, value] of entries) {
4308
4160
  const built = buildHavingEntry(key, value, alias, params, dialect, model);
4309
4161
  for (const c of built) {
4310
4162
  if (c && c.trim().length > 0) clauses.push(c);
@@ -4312,11 +4164,20 @@ function buildHavingNode(node, alias, params, dialect, model) {
4312
4164
  }
4313
4165
  return clauses.join(SQL_SEPARATORS.CONDITION_AND);
4314
4166
  }
4167
+ function buildLogicalClause2(key, value, alias, params, dialect, model) {
4168
+ const items = normalizeLogicalValue2(key, value);
4169
+ const subClauses = [];
4170
+ for (const it of items) {
4171
+ const c = buildHavingNode(it, alias, params, dialect, model);
4172
+ if (c && c.trim().length > 0) subClauses.push(`(${c})`);
4173
+ }
4174
+ if (subClauses.length === 0) return "";
4175
+ return combineLogical(key, subClauses);
4176
+ }
4315
4177
  function assertHavingAggTarget(aggKey, field, model) {
4316
4178
  if (field === "_all") {
4317
- if (aggKey !== "_count") {
4179
+ if (aggKey !== "_count")
4318
4180
  throw new Error(`HAVING '${aggKey}' does not support '_all'`);
4319
- }
4320
4181
  return;
4321
4182
  }
4322
4183
  if (aggKey === "_sum" || aggKey === "_avg") {
@@ -4352,29 +4213,50 @@ function buildHavingForFieldFirstShape(fieldName, target, alias, params, dialect
4352
4213
  for (const aggKey of keys) {
4353
4214
  const aggFilter = obj[aggKey];
4354
4215
  if (!isPlainObject(aggFilter)) continue;
4216
+ if (Object.keys(aggFilter).length === 0) continue;
4355
4217
  if (aggKey === "_sum" || aggKey === "_avg") {
4356
4218
  assertNumericField(model, fieldName, "HAVING");
4357
4219
  }
4358
- const entries = Object.entries(aggFilter);
4359
- if (entries.length === 0) continue;
4360
4220
  const expr = aggExprForField(aggKey, fieldName, alias, model);
4361
- const clauses = buildComparisons(
4362
- expr,
4363
- aggFilter,
4221
+ out.push(...buildHavingOpsForExpr(expr, aggFilter, params, dialect));
4222
+ }
4223
+ return out;
4224
+ }
4225
+ function buildHavingEntry(key, value, alias, params, dialect, model) {
4226
+ if (isLogicalKey(key)) {
4227
+ const logical = buildLogicalClause2(
4228
+ key,
4229
+ value,
4230
+ alias,
4364
4231
  params,
4365
4232
  dialect,
4366
- buildSimpleComparison
4233
+ model
4367
4234
  );
4368
- out.push(...clauses);
4235
+ return logical ? [logical] : [];
4369
4236
  }
4370
- return out;
4237
+ if (isAggregateKey(key)) {
4238
+ return buildHavingForAggregateFirstShape(
4239
+ key,
4240
+ value,
4241
+ alias,
4242
+ params,
4243
+ dialect,
4244
+ model
4245
+ );
4246
+ }
4247
+ return buildHavingForFieldFirstShape(
4248
+ key,
4249
+ value,
4250
+ alias,
4251
+ params,
4252
+ dialect,
4253
+ model
4254
+ );
4371
4255
  }
4372
4256
  function buildHavingClause(having, alias, params, model, dialect) {
4373
4257
  if (!isNotNullish(having)) return "";
4374
4258
  const d = dialect != null ? dialect : getGlobalDialect();
4375
- if (!isPlainObject(having)) {
4376
- throw new Error("having must be an object");
4377
- }
4259
+ if (!isPlainObject(having)) throw new Error("having must be an object");
4378
4260
  return buildHavingNode(having, alias, params, d, model);
4379
4261
  }
4380
4262
  function normalizeCountArg(v) {
@@ -4388,9 +4270,6 @@ function pushCountAllField(fields) {
4388
4270
  `${SQL_TEMPLATES.COUNT_ALL} ${SQL_TEMPLATES.AS} ${quote("_count._all")}`
4389
4271
  );
4390
4272
  }
4391
- function assertCountableScalarField(model, fieldName) {
4392
- assertScalarField(model, fieldName, "_count");
4393
- }
4394
4273
  function pushCountField(fields, alias, fieldName, model) {
4395
4274
  const outAlias = `_count.${fieldName}`;
4396
4275
  fields.push(
@@ -4411,7 +4290,7 @@ function addCountFields(fields, countArg, alias, model) {
4411
4290
  ([f, v]) => f !== "_all" && isTruthySelection(v)
4412
4291
  );
4413
4292
  for (const [f] of selected) {
4414
- assertCountableScalarField(model, f);
4293
+ assertScalarField(model, f, "_count");
4415
4294
  pushCountField(fields, alias, f, model);
4416
4295
  }
4417
4296
  }
@@ -4501,9 +4380,7 @@ function buildGroupBySelectParts(args, alias, model, byFields) {
4501
4380
  }
4502
4381
  function buildGroupByHaving(args, alias, params, model, dialect) {
4503
4382
  if (!isNotNullish(args.having)) return "";
4504
- if (!isPlainObject(args.having)) {
4505
- throw new Error("having must be an object");
4506
- }
4383
+ if (!isPlainObject(args.having)) throw new Error("having must be an object");
4507
4384
  const h = buildHavingClause(args.having, alias, params, model, dialect);
4508
4385
  if (!h || h.trim().length === 0) return "";
4509
4386
  return `${SQL_TEMPLATES.HAVING} ${h}`;
@@ -4536,10 +4413,9 @@ function buildGroupBySql(args, whereResult, tableName, alias, model, dialect) {
4536
4413
  const snapshot = params.snapshot();
4537
4414
  validateSelectQuery(sql);
4538
4415
  validateParamConsistency(sql, [...whereResult.params, ...snapshot.params]);
4539
- const mergedParams = [...whereResult.params, ...snapshot.params];
4540
4416
  return Object.freeze({
4541
4417
  sql,
4542
- params: Object.freeze(mergedParams),
4418
+ params: Object.freeze([...whereResult.params, ...snapshot.params]),
4543
4419
  paramMappings: Object.freeze([
4544
4420
  ...whereResult.paramMappings,
4545
4421
  ...snapshot.mappings
@@ -4941,6 +4817,27 @@ function normalizeValue(value: unknown, seen = new WeakSet<object>(), depth = 0)
4941
4817
  return value
4942
4818
  }
4943
4819
 
4820
+ /**
4821
+ * Get nested value from object using dot notation path
4822
+ */
4823
+ function getByPath(obj: any, path: string): unknown {
4824
+ if (!obj || !path) return undefined
4825
+ const keys = path.split('.')
4826
+ let result = obj
4827
+ for (const key of keys) {
4828
+ if (result == null) return undefined
4829
+ result = result[key]
4830
+ }
4831
+ return result
4832
+ }
4833
+
4834
+ /**
4835
+ * Normalize all params in array
4836
+ */
4837
+ function normalizeParams(params: unknown[]): unknown[] {
4838
+ return params.map(p => normalizeValue(p))
4839
+ }
4840
+
4944
4841
 
4945
4842
  export const MODELS: Model[] = ${JSON.stringify(cleanModels, null, 2)}
4946
4843
 
@@ -5081,34 +4978,39 @@ function normalizeQuery(args: any): string {
5081
4978
 
5082
4979
  function extractDynamicParams(args: any, dynamicKeys: string[]): unknown[] {
5083
4980
  const params: unknown[] = []
5084
-
4981
+
5085
4982
  for (const key of dynamicKeys) {
5086
4983
  const parts = key.split(':')
5087
4984
  const lookupKey = parts.length === 2 ? parts[1] : key
5088
- const value = args[lookupKey]
5089
-
4985
+
4986
+ const value =
4987
+ lookupKey.includes('.') ? getByPath(args, lookupKey) : args?.[lookupKey]
4988
+
5090
4989
  if (value === undefined) {
5091
4990
  throw new Error(\`Missing required parameter: \${key}\`)
5092
4991
  }
5093
-
4992
+
5094
4993
  params.push(normalizeValue(value))
5095
4994
  }
5096
-
4995
+
5097
4996
  return params
5098
4997
  }
5099
4998
 
4999
+
5100
5000
  async function executeQuery(client: any, sql: string, params: unknown[]): Promise<unknown[]> {
5001
+ const normalizedParams = normalizeParams(params)
5002
+
5101
5003
  if (DIALECT === 'postgres') {
5102
- return await client.unsafe(sql, params)
5004
+ return await client.unsafe(sql, normalizedParams)
5103
5005
  }
5104
-
5006
+
5105
5007
  const stmt = client.prepare(sql)
5106
-
5008
+
5107
5009
  if (sql.toUpperCase().includes('COUNT(*) AS')) {
5108
- return [stmt.get(...params)]
5010
+ return [stmt.get(...normalizedParams)]
5109
5011
  }
5110
-
5111
- return stmt.all(...params)
5012
+
5013
+ return stmt.all(...normalizedParams)
5112
5014
  }
5113
5015
 
5114
5016
  export function speedExtension(config: {
@@ -5153,18 +5055,21 @@ export function speedExtension(config: {
5153
5055
 
5154
5056
  if (prebakedQuery) {
5155
5057
  sql = prebakedQuery.sql
5156
- params = [...prebakedQuery.params, ...extractDynamicParams(transformedArgs, prebakedQuery.dynamicKeys)]
5058
+ params = normalizeParams([
5059
+ ...prebakedQuery.params,
5060
+ ...extractDynamicParams(transformedArgs, prebakedQuery.dynamicKeys),
5061
+ ])
5157
5062
  prebaked = true
5158
5063
  } else {
5159
5064
  const model = MODELS.find((m) => m.name === modelName)
5160
-
5065
+
5161
5066
  if (!model) {
5162
5067
  return this.$parent[modelName][method](args)
5163
5068
  }
5164
5069
 
5165
5070
  const result = buildSQL(model, MODELS, method, transformedArgs, DIALECT)
5166
5071
  sql = result.sql
5167
- params = result.params
5072
+ params = normalizeParams(result.params as unknown[])
5168
5073
  }
5169
5074
 
5170
5075
  if (debug) {