bun-sqlite-for-rxdb 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -12254,6 +12254,13 @@ function getColumnInfo(path2, schema) {
12254
12254
  if (path2 === schema.primaryKey) {
12255
12255
  return { column: "id", type: "string" };
12256
12256
  }
12257
+ const properties = schema.properties;
12258
+ const fieldSchema = properties?.[path2];
12259
+ if (fieldSchema && typeof fieldSchema === "object" && "type" in fieldSchema) {
12260
+ if (fieldSchema.type === "array") {
12261
+ return { jsonPath: `$.${path2}`, type: "array" };
12262
+ }
12263
+ }
12257
12264
  return { jsonPath: `$.${path2}`, type: "unknown" };
12258
12265
  }
12259
12266
 
@@ -12342,31 +12349,85 @@ function smartRegexToLike(field, pattern, options, schema, fieldName) {
12342
12349
  }
12343
12350
 
12344
12351
  // src/query/operators.ts
12345
- function translateEq(field, value) {
12352
+ function translateEq(field, value, schema, actualFieldName) {
12346
12353
  if (value === null) {
12347
12354
  return { sql: `${field} IS NULL`, args: [] };
12348
12355
  }
12356
+ if (schema && actualFieldName) {
12357
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12358
+ if (field !== "value" && columnInfo.type === "array") {
12359
+ return {
12360
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value = ?)`,
12361
+ args: [value]
12362
+ };
12363
+ }
12364
+ }
12349
12365
  return { sql: `${field} = ?`, args: [value] };
12350
12366
  }
12351
- function translateNe(field, value) {
12367
+ function translateNe(field, value, schema, actualFieldName) {
12352
12368
  if (value === null) {
12353
12369
  return { sql: `${field} IS NOT NULL`, args: [] };
12354
12370
  }
12355
- return { sql: `${field} <> ?`, args: [value] };
12371
+ if (schema && actualFieldName) {
12372
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12373
+ if (field !== "value" && columnInfo.type === "array") {
12374
+ return {
12375
+ sql: `NOT EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value = ?)`,
12376
+ args: [value]
12377
+ };
12378
+ }
12379
+ }
12380
+ return { sql: `(${field} <> ? OR ${field} IS NULL)`, args: [value] };
12356
12381
  }
12357
- function translateGt(field, value) {
12382
+ function translateGt(field, value, schema, actualFieldName) {
12383
+ if (schema && actualFieldName) {
12384
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12385
+ if (field !== "value" && columnInfo.type === "array") {
12386
+ return {
12387
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value > ?)`,
12388
+ args: [value]
12389
+ };
12390
+ }
12391
+ }
12358
12392
  return { sql: `${field} > ?`, args: [value] };
12359
12393
  }
12360
- function translateGte(field, value) {
12394
+ function translateGte(field, value, schema, actualFieldName) {
12395
+ if (schema && actualFieldName) {
12396
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12397
+ if (field !== "value" && columnInfo.type === "array") {
12398
+ return {
12399
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value >= ?)`,
12400
+ args: [value]
12401
+ };
12402
+ }
12403
+ }
12361
12404
  return { sql: `${field} >= ?`, args: [value] };
12362
12405
  }
12363
- function translateLt(field, value) {
12406
+ function translateLt(field, value, schema, actualFieldName) {
12407
+ if (schema && actualFieldName) {
12408
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12409
+ if (field !== "value" && columnInfo.type === "array") {
12410
+ return {
12411
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value < ?)`,
12412
+ args: [value]
12413
+ };
12414
+ }
12415
+ }
12364
12416
  return { sql: `${field} < ?`, args: [value] };
12365
12417
  }
12366
- function translateLte(field, value) {
12418
+ function translateLte(field, value, schema, actualFieldName) {
12419
+ if (schema && actualFieldName) {
12420
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12421
+ if (field !== "value" && columnInfo.type === "array") {
12422
+ return {
12423
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value <= ?)`,
12424
+ args: [value]
12425
+ };
12426
+ }
12427
+ }
12367
12428
  return { sql: `${field} <= ?`, args: [value] };
12368
12429
  }
12369
- function translateIn(field, values) {
12430
+ function translateIn(field, values, schema, actualFieldName) {
12370
12431
  if (!Array.isArray(values) || values.length === 0) {
12371
12432
  return { sql: "1=0", args: [] };
12372
12433
  }
@@ -12375,17 +12436,31 @@ function translateIn(field, values) {
12375
12436
  if (nonNullValues.length === 0) {
12376
12437
  return { sql: `${field} IS NULL`, args: [] };
12377
12438
  }
12378
- const placeholders = nonNullValues.map(() => "?").join(", ");
12379
- const inClause = `${field} IN (${placeholders})`;
12439
+ if (schema && actualFieldName) {
12440
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12441
+ if (field !== "value" && columnInfo.type === "array") {
12442
+ const inClause2 = `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value IN (SELECT value FROM json_each(?)))`;
12443
+ const args2 = [JSON.stringify(nonNullValues)];
12444
+ if (hasNull) {
12445
+ return {
12446
+ sql: `(${inClause2} OR ${field} IS NULL)`,
12447
+ args: args2
12448
+ };
12449
+ }
12450
+ return { sql: inClause2, args: args2 };
12451
+ }
12452
+ }
12453
+ const inClause = `${field} IN (SELECT value FROM json_each(?))`;
12454
+ const args = [JSON.stringify(nonNullValues)];
12380
12455
  if (hasNull) {
12381
12456
  return {
12382
12457
  sql: `(${inClause} OR ${field} IS NULL)`,
12383
- args: nonNullValues
12458
+ args
12384
12459
  };
12385
12460
  }
12386
- return { sql: inClause, args: nonNullValues };
12461
+ return { sql: inClause, args };
12387
12462
  }
12388
- function translateNin(field, values) {
12463
+ function translateNin(field, values, schema, actualFieldName) {
12389
12464
  if (!Array.isArray(values) || values.length === 0) {
12390
12465
  return { sql: "1=1", args: [] };
12391
12466
  }
@@ -12394,15 +12469,29 @@ function translateNin(field, values) {
12394
12469
  if (nonNullValues.length === 0) {
12395
12470
  return { sql: `${field} IS NOT NULL`, args: [] };
12396
12471
  }
12397
- const placeholders = nonNullValues.map(() => "?").join(", ");
12398
- const ninClause = `${field} NOT IN (${placeholders})`;
12472
+ if (schema && actualFieldName) {
12473
+ const columnInfo = getColumnInfo(actualFieldName, schema);
12474
+ if (field !== "value" && columnInfo.type === "array") {
12475
+ const ninClause2 = `NOT EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value IN (SELECT value FROM json_each(?)))`;
12476
+ const args2 = [JSON.stringify(nonNullValues)];
12477
+ if (hasNull) {
12478
+ return {
12479
+ sql: `(${ninClause2} AND ${field} IS NOT NULL)`,
12480
+ args: args2
12481
+ };
12482
+ }
12483
+ return { sql: ninClause2, args: args2 };
12484
+ }
12485
+ }
12486
+ const ninClause = `${field} NOT IN (SELECT value FROM json_each(?))`;
12487
+ const args = [JSON.stringify(nonNullValues)];
12399
12488
  if (hasNull) {
12400
12489
  return {
12401
12490
  sql: `(${ninClause} AND ${field} IS NOT NULL)`,
12402
- args: nonNullValues
12491
+ args
12403
12492
  };
12404
12493
  }
12405
- return { sql: ninClause, args: nonNullValues };
12494
+ return { sql: ninClause, args };
12406
12495
  }
12407
12496
  function translateExists(field, exists) {
12408
12497
  return {
@@ -12416,17 +12505,18 @@ function translateRegex(field, pattern, options, schema, fieldName) {
12416
12505
  return smartResult;
12417
12506
  return null;
12418
12507
  }
12419
- function buildElemMatchConditions(criteria) {
12508
+ function buildElemMatchConditions(criteria, schema, baseFieldName) {
12420
12509
  const conditions = [];
12421
12510
  const args = [];
12422
12511
  for (const [key, value] of Object.entries(criteria)) {
12423
12512
  if (key.startsWith("$")) {
12424
- const fragment = processOperatorValue("json_each.value", { [key]: value });
12513
+ const fragment = processOperatorValue("value", { [key]: value }, schema, baseFieldName);
12425
12514
  conditions.push(fragment.sql);
12426
12515
  args.push(...fragment.args);
12427
12516
  } else {
12428
- const propertyField = `json_extract(json_each.value, '$.${key}')`;
12429
- const fragment = processOperatorValue(propertyField, value);
12517
+ const propertyField = `json_extract(value, '$.${key}')`;
12518
+ const nestedFieldName = `${baseFieldName}.${key}`;
12519
+ const fragment = processOperatorValue(propertyField, value, schema, nestedFieldName);
12430
12520
  conditions.push(fragment.sql);
12431
12521
  args.push(...fragment.args);
12432
12522
  }
@@ -12436,73 +12526,74 @@ function buildElemMatchConditions(criteria) {
12436
12526
  args
12437
12527
  };
12438
12528
  }
12439
- function translateElemMatch(field, criteria) {
12529
+ function translateElemMatch(field, criteria, schema, actualFieldName) {
12530
+ if (typeof criteria === "object" && criteria !== null && !Array.isArray(criteria) && Object.keys(criteria).length === 0) {
12531
+ return { sql: "1=0", args: [] };
12532
+ }
12440
12533
  if (typeof criteria !== "object" || criteria === null) {
12441
12534
  return {
12442
- sql: `EXISTS (SELECT 1 FROM json_each(${field}) WHERE json_each.value = ?)`,
12535
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE value = ?)`,
12443
12536
  args: [criteria]
12444
12537
  };
12445
12538
  }
12446
12539
  if (criteria.$and && Array.isArray(criteria.$and)) {
12447
- const fragments = criteria.$and.map((cond) => buildElemMatchConditions(cond));
12540
+ const fragments = criteria.$and.map((cond) => buildElemMatchConditions(cond, schema, actualFieldName));
12448
12541
  const sql = fragments.map((f) => f.sql).join(" AND ");
12449
12542
  const args = fragments.flatMap((f) => f.args);
12450
12543
  return {
12451
- sql: `EXISTS (SELECT 1 FROM json_each(${field}) WHERE ${sql})`,
12544
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE ${sql})`,
12452
12545
  args
12453
12546
  };
12454
12547
  }
12455
12548
  if (criteria.$or && Array.isArray(criteria.$or)) {
12456
- const fragments = criteria.$or.map((cond) => buildElemMatchConditions(cond));
12549
+ const fragments = criteria.$or.map((cond) => buildElemMatchConditions(cond, schema, actualFieldName));
12457
12550
  const sql = fragments.map((f) => f.sql).join(" OR ");
12458
12551
  const args = fragments.flatMap((f) => f.args);
12459
12552
  return {
12460
- sql: `EXISTS (SELECT 1 FROM json_each(${field}) WHERE ${sql})`,
12553
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE ${sql})`,
12461
12554
  args
12462
12555
  };
12463
12556
  }
12464
12557
  if (criteria.$nor && Array.isArray(criteria.$nor)) {
12465
- const fragments = criteria.$nor.map((cond) => buildElemMatchConditions(cond));
12558
+ const fragments = criteria.$nor.map((cond) => buildElemMatchConditions(cond, schema, actualFieldName));
12466
12559
  const sql = fragments.map((f) => f.sql).join(" OR ");
12467
12560
  const args = fragments.flatMap((f) => f.args);
12468
12561
  return {
12469
- sql: `EXISTS (SELECT 1 FROM json_each(${field}) WHERE NOT (${sql}))`,
12562
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE NOT (${sql}))`,
12470
12563
  args
12471
12564
  };
12472
12565
  }
12473
- const fragment = buildElemMatchConditions(criteria);
12474
- if (fragment.sql === "1=1") {
12475
- return null;
12476
- }
12566
+ const fragment = buildElemMatchConditions(criteria, schema, actualFieldName);
12477
12567
  return {
12478
- sql: `EXISTS (SELECT 1 FROM json_each(${field}) WHERE ${fragment.sql})`,
12568
+ sql: `EXISTS (SELECT 1 FROM jsonb_each(${field}) WHERE ${fragment.sql})`,
12479
12569
  args: fragment.args
12480
12570
  };
12481
12571
  }
12482
- function processOperatorValue(field, value) {
12572
+ function processOperatorValue(field, value, schema, actualFieldName) {
12483
12573
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
12484
12574
  const [[op, opValue]] = Object.entries(value);
12485
12575
  if (!op.startsWith("$")) {
12486
12576
  const jsonPath = `json_extract(${field}, '$.${op}')`;
12487
- return translateEq(jsonPath, opValue);
12577
+ const nestedFieldName = `${actualFieldName}.${op}`;
12578
+ return translateEq(jsonPath, opValue, schema, nestedFieldName);
12488
12579
  }
12489
12580
  switch (op) {
12490
12581
  case "$eq":
12491
- return translateEq(field, opValue);
12582
+ return translateEq(field, opValue, schema, actualFieldName);
12492
12583
  case "$ne":
12493
- return translateNe(field, opValue);
12584
+ return translateNe(field, opValue, schema, actualFieldName);
12494
12585
  case "$gt":
12495
- return translateGt(field, opValue);
12586
+ return translateGt(field, opValue, schema, actualFieldName);
12496
12587
  case "$gte":
12497
- return translateGte(field, opValue);
12588
+ return translateGte(field, opValue, schema, actualFieldName);
12498
12589
  case "$lt":
12499
- return translateLt(field, opValue);
12590
+ return translateLt(field, opValue, schema, actualFieldName);
12500
12591
  case "$lte":
12501
- return translateLte(field, opValue);
12592
+ return translateLte(field, opValue, schema, actualFieldName);
12502
12593
  case "$in":
12503
- return translateIn(field, opValue);
12594
+ return translateIn(field, opValue, schema, actualFieldName);
12504
12595
  case "$nin":
12505
- return translateNin(field, opValue);
12596
+ return translateNin(field, opValue, schema, actualFieldName);
12506
12597
  case "$exists":
12507
12598
  return translateExists(field, opValue);
12508
12599
  case "$size":
@@ -12510,48 +12601,96 @@ function processOperatorValue(field, value) {
12510
12601
  case "$mod": {
12511
12602
  const result = translateMod(field, opValue);
12512
12603
  if (!result)
12513
- return translateEq(field, opValue);
12604
+ return translateEq(field, opValue, schema, actualFieldName);
12514
12605
  return result;
12515
12606
  }
12607
+ case "$regex": {
12608
+ const options = value.$options;
12609
+ const regexFragment = translateRegex(field, opValue, options, schema, actualFieldName);
12610
+ return regexFragment || { sql: "1=0", args: [] };
12611
+ }
12612
+ case "$type": {
12613
+ let jsonCol = "data";
12614
+ let path2 = `$.${actualFieldName}`;
12615
+ let useDirectType = false;
12616
+ if (field === "value") {
12617
+ jsonCol = "value";
12618
+ path2 = "";
12619
+ useDirectType = true;
12620
+ } else if (field.startsWith("json_extract(")) {
12621
+ const match = field.match(/json_extract\(([^,]+),\s*'([^']+)'\)/);
12622
+ if (match) {
12623
+ jsonCol = match[1];
12624
+ path2 = match[2];
12625
+ }
12626
+ }
12627
+ if (useDirectType) {
12628
+ const typeMap = {
12629
+ null: "null",
12630
+ boolean: "true",
12631
+ number: "integer",
12632
+ string: "text",
12633
+ array: "array",
12634
+ object: "object"
12635
+ };
12636
+ const sqlType = typeMap[opValue];
12637
+ if (!sqlType)
12638
+ return { sql: "1=0", args: [] };
12639
+ if (opValue === "boolean") {
12640
+ return { sql: `(type IN ('true', 'false'))`, args: [] };
12641
+ }
12642
+ if (opValue === "number") {
12643
+ return { sql: `(type IN ('integer', 'real'))`, args: [] };
12644
+ }
12645
+ return { sql: `type = '${sqlType}'`, args: [] };
12646
+ }
12647
+ const typeFragment = translateType(jsonCol, path2, opValue, true);
12648
+ return typeFragment || { sql: "1=0", args: [] };
12649
+ }
12650
+ case "$elemMatch": {
12651
+ const elemMatchFragment = translateElemMatch(field, opValue, schema, actualFieldName);
12652
+ return elemMatchFragment || { sql: "1=0", args: [] };
12653
+ }
12516
12654
  case "$not": {
12517
- const result = translateNot(field, opValue);
12655
+ const result = translateNot(field, opValue, schema, actualFieldName);
12518
12656
  if (!result)
12519
- return translateEq(field, opValue);
12657
+ return translateEq(field, opValue, schema, actualFieldName);
12520
12658
  return result;
12521
12659
  }
12522
12660
  case "$and": {
12523
12661
  if (!Array.isArray(opValue))
12524
- return translateEq(field, opValue);
12525
- const fragments = opValue.map((v) => processOperatorValue(field, v));
12662
+ return translateEq(field, opValue, schema, actualFieldName);
12663
+ const fragments = opValue.map((v) => processOperatorValue(field, v, schema, actualFieldName));
12526
12664
  const sql = fragments.map((f) => f.sql).join(" AND ");
12527
12665
  const args = fragments.flatMap((f) => f.args);
12528
12666
  return { sql: `(${sql})`, args };
12529
12667
  }
12530
12668
  case "$or": {
12531
12669
  if (!Array.isArray(opValue))
12532
- return translateEq(field, opValue);
12533
- const fragments = opValue.map((v) => processOperatorValue(field, v));
12670
+ return translateEq(field, opValue, schema, actualFieldName);
12671
+ const fragments = opValue.map((v) => processOperatorValue(field, v, schema, actualFieldName));
12534
12672
  const sql = fragments.map((f) => f.sql).join(" OR ");
12535
12673
  const args = fragments.flatMap((f) => f.args);
12536
12674
  return { sql: `(${sql})`, args };
12537
12675
  }
12538
12676
  default:
12539
- return translateEq(field, opValue);
12677
+ return translateEq(field, opValue, schema, actualFieldName);
12540
12678
  }
12541
12679
  }
12542
- return translateEq(field, value);
12680
+ return translateEq(field, value, schema, actualFieldName);
12543
12681
  }
12544
- function translateNot(field, criteria) {
12545
- if (!criteria || typeof criteria === "object" && Object.keys(criteria).length === 0)
12546
- return null;
12547
- const inner = processOperatorValue(field, criteria);
12682
+ function translateNot(field, criteria, schema, actualFieldName) {
12683
+ if (criteria === undefined || criteria === null || typeof criteria !== "object" || Array.isArray(criteria) || Object.keys(criteria).length === 0) {
12684
+ return { sql: "1=0", args: [] };
12685
+ }
12686
+ const inner = processOperatorValue(field, criteria, schema, actualFieldName);
12548
12687
  return {
12549
- sql: `NOT(${inner.sql})`,
12688
+ sql: `NOT (${inner.sql})`,
12550
12689
  args: inner.args
12551
12690
  };
12552
12691
  }
12553
- function translateType(jsonColumn, fieldName, type6) {
12554
- const jsonPath = `$.${fieldName}`;
12692
+ function translateType(jsonColumn, fieldName, type6, isDirectPath = false) {
12693
+ const jsonPath = isDirectPath ? fieldName : `$.${fieldName}`;
12555
12694
  switch (type6) {
12556
12695
  case "null":
12557
12696
  return { sql: `json_type(${jsonColumn}, '${jsonPath}') = 'null'`, args: [] };
@@ -12566,7 +12705,7 @@ function translateType(jsonColumn, fieldName, type6) {
12566
12705
  case "object":
12567
12706
  return { sql: `json_type(${jsonColumn}, '${jsonPath}') = 'object'`, args: [] };
12568
12707
  default:
12569
- return null;
12708
+ return { sql: "1=0", args: [] };
12570
12709
  }
12571
12710
  }
12572
12711
  function translateSize(field, size) {
@@ -12577,11 +12716,11 @@ function translateSize(field, size) {
12577
12716
  }
12578
12717
  function translateMod(field, value) {
12579
12718
  if (!Array.isArray(value) || value.length !== 2)
12580
- return null;
12719
+ return { sql: "1=0", args: [] };
12581
12720
  const [divisor, remainder] = value;
12582
12721
  return {
12583
- sql: `${field} % ? = ?`,
12584
- args: [divisor, remainder]
12722
+ sql: `(${field} - (CAST(${field} / ? AS INTEGER) * ?)) = ?`,
12723
+ args: [divisor, divisor, remainder]
12585
12724
  };
12586
12725
  }
12587
12726
 
@@ -12708,12 +12847,12 @@ function buildWhereClause(selector, schema, collectionName) {
12708
12847
  }
12709
12848
  function buildLogicalOperator(operator, conditions, schema, logicalDepth) {
12710
12849
  if (conditions.length === 0) {
12711
- return { sql: "1=1", args: [] };
12850
+ return { sql: operator === "or" ? "1=0" : "1=1", args: [] };
12712
12851
  }
12713
12852
  const fragments = conditions.map((subSelector) => processSelector(subSelector, schema, logicalDepth + 1));
12714
12853
  if (fragments.some((f) => f === null))
12715
12854
  return null;
12716
- const sql = fragments.map((f) => f.sql).join(" OR ");
12855
+ const sql = fragments.map((f) => `(${f.sql})`).join(" OR ");
12717
12856
  const args = fragments.flatMap((f) => f.args);
12718
12857
  return operator === "nor" ? { sql: `NOT(${sql})`, args } : { sql, args };
12719
12858
  }
@@ -12738,8 +12877,7 @@ function processSelector(selector, schema, logicalDepth) {
12738
12877
  const orFragment = buildLogicalOperator("or", value, schema, logicalDepth);
12739
12878
  if (!orFragment)
12740
12879
  return null;
12741
- const needsParens = logicalDepth > 0;
12742
- conditions.push(needsParens ? `(${orFragment.sql})` : orFragment.sql);
12880
+ conditions.push(`(${orFragment.sql})`);
12743
12881
  args.push(...orFragment.args);
12744
12882
  continue;
12745
12883
  }
@@ -12755,32 +12893,35 @@ function processSelector(selector, schema, logicalDepth) {
12755
12893
  const fieldName = columnInfo.column || `json_extract(data, '${columnInfo.jsonPath}')`;
12756
12894
  const actualFieldName = columnInfo.jsonPath?.replace(/^\$\./, "") || columnInfo.column || field;
12757
12895
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
12896
+ if (Object.keys(value).length === 0) {
12897
+ return { sql: "1=0", args: [] };
12898
+ }
12758
12899
  for (const [op, opValue] of Object.entries(value)) {
12759
12900
  let fragment;
12760
12901
  switch (op) {
12761
12902
  case "$eq":
12762
- fragment = translateEq(fieldName, opValue);
12903
+ fragment = translateEq(fieldName, opValue, schema, actualFieldName);
12763
12904
  break;
12764
12905
  case "$ne":
12765
- fragment = translateNe(fieldName, opValue);
12906
+ fragment = translateNe(fieldName, opValue, schema, actualFieldName);
12766
12907
  break;
12767
12908
  case "$gt":
12768
- fragment = translateGt(fieldName, opValue);
12909
+ fragment = translateGt(fieldName, opValue, schema, actualFieldName);
12769
12910
  break;
12770
12911
  case "$gte":
12771
- fragment = translateGte(fieldName, opValue);
12912
+ fragment = translateGte(fieldName, opValue, schema, actualFieldName);
12772
12913
  break;
12773
12914
  case "$lt":
12774
- fragment = translateLt(fieldName, opValue);
12915
+ fragment = translateLt(fieldName, opValue, schema, actualFieldName);
12775
12916
  break;
12776
12917
  case "$lte":
12777
- fragment = translateLte(fieldName, opValue);
12918
+ fragment = translateLte(fieldName, opValue, schema, actualFieldName);
12778
12919
  break;
12779
12920
  case "$in":
12780
- fragment = translateIn(fieldName, opValue);
12921
+ fragment = translateIn(fieldName, opValue, schema, actualFieldName);
12781
12922
  break;
12782
12923
  case "$nin":
12783
- fragment = translateNin(fieldName, opValue);
12924
+ fragment = translateNin(fieldName, opValue, schema, actualFieldName);
12784
12925
  break;
12785
12926
  case "$exists":
12786
12927
  fragment = translateExists(fieldName, opValue);
@@ -12793,13 +12934,13 @@ function processSelector(selector, schema, logicalDepth) {
12793
12934
  fragment = regexFragment;
12794
12935
  break;
12795
12936
  case "$elemMatch":
12796
- const elemMatchFragment = translateElemMatch(fieldName, opValue);
12937
+ const elemMatchFragment = translateElemMatch(fieldName, opValue, schema, actualFieldName);
12797
12938
  if (!elemMatchFragment)
12798
12939
  return null;
12799
12940
  fragment = elemMatchFragment;
12800
12941
  break;
12801
12942
  case "$not": {
12802
- const notResult = translateNot(fieldName, opValue);
12943
+ const notResult = translateNot(fieldName, opValue, schema, actualFieldName);
12803
12944
  if (!notResult)
12804
12945
  return null;
12805
12946
  fragment = notResult;
@@ -12828,7 +12969,7 @@ function processSelector(selector, schema, logicalDepth) {
12828
12969
  args.push(...fragment.args);
12829
12970
  }
12830
12971
  } else {
12831
- const fragment = translateEq(fieldName, value);
12972
+ const fragment = translateEq(fieldName, value, schema, actualFieldName);
12832
12973
  conditions.push(fragment.sql);
12833
12974
  args.push(...fragment.args);
12834
12975
  }
@@ -12837,6 +12978,100 @@ function processSelector(selector, schema, logicalDepth) {
12837
12978
  return { sql: where, args };
12838
12979
  }
12839
12980
 
12981
+ // src/query/lightweight-matcher.ts
12982
+ var operators = {
12983
+ $eq: (a, b) => a === b,
12984
+ $ne: (a, b) => a !== b,
12985
+ $gt: (a, b) => a > b,
12986
+ $gte: (a, b) => a >= b,
12987
+ $lt: (a, b) => a < b,
12988
+ $lte: (a, b) => a <= b,
12989
+ $in: (a, b) => Array.isArray(b) && b.some((v) => v === a),
12990
+ $nin: (a, b) => Array.isArray(b) && !b.some((v) => v === a),
12991
+ $exists: (a, b) => a !== undefined === b,
12992
+ $type: (a, b) => {
12993
+ const type6 = Array.isArray(a) ? "array" : typeof a;
12994
+ return type6 === b;
12995
+ },
12996
+ $mod: (a, b) => {
12997
+ if (!Array.isArray(b) || b.length !== 2)
12998
+ return false;
12999
+ const [divisor, remainder] = b;
13000
+ return typeof a === "number" && a % divisor === remainder;
13001
+ },
13002
+ $size: (a, b) => Array.isArray(a) && a.length === b
13003
+ };
13004
+ function getNestedValue(obj, path2) {
13005
+ return path2.split(".").reduce((current, key) => current?.[key], obj);
13006
+ }
13007
+ function matchesSelector(doc, selector) {
13008
+ if (!selector || typeof selector !== "object")
13009
+ return true;
13010
+ if (selector.$and) {
13011
+ return Array.isArray(selector.$and) && selector.$and.every((s) => matchesSelector(doc, s));
13012
+ }
13013
+ if (selector.$or) {
13014
+ return Array.isArray(selector.$or) && selector.$or.some((s) => matchesSelector(doc, s));
13015
+ }
13016
+ if (selector.$nor) {
13017
+ return Array.isArray(selector.$nor) && !selector.$nor.some((s) => matchesSelector(doc, s));
13018
+ }
13019
+ for (const [field, condition] of Object.entries(selector)) {
13020
+ const value = getNestedValue(doc, field);
13021
+ if (typeof condition !== "object" || condition === null || Array.isArray(condition)) {
13022
+ if (value !== condition)
13023
+ return false;
13024
+ continue;
13025
+ }
13026
+ for (const [op, opValue] of Object.entries(condition)) {
13027
+ if (op === "$regex") {
13028
+ const options = condition.$options;
13029
+ if (!matchesRegex(value, opValue, options))
13030
+ return false;
13031
+ continue;
13032
+ }
13033
+ if (op === "$not") {
13034
+ if (matchesOperator(value, opValue))
13035
+ return false;
13036
+ continue;
13037
+ }
13038
+ if (op === "$elemMatch") {
13039
+ if (!Array.isArray(value))
13040
+ return false;
13041
+ const hasMatch = value.some((item) => matchesSelector(item, opValue));
13042
+ if (!hasMatch)
13043
+ return false;
13044
+ continue;
13045
+ }
13046
+ if (op === "$options")
13047
+ continue;
13048
+ const operator = operators[op];
13049
+ if (!operator)
13050
+ return false;
13051
+ if (!operator(value, opValue))
13052
+ return false;
13053
+ }
13054
+ }
13055
+ return true;
13056
+ }
13057
+ function matchesOperator(value, operator) {
13058
+ if (typeof operator !== "object" || operator === null) {
13059
+ return value === operator;
13060
+ }
13061
+ for (const [op, opValue] of Object.entries(operator)) {
13062
+ if (op === "$regex") {
13063
+ const options = operator.$options;
13064
+ return matchesRegex(value, opValue, options);
13065
+ }
13066
+ const operatorFn = operators[op];
13067
+ if (!operatorFn)
13068
+ return false;
13069
+ if (operatorFn(value, opValue))
13070
+ return true;
13071
+ }
13072
+ return false;
13073
+ }
13074
+
12840
13075
  // src/rxdb-helpers.ts
12841
13076
  function randomToken2(length) {
12842
13077
  return Math.random().toString(36).substring(2, 2 + length);
@@ -13375,6 +13610,9 @@ class BunSQLiteStorageInstance {
13375
13610
  queryArgs.push(preparedQuery.query.limit);
13376
13611
  }
13377
13612
  if (preparedQuery.query.skip) {
13613
+ if (!preparedQuery.query.limit) {
13614
+ sql += ` LIMIT -1`;
13615
+ }
13378
13616
  sql += ` OFFSET ?`;
13379
13617
  queryArgs.push(preparedQuery.query.skip);
13380
13618
  }
@@ -13389,31 +13627,6 @@ class BunSQLiteStorageInstance {
13389
13627
  const documents = rows.map((row) => JSON.parse(row.data));
13390
13628
  return { documents };
13391
13629
  }
13392
- matchesSelector(doc, selector) {
13393
- for (const [key, value] of Object.entries(selector)) {
13394
- const docValue = this.getNestedValue(doc, key);
13395
- if (typeof value === "object" && value !== null) {
13396
- for (const [op, opValue] of Object.entries(value)) {
13397
- if (op === "$eq" && docValue !== opValue)
13398
- return false;
13399
- if (op === "$ne" && docValue === opValue)
13400
- return false;
13401
- if (op === "$gt" && !(docValue > opValue))
13402
- return false;
13403
- if (op === "$gte" && !(docValue >= opValue))
13404
- return false;
13405
- if (op === "$lt" && !(docValue < opValue))
13406
- return false;
13407
- if (op === "$lte" && !(docValue <= opValue))
13408
- return false;
13409
- }
13410
- } else {
13411
- if (docValue !== value)
13412
- return false;
13413
- }
13414
- }
13415
- return true;
13416
- }
13417
13630
  sortDocuments(docs, sort) {
13418
13631
  return docs.sort((a, b) => {
13419
13632
  for (const sortField of sort) {
@@ -13512,17 +13725,38 @@ class BunSQLiteStorageInstance {
13512
13725
  }
13513
13726
  queryWithOurMemory(preparedQuery) {
13514
13727
  const query = `SELECT json(data) as data FROM "${this.tableName}"`;
13515
- const rows = this.stmtManager.all({ query, params: [] });
13516
- let documents = rows.map((row) => JSON.parse(row.data));
13517
- documents = documents.filter((doc) => this.matchesRegexSelector(doc, preparedQuery.query.selector));
13518
- if (preparedQuery.query.sort && preparedQuery.query.sort.length > 0) {
13519
- documents = this.sortDocuments(documents, preparedQuery.query.sort);
13520
- }
13521
- if (preparedQuery.query.skip) {
13522
- documents = documents.slice(preparedQuery.query.skip);
13523
- }
13524
- if (preparedQuery.query.limit) {
13525
- documents = documents.slice(0, preparedQuery.query.limit);
13728
+ const selector = preparedQuery.query.selector;
13729
+ const hasSort = preparedQuery.query.sort && preparedQuery.query.sort.length > 0;
13730
+ if (hasSort) {
13731
+ const rows = this.stmtManager.all({ query, params: [] });
13732
+ let documents2 = rows.map((row) => JSON.parse(row.data));
13733
+ documents2 = documents2.filter((doc) => matchesSelector(doc, selector));
13734
+ documents2 = this.sortDocuments(documents2, preparedQuery.query.sort);
13735
+ if (preparedQuery.query.skip) {
13736
+ documents2 = documents2.slice(preparedQuery.query.skip);
13737
+ }
13738
+ if (preparedQuery.query.limit) {
13739
+ documents2 = documents2.slice(0, preparedQuery.query.limit);
13740
+ }
13741
+ return { documents: documents2 };
13742
+ }
13743
+ const stmt = this.db.prepare(query);
13744
+ const documents = [];
13745
+ const skip = preparedQuery.query.skip || 0;
13746
+ const limit = preparedQuery.query.limit;
13747
+ let skipped = 0;
13748
+ for (const row of stmt.iterate()) {
13749
+ const doc = JSON.parse(row.data);
13750
+ if (matchesSelector(doc, selector)) {
13751
+ if (skipped < skip) {
13752
+ skipped++;
13753
+ continue;
13754
+ }
13755
+ documents.push(doc);
13756
+ if (limit && documents.length >= limit) {
13757
+ break;
13758
+ }
13759
+ }
13526
13760
  }
13527
13761
  return { documents };
13528
13762
  }