squel 6.2.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.2.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);
@@ -1174,12 +1346,93 @@ function _buildSquel(flavour = null) {
1174
1346
  };
1175
1347
  }
1176
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
+ };
1177
1424
  cls.QueryBuilder = class extends cls.BaseBuilder {
1178
1425
  blocks;
1179
1426
  constructor(options, blocks) {
1180
1427
  super(options);
1181
1428
  this.blocks = blocks || [];
1182
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
+ });
1183
1436
  const exposedMethods = block.exposedMethods();
1184
1437
  for (const methodName in exposedMethods) {
1185
1438
  const methodBody = exposedMethods[methodName];
@@ -1188,7 +1441,10 @@ function _buildSquel(flavour = null) {
1188
1441
  }
1189
1442
  ((b, name, body) => {
1190
1443
  this[name] = (...args) => {
1191
- body.call(b, ...args);
1444
+ const ret = body.call(b, ...args);
1445
+ if (ret !== undefined && ret !== b) {
1446
+ return ret;
1447
+ }
1192
1448
  return this;
1193
1449
  };
1194
1450
  })(block, methodName, methodBody);
@@ -1244,6 +1500,7 @@ function _buildSquel(flavour = null) {
1244
1500
  cls.Select = class extends cls.QueryBuilder {
1245
1501
  constructor(options, blocks = null) {
1246
1502
  blocks = blocks || [
1503
+ new cls.WithBlock(options),
1247
1504
  new cls.StringBlock(options, "SELECT"),
1248
1505
  new cls.FunctionBlock(options),
1249
1506
  new cls.DistinctBlock(options),
@@ -1265,12 +1522,14 @@ function _buildSquel(flavour = null) {
1265
1522
  cls.Update = class extends cls.QueryBuilder {
1266
1523
  constructor(options, blocks = null) {
1267
1524
  blocks = blocks || [
1525
+ new cls.WithBlock(options),
1268
1526
  new cls.StringBlock(options, "UPDATE"),
1269
1527
  new cls.UpdateTableBlock(options),
1270
1528
  new cls.SetFieldBlock(options),
1271
1529
  new cls.WhereBlock(options),
1272
1530
  new cls.OrderByBlock(options),
1273
- new cls.LimitBlock(options)
1531
+ new cls.LimitBlock(options),
1532
+ new cls.ReturningBlock(options)
1274
1533
  ];
1275
1534
  super(options, blocks);
1276
1535
  }
@@ -1278,13 +1537,15 @@ function _buildSquel(flavour = null) {
1278
1537
  cls.Delete = class extends cls.QueryBuilder {
1279
1538
  constructor(options, blocks = null) {
1280
1539
  blocks = blocks || [
1540
+ new cls.WithBlock(options),
1281
1541
  new cls.StringBlock(options, "DELETE"),
1282
1542
  new cls.TargetTableBlock(options),
1283
1543
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
1284
1544
  new cls.JoinBlock(options),
1285
1545
  new cls.WhereBlock(options),
1286
1546
  new cls.OrderByBlock(options),
1287
- new cls.LimitBlock(options)
1547
+ new cls.LimitBlock(options),
1548
+ new cls.ReturningBlock(options)
1288
1549
  ];
1289
1550
  super(options, blocks);
1290
1551
  }
@@ -1292,10 +1553,12 @@ function _buildSquel(flavour = null) {
1292
1553
  cls.Insert = class extends cls.QueryBuilder {
1293
1554
  constructor(options, blocks = null) {
1294
1555
  blocks = blocks || [
1556
+ new cls.WithBlock(options),
1295
1557
  new cls.StringBlock(options, "INSERT"),
1296
1558
  new cls.IntoTableBlock(options),
1297
1559
  new cls.InsertFieldValueBlock(options),
1298
- new cls.InsertFieldsFromQueryBlock(options)
1560
+ new cls.InsertFieldsFromQueryBlock(options),
1561
+ new cls.ReturningBlock(options)
1299
1562
  ];
1300
1563
  super(options, blocks);
1301
1564
  }
@@ -1319,6 +1582,8 @@ function _buildSquel(flavour = null) {
1319
1582
  inst.function(...args);
1320
1583
  return inst;
1321
1584
  },
1585
+ over: (funcExpr, ...funcParams) => new cls.Over(funcExpr, funcParams),
1586
+ jsonExtract: (field, path) => new cls.JsonExtract(field, path),
1322
1587
  registerValueHandler: cls.registerValueHandler
1323
1588
  };
1324
1589
  _squel.remove = _squel.delete;
@@ -1344,10 +1609,40 @@ var core_default = squel;
1344
1609
  // src/mysql.ts
1345
1610
  squel.flavours.mysql = (_squel) => {
1346
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
+ }
1347
1621
  cls.MysqlOnDuplicateKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1348
1622
  onDupUpdate(field, value, options) {
1349
1623
  this._set(field, value, options);
1350
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
+ }
1351
1646
  _toParamString(options = {}) {
1352
1647
  let totalStr = "";
1353
1648
  const totalValues = [];
@@ -1376,6 +1671,7 @@ squel.flavours.mysql = (_squel) => {
1376
1671
  cls.Insert = class extends cls.QueryBuilder {
1377
1672
  constructor(options, blocks = null) {
1378
1673
  blocks = blocks || [
1674
+ new cls.WithBlock(options),
1379
1675
  new cls.StringBlock(options, "INSERT"),
1380
1676
  new cls.IntoTableBlock(options),
1381
1677
  new cls.InsertFieldValueBlock(options),
@@ -1388,6 +1684,7 @@ squel.flavours.mysql = (_squel) => {
1388
1684
  cls.Replace = class extends cls.QueryBuilder {
1389
1685
  constructor(options, blocks = null) {
1390
1686
  blocks = blocks || [
1687
+ new cls.WithBlock(options),
1391
1688
  new cls.StringBlock(options, "REPLACE"),
1392
1689
  new cls.IntoTableBlock(options),
1393
1690
  new cls.InsertFieldValueBlock(options),
@@ -1406,6 +1703,15 @@ squel.flavours.postgres = (_squel) => {
1406
1703
  cls.DefaultQueryBuilderOptions.numberedParametersStartAt = 1;
1407
1704
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1408
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
+ }
1409
1715
  cls.PostgresOnConflictKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1410
1716
  _onConflict;
1411
1717
  _dupFields;
@@ -1416,17 +1722,46 @@ squel.flavours.postgres = (_squel) => {
1416
1722
  }
1417
1723
  onConflict(conflictFields, fields) {
1418
1724
  this._onConflict = true;
1419
- if (!conflictFields)
1420
- return;
1421
- if (!_isArray(conflictFields)) {
1422
- conflictFields = [conflictFields];
1725
+ if (conflictFields) {
1726
+ if (!_isArray(conflictFields)) {
1727
+ conflictFields = [conflictFields];
1728
+ }
1729
+ this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1423
1730
  }
1424
- this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1425
1731
  if (fields) {
1426
1732
  Object.keys(fields).forEach((key) => {
1427
1733
  this._set(key, fields[key]);
1428
1734
  });
1429
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;
1430
1765
  }
1431
1766
  _toParamString(options = {}) {
1432
1767
  let totalStr = "";
@@ -1456,69 +1791,6 @@ squel.flavours.postgres = (_squel) => {
1456
1791
  return returned;
1457
1792
  }
1458
1793
  };
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
1794
  cls.UsingBlock = class extends cls.AbstractTableBlock {
1523
1795
  constructor(options) {
1524
1796
  super({ ...options, prefix: "USING" });
@@ -1632,6 +1904,7 @@ squel.flavours.mssql = (_squel) => {
1632
1904
  cls.DefaultQueryBuilderOptions.replaceSingleQuotes = true;
1633
1905
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1634
1906
  cls.DefaultQueryBuilderOptions.numberedParametersPrefix = "@";
1907
+ cls.DefaultQueryBuilderOptions.useRecursiveKeyword = false;
1635
1908
  _squel.registerValueHandler(Date, (value) => {
1636
1909
  const date = value;
1637
1910
  return `'${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()} ${date.getUTCHours()}:${date.getUTCMinutes()}:${date.getUTCSeconds()}'`;
@@ -1731,19 +2004,36 @@ squel.flavours.mssql = (_squel) => {
1731
2004
  super(options);
1732
2005
  this._outputs = [];
1733
2006
  }
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)}`);
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);
1740
2023
  });
1741
2024
  }
1742
2025
  }
1743
2026
  _toParamString(options) {
1744
2027
  const ret = super._toParamString(options);
1745
2028
  if (ret.text.length && this._outputs.length > 0) {
1746
- 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(", ")} `;
1747
2037
  const valuesPos = ret.text.indexOf("VALUES");
1748
2038
  ret.text = ret.text.substring(0, valuesPos) + innerStr + ret.text.substring(valuesPos);
1749
2039
  }
@@ -1788,6 +2078,7 @@ squel.flavours.mssql = (_squel) => {
1788
2078
  constructor(options, blocks = null) {
1789
2079
  const limitOffsetTopBlock = new cls.MssqlLimitOffsetTopBlock(options);
1790
2080
  blocks = blocks || [
2081
+ new cls.WithBlock(options),
1791
2082
  new cls.StringBlock(options, "SELECT"),
1792
2083
  new cls.DistinctBlock(options),
1793
2084
  limitOffsetTopBlock.TOP(),
@@ -1808,6 +2099,7 @@ squel.flavours.mssql = (_squel) => {
1808
2099
  cls.Update = class extends cls.QueryBuilder {
1809
2100
  constructor(options, blocks = null) {
1810
2101
  blocks = blocks || [
2102
+ new cls.WithBlock(options),
1811
2103
  new cls.StringBlock(options, "UPDATE"),
1812
2104
  new cls.MssqlUpdateTopBlock(options),
1813
2105
  new cls.UpdateTableBlock(options),
@@ -1821,6 +2113,7 @@ squel.flavours.mssql = (_squel) => {
1821
2113
  cls.Delete = class extends cls.QueryBuilder {
1822
2114
  constructor(options, blocks = null) {
1823
2115
  blocks = blocks || [
2116
+ new cls.WithBlock(options),
1824
2117
  new cls.StringBlock(options, "DELETE"),
1825
2118
  new cls.TargetTableBlock(options),
1826
2119
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
@@ -1836,6 +2129,7 @@ squel.flavours.mssql = (_squel) => {
1836
2129
  cls.Insert = class extends cls.QueryBuilder {
1837
2130
  constructor(options, blocks = null) {
1838
2131
  blocks = blocks || [
2132
+ new cls.WithBlock(options),
1839
2133
  new cls.StringBlock(options, "INSERT"),
1840
2134
  new cls.IntoTableBlock(options),
1841
2135
  new cls.MssqlInsertFieldValueBlock(options),
@@ -1844,9 +2138,202 @@ squel.flavours.mssql = (_squel) => {
1844
2138
  super(options, blocks);
1845
2139
  }
1846
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);
1847
2334
  };
1848
2335
 
1849
2336
  // src/index.ts
1850
2337
  var src_default = core_default;
1851
2338
 
1852
- //# debugId=C017CD4CA2D6F7B164756E2164756E21
2339
+ //# debugId=4D152D45BD38372364756E2164756E21