workers-qb 1.13.0 → 1.14.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.d.mts +202 -6
- package/dist/index.d.ts +202 -6
- package/dist/index.js +380 -30
- package/dist/index.mjs +380 -30
- package/docs/advanced-queries.md +202 -0
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -122,8 +122,9 @@ var QueryBuilderError = class _QueryBuilderError extends Error {
|
|
|
122
122
|
Hint: ${options.hint}`;
|
|
123
123
|
}
|
|
124
124
|
this.message = enhancedMessage;
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
const ErrorWithCapture = Error;
|
|
126
|
+
if (ErrorWithCapture.captureStackTrace) {
|
|
127
|
+
ErrorWithCapture.captureStackTrace(this, _QueryBuilderError);
|
|
127
128
|
}
|
|
128
129
|
}
|
|
129
130
|
};
|
|
@@ -375,7 +376,13 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
375
376
|
let builtCondition = conditionParts[0] ?? "";
|
|
376
377
|
for (let j = 0; j < conditionParts.length - 1; j++) {
|
|
377
378
|
if (paramIndex >= currentInputParams.length) {
|
|
378
|
-
|
|
379
|
+
const totalPlaceholders = currentInputConditions.join(" AND ").split("?").length - 1;
|
|
380
|
+
throw new ParameterMismatchError({
|
|
381
|
+
clause: "WHERE",
|
|
382
|
+
query: currentInputConditions.join(" AND "),
|
|
383
|
+
expectedParams: totalPlaceholders,
|
|
384
|
+
receivedParams: currentInputParams.length
|
|
385
|
+
});
|
|
379
386
|
}
|
|
380
387
|
const currentParam = currentInputParams[paramIndex++];
|
|
381
388
|
const isSubQuery = typeof currentParam === "object" && currentParam !== null && ("tableName" in currentParam || "getOptions" in currentParam) && !currentParam.hasOwnProperty("_raw") || currentParam instanceof _SelectBuilder;
|
|
@@ -394,7 +401,13 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
394
401
|
processedNewConditions.push(builtCondition);
|
|
395
402
|
}
|
|
396
403
|
if (paramIndex < currentInputParams.length) {
|
|
397
|
-
|
|
404
|
+
const totalPlaceholders = currentInputConditions.join(" AND ").split("?").length - 1;
|
|
405
|
+
throw new ParameterMismatchError({
|
|
406
|
+
clause: "WHERE",
|
|
407
|
+
query: currentInputConditions.join(" AND "),
|
|
408
|
+
expectedParams: totalPlaceholders,
|
|
409
|
+
receivedParams: currentInputParams.length
|
|
410
|
+
});
|
|
398
411
|
}
|
|
399
412
|
return new _SelectBuilder(
|
|
400
413
|
{
|
|
@@ -410,6 +423,62 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
410
423
|
this._fetchOne
|
|
411
424
|
);
|
|
412
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* Add an OR WHERE condition to the query.
|
|
428
|
+
* All previously added WHERE conditions are grouped together and ORed with the new condition.
|
|
429
|
+
* Subsequent `.where()` calls after `.orWhere()` are ANDed as independent conditions.
|
|
430
|
+
*
|
|
431
|
+
* @param conditions - The SQL condition string(s) (can use ? placeholders)
|
|
432
|
+
* @param params - The parameter(s) to bind to the ? placeholders
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* // Simple OR condition
|
|
436
|
+
* qb.select('users').where('status = ?', 'active').orWhere('status = ?', 'pending').execute()
|
|
437
|
+
* // SELECT * FROM users WHERE (status = ?) OR (status = ?)
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* // Multiple where conditions ORed together
|
|
441
|
+
* qb.select('users')
|
|
442
|
+
* .where('tenant_id = ?', 1)
|
|
443
|
+
* .where('status = ?', 'active')
|
|
444
|
+
* .orWhere('role = ?', 'superadmin')
|
|
445
|
+
* .execute()
|
|
446
|
+
* // SELECT * FROM users WHERE ((tenant_id = ?) AND (status = ?)) OR (role = ?)
|
|
447
|
+
*/
|
|
448
|
+
orWhere(conditions, params) {
|
|
449
|
+
const existingConditions = this._options.where && typeof this._options.where === "object" && "conditions" in this._options.where ? this._options.where.conditions : [];
|
|
450
|
+
const existingParams = this._options.where && typeof this._options.where === "object" && "params" in this._options.where && this._options.where.params ? Array.isArray(this._options.where.params) ? this._options.where.params : [this._options.where.params] : [];
|
|
451
|
+
if (existingConditions.length === 0) {
|
|
452
|
+
return this.where(conditions, params);
|
|
453
|
+
}
|
|
454
|
+
const clearedBuilder = new _SelectBuilder(
|
|
455
|
+
{
|
|
456
|
+
...this._options,
|
|
457
|
+
where: void 0
|
|
458
|
+
},
|
|
459
|
+
this._fetchAll,
|
|
460
|
+
this._fetchOne
|
|
461
|
+
);
|
|
462
|
+
const processedBuilder = clearedBuilder.where(conditions, params);
|
|
463
|
+
const processedWhere = processedBuilder._options.where;
|
|
464
|
+
const newConditions = processedWhere && typeof processedWhere === "object" && "conditions" in processedWhere ? processedWhere.conditions : [];
|
|
465
|
+
const newParams = processedWhere && typeof processedWhere === "object" && "params" in processedWhere && processedWhere.params ? Array.isArray(processedWhere.params) ? processedWhere.params : [processedWhere.params] : [];
|
|
466
|
+
const existingCombined = existingConditions.length === 1 ? existingConditions[0] : `(${existingConditions.join(") AND (")})`;
|
|
467
|
+
const newCombined = newConditions.length === 1 ? newConditions[0] : `(${newConditions.join(") AND (")})`;
|
|
468
|
+
const orCondition = `(${existingCombined}) OR (${newCombined})`;
|
|
469
|
+
return new _SelectBuilder(
|
|
470
|
+
{
|
|
471
|
+
// Spread processedBuilder._options to pick up any new subQueryPlaceholders/TokenNextId
|
|
472
|
+
...processedBuilder._options,
|
|
473
|
+
where: {
|
|
474
|
+
conditions: [orCondition],
|
|
475
|
+
params: [...existingParams, ...newParams]
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
this._fetchAll,
|
|
479
|
+
this._fetchOne
|
|
480
|
+
);
|
|
481
|
+
}
|
|
413
482
|
whereIn(fields, values) {
|
|
414
483
|
let whereInCondition;
|
|
415
484
|
let whereInParams;
|
|
@@ -438,6 +507,229 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
438
507
|
}
|
|
439
508
|
return this.where(whereInCondition, whereInParams);
|
|
440
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* Conditionally apply query modifications based on a runtime value.
|
|
512
|
+
* If condition is truthy, the callback is invoked with the current builder
|
|
513
|
+
* and its return value is used. If condition is falsy and an otherwise callback
|
|
514
|
+
* is provided, it is invoked instead. Otherwise, the builder is returned unchanged.
|
|
515
|
+
*
|
|
516
|
+
* @param condition - A value to check for truthiness
|
|
517
|
+
* @param callback - Function that receives the builder and returns a modified builder
|
|
518
|
+
* @param otherwise - Optional function applied when condition is falsy
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* qb.select('users')
|
|
522
|
+
* .when(nameFilter, q => q.where('name LIKE ?', [`%${nameFilter}%`]))
|
|
523
|
+
* .when(sortByDate, q => q.orderBy({ created_at: 'DESC' }))
|
|
524
|
+
* .execute()
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* // With otherwise callback
|
|
528
|
+
* qb.select('products')
|
|
529
|
+
* .when(
|
|
530
|
+
* inStock,
|
|
531
|
+
* q => q.where('stock > ?', 0),
|
|
532
|
+
* q => q.where('stock = ?', 0)
|
|
533
|
+
* )
|
|
534
|
+
* .execute()
|
|
535
|
+
*/
|
|
536
|
+
when(condition, callback, otherwise) {
|
|
537
|
+
if (condition) {
|
|
538
|
+
return callback(this);
|
|
539
|
+
}
|
|
540
|
+
if (otherwise) {
|
|
541
|
+
return otherwise(this);
|
|
542
|
+
}
|
|
543
|
+
return this;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Add a WHERE column IS NULL condition.
|
|
547
|
+
*
|
|
548
|
+
* @param column - The column name to check for NULL
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* qb.select('users').whereNull('deleted_at').execute()
|
|
552
|
+
* // SELECT * FROM users WHERE deleted_at IS NULL
|
|
553
|
+
*/
|
|
554
|
+
whereNull(column) {
|
|
555
|
+
return this.where(`${column} IS NULL`);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Add a WHERE column IS NOT NULL condition.
|
|
559
|
+
*
|
|
560
|
+
* @param column - The column name to check for NOT NULL
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* qb.select('users').whereNotNull('email_verified_at').execute()
|
|
564
|
+
* // SELECT * FROM users WHERE email_verified_at IS NOT NULL
|
|
565
|
+
*/
|
|
566
|
+
whereNotNull(column) {
|
|
567
|
+
return this.where(`${column} IS NOT NULL`);
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Add a WHERE column BETWEEN min AND max condition.
|
|
571
|
+
*
|
|
572
|
+
* @param column - The column name
|
|
573
|
+
* @param range - Tuple of [min, max] values
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* qb.select('products').whereBetween('price', [10, 100]).execute()
|
|
577
|
+
* // SELECT * FROM products WHERE price BETWEEN ? AND ?
|
|
578
|
+
*/
|
|
579
|
+
whereBetween(column, range) {
|
|
580
|
+
return this.where(`${column} BETWEEN ? AND ?`, [range[0], range[1]]);
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Add a WHERE column NOT BETWEEN min AND max condition.
|
|
584
|
+
*
|
|
585
|
+
* @param column - The column name
|
|
586
|
+
* @param range - Tuple of [min, max] values
|
|
587
|
+
*
|
|
588
|
+
* @example
|
|
589
|
+
* qb.select('products').whereNotBetween('price', [10, 100]).execute()
|
|
590
|
+
* // SELECT * FROM products WHERE price NOT BETWEEN ? AND ?
|
|
591
|
+
*/
|
|
592
|
+
whereNotBetween(column, range) {
|
|
593
|
+
return this.where(`${column} NOT BETWEEN ? AND ?`, [range[0], range[1]]);
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Add an OR WHERE column IS NULL condition.
|
|
597
|
+
*
|
|
598
|
+
* @param column - The column name to check for NULL
|
|
599
|
+
*
|
|
600
|
+
* @example
|
|
601
|
+
* qb.select('users').where('active = ?', true).orWhereNull('deleted_at').execute()
|
|
602
|
+
* // SELECT * FROM users WHERE (active = ?) OR (deleted_at IS NULL)
|
|
603
|
+
*/
|
|
604
|
+
orWhereNull(column) {
|
|
605
|
+
return this.orWhere(`${column} IS NULL`);
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Add an OR WHERE column IS NOT NULL condition.
|
|
609
|
+
*
|
|
610
|
+
* @param column - The column name to check for NOT NULL
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* qb.select('users').whereNull('deleted_at').orWhereNotNull('verified_at').execute()
|
|
614
|
+
* // SELECT * FROM users WHERE (deleted_at IS NULL) OR (verified_at IS NOT NULL)
|
|
615
|
+
*/
|
|
616
|
+
orWhereNotNull(column) {
|
|
617
|
+
return this.orWhere(`${column} IS NOT NULL`);
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Add an OR WHERE column BETWEEN min AND max condition.
|
|
621
|
+
*
|
|
622
|
+
* @param column - The column name
|
|
623
|
+
* @param range - Tuple of [min, max] values
|
|
624
|
+
*
|
|
625
|
+
* @example
|
|
626
|
+
* qb.select('products').where('active = ?', true).orWhereBetween('price', [10, 100]).execute()
|
|
627
|
+
* // SELECT * FROM products WHERE (active = ?) OR (price BETWEEN ? AND ?)
|
|
628
|
+
*/
|
|
629
|
+
orWhereBetween(column, range) {
|
|
630
|
+
return this.orWhere(`${column} BETWEEN ? AND ?`, [range[0], range[1]]);
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Add an OR WHERE column NOT BETWEEN min AND max condition.
|
|
634
|
+
*
|
|
635
|
+
* @param column - The column name
|
|
636
|
+
* @param range - Tuple of [min, max] values
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* qb.select('products').where('featured = ?', true).orWhereNotBetween('price', [10, 100]).execute()
|
|
640
|
+
* // SELECT * FROM products WHERE (featured = ?) OR (price NOT BETWEEN ? AND ?)
|
|
641
|
+
*/
|
|
642
|
+
orWhereNotBetween(column, range) {
|
|
643
|
+
return this.orWhere(`${column} NOT BETWEEN ? AND ?`, [range[0], range[1]]);
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Add a WHERE column LIKE pattern condition.
|
|
647
|
+
*
|
|
648
|
+
* @param column - The column name
|
|
649
|
+
* @param pattern - The LIKE pattern (e.g., '%search%')
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* qb.select('users').whereLike('name', '%john%').execute()
|
|
653
|
+
* // SELECT * FROM users WHERE name LIKE ?
|
|
654
|
+
*/
|
|
655
|
+
whereLike(column, pattern) {
|
|
656
|
+
return this.where(`${column} LIKE ?`, [pattern]);
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Add a WHERE column NOT LIKE pattern condition.
|
|
660
|
+
*
|
|
661
|
+
* @param column - The column name
|
|
662
|
+
* @param pattern - The LIKE pattern
|
|
663
|
+
*
|
|
664
|
+
* @example
|
|
665
|
+
* qb.select('users').whereNotLike('email', '%@spam.com').execute()
|
|
666
|
+
* // SELECT * FROM users WHERE email NOT LIKE ?
|
|
667
|
+
*/
|
|
668
|
+
whereNotLike(column, pattern) {
|
|
669
|
+
return this.where(`${column} NOT LIKE ?`, [pattern]);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Add an OR WHERE column LIKE pattern condition.
|
|
673
|
+
*
|
|
674
|
+
* @param column - The column name
|
|
675
|
+
* @param pattern - The LIKE pattern (e.g., '%search%')
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* qb.select('users').whereLike('name', '%john%').orWhereLike('email', '%john%').execute()
|
|
679
|
+
* // SELECT * FROM users WHERE (name LIKE ?) OR (email LIKE ?)
|
|
680
|
+
*/
|
|
681
|
+
orWhereLike(column, pattern) {
|
|
682
|
+
return this.orWhere(`${column} LIKE ?`, [pattern]);
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Add an OR WHERE column NOT LIKE pattern condition.
|
|
686
|
+
*
|
|
687
|
+
* @param column - The column name
|
|
688
|
+
* @param pattern - The LIKE pattern
|
|
689
|
+
*
|
|
690
|
+
* @example
|
|
691
|
+
* qb.select('users').where('active = ?', true).orWhereNotLike('email', '%@spam.com').execute()
|
|
692
|
+
* // SELECT * FROM users WHERE (active = ?) OR (email NOT LIKE ?)
|
|
693
|
+
*/
|
|
694
|
+
orWhereNotLike(column, pattern) {
|
|
695
|
+
return this.orWhere(`${column} NOT LIKE ?`, [pattern]);
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Add a WHERE column NOT IN (values) condition.
|
|
699
|
+
*
|
|
700
|
+
* @param fields - Column name(s) to check
|
|
701
|
+
* @param values - Values to exclude
|
|
702
|
+
*
|
|
703
|
+
* @example
|
|
704
|
+
* qb.select('users').whereNotIn('status', ['banned', 'suspended']).execute()
|
|
705
|
+
* // SELECT * FROM users WHERE (status) NOT IN (VALUES (?), (?))
|
|
706
|
+
*/
|
|
707
|
+
whereNotIn(fields, values) {
|
|
708
|
+
let whereNotInCondition;
|
|
709
|
+
let whereNotInParams;
|
|
710
|
+
const separateWithComma = (prev, next) => prev + ", " + next;
|
|
711
|
+
if (values.length === 0) {
|
|
712
|
+
return new _SelectBuilder(
|
|
713
|
+
{ ...this._options },
|
|
714
|
+
this._fetchAll,
|
|
715
|
+
this._fetchOne
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
if (!Array.isArray(fields)) {
|
|
719
|
+
whereNotInCondition = `(${fields}) NOT IN (VALUES `;
|
|
720
|
+
whereNotInCondition += values.map(() => "(?)").reduce(separateWithComma);
|
|
721
|
+
whereNotInCondition += ")";
|
|
722
|
+
whereNotInParams = values;
|
|
723
|
+
} else {
|
|
724
|
+
const fieldLength = fields.length;
|
|
725
|
+
whereNotInCondition = `(${fields.map((val) => val).reduce(separateWithComma)}) NOT IN (VALUES `;
|
|
726
|
+
const valuesString = `(${[...new Array(fieldLength).keys()].map(() => "?").reduce(separateWithComma)})`;
|
|
727
|
+
whereNotInCondition += [...new Array(values.length).keys()].map(() => valuesString).reduce(separateWithComma);
|
|
728
|
+
whereNotInCondition += ")";
|
|
729
|
+
whereNotInParams = values.flat();
|
|
730
|
+
}
|
|
731
|
+
return this.where(whereNotInCondition, whereNotInParams);
|
|
732
|
+
}
|
|
441
733
|
join(join) {
|
|
442
734
|
const joins = Array.isArray(join) ? join : [join];
|
|
443
735
|
const processedJoins = joins.map((j) => {
|
|
@@ -478,7 +770,7 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
478
770
|
* Add a CROSS JOIN to the query.
|
|
479
771
|
*/
|
|
480
772
|
crossJoin(params) {
|
|
481
|
-
return this.join({ ...params, type: "CROSS" /* CROSS */, on: "
|
|
773
|
+
return this.join({ ...params, type: "CROSS" /* CROSS */, on: "" });
|
|
482
774
|
}
|
|
483
775
|
/**
|
|
484
776
|
* Add a NATURAL JOIN to the query.
|
|
@@ -635,7 +927,13 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
635
927
|
let builtCondition = conditionParts[0] ?? "";
|
|
636
928
|
for (let j = 0; j < conditionParts.length - 1; j++) {
|
|
637
929
|
if (paramIndex >= currentInputParams.length) {
|
|
638
|
-
|
|
930
|
+
const totalPlaceholders = currentInputConditions.join(" AND ").split("?").length - 1;
|
|
931
|
+
throw new ParameterMismatchError({
|
|
932
|
+
clause: "HAVING",
|
|
933
|
+
query: currentInputConditions.join(" AND "),
|
|
934
|
+
expectedParams: totalPlaceholders,
|
|
935
|
+
receivedParams: currentInputParams.length
|
|
936
|
+
});
|
|
639
937
|
}
|
|
640
938
|
const currentParam = currentInputParams[paramIndex++];
|
|
641
939
|
const isSubQuery = typeof currentParam === "object" && currentParam !== null && ("tableName" in currentParam || "getOptions" in currentParam) && !currentParam.hasOwnProperty("_raw") || currentParam instanceof _SelectBuilder;
|
|
@@ -654,7 +952,13 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
654
952
|
processedNewConditions.push(builtCondition);
|
|
655
953
|
}
|
|
656
954
|
if (paramIndex < currentInputParams.length) {
|
|
657
|
-
|
|
955
|
+
const totalPlaceholders = currentInputConditions.join(" AND ").split("?").length - 1;
|
|
956
|
+
throw new ParameterMismatchError({
|
|
957
|
+
clause: "HAVING",
|
|
958
|
+
query: currentInputConditions.join(" AND "),
|
|
959
|
+
expectedParams: totalPlaceholders,
|
|
960
|
+
receivedParams: currentInputParams.length
|
|
961
|
+
});
|
|
658
962
|
}
|
|
659
963
|
return new _SelectBuilder(
|
|
660
964
|
{
|
|
@@ -766,6 +1070,18 @@ var SelectBuilder = class _SelectBuilder {
|
|
|
766
1070
|
*/
|
|
767
1071
|
paginate(options) {
|
|
768
1072
|
const { page, perPage } = options;
|
|
1073
|
+
if (!Number.isInteger(page) || page < 1) {
|
|
1074
|
+
throw new InvalidConfigurationError(
|
|
1075
|
+
`Invalid page value: ${page}. Page must be an integer >= 1.`,
|
|
1076
|
+
"Pass a positive integer for the page option, e.g. paginate({ page: 1, perPage: 20 })"
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
if (!Number.isInteger(perPage) || perPage < 1) {
|
|
1080
|
+
throw new InvalidConfigurationError(
|
|
1081
|
+
`Invalid perPage value: ${perPage}. PerPage must be an integer >= 1.`,
|
|
1082
|
+
"Pass a positive integer for the perPage option, e.g. paginate({ page: 1, perPage: 20 })"
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
769
1085
|
const offset = (page - 1) * perPage;
|
|
770
1086
|
const countQuery = this._fetchOne(this._options);
|
|
771
1087
|
const dataQuery = this._fetchAll({
|
|
@@ -1009,7 +1325,7 @@ var QueryBuilder = class {
|
|
|
1009
1325
|
insert(params) {
|
|
1010
1326
|
let args = [];
|
|
1011
1327
|
if (typeof params.onConflict === "object") {
|
|
1012
|
-
if (typeof params.onConflict?.where === "object" && !Array.isArray(params.onConflict?.where) && params.onConflict?.where?.params) {
|
|
1328
|
+
if (typeof params.onConflict?.where === "object" && !Array.isArray(params.onConflict?.where) && params.onConflict?.where?.params != null) {
|
|
1013
1329
|
args = args.concat(params.onConflict.where?.params);
|
|
1014
1330
|
}
|
|
1015
1331
|
if (params.onConflict.data) {
|
|
@@ -1037,7 +1353,7 @@ var QueryBuilder = class {
|
|
|
1037
1353
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1038
1354
|
update(params) {
|
|
1039
1355
|
let args = this._parse_arguments(params.data);
|
|
1040
|
-
if (typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params) {
|
|
1356
|
+
if (typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params != null) {
|
|
1041
1357
|
if (Array.isArray(params.where?.params)) {
|
|
1042
1358
|
args = params.where?.params.concat(args);
|
|
1043
1359
|
} else {
|
|
@@ -1061,7 +1377,7 @@ var QueryBuilder = class {
|
|
|
1061
1377
|
return this.execute(q);
|
|
1062
1378
|
},
|
|
1063
1379
|
this._delete(params),
|
|
1064
|
-
typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params ? Array.isArray(params.where?.params) ? params.where?.params : [params.where?.params] : void 0,
|
|
1380
|
+
typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params != null ? Array.isArray(params.where?.params) ? params.where?.params : [params.where?.params] : void 0,
|
|
1065
1381
|
"ALL" /* ALL */
|
|
1066
1382
|
);
|
|
1067
1383
|
}
|
|
@@ -1104,7 +1420,7 @@ var QueryBuilder = class {
|
|
|
1104
1420
|
let onConflict = "";
|
|
1105
1421
|
if (params.onConflict && typeof params.onConflict === "object") {
|
|
1106
1422
|
onConflict = this._onConflict(params.onConflict);
|
|
1107
|
-
if (typeof params.onConflict?.where === "object" && !Array.isArray(params.onConflict?.where) && params.onConflict?.where?.params) {
|
|
1423
|
+
if (typeof params.onConflict?.where === "object" && !Array.isArray(params.onConflict?.where) && params.onConflict?.where?.params != null) {
|
|
1108
1424
|
if (Array.isArray(params.onConflict.where?.params)) {
|
|
1109
1425
|
index += (params.onConflict.where?.params).length;
|
|
1110
1426
|
} else {
|
|
@@ -1132,7 +1448,7 @@ var QueryBuilder = class {
|
|
|
1132
1448
|
return `INSERT ${orConflict} INTO ${params.tableName} (${columns}) VALUES ${rows.join(", ")}` + onConflict + this._returning(params.returning);
|
|
1133
1449
|
}
|
|
1134
1450
|
_update(params) {
|
|
1135
|
-
const whereParamsLength = typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params ? Array.isArray(params.where?.params) ? Object.keys(params.where?.params).length : 1 : 0;
|
|
1451
|
+
const whereParamsLength = typeof params.where === "object" && !Array.isArray(params.where) && params.where?.params != null ? Array.isArray(params.where?.params) ? Object.keys(params.where?.params).length : 1 : 0;
|
|
1136
1452
|
let whereString = this._where(params.where);
|
|
1137
1453
|
let parameterIndex = 1;
|
|
1138
1454
|
if (whereString && whereString.match(/(?<!\d)\?(?!\d)/)) {
|
|
@@ -1153,7 +1469,7 @@ var QueryBuilder = class {
|
|
|
1153
1469
|
}
|
|
1154
1470
|
_delete(params) {
|
|
1155
1471
|
return `DELETE
|
|
1156
|
-
FROM ${params.tableName}` + this._where(params.where) + this.
|
|
1472
|
+
FROM ${params.tableName}` + this._where(params.where) + this._orderBy(params.orderBy) + this._limit(params.limit) + this._offset(params.offset) + this._returning(params.returning);
|
|
1157
1473
|
}
|
|
1158
1474
|
_select(params, queryArgs) {
|
|
1159
1475
|
let newQueryArgs = queryArgs;
|
|
@@ -1205,7 +1521,7 @@ var QueryBuilder = class {
|
|
|
1205
1521
|
let primitiveParams = [];
|
|
1206
1522
|
if (typeof value === "object" && !Array.isArray(value)) {
|
|
1207
1523
|
conditionStrings = Array.isArray(value.conditions) ? value.conditions : [value.conditions];
|
|
1208
|
-
if (value.params) {
|
|
1524
|
+
if (value.params != null) {
|
|
1209
1525
|
primitiveParams = Array.isArray(value.params) ? value.params : [value.params];
|
|
1210
1526
|
}
|
|
1211
1527
|
} else if (Array.isArray(value)) {
|
|
@@ -1297,7 +1613,7 @@ var QueryBuilder = class {
|
|
|
1297
1613
|
} else {
|
|
1298
1614
|
tableSql = `(${context.toSQLCompiler(item.table, context.queryArgs)})`;
|
|
1299
1615
|
}
|
|
1300
|
-
if (item.type === "NATURAL" /* NATURAL */ || item.type === "NATURAL") {
|
|
1616
|
+
if (item.type === "NATURAL" /* NATURAL */ || item.type === "NATURAL" || !item.on) {
|
|
1301
1617
|
joinQuery.push(`${type}JOIN ${tableSql}${item.alias ? ` AS ${item.alias}` : ""}`);
|
|
1302
1618
|
} else {
|
|
1303
1619
|
joinQuery.push(`${type}JOIN ${tableSql}${item.alias ? ` AS ${item.alias}` : ""} ON ${item.on}`);
|
|
@@ -1317,7 +1633,7 @@ var QueryBuilder = class {
|
|
|
1317
1633
|
let primitiveParams = [];
|
|
1318
1634
|
if (typeof value === "object" && !Array.isArray(value)) {
|
|
1319
1635
|
conditionStrings = Array.isArray(value.conditions) ? value.conditions : [value.conditions];
|
|
1320
|
-
if (value.params) {
|
|
1636
|
+
if (value.params != null) {
|
|
1321
1637
|
primitiveParams = Array.isArray(value.params) ? value.params : [value.params];
|
|
1322
1638
|
}
|
|
1323
1639
|
} else if (Array.isArray(value)) {
|
|
@@ -1414,11 +1730,11 @@ var QueryBuilder = class {
|
|
|
1414
1730
|
return ` ORDER BY ${result.join(", ")}`;
|
|
1415
1731
|
}
|
|
1416
1732
|
_limit(value) {
|
|
1417
|
-
if (
|
|
1733
|
+
if (value == null) return "";
|
|
1418
1734
|
return ` LIMIT ${value}`;
|
|
1419
1735
|
}
|
|
1420
1736
|
_offset(value) {
|
|
1421
|
-
if (
|
|
1737
|
+
if (value == null) return "";
|
|
1422
1738
|
return ` OFFSET ${value}`;
|
|
1423
1739
|
}
|
|
1424
1740
|
_returning(value) {
|
|
@@ -1474,10 +1790,10 @@ var syncMigrationsBuilder = class {
|
|
|
1474
1790
|
const appliedMigrations = [];
|
|
1475
1791
|
for (const migration of this.getUnapplied()) {
|
|
1476
1792
|
this._builder.raw({
|
|
1477
|
-
query:
|
|
1478
|
-
${migration.sql}
|
|
1793
|
+
query: `${migration.sql}
|
|
1479
1794
|
INSERT INTO ${this._tableName} (name)
|
|
1480
|
-
values (
|
|
1795
|
+
values (?);`,
|
|
1796
|
+
args: [migration.name]
|
|
1481
1797
|
}).execute();
|
|
1482
1798
|
appliedMigrations.push(migration);
|
|
1483
1799
|
}
|
|
@@ -1529,10 +1845,10 @@ var asyncMigrationsBuilder = class {
|
|
|
1529
1845
|
const appliedMigrations = [];
|
|
1530
1846
|
for (const migration of await this.getUnapplied()) {
|
|
1531
1847
|
await this._builder.raw({
|
|
1532
|
-
query:
|
|
1533
|
-
${migration.sql}
|
|
1848
|
+
query: `${migration.sql}
|
|
1534
1849
|
INSERT INTO ${this._tableName} (name)
|
|
1535
|
-
values (
|
|
1850
|
+
values (?);`,
|
|
1851
|
+
args: [migration.name]
|
|
1536
1852
|
}).execute();
|
|
1537
1853
|
appliedMigrations.push(migration);
|
|
1538
1854
|
}
|
|
@@ -1589,7 +1905,7 @@ var D1QB = class extends QueryBuilder {
|
|
|
1589
1905
|
}
|
|
1590
1906
|
_getQueryType(sql) {
|
|
1591
1907
|
const trimmed = sql.trim().toUpperCase();
|
|
1592
|
-
if (trimmed.startsWith("SELECT")) return "SELECT";
|
|
1908
|
+
if (trimmed.startsWith("SELECT") || trimmed.startsWith("WITH")) return "SELECT";
|
|
1593
1909
|
if (trimmed.startsWith("INSERT")) return "INSERT";
|
|
1594
1910
|
if (trimmed.startsWith("UPDATE")) return "UPDATE";
|
|
1595
1911
|
if (trimmed.startsWith("DELETE")) return "DELETE";
|
|
@@ -1685,7 +2001,7 @@ var DOQB = class extends QueryBuilder {
|
|
|
1685
2001
|
const resultArray = cursor.toArray();
|
|
1686
2002
|
const rowsRead = cursor.rowsRead;
|
|
1687
2003
|
const rowsWritten = cursor.rowsWritten;
|
|
1688
|
-
if (query.fetchType
|
|
2004
|
+
if (query.fetchType === "ONE" /* ONE */) {
|
|
1689
2005
|
return {
|
|
1690
2006
|
results: resultArray.length > 0 ? resultArray[0] : void 0,
|
|
1691
2007
|
rowsRead,
|
|
@@ -1706,7 +2022,7 @@ var DOQB = class extends QueryBuilder {
|
|
|
1706
2022
|
}
|
|
1707
2023
|
_getQueryType(sql) {
|
|
1708
2024
|
const trimmed = sql.trim().toUpperCase();
|
|
1709
|
-
if (trimmed.startsWith("SELECT")) return "SELECT";
|
|
2025
|
+
if (trimmed.startsWith("SELECT") || trimmed.startsWith("WITH")) return "SELECT";
|
|
1710
2026
|
if (trimmed.startsWith("INSERT")) return "INSERT";
|
|
1711
2027
|
if (trimmed.startsWith("UPDATE")) return "UPDATE";
|
|
1712
2028
|
if (trimmed.startsWith("DELETE")) return "DELETE";
|
|
@@ -1754,15 +2070,47 @@ var DOQB = class extends QueryBuilder {
|
|
|
1754
2070
|
};
|
|
1755
2071
|
|
|
1756
2072
|
// src/databases/pg.ts
|
|
2073
|
+
var PGMigrationsBuilder = class extends asyncMigrationsBuilder {
|
|
2074
|
+
async initialize() {
|
|
2075
|
+
await this._builder.createTable({
|
|
2076
|
+
tableName: this._tableName,
|
|
2077
|
+
schema: `id SERIAL PRIMARY KEY,
|
|
2078
|
+
name TEXT UNIQUE,
|
|
2079
|
+
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL`,
|
|
2080
|
+
ifNotExists: true
|
|
2081
|
+
}).execute();
|
|
2082
|
+
}
|
|
2083
|
+
async apply() {
|
|
2084
|
+
const appliedMigrations = [];
|
|
2085
|
+
for (const migration of await this.getUnapplied()) {
|
|
2086
|
+
await this._builder.raw({ query: "BEGIN" }).execute();
|
|
2087
|
+
try {
|
|
2088
|
+
await this._builder.raw({
|
|
2089
|
+
query: migration.sql
|
|
2090
|
+
}).execute();
|
|
2091
|
+
await this._builder.raw({
|
|
2092
|
+
query: `INSERT INTO ${this._tableName} (name)
|
|
2093
|
+
values (?);`,
|
|
2094
|
+
args: [migration.name]
|
|
2095
|
+
}).execute();
|
|
2096
|
+
await this._builder.raw({ query: "COMMIT" }).execute();
|
|
2097
|
+
appliedMigrations.push(migration);
|
|
2098
|
+
} catch (error) {
|
|
2099
|
+
await this._builder.raw({ query: "ROLLBACK" }).execute();
|
|
2100
|
+
throw error;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
return appliedMigrations;
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
1757
2106
|
var PGQB = class extends QueryBuilder {
|
|
1758
2107
|
db;
|
|
1759
|
-
_migrationsBuilder = asyncMigrationsBuilder;
|
|
1760
2108
|
constructor(db, options) {
|
|
1761
2109
|
super(options);
|
|
1762
2110
|
this.db = db;
|
|
1763
2111
|
}
|
|
1764
2112
|
migrations(options) {
|
|
1765
|
-
return new
|
|
2113
|
+
return new PGMigrationsBuilder(options, this);
|
|
1766
2114
|
}
|
|
1767
2115
|
async connect() {
|
|
1768
2116
|
await this.db.connect();
|
|
@@ -1772,7 +2120,9 @@ var PGQB = class extends QueryBuilder {
|
|
|
1772
2120
|
}
|
|
1773
2121
|
async execute(query) {
|
|
1774
2122
|
return await this.loggerWrapper(query, this.options.logger, async () => {
|
|
1775
|
-
const
|
|
2123
|
+
const maxNumbered = Math.max(0, ...[...query.query.matchAll(/\?(\d+)/g)].map((m) => Number.parseInt(m[1], 10)));
|
|
2124
|
+
let paramIndex = maxNumbered;
|
|
2125
|
+
const queryString = query.query.replace(/\?(\d+)?/g, (_, n) => n !== void 0 ? `$${n}` : `$${++paramIndex}`);
|
|
1776
2126
|
let result;
|
|
1777
2127
|
if (query.arguments) {
|
|
1778
2128
|
result = await this.db.query({
|