squel 6.1.0 → 6.2.1

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.1.0",
49
+ version: "6.2.1",
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);
@@ -1158,12 +1330,109 @@ function _buildSquel(flavour = null) {
1158
1330
  return { text: totalStr, values: totalValues };
1159
1331
  }
1160
1332
  };
1333
+ cls.ForBlock = class extends cls.Block {
1334
+ _forStr;
1335
+ constructor(options) {
1336
+ super(options);
1337
+ this._forStr = null;
1338
+ }
1339
+ for(str) {
1340
+ this._forStr = str;
1341
+ }
1342
+ _toParamString() {
1343
+ return {
1344
+ text: this._forStr !== null ? `FOR ${this._forStr}` : "",
1345
+ values: []
1346
+ };
1347
+ }
1348
+ };
1349
+ cls.WithBlock = class extends cls.Block {
1350
+ _tables;
1351
+ constructor(options) {
1352
+ super(options);
1353
+ this._tables = [];
1354
+ }
1355
+ with(alias, table) {
1356
+ this._tables.push({ alias, table, recursive: false });
1357
+ }
1358
+ withRecursive(alias, table) {
1359
+ this._tables.push({ alias, table, recursive: true });
1360
+ }
1361
+ _toParamString(options = {}) {
1362
+ const parts = [];
1363
+ const values = [];
1364
+ let anyRecursive = false;
1365
+ for (const { alias, table, recursive } of this._tables) {
1366
+ if (recursive) {
1367
+ anyRecursive = true;
1368
+ }
1369
+ const ret = table._toParamString({
1370
+ buildParameterized: options.buildParameterized,
1371
+ nested: true
1372
+ });
1373
+ parts.push(`${alias} AS ${ret.text}`);
1374
+ ret.values.forEach((v) => values.push(v));
1375
+ }
1376
+ if (!parts.length) {
1377
+ return { text: "", values: [] };
1378
+ }
1379
+ const isMssql = this.options.useRecursiveKeyword === false;
1380
+ const prefix = anyRecursive && !isMssql ? "WITH RECURSIVE" : "WITH";
1381
+ return {
1382
+ text: `${prefix} ${parts.join(", ")}`,
1383
+ values
1384
+ };
1385
+ }
1386
+ };
1387
+ cls.ReturningBlock = class extends cls.Block {
1388
+ _fields;
1389
+ constructor(options) {
1390
+ super(options);
1391
+ this._fields = [];
1392
+ }
1393
+ returning(field, alias = null, options = {}) {
1394
+ alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1395
+ field = this._sanitizeField(field);
1396
+ const existingField = this._fields.filter((f) => f.name === field && f.alias === alias);
1397
+ if (existingField.length)
1398
+ return this;
1399
+ this._fields.push({ name: field, alias, options });
1400
+ }
1401
+ _toParamString(options = {}) {
1402
+ const { buildParameterized } = options;
1403
+ let totalStr = "";
1404
+ const totalValues = [];
1405
+ for (const field of this._fields) {
1406
+ totalStr = _pad(totalStr, ", ");
1407
+ const { name, alias, options: fieldOptions } = field;
1408
+ if (typeof name === "string") {
1409
+ totalStr += this._formatFieldName(name, fieldOptions);
1410
+ } else {
1411
+ const ret = name._toParamString({ nested: true, buildParameterized });
1412
+ totalStr += ret.text;
1413
+ ret.values.forEach((v) => totalValues.push(v));
1414
+ }
1415
+ if (alias)
1416
+ totalStr += ` AS ${this._formatFieldAlias(alias)}`;
1417
+ }
1418
+ return {
1419
+ text: totalStr.length > 0 ? `RETURNING ${totalStr}` : "",
1420
+ values: totalValues
1421
+ };
1422
+ }
1423
+ };
1161
1424
  cls.QueryBuilder = class extends cls.BaseBuilder {
1162
1425
  blocks;
1163
1426
  constructor(options, blocks) {
1164
1427
  super(options);
1165
1428
  this.blocks = blocks || [];
1166
1429
  for (const block of this.blocks) {
1430
+ Object.defineProperty(block, "_queryBuilder", {
1431
+ value: this,
1432
+ enumerable: false,
1433
+ writable: true,
1434
+ configurable: true
1435
+ });
1167
1436
  const exposedMethods = block.exposedMethods();
1168
1437
  for (const methodName in exposedMethods) {
1169
1438
  const methodBody = exposedMethods[methodName];
@@ -1172,7 +1441,10 @@ function _buildSquel(flavour = null) {
1172
1441
  }
1173
1442
  ((b, name, body) => {
1174
1443
  this[name] = (...args) => {
1175
- body.call(b, ...args);
1444
+ const ret = body.call(b, ...args);
1445
+ if (ret !== undefined && ret !== b) {
1446
+ return ret;
1447
+ }
1176
1448
  return this;
1177
1449
  };
1178
1450
  })(block, methodName, methodBody);
@@ -1228,6 +1500,7 @@ function _buildSquel(flavour = null) {
1228
1500
  cls.Select = class extends cls.QueryBuilder {
1229
1501
  constructor(options, blocks = null) {
1230
1502
  blocks = blocks || [
1503
+ new cls.WithBlock(options),
1231
1504
  new cls.StringBlock(options, "SELECT"),
1232
1505
  new cls.FunctionBlock(options),
1233
1506
  new cls.DistinctBlock(options),
@@ -1240,7 +1513,8 @@ function _buildSquel(flavour = null) {
1240
1513
  new cls.OrderByBlock(options),
1241
1514
  new cls.LimitBlock(options),
1242
1515
  new cls.OffsetBlock(options),
1243
- new cls.UnionBlock(options)
1516
+ new cls.UnionBlock(options),
1517
+ new cls.ForBlock(options)
1244
1518
  ];
1245
1519
  super(options, blocks);
1246
1520
  }
@@ -1248,12 +1522,14 @@ function _buildSquel(flavour = null) {
1248
1522
  cls.Update = class extends cls.QueryBuilder {
1249
1523
  constructor(options, blocks = null) {
1250
1524
  blocks = blocks || [
1525
+ new cls.WithBlock(options),
1251
1526
  new cls.StringBlock(options, "UPDATE"),
1252
1527
  new cls.UpdateTableBlock(options),
1253
1528
  new cls.SetFieldBlock(options),
1254
1529
  new cls.WhereBlock(options),
1255
1530
  new cls.OrderByBlock(options),
1256
- new cls.LimitBlock(options)
1531
+ new cls.LimitBlock(options),
1532
+ new cls.ReturningBlock(options)
1257
1533
  ];
1258
1534
  super(options, blocks);
1259
1535
  }
@@ -1261,13 +1537,15 @@ function _buildSquel(flavour = null) {
1261
1537
  cls.Delete = class extends cls.QueryBuilder {
1262
1538
  constructor(options, blocks = null) {
1263
1539
  blocks = blocks || [
1540
+ new cls.WithBlock(options),
1264
1541
  new cls.StringBlock(options, "DELETE"),
1265
1542
  new cls.TargetTableBlock(options),
1266
1543
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
1267
1544
  new cls.JoinBlock(options),
1268
1545
  new cls.WhereBlock(options),
1269
1546
  new cls.OrderByBlock(options),
1270
- new cls.LimitBlock(options)
1547
+ new cls.LimitBlock(options),
1548
+ new cls.ReturningBlock(options)
1271
1549
  ];
1272
1550
  super(options, blocks);
1273
1551
  }
@@ -1275,10 +1553,12 @@ function _buildSquel(flavour = null) {
1275
1553
  cls.Insert = class extends cls.QueryBuilder {
1276
1554
  constructor(options, blocks = null) {
1277
1555
  blocks = blocks || [
1556
+ new cls.WithBlock(options),
1278
1557
  new cls.StringBlock(options, "INSERT"),
1279
1558
  new cls.IntoTableBlock(options),
1280
1559
  new cls.InsertFieldValueBlock(options),
1281
- new cls.InsertFieldsFromQueryBlock(options)
1560
+ new cls.InsertFieldsFromQueryBlock(options),
1561
+ new cls.ReturningBlock(options)
1282
1562
  ];
1283
1563
  super(options, blocks);
1284
1564
  }
@@ -1302,6 +1582,8 @@ function _buildSquel(flavour = null) {
1302
1582
  inst.function(...args);
1303
1583
  return inst;
1304
1584
  },
1585
+ over: (funcExpr, ...funcParams) => new cls.Over(funcExpr, funcParams),
1586
+ jsonExtract: (field, path) => new cls.JsonExtract(field, path),
1305
1587
  registerValueHandler: cls.registerValueHandler
1306
1588
  };
1307
1589
  _squel.remove = _squel.delete;
@@ -1327,10 +1609,40 @@ var core_default = squel;
1327
1609
  // src/mysql.ts
1328
1610
  squel.flavours.mysql = (_squel) => {
1329
1611
  const cls = _squel.cls;
1612
+
1613
+ class MysqlOnDuplicateKeyUpdateHelper {
1614
+ builder;
1615
+ block;
1616
+ constructor(builder, block) {
1617
+ this.builder = builder;
1618
+ this.block = block;
1619
+ }
1620
+ }
1330
1621
  cls.MysqlOnDuplicateKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1331
1622
  onDupUpdate(field, value, options) {
1332
1623
  this._set(field, value, options);
1333
1624
  }
1625
+ onDuplicateKeyUpdate() {
1626
+ const helper = new MysqlOnDuplicateKeyUpdateHelper(this._queryBuilder, this);
1627
+ return new Proxy(helper, {
1628
+ get(target, prop, receiver) {
1629
+ if (prop === "set") {
1630
+ return (field, value, options) => {
1631
+ target.block._set(field, value, options);
1632
+ return receiver;
1633
+ };
1634
+ }
1635
+ const val = target.builder[prop];
1636
+ if (typeof val === "function") {
1637
+ return (...args) => {
1638
+ const ret = val.apply(target.builder, args);
1639
+ return ret === target.builder ? receiver : ret;
1640
+ };
1641
+ }
1642
+ return val;
1643
+ }
1644
+ });
1645
+ }
1334
1646
  _toParamString(options = {}) {
1335
1647
  let totalStr = "";
1336
1648
  const totalValues = [];
@@ -1359,6 +1671,7 @@ squel.flavours.mysql = (_squel) => {
1359
1671
  cls.Insert = class extends cls.QueryBuilder {
1360
1672
  constructor(options, blocks = null) {
1361
1673
  blocks = blocks || [
1674
+ new cls.WithBlock(options),
1362
1675
  new cls.StringBlock(options, "INSERT"),
1363
1676
  new cls.IntoTableBlock(options),
1364
1677
  new cls.InsertFieldValueBlock(options),
@@ -1371,6 +1684,7 @@ squel.flavours.mysql = (_squel) => {
1371
1684
  cls.Replace = class extends cls.QueryBuilder {
1372
1685
  constructor(options, blocks = null) {
1373
1686
  blocks = blocks || [
1687
+ new cls.WithBlock(options),
1374
1688
  new cls.StringBlock(options, "REPLACE"),
1375
1689
  new cls.IntoTableBlock(options),
1376
1690
  new cls.InsertFieldValueBlock(options),
@@ -1389,6 +1703,15 @@ squel.flavours.postgres = (_squel) => {
1389
1703
  cls.DefaultQueryBuilderOptions.numberedParametersStartAt = 1;
1390
1704
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1391
1705
  cls.DefaultQueryBuilderOptions.useAsForTableAliasNames = true;
1706
+
1707
+ class PostgresOnConflictUpdateHelper {
1708
+ builder;
1709
+ block;
1710
+ constructor(builder, block) {
1711
+ this.builder = builder;
1712
+ this.block = block;
1713
+ }
1714
+ }
1392
1715
  cls.PostgresOnConflictKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1393
1716
  _onConflict;
1394
1717
  _dupFields;
@@ -1399,17 +1722,46 @@ squel.flavours.postgres = (_squel) => {
1399
1722
  }
1400
1723
  onConflict(conflictFields, fields) {
1401
1724
  this._onConflict = true;
1402
- if (!conflictFields)
1403
- return;
1404
- if (!_isArray(conflictFields)) {
1405
- conflictFields = [conflictFields];
1725
+ if (conflictFields) {
1726
+ if (!_isArray(conflictFields)) {
1727
+ conflictFields = [conflictFields];
1728
+ }
1729
+ this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1406
1730
  }
1407
- this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1408
1731
  if (fields) {
1409
1732
  Object.keys(fields).forEach((key) => {
1410
1733
  this._set(key, fields[key]);
1411
1734
  });
1412
1735
  }
1736
+ return this._queryBuilder;
1737
+ }
1738
+ doUpdate() {
1739
+ const helper = new PostgresOnConflictUpdateHelper(this._queryBuilder, this);
1740
+ return new Proxy(helper, {
1741
+ get(target, prop, receiver) {
1742
+ if (prop === "set") {
1743
+ return (field, value, options) => {
1744
+ target.block._set(field, value, options);
1745
+ return receiver;
1746
+ };
1747
+ }
1748
+ const val = target.builder[prop];
1749
+ if (typeof val === "function") {
1750
+ return (...args) => {
1751
+ const ret = val.apply(target.builder, args);
1752
+ return ret === target.builder ? receiver : ret;
1753
+ };
1754
+ }
1755
+ return val;
1756
+ }
1757
+ });
1758
+ }
1759
+ doNothing() {
1760
+ this._onConflict = true;
1761
+ this._fields = [];
1762
+ this._values = [[]];
1763
+ this._valueOptions = [[]];
1764
+ return this._queryBuilder;
1413
1765
  }
1414
1766
  _toParamString(options = {}) {
1415
1767
  let totalStr = "";
@@ -1439,69 +1791,6 @@ squel.flavours.postgres = (_squel) => {
1439
1791
  return returned;
1440
1792
  }
1441
1793
  };
1442
- cls.ReturningBlock = class extends cls.Block {
1443
- _fields;
1444
- constructor(options) {
1445
- super(options);
1446
- this._fields = [];
1447
- }
1448
- returning(field, alias = null, options = {}) {
1449
- alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1450
- field = this._sanitizeField(field);
1451
- const existingField = this._fields.filter((f) => f.name === field && f.alias === alias);
1452
- if (existingField.length)
1453
- return this;
1454
- this._fields.push({ name: field, alias, options });
1455
- }
1456
- _toParamString(options = {}) {
1457
- const { buildParameterized } = options;
1458
- let totalStr = "";
1459
- const totalValues = [];
1460
- for (const field of this._fields) {
1461
- totalStr = _pad(totalStr, ", ");
1462
- const { name, alias, options: fieldOptions } = field;
1463
- if (typeof name === "string") {
1464
- totalStr += this._formatFieldName(name, fieldOptions);
1465
- } else {
1466
- const ret = name._toParamString({ nested: true, buildParameterized });
1467
- totalStr += ret.text;
1468
- ret.values.forEach((v) => totalValues.push(v));
1469
- }
1470
- if (alias)
1471
- totalStr += ` AS ${this._formatFieldAlias(alias)}`;
1472
- }
1473
- return {
1474
- text: totalStr.length > 0 ? `RETURNING ${totalStr}` : "",
1475
- values: totalValues
1476
- };
1477
- }
1478
- };
1479
- cls.WithBlock = class extends cls.Block {
1480
- _tables;
1481
- constructor(options) {
1482
- super(options);
1483
- this._tables = [];
1484
- }
1485
- with(alias, table) {
1486
- this._tables.push({ alias, table });
1487
- }
1488
- _toParamString(options = {}) {
1489
- const parts = [];
1490
- const values = [];
1491
- for (const { alias, table } of this._tables) {
1492
- const ret = table._toParamString({
1493
- buildParameterized: options.buildParameterized,
1494
- nested: true
1495
- });
1496
- parts.push(`${alias} AS ${ret.text}`);
1497
- ret.values.forEach((v) => values.push(v));
1498
- }
1499
- return {
1500
- text: parts.length ? `WITH ${parts.join(", ")}` : "",
1501
- values
1502
- };
1503
- }
1504
- };
1505
1794
  cls.UsingBlock = class extends cls.AbstractTableBlock {
1506
1795
  constructor(options) {
1507
1796
  super({ ...options, prefix: "USING" });
@@ -1550,7 +1839,8 @@ squel.flavours.postgres = (_squel) => {
1550
1839
  new cls.OrderByBlock(options),
1551
1840
  new cls.LimitBlock(options),
1552
1841
  new cls.OffsetBlock(options),
1553
- new cls.UnionBlock(options)
1842
+ new cls.UnionBlock(options),
1843
+ new cls.ForBlock(options)
1554
1844
  ];
1555
1845
  super(options, blocks);
1556
1846
  }
@@ -1614,6 +1904,7 @@ squel.flavours.mssql = (_squel) => {
1614
1904
  cls.DefaultQueryBuilderOptions.replaceSingleQuotes = true;
1615
1905
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1616
1906
  cls.DefaultQueryBuilderOptions.numberedParametersPrefix = "@";
1907
+ cls.DefaultQueryBuilderOptions.useRecursiveKeyword = false;
1617
1908
  _squel.registerValueHandler(Date, (value) => {
1618
1909
  const date = value;
1619
1910
  return `'${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()} ${date.getUTCHours()}:${date.getUTCMinutes()}:${date.getUTCSeconds()}'`;
@@ -1713,19 +2004,36 @@ squel.flavours.mssql = (_squel) => {
1713
2004
  super(options);
1714
2005
  this._outputs = [];
1715
2006
  }
1716
- output(fields) {
1717
- if (typeof fields === "string") {
1718
- this._outputs.push(`INSERTED.${this._sanitizeField(fields)}`);
1719
- } else {
1720
- fields.forEach((f) => {
1721
- this._outputs.push(`INSERTED.${this._sanitizeField(f)}`);
2007
+ outputs(outputs) {
2008
+ for (const output in outputs) {
2009
+ this.output(output, outputs[output]);
2010
+ }
2011
+ }
2012
+ output(output, alias = null) {
2013
+ if (typeof output === "string") {
2014
+ output = this._sanitizeField(output);
2015
+ alias = alias ? this._sanitizeFieldAlias(alias) : alias;
2016
+ this._outputs.push({
2017
+ name: `INSERTED.${output}`,
2018
+ alias
2019
+ });
2020
+ } else if (Array.isArray(output)) {
2021
+ output.forEach((f) => {
2022
+ this.output(f);
1722
2023
  });
1723
2024
  }
1724
2025
  }
1725
2026
  _toParamString(options) {
1726
2027
  const ret = super._toParamString(options);
1727
2028
  if (ret.text.length && this._outputs.length > 0) {
1728
- const innerStr = `OUTPUT ${this._outputs.join(", ")} `;
2029
+ const parts = this._outputs.map((o) => {
2030
+ let str = o.name;
2031
+ if (o.alias) {
2032
+ str += ` AS ${this._formatFieldAlias(o.alias)}`;
2033
+ }
2034
+ return str;
2035
+ });
2036
+ const innerStr = `OUTPUT ${parts.join(", ")} `;
1729
2037
  const valuesPos = ret.text.indexOf("VALUES");
1730
2038
  ret.text = ret.text.substring(0, valuesPos) + innerStr + ret.text.substring(valuesPos);
1731
2039
  }
@@ -1770,6 +2078,7 @@ squel.flavours.mssql = (_squel) => {
1770
2078
  constructor(options, blocks = null) {
1771
2079
  const limitOffsetTopBlock = new cls.MssqlLimitOffsetTopBlock(options);
1772
2080
  blocks = blocks || [
2081
+ new cls.WithBlock(options),
1773
2082
  new cls.StringBlock(options, "SELECT"),
1774
2083
  new cls.DistinctBlock(options),
1775
2084
  limitOffsetTopBlock.TOP(),
@@ -1790,6 +2099,7 @@ squel.flavours.mssql = (_squel) => {
1790
2099
  cls.Update = class extends cls.QueryBuilder {
1791
2100
  constructor(options, blocks = null) {
1792
2101
  blocks = blocks || [
2102
+ new cls.WithBlock(options),
1793
2103
  new cls.StringBlock(options, "UPDATE"),
1794
2104
  new cls.MssqlUpdateTopBlock(options),
1795
2105
  new cls.UpdateTableBlock(options),
@@ -1803,6 +2113,7 @@ squel.flavours.mssql = (_squel) => {
1803
2113
  cls.Delete = class extends cls.QueryBuilder {
1804
2114
  constructor(options, blocks = null) {
1805
2115
  blocks = blocks || [
2116
+ new cls.WithBlock(options),
1806
2117
  new cls.StringBlock(options, "DELETE"),
1807
2118
  new cls.TargetTableBlock(options),
1808
2119
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
@@ -1818,6 +2129,7 @@ squel.flavours.mssql = (_squel) => {
1818
2129
  cls.Insert = class extends cls.QueryBuilder {
1819
2130
  constructor(options, blocks = null) {
1820
2131
  blocks = blocks || [
2132
+ new cls.WithBlock(options),
1821
2133
  new cls.StringBlock(options, "INSERT"),
1822
2134
  new cls.IntoTableBlock(options),
1823
2135
  new cls.MssqlInsertFieldValueBlock(options),
@@ -1826,9 +2138,202 @@ squel.flavours.mssql = (_squel) => {
1826
2138
  super(options, blocks);
1827
2139
  }
1828
2140
  };
2141
+ cls.MergeIntoBlock = class extends cls.Block {
2142
+ _table = null;
2143
+ _alias = null;
2144
+ into(table, alias = null) {
2145
+ this._table = this._sanitizeTable(table);
2146
+ this._alias = alias ? this._sanitizeTableAlias(alias) : null;
2147
+ }
2148
+ _toParamString() {
2149
+ if (!this._table)
2150
+ throw new Error("into() needs to be called");
2151
+ let str = this._formatTableName(this._table);
2152
+ if (this._alias) {
2153
+ str += ` AS ${this._formatTableAlias(this._alias)}`;
2154
+ }
2155
+ return { text: str, values: [] };
2156
+ }
2157
+ };
2158
+ cls.MergeUsingBlock = class extends cls.Block {
2159
+ _source = null;
2160
+ _alias = null;
2161
+ _condition = null;
2162
+ using(source, alias = null, condition = null) {
2163
+ this._source = typeof source === "string" ? this._sanitizeTable(source) : this._sanitizeBaseBuilder(source);
2164
+ this._alias = alias ? this._sanitizeTableAlias(alias) : null;
2165
+ this._condition = condition ? this._sanitizeExpression(condition) : null;
2166
+ }
2167
+ _toParamString(options = {}) {
2168
+ if (!this._source)
2169
+ throw new Error("using() needs to be called");
2170
+ let sourceStr = "";
2171
+ const values = [];
2172
+ if (typeof this._source === "string") {
2173
+ sourceStr = this._formatTableName(this._source);
2174
+ } else {
2175
+ const ret = this._source._toParamString({
2176
+ buildParameterized: options.buildParameterized,
2177
+ nested: true
2178
+ });
2179
+ sourceStr = ret.text;
2180
+ ret.values.forEach((v) => values.push(v));
2181
+ }
2182
+ if (this._alias) {
2183
+ sourceStr += ` AS ${this._formatTableAlias(this._alias)}`;
2184
+ }
2185
+ let conditionStr = "";
2186
+ if (this._condition) {
2187
+ let ret;
2188
+ if (typeof this._condition === "string") {
2189
+ ret = this._buildString(this._condition, [], {
2190
+ buildParameterized: options.buildParameterized
2191
+ });
2192
+ } else {
2193
+ ret = this._condition._toParamString({
2194
+ buildParameterized: options.buildParameterized
2195
+ });
2196
+ }
2197
+ conditionStr = ` ON ${this._applyNestingFormatting(ret.text)}`;
2198
+ ret.values.forEach((v) => values.push(v));
2199
+ }
2200
+ return {
2201
+ text: `USING ${sourceStr}${conditionStr}`,
2202
+ values
2203
+ };
2204
+ }
2205
+ };
2206
+
2207
+ class MergeMatchedClauseHelper {
2208
+ builder;
2209
+ clause;
2210
+ constructor(builder, clause) {
2211
+ this.builder = builder;
2212
+ this.clause = clause;
2213
+ }
2214
+ update(fields) {
2215
+ this.clause.action = { type: "UPDATE", fields };
2216
+ return this.builder;
2217
+ }
2218
+ delete() {
2219
+ this.clause.action = { type: "DELETE" };
2220
+ return this.builder;
2221
+ }
2222
+ }
2223
+
2224
+ class MergeNotMatchedClauseHelper {
2225
+ builder;
2226
+ clause;
2227
+ constructor(builder, clause) {
2228
+ this.builder = builder;
2229
+ this.clause = clause;
2230
+ }
2231
+ insert(fields) {
2232
+ this.clause.action = { type: "INSERT", fields };
2233
+ return this.builder;
2234
+ }
2235
+ }
2236
+ cls.MergeWhenBlock = class extends cls.Block {
2237
+ _clauses;
2238
+ constructor(options) {
2239
+ super(options);
2240
+ this._clauses = [];
2241
+ }
2242
+ whenMatched(condition = null) {
2243
+ const clause = { type: "MATCHED", condition, action: null };
2244
+ this._clauses.push(clause);
2245
+ return new MergeMatchedClauseHelper(this._queryBuilder, clause);
2246
+ }
2247
+ whenNotMatched(condition = null) {
2248
+ const clause = { type: "NOT_MATCHED", condition, action: null };
2249
+ this._clauses.push(clause);
2250
+ return new MergeNotMatchedClauseHelper(this._queryBuilder, clause);
2251
+ }
2252
+ _toParamString(options = {}) {
2253
+ let totalStr = "";
2254
+ const totalValues = [];
2255
+ for (const clause of this._clauses) {
2256
+ if (!clause.action)
2257
+ continue;
2258
+ totalStr = _pad(totalStr, " ");
2259
+ let condStr = "";
2260
+ if (clause.condition) {
2261
+ const ret = this._buildString(clause.condition, [], {
2262
+ buildParameterized: options.buildParameterized
2263
+ });
2264
+ condStr = ` AND ${ret.text}`;
2265
+ ret.values.forEach((v) => totalValues.push(v));
2266
+ }
2267
+ let actionStr = "";
2268
+ if (clause.action.type === "UPDATE") {
2269
+ let setStr = "";
2270
+ for (const key of Object.keys(clause.action.fields)) {
2271
+ setStr = _pad(setStr, ", ");
2272
+ const val = clause.action.fields[key];
2273
+ if (val && typeof val._toParamString === "function") {
2274
+ const ret = val._toParamString({
2275
+ buildParameterized: options.buildParameterized
2276
+ });
2277
+ setStr += `${this._formatFieldName(key)} = ${ret.text}`;
2278
+ ret.values.forEach((v) => totalValues.push(v));
2279
+ } else {
2280
+ const ret = this._buildString(`${this._formatFieldName(key)} = ${this.options.parameterCharacter}`, [val], {
2281
+ buildParameterized: options.buildParameterized
2282
+ });
2283
+ setStr += ret.text;
2284
+ ret.values.forEach((v) => totalValues.push(v));
2285
+ }
2286
+ }
2287
+ actionStr = `THEN UPDATE SET ${setStr}`;
2288
+ } else if (clause.action.type === "DELETE") {
2289
+ actionStr = "THEN DELETE";
2290
+ } else if (clause.action.type === "INSERT") {
2291
+ const cols = Object.keys(clause.action.fields).map((c) => this._formatFieldName(c)).join(", ");
2292
+ let valsStr = "";
2293
+ for (const key of Object.keys(clause.action.fields)) {
2294
+ valsStr = _pad(valsStr, ", ");
2295
+ const val = clause.action.fields[key];
2296
+ if (val && typeof val._toParamString === "function") {
2297
+ const ret = val._toParamString({
2298
+ buildParameterized: options.buildParameterized
2299
+ });
2300
+ valsStr += ret.text;
2301
+ ret.values.forEach((v) => totalValues.push(v));
2302
+ } else {
2303
+ const ret = this._buildString(this.options.parameterCharacter, [val], {
2304
+ buildParameterized: options.buildParameterized
2305
+ });
2306
+ valsStr += ret.text;
2307
+ ret.values.forEach((v) => totalValues.push(v));
2308
+ }
2309
+ }
2310
+ actionStr = `THEN INSERT (${cols}) VALUES (${valsStr})`;
2311
+ }
2312
+ const whenWord = clause.type === "MATCHED" ? "WHEN MATCHED" : "WHEN NOT MATCHED";
2313
+ totalStr += `${whenWord}${condStr} ${actionStr}`;
2314
+ }
2315
+ return {
2316
+ text: totalStr.length ? `${totalStr};` : "",
2317
+ values: totalValues
2318
+ };
2319
+ }
2320
+ };
2321
+ cls.Merge = class extends cls.QueryBuilder {
2322
+ constructor(options, blocks = null) {
2323
+ blocks = blocks || [
2324
+ new cls.WithBlock(options),
2325
+ new cls.StringBlock(options, "MERGE INTO"),
2326
+ new cls.MergeIntoBlock(options),
2327
+ new cls.MergeUsingBlock(options),
2328
+ new cls.MergeWhenBlock(options)
2329
+ ];
2330
+ super(options, blocks);
2331
+ }
2332
+ };
2333
+ _squel.merge = (options, blocks) => new cls.Merge(options, blocks);
1829
2334
  };
1830
2335
 
1831
2336
  // src/index.ts
1832
2337
  var src_default = core_default;
1833
2338
 
1834
- //# debugId=D27340B1E6396E3D64756E2164756E21
2339
+ //# debugId=4D152D45BD38372364756E2164756E21