squel 6.2.0 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -46,7 +46,7 @@ module.exports = __toCommonJS(exports_src);
46
46
  // package.json
47
47
  var package_default = {
48
48
  name: "squel",
49
- version: "6.2.0",
49
+ version: "6.3.0",
50
50
  description: "SQL query string builder",
51
51
  keywords: [
52
52
  "sql",
@@ -152,7 +152,7 @@ function _clone(src) {
152
152
  if (_isPlainObject(src) || _isArray(src)) {
153
153
  const ret = new anySrc.constructor;
154
154
  for (const key of Object.getOwnPropertyNames(src)) {
155
- if (typeof anySrc[key] !== "function") {
155
+ if (typeof anySrc[key] !== "function" && key !== "_queryBuilder") {
156
156
  ret[key] = _clone(anySrc[key]);
157
157
  }
158
158
  }
@@ -575,6 +575,178 @@ function _buildSquel(flavour = null) {
575
575
  return { text: totalStr, values: totalValues };
576
576
  }
577
577
  };
578
+ cls.Over = class extends cls.BaseBuilder {
579
+ _funcExpr;
580
+ _funcParams;
581
+ _partitionFields;
582
+ _orderFields;
583
+ _rows;
584
+ _range;
585
+ constructor(funcExpr, funcParams = [], options) {
586
+ super(options);
587
+ this._funcExpr = funcExpr;
588
+ this._funcParams = funcParams || [];
589
+ this._partitionFields = [];
590
+ this._orderFields = [];
591
+ this._rows = null;
592
+ this._range = null;
593
+ }
594
+ partitionBy(...fields) {
595
+ let flatFields = [];
596
+ for (const field of fields) {
597
+ if (_isArray(field)) {
598
+ flatFields = flatFields.concat(field);
599
+ } else {
600
+ flatFields.push(field);
601
+ }
602
+ }
603
+ for (const field of flatFields) {
604
+ this._partitionFields.push(this._sanitizeField(field));
605
+ }
606
+ return this;
607
+ }
608
+ orderBy(field, dir, ...values) {
609
+ field = this._sanitizeField(field);
610
+ let direction;
611
+ if (typeof dir === "string") {
612
+ direction = dir;
613
+ } else if (dir === undefined) {
614
+ direction = "ASC";
615
+ } else if (dir === null) {
616
+ direction = null;
617
+ } else {
618
+ direction = dir ? "ASC" : "DESC";
619
+ }
620
+ this._orderFields.push({ field, dir: direction, values: values || [] });
621
+ return this;
622
+ }
623
+ rowsBetween(start, end) {
624
+ if (end === undefined) {
625
+ this._rows = `ROWS BETWEEN ${start}`;
626
+ } else {
627
+ this._rows = `ROWS BETWEEN ${start} AND ${end}`;
628
+ }
629
+ this._range = null;
630
+ return this;
631
+ }
632
+ rangeBetween(start, end) {
633
+ if (end === undefined) {
634
+ this._range = `RANGE BETWEEN ${start}`;
635
+ } else {
636
+ this._range = `RANGE BETWEEN ${start} AND ${end}`;
637
+ }
638
+ this._rows = null;
639
+ return this;
640
+ }
641
+ _toParamString(options = {}) {
642
+ const values = [];
643
+ let funcRet;
644
+ if (cls.isSquelBuilder(this._funcExpr)) {
645
+ funcRet = this._funcExpr._toParamString({
646
+ buildParameterized: options.buildParameterized
647
+ });
648
+ } else {
649
+ funcRet = this._buildString(this._funcExpr, this._funcParams, {
650
+ buildParameterized: options.buildParameterized
651
+ });
652
+ }
653
+ funcRet.values.forEach((v) => values.push(v));
654
+ let overPartsStr = "";
655
+ if (this._partitionFields.length > 0) {
656
+ let partitionStr = "";
657
+ for (const field of this._partitionFields) {
658
+ partitionStr = _pad(partitionStr, ", ");
659
+ if (cls.isSquelBuilder(field)) {
660
+ const ret = field._toParamString({
661
+ buildParameterized: options.buildParameterized
662
+ });
663
+ partitionStr += ret.text;
664
+ ret.values.forEach((v) => values.push(v));
665
+ } else {
666
+ partitionStr += this._formatFieldName(field);
667
+ }
668
+ }
669
+ overPartsStr = `PARTITION BY ${partitionStr}`;
670
+ }
671
+ if (this._orderFields.length > 0) {
672
+ let orderStr = "";
673
+ for (const { field, dir, values: orderVals } of this._orderFields) {
674
+ orderStr = _pad(orderStr, ", ");
675
+ let ret;
676
+ if (cls.isSquelBuilder(field)) {
677
+ ret = field._toParamString({
678
+ buildParameterized: options.buildParameterized
679
+ });
680
+ } else {
681
+ ret = this._buildString(field, orderVals, {
682
+ buildParameterized: options.buildParameterized
683
+ });
684
+ }
685
+ orderStr += ret.text;
686
+ ret.values.forEach((v) => values.push(v));
687
+ if (dir !== null) {
688
+ orderStr += ` ${dir}`;
689
+ }
690
+ }
691
+ overPartsStr = _pad(overPartsStr, " ") + `ORDER BY ${orderStr}`;
692
+ }
693
+ const frameClause = this._rows || this._range;
694
+ if (frameClause) {
695
+ overPartsStr = _pad(overPartsStr, " ") + frameClause;
696
+ }
697
+ return {
698
+ text: `${funcRet.text} OVER (${overPartsStr})`,
699
+ values
700
+ };
701
+ }
702
+ };
703
+ cls.JsonExtract = class extends cls.BaseBuilder {
704
+ _field;
705
+ _path;
706
+ constructor(field, path, options) {
707
+ super(options);
708
+ this._field = field;
709
+ this._path = path;
710
+ }
711
+ _toParamString(options = {}) {
712
+ const values = [];
713
+ let fieldStr = "";
714
+ if (cls.isSquelBuilder(this._field)) {
715
+ const ret = this._field._toParamString({
716
+ buildParameterized: options.buildParameterized
717
+ });
718
+ fieldStr = ret.text;
719
+ ret.values.forEach((v) => values.push(v));
720
+ } else {
721
+ fieldStr = this._formatFieldName(this._field);
722
+ }
723
+ let cleanPath = this._path;
724
+ if (cleanPath.startsWith("$")) {
725
+ cleanPath = cleanPath.slice(1);
726
+ }
727
+ if (cleanPath.startsWith(".")) {
728
+ cleanPath = cleanPath.slice(1);
729
+ }
730
+ const parts = cleanPath.split(".").filter(Boolean);
731
+ let sql = "";
732
+ if (flavour === "postgres") {
733
+ if (parts.length === 0) {
734
+ sql = fieldStr;
735
+ } else {
736
+ sql = fieldStr;
737
+ for (let i = 0;i < parts.length; i++) {
738
+ const op = i === parts.length - 1 ? "->>" : "->";
739
+ sql += `${op}'${parts[i]}'`;
740
+ }
741
+ }
742
+ } else if (flavour === "mssql") {
743
+ sql = `JSON_VALUE(${fieldStr}, '${this._path}')`;
744
+ } else {
745
+ sql = `json_extract(${fieldStr}, '${this._path}')`;
746
+ }
747
+ return { text: sql, values };
748
+ }
749
+ };
578
750
  cls.Block = class extends cls.BaseBuilder {
579
751
  constructor(options) {
580
752
  super(options);
@@ -1088,7 +1260,7 @@ function _buildSquel(flavour = null) {
1088
1260
  _toParamString(options = {}) {
1089
1261
  let totalStr = "";
1090
1262
  const totalValues = [];
1091
- for (const { type, table, alias, condition } of this._joins) {
1263
+ for (const { type, table, alias, condition, isApply } of this._joins) {
1092
1264
  totalStr = _pad(totalStr, this.options.separator);
1093
1265
  let tableStr;
1094
1266
  if (cls.isSquelBuilder(table)) {
@@ -1101,7 +1273,11 @@ function _buildSquel(flavour = null) {
1101
1273
  } else {
1102
1274
  tableStr = this._formatTableName(table);
1103
1275
  }
1104
- totalStr += `${type} JOIN ${tableStr}`;
1276
+ if (isApply) {
1277
+ totalStr += `${type} ${tableStr}`;
1278
+ } else {
1279
+ totalStr += `${type} JOIN ${tableStr}`;
1280
+ }
1105
1281
  if (alias)
1106
1282
  totalStr += ` ${this._formatTableAlias(alias)}`;
1107
1283
  if (condition) {
@@ -1174,12 +1350,93 @@ function _buildSquel(flavour = null) {
1174
1350
  };
1175
1351
  }
1176
1352
  };
1353
+ cls.WithBlock = class extends cls.Block {
1354
+ _tables;
1355
+ constructor(options) {
1356
+ super(options);
1357
+ this._tables = [];
1358
+ }
1359
+ with(alias, table) {
1360
+ this._tables.push({ alias, table, recursive: false });
1361
+ }
1362
+ withRecursive(alias, table) {
1363
+ this._tables.push({ alias, table, recursive: true });
1364
+ }
1365
+ _toParamString(options = {}) {
1366
+ const parts = [];
1367
+ const values = [];
1368
+ let anyRecursive = false;
1369
+ for (const { alias, table, recursive } of this._tables) {
1370
+ if (recursive) {
1371
+ anyRecursive = true;
1372
+ }
1373
+ const ret = table._toParamString({
1374
+ buildParameterized: options.buildParameterized,
1375
+ nested: true
1376
+ });
1377
+ parts.push(`${alias} AS ${ret.text}`);
1378
+ ret.values.forEach((v) => values.push(v));
1379
+ }
1380
+ if (!parts.length) {
1381
+ return { text: "", values: [] };
1382
+ }
1383
+ const isMssql = this.options.useRecursiveKeyword === false;
1384
+ const prefix = anyRecursive && !isMssql ? "WITH RECURSIVE" : "WITH";
1385
+ return {
1386
+ text: `${prefix} ${parts.join(", ")}`,
1387
+ values
1388
+ };
1389
+ }
1390
+ };
1391
+ cls.ReturningBlock = class extends cls.Block {
1392
+ _fields;
1393
+ constructor(options) {
1394
+ super(options);
1395
+ this._fields = [];
1396
+ }
1397
+ returning(field, alias = null, options = {}) {
1398
+ alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1399
+ field = this._sanitizeField(field);
1400
+ const existingField = this._fields.filter((f) => f.name === field && f.alias === alias);
1401
+ if (existingField.length)
1402
+ return this;
1403
+ this._fields.push({ name: field, alias, options });
1404
+ }
1405
+ _toParamString(options = {}) {
1406
+ const { buildParameterized } = options;
1407
+ let totalStr = "";
1408
+ const totalValues = [];
1409
+ for (const field of this._fields) {
1410
+ totalStr = _pad(totalStr, ", ");
1411
+ const { name, alias, options: fieldOptions } = field;
1412
+ if (typeof name === "string") {
1413
+ totalStr += this._formatFieldName(name, fieldOptions);
1414
+ } else {
1415
+ const ret = name._toParamString({ nested: true, buildParameterized });
1416
+ totalStr += ret.text;
1417
+ ret.values.forEach((v) => totalValues.push(v));
1418
+ }
1419
+ if (alias)
1420
+ totalStr += ` AS ${this._formatFieldAlias(alias)}`;
1421
+ }
1422
+ return {
1423
+ text: totalStr.length > 0 ? `RETURNING ${totalStr}` : "",
1424
+ values: totalValues
1425
+ };
1426
+ }
1427
+ };
1177
1428
  cls.QueryBuilder = class extends cls.BaseBuilder {
1178
1429
  blocks;
1179
1430
  constructor(options, blocks) {
1180
1431
  super(options);
1181
1432
  this.blocks = blocks || [];
1182
1433
  for (const block of this.blocks) {
1434
+ Object.defineProperty(block, "_queryBuilder", {
1435
+ value: this,
1436
+ enumerable: false,
1437
+ writable: true,
1438
+ configurable: true
1439
+ });
1183
1440
  const exposedMethods = block.exposedMethods();
1184
1441
  for (const methodName in exposedMethods) {
1185
1442
  const methodBody = exposedMethods[methodName];
@@ -1188,7 +1445,10 @@ function _buildSquel(flavour = null) {
1188
1445
  }
1189
1446
  ((b, name, body) => {
1190
1447
  this[name] = (...args) => {
1191
- body.call(b, ...args);
1448
+ const ret = body.call(b, ...args);
1449
+ if (ret !== undefined && ret !== b) {
1450
+ return ret;
1451
+ }
1192
1452
  return this;
1193
1453
  };
1194
1454
  })(block, methodName, methodBody);
@@ -1244,6 +1504,7 @@ function _buildSquel(flavour = null) {
1244
1504
  cls.Select = class extends cls.QueryBuilder {
1245
1505
  constructor(options, blocks = null) {
1246
1506
  blocks = blocks || [
1507
+ new cls.WithBlock(options),
1247
1508
  new cls.StringBlock(options, "SELECT"),
1248
1509
  new cls.FunctionBlock(options),
1249
1510
  new cls.DistinctBlock(options),
@@ -1265,12 +1526,14 @@ function _buildSquel(flavour = null) {
1265
1526
  cls.Update = class extends cls.QueryBuilder {
1266
1527
  constructor(options, blocks = null) {
1267
1528
  blocks = blocks || [
1529
+ new cls.WithBlock(options),
1268
1530
  new cls.StringBlock(options, "UPDATE"),
1269
1531
  new cls.UpdateTableBlock(options),
1270
1532
  new cls.SetFieldBlock(options),
1271
1533
  new cls.WhereBlock(options),
1272
1534
  new cls.OrderByBlock(options),
1273
- new cls.LimitBlock(options)
1535
+ new cls.LimitBlock(options),
1536
+ new cls.ReturningBlock(options)
1274
1537
  ];
1275
1538
  super(options, blocks);
1276
1539
  }
@@ -1278,13 +1541,15 @@ function _buildSquel(flavour = null) {
1278
1541
  cls.Delete = class extends cls.QueryBuilder {
1279
1542
  constructor(options, blocks = null) {
1280
1543
  blocks = blocks || [
1544
+ new cls.WithBlock(options),
1281
1545
  new cls.StringBlock(options, "DELETE"),
1282
1546
  new cls.TargetTableBlock(options),
1283
1547
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
1284
1548
  new cls.JoinBlock(options),
1285
1549
  new cls.WhereBlock(options),
1286
1550
  new cls.OrderByBlock(options),
1287
- new cls.LimitBlock(options)
1551
+ new cls.LimitBlock(options),
1552
+ new cls.ReturningBlock(options)
1288
1553
  ];
1289
1554
  super(options, blocks);
1290
1555
  }
@@ -1292,10 +1557,12 @@ function _buildSquel(flavour = null) {
1292
1557
  cls.Insert = class extends cls.QueryBuilder {
1293
1558
  constructor(options, blocks = null) {
1294
1559
  blocks = blocks || [
1560
+ new cls.WithBlock(options),
1295
1561
  new cls.StringBlock(options, "INSERT"),
1296
1562
  new cls.IntoTableBlock(options),
1297
1563
  new cls.InsertFieldValueBlock(options),
1298
- new cls.InsertFieldsFromQueryBlock(options)
1564
+ new cls.InsertFieldsFromQueryBlock(options),
1565
+ new cls.ReturningBlock(options)
1299
1566
  ];
1300
1567
  super(options, blocks);
1301
1568
  }
@@ -1319,6 +1586,8 @@ function _buildSquel(flavour = null) {
1319
1586
  inst.function(...args);
1320
1587
  return inst;
1321
1588
  },
1589
+ over: (funcExpr, ...funcParams) => new cls.Over(funcExpr, funcParams),
1590
+ jsonExtract: (field, path) => new cls.JsonExtract(field, path),
1322
1591
  registerValueHandler: cls.registerValueHandler
1323
1592
  };
1324
1593
  _squel.remove = _squel.delete;
@@ -1344,10 +1613,40 @@ var core_default = squel;
1344
1613
  // src/mysql.ts
1345
1614
  squel.flavours.mysql = (_squel) => {
1346
1615
  const cls = _squel.cls;
1616
+
1617
+ class MysqlOnDuplicateKeyUpdateHelper {
1618
+ builder;
1619
+ block;
1620
+ constructor(builder, block) {
1621
+ this.builder = builder;
1622
+ this.block = block;
1623
+ }
1624
+ }
1347
1625
  cls.MysqlOnDuplicateKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1348
1626
  onDupUpdate(field, value, options) {
1349
1627
  this._set(field, value, options);
1350
1628
  }
1629
+ onDuplicateKeyUpdate() {
1630
+ const helper = new MysqlOnDuplicateKeyUpdateHelper(this._queryBuilder, this);
1631
+ return new Proxy(helper, {
1632
+ get(target, prop, receiver) {
1633
+ if (prop === "set") {
1634
+ return (field, value, options) => {
1635
+ target.block._set(field, value, options);
1636
+ return receiver;
1637
+ };
1638
+ }
1639
+ const val = target.builder[prop];
1640
+ if (typeof val === "function") {
1641
+ return (...args) => {
1642
+ const ret = val.apply(target.builder, args);
1643
+ return ret === target.builder ? receiver : ret;
1644
+ };
1645
+ }
1646
+ return val;
1647
+ }
1648
+ });
1649
+ }
1351
1650
  _toParamString(options = {}) {
1352
1651
  let totalStr = "";
1353
1652
  const totalValues = [];
@@ -1376,6 +1675,7 @@ squel.flavours.mysql = (_squel) => {
1376
1675
  cls.Insert = class extends cls.QueryBuilder {
1377
1676
  constructor(options, blocks = null) {
1378
1677
  blocks = blocks || [
1678
+ new cls.WithBlock(options),
1379
1679
  new cls.StringBlock(options, "INSERT"),
1380
1680
  new cls.IntoTableBlock(options),
1381
1681
  new cls.InsertFieldValueBlock(options),
@@ -1388,6 +1688,7 @@ squel.flavours.mysql = (_squel) => {
1388
1688
  cls.Replace = class extends cls.QueryBuilder {
1389
1689
  constructor(options, blocks = null) {
1390
1690
  blocks = blocks || [
1691
+ new cls.WithBlock(options),
1391
1692
  new cls.StringBlock(options, "REPLACE"),
1392
1693
  new cls.IntoTableBlock(options),
1393
1694
  new cls.InsertFieldValueBlock(options),
@@ -1406,6 +1707,15 @@ squel.flavours.postgres = (_squel) => {
1406
1707
  cls.DefaultQueryBuilderOptions.numberedParametersStartAt = 1;
1407
1708
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1408
1709
  cls.DefaultQueryBuilderOptions.useAsForTableAliasNames = true;
1710
+
1711
+ class PostgresOnConflictUpdateHelper {
1712
+ builder;
1713
+ block;
1714
+ constructor(builder, block) {
1715
+ this.builder = builder;
1716
+ this.block = block;
1717
+ }
1718
+ }
1409
1719
  cls.PostgresOnConflictKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1410
1720
  _onConflict;
1411
1721
  _dupFields;
@@ -1416,17 +1726,46 @@ squel.flavours.postgres = (_squel) => {
1416
1726
  }
1417
1727
  onConflict(conflictFields, fields) {
1418
1728
  this._onConflict = true;
1419
- if (!conflictFields)
1420
- return;
1421
- if (!_isArray(conflictFields)) {
1422
- conflictFields = [conflictFields];
1729
+ if (conflictFields) {
1730
+ if (!_isArray(conflictFields)) {
1731
+ conflictFields = [conflictFields];
1732
+ }
1733
+ this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1423
1734
  }
1424
- this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1425
1735
  if (fields) {
1426
1736
  Object.keys(fields).forEach((key) => {
1427
1737
  this._set(key, fields[key]);
1428
1738
  });
1429
1739
  }
1740
+ return this._queryBuilder;
1741
+ }
1742
+ doUpdate() {
1743
+ const helper = new PostgresOnConflictUpdateHelper(this._queryBuilder, this);
1744
+ return new Proxy(helper, {
1745
+ get(target, prop, receiver) {
1746
+ if (prop === "set") {
1747
+ return (field, value, options) => {
1748
+ target.block._set(field, value, options);
1749
+ return receiver;
1750
+ };
1751
+ }
1752
+ const val = target.builder[prop];
1753
+ if (typeof val === "function") {
1754
+ return (...args) => {
1755
+ const ret = val.apply(target.builder, args);
1756
+ return ret === target.builder ? receiver : ret;
1757
+ };
1758
+ }
1759
+ return val;
1760
+ }
1761
+ });
1762
+ }
1763
+ doNothing() {
1764
+ this._onConflict = true;
1765
+ this._fields = [];
1766
+ this._values = [[]];
1767
+ this._valueOptions = [[]];
1768
+ return this._queryBuilder;
1430
1769
  }
1431
1770
  _toParamString(options = {}) {
1432
1771
  let totalStr = "";
@@ -1456,69 +1795,6 @@ squel.flavours.postgres = (_squel) => {
1456
1795
  return returned;
1457
1796
  }
1458
1797
  };
1459
- cls.ReturningBlock = class extends cls.Block {
1460
- _fields;
1461
- constructor(options) {
1462
- super(options);
1463
- this._fields = [];
1464
- }
1465
- returning(field, alias = null, options = {}) {
1466
- alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1467
- field = this._sanitizeField(field);
1468
- const existingField = this._fields.filter((f) => f.name === field && f.alias === alias);
1469
- if (existingField.length)
1470
- return this;
1471
- this._fields.push({ name: field, alias, options });
1472
- }
1473
- _toParamString(options = {}) {
1474
- const { buildParameterized } = options;
1475
- let totalStr = "";
1476
- const totalValues = [];
1477
- for (const field of this._fields) {
1478
- totalStr = _pad(totalStr, ", ");
1479
- const { name, alias, options: fieldOptions } = field;
1480
- if (typeof name === "string") {
1481
- totalStr += this._formatFieldName(name, fieldOptions);
1482
- } else {
1483
- const ret = name._toParamString({ nested: true, buildParameterized });
1484
- totalStr += ret.text;
1485
- ret.values.forEach((v) => totalValues.push(v));
1486
- }
1487
- if (alias)
1488
- totalStr += ` AS ${this._formatFieldAlias(alias)}`;
1489
- }
1490
- return {
1491
- text: totalStr.length > 0 ? `RETURNING ${totalStr}` : "",
1492
- values: totalValues
1493
- };
1494
- }
1495
- };
1496
- cls.WithBlock = class extends cls.Block {
1497
- _tables;
1498
- constructor(options) {
1499
- super(options);
1500
- this._tables = [];
1501
- }
1502
- with(alias, table) {
1503
- this._tables.push({ alias, table });
1504
- }
1505
- _toParamString(options = {}) {
1506
- const parts = [];
1507
- const values = [];
1508
- for (const { alias, table } of this._tables) {
1509
- const ret = table._toParamString({
1510
- buildParameterized: options.buildParameterized,
1511
- nested: true
1512
- });
1513
- parts.push(`${alias} AS ${ret.text}`);
1514
- ret.values.forEach((v) => values.push(v));
1515
- }
1516
- return {
1517
- text: parts.length ? `WITH ${parts.join(", ")}` : "",
1518
- values
1519
- };
1520
- }
1521
- };
1522
1798
  cls.UsingBlock = class extends cls.AbstractTableBlock {
1523
1799
  constructor(options) {
1524
1800
  super({ ...options, prefix: "USING" });
@@ -1632,6 +1908,7 @@ squel.flavours.mssql = (_squel) => {
1632
1908
  cls.DefaultQueryBuilderOptions.replaceSingleQuotes = true;
1633
1909
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1634
1910
  cls.DefaultQueryBuilderOptions.numberedParametersPrefix = "@";
1911
+ cls.DefaultQueryBuilderOptions.useRecursiveKeyword = false;
1635
1912
  _squel.registerValueHandler(Date, (value) => {
1636
1913
  const date = value;
1637
1914
  return `'${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()} ${date.getUTCHours()}:${date.getUTCMinutes()}:${date.getUTCSeconds()}'`;
@@ -1731,19 +2008,36 @@ squel.flavours.mssql = (_squel) => {
1731
2008
  super(options);
1732
2009
  this._outputs = [];
1733
2010
  }
1734
- output(fields) {
1735
- if (typeof fields === "string") {
1736
- this._outputs.push(`INSERTED.${this._sanitizeField(fields)}`);
1737
- } else {
1738
- fields.forEach((f) => {
1739
- this._outputs.push(`INSERTED.${this._sanitizeField(f)}`);
2011
+ outputs(outputs) {
2012
+ for (const output in outputs) {
2013
+ this.output(output, outputs[output]);
2014
+ }
2015
+ }
2016
+ output(output, alias = null) {
2017
+ if (typeof output === "string") {
2018
+ output = this._sanitizeField(output);
2019
+ alias = alias ? this._sanitizeFieldAlias(alias) : alias;
2020
+ this._outputs.push({
2021
+ name: `INSERTED.${output}`,
2022
+ alias
2023
+ });
2024
+ } else if (Array.isArray(output)) {
2025
+ output.forEach((f) => {
2026
+ this.output(f);
1740
2027
  });
1741
2028
  }
1742
2029
  }
1743
2030
  _toParamString(options) {
1744
2031
  const ret = super._toParamString(options);
1745
2032
  if (ret.text.length && this._outputs.length > 0) {
1746
- const innerStr = `OUTPUT ${this._outputs.join(", ")} `;
2033
+ const parts = this._outputs.map((o) => {
2034
+ let str = o.name;
2035
+ if (o.alias) {
2036
+ str += ` AS ${this._formatFieldAlias(o.alias)}`;
2037
+ }
2038
+ return str;
2039
+ });
2040
+ const innerStr = `OUTPUT ${parts.join(", ")} `;
1747
2041
  const valuesPos = ret.text.indexOf("VALUES");
1748
2042
  ret.text = ret.text.substring(0, valuesPos) + innerStr + ret.text.substring(valuesPos);
1749
2043
  }
@@ -1784,16 +2078,40 @@ squel.flavours.mssql = (_squel) => {
1784
2078
  return { text: totalStr, values: [] };
1785
2079
  }
1786
2080
  };
2081
+ cls.MssqlJoinBlock = class extends cls.JoinBlock {
2082
+ apply(table, alias = null, type = "CROSS") {
2083
+ table = this._sanitizeTable(table, true);
2084
+ alias = alias ? this._sanitizeTableAlias(alias) : alias;
2085
+ let applyType = type.toUpperCase();
2086
+ if (!applyType.endsWith("APPLY")) {
2087
+ applyType = `${applyType} APPLY`;
2088
+ }
2089
+ this._joins.push({
2090
+ type: applyType,
2091
+ table,
2092
+ alias,
2093
+ condition: null,
2094
+ isApply: true
2095
+ });
2096
+ }
2097
+ cross_apply(table, alias = null) {
2098
+ this.apply(table, alias, "CROSS");
2099
+ }
2100
+ outer_apply(table, alias = null) {
2101
+ this.apply(table, alias, "OUTER");
2102
+ }
2103
+ };
1787
2104
  cls.Select = class extends cls.QueryBuilder {
1788
2105
  constructor(options, blocks = null) {
1789
2106
  const limitOffsetTopBlock = new cls.MssqlLimitOffsetTopBlock(options);
1790
2107
  blocks = blocks || [
2108
+ new cls.WithBlock(options),
1791
2109
  new cls.StringBlock(options, "SELECT"),
1792
2110
  new cls.DistinctBlock(options),
1793
2111
  limitOffsetTopBlock.TOP(),
1794
2112
  new cls.GetFieldBlock(options),
1795
2113
  new cls.FromTableBlock(options),
1796
- new cls.JoinBlock(options),
2114
+ new cls.MssqlJoinBlock(options),
1797
2115
  new cls.WhereBlock(options),
1798
2116
  new cls.GroupByBlock(options),
1799
2117
  new cls.HavingBlock(options),
@@ -1808,6 +2126,7 @@ squel.flavours.mssql = (_squel) => {
1808
2126
  cls.Update = class extends cls.QueryBuilder {
1809
2127
  constructor(options, blocks = null) {
1810
2128
  blocks = blocks || [
2129
+ new cls.WithBlock(options),
1811
2130
  new cls.StringBlock(options, "UPDATE"),
1812
2131
  new cls.MssqlUpdateTopBlock(options),
1813
2132
  new cls.UpdateTableBlock(options),
@@ -1821,6 +2140,7 @@ squel.flavours.mssql = (_squel) => {
1821
2140
  cls.Delete = class extends cls.QueryBuilder {
1822
2141
  constructor(options, blocks = null) {
1823
2142
  blocks = blocks || [
2143
+ new cls.WithBlock(options),
1824
2144
  new cls.StringBlock(options, "DELETE"),
1825
2145
  new cls.TargetTableBlock(options),
1826
2146
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
@@ -1836,6 +2156,7 @@ squel.flavours.mssql = (_squel) => {
1836
2156
  cls.Insert = class extends cls.QueryBuilder {
1837
2157
  constructor(options, blocks = null) {
1838
2158
  blocks = blocks || [
2159
+ new cls.WithBlock(options),
1839
2160
  new cls.StringBlock(options, "INSERT"),
1840
2161
  new cls.IntoTableBlock(options),
1841
2162
  new cls.MssqlInsertFieldValueBlock(options),
@@ -1844,9 +2165,202 @@ squel.flavours.mssql = (_squel) => {
1844
2165
  super(options, blocks);
1845
2166
  }
1846
2167
  };
2168
+ cls.MergeIntoBlock = class extends cls.Block {
2169
+ _table = null;
2170
+ _alias = null;
2171
+ into(table, alias = null) {
2172
+ this._table = this._sanitizeTable(table);
2173
+ this._alias = alias ? this._sanitizeTableAlias(alias) : null;
2174
+ }
2175
+ _toParamString() {
2176
+ if (!this._table)
2177
+ throw new Error("into() needs to be called");
2178
+ let str = this._formatTableName(this._table);
2179
+ if (this._alias) {
2180
+ str += ` AS ${this._formatTableAlias(this._alias)}`;
2181
+ }
2182
+ return { text: str, values: [] };
2183
+ }
2184
+ };
2185
+ cls.MergeUsingBlock = class extends cls.Block {
2186
+ _source = null;
2187
+ _alias = null;
2188
+ _condition = null;
2189
+ using(source, alias = null, condition = null) {
2190
+ this._source = typeof source === "string" ? this._sanitizeTable(source) : this._sanitizeBaseBuilder(source);
2191
+ this._alias = alias ? this._sanitizeTableAlias(alias) : null;
2192
+ this._condition = condition ? this._sanitizeExpression(condition) : null;
2193
+ }
2194
+ _toParamString(options = {}) {
2195
+ if (!this._source)
2196
+ throw new Error("using() needs to be called");
2197
+ let sourceStr = "";
2198
+ const values = [];
2199
+ if (typeof this._source === "string") {
2200
+ sourceStr = this._formatTableName(this._source);
2201
+ } else {
2202
+ const ret = this._source._toParamString({
2203
+ buildParameterized: options.buildParameterized,
2204
+ nested: true
2205
+ });
2206
+ sourceStr = ret.text;
2207
+ ret.values.forEach((v) => values.push(v));
2208
+ }
2209
+ if (this._alias) {
2210
+ sourceStr += ` AS ${this._formatTableAlias(this._alias)}`;
2211
+ }
2212
+ let conditionStr = "";
2213
+ if (this._condition) {
2214
+ let ret;
2215
+ if (typeof this._condition === "string") {
2216
+ ret = this._buildString(this._condition, [], {
2217
+ buildParameterized: options.buildParameterized
2218
+ });
2219
+ } else {
2220
+ ret = this._condition._toParamString({
2221
+ buildParameterized: options.buildParameterized
2222
+ });
2223
+ }
2224
+ conditionStr = ` ON ${this._applyNestingFormatting(ret.text)}`;
2225
+ ret.values.forEach((v) => values.push(v));
2226
+ }
2227
+ return {
2228
+ text: `USING ${sourceStr}${conditionStr}`,
2229
+ values
2230
+ };
2231
+ }
2232
+ };
2233
+
2234
+ class MergeMatchedClauseHelper {
2235
+ builder;
2236
+ clause;
2237
+ constructor(builder, clause) {
2238
+ this.builder = builder;
2239
+ this.clause = clause;
2240
+ }
2241
+ update(fields) {
2242
+ this.clause.action = { type: "UPDATE", fields };
2243
+ return this.builder;
2244
+ }
2245
+ delete() {
2246
+ this.clause.action = { type: "DELETE" };
2247
+ return this.builder;
2248
+ }
2249
+ }
2250
+
2251
+ class MergeNotMatchedClauseHelper {
2252
+ builder;
2253
+ clause;
2254
+ constructor(builder, clause) {
2255
+ this.builder = builder;
2256
+ this.clause = clause;
2257
+ }
2258
+ insert(fields) {
2259
+ this.clause.action = { type: "INSERT", fields };
2260
+ return this.builder;
2261
+ }
2262
+ }
2263
+ cls.MergeWhenBlock = class extends cls.Block {
2264
+ _clauses;
2265
+ constructor(options) {
2266
+ super(options);
2267
+ this._clauses = [];
2268
+ }
2269
+ whenMatched(condition = null) {
2270
+ const clause = { type: "MATCHED", condition, action: null };
2271
+ this._clauses.push(clause);
2272
+ return new MergeMatchedClauseHelper(this._queryBuilder, clause);
2273
+ }
2274
+ whenNotMatched(condition = null) {
2275
+ const clause = { type: "NOT_MATCHED", condition, action: null };
2276
+ this._clauses.push(clause);
2277
+ return new MergeNotMatchedClauseHelper(this._queryBuilder, clause);
2278
+ }
2279
+ _toParamString(options = {}) {
2280
+ let totalStr = "";
2281
+ const totalValues = [];
2282
+ for (const clause of this._clauses) {
2283
+ if (!clause.action)
2284
+ continue;
2285
+ totalStr = _pad(totalStr, " ");
2286
+ let condStr = "";
2287
+ if (clause.condition) {
2288
+ const ret = this._buildString(clause.condition, [], {
2289
+ buildParameterized: options.buildParameterized
2290
+ });
2291
+ condStr = ` AND ${ret.text}`;
2292
+ ret.values.forEach((v) => totalValues.push(v));
2293
+ }
2294
+ let actionStr = "";
2295
+ if (clause.action.type === "UPDATE") {
2296
+ let setStr = "";
2297
+ for (const key of Object.keys(clause.action.fields)) {
2298
+ setStr = _pad(setStr, ", ");
2299
+ const val = clause.action.fields[key];
2300
+ if (val && typeof val._toParamString === "function") {
2301
+ const ret = val._toParamString({
2302
+ buildParameterized: options.buildParameterized
2303
+ });
2304
+ setStr += `${this._formatFieldName(key)} = ${ret.text}`;
2305
+ ret.values.forEach((v) => totalValues.push(v));
2306
+ } else {
2307
+ const ret = this._buildString(`${this._formatFieldName(key)} = ${this.options.parameterCharacter}`, [val], {
2308
+ buildParameterized: options.buildParameterized
2309
+ });
2310
+ setStr += ret.text;
2311
+ ret.values.forEach((v) => totalValues.push(v));
2312
+ }
2313
+ }
2314
+ actionStr = `THEN UPDATE SET ${setStr}`;
2315
+ } else if (clause.action.type === "DELETE") {
2316
+ actionStr = "THEN DELETE";
2317
+ } else if (clause.action.type === "INSERT") {
2318
+ const cols = Object.keys(clause.action.fields).map((c) => this._formatFieldName(c)).join(", ");
2319
+ let valsStr = "";
2320
+ for (const key of Object.keys(clause.action.fields)) {
2321
+ valsStr = _pad(valsStr, ", ");
2322
+ const val = clause.action.fields[key];
2323
+ if (val && typeof val._toParamString === "function") {
2324
+ const ret = val._toParamString({
2325
+ buildParameterized: options.buildParameterized
2326
+ });
2327
+ valsStr += ret.text;
2328
+ ret.values.forEach((v) => totalValues.push(v));
2329
+ } else {
2330
+ const ret = this._buildString(this.options.parameterCharacter, [val], {
2331
+ buildParameterized: options.buildParameterized
2332
+ });
2333
+ valsStr += ret.text;
2334
+ ret.values.forEach((v) => totalValues.push(v));
2335
+ }
2336
+ }
2337
+ actionStr = `THEN INSERT (${cols}) VALUES (${valsStr})`;
2338
+ }
2339
+ const whenWord = clause.type === "MATCHED" ? "WHEN MATCHED" : "WHEN NOT MATCHED";
2340
+ totalStr += `${whenWord}${condStr} ${actionStr}`;
2341
+ }
2342
+ return {
2343
+ text: totalStr.length ? `${totalStr};` : "",
2344
+ values: totalValues
2345
+ };
2346
+ }
2347
+ };
2348
+ cls.Merge = class extends cls.QueryBuilder {
2349
+ constructor(options, blocks = null) {
2350
+ blocks = blocks || [
2351
+ new cls.WithBlock(options),
2352
+ new cls.StringBlock(options, "MERGE INTO"),
2353
+ new cls.MergeIntoBlock(options),
2354
+ new cls.MergeUsingBlock(options),
2355
+ new cls.MergeWhenBlock(options)
2356
+ ];
2357
+ super(options, blocks);
2358
+ }
2359
+ };
2360
+ _squel.merge = (options, blocks) => new cls.Merge(options, blocks);
1847
2361
  };
1848
2362
 
1849
2363
  // src/index.ts
1850
2364
  var src_default = core_default;
1851
2365
 
1852
- //# debugId=C017CD4CA2D6F7B164756E2164756E21
2366
+ //# debugId=5F717BC6364CC8E864756E2164756E21