pqb 0.52.0 → 0.52.2

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
@@ -927,20 +927,33 @@ const getSqlText = (sql) => {
927
927
  };
928
928
 
929
929
  class CustomTypeColumn extends ColumnType {
930
- constructor(schema, dataType, extension) {
930
+ constructor(schema, typeName, typeSchema, extension) {
931
931
  super(
932
932
  schema,
933
933
  schema.unknown(),
934
934
  schema.unknown(),
935
935
  schema.unknown()
936
936
  );
937
- this.dataType = dataType;
937
+ this.typeName = typeName;
938
+ this.typeSchema = typeSchema;
938
939
  this.operators = Operators.any;
940
+ this.dataType = typeSchema ? typeSchema + "." + typeName : typeName;
939
941
  this.data.isOfCustomType = true;
940
942
  this.data.extension = extension;
941
943
  }
942
944
  toCode(ctx, key) {
943
- return columnCode(this, ctx, key, `type(${orchidCore.singleQuote(this.dataType)})`);
945
+ const {
946
+ dataType,
947
+ data: { typmod }
948
+ } = this;
949
+ return columnCode(
950
+ this,
951
+ ctx,
952
+ key,
953
+ `type(${orchidCore.singleQuote(
954
+ (dataType.startsWith(ctx.currentSchema) ? dataType.slice(ctx.currentSchema.length + 1) : dataType) + (typmod !== void 0 && typmod !== -1 && !dataType.includes("(") ? `(${typmod})` : "")
955
+ )})`
956
+ );
944
957
  }
945
958
  as(column) {
946
959
  const c = orchidCore.setColumnData(
@@ -1274,1507 +1287,1522 @@ const Operators = {
1274
1287
  array
1275
1288
  };
1276
1289
 
1277
- class TextBaseColumn extends ColumnType {
1278
- constructor(schema, schemaType = schema.stringSchema()) {
1279
- super(schema, schemaType);
1280
- this.operators = Operators.text;
1281
- }
1282
- }
1283
- class LimitedTextBaseColumn extends TextBaseColumn {
1284
- constructor(schema, limit) {
1290
+ const dateTimeEncode = (input) => {
1291
+ return typeof input === "number" ? new Date(input) : input;
1292
+ };
1293
+ class DateBaseColumn extends ColumnType {
1294
+ constructor(schema) {
1285
1295
  super(
1286
1296
  schema,
1287
- limit !== void 0 ? schema.stringMax(limit) : schema.stringSchema()
1288
- );
1289
- this.data.maxChars = limit;
1290
- }
1291
- toSQL() {
1292
- return orchidCore.joinTruthy(
1293
- this.dataType,
1294
- this.data.maxChars !== void 0 && `(${this.data.maxChars})`
1297
+ schema.stringNumberDate(),
1298
+ schema.stringSchema(),
1299
+ schema.stringNumberDate()
1295
1300
  );
1301
+ this.operators = Operators.date;
1302
+ this.asNumber = schema.dateAsNumber;
1303
+ this.asDate = schema.dateAsDate;
1304
+ this.data.encode = dateTimeEncode;
1296
1305
  }
1297
1306
  }
1298
- class VarCharColumn extends LimitedTextBaseColumn {
1307
+ class DateColumn extends DateBaseColumn {
1299
1308
  constructor() {
1300
1309
  super(...arguments);
1301
- this.dataType = "varchar";
1310
+ this.dataType = "date";
1302
1311
  }
1303
1312
  toCode(ctx, key) {
1304
- const { maxChars } = this.data;
1305
1313
  return columnCode(
1306
1314
  this,
1307
1315
  ctx,
1308
1316
  key,
1309
- `varchar(${maxChars ?? ""})${orchidCore.stringDataToCode(this.data, ctx.migration)}`
1317
+ `date()${orchidCore.dateDataToCode(this.data, ctx.migration)}`
1310
1318
  );
1311
1319
  }
1312
1320
  }
1313
- class StringColumn extends VarCharColumn {
1314
- constructor(schema, limit = 255) {
1315
- super(schema, limit);
1321
+ class DateTimeBaseClass extends DateBaseColumn {
1322
+ constructor(schema, dateTimePrecision) {
1323
+ super(schema);
1324
+ this.data.dateTimePrecision = dateTimePrecision;
1316
1325
  }
1317
- toCode(ctx, key) {
1318
- let max = this.data.maxChars;
1319
- if (max === 255) max = void 0;
1326
+ toSQL() {
1327
+ return orchidCore.joinTruthy(
1328
+ this.dataType,
1329
+ this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`
1330
+ );
1331
+ }
1332
+ }
1333
+ class DateTimeTzBaseClass extends DateTimeBaseClass {
1334
+ toSQL() {
1335
+ return orchidCore.joinTruthy(
1336
+ this.baseDataType,
1337
+ this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`,
1338
+ " with time zone"
1339
+ );
1340
+ }
1341
+ }
1342
+ const timestampToCode = (self, ctx, key) => {
1343
+ const { dateTimePrecision: p } = self.data;
1344
+ const { defaultTimestamp } = self.data;
1345
+ if (defaultTimestamp) {
1346
+ const noTz = self instanceof TimestampColumn ? "NoTZ" : "";
1347
+ const def = self.data.default;
1348
+ const modifyQuery = self.data.modifyQuery;
1349
+ self.data.default = void 0;
1350
+ self.data.modifyQuery = void 0;
1351
+ const code = columnCode(
1352
+ self,
1353
+ ctx,
1354
+ key,
1355
+ `timestamps${noTz}(${p && p !== 6 ? p : ""}).${defaultTimestamp}${orchidCore.dateDataToCode(self.data, ctx.migration)}`
1356
+ );
1357
+ self.data.default = def;
1358
+ self.data.modifyQuery = modifyQuery;
1359
+ return code;
1360
+ } else {
1320
1361
  return columnCode(
1321
- this,
1362
+ self,
1322
1363
  ctx,
1323
1364
  key,
1324
- `string(${max ?? ""})${orchidCore.stringDataToCode(this.data, ctx.migration)}`
1365
+ `${self instanceof TimestampColumn ? "timestampNoTZ" : "timestamp"}(${p && p !== 6 ? p : ""})${orchidCore.dateDataToCode(self.data, ctx.migration)}`
1325
1366
  );
1326
1367
  }
1327
- }
1328
- const textColumnToCode = (column, ctx, key) => {
1329
- const data = { ...column.data };
1330
- let args = "";
1331
- const hasMax = data.maxArg !== void 0 && data.max === data.maxArg;
1332
- if (data.minArg !== void 0 && data.min === data.minArg || hasMax) {
1333
- if (data.minArg !== 0 || hasMax && data.max !== Infinity) {
1334
- args += data.minArg;
1335
- }
1336
- delete data.min;
1337
- if (hasMax) {
1338
- if (data.maxArg !== Infinity) {
1339
- args += `, ${data.maxArg}`;
1340
- }
1341
- delete data.max;
1342
- }
1343
- }
1344
- return columnCode(
1345
- column,
1346
- ctx,
1347
- key,
1348
- `${column.dataType}(${args})${orchidCore.stringDataToCode(data, ctx.migration)}`
1349
- );
1350
1368
  };
1351
- class TextColumn extends TextBaseColumn {
1352
- constructor(schema) {
1353
- super(schema, schema.stringSchema());
1354
- this.dataType = "text";
1369
+ class TimestampColumn extends DateTimeBaseClass {
1370
+ constructor() {
1371
+ super(...arguments);
1372
+ this.dataType = "timestamp";
1355
1373
  }
1356
1374
  toCode(ctx, key) {
1357
- return textColumnToCode(this, ctx, key);
1375
+ return timestampToCode(this, ctx, key);
1358
1376
  }
1359
1377
  }
1360
- const byteaParse = (val) => typeof val === "string" ? Buffer.from(val.slice(2), "hex") : val;
1361
- class ByteaColumn extends ColumnType {
1362
- constructor(schema) {
1363
- super(schema, schema.buffer());
1364
- this.dataType = "bytea";
1365
- this.operators = Operators.text;
1366
- setColumnDefaultParse(this, byteaParse);
1378
+ class TimestampTZColumn extends DateTimeTzBaseClass {
1379
+ constructor() {
1380
+ super(...arguments);
1381
+ this.dataType = "timestamptz";
1382
+ this.baseDataType = "timestamp";
1367
1383
  }
1368
1384
  toCode(ctx, key) {
1369
- return columnCode(this, ctx, key, `bytea()`);
1385
+ return timestampToCode(this, ctx, key);
1370
1386
  }
1371
1387
  }
1372
- class PointColumn extends ColumnType {
1373
- constructor(schema) {
1388
+ class TimeColumn extends ColumnType {
1389
+ constructor(schema, dateTimePrecision) {
1374
1390
  super(schema, schema.stringSchema());
1375
- this.dataType = "point";
1376
- this.operators = Operators.text;
1391
+ this.dataType = "time";
1392
+ this.operators = Operators.time;
1393
+ this.data.dateTimePrecision = dateTimePrecision;
1377
1394
  }
1378
1395
  toCode(ctx, key) {
1379
- return columnCode(this, ctx, key, `point()`);
1396
+ const { dateTimePrecision } = this.data;
1397
+ return columnCode(
1398
+ this,
1399
+ ctx,
1400
+ key,
1401
+ `time(${dateTimePrecision || ""})${orchidCore.dateDataToCode(
1402
+ this.data,
1403
+ ctx.migration
1404
+ )}`
1405
+ );
1380
1406
  }
1381
1407
  }
1382
- class LineColumn extends ColumnType {
1383
- constructor(schema) {
1384
- super(schema, schema.stringSchema());
1385
- this.dataType = "line";
1386
- this.operators = Operators.text;
1408
+ class IntervalColumn extends ColumnType {
1409
+ constructor(schema, fields, precision) {
1410
+ super(schema, schema.timeInterval());
1411
+ this.dataType = "interval";
1412
+ this.operators = Operators.date;
1413
+ this.data.fields = fields;
1414
+ this.data.precision = precision;
1387
1415
  }
1388
1416
  toCode(ctx, key) {
1389
- return columnCode(this, ctx, key, `line()`);
1390
- }
1391
- }
1392
- class LsegColumn extends ColumnType {
1393
- constructor(schema) {
1394
- super(schema, schema.stringSchema());
1395
- this.dataType = "lseg";
1396
- this.operators = Operators.text;
1417
+ const { fields, precision } = this.data;
1418
+ return columnCode(
1419
+ this,
1420
+ ctx,
1421
+ key,
1422
+ `interval(${[fields && `'${fields}'`, precision && String(precision)].filter((part) => part).join(", ")})`
1423
+ );
1397
1424
  }
1398
- toCode(ctx, key) {
1399
- return columnCode(this, ctx, key, `lseg()`);
1425
+ toSQL() {
1426
+ return orchidCore.joinTruthy(
1427
+ this.dataType,
1428
+ this.data.fields && ` ${this.data.fields}`,
1429
+ this.data.precision !== void 0 && ` (${this.data.precision})`
1430
+ );
1400
1431
  }
1401
1432
  }
1402
- class BoxColumn extends ColumnType {
1403
- constructor(schema) {
1404
- super(schema, schema.stringSchema());
1405
- this.dataType = "box";
1406
- this.operators = Operators.text;
1407
- }
1408
- toCode(ctx, key) {
1409
- return columnCode(this, ctx, key, `box()`);
1433
+
1434
+ class ArrayColumn extends ColumnType {
1435
+ constructor(schema, item, inputType, outputType, queryType) {
1436
+ super(schema, inputType, outputType, queryType);
1437
+ this.dataType = "array";
1438
+ this.operators = Operators.array;
1439
+ item.data.isNullable = true;
1440
+ setColumnDefaultParse(this, (input) => parse$1.call(this, input));
1441
+ this.data.item = item instanceof ArrayColumn ? item.data.item : item;
1442
+ this.data.name = item.data.name;
1443
+ this.data.arrayDims = item instanceof ArrayColumn ? item.data.arrayDims + 1 : 1;
1410
1444
  }
1411
- }
1412
- class PathColumn extends ColumnType {
1413
- constructor(schema) {
1414
- super(schema, schema.stringSchema());
1415
- this.dataType = "path";
1416
- this.operators = Operators.text;
1445
+ toSQL() {
1446
+ return this.data.item.toSQL() + "[]".repeat(this.data.arrayDims);
1417
1447
  }
1418
1448
  toCode(ctx, key) {
1419
- return columnCode(this, ctx, key, `path()`);
1449
+ let open = "array(";
1450
+ let close = ")";
1451
+ for (let i = 1; i < this.data.arrayDims; i++) {
1452
+ open += `${ctx.t}.array(`;
1453
+ close += ")";
1454
+ }
1455
+ const code = [open];
1456
+ const { item } = this.data;
1457
+ const { isNullable } = item.data;
1458
+ delete item.data.isNullable;
1459
+ orchidCore.addCode(code, item.toCode(ctx, key));
1460
+ item.data.isNullable = isNullable;
1461
+ orchidCore.addCode(code, `${close}${orchidCore.arrayDataToCode(this.data, ctx.migration)}`);
1462
+ return columnCode(this, ctx, key, code);
1420
1463
  }
1421
1464
  }
1422
- class PolygonColumn extends ColumnType {
1423
- constructor(schema) {
1424
- super(schema, schema.stringSchema());
1425
- this.dataType = "polygon";
1426
- this.operators = Operators.text;
1427
- }
1428
- toCode(ctx, key) {
1429
- return columnCode(this, ctx, key, `polygon()`);
1465
+ const parse$1 = function(source) {
1466
+ if (typeof source !== "string") return source;
1467
+ const entries = [];
1468
+ parsePostgresArray(source, entries, this.data.item.data.parseItem);
1469
+ return entries;
1470
+ };
1471
+ const parsePostgresArray = (source, entries, transform) => {
1472
+ let pos = 0;
1473
+ if (source[0] === "[") {
1474
+ pos = source.indexOf("=") + 1;
1475
+ if (!pos) pos = source.length;
1430
1476
  }
1431
- }
1432
- class CircleColumn extends ColumnType {
1433
- constructor(schema) {
1434
- super(schema, schema.stringSchema());
1435
- this.dataType = "circle";
1436
- this.operators = Operators.text;
1477
+ if (source[pos] === "{") pos++;
1478
+ let recorded = "";
1479
+ while (pos < source.length) {
1480
+ const character = source[pos++];
1481
+ if (character === "{") {
1482
+ const innerEntries = [];
1483
+ entries.push(innerEntries);
1484
+ pos += parsePostgresArray(source.slice(pos - 1), innerEntries, transform) - 1;
1485
+ } else if (character === "}") {
1486
+ if (recorded) {
1487
+ entries.push(
1488
+ recorded === "NULL" ? null : transform ? transform(recorded) : recorded
1489
+ );
1490
+ }
1491
+ return pos;
1492
+ } else if (character === '"') {
1493
+ let esc = false;
1494
+ let rec = "";
1495
+ while (pos < source.length) {
1496
+ let char;
1497
+ while ((char = source[pos++]) === "\\") {
1498
+ if (!(esc = !esc)) rec += "\\";
1499
+ }
1500
+ if (esc) {
1501
+ esc = false;
1502
+ } else if (char === '"') {
1503
+ break;
1504
+ }
1505
+ rec += char;
1506
+ }
1507
+ entries.push(transform ? transform(rec) : rec);
1508
+ recorded = "";
1509
+ } else if (character === ",") {
1510
+ if (recorded) {
1511
+ entries.push(
1512
+ recorded === "NULL" ? null : transform ? transform(recorded) : recorded
1513
+ );
1514
+ recorded = "";
1515
+ }
1516
+ } else {
1517
+ recorded += character;
1518
+ }
1519
+ }
1520
+ return pos;
1521
+ };
1522
+
1523
+ const encode$1 = (x) => x === null ? x : JSON.stringify(x);
1524
+ class JSONColumn extends ColumnType {
1525
+ constructor(schema, inputType) {
1526
+ super(schema, inputType);
1527
+ this.dataType = "jsonb";
1528
+ this.operators = Operators.json;
1529
+ this.data.encode = encode$1;
1530
+ this.data.parseItem = JSON.parse;
1437
1531
  }
1438
1532
  toCode(ctx, key) {
1439
- return columnCode(this, ctx, key, `circle()`);
1533
+ return columnCode(this, ctx, key, `json()`);
1440
1534
  }
1441
1535
  }
1442
- class MoneyColumn extends ColumnType {
1536
+ class JSONTextColumn extends ColumnType {
1443
1537
  constructor(schema) {
1444
- super(schema, schema.number());
1445
- this.dataType = "money";
1446
- this.operators = Operators.number;
1447
- setColumnDefaultParse(this, moneyParse);
1538
+ super(schema, schema.stringSchema());
1539
+ this.dataType = "json";
1540
+ this.operators = Operators.text;
1541
+ }
1542
+ static get instance() {
1543
+ return this._instance ?? (this._instance = new JSONTextColumn(defaultSchemaConfig));
1448
1544
  }
1449
1545
  toCode(ctx, key) {
1450
- return columnCode(this, ctx, key, `money()`);
1546
+ return columnCode(this, ctx, key, `jsonText()`);
1451
1547
  }
1452
1548
  }
1453
- const moneyParse = Object.assign(
1454
- function(input) {
1455
- return input === null ? input : parseFloat(input.replace(/,/g, "").replace(/\$/g, ""));
1456
- },
1457
- {
1458
- hideFromCode: true
1549
+
1550
+ class NumberBaseColumn extends ColumnType {
1551
+ constructor() {
1552
+ super(...arguments);
1553
+ this.operators = Operators.number;
1459
1554
  }
1460
- );
1461
- class CidrColumn extends ColumnType {
1555
+ }
1556
+ class IntegerBaseColumn extends NumberBaseColumn {
1557
+ constructor(schema) {
1558
+ super(schema, schema.int());
1559
+ this.data.int = true;
1560
+ }
1561
+ }
1562
+ class NumberAsStringBaseColumn extends ColumnType {
1462
1563
  constructor(schema) {
1463
1564
  super(schema, schema.stringSchema());
1464
- this.dataType = "cidr";
1465
- this.operators = Operators.text;
1565
+ this.operators = Operators.number;
1566
+ this.data.jsonCast = "text";
1567
+ }
1568
+ }
1569
+ class DecimalColumn extends NumberAsStringBaseColumn {
1570
+ constructor(schema, numericPrecision, numericScale) {
1571
+ super(schema);
1572
+ this.operators = Operators.number;
1573
+ this.dataType = "numeric";
1574
+ this.data.numericPrecision = numericPrecision;
1575
+ this.data.numericScale = numericScale;
1576
+ this.data.alias = "decimal";
1466
1577
  }
1467
1578
  toCode(ctx, key) {
1468
- return columnCode(this, ctx, key, `cidr()`);
1579
+ const { numericPrecision, numericScale } = this.data;
1580
+ return columnCode(
1581
+ this,
1582
+ ctx,
1583
+ key,
1584
+ `decimal(${numericPrecision || ""}${numericScale ? `, ${numericScale}` : ""})`
1585
+ );
1586
+ }
1587
+ toSQL() {
1588
+ const { numericPrecision, numericScale } = this.data;
1589
+ return orchidCore.joinTruthy(
1590
+ this.dataType,
1591
+ numericPrecision ? numericScale ? `(${numericPrecision}, ${numericScale})` : `(${numericPrecision})` : void 0
1592
+ );
1469
1593
  }
1470
1594
  }
1471
- class InetColumn extends ColumnType {
1595
+ const skipNumberMethods = { int: true };
1596
+ const intToCode = (column, ctx, key, alias) => {
1597
+ let code;
1598
+ if (column.data.identity) {
1599
+ code = identityToCode(column.data.identity, alias);
1600
+ } else {
1601
+ code = [`${alias}()`];
1602
+ }
1603
+ orchidCore.addCode(
1604
+ code,
1605
+ orchidCore.numberDataToCode(column.data, ctx.migration, skipNumberMethods)
1606
+ );
1607
+ return columnCode(column, ctx, key, code);
1608
+ };
1609
+ class SmallIntColumn extends IntegerBaseColumn {
1472
1610
  constructor(schema) {
1473
- super(schema, schema.stringSchema());
1474
- this.dataType = "inet";
1475
- this.operators = Operators.text;
1611
+ super(schema);
1612
+ this.dataType = "int2";
1613
+ this.data.alias = "smallint";
1614
+ this.data.parseItem = parseInt;
1476
1615
  }
1477
1616
  toCode(ctx, key) {
1478
- return columnCode(this, ctx, key, `inet()`);
1617
+ return intToCode(this, ctx, key, "smallint");
1618
+ }
1619
+ identity(options = {}) {
1620
+ return orchidCore.setColumnData(this, "identity", options);
1479
1621
  }
1480
1622
  }
1481
- class MacAddrColumn extends ColumnType {
1623
+ class IntegerColumn extends IntegerBaseColumn {
1482
1624
  constructor(schema) {
1483
- super(schema, schema.stringSchema());
1484
- this.dataType = "macaddr";
1485
- this.operators = Operators.text;
1625
+ super(schema);
1626
+ this.dataType = "int4";
1627
+ this.data.alias = "integer";
1628
+ this.data.parseItem = parseInt;
1486
1629
  }
1487
1630
  toCode(ctx, key) {
1488
- return columnCode(this, ctx, key, `macaddr()`);
1631
+ return intToCode(this, ctx, key, "integer");
1632
+ }
1633
+ identity(options = {}) {
1634
+ return orchidCore.setColumnData(this, "identity", options);
1489
1635
  }
1490
1636
  }
1491
- class MacAddr8Column extends ColumnType {
1637
+ class BigIntColumn extends NumberAsStringBaseColumn {
1492
1638
  constructor(schema) {
1493
- super(schema, schema.stringSchema());
1494
- this.dataType = "macaddr8";
1495
- this.operators = Operators.text;
1639
+ super(schema);
1640
+ this.dataType = "int8";
1641
+ this.data.alias = "bigint";
1496
1642
  }
1497
1643
  toCode(ctx, key) {
1498
- return columnCode(this, ctx, key, `macaddr8()`);
1644
+ return intToCode(this, ctx, key, "bigint");
1645
+ }
1646
+ identity(options = {}) {
1647
+ return orchidCore.setColumnData(this, "identity", options);
1499
1648
  }
1500
1649
  }
1501
- class BitColumn extends ColumnType {
1502
- constructor(schema, length) {
1503
- super(schema, schema.bit(length));
1504
- this.dataType = "bit";
1505
- this.operators = Operators.text;
1506
- this.data.length = length;
1650
+ class RealColumn extends NumberBaseColumn {
1651
+ constructor(schema) {
1652
+ super(schema, schema.number());
1653
+ this.dataType = "float4";
1654
+ this.data.alias = "real";
1655
+ this.data.parseItem = parseFloat;
1507
1656
  }
1508
1657
  toCode(ctx, key) {
1509
- const { length } = this.data;
1510
- return columnCode(this, ctx, key, `bit(${length})`);
1511
- }
1512
- toSQL() {
1513
- return orchidCore.joinTruthy(
1514
- this.dataType,
1515
- this.data.length !== void 0 && `(${this.data.length})`
1658
+ return columnCode(
1659
+ this,
1660
+ ctx,
1661
+ key,
1662
+ `real()${orchidCore.numberDataToCode(this.data, ctx.migration)}`
1516
1663
  );
1517
1664
  }
1518
1665
  }
1519
- class BitVaryingColumn extends ColumnType {
1520
- constructor(schema, length) {
1521
- super(schema, schema.bit(length));
1522
- this.dataType = "varbit";
1523
- this.operators = Operators.text;
1524
- this.data.length = length;
1525
- this.data.alias = "bitVarying";
1666
+ class DoublePrecisionColumn extends NumberAsStringBaseColumn {
1667
+ constructor(schema) {
1668
+ super(schema);
1669
+ this.dataType = "float8";
1670
+ this.data.alias = "doublePrecision";
1526
1671
  }
1527
1672
  toCode(ctx, key) {
1528
- const { length } = this.data;
1529
- return columnCode(this, ctx, key, `bitVarying(${length ?? ""})`);
1673
+ return columnCode(this, ctx, key, `doublePrecision()`);
1674
+ }
1675
+ }
1676
+ class SmallSerialColumn extends IntegerBaseColumn {
1677
+ constructor(schema) {
1678
+ super(schema);
1679
+ this.dataType = "int2";
1680
+ this.data.int = true;
1681
+ this.data.alias = "smallSerial";
1682
+ this.data.parseItem = parseInt;
1530
1683
  }
1531
1684
  toSQL() {
1532
- return orchidCore.joinTruthy(
1533
- this.dataType,
1534
- this.data.length !== void 0 && `(${this.data.length})`
1685
+ return "smallserial";
1686
+ }
1687
+ toCode(ctx, key) {
1688
+ return columnCode(
1689
+ this,
1690
+ ctx,
1691
+ key,
1692
+ `smallSerial()${orchidCore.numberDataToCode(
1693
+ this.data,
1694
+ ctx.migration,
1695
+ skipNumberMethods
1696
+ )}`
1535
1697
  );
1536
1698
  }
1537
1699
  }
1538
- class TsVectorColumn extends ColumnType {
1539
- constructor(schema, defaultLanguage = orchidCore.getDefaultLanguage()) {
1540
- super(schema, schema.stringSchema());
1541
- this.defaultLanguage = defaultLanguage;
1542
- this.dataType = "tsvector";
1543
- this.operators = Operators.text;
1700
+ class SerialColumn extends IntegerBaseColumn {
1701
+ constructor(schema) {
1702
+ super(schema);
1703
+ this.dataType = "int4";
1704
+ this.data.int = true;
1705
+ this.data.alias = "serial";
1706
+ this.data.parseItem = parseInt;
1544
1707
  }
1545
- toCode(ctx, key) {
1546
- return columnCode(this, ctx, key, `tsvector()`);
1547
- }
1548
- /**
1549
- * For `tsvector` column type, it can also accept language (optional) and columns:
1550
- *
1551
- * ```ts
1552
- * import { change } from '../dbScript';
1553
- *
1554
- * change(async (db) => {
1555
- * await db.createTable('post', (t) => ({
1556
- * id: t.id(),
1557
- * title: t.text(),
1558
- * body: t.text(),
1559
- * // join title and body into a single ts_vector
1560
- * generatedTsVector: t.tsvector().generated(['title', 'body']).searchIndex(),
1561
- * // with language:
1562
- * spanishTsVector: t
1563
- * .tsvector()
1564
- * .generated('spanish', ['title', 'body'])
1565
- * .searchIndex(),
1566
- * }));
1567
- * });
1568
- * ```
1569
- *
1570
- * @param args
1571
- */
1572
- generated(...args) {
1573
- const arg = args[0];
1574
- if (typeof arg === "object" && "raw" in arg) {
1575
- return super.generated(...args);
1576
- }
1577
- const toSQL = (ctx) => {
1578
- const first = args[0];
1579
- const target = typeof first === "string" ? args[1] : first;
1580
- const language = typeof first === "string" ? first : this.defaultLanguage;
1581
- const { snakeCase } = ctx;
1582
- let sql;
1583
- if (Array.isArray(target)) {
1584
- const columns = target.length === 1 ? `"${snakeCase ? orchidCore.toSnakeCase(target[0]) : target[0]}"` : target.map(
1585
- (column2) => `coalesce("${snakeCase ? orchidCore.toSnakeCase(column2) : column2}", '')`
1586
- ).join(` || ' ' || `);
1587
- sql = `to_tsvector('${language}', ${columns})`;
1588
- } else {
1589
- for (const key in target) {
1590
- sql = (sql ? sql + " || " : "(") + `setweight(to_tsvector('${language}', coalesce("${snakeCase ? orchidCore.toSnakeCase(key) : key}", '')), '${target[key]}')`;
1591
- }
1592
- if (sql) {
1593
- sql += ")";
1594
- } else {
1595
- throw new Error("Empty target in the text search generated column");
1596
- }
1597
- }
1598
- return sql;
1599
- };
1600
- const toCode = () => {
1601
- let code = ".generated(";
1602
- const first = args[0];
1603
- let target;
1604
- if (typeof first === "string") {
1605
- code += `'${first}', `;
1606
- target = args[1];
1607
- } else {
1608
- target = args[0];
1609
- }
1610
- if (Array.isArray(target)) {
1611
- code += `[${target.map((x) => `'${x}'`).join(", ")}]`;
1612
- } else {
1613
- const pairs = [];
1614
- for (const key in target) {
1615
- pairs.push(
1616
- `${orchidCore.quoteObjectKey(key)}: '${target[key]}'`
1617
- );
1618
- }
1619
- code += `{ ${pairs.join(", ")} }`;
1620
- }
1621
- return code + ")";
1622
- };
1623
- const column = orchidCore.setColumnData(this, "generated", {
1624
- toSQL,
1625
- toCode
1626
- });
1627
- column.data.readonly = true;
1628
- return column;
1629
- }
1630
- }
1631
- class TsQueryColumn extends ColumnType {
1632
- constructor(schema) {
1633
- super(schema, schema.stringSchema());
1634
- this.dataType = "tsquery";
1635
- this.operators = Operators.text;
1708
+ toSQL() {
1709
+ return "serial";
1636
1710
  }
1637
1711
  toCode(ctx, key) {
1638
- return columnCode(this, ctx, key, `tsquery()`);
1712
+ return columnCode(
1713
+ this,
1714
+ ctx,
1715
+ key,
1716
+ `serial()${orchidCore.numberDataToCode(
1717
+ this.data,
1718
+ ctx.migration,
1719
+ skipNumberMethods
1720
+ )}`
1721
+ );
1639
1722
  }
1640
1723
  }
1641
- const uuidDefaultSQL = "gen_random_uuid()";
1642
- const uuidDefault = new RawSQL(uuidDefaultSQL);
1643
- class UUIDColumn extends ColumnType {
1724
+ class BigSerialColumn extends NumberAsStringBaseColumn {
1644
1725
  constructor(schema) {
1645
- super(schema, schema.uuid());
1646
- this.dataType = "uuid";
1647
- this.operators = Operators.text;
1648
- this.data.defaultDefault = uuidDefault;
1726
+ super(schema);
1727
+ this.dataType = "int8";
1728
+ this.data.alias = "bigint";
1649
1729
  }
1650
- /**
1651
- * see {@link ColumnType.primaryKey}
1652
- */
1653
- primaryKey(name) {
1654
- const column = super.primaryKey(name);
1655
- if (!column.data.default) column.data.default = uuidDefault;
1656
- return column;
1730
+ toSQL() {
1731
+ return "bigserial";
1657
1732
  }
1658
1733
  toCode(ctx, key) {
1659
- return columnCode(this, ctx, key, `uuid()`);
1734
+ return columnCode(this, ctx, key, `bigSerial()`);
1660
1735
  }
1661
1736
  }
1662
- class XMLColumn extends ColumnType {
1663
- constructor(schema) {
1664
- super(schema, schema.stringSchema());
1665
- this.dataType = "xml";
1737
+
1738
+ const parseDateToDate = (value) => new Date(value);
1739
+ const defaultSchemaConfig = {
1740
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1741
+ parse(fn) {
1742
+ return setColumnParse(this, fn);
1743
+ },
1744
+ parseNull(fn) {
1745
+ return setColumnParseNull(this, fn);
1746
+ },
1747
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1748
+ encode(fn) {
1749
+ return orchidCore.setColumnData(this, "encode", fn);
1750
+ },
1751
+ asType() {
1752
+ return this;
1753
+ },
1754
+ dateAsNumber() {
1755
+ return this.parse(Date.parse);
1756
+ },
1757
+ dateAsDate() {
1758
+ return this.parse(parseDateToDate);
1759
+ },
1760
+ enum(dataType, type) {
1761
+ return new EnumColumn(defaultSchemaConfig, dataType, type, void 0);
1762
+ },
1763
+ array(item) {
1764
+ return new ArrayColumn(defaultSchemaConfig, item, void 0);
1765
+ },
1766
+ boolean: orchidCore.noop,
1767
+ buffer: orchidCore.noop,
1768
+ unknown: orchidCore.noop,
1769
+ never: orchidCore.noop,
1770
+ stringSchema: orchidCore.noop,
1771
+ stringMin: orchidCore.noop,
1772
+ stringMax: orchidCore.noop,
1773
+ stringMinMax: orchidCore.noop,
1774
+ number: orchidCore.noop,
1775
+ int: orchidCore.noop,
1776
+ stringNumberDate: orchidCore.noop,
1777
+ timeInterval: orchidCore.noop,
1778
+ bit: orchidCore.noop,
1779
+ uuid: orchidCore.noop,
1780
+ nullable() {
1781
+ return orchidCore.setColumnData(this, "isNullable", true);
1782
+ },
1783
+ json() {
1784
+ return new JSONColumn(defaultSchemaConfig, void 0);
1785
+ },
1786
+ setErrors: orchidCore.noop,
1787
+ smallint: () => new SmallIntColumn(defaultSchemaConfig),
1788
+ integer: () => new IntegerColumn(defaultSchemaConfig),
1789
+ real: () => new RealColumn(defaultSchemaConfig),
1790
+ smallSerial: () => new SmallSerialColumn(defaultSchemaConfig),
1791
+ serial: () => new SerialColumn(defaultSchemaConfig),
1792
+ bigint: () => new BigIntColumn(defaultSchemaConfig),
1793
+ decimal: (precision, scale) => new DecimalColumn(defaultSchemaConfig, precision, scale),
1794
+ doublePrecision: () => new DoublePrecisionColumn(defaultSchemaConfig),
1795
+ bigSerial: () => new BigSerialColumn(defaultSchemaConfig),
1796
+ money: () => new MoneyColumn(defaultSchemaConfig),
1797
+ varchar: (limit) => new VarCharColumn(defaultSchemaConfig, limit),
1798
+ text: () => new TextColumn(defaultSchemaConfig),
1799
+ string: (limit) => new StringColumn(defaultSchemaConfig, limit),
1800
+ citext: () => new CitextColumn(defaultSchemaConfig),
1801
+ date: () => new DateColumn(defaultSchemaConfig),
1802
+ timestampNoTZ: (precision) => new TimestampColumn(defaultSchemaConfig, precision),
1803
+ timestamp: (precision) => new TimestampTZColumn(defaultSchemaConfig, precision),
1804
+ geographyPointSchema: orchidCore.noop
1805
+ };
1806
+
1807
+ class TextBaseColumn extends ColumnType {
1808
+ constructor(schema, schemaType = schema.stringSchema()) {
1809
+ super(schema, schemaType);
1666
1810
  this.operators = Operators.text;
1667
1811
  }
1668
- toCode(ctx, key) {
1669
- return columnCode(this, ctx, key, `xml()`);
1670
- }
1671
- }
1672
- class CitextColumn extends TextBaseColumn {
1673
- constructor(schema) {
1674
- super(schema, schema.stringSchema());
1675
- this.dataType = "citext";
1676
- this.data.extension = "citext";
1677
- }
1678
- toCode(ctx, key) {
1679
- return textColumnToCode(this, ctx, key);
1680
- }
1681
1812
  }
1682
-
1683
- const dateTimeEncode = (input) => {
1684
- return typeof input === "number" ? new Date(input) : input;
1685
- };
1686
- class DateBaseColumn extends ColumnType {
1687
- constructor(schema) {
1813
+ class LimitedTextBaseColumn extends TextBaseColumn {
1814
+ constructor(schema, limit) {
1688
1815
  super(
1689
1816
  schema,
1690
- schema.stringNumberDate(),
1691
- schema.stringSchema(),
1692
- schema.stringNumberDate()
1817
+ limit !== void 0 ? schema.stringMax(limit) : schema.stringSchema()
1818
+ );
1819
+ this.data.maxChars = limit;
1820
+ }
1821
+ toSQL() {
1822
+ return orchidCore.joinTruthy(
1823
+ this.dataType,
1824
+ this.data.maxChars !== void 0 && `(${this.data.maxChars})`
1693
1825
  );
1694
- this.operators = Operators.date;
1695
- this.asNumber = schema.dateAsNumber;
1696
- this.asDate = schema.dateAsDate;
1697
- this.data.encode = dateTimeEncode;
1698
1826
  }
1699
1827
  }
1700
- class DateColumn extends DateBaseColumn {
1828
+ class VarCharColumn extends LimitedTextBaseColumn {
1701
1829
  constructor() {
1702
1830
  super(...arguments);
1703
- this.dataType = "date";
1831
+ this.dataType = "varchar";
1704
1832
  }
1705
1833
  toCode(ctx, key) {
1834
+ const { maxChars } = this.data;
1706
1835
  return columnCode(
1707
1836
  this,
1708
1837
  ctx,
1709
1838
  key,
1710
- `date()${orchidCore.dateDataToCode(this.data, ctx.migration)}`
1839
+ `varchar(${maxChars ?? ""})${orchidCore.stringDataToCode(this.data, ctx.migration)}`
1711
1840
  );
1712
1841
  }
1713
1842
  }
1714
- class DateTimeBaseClass extends DateBaseColumn {
1715
- constructor(schema, dateTimePrecision) {
1716
- super(schema);
1717
- this.data.dateTimePrecision = dateTimePrecision;
1718
- }
1719
- toSQL() {
1720
- return orchidCore.joinTruthy(
1721
- this.dataType,
1722
- this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`
1723
- );
1843
+ class StringColumn extends VarCharColumn {
1844
+ constructor(schema, limit = 255) {
1845
+ super(schema, limit);
1724
1846
  }
1725
- }
1726
- class DateTimeTzBaseClass extends DateTimeBaseClass {
1727
- toSQL() {
1728
- return orchidCore.joinTruthy(
1729
- this.baseDataType,
1730
- this.data.dateTimePrecision !== void 0 && `(${this.data.dateTimePrecision})`,
1731
- " with time zone"
1732
- );
1733
- }
1734
- }
1735
- const timestampToCode = (self, ctx, key) => {
1736
- const { dateTimePrecision: p } = self.data;
1737
- const { defaultTimestamp } = self.data;
1738
- if (defaultTimestamp) {
1739
- const noTz = self instanceof TimestampColumn ? "NoTZ" : "";
1740
- const def = self.data.default;
1741
- const modifyQuery = self.data.modifyQuery;
1742
- self.data.default = void 0;
1743
- self.data.modifyQuery = void 0;
1744
- const code = columnCode(
1745
- self,
1746
- ctx,
1747
- key,
1748
- `timestamps${noTz}(${p && p !== 6 ? p : ""}).${defaultTimestamp}${orchidCore.dateDataToCode(self.data, ctx.migration)}`
1749
- );
1750
- self.data.default = def;
1751
- self.data.modifyQuery = modifyQuery;
1752
- return code;
1753
- } else {
1847
+ toCode(ctx, key) {
1848
+ let max = this.data.maxChars;
1849
+ if (max === 255) max = void 0;
1754
1850
  return columnCode(
1755
- self,
1851
+ this,
1756
1852
  ctx,
1757
1853
  key,
1758
- `${self instanceof TimestampColumn ? "timestampNoTZ" : "timestamp"}(${p && p !== 6 ? p : ""})${orchidCore.dateDataToCode(self.data, ctx.migration)}`
1854
+ `string(${max ?? ""})${orchidCore.stringDataToCode(this.data, ctx.migration)}`
1759
1855
  );
1760
1856
  }
1857
+ }
1858
+ const textColumnToCode = (column, ctx, key) => {
1859
+ const data = { ...column.data };
1860
+ let args = "";
1861
+ const hasMax = data.maxArg !== void 0 && data.max === data.maxArg;
1862
+ if (data.minArg !== void 0 && data.min === data.minArg || hasMax) {
1863
+ if (data.minArg !== 0 || hasMax && data.max !== Infinity) {
1864
+ args += data.minArg;
1865
+ }
1866
+ delete data.min;
1867
+ if (hasMax) {
1868
+ if (data.maxArg !== Infinity) {
1869
+ args += `, ${data.maxArg}`;
1870
+ }
1871
+ delete data.max;
1872
+ }
1873
+ }
1874
+ return columnCode(
1875
+ column,
1876
+ ctx,
1877
+ key,
1878
+ `${column.dataType}(${args})${orchidCore.stringDataToCode(data, ctx.migration)}`
1879
+ );
1761
1880
  };
1762
- class TimestampColumn extends DateTimeBaseClass {
1763
- constructor() {
1764
- super(...arguments);
1765
- this.dataType = "timestamp";
1881
+ class TextColumn extends TextBaseColumn {
1882
+ constructor(schema) {
1883
+ super(schema, schema.stringSchema());
1884
+ this.dataType = "text";
1885
+ }
1886
+ static get instance() {
1887
+ return this._instance ?? (this._instance = new TextColumn(defaultSchemaConfig));
1766
1888
  }
1767
1889
  toCode(ctx, key) {
1768
- return timestampToCode(this, ctx, key);
1890
+ return textColumnToCode(this, ctx, key);
1769
1891
  }
1770
1892
  }
1771
- class TimestampTZColumn extends DateTimeTzBaseClass {
1772
- constructor() {
1773
- super(...arguments);
1774
- this.dataType = "timestamptz";
1775
- this.baseDataType = "timestamp";
1893
+ const byteaParse = (val) => typeof val === "string" ? Buffer.from(val.slice(2), "hex") : val;
1894
+ class ByteaColumn extends ColumnType {
1895
+ constructor(schema) {
1896
+ super(schema, schema.buffer());
1897
+ this.dataType = "bytea";
1898
+ this.operators = Operators.text;
1899
+ setColumnDefaultParse(this, byteaParse);
1776
1900
  }
1777
1901
  toCode(ctx, key) {
1778
- return timestampToCode(this, ctx, key);
1902
+ return columnCode(this, ctx, key, `bytea()`);
1779
1903
  }
1780
1904
  }
1781
- class TimeColumn extends ColumnType {
1782
- constructor(schema, dateTimePrecision) {
1905
+ class PointColumn extends ColumnType {
1906
+ constructor(schema) {
1783
1907
  super(schema, schema.stringSchema());
1784
- this.dataType = "time";
1785
- this.operators = Operators.time;
1786
- this.data.dateTimePrecision = dateTimePrecision;
1908
+ this.dataType = "point";
1909
+ this.operators = Operators.text;
1787
1910
  }
1788
1911
  toCode(ctx, key) {
1789
- const { dateTimePrecision } = this.data;
1790
- return columnCode(
1791
- this,
1792
- ctx,
1793
- key,
1794
- `time(${dateTimePrecision || ""})${orchidCore.dateDataToCode(
1795
- this.data,
1796
- ctx.migration
1797
- )}`
1798
- );
1912
+ return columnCode(this, ctx, key, `point()`);
1799
1913
  }
1800
1914
  }
1801
- class IntervalColumn extends ColumnType {
1802
- constructor(schema, fields, precision) {
1803
- super(schema, schema.timeInterval());
1804
- this.dataType = "interval";
1805
- this.operators = Operators.date;
1806
- this.data.fields = fields;
1807
- this.data.precision = precision;
1915
+ class LineColumn extends ColumnType {
1916
+ constructor(schema) {
1917
+ super(schema, schema.stringSchema());
1918
+ this.dataType = "line";
1919
+ this.operators = Operators.text;
1808
1920
  }
1809
1921
  toCode(ctx, key) {
1810
- const { fields, precision } = this.data;
1811
- return columnCode(
1812
- this,
1813
- ctx,
1814
- key,
1815
- `interval(${[fields && `'${fields}'`, precision && String(precision)].filter((part) => part).join(", ")})`
1816
- );
1817
- }
1818
- toSQL() {
1819
- return orchidCore.joinTruthy(
1820
- this.dataType,
1821
- this.data.fields && ` ${this.data.fields}`,
1822
- this.data.precision !== void 0 && ` (${this.data.precision})`
1823
- );
1922
+ return columnCode(this, ctx, key, `line()`);
1824
1923
  }
1825
1924
  }
1826
-
1827
- class BooleanColumn extends ColumnType {
1925
+ class LsegColumn extends ColumnType {
1828
1926
  constructor(schema) {
1829
- super(schema, schema.boolean());
1830
- this.dataType = "bool";
1831
- this.operators = Operators.boolean;
1832
- this.data.alias = "boolean";
1833
- this.data.parseItem = parseItem;
1927
+ super(schema, schema.stringSchema());
1928
+ this.dataType = "lseg";
1929
+ this.operators = Operators.text;
1834
1930
  }
1835
1931
  toCode(ctx, key) {
1836
- return columnCode(this, ctx, key, "boolean()");
1932
+ return columnCode(this, ctx, key, `lseg()`);
1837
1933
  }
1838
1934
  }
1839
- const parseItem = (input) => input[0] === "t";
1840
-
1841
- const encode$1 = (x) => x === null ? x : JSON.stringify(x);
1842
- class JSONColumn extends ColumnType {
1843
- constructor(schema, inputType) {
1844
- super(schema, inputType);
1845
- this.dataType = "jsonb";
1846
- this.operators = Operators.json;
1847
- this.data.encode = encode$1;
1848
- this.data.parseItem = JSON.parse;
1935
+ class BoxColumn extends ColumnType {
1936
+ constructor(schema) {
1937
+ super(schema, schema.stringSchema());
1938
+ this.dataType = "box";
1939
+ this.operators = Operators.text;
1849
1940
  }
1850
1941
  toCode(ctx, key) {
1851
- return columnCode(this, ctx, key, `json()`);
1942
+ return columnCode(this, ctx, key, `box()`);
1852
1943
  }
1853
1944
  }
1854
- class JSONTextColumn extends ColumnType {
1945
+ class PathColumn extends ColumnType {
1855
1946
  constructor(schema) {
1856
1947
  super(schema, schema.stringSchema());
1857
- this.dataType = "json";
1948
+ this.dataType = "path";
1858
1949
  this.operators = Operators.text;
1859
1950
  }
1860
1951
  toCode(ctx, key) {
1861
- return columnCode(this, ctx, key, `jsonText()`);
1952
+ return columnCode(this, ctx, key, `path()`);
1862
1953
  }
1863
1954
  }
1864
-
1865
- var __typeError = (msg) => {
1866
- throw TypeError(msg);
1867
- };
1868
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
1869
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1870
- var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1871
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
1872
- var _query, _query2;
1873
- class OrchidOrmError extends Error {
1874
- }
1875
- class NotFoundError extends OrchidOrmError {
1876
- constructor(query, message = "Record is not found") {
1877
- super(message);
1878
- // `#query` is private to prevent it from serializing to not cause problems to test runner reports
1879
- __privateAdd(this, _query);
1880
- __privateSet(this, _query, query);
1955
+ class PolygonColumn extends ColumnType {
1956
+ constructor(schema) {
1957
+ super(schema, schema.stringSchema());
1958
+ this.dataType = "polygon";
1959
+ this.operators = Operators.text;
1881
1960
  }
1882
- get query() {
1883
- return __privateGet(this, _query);
1961
+ toCode(ctx, key) {
1962
+ return columnCode(this, ctx, key, `polygon()`);
1884
1963
  }
1885
1964
  }
1886
- _query = new WeakMap();
1887
- class OrchidOrmInternalError extends Error {
1888
- constructor(query, message) {
1889
- super(message);
1890
- // `#query` is private to prevent it from serializing to not cause problems to test runner reports
1891
- __privateAdd(this, _query2);
1892
- __privateSet(this, _query2, query);
1965
+ class CircleColumn extends ColumnType {
1966
+ constructor(schema) {
1967
+ super(schema, schema.stringSchema());
1968
+ this.dataType = "circle";
1969
+ this.operators = Operators.text;
1893
1970
  }
1894
- get query() {
1895
- return __privateGet(this, _query2);
1971
+ toCode(ctx, key) {
1972
+ return columnCode(this, ctx, key, `circle()`);
1896
1973
  }
1897
1974
  }
1898
- _query2 = new WeakMap();
1899
- class QueryError extends OrchidOrmInternalError {
1900
- get isUnique() {
1901
- return this.code === "23505";
1975
+ class MoneyColumn extends ColumnType {
1976
+ constructor(schema) {
1977
+ super(schema, schema.number());
1978
+ this.dataType = "money";
1979
+ this.operators = Operators.number;
1980
+ setColumnDefaultParse(this, moneyParse);
1902
1981
  }
1903
- get columns() {
1904
- if (this.columnsCache) return this.columnsCache;
1905
- const columns = {};
1906
- if (this.detail) {
1907
- const list = this.detail.match(/\((.*)\)=/)?.[1];
1908
- if (list) {
1909
- list.split(", ").forEach((item) => {
1910
- const column = item.startsWith('"') ? item.slice(1, -1) : item;
1911
- const key = this.query.columnNameToKey(column) ?? column;
1912
- columns[key] = true;
1913
- });
1914
- }
1915
- }
1916
- return this.columnsCache = columns;
1982
+ toCode(ctx, key) {
1983
+ return columnCode(this, ctx, key, `money()`);
1917
1984
  }
1918
1985
  }
1919
- class MoreThanOneRowError extends OrchidOrmInternalError {
1920
- constructor(query, message) {
1921
- super(query, message);
1986
+ const moneyParse = Object.assign(
1987
+ function(input) {
1988
+ return input === null ? input : parseFloat(input.replace(/,/g, "").replace(/\$/g, ""));
1989
+ },
1990
+ {
1991
+ hideFromCode: true
1922
1992
  }
1923
- }
1924
- class UnhandledTypeError extends OrchidOrmInternalError {
1925
- constructor(query, value) {
1926
- super(query, `Unhandled type: ${JSON.stringify(value)} received`);
1993
+ );
1994
+ class CidrColumn extends ColumnType {
1995
+ constructor(schema) {
1996
+ super(schema, schema.stringSchema());
1997
+ this.dataType = "cidr";
1998
+ this.operators = Operators.text;
1999
+ }
2000
+ toCode(ctx, key) {
2001
+ return columnCode(this, ctx, key, `cidr()`);
1927
2002
  }
1928
2003
  }
1929
-
1930
- const _clone = (q) => q.clone();
1931
- const pushQueryArrayImmutable = (q, key, value) => {
1932
- const arr = q.q[key];
1933
- q.q[key] = arr ? [...arr, ...value] : value;
1934
- return q;
1935
- };
1936
- const pushQueryValueImmutable = (q, key, value) => {
1937
- orchidCore.pushOrNewArrayToObjectImmutable(q.q, key, value);
1938
- return q;
1939
- };
1940
- const setQueryObjectValueImmutable = (q, object, key, value) => {
1941
- q.q[object] = {
1942
- ...q.q[object],
1943
- [key]: value
1944
- };
1945
- return q;
1946
- };
1947
- const throwIfNoWhere = (q, method) => {
1948
- if (!q.q.or && !q.q.and && !q.q.scopes && !q.q.all) {
1949
- throw new OrchidOrmInternalError(
1950
- q,
1951
- `Dangerous ${method} without conditions`
1952
- );
1953
- }
1954
- };
1955
- const throwIfJoinLateral = (q, method) => {
1956
- if (q.q.join?.some(
1957
- (x) => Array.isArray(x) || "s" in x.args && x.args.s
1958
- )) {
1959
- throw new OrchidOrmInternalError(
1960
- q,
1961
- `Cannot join a complex query in ${method}`
1962
- );
2004
+ class InetColumn extends ColumnType {
2005
+ constructor(schema) {
2006
+ super(schema, schema.stringSchema());
2007
+ this.dataType = "inet";
2008
+ this.operators = Operators.text;
1963
2009
  }
1964
- };
1965
- const saveSearchAlias = (q, as, key) => {
1966
- const shapes = q.q[key];
1967
- if (shapes?.[as]) {
1968
- let suffix = 2;
1969
- while (shapes[as = `${as}${suffix}`]) {
1970
- suffix++;
1971
- }
2010
+ toCode(ctx, key) {
2011
+ return columnCode(this, ctx, key, `inet()`);
1972
2012
  }
1973
- setQueryObjectValueImmutable(q, key, as, orchidCore.emptyObject);
1974
- return as;
1975
- };
1976
- const extendQuery = (q, methods) => {
1977
- const base = Object.create(q.baseQuery);
1978
- base.baseQuery = base;
1979
- Object.assign(base, methods);
1980
- const cloned = Object.create(base);
1981
- cloned.q = getClonedQueryData(q.q);
1982
- return cloned;
1983
- };
1984
- const getPrimaryKeys = (q) => {
1985
- var _a;
1986
- return (_a = q.internal).primaryKeys ?? (_a.primaryKeys = collectPrimaryKeys(q));
1987
- };
1988
- const collectPrimaryKeys = (q) => {
1989
- const primaryKeys = [];
1990
- const { shape } = q.q;
1991
- for (const key in shape) {
1992
- if (shape[key].data.primaryKey) {
1993
- primaryKeys.push(key);
1994
- }
2013
+ }
2014
+ class MacAddrColumn extends ColumnType {
2015
+ constructor(schema) {
2016
+ super(schema, schema.stringSchema());
2017
+ this.dataType = "macaddr";
2018
+ this.operators = Operators.text;
1995
2019
  }
1996
- const pkey = q.internal.tableData.primaryKey;
1997
- if (pkey) {
1998
- primaryKeys.push(...pkey.columns);
2020
+ toCode(ctx, key) {
2021
+ return columnCode(this, ctx, key, `macaddr()`);
1999
2022
  }
2000
- return primaryKeys;
2001
- };
2002
- const _queryAll = (q) => {
2003
- q.q.returnType = "all";
2004
- q.q.all = true;
2005
- return q;
2006
- };
2007
- const _queryTake = (query) => {
2008
- const q = query.q;
2009
- switch (q.returnType) {
2010
- case "valueOrThrow":
2011
- case "pluck":
2012
- case "void":
2013
- break;
2014
- case "value": {
2015
- q.returnType = "valueOrThrow";
2016
- break;
2017
- }
2018
- default: {
2019
- q.returnType = "oneOrThrow";
2020
- }
2023
+ }
2024
+ class MacAddr8Column extends ColumnType {
2025
+ constructor(schema) {
2026
+ super(schema, schema.stringSchema());
2027
+ this.dataType = "macaddr8";
2028
+ this.operators = Operators.text;
2021
2029
  }
2022
- return query;
2023
- };
2024
- const _queryTakeOptional = (query) => {
2025
- const q = query.q;
2026
- switch (q.returnType) {
2027
- case "value":
2028
- case "pluck":
2029
- case "void":
2030
- break;
2031
- case "valueOrThrow": {
2032
- q.returnType = "value";
2033
- break;
2034
- }
2035
- default: {
2036
- q.returnType = "one";
2037
- }
2030
+ toCode(ctx, key) {
2031
+ return columnCode(this, ctx, key, `macaddr8()`);
2038
2032
  }
2039
- return query;
2040
- };
2041
- const _queryExec = (q) => {
2042
- q.q.returnType = "void";
2043
- return q;
2044
- };
2045
- const _queryRows = (q) => {
2046
- q.q.returnType = "rows";
2047
- return q;
2048
- };
2049
- const getFullColumnTable = (q, column, index, as) => {
2050
- const table = column.slice(0, index);
2051
- return as && table !== as && q.q.aliases?.[table] === as ? as : table;
2052
- };
2053
-
2054
- function simpleColumnToSQL(ctx, key, column, quotedAs) {
2055
- if (!column) return `"${key}"`;
2056
- const { data } = column;
2057
- return data.computed ? data.computed.toSQL(ctx, quotedAs) : `${quotedAs ? `${quotedAs}.` : ""}"${data.name || key}"`;
2058
- }
2059
- function simpleExistingColumnToSQL(ctx, key, column, quotedAs) {
2060
- const { data } = column;
2061
- return data.computed ? data.computed.toSQL(ctx, quotedAs) : `${quotedAs ? `${quotedAs}.` : ""}"${data.name || key}"`;
2062
2033
  }
2063
- const columnToSql = (ctx, data, shape, column, quotedAs, select) => {
2064
- const index = column.indexOf(".");
2065
- if (index !== -1) {
2066
- return columnWithDotToSql(
2067
- ctx,
2068
- data,
2069
- shape,
2070
- column,
2071
- index,
2072
- quotedAs,
2073
- select
2034
+ class BitColumn extends ColumnType {
2035
+ constructor(schema, length) {
2036
+ super(schema, schema.bit(length));
2037
+ this.dataType = "bit";
2038
+ this.operators = Operators.text;
2039
+ this.data.length = length;
2040
+ }
2041
+ toCode(ctx, key) {
2042
+ const { length } = this.data;
2043
+ return columnCode(this, ctx, key, `bit(${length})`);
2044
+ }
2045
+ toSQL() {
2046
+ return orchidCore.joinTruthy(
2047
+ this.dataType,
2048
+ this.data.length !== void 0 && `(${this.data.length})`
2074
2049
  );
2075
2050
  }
2076
- if (!select && data.joinedShapes?.[column]) {
2077
- return `"${column}".r`;
2051
+ }
2052
+ class BitVaryingColumn extends ColumnType {
2053
+ constructor(schema, length) {
2054
+ super(schema, schema.bit(length));
2055
+ this.dataType = "varbit";
2056
+ this.operators = Operators.text;
2057
+ this.data.length = length;
2058
+ this.data.alias = "bitVarying";
2078
2059
  }
2079
- return simpleColumnToSQL(ctx, column, shape[column], quotedAs);
2080
- };
2081
- const maybeSelectedColumnToSql = (ctx, data, column, quotedAs) => {
2082
- const index = column.indexOf(".");
2083
- if (index !== -1) {
2084
- return columnWithDotToSql(ctx, data, data.shape, column, index, quotedAs);
2085
- } else {
2086
- if (data.joinedShapes?.[column]) {
2087
- return `"${column}".r`;
2088
- }
2089
- if (data.select) {
2090
- for (const s of data.select) {
2091
- if (typeof s === "object" && "selectAs" in s) {
2092
- if (column in s.selectAs) {
2093
- return simpleColumnToSQL(ctx, column, data.shape[column]);
2094
- }
2095
- }
2096
- }
2097
- }
2098
- return simpleColumnToSQL(ctx, column, data.shape[column], quotedAs);
2060
+ toCode(ctx, key) {
2061
+ const { length } = this.data;
2062
+ return columnCode(this, ctx, key, `bitVarying(${length ?? ""})`);
2099
2063
  }
2100
- };
2101
- const columnWithDotToSql = (ctx, data, shape, column, index, quotedAs, select) => {
2102
- const table = column.slice(0, index);
2103
- const key = column.slice(index + 1);
2104
- if (key === "*") {
2105
- const shape2 = data.joinedShapes?.[table];
2106
- return shape2 ? select ? makeRowToJson(table, shape2, true) : `"${table}".*` : column;
2064
+ toSQL() {
2065
+ return orchidCore.joinTruthy(
2066
+ this.dataType,
2067
+ this.data.length !== void 0 && `(${this.data.length})`
2068
+ );
2107
2069
  }
2108
- const tableName = data.aliases?.[table] || table;
2109
- const quoted = `"${table}"`;
2110
- const col = quoted === quotedAs ? shape[key] : data.joinedShapes?.[tableName]?.[key];
2111
- if (col) {
2112
- if (col.data.name) {
2113
- return `"${tableName}"."${col.data.name}"`;
2114
- }
2115
- if (col.data.computed) {
2116
- return col.data.computed.toSQL(ctx, quoted);
2117
- }
2118
- return `"${tableName}"."${key}"`;
2070
+ }
2071
+ class TsVectorColumn extends ColumnType {
2072
+ constructor(schema, defaultLanguage = orchidCore.getDefaultLanguage()) {
2073
+ super(schema, schema.stringSchema());
2074
+ this.defaultLanguage = defaultLanguage;
2075
+ this.dataType = "tsvector";
2076
+ this.operators = Operators.text;
2119
2077
  }
2120
- return `"${tableName}"."${key}"`;
2121
- };
2122
- const columnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList) => {
2123
- const index = column.indexOf(".");
2124
- return index !== -1 ? tableColumnToSqlWithAs(
2125
- ctx,
2126
- data,
2127
- column,
2128
- column.slice(0, index),
2129
- column.slice(index + 1),
2130
- as,
2131
- quotedAs,
2132
- select,
2133
- jsonList
2134
- ) : ownColumnToSqlWithAs(ctx, data, column, as, quotedAs, select, jsonList);
2135
- };
2136
- const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, select, jsonList) => {
2137
- if (key === "*") {
2138
- if (jsonList) jsonList[as] = void 0;
2139
- const shape = data.joinedShapes?.[table];
2140
- if (shape) {
2141
- {
2142
- return makeRowToJson(table, shape, true) + ` "${as}"`;
2143
- }
2078
+ toCode(ctx, key) {
2079
+ return columnCode(this, ctx, key, `tsvector()`);
2080
+ }
2081
+ /**
2082
+ * For `tsvector` column type, it can also accept language (optional) and columns:
2083
+ *
2084
+ * ```ts
2085
+ * import { change } from '../dbScript';
2086
+ *
2087
+ * change(async (db) => {
2088
+ * await db.createTable('post', (t) => ({
2089
+ * id: t.id(),
2090
+ * title: t.text(),
2091
+ * body: t.text(),
2092
+ * // join title and body into a single ts_vector
2093
+ * generatedTsVector: t.tsvector().generated(['title', 'body']).searchIndex(),
2094
+ * // with language:
2095
+ * spanishTsVector: t
2096
+ * .tsvector()
2097
+ * .generated('spanish', ['title', 'body'])
2098
+ * .searchIndex(),
2099
+ * }));
2100
+ * });
2101
+ * ```
2102
+ *
2103
+ * @param args
2104
+ */
2105
+ generated(...args) {
2106
+ const arg = args[0];
2107
+ if (typeof arg === "object" && "raw" in arg) {
2108
+ return super.generated(...args);
2144
2109
  }
2110
+ const toSQL = (ctx) => {
2111
+ const first = args[0];
2112
+ const target = typeof first === "string" ? args[1] : first;
2113
+ const language = typeof first === "string" ? first : this.defaultLanguage;
2114
+ const { snakeCase } = ctx;
2115
+ let sql;
2116
+ if (Array.isArray(target)) {
2117
+ const columns = target.length === 1 ? `"${snakeCase ? orchidCore.toSnakeCase(target[0]) : target[0]}"` : target.map(
2118
+ (column2) => `coalesce("${snakeCase ? orchidCore.toSnakeCase(column2) : column2}", '')`
2119
+ ).join(` || ' ' || `);
2120
+ sql = `to_tsvector('${language}', ${columns})`;
2121
+ } else {
2122
+ for (const key in target) {
2123
+ sql = (sql ? sql + " || " : "(") + `setweight(to_tsvector('${language}', coalesce("${snakeCase ? orchidCore.toSnakeCase(key) : key}", '')), '${target[key]}')`;
2124
+ }
2125
+ if (sql) {
2126
+ sql += ")";
2127
+ } else {
2128
+ throw new Error("Empty target in the text search generated column");
2129
+ }
2130
+ }
2131
+ return sql;
2132
+ };
2133
+ const toCode = () => {
2134
+ let code = ".generated(";
2135
+ const first = args[0];
2136
+ let target;
2137
+ if (typeof first === "string") {
2138
+ code += `'${first}', `;
2139
+ target = args[1];
2140
+ } else {
2141
+ target = args[0];
2142
+ }
2143
+ if (Array.isArray(target)) {
2144
+ code += `[${target.map((x) => `'${x}'`).join(", ")}]`;
2145
+ } else {
2146
+ const pairs = [];
2147
+ for (const key in target) {
2148
+ pairs.push(
2149
+ `${orchidCore.quoteObjectKey(key)}: '${target[key]}'`
2150
+ );
2151
+ }
2152
+ code += `{ ${pairs.join(", ")} }`;
2153
+ }
2154
+ return code + ")";
2155
+ };
2156
+ const column = orchidCore.setColumnData(this, "generated", {
2157
+ toSQL,
2158
+ toCode
2159
+ });
2160
+ column.data.readonly = true;
2145
2161
  return column;
2146
2162
  }
2147
- const tableName = data.aliases?.[table] || table;
2148
- const quoted = `"${table}"`;
2149
- const col = quoted === quotedAs ? data.shape[key] : data.joinedShapes?.[tableName][key];
2150
- if (jsonList) jsonList[as] = col;
2151
- if (col) {
2152
- if (col.data.name && col.data.name !== key) {
2153
- return `"${tableName}"."${col.data.name}" "${as}"`;
2154
- }
2155
- if (col.data.computed) {
2156
- return `${col.data.computed.toSQL(ctx, quoted)} "${as}"`;
2157
- }
2163
+ }
2164
+ class TsQueryColumn extends ColumnType {
2165
+ constructor(schema) {
2166
+ super(schema, schema.stringSchema());
2167
+ this.dataType = "tsquery";
2168
+ this.operators = Operators.text;
2158
2169
  }
2159
- return `"${tableName}"."${key}"${key === as ? "" : ` "${as}"`}`;
2160
- };
2161
- const ownColumnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList) => {
2162
- const col = data.shape[column];
2163
- if (jsonList) jsonList[as] = col;
2164
- if (col) {
2165
- if (col.data.name && col.data.name !== column) {
2166
- return `${quotedAs ? `${quotedAs}.` : ""}"${col.data.name}"${col.data.name === as ? "" : ` "${as}"`}`;
2167
- }
2168
- if (col.data.computed) {
2169
- return `${col.data.computed.toSQL(ctx, quotedAs)} "${as}"`;
2170
- }
2170
+ toCode(ctx, key) {
2171
+ return columnCode(this, ctx, key, `tsquery()`);
2171
2172
  }
2172
- return `${quotedAs ? `${quotedAs}.` : ""}"${column}"${column === as ? "" : ` "${as}"`}`;
2173
- };
2174
- const rawOrColumnToSql = (ctx, data, expr, quotedAs, shape = data.shape, select) => {
2175
- return typeof expr === "string" ? columnToSql(ctx, data, shape, expr, quotedAs, select) : expr.toSQL(ctx, quotedAs);
2176
- };
2177
- const quoteSchemaAndTable = (schema, table) => {
2178
- return schema ? `"${schema}"."${table}"` : `"${table}"`;
2179
- };
2180
- const makeRowToJson = (table, shape, aliasName) => {
2181
- let isSimple = true;
2182
- const list = [];
2183
- for (const key in shape) {
2184
- const column = shape[key];
2185
- if (column.data.explicitSelect) {
2186
- continue;
2187
- }
2188
- if (aliasName && column.data.name || column.data.jsonCast) {
2189
- isSimple = false;
2190
- }
2191
- list.push(
2192
- `'${key}', "${table}"."${aliasName && column.data.name || key}"${column.data.jsonCast ? `::${column.data.jsonCast}` : ""}`
2193
- );
2173
+ }
2174
+ const uuidDefaultSQL = "gen_random_uuid()";
2175
+ const uuidDefault = new RawSQL(uuidDefaultSQL);
2176
+ class UUIDColumn extends ColumnType {
2177
+ constructor(schema) {
2178
+ super(schema, schema.uuid());
2179
+ this.dataType = "uuid";
2180
+ this.operators = Operators.text;
2181
+ this.data.defaultDefault = uuidDefault;
2194
2182
  }
2195
- return isSimple ? `row_to_json("${table}".*)` : `CASE WHEN "${table}".* IS NULL THEN NULL ELSE json_build_object(` + list.join(", ") + ") END";
2196
- };
2197
-
2198
- const queryTypeWithLimitOne = {
2199
- one: true,
2200
- oneOrThrow: true,
2201
- value: true,
2202
- valueOrThrow: true
2203
- };
2204
- const isQueryReturnsAll = (q) => !q.q.returnType || q.q.returnType === "all";
2205
-
2206
- const pushDistinctSql = (ctx, table, distinct, quotedAs) => {
2207
- ctx.sql.push("DISTINCT");
2208
- if (distinct.length) {
2209
- const columns = distinct?.map(
2210
- (item) => rawOrColumnToSql(ctx, table.q, item, quotedAs)
2211
- );
2212
- ctx.sql.push(`ON (${columns?.join(", ") || ""})`);
2183
+ /**
2184
+ * see {@link ColumnType.primaryKey}
2185
+ */
2186
+ primaryKey(name) {
2187
+ const column = super.primaryKey(name);
2188
+ if (!column.data.default) column.data.default = uuidDefault;
2189
+ return column;
2213
2190
  }
2214
- };
2191
+ toCode(ctx, key) {
2192
+ return columnCode(this, ctx, key, `uuid()`);
2193
+ }
2194
+ }
2195
+ class XMLColumn extends ColumnType {
2196
+ constructor(schema) {
2197
+ super(schema, schema.stringSchema());
2198
+ this.dataType = "xml";
2199
+ this.operators = Operators.text;
2200
+ }
2201
+ static get instance() {
2202
+ return this._instance ?? (this._instance = new XMLColumn(defaultSchemaConfig));
2203
+ }
2204
+ toCode(ctx, key) {
2205
+ return columnCode(this, ctx, key, `xml()`);
2206
+ }
2207
+ }
2208
+ class CitextColumn extends TextBaseColumn {
2209
+ constructor(schema) {
2210
+ super(schema, schema.stringSchema());
2211
+ this.dataType = "citext";
2212
+ this.data.extension = "citext";
2213
+ }
2214
+ toCode(ctx, key) {
2215
+ return textColumnToCode(this, ctx, key);
2216
+ }
2217
+ }
2215
2218
 
2216
- const noneResult = (q, queryData, type) => {
2217
- if (!type || type === "all" || type === "rows" || type === "pluck") {
2218
- return [];
2219
- } else if (type === "one" || type === "value" || type === "void") {
2220
- return queryData.notFoundDefault;
2221
- } else if (type === "valueOrThrow" && queryData.returning) {
2222
- return 0;
2223
- } else {
2224
- throw new NotFoundError(q);
2219
+ class BooleanColumn extends ColumnType {
2220
+ constructor(schema) {
2221
+ super(schema, schema.boolean());
2222
+ this.dataType = "bool";
2223
+ this.operators = Operators.boolean;
2224
+ this.data.alias = "boolean";
2225
+ this.data.parseItem = parseItem;
2226
+ }
2227
+ static get instance() {
2228
+ return this._instance ?? (this._instance = new BooleanColumn(defaultSchemaConfig));
2229
+ }
2230
+ toCode(ctx, key) {
2231
+ return columnCode(this, ctx, key, "boolean()");
2225
2232
  }
2233
+ }
2234
+ const parseItem = (input) => input[0] === "t";
2235
+
2236
+ var __typeError = (msg) => {
2237
+ throw TypeError(msg);
2226
2238
  };
2227
- const noneMethods = {
2228
- // `then` resolves or rejects based on a return type of the query.
2229
- // It is `async` so it returns a chainable Promise.
2230
- async then(resolve, reject) {
2231
- try {
2232
- const result = noneResult(this, this.q, this.q.returnType);
2233
- resolve?.(result);
2234
- } catch (err) {
2235
- reject?.(err);
2239
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
2240
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
2241
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
2242
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
2243
+ var _query, _query2;
2244
+ class OrchidOrmError extends Error {
2245
+ }
2246
+ class NotFoundError extends OrchidOrmError {
2247
+ constructor(query, message = "Record is not found") {
2248
+ super(message);
2249
+ // `#query` is private to prevent it from serializing to not cause problems to test runner reports
2250
+ __privateAdd(this, _query);
2251
+ __privateSet(this, _query, query);
2252
+ }
2253
+ get query() {
2254
+ return __privateGet(this, _query);
2255
+ }
2256
+ }
2257
+ _query = new WeakMap();
2258
+ class OrchidOrmInternalError extends Error {
2259
+ constructor(query, message) {
2260
+ super(message);
2261
+ // `#query` is private to prevent it from serializing to not cause problems to test runner reports
2262
+ __privateAdd(this, _query2);
2263
+ __privateSet(this, _query2, query);
2264
+ }
2265
+ get query() {
2266
+ return __privateGet(this, _query2);
2267
+ }
2268
+ }
2269
+ _query2 = new WeakMap();
2270
+ class QueryError extends OrchidOrmInternalError {
2271
+ get isUnique() {
2272
+ return this.code === "23505";
2273
+ }
2274
+ get columns() {
2275
+ if (this.columnsCache) return this.columnsCache;
2276
+ const columns = {};
2277
+ if (this.detail) {
2278
+ const list = this.detail.match(/\((.*)\)=/)?.[1];
2279
+ if (list) {
2280
+ list.split(", ").forEach((item) => {
2281
+ const column = item.startsWith('"') ? item.slice(1, -1) : item;
2282
+ const key = this.query.columnNameToKey(column) ?? column;
2283
+ columns[key] = true;
2284
+ });
2285
+ }
2236
2286
  }
2237
- },
2238
- // `catch` returns a Promise, so it is chainable with then/catch.
2239
- catch: () => new Promise(orchidCore.noop)
2287
+ return this.columnsCache = columns;
2288
+ }
2289
+ }
2290
+ class MoreThanOneRowError extends OrchidOrmInternalError {
2291
+ constructor(query, message) {
2292
+ super(query, message);
2293
+ }
2294
+ }
2295
+ class UnhandledTypeError extends OrchidOrmInternalError {
2296
+ constructor(query, value) {
2297
+ super(query, `Unhandled type: ${JSON.stringify(value)} received`);
2298
+ }
2299
+ }
2300
+
2301
+ const _clone = (q) => q.clone();
2302
+ const pushQueryArrayImmutable = (q, key, value) => {
2303
+ const arr = q.q[key];
2304
+ q.q[key] = arr ? [...arr, ...value] : value;
2305
+ return q;
2240
2306
  };
2241
- const _queryNone = (q) => {
2242
- if (isQueryNone(q)) return q;
2243
- q = extendQuery(q, noneMethods);
2244
- pushQueryValueImmutable(q, "and", new RawSQL("false"));
2245
- pushQueryValueImmutable(
2246
- q,
2247
- "transform",
2248
- (_, queryData) => noneResult(q, queryData, queryData.returnType)
2249
- );
2307
+ const pushQueryValueImmutable = (q, key, value) => {
2308
+ orchidCore.pushOrNewArrayToObjectImmutable(q.q, key, value);
2250
2309
  return q;
2251
2310
  };
2252
- const isQueryNone = (q) => q.then === noneMethods.then;
2253
-
2254
- const _join = (query, require, type, first, args) => {
2255
- let joinKey;
2256
- let shape;
2257
- let parsers;
2258
- let batchParsers;
2259
- let computeds;
2260
- let joinSubQuery = false;
2261
- first = preprocessJoinArg(query, first);
2262
- if (typeof first === "object") {
2263
- let isInternalJoin;
2264
- if ("_internalJoin" in first) {
2265
- isInternalJoin = true;
2266
- first = first._internalJoin;
2267
- }
2268
- if (require && isQueryNone(first)) {
2269
- return _queryNone(query);
2270
- }
2271
- const q = first;
2272
- if (!isInternalJoin) {
2273
- joinSubQuery = getIsJoinSubQuery(q);
2274
- }
2275
- joinKey = q.q.as || q.table;
2276
- if (joinKey) {
2277
- shape = getShapeFromSelect(q, joinSubQuery && !!q.q.select);
2278
- parsers = q.q.parsers;
2279
- batchParsers = q.q.batchParsers;
2280
- computeds = q.q.computeds;
2281
- if (joinSubQuery) {
2282
- first = q.clone();
2283
- first.shape = shape;
2284
- }
2285
- }
2286
- } else {
2287
- joinKey = first;
2288
- const relation = query.relations[joinKey];
2289
- if (relation) {
2290
- shape = getShapeFromSelect(relation.relationConfig.query);
2291
- const r = relation.relationConfig.query;
2292
- parsers = r.q.parsers;
2293
- batchParsers = r.q.batchParsers;
2294
- computeds = r.q.computeds;
2295
- } else {
2296
- const w = query.q.withShapes?.[joinKey];
2297
- shape = w?.shape;
2298
- computeds = w?.computeds;
2299
- if (shape) {
2300
- if (!require) shape = { ...shape };
2301
- const arg = { parsers: {} };
2302
- for (const key in shape) {
2303
- addColumnParserToQuery(arg, key, shape[key]);
2304
- }
2305
- }
2306
- }
2307
- }
2308
- const joinArgs = processJoinArgs(
2309
- query,
2310
- first,
2311
- args,
2312
- joinSubQuery
2313
- );
2314
- if (require && "r" in joinArgs && isQueryNone(joinArgs.r)) {
2315
- return _queryNone(query);
2316
- } else if (joinKey && "s" in joinArgs && joinArgs.s) {
2317
- const j = "j" in joinArgs ? joinArgs.r ?? joinArgs.j : "r" in joinArgs ? joinArgs.r : joinArgs.q;
2318
- const jq = j.q;
2319
- if (jq.select || !jq.selectAllColumns) {
2320
- const { q } = query;
2321
- const shape2 = getShapeFromSelect(j, true);
2322
- orchidCore.setObjectValueImmutable(q, "joinedShapes", joinKey, shape2);
2323
- orchidCore.setObjectValueImmutable(q, "joinedParsers", joinKey, jq.parsers);
2324
- if (jq.batchParsers) {
2325
- orchidCore.setObjectValueImmutable(
2326
- jq,
2327
- "joinedBatchParsers",
2328
- joinKey,
2329
- jq.batchParsers
2330
- );
2331
- }
2332
- orchidCore.setObjectValueImmutable(q, "joinedComputeds", joinKey, jq.computeds);
2333
- } else {
2334
- addAllShapesAndParsers(
2335
- query,
2336
- joinKey,
2337
- shape,
2338
- parsers,
2339
- batchParsers,
2340
- computeds
2341
- );
2342
- }
2343
- } else {
2344
- addAllShapesAndParsers(
2345
- query,
2346
- joinKey,
2347
- shape,
2348
- parsers,
2349
- batchParsers,
2350
- computeds
2311
+ const setQueryObjectValueImmutable = (q, object, key, value) => {
2312
+ q.q[object] = {
2313
+ ...q.q[object],
2314
+ [key]: value
2315
+ };
2316
+ return q;
2317
+ };
2318
+ const throwIfNoWhere = (q, method) => {
2319
+ if (!q.q.or && !q.q.and && !q.q.scopes && !q.q.all) {
2320
+ throw new OrchidOrmInternalError(
2321
+ q,
2322
+ `Dangerous ${method} without conditions`
2351
2323
  );
2352
2324
  }
2353
- pushQueryValueImmutable(query, "join", {
2354
- type,
2355
- args: joinArgs
2356
- });
2357
- if (query.q.type === "delete") {
2358
- throwIfJoinLateral(
2359
- query,
2360
- query.q.type
2325
+ };
2326
+ const throwIfJoinLateral = (q, method) => {
2327
+ if (q.q.join?.some(
2328
+ (x) => Array.isArray(x) || "s" in x.args && x.args.s
2329
+ )) {
2330
+ throw new OrchidOrmInternalError(
2331
+ q,
2332
+ `Cannot join a complex query in ${method}`
2361
2333
  );
2362
2334
  }
2363
- return query;
2364
2335
  };
2365
- const addAllShapesAndParsers = (query, joinKey, shape, parsers, batchParsers, computeds) => {
2366
- if (!joinKey) return;
2367
- const { q } = query;
2368
- orchidCore.setObjectValueImmutable(q, "joinedShapes", joinKey, shape);
2369
- orchidCore.setObjectValueImmutable(q, "joinedParsers", joinKey, parsers);
2370
- if (batchParsers) {
2371
- orchidCore.setObjectValueImmutable(q, "joinedBatchParsers", joinKey, batchParsers);
2336
+ const saveSearchAlias = (q, as, key) => {
2337
+ const shapes = q.q[key];
2338
+ if (shapes?.[as]) {
2339
+ let suffix = 2;
2340
+ while (shapes[as = `${as}${suffix}`]) {
2341
+ suffix++;
2342
+ }
2372
2343
  }
2373
- orchidCore.setObjectValueImmutable(q, "joinedComputeds", joinKey, computeds);
2344
+ setQueryObjectValueImmutable(q, key, as, orchidCore.emptyObject);
2345
+ return as;
2374
2346
  };
2375
- const _joinLateralProcessArg = (q, arg, cb) => {
2376
- let relation;
2377
- if (typeof arg === "string") {
2378
- relation = q.relations[arg];
2379
- if (relation) {
2380
- arg = _clone(relation.relationConfig.query);
2381
- } else {
2382
- const w = q.q.withShapes?.[arg];
2383
- if (w) {
2384
- const t = Object.create(q.queryBuilder);
2385
- t.table = arg;
2386
- t.shape = w.shape;
2387
- t.computeds = w.computeds;
2388
- t.q = {
2389
- ...t.q,
2390
- shape: w.shape
2391
- };
2392
- t.baseQuery = t;
2393
- arg = t;
2394
- }
2347
+ const extendQuery = (q, methods) => {
2348
+ const base = Object.create(q.baseQuery);
2349
+ base.baseQuery = base;
2350
+ Object.assign(base, methods);
2351
+ const cloned = Object.create(base);
2352
+ cloned.q = getClonedQueryData(q.q);
2353
+ return cloned;
2354
+ };
2355
+ const getPrimaryKeys = (q) => {
2356
+ var _a;
2357
+ return (_a = q.internal).primaryKeys ?? (_a.primaryKeys = collectPrimaryKeys(q));
2358
+ };
2359
+ const collectPrimaryKeys = (q) => {
2360
+ const primaryKeys = [];
2361
+ const { shape } = q.q;
2362
+ for (const key in shape) {
2363
+ if (shape[key].data.primaryKey) {
2364
+ primaryKeys.push(key);
2395
2365
  }
2396
2366
  }
2397
- let result = resolveSubQueryCallbackV2(
2398
- arg,
2399
- cb
2400
- );
2401
- if (relation) {
2402
- result = relation.relationConfig.joinQuery(
2403
- result,
2404
- q
2405
- );
2367
+ const pkey = q.internal.tableData.primaryKey;
2368
+ if (pkey) {
2369
+ primaryKeys.push(...pkey.columns);
2406
2370
  }
2407
- return result;
2371
+ return primaryKeys;
2408
2372
  };
2409
- const _joinLateral = (self, type, arg, as) => {
2410
- const q = self;
2411
- arg.q.joinTo = q;
2412
- const joinedAs = getQueryAs(q);
2413
- orchidCore.setObjectValueImmutable(arg.q, "joinedShapes", joinedAs, q.q.shape);
2414
- const joinKey = as || arg.q.as || arg.table;
2415
- if (joinKey) {
2416
- const shape = getShapeFromSelect(arg, true);
2417
- orchidCore.setObjectValueImmutable(q.q, "joinedShapes", joinKey, shape);
2418
- orchidCore.setObjectValueImmutable(q.q, "joinedParsers", joinKey, arg.q.parsers);
2419
- if (arg.q.batchParsers) {
2420
- orchidCore.setObjectValueImmutable(
2421
- q.q,
2422
- "joinedBatchParsers",
2423
- joinKey,
2424
- arg.q.batchParsers
2425
- );
2373
+ const _queryAll = (q) => {
2374
+ q.q.returnType = "all";
2375
+ q.q.all = true;
2376
+ return q;
2377
+ };
2378
+ const _queryTake = (query) => {
2379
+ const q = query.q;
2380
+ switch (q.returnType) {
2381
+ case "valueOrThrow":
2382
+ case "pluck":
2383
+ case "void":
2384
+ break;
2385
+ case "value": {
2386
+ q.returnType = "valueOrThrow";
2387
+ break;
2388
+ }
2389
+ default: {
2390
+ q.returnType = "oneOrThrow";
2426
2391
  }
2427
2392
  }
2428
- as || (as = getQueryAs(arg));
2429
- orchidCore.setObjectValueImmutable(q.q, "joinedComputeds", as, arg.q.computeds);
2430
- pushQueryValueImmutable(q, "join", [type, arg, as]);
2393
+ return query;
2394
+ };
2395
+ const _queryTakeOptional = (query) => {
2396
+ const q = query.q;
2397
+ switch (q.returnType) {
2398
+ case "value":
2399
+ case "pluck":
2400
+ case "void":
2401
+ break;
2402
+ case "valueOrThrow": {
2403
+ q.returnType = "value";
2404
+ break;
2405
+ }
2406
+ default: {
2407
+ q.returnType = "one";
2408
+ }
2409
+ }
2410
+ return query;
2411
+ };
2412
+ const _queryExec = (q) => {
2413
+ q.q.returnType = "void";
2414
+ return q;
2415
+ };
2416
+ const _queryRows = (q) => {
2417
+ q.q.returnType = "rows";
2431
2418
  return q;
2432
2419
  };
2420
+ const getFullColumnTable = (q, column, index, as) => {
2421
+ const table = column.slice(0, index);
2422
+ return as && table !== as && q.q.aliases?.[table] === as ? as : table;
2423
+ };
2433
2424
 
2434
- class ArrayColumn extends ColumnType {
2435
- constructor(schema, item, inputType, outputType, queryType) {
2436
- super(schema, inputType, outputType, queryType);
2437
- this.dataType = "array";
2438
- this.operators = Operators.array;
2439
- item.data.isNullable = true;
2440
- setColumnDefaultParse(this, (input) => parse$1.call(this, input));
2441
- this.data.item = item instanceof ArrayColumn ? item.data.item : item;
2442
- this.data.name = item.data.name;
2443
- this.data.arrayDims = item instanceof ArrayColumn ? item.data.arrayDims + 1 : 1;
2425
+ function simpleColumnToSQL(ctx, key, column, quotedAs) {
2426
+ if (!column) return `"${key}"`;
2427
+ const { data } = column;
2428
+ return data.computed ? data.computed.toSQL(ctx, quotedAs) : `${quotedAs ? `${quotedAs}.` : ""}"${data.name || key}"`;
2429
+ }
2430
+ function simpleExistingColumnToSQL(ctx, key, column, quotedAs) {
2431
+ const { data } = column;
2432
+ return data.computed ? data.computed.toSQL(ctx, quotedAs) : `${quotedAs ? `${quotedAs}.` : ""}"${data.name || key}"`;
2433
+ }
2434
+ const columnToSql = (ctx, data, shape, column, quotedAs, select) => {
2435
+ const index = column.indexOf(".");
2436
+ if (index !== -1) {
2437
+ return columnWithDotToSql(
2438
+ ctx,
2439
+ data,
2440
+ shape,
2441
+ column,
2442
+ index,
2443
+ quotedAs,
2444
+ select
2445
+ );
2444
2446
  }
2445
- toSQL() {
2446
- return this.data.item.toSQL() + "[]".repeat(this.data.arrayDims);
2447
+ if (!select && data.joinedShapes?.[column]) {
2448
+ return `"${column}".r`;
2447
2449
  }
2448
- toCode(ctx, key) {
2449
- let open = "array(";
2450
- let close = ")";
2451
- for (let i = 1; i < this.data.arrayDims; i++) {
2452
- open += `${ctx.t}.array(`;
2453
- close += ")";
2450
+ return simpleColumnToSQL(ctx, column, shape[column], quotedAs);
2451
+ };
2452
+ const maybeSelectedColumnToSql = (ctx, data, column, quotedAs) => {
2453
+ const index = column.indexOf(".");
2454
+ if (index !== -1) {
2455
+ return columnWithDotToSql(ctx, data, data.shape, column, index, quotedAs);
2456
+ } else {
2457
+ if (data.joinedShapes?.[column]) {
2458
+ return `"${column}".r`;
2454
2459
  }
2455
- const code = [open];
2456
- const { item } = this.data;
2457
- const { isNullable } = item.data;
2458
- delete item.data.isNullable;
2459
- orchidCore.addCode(code, item.toCode(ctx, key));
2460
- item.data.isNullable = isNullable;
2461
- orchidCore.addCode(code, `${close}${orchidCore.arrayDataToCode(this.data, ctx.migration)}`);
2462
- return columnCode(this, ctx, key, code);
2460
+ if (data.select) {
2461
+ for (const s of data.select) {
2462
+ if (typeof s === "object" && "selectAs" in s) {
2463
+ if (column in s.selectAs) {
2464
+ return simpleColumnToSQL(ctx, column, data.shape[column]);
2465
+ }
2466
+ }
2467
+ }
2468
+ }
2469
+ return simpleColumnToSQL(ctx, column, data.shape[column], quotedAs);
2463
2470
  }
2464
- }
2465
- const parse$1 = function(source) {
2466
- if (typeof source !== "string") return source;
2467
- const entries = [];
2468
- parsePostgresArray(source, entries, this.data.item.data.parseItem);
2469
- return entries;
2470
2471
  };
2471
- const parsePostgresArray = (source, entries, transform) => {
2472
- let pos = 0;
2473
- if (source[0] === "[") {
2474
- pos = source.indexOf("=") + 1;
2475
- if (!pos) pos = source.length;
2472
+ const columnWithDotToSql = (ctx, data, shape, column, index, quotedAs, select) => {
2473
+ const table = column.slice(0, index);
2474
+ const key = column.slice(index + 1);
2475
+ if (key === "*") {
2476
+ const shape2 = data.joinedShapes?.[table];
2477
+ return shape2 ? select ? makeRowToJson(table, shape2, true) : `"${table}".*` : column;
2476
2478
  }
2477
- if (source[pos] === "{") pos++;
2478
- let recorded = "";
2479
- while (pos < source.length) {
2480
- const character = source[pos++];
2481
- if (character === "{") {
2482
- const innerEntries = [];
2483
- entries.push(innerEntries);
2484
- pos += parsePostgresArray(source.slice(pos - 1), innerEntries, transform) - 1;
2485
- } else if (character === "}") {
2486
- if (recorded) {
2487
- entries.push(
2488
- recorded === "NULL" ? null : transform ? transform(recorded) : recorded
2489
- );
2490
- }
2491
- return pos;
2492
- } else if (character === '"') {
2493
- let esc = false;
2494
- let rec = "";
2495
- while (pos < source.length) {
2496
- let char;
2497
- while ((char = source[pos++]) === "\\") {
2498
- if (!(esc = !esc)) rec += "\\";
2499
- }
2500
- if (esc) {
2501
- esc = false;
2502
- } else if (char === '"') {
2503
- break;
2504
- }
2505
- rec += char;
2506
- }
2507
- entries.push(transform ? transform(rec) : rec);
2508
- recorded = "";
2509
- } else if (character === ",") {
2510
- if (recorded) {
2511
- entries.push(
2512
- recorded === "NULL" ? null : transform ? transform(recorded) : recorded
2513
- );
2514
- recorded = "";
2479
+ const tableName = data.aliases?.[table] || table;
2480
+ const quoted = `"${table}"`;
2481
+ const col = quoted === quotedAs ? shape[key] : data.joinedShapes?.[tableName]?.[key];
2482
+ if (col) {
2483
+ if (col.data.name) {
2484
+ return `"${tableName}"."${col.data.name}"`;
2485
+ }
2486
+ if (col.data.computed) {
2487
+ return col.data.computed.toSQL(ctx, quoted);
2488
+ }
2489
+ return `"${tableName}"."${key}"`;
2490
+ }
2491
+ return `"${tableName}"."${key}"`;
2492
+ };
2493
+ const columnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList) => {
2494
+ const index = column.indexOf(".");
2495
+ return index !== -1 ? tableColumnToSqlWithAs(
2496
+ ctx,
2497
+ data,
2498
+ column,
2499
+ column.slice(0, index),
2500
+ column.slice(index + 1),
2501
+ as,
2502
+ quotedAs,
2503
+ select,
2504
+ jsonList
2505
+ ) : ownColumnToSqlWithAs(ctx, data, column, as, quotedAs, select, jsonList);
2506
+ };
2507
+ const tableColumnToSqlWithAs = (ctx, data, column, table, key, as, quotedAs, select, jsonList) => {
2508
+ if (key === "*") {
2509
+ if (jsonList) jsonList[as] = void 0;
2510
+ const shape = data.joinedShapes?.[table];
2511
+ if (shape) {
2512
+ {
2513
+ return makeRowToJson(table, shape, true) + ` "${as}"`;
2515
2514
  }
2516
- } else {
2517
- recorded += character;
2515
+ }
2516
+ return column;
2517
+ }
2518
+ const tableName = data.aliases?.[table] || table;
2519
+ const quoted = `"${table}"`;
2520
+ const col = quoted === quotedAs ? data.shape[key] : data.joinedShapes?.[tableName][key];
2521
+ if (jsonList) jsonList[as] = col;
2522
+ if (col) {
2523
+ if (col.data.name && col.data.name !== key) {
2524
+ return `"${tableName}"."${col.data.name}" "${as}"`;
2525
+ }
2526
+ if (col.data.computed) {
2527
+ return `${col.data.computed.toSQL(ctx, quoted)} "${as}"`;
2518
2528
  }
2519
2529
  }
2520
- return pos;
2530
+ return `"${tableName}"."${key}"${key === as ? "" : ` "${as}"`}`;
2521
2531
  };
2522
-
2523
- class NumberBaseColumn extends ColumnType {
2524
- constructor() {
2525
- super(...arguments);
2526
- this.operators = Operators.number;
2527
- }
2528
- }
2529
- class IntegerBaseColumn extends NumberBaseColumn {
2530
- constructor(schema) {
2531
- super(schema, schema.int());
2532
- this.data.int = true;
2533
- }
2534
- }
2535
- class NumberAsStringBaseColumn extends ColumnType {
2536
- constructor(schema) {
2537
- super(schema, schema.stringSchema());
2538
- this.operators = Operators.number;
2539
- this.data.jsonCast = "text";
2540
- }
2541
- }
2542
- class DecimalColumn extends NumberAsStringBaseColumn {
2543
- constructor(schema, numericPrecision, numericScale) {
2544
- super(schema);
2545
- this.operators = Operators.number;
2546
- this.dataType = "numeric";
2547
- this.data.numericPrecision = numericPrecision;
2548
- this.data.numericScale = numericScale;
2549
- this.data.alias = "decimal";
2532
+ const ownColumnToSqlWithAs = (ctx, data, column, as, quotedAs, select, jsonList) => {
2533
+ const col = data.shape[column];
2534
+ if (jsonList) jsonList[as] = col;
2535
+ if (col) {
2536
+ if (col.data.name && col.data.name !== column) {
2537
+ return `${quotedAs ? `${quotedAs}.` : ""}"${col.data.name}"${col.data.name === as ? "" : ` "${as}"`}`;
2538
+ }
2539
+ if (col.data.computed) {
2540
+ return `${col.data.computed.toSQL(ctx, quotedAs)} "${as}"`;
2541
+ }
2550
2542
  }
2551
- toCode(ctx, key) {
2552
- const { numericPrecision, numericScale } = this.data;
2553
- return columnCode(
2554
- this,
2555
- ctx,
2556
- key,
2557
- `decimal(${numericPrecision || ""}${numericScale ? `, ${numericScale}` : ""})`
2543
+ return `${quotedAs ? `${quotedAs}.` : ""}"${column}"${column === as ? "" : ` "${as}"`}`;
2544
+ };
2545
+ const rawOrColumnToSql = (ctx, data, expr, quotedAs, shape = data.shape, select) => {
2546
+ return typeof expr === "string" ? columnToSql(ctx, data, shape, expr, quotedAs, select) : expr.toSQL(ctx, quotedAs);
2547
+ };
2548
+ const quoteSchemaAndTable = (schema, table) => {
2549
+ return schema ? `"${schema}"."${table}"` : `"${table}"`;
2550
+ };
2551
+ const makeRowToJson = (table, shape, aliasName) => {
2552
+ let isSimple = true;
2553
+ const list = [];
2554
+ for (const key in shape) {
2555
+ const column = shape[key];
2556
+ if (column.data.explicitSelect) {
2557
+ continue;
2558
+ }
2559
+ if (aliasName && column.data.name || column.data.jsonCast) {
2560
+ isSimple = false;
2561
+ }
2562
+ list.push(
2563
+ `'${key}', "${table}"."${aliasName && column.data.name || key}"${column.data.jsonCast ? `::${column.data.jsonCast}` : ""}`
2558
2564
  );
2559
2565
  }
2560
- toSQL() {
2561
- const { numericPrecision, numericScale } = this.data;
2562
- return orchidCore.joinTruthy(
2563
- this.dataType,
2564
- numericPrecision ? numericScale ? `(${numericPrecision}, ${numericScale})` : `(${numericPrecision})` : void 0
2566
+ return isSimple ? `row_to_json("${table}".*)` : `CASE WHEN "${table}".* IS NULL THEN NULL ELSE json_build_object(` + list.join(", ") + ") END";
2567
+ };
2568
+
2569
+ const queryTypeWithLimitOne = {
2570
+ one: true,
2571
+ oneOrThrow: true,
2572
+ value: true,
2573
+ valueOrThrow: true
2574
+ };
2575
+ const isQueryReturnsAll = (q) => !q.q.returnType || q.q.returnType === "all";
2576
+
2577
+ const pushDistinctSql = (ctx, table, distinct, quotedAs) => {
2578
+ ctx.sql.push("DISTINCT");
2579
+ if (distinct.length) {
2580
+ const columns = distinct?.map(
2581
+ (item) => rawOrColumnToSql(ctx, table.q, item, quotedAs)
2565
2582
  );
2583
+ ctx.sql.push(`ON (${columns?.join(", ") || ""})`);
2566
2584
  }
2567
- }
2568
- const skipNumberMethods = { int: true };
2569
- const intToCode = (column, ctx, key, alias) => {
2570
- let code;
2571
- if (column.data.identity) {
2572
- code = identityToCode(column.data.identity, alias);
2585
+ };
2586
+
2587
+ const noneResult = (q, queryData, type) => {
2588
+ if (!type || type === "all" || type === "rows" || type === "pluck") {
2589
+ return [];
2590
+ } else if (type === "one" || type === "value" || type === "void") {
2591
+ return queryData.notFoundDefault;
2592
+ } else if (type === "valueOrThrow" && queryData.returning) {
2593
+ return 0;
2573
2594
  } else {
2574
- code = [`${alias}()`];
2595
+ throw new NotFoundError(q);
2575
2596
  }
2576
- orchidCore.addCode(
2577
- code,
2578
- orchidCore.numberDataToCode(column.data, ctx.migration, skipNumberMethods)
2597
+ };
2598
+ const noneMethods = {
2599
+ // `then` resolves or rejects based on a return type of the query.
2600
+ // It is `async` so it returns a chainable Promise.
2601
+ async then(resolve, reject) {
2602
+ try {
2603
+ const result = noneResult(this, this.q, this.q.returnType);
2604
+ resolve?.(result);
2605
+ } catch (err) {
2606
+ reject?.(err);
2607
+ }
2608
+ },
2609
+ // `catch` returns a Promise, so it is chainable with then/catch.
2610
+ catch: () => new Promise(orchidCore.noop)
2611
+ };
2612
+ const _queryNone = (q) => {
2613
+ if (isQueryNone(q)) return q;
2614
+ q = extendQuery(q, noneMethods);
2615
+ pushQueryValueImmutable(q, "and", new RawSQL("false"));
2616
+ pushQueryValueImmutable(
2617
+ q,
2618
+ "transform",
2619
+ (_, queryData) => noneResult(q, queryData, queryData.returnType)
2579
2620
  );
2580
- return columnCode(column, ctx, key, code);
2621
+ return q;
2581
2622
  };
2582
- class SmallIntColumn extends IntegerBaseColumn {
2583
- constructor(schema) {
2584
- super(schema);
2585
- this.dataType = "int2";
2586
- this.data.alias = "smallint";
2587
- this.data.parseItem = parseInt;
2588
- }
2589
- toCode(ctx, key) {
2590
- return intToCode(this, ctx, key, "smallint");
2591
- }
2592
- identity(options = {}) {
2593
- return orchidCore.setColumnData(this, "identity", options);
2594
- }
2595
- }
2596
- class IntegerColumn extends IntegerBaseColumn {
2597
- constructor(schema) {
2598
- super(schema);
2599
- this.dataType = "int4";
2600
- this.data.alias = "integer";
2601
- this.data.parseItem = parseInt;
2602
- }
2603
- toCode(ctx, key) {
2604
- return intToCode(this, ctx, key, "integer");
2605
- }
2606
- identity(options = {}) {
2607
- return orchidCore.setColumnData(this, "identity", options);
2608
- }
2609
- }
2610
- class BigIntColumn extends NumberAsStringBaseColumn {
2611
- constructor(schema) {
2612
- super(schema);
2613
- this.dataType = "int8";
2614
- this.data.alias = "bigint";
2615
- }
2616
- toCode(ctx, key) {
2617
- return intToCode(this, ctx, key, "bigint");
2618
- }
2619
- identity(options = {}) {
2620
- return orchidCore.setColumnData(this, "identity", options);
2621
- }
2622
- }
2623
- class RealColumn extends NumberBaseColumn {
2624
- constructor(schema) {
2625
- super(schema, schema.number());
2626
- this.dataType = "float4";
2627
- this.data.alias = "real";
2628
- this.data.parseItem = parseFloat;
2629
- }
2630
- toCode(ctx, key) {
2631
- return columnCode(
2632
- this,
2633
- ctx,
2634
- key,
2635
- `real()${orchidCore.numberDataToCode(this.data, ctx.migration)}`
2636
- );
2637
- }
2638
- }
2639
- class DoublePrecisionColumn extends NumberAsStringBaseColumn {
2640
- constructor(schema) {
2641
- super(schema);
2642
- this.dataType = "float8";
2643
- this.data.alias = "doublePrecision";
2644
- }
2645
- toCode(ctx, key) {
2646
- return columnCode(this, ctx, key, `doublePrecision()`);
2647
- }
2648
- }
2649
- class SmallSerialColumn extends IntegerBaseColumn {
2650
- constructor(schema) {
2651
- super(schema);
2652
- this.dataType = "int2";
2653
- this.data.int = true;
2654
- this.data.alias = "smallSerial";
2655
- this.data.parseItem = parseInt;
2623
+ const isQueryNone = (q) => q.then === noneMethods.then;
2624
+
2625
+ const _join = (query, require, type, first, args) => {
2626
+ let joinKey;
2627
+ let shape;
2628
+ let parsers;
2629
+ let batchParsers;
2630
+ let computeds;
2631
+ let joinSubQuery = false;
2632
+ first = preprocessJoinArg(query, first);
2633
+ if (typeof first === "object") {
2634
+ let isInternalJoin;
2635
+ if ("_internalJoin" in first) {
2636
+ isInternalJoin = true;
2637
+ first = first._internalJoin;
2638
+ }
2639
+ if (require && isQueryNone(first)) {
2640
+ return _queryNone(query);
2641
+ }
2642
+ const q = first;
2643
+ if (!isInternalJoin) {
2644
+ joinSubQuery = getIsJoinSubQuery(q);
2645
+ }
2646
+ joinKey = q.q.as || q.table;
2647
+ if (joinKey) {
2648
+ shape = getShapeFromSelect(q, joinSubQuery && !!q.q.select);
2649
+ parsers = q.q.parsers;
2650
+ batchParsers = q.q.batchParsers;
2651
+ computeds = q.q.computeds;
2652
+ if (joinSubQuery) {
2653
+ first = q.clone();
2654
+ first.shape = shape;
2655
+ }
2656
+ }
2657
+ } else {
2658
+ joinKey = first;
2659
+ const relation = query.relations[joinKey];
2660
+ if (relation) {
2661
+ shape = getShapeFromSelect(relation.relationConfig.query);
2662
+ const r = relation.relationConfig.query;
2663
+ parsers = r.q.parsers;
2664
+ batchParsers = r.q.batchParsers;
2665
+ computeds = r.q.computeds;
2666
+ } else {
2667
+ const w = query.q.withShapes?.[joinKey];
2668
+ shape = w?.shape;
2669
+ computeds = w?.computeds;
2670
+ if (shape) {
2671
+ if (!require) shape = { ...shape };
2672
+ const arg = { parsers: {} };
2673
+ for (const key in shape) {
2674
+ addColumnParserToQuery(arg, key, shape[key]);
2675
+ }
2676
+ }
2677
+ }
2656
2678
  }
2657
- toSQL() {
2658
- return "smallserial";
2679
+ const joinArgs = processJoinArgs(
2680
+ query,
2681
+ first,
2682
+ args,
2683
+ joinSubQuery
2684
+ );
2685
+ if (require && "r" in joinArgs && isQueryNone(joinArgs.r)) {
2686
+ return _queryNone(query);
2687
+ } else if (joinKey && "s" in joinArgs && joinArgs.s) {
2688
+ const j = "j" in joinArgs ? joinArgs.r ?? joinArgs.j : "r" in joinArgs ? joinArgs.r : joinArgs.q;
2689
+ const jq = j.q;
2690
+ if (jq.select || !jq.selectAllColumns) {
2691
+ const { q } = query;
2692
+ const shape2 = getShapeFromSelect(j, true);
2693
+ orchidCore.setObjectValueImmutable(q, "joinedShapes", joinKey, shape2);
2694
+ orchidCore.setObjectValueImmutable(q, "joinedParsers", joinKey, jq.parsers);
2695
+ if (jq.batchParsers) {
2696
+ orchidCore.setObjectValueImmutable(
2697
+ jq,
2698
+ "joinedBatchParsers",
2699
+ joinKey,
2700
+ jq.batchParsers
2701
+ );
2702
+ }
2703
+ orchidCore.setObjectValueImmutable(q, "joinedComputeds", joinKey, jq.computeds);
2704
+ } else {
2705
+ addAllShapesAndParsers(
2706
+ query,
2707
+ joinKey,
2708
+ shape,
2709
+ parsers,
2710
+ batchParsers,
2711
+ computeds
2712
+ );
2713
+ }
2714
+ } else {
2715
+ addAllShapesAndParsers(
2716
+ query,
2717
+ joinKey,
2718
+ shape,
2719
+ parsers,
2720
+ batchParsers,
2721
+ computeds
2722
+ );
2659
2723
  }
2660
- toCode(ctx, key) {
2661
- return columnCode(
2662
- this,
2663
- ctx,
2664
- key,
2665
- `smallSerial()${orchidCore.numberDataToCode(
2666
- this.data,
2667
- ctx.migration,
2668
- skipNumberMethods
2669
- )}`
2724
+ pushQueryValueImmutable(query, "join", {
2725
+ type,
2726
+ args: joinArgs
2727
+ });
2728
+ if (query.q.type === "delete") {
2729
+ throwIfJoinLateral(
2730
+ query,
2731
+ query.q.type
2670
2732
  );
2671
2733
  }
2672
- }
2673
- class SerialColumn extends IntegerBaseColumn {
2674
- constructor(schema) {
2675
- super(schema);
2676
- this.dataType = "int4";
2677
- this.data.int = true;
2678
- this.data.alias = "serial";
2679
- this.data.parseItem = parseInt;
2734
+ return query;
2735
+ };
2736
+ const addAllShapesAndParsers = (query, joinKey, shape, parsers, batchParsers, computeds) => {
2737
+ if (!joinKey) return;
2738
+ const { q } = query;
2739
+ orchidCore.setObjectValueImmutable(q, "joinedShapes", joinKey, shape);
2740
+ orchidCore.setObjectValueImmutable(q, "joinedParsers", joinKey, parsers);
2741
+ if (batchParsers) {
2742
+ orchidCore.setObjectValueImmutable(q, "joinedBatchParsers", joinKey, batchParsers);
2680
2743
  }
2681
- toSQL() {
2682
- return "serial";
2744
+ orchidCore.setObjectValueImmutable(q, "joinedComputeds", joinKey, computeds);
2745
+ };
2746
+ const _joinLateralProcessArg = (q, arg, cb) => {
2747
+ let relation;
2748
+ if (typeof arg === "string") {
2749
+ relation = q.relations[arg];
2750
+ if (relation) {
2751
+ arg = _clone(relation.relationConfig.query);
2752
+ } else {
2753
+ const w = q.q.withShapes?.[arg];
2754
+ if (w) {
2755
+ const t = Object.create(q.queryBuilder);
2756
+ t.table = arg;
2757
+ t.shape = w.shape;
2758
+ t.computeds = w.computeds;
2759
+ t.q = {
2760
+ ...t.q,
2761
+ shape: w.shape
2762
+ };
2763
+ t.baseQuery = t;
2764
+ arg = t;
2765
+ }
2766
+ }
2683
2767
  }
2684
- toCode(ctx, key) {
2685
- return columnCode(
2686
- this,
2687
- ctx,
2688
- key,
2689
- `serial()${orchidCore.numberDataToCode(
2690
- this.data,
2691
- ctx.migration,
2692
- skipNumberMethods
2693
- )}`
2768
+ let result = resolveSubQueryCallbackV2(
2769
+ arg,
2770
+ cb
2771
+ );
2772
+ if (relation) {
2773
+ result = relation.relationConfig.joinQuery(
2774
+ result,
2775
+ q
2694
2776
  );
2695
2777
  }
2696
- }
2697
- class BigSerialColumn extends NumberAsStringBaseColumn {
2698
- constructor(schema) {
2699
- super(schema);
2700
- this.dataType = "int8";
2701
- this.data.alias = "bigint";
2702
- }
2703
- toSQL() {
2704
- return "bigserial";
2705
- }
2706
- toCode(ctx, key) {
2707
- return columnCode(this, ctx, key, `bigSerial()`);
2778
+ return result;
2779
+ };
2780
+ const _joinLateral = (self, type, arg, as, innerJoinLateral) => {
2781
+ const q = self;
2782
+ arg.q.joinTo = q;
2783
+ const joinedAs = getQueryAs(q);
2784
+ orchidCore.setObjectValueImmutable(arg.q, "joinedShapes", joinedAs, q.q.shape);
2785
+ const joinKey = as || arg.q.as || arg.table;
2786
+ if (joinKey) {
2787
+ const shape = getShapeFromSelect(arg, true);
2788
+ orchidCore.setObjectValueImmutable(q.q, "joinedShapes", joinKey, shape);
2789
+ orchidCore.setObjectValueImmutable(q.q, "joinedParsers", joinKey, arg.q.parsers);
2790
+ if (arg.q.batchParsers) {
2791
+ orchidCore.setObjectValueImmutable(
2792
+ q.q,
2793
+ "joinedBatchParsers",
2794
+ joinKey,
2795
+ arg.q.batchParsers
2796
+ );
2797
+ }
2708
2798
  }
2709
- }
2710
-
2711
- const parseDateToDate = (value) => new Date(value);
2712
- const defaultSchemaConfig = {
2713
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2714
- parse(fn) {
2715
- return setColumnParse(this, fn);
2716
- },
2717
- parseNull(fn) {
2718
- return setColumnParseNull(this, fn);
2719
- },
2720
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2721
- encode(fn) {
2722
- return orchidCore.setColumnData(this, "encode", fn);
2723
- },
2724
- asType() {
2725
- return this;
2726
- },
2727
- dateAsNumber() {
2728
- return this.parse(Date.parse);
2729
- },
2730
- dateAsDate() {
2731
- return this.parse(parseDateToDate);
2732
- },
2733
- enum(dataType, type) {
2734
- return new EnumColumn(defaultSchemaConfig, dataType, type, void 0);
2735
- },
2736
- array(item) {
2737
- return new ArrayColumn(defaultSchemaConfig, item, void 0);
2738
- },
2739
- boolean: orchidCore.noop,
2740
- buffer: orchidCore.noop,
2741
- unknown: orchidCore.noop,
2742
- never: orchidCore.noop,
2743
- stringSchema: orchidCore.noop,
2744
- stringMin: orchidCore.noop,
2745
- stringMax: orchidCore.noop,
2746
- stringMinMax: orchidCore.noop,
2747
- number: orchidCore.noop,
2748
- int: orchidCore.noop,
2749
- stringNumberDate: orchidCore.noop,
2750
- timeInterval: orchidCore.noop,
2751
- bit: orchidCore.noop,
2752
- uuid: orchidCore.noop,
2753
- nullable() {
2754
- return orchidCore.setColumnData(this, "isNullable", true);
2755
- },
2756
- json() {
2757
- return new JSONColumn(defaultSchemaConfig, void 0);
2758
- },
2759
- setErrors: orchidCore.noop,
2760
- smallint: () => new SmallIntColumn(defaultSchemaConfig),
2761
- integer: () => new IntegerColumn(defaultSchemaConfig),
2762
- real: () => new RealColumn(defaultSchemaConfig),
2763
- smallSerial: () => new SmallSerialColumn(defaultSchemaConfig),
2764
- serial: () => new SerialColumn(defaultSchemaConfig),
2765
- bigint: () => new BigIntColumn(defaultSchemaConfig),
2766
- decimal: (precision, scale) => new DecimalColumn(defaultSchemaConfig, precision, scale),
2767
- doublePrecision: () => new DoublePrecisionColumn(defaultSchemaConfig),
2768
- bigSerial: () => new BigSerialColumn(defaultSchemaConfig),
2769
- money: () => new MoneyColumn(defaultSchemaConfig),
2770
- varchar: (limit) => new VarCharColumn(defaultSchemaConfig, limit),
2771
- text: () => new TextColumn(defaultSchemaConfig),
2772
- string: (limit) => new StringColumn(defaultSchemaConfig, limit),
2773
- citext: () => new CitextColumn(defaultSchemaConfig),
2774
- date: () => new DateColumn(defaultSchemaConfig),
2775
- timestampNoTZ: (precision) => new TimestampColumn(defaultSchemaConfig, precision),
2776
- timestamp: (precision) => new TimestampTZColumn(defaultSchemaConfig, precision),
2777
- geographyPointSchema: orchidCore.noop
2799
+ as || (as = getQueryAs(arg));
2800
+ orchidCore.setObjectValueImmutable(q.q, "joinedComputeds", as, arg.q.computeds);
2801
+ pushQueryValueImmutable(q, "join", {
2802
+ type: `${type} LATERAL`,
2803
+ args: { l: arg, a: as, i: innerJoinLateral }
2804
+ });
2805
+ return q;
2778
2806
  };
2779
2807
 
2780
2808
  const escape = (value, migration, nested) => {
@@ -4225,10 +4253,12 @@ const processSelectArg = (q, as, arg, columnAs) => {
4225
4253
  joinQuery = true;
4226
4254
  value = value.joinQuery(value, q);
4227
4255
  let query;
4228
- const returnType = value.q.returnType;
4256
+ const { returnType, innerJoinLateral } = value.q;
4229
4257
  if (!returnType || returnType === "all") {
4230
4258
  query = value.json(false);
4231
- value.q.coalesceValue = emptyArrSQL;
4259
+ if (!innerJoinLateral) {
4260
+ value.q.coalesceValue = emptyArrSQL;
4261
+ }
4232
4262
  } else if (returnType === "pluck") {
4233
4263
  query = value.q.select ? value.wrap(cloneQueryBaseUnscoped(value)).jsonAgg(value.q.select[0]) : value.json(false);
4234
4264
  value.q.coalesceValue = emptyArrSQL;
@@ -4255,9 +4285,12 @@ const processSelectArg = (q, as, arg, columnAs) => {
4255
4285
  }
4256
4286
  _joinLateral(
4257
4287
  q,
4258
- value.q.innerJoinLateral ? "JOIN" : "LEFT JOIN",
4288
+ innerJoinLateral ? "JOIN" : "LEFT JOIN",
4259
4289
  query,
4260
- key
4290
+ key,
4291
+ // no need for `ON p.r IS NOT NULL` check when joining a single record,
4292
+ // `JOIN` will handle it on itself.
4293
+ innerJoinLateral && returnType !== "one" && returnType !== "oneOrThrow"
4261
4294
  );
4262
4295
  }
4263
4296
  }
@@ -4385,7 +4418,7 @@ const getShapeFromSelect = (q, isSubQuery) => {
4385
4418
  const { returnType } = it.q;
4386
4419
  if (returnType === "value" || returnType === "valueOrThrow") {
4387
4420
  const type = it.q.getColumn;
4388
- if (type) result[key] = type;
4421
+ result[key] = type || UnknownColumn.instance;
4389
4422
  } else {
4390
4423
  result[key] = new JSONTextColumn(defaultSchemaConfig);
4391
4424
  }
@@ -6024,7 +6057,13 @@ const pushIn = (ctx, query, ands, quotedAs, arg) => {
6024
6057
  const processJoinItem = (ctx, table, query, args, quotedAs) => {
6025
6058
  let target;
6026
6059
  let on;
6027
- if ("j" in args) {
6060
+ if ("l" in args) {
6061
+ const { aliasValue } = ctx;
6062
+ ctx.aliasValue = true;
6063
+ target = `(${getSqlText(args.l.toSQL(ctx))}) "${query.aliases?.[args.a] || args.a}"`;
6064
+ on = `${args.i ? `"${args.a}".r IS NOT NULL` : "true"}`;
6065
+ ctx.aliasValue = aliasValue;
6066
+ } else if ("j" in args) {
6028
6067
  const { j, s, r } = args;
6029
6068
  const tableName = typeof j.q.from === "string" ? j.q.from : j.table;
6030
6069
  const quotedTable = quoteSchemaAndTable(j.q.schema, tableName);
@@ -6194,24 +6233,14 @@ const getObjectOrRawConditions = (ctx, query, data, quotedAs, joinAs, joinShape)
6194
6233
  const pushJoinSql = (ctx, table, query, quotedAs) => {
6195
6234
  const joinSet = query.join.length > 1 ? /* @__PURE__ */ new Set() : null;
6196
6235
  for (const item of query.join) {
6197
- let sql;
6198
- if (Array.isArray(item)) {
6199
- const q = item[1];
6200
- const { aliasValue } = ctx;
6201
- ctx.aliasValue = true;
6202
- const as = item[2];
6203
- sql = `${item[0]} LATERAL (${getSqlText(q.toSQL(ctx))}) "${query.aliases?.[as] || as}" ON true`;
6204
- ctx.aliasValue = aliasValue;
6205
- } else {
6206
- const { target, on = "true" } = processJoinItem(
6207
- ctx,
6208
- table,
6209
- query,
6210
- item.args,
6211
- quotedAs
6212
- );
6213
- sql = `${item.type} ${target} ON ${on}`;
6214
- }
6236
+ const { target, on = "true" } = processJoinItem(
6237
+ ctx,
6238
+ table,
6239
+ query,
6240
+ item.args,
6241
+ quotedAs
6242
+ );
6243
+ const sql = `${item.type} ${target} ON ${on}`;
6215
6244
  if (joinSet) {
6216
6245
  if (joinSet.has(sql)) continue;
6217
6246
  joinSet.add(sql);
@@ -8034,7 +8063,7 @@ class AggregateMethods {
8034
8063
  boolAnd(arg, options) {
8035
8064
  return makeFnExpression(
8036
8065
  this,
8037
- orchidCore.emptyObject,
8066
+ BooleanColumn.instance,
8038
8067
  "bool_and",
8039
8068
  [arg],
8040
8069
  options
@@ -8063,7 +8092,7 @@ class AggregateMethods {
8063
8092
  boolOr(arg, options) {
8064
8093
  return makeFnExpression(
8065
8094
  this,
8066
- orchidCore.emptyObject,
8095
+ BooleanColumn.instance,
8067
8096
  "bool_or",
8068
8097
  [arg],
8069
8098
  options
@@ -8075,7 +8104,7 @@ class AggregateMethods {
8075
8104
  every(arg, options) {
8076
8105
  return makeFnExpression(
8077
8106
  this,
8078
- orchidCore.emptyObject,
8107
+ BooleanColumn.instance,
8079
8108
  "every",
8080
8109
  [arg],
8081
8110
  options
@@ -8108,7 +8137,7 @@ class AggregateMethods {
8108
8137
  jsonAgg(arg, options) {
8109
8138
  return makeFnExpression(
8110
8139
  this,
8111
- orchidCore.emptyObject,
8140
+ JSONTextColumn.instance,
8112
8141
  "json_agg",
8113
8142
  [arg],
8114
8143
  options
@@ -8120,7 +8149,7 @@ class AggregateMethods {
8120
8149
  jsonbAgg(arg, options) {
8121
8150
  return makeFnExpression(
8122
8151
  this,
8123
- orchidCore.emptyObject,
8152
+ JSONTextColumn.instance,
8124
8153
  "jsonb_agg",
8125
8154
  [arg],
8126
8155
  options
@@ -8161,7 +8190,7 @@ class AggregateMethods {
8161
8190
  jsonObjectAgg(arg, options) {
8162
8191
  return makeFnExpression(
8163
8192
  this,
8164
- orchidCore.emptyObject,
8193
+ JSONTextColumn.instance,
8165
8194
  "json_object_agg",
8166
8195
  [{ pairs: arg }],
8167
8196
  options
@@ -8173,7 +8202,7 @@ class AggregateMethods {
8173
8202
  jsonbObjectAgg(arg, options) {
8174
8203
  return makeFnExpression(
8175
8204
  this,
8176
- orchidCore.emptyObject,
8205
+ JSONTextColumn.instance,
8177
8206
  "jsonb_object_agg",
8178
8207
  [{ pairs: arg }],
8179
8208
  options
@@ -8204,7 +8233,7 @@ class AggregateMethods {
8204
8233
  stringAgg(arg, delimiter, options) {
8205
8234
  return makeFnExpression(
8206
8235
  this,
8207
- orchidCore.emptyObject,
8236
+ TextColumn.instance,
8208
8237
  "string_agg",
8209
8238
  [arg, { value: delimiter }],
8210
8239
  options
@@ -8230,7 +8259,7 @@ class AggregateMethods {
8230
8259
  xmlAgg(arg, options) {
8231
8260
  return makeFnExpression(
8232
8261
  this,
8233
- orchidCore.emptyObject,
8262
+ XMLColumn.instance,
8234
8263
  "xmlagg",
8235
8264
  [arg],
8236
8265
  options