pqb 0.42.6 → 0.42.8

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
@@ -331,6 +331,58 @@ class ColumnType extends orchidCore.ColumnTypeBase {
331
331
  name: typeof args[0] === "string" ? args[0] : void 0
332
332
  });
333
333
  }
334
+ /**
335
+ * Add [EXCLUDE constraint](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) to the column.
336
+ *
337
+ * ```ts
338
+ * import { change } from '../dbScript';
339
+ *
340
+ * change(async (db) => {
341
+ * await db.createTable('table', (t) => ({
342
+ * // exclude rows with overlapping time ranges, && is for the `WITH` operator
343
+ * timeRange: t.type('tstzrange').exclude('&&'),
344
+ * // with a database-level name:
345
+ * timeRange: t.type('tstzrange').exclude('&&', 'no_overlap'),
346
+ * // with options:
347
+ * timeRange: t.type('tstzrange').exclude('&&', { ...options }),
348
+ * // with name and options:
349
+ * name: t.type('tstzrange').exclude('&&', 'no_overlap', { ...options }),
350
+ * }));
351
+ * });
352
+ * ```
353
+ *
354
+ * Possible options are:
355
+ *
356
+ * ```ts
357
+ * interface ExcludeColumnOptions {
358
+ * // specify collation:
359
+ * collate?: string;
360
+ * // see `opclass` in the Postgres document for creating the index
361
+ * opclass?: string;
362
+ * // specify index order such as ASC NULLS FIRST, DESC NULLS LAST
363
+ * order?: string;
364
+ * // algorithm to use such as GIST, GIN
365
+ * using?: string;
366
+ * // EXCLUDE creates an index under the hood, include columns to the index
367
+ * include?: MaybeArray<string>;
368
+ * // see "storage parameters" in the Postgres document for creating an index, for example, 'fillfactor = 70'
369
+ * with?: string;
370
+ * // The tablespace in which to create the constraint. If not specified, default_tablespace is consulted, or temp_tablespaces for indexes on temporary tables.
371
+ * tablespace?: string;
372
+ * // WHERE clause to filter records for the constraint
373
+ * where?: string;
374
+ * // for dropping the index at a down migration
375
+ * dropMode?: DropMode;
376
+ * }
377
+ * ```
378
+ */
379
+ exclude(...args) {
380
+ return orchidCore.pushColumnData(this, "excludes", {
381
+ with: args[0],
382
+ options: (typeof args[1] === "string" ? args[2] : args[1]) ?? orchidCore.emptyObject,
383
+ name: typeof args[1] === "string" ? args[1] : void 0
384
+ });
385
+ }
334
386
  comment(comment) {
335
387
  return orchidCore.setColumnData(this, "comment", comment);
336
388
  }
@@ -364,7 +416,21 @@ class ColumnType extends orchidCore.ColumnTypeBase {
364
416
  */
365
417
  generated(...args) {
366
418
  const sql = raw(...args);
367
- return orchidCore.setColumnData(this, "generated", (...args2) => sql.toSQL(...args2));
419
+ return orchidCore.setColumnData(this, "generated", {
420
+ toSQL(ctx, quoted) {
421
+ return sql.toSQL(ctx, quoted);
422
+ },
423
+ toCode() {
424
+ let sql2 = ".generated";
425
+ if (Array.isArray(args[0])) {
426
+ sql2 += orchidCore.templateLiteralSQLToCode(args);
427
+ } else {
428
+ const { raw: raw2, values } = args[0];
429
+ sql2 += `({ raw: '${raw2.replace(/'/g, "\\'")}'${values ? `, values: ${JSON.stringify(values)}` : ""} })`;
430
+ }
431
+ return sql2;
432
+ }
433
+ });
368
434
  }
369
435
  }
370
436
 
@@ -441,20 +507,12 @@ const columnsShapeToCode = (ctx, shape) => {
441
507
  return code;
442
508
  };
443
509
  const pushTableDataCode = (code, ast) => {
444
- const lines = [];
445
- if (ast.primaryKey) {
446
- lines.push([primaryKeyInnerToCode(ast.primaryKey, "t") + ","]);
447
- }
448
- if (ast.indexes) {
449
- for (const index of ast.indexes) {
450
- lines.push(indexToCode(index, "t"));
451
- }
452
- }
453
- if (ast.constraints) {
454
- for (const constraint of ast.constraints) {
455
- lines.push(constraintToCode(constraint, "t", true));
456
- }
457
- }
510
+ const lines = [
511
+ ast.primaryKey && [primaryKeyInnerToCode(ast.primaryKey, "t") + ","],
512
+ ...ast.indexes?.map((x) => indexToCode(x, "t")) || orchidCore.emptyArray,
513
+ ...ast.excludes?.map((x) => excludeToCode(x, "t")) || orchidCore.emptyArray,
514
+ ...ast.constraints?.map((x) => constraintToCode(x, "t", true)) || orchidCore.emptyArray
515
+ ].filter((x) => !!x);
458
516
  if (lines.length > 1) {
459
517
  code.push("(t) => [", ...lines, "],");
460
518
  } else if (lines[0].length === 1 && typeof lines[0][0] === "string") {
@@ -468,18 +526,17 @@ const primaryKeyInnerToCode = (primaryKey, t) => {
468
526
  const name = primaryKey.name;
469
527
  return `${t}.primaryKey([${primaryKey.columns.map(orchidCore.singleQuote).join(", ")}]${name ? `, ${orchidCore.singleQuote(name)}` : ""})`;
470
528
  };
471
- const indexToCode = (index, t, prefix) => {
472
- const code = indexInnerToCode(index, t);
529
+ const indexOrExcludeToCode = (innerToCode) => (item, t, prefix) => {
530
+ const code = innerToCode(item, t);
473
531
  if (prefix) code[0] = prefix + code[0];
474
532
  const last = code[code.length - 1];
475
533
  if (typeof last === "string" && !last.endsWith(",")) orchidCore.addCode(code, ",");
476
534
  return code;
477
535
  };
478
536
  const indexInnerToCode = (index, t) => {
479
- const code = [];
480
- code.push(
537
+ const code = [
481
538
  `${t}.${index.options.tsVector ? "searchIndex" : index.options.unique ? "unique" : "index"}(`
482
- );
539
+ ];
483
540
  const columnOptions = ["collate", "opclass", "order", "weight"];
484
541
  const indexOptionsKeys = [
485
542
  index.options.tsVector ? "unique" : void 0,
@@ -570,6 +627,54 @@ const indexInnerToCode = (index, t) => {
570
627
  }
571
628
  return code;
572
629
  };
630
+ const indexToCode = indexOrExcludeToCode(indexInnerToCode);
631
+ const excludeInnerToCode = (item, t) => {
632
+ const code = [`${t}.exclude(`];
633
+ const columnOptions = ["collate", "opclass", "order", "with"];
634
+ const optionsKeys = [
635
+ "using",
636
+ "include",
637
+ "with",
638
+ "tablespace",
639
+ "where",
640
+ "dropMode"
641
+ ];
642
+ const hasOptions = optionsKeys.some((key) => key && item.options[key]);
643
+ const objects = [];
644
+ for (const column of item.columns) {
645
+ const expr = "column" in column ? column.column : column.expression;
646
+ const props = [
647
+ `${"column" in column ? "column" : "expression"}: ${orchidCore.singleQuote(expr)},`
648
+ ];
649
+ for (const key of columnOptions) {
650
+ const value = column[key];
651
+ if (value !== void 0) {
652
+ props.push(`${key}: ${orchidCore.singleQuote(value)},`);
653
+ }
654
+ }
655
+ objects.push("{", props, "},");
656
+ }
657
+ code.push(["[", objects, hasOptions || item.name ? "]," : "]"]);
658
+ if (item.name) {
659
+ orchidCore.addCode(code, ` ${orchidCore.singleQuote(item.name)},`);
660
+ }
661
+ if (hasOptions) {
662
+ code.push(["{"]);
663
+ const options = [];
664
+ for (const key of optionsKeys) {
665
+ if (!key) continue;
666
+ const value = item.options[key];
667
+ if (value === null || value === void 0) continue;
668
+ options.push(
669
+ `${key}: ${Array.isArray(value) ? orchidCore.singleQuoteArray(value) : typeof value === "string" ? orchidCore.singleQuote(value) : value},`
670
+ );
671
+ }
672
+ code.push([options, "},"]);
673
+ }
674
+ code.push("),");
675
+ return code;
676
+ };
677
+ const excludeToCode = indexOrExcludeToCode(excludeInnerToCode);
573
678
  const constraintToCode = (item, t, m, prefix) => {
574
679
  const code = constraintInnerToCode(item, t, m);
575
680
  if (prefix) code[0] = prefix + code[0];
@@ -658,25 +763,22 @@ const foreignKeyArgumentToCode = ({
658
763
  }
659
764
  return code;
660
765
  };
661
- const columnIndexesToCode = (indexes) => {
766
+ const columnIndexesToCode = (items) => {
662
767
  const code = [];
663
- for (const { options, name } of indexes) {
768
+ for (const { options, name } of items) {
664
769
  orchidCore.addCode(code, `.${options.unique ? "unique" : "index"}(`);
665
- const arr = [];
666
- if (options.collate) arr.push(`collate: ${orchidCore.singleQuote(options.collate)},`);
667
- if (options.opclass) arr.push(`opclass: ${orchidCore.singleQuote(options.opclass)},`);
668
- if (options.order) arr.push(`order: ${orchidCore.singleQuote(options.order)},`);
669
- if (name) arr.push(`name: ${orchidCore.singleQuote(name)},`);
670
- if (options.using) arr.push(`using: ${orchidCore.singleQuote(options.using)},`);
671
- if (options.include)
672
- arr.push(
673
- `include: ${typeof options.include === "string" ? orchidCore.singleQuote(options.include) : `[${options.include.map(orchidCore.singleQuote).join(", ")}]`},`
674
- );
675
- if (options.nullsNotDistinct) arr.push(`nullsNotDistinct: true,`);
676
- if (options.with) arr.push(`with: ${orchidCore.singleQuote(options.with)},`);
677
- if (options.tablespace)
678
- arr.push(`tablespace: ${orchidCore.singleQuote(options.tablespace)},`);
679
- if (options.where) arr.push(`where: ${orchidCore.singleQuote(options.where)},`);
770
+ const arr = [
771
+ options.collate && `collate: ${orchidCore.singleQuote(options.collate)},`,
772
+ options.opclass && `opclass: ${orchidCore.singleQuote(options.opclass)},`,
773
+ options.order && `order: ${orchidCore.singleQuote(options.order)},`,
774
+ name && `name: ${orchidCore.singleQuote(name)},`,
775
+ options.using && `using: ${orchidCore.singleQuote(options.using)},`,
776
+ options.include && `include: ${typeof options.include === "string" ? orchidCore.singleQuote(options.include) : `[${options.include.map(orchidCore.singleQuote).join(", ")}]`},`,
777
+ options.nullsNotDistinct && `nullsNotDistinct: true,`,
778
+ options.with && `with: ${orchidCore.singleQuote(options.with)},`,
779
+ options.tablespace && `tablespace: ${orchidCore.singleQuote(options.tablespace)},`,
780
+ options.where && `where: ${orchidCore.singleQuote(options.where)},`
781
+ ].filter((x) => !!x);
680
782
  if (arr.length) {
681
783
  orchidCore.addCode(code, "{");
682
784
  orchidCore.addCode(code, arr);
@@ -686,6 +788,30 @@ const columnIndexesToCode = (indexes) => {
686
788
  }
687
789
  return code;
688
790
  };
791
+ const columnExcludesToCode = (items) => {
792
+ const code = [];
793
+ for (const { options, name, with: w } of items) {
794
+ orchidCore.addCode(code, `.exclude('${w}'`);
795
+ const arr = [
796
+ options.collate && `collate: ${orchidCore.singleQuote(options.collate)},`,
797
+ options.opclass && `opclass: ${orchidCore.singleQuote(options.opclass)},`,
798
+ options.order && `order: ${orchidCore.singleQuote(options.order)},`,
799
+ name && `name: ${orchidCore.singleQuote(name)},`,
800
+ options.using && `using: ${orchidCore.singleQuote(options.using)},`,
801
+ options.include && `include: ${typeof options.include === "string" ? orchidCore.singleQuote(options.include) : `[${options.include.map(orchidCore.singleQuote).join(", ")}]`},`,
802
+ options.with && `with: ${orchidCore.singleQuote(options.with)},`,
803
+ options.tablespace && `tablespace: ${orchidCore.singleQuote(options.tablespace)},`,
804
+ options.where && `where: ${orchidCore.singleQuote(options.where)},`
805
+ ].filter((x) => !!x);
806
+ if (arr.length) {
807
+ orchidCore.addCode(code, ", {");
808
+ orchidCore.addCode(code, arr);
809
+ orchidCore.addCode(code, "}");
810
+ }
811
+ orchidCore.addCode(code, ")");
812
+ }
813
+ return code;
814
+ };
689
815
  const columnCheckToCode = (ctx, { sql, name }, columnName) => {
690
816
  return `.check(${sql.toCode(ctx.t)}${name && name !== `${ctx.table}_${columnName}_check` ? `, { name: '${name}' }` : ""})`;
691
817
  };
@@ -728,6 +854,9 @@ const columnCode = (type, ctx, key, code) => {
728
854
  } else {
729
855
  code[0].unshift(prepend);
730
856
  }
857
+ if (data.generated) {
858
+ orchidCore.addCode(code, data.generated.toCode());
859
+ }
731
860
  if (data.primaryKey) {
732
861
  orchidCore.addCode(
733
862
  code,
@@ -762,6 +891,11 @@ const columnCode = (type, ctx, key, code) => {
762
891
  orchidCore.addCode(code, part);
763
892
  }
764
893
  }
894
+ if (data.excludes) {
895
+ for (const part of columnExcludesToCode(data.excludes)) {
896
+ orchidCore.addCode(code, part);
897
+ }
898
+ }
765
899
  if (data.comment) orchidCore.addCode(code, `.comment(${orchidCore.singleQuote(data.comment)})`);
766
900
  if (data.check) {
767
901
  orchidCore.addCode(code, columnCheckToCode(ctx, data.check, name));
@@ -1322,32 +1456,59 @@ class TsVectorColumn extends ColumnType {
1322
1456
  * @param args
1323
1457
  */
1324
1458
  generated(...args) {
1325
- return orchidCore.setColumnData(this, "generated", (ctx, quotedAs) => {
1459
+ const arg = args[0];
1460
+ if (typeof arg === "object" && "raw" in arg) {
1461
+ return super.generated(...args);
1462
+ }
1463
+ const toSQL = (ctx) => {
1326
1464
  const first = args[0];
1327
- if (typeof first === "string" || !("raw" in first)) {
1328
- const target = typeof first === "string" ? args[1] : first;
1329
- const language = typeof first === "string" ? first : this.defaultLanguage;
1330
- const { snakeCase } = ctx;
1331
- let sql;
1332
- if (Array.isArray(target)) {
1333
- const columns = target.length === 1 ? `"${snakeCase ? orchidCore.toSnakeCase(target[0]) : target[0]}"` : target.map(
1334
- (column) => `coalesce("${snakeCase ? orchidCore.toSnakeCase(column) : column}", '')`
1335
- ).join(` || ' ' || `);
1336
- sql = `to_tsvector('${language}', ${columns})`;
1465
+ const target = typeof first === "string" ? args[1] : first;
1466
+ const language = typeof first === "string" ? first : this.defaultLanguage;
1467
+ const { snakeCase } = ctx;
1468
+ let sql;
1469
+ if (Array.isArray(target)) {
1470
+ const columns = target.length === 1 ? `"${snakeCase ? orchidCore.toSnakeCase(target[0]) : target[0]}"` : target.map(
1471
+ (column) => `coalesce("${snakeCase ? orchidCore.toSnakeCase(column) : column}", '')`
1472
+ ).join(` || ' ' || `);
1473
+ sql = `to_tsvector('${language}', ${columns})`;
1474
+ } else {
1475
+ for (const key in target) {
1476
+ sql = (sql ? sql + " || " : "(") + `setweight(to_tsvector('${language}', coalesce("${snakeCase ? orchidCore.toSnakeCase(key) : key}", '')), '${target[key]}')`;
1477
+ }
1478
+ if (sql) {
1479
+ sql += ")";
1337
1480
  } else {
1338
- for (const key in target) {
1339
- sql = (sql ? sql + " || " : "(") + `setweight(to_tsvector('${language}', coalesce("${snakeCase ? orchidCore.toSnakeCase(key) : key}", '')), '${target[key]}')`;
1340
- }
1341
- if (sql) {
1342
- sql += ")";
1343
- } else {
1344
- throw new Error("Empty target in the text search generated column");
1345
- }
1481
+ throw new Error("Empty target in the text search generated column");
1346
1482
  }
1347
- return sql;
1483
+ }
1484
+ return sql;
1485
+ };
1486
+ const toCode = () => {
1487
+ let code = ".generated(";
1488
+ const first = args[0];
1489
+ let target;
1490
+ if (typeof first === "string") {
1491
+ code += `'${first}', `;
1492
+ target = args[1];
1348
1493
  } else {
1349
- return raw(...args).toSQL(ctx, quotedAs);
1494
+ target = args[0];
1350
1495
  }
1496
+ if (Array.isArray(target)) {
1497
+ code += `[${target.map((x) => `'${x}'`).join(", ")}]`;
1498
+ } else {
1499
+ const pairs = [];
1500
+ for (const key in target) {
1501
+ pairs.push(
1502
+ `${orchidCore.quoteObjectKey(key)}: '${target[key]}'`
1503
+ );
1504
+ }
1505
+ code += `{ ${pairs.join(", ")} }`;
1506
+ }
1507
+ return code + ")";
1508
+ };
1509
+ return orchidCore.setColumnData(this, "generated", {
1510
+ toSQL,
1511
+ toCode
1351
1512
  });
1352
1513
  }
1353
1514
  }
@@ -11986,6 +12147,19 @@ const tableDataMethods = {
11986
12147
  input.index.options.tsVector = true;
11987
12148
  return input;
11988
12149
  },
12150
+ exclude(columns, ...[first, second]) {
12151
+ if (typeof first === "string") {
12152
+ const options = second ?? {};
12153
+ return {
12154
+ exclude: { columns, options, name: first }
12155
+ };
12156
+ } else {
12157
+ const options = first ?? {};
12158
+ return {
12159
+ exclude: { columns, options }
12160
+ };
12161
+ }
12162
+ },
11989
12163
  foreignKey(columns, fnOrTable, foreignColumns, options) {
11990
12164
  return {
11991
12165
  constraint: {
@@ -12017,15 +12191,13 @@ const parseTableDataInput = (tableData, item) => {
12017
12191
  if (item.primaryKey) {
12018
12192
  tableData.primaryKey = item.primaryKey;
12019
12193
  } else if (item.index) {
12020
- const index = item.index;
12021
- for (let i = index.columns.length - 1; i >= 0; i--) {
12022
- if (typeof index.columns[i] === "string") {
12023
- index.columns[i] = {
12024
- column: index.columns[i]
12025
- };
12026
- }
12027
- }
12028
- (tableData.indexes ?? (tableData.indexes = [])).push(item.index);
12194
+ (tableData.indexes ?? (tableData.indexes = [])).push(
12195
+ parseIndexOrExclude(item.index)
12196
+ );
12197
+ } else if (item.exclude) {
12198
+ (tableData.excludes ?? (tableData.excludes = [])).push(
12199
+ parseIndexOrExclude(item.exclude)
12200
+ );
12029
12201
  } else if (item.constraint) {
12030
12202
  (tableData.constraints ?? (tableData.constraints = [])).push(item.constraint);
12031
12203
  if (item.constraint.references?.options?.dropMode) {
@@ -12033,6 +12205,16 @@ const parseTableDataInput = (tableData, item) => {
12033
12205
  }
12034
12206
  }
12035
12207
  };
12208
+ const parseIndexOrExclude = (item) => {
12209
+ for (let i = item.columns.length - 1; i >= 0; i--) {
12210
+ if (typeof item.columns[i] === "string") {
12211
+ item.columns[i] = {
12212
+ column: item.columns[i]
12213
+ };
12214
+ }
12215
+ }
12216
+ return item;
12217
+ };
12036
12218
 
12037
12219
  const anyShape = {};
12038
12220
  class Db extends QueryMethods {
@@ -12674,6 +12856,7 @@ exports.cloneQuery = cloneQuery;
12674
12856
  exports.cloneQueryBaseUnscoped = cloneQueryBaseUnscoped;
12675
12857
  exports.columnCheckToCode = columnCheckToCode;
12676
12858
  exports.columnCode = columnCode;
12859
+ exports.columnExcludesToCode = columnExcludesToCode;
12677
12860
  exports.columnForeignKeysToCode = columnForeignKeysToCode;
12678
12861
  exports.columnIndexesToCode = columnIndexesToCode;
12679
12862
  exports.columnsShapeToCode = columnsShapeToCode;
@@ -12687,6 +12870,8 @@ exports.defaultSchemaConfig = defaultSchemaConfig;
12687
12870
  exports.escapeForLog = escapeForLog;
12688
12871
  exports.escapeForMigration = escapeForMigration;
12689
12872
  exports.escapeString = escapeString;
12873
+ exports.excludeInnerToCode = excludeInnerToCode;
12874
+ exports.excludeToCode = excludeToCode;
12690
12875
  exports.extendQuery = extendQuery;
12691
12876
  exports.filterResult = filterResult;
12692
12877
  exports.foreignKeyArgumentToCode = foreignKeyArgumentToCode;