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/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "squel",
4
- version: "6.2.0",
4
+ version: "6.2.1",
5
5
  description: "SQL query string builder",
6
6
  keywords: [
7
7
  "sql",
@@ -107,7 +107,7 @@ function _clone(src) {
107
107
  if (_isPlainObject(src) || _isArray(src)) {
108
108
  const ret = new anySrc.constructor;
109
109
  for (const key of Object.getOwnPropertyNames(src)) {
110
- if (typeof anySrc[key] !== "function") {
110
+ if (typeof anySrc[key] !== "function" && key !== "_queryBuilder") {
111
111
  ret[key] = _clone(anySrc[key]);
112
112
  }
113
113
  }
@@ -530,6 +530,178 @@ function _buildSquel(flavour = null) {
530
530
  return { text: totalStr, values: totalValues };
531
531
  }
532
532
  };
533
+ cls.Over = class extends cls.BaseBuilder {
534
+ _funcExpr;
535
+ _funcParams;
536
+ _partitionFields;
537
+ _orderFields;
538
+ _rows;
539
+ _range;
540
+ constructor(funcExpr, funcParams = [], options) {
541
+ super(options);
542
+ this._funcExpr = funcExpr;
543
+ this._funcParams = funcParams || [];
544
+ this._partitionFields = [];
545
+ this._orderFields = [];
546
+ this._rows = null;
547
+ this._range = null;
548
+ }
549
+ partitionBy(...fields) {
550
+ let flatFields = [];
551
+ for (const field of fields) {
552
+ if (_isArray(field)) {
553
+ flatFields = flatFields.concat(field);
554
+ } else {
555
+ flatFields.push(field);
556
+ }
557
+ }
558
+ for (const field of flatFields) {
559
+ this._partitionFields.push(this._sanitizeField(field));
560
+ }
561
+ return this;
562
+ }
563
+ orderBy(field, dir, ...values) {
564
+ field = this._sanitizeField(field);
565
+ let direction;
566
+ if (typeof dir === "string") {
567
+ direction = dir;
568
+ } else if (dir === undefined) {
569
+ direction = "ASC";
570
+ } else if (dir === null) {
571
+ direction = null;
572
+ } else {
573
+ direction = dir ? "ASC" : "DESC";
574
+ }
575
+ this._orderFields.push({ field, dir: direction, values: values || [] });
576
+ return this;
577
+ }
578
+ rowsBetween(start, end) {
579
+ if (end === undefined) {
580
+ this._rows = `ROWS BETWEEN ${start}`;
581
+ } else {
582
+ this._rows = `ROWS BETWEEN ${start} AND ${end}`;
583
+ }
584
+ this._range = null;
585
+ return this;
586
+ }
587
+ rangeBetween(start, end) {
588
+ if (end === undefined) {
589
+ this._range = `RANGE BETWEEN ${start}`;
590
+ } else {
591
+ this._range = `RANGE BETWEEN ${start} AND ${end}`;
592
+ }
593
+ this._rows = null;
594
+ return this;
595
+ }
596
+ _toParamString(options = {}) {
597
+ const values = [];
598
+ let funcRet;
599
+ if (cls.isSquelBuilder(this._funcExpr)) {
600
+ funcRet = this._funcExpr._toParamString({
601
+ buildParameterized: options.buildParameterized
602
+ });
603
+ } else {
604
+ funcRet = this._buildString(this._funcExpr, this._funcParams, {
605
+ buildParameterized: options.buildParameterized
606
+ });
607
+ }
608
+ funcRet.values.forEach((v) => values.push(v));
609
+ let overPartsStr = "";
610
+ if (this._partitionFields.length > 0) {
611
+ let partitionStr = "";
612
+ for (const field of this._partitionFields) {
613
+ partitionStr = _pad(partitionStr, ", ");
614
+ if (cls.isSquelBuilder(field)) {
615
+ const ret = field._toParamString({
616
+ buildParameterized: options.buildParameterized
617
+ });
618
+ partitionStr += ret.text;
619
+ ret.values.forEach((v) => values.push(v));
620
+ } else {
621
+ partitionStr += this._formatFieldName(field);
622
+ }
623
+ }
624
+ overPartsStr = `PARTITION BY ${partitionStr}`;
625
+ }
626
+ if (this._orderFields.length > 0) {
627
+ let orderStr = "";
628
+ for (const { field, dir, values: orderVals } of this._orderFields) {
629
+ orderStr = _pad(orderStr, ", ");
630
+ let ret;
631
+ if (cls.isSquelBuilder(field)) {
632
+ ret = field._toParamString({
633
+ buildParameterized: options.buildParameterized
634
+ });
635
+ } else {
636
+ ret = this._buildString(field, orderVals, {
637
+ buildParameterized: options.buildParameterized
638
+ });
639
+ }
640
+ orderStr += ret.text;
641
+ ret.values.forEach((v) => values.push(v));
642
+ if (dir !== null) {
643
+ orderStr += ` ${dir}`;
644
+ }
645
+ }
646
+ overPartsStr = _pad(overPartsStr, " ") + `ORDER BY ${orderStr}`;
647
+ }
648
+ const frameClause = this._rows || this._range;
649
+ if (frameClause) {
650
+ overPartsStr = _pad(overPartsStr, " ") + frameClause;
651
+ }
652
+ return {
653
+ text: `${funcRet.text} OVER (${overPartsStr})`,
654
+ values
655
+ };
656
+ }
657
+ };
658
+ cls.JsonExtract = class extends cls.BaseBuilder {
659
+ _field;
660
+ _path;
661
+ constructor(field, path, options) {
662
+ super(options);
663
+ this._field = field;
664
+ this._path = path;
665
+ }
666
+ _toParamString(options = {}) {
667
+ const values = [];
668
+ let fieldStr = "";
669
+ if (cls.isSquelBuilder(this._field)) {
670
+ const ret = this._field._toParamString({
671
+ buildParameterized: options.buildParameterized
672
+ });
673
+ fieldStr = ret.text;
674
+ ret.values.forEach((v) => values.push(v));
675
+ } else {
676
+ fieldStr = this._formatFieldName(this._field);
677
+ }
678
+ let cleanPath = this._path;
679
+ if (cleanPath.startsWith("$")) {
680
+ cleanPath = cleanPath.slice(1);
681
+ }
682
+ if (cleanPath.startsWith(".")) {
683
+ cleanPath = cleanPath.slice(1);
684
+ }
685
+ const parts = cleanPath.split(".").filter(Boolean);
686
+ let sql = "";
687
+ if (flavour === "postgres") {
688
+ if (parts.length === 0) {
689
+ sql = fieldStr;
690
+ } else {
691
+ sql = fieldStr;
692
+ for (let i = 0;i < parts.length; i++) {
693
+ const op = i === parts.length - 1 ? "->>" : "->";
694
+ sql += `${op}'${parts[i]}'`;
695
+ }
696
+ }
697
+ } else if (flavour === "mssql") {
698
+ sql = `JSON_VALUE(${fieldStr}, '${this._path}')`;
699
+ } else {
700
+ sql = `json_extract(${fieldStr}, '${this._path}')`;
701
+ }
702
+ return { text: sql, values };
703
+ }
704
+ };
533
705
  cls.Block = class extends cls.BaseBuilder {
534
706
  constructor(options) {
535
707
  super(options);
@@ -1129,12 +1301,93 @@ function _buildSquel(flavour = null) {
1129
1301
  };
1130
1302
  }
1131
1303
  };
1304
+ cls.WithBlock = class extends cls.Block {
1305
+ _tables;
1306
+ constructor(options) {
1307
+ super(options);
1308
+ this._tables = [];
1309
+ }
1310
+ with(alias, table) {
1311
+ this._tables.push({ alias, table, recursive: false });
1312
+ }
1313
+ withRecursive(alias, table) {
1314
+ this._tables.push({ alias, table, recursive: true });
1315
+ }
1316
+ _toParamString(options = {}) {
1317
+ const parts = [];
1318
+ const values = [];
1319
+ let anyRecursive = false;
1320
+ for (const { alias, table, recursive } of this._tables) {
1321
+ if (recursive) {
1322
+ anyRecursive = true;
1323
+ }
1324
+ const ret = table._toParamString({
1325
+ buildParameterized: options.buildParameterized,
1326
+ nested: true
1327
+ });
1328
+ parts.push(`${alias} AS ${ret.text}`);
1329
+ ret.values.forEach((v) => values.push(v));
1330
+ }
1331
+ if (!parts.length) {
1332
+ return { text: "", values: [] };
1333
+ }
1334
+ const isMssql = this.options.useRecursiveKeyword === false;
1335
+ const prefix = anyRecursive && !isMssql ? "WITH RECURSIVE" : "WITH";
1336
+ return {
1337
+ text: `${prefix} ${parts.join(", ")}`,
1338
+ values
1339
+ };
1340
+ }
1341
+ };
1342
+ cls.ReturningBlock = class extends cls.Block {
1343
+ _fields;
1344
+ constructor(options) {
1345
+ super(options);
1346
+ this._fields = [];
1347
+ }
1348
+ returning(field, alias = null, options = {}) {
1349
+ alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1350
+ field = this._sanitizeField(field);
1351
+ const existingField = this._fields.filter((f) => f.name === field && f.alias === alias);
1352
+ if (existingField.length)
1353
+ return this;
1354
+ this._fields.push({ name: field, alias, options });
1355
+ }
1356
+ _toParamString(options = {}) {
1357
+ const { buildParameterized } = options;
1358
+ let totalStr = "";
1359
+ const totalValues = [];
1360
+ for (const field of this._fields) {
1361
+ totalStr = _pad(totalStr, ", ");
1362
+ const { name, alias, options: fieldOptions } = field;
1363
+ if (typeof name === "string") {
1364
+ totalStr += this._formatFieldName(name, fieldOptions);
1365
+ } else {
1366
+ const ret = name._toParamString({ nested: true, buildParameterized });
1367
+ totalStr += ret.text;
1368
+ ret.values.forEach((v) => totalValues.push(v));
1369
+ }
1370
+ if (alias)
1371
+ totalStr += ` AS ${this._formatFieldAlias(alias)}`;
1372
+ }
1373
+ return {
1374
+ text: totalStr.length > 0 ? `RETURNING ${totalStr}` : "",
1375
+ values: totalValues
1376
+ };
1377
+ }
1378
+ };
1132
1379
  cls.QueryBuilder = class extends cls.BaseBuilder {
1133
1380
  blocks;
1134
1381
  constructor(options, blocks) {
1135
1382
  super(options);
1136
1383
  this.blocks = blocks || [];
1137
1384
  for (const block of this.blocks) {
1385
+ Object.defineProperty(block, "_queryBuilder", {
1386
+ value: this,
1387
+ enumerable: false,
1388
+ writable: true,
1389
+ configurable: true
1390
+ });
1138
1391
  const exposedMethods = block.exposedMethods();
1139
1392
  for (const methodName in exposedMethods) {
1140
1393
  const methodBody = exposedMethods[methodName];
@@ -1143,7 +1396,10 @@ function _buildSquel(flavour = null) {
1143
1396
  }
1144
1397
  ((b, name, body) => {
1145
1398
  this[name] = (...args) => {
1146
- body.call(b, ...args);
1399
+ const ret = body.call(b, ...args);
1400
+ if (ret !== undefined && ret !== b) {
1401
+ return ret;
1402
+ }
1147
1403
  return this;
1148
1404
  };
1149
1405
  })(block, methodName, methodBody);
@@ -1199,6 +1455,7 @@ function _buildSquel(flavour = null) {
1199
1455
  cls.Select = class extends cls.QueryBuilder {
1200
1456
  constructor(options, blocks = null) {
1201
1457
  blocks = blocks || [
1458
+ new cls.WithBlock(options),
1202
1459
  new cls.StringBlock(options, "SELECT"),
1203
1460
  new cls.FunctionBlock(options),
1204
1461
  new cls.DistinctBlock(options),
@@ -1220,12 +1477,14 @@ function _buildSquel(flavour = null) {
1220
1477
  cls.Update = class extends cls.QueryBuilder {
1221
1478
  constructor(options, blocks = null) {
1222
1479
  blocks = blocks || [
1480
+ new cls.WithBlock(options),
1223
1481
  new cls.StringBlock(options, "UPDATE"),
1224
1482
  new cls.UpdateTableBlock(options),
1225
1483
  new cls.SetFieldBlock(options),
1226
1484
  new cls.WhereBlock(options),
1227
1485
  new cls.OrderByBlock(options),
1228
- new cls.LimitBlock(options)
1486
+ new cls.LimitBlock(options),
1487
+ new cls.ReturningBlock(options)
1229
1488
  ];
1230
1489
  super(options, blocks);
1231
1490
  }
@@ -1233,13 +1492,15 @@ function _buildSquel(flavour = null) {
1233
1492
  cls.Delete = class extends cls.QueryBuilder {
1234
1493
  constructor(options, blocks = null) {
1235
1494
  blocks = blocks || [
1495
+ new cls.WithBlock(options),
1236
1496
  new cls.StringBlock(options, "DELETE"),
1237
1497
  new cls.TargetTableBlock(options),
1238
1498
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
1239
1499
  new cls.JoinBlock(options),
1240
1500
  new cls.WhereBlock(options),
1241
1501
  new cls.OrderByBlock(options),
1242
- new cls.LimitBlock(options)
1502
+ new cls.LimitBlock(options),
1503
+ new cls.ReturningBlock(options)
1243
1504
  ];
1244
1505
  super(options, blocks);
1245
1506
  }
@@ -1247,10 +1508,12 @@ function _buildSquel(flavour = null) {
1247
1508
  cls.Insert = class extends cls.QueryBuilder {
1248
1509
  constructor(options, blocks = null) {
1249
1510
  blocks = blocks || [
1511
+ new cls.WithBlock(options),
1250
1512
  new cls.StringBlock(options, "INSERT"),
1251
1513
  new cls.IntoTableBlock(options),
1252
1514
  new cls.InsertFieldValueBlock(options),
1253
- new cls.InsertFieldsFromQueryBlock(options)
1515
+ new cls.InsertFieldsFromQueryBlock(options),
1516
+ new cls.ReturningBlock(options)
1254
1517
  ];
1255
1518
  super(options, blocks);
1256
1519
  }
@@ -1274,6 +1537,8 @@ function _buildSquel(flavour = null) {
1274
1537
  inst.function(...args);
1275
1538
  return inst;
1276
1539
  },
1540
+ over: (funcExpr, ...funcParams) => new cls.Over(funcExpr, funcParams),
1541
+ jsonExtract: (field, path) => new cls.JsonExtract(field, path),
1277
1542
  registerValueHandler: cls.registerValueHandler
1278
1543
  };
1279
1544
  _squel.remove = _squel.delete;
@@ -1299,10 +1564,40 @@ var core_default = squel;
1299
1564
  // src/mysql.ts
1300
1565
  squel.flavours.mysql = (_squel) => {
1301
1566
  const cls = _squel.cls;
1567
+
1568
+ class MysqlOnDuplicateKeyUpdateHelper {
1569
+ builder;
1570
+ block;
1571
+ constructor(builder, block) {
1572
+ this.builder = builder;
1573
+ this.block = block;
1574
+ }
1575
+ }
1302
1576
  cls.MysqlOnDuplicateKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1303
1577
  onDupUpdate(field, value, options) {
1304
1578
  this._set(field, value, options);
1305
1579
  }
1580
+ onDuplicateKeyUpdate() {
1581
+ const helper = new MysqlOnDuplicateKeyUpdateHelper(this._queryBuilder, this);
1582
+ return new Proxy(helper, {
1583
+ get(target, prop, receiver) {
1584
+ if (prop === "set") {
1585
+ return (field, value, options) => {
1586
+ target.block._set(field, value, options);
1587
+ return receiver;
1588
+ };
1589
+ }
1590
+ const val = target.builder[prop];
1591
+ if (typeof val === "function") {
1592
+ return (...args) => {
1593
+ const ret = val.apply(target.builder, args);
1594
+ return ret === target.builder ? receiver : ret;
1595
+ };
1596
+ }
1597
+ return val;
1598
+ }
1599
+ });
1600
+ }
1306
1601
  _toParamString(options = {}) {
1307
1602
  let totalStr = "";
1308
1603
  const totalValues = [];
@@ -1331,6 +1626,7 @@ squel.flavours.mysql = (_squel) => {
1331
1626
  cls.Insert = class extends cls.QueryBuilder {
1332
1627
  constructor(options, blocks = null) {
1333
1628
  blocks = blocks || [
1629
+ new cls.WithBlock(options),
1334
1630
  new cls.StringBlock(options, "INSERT"),
1335
1631
  new cls.IntoTableBlock(options),
1336
1632
  new cls.InsertFieldValueBlock(options),
@@ -1343,6 +1639,7 @@ squel.flavours.mysql = (_squel) => {
1343
1639
  cls.Replace = class extends cls.QueryBuilder {
1344
1640
  constructor(options, blocks = null) {
1345
1641
  blocks = blocks || [
1642
+ new cls.WithBlock(options),
1346
1643
  new cls.StringBlock(options, "REPLACE"),
1347
1644
  new cls.IntoTableBlock(options),
1348
1645
  new cls.InsertFieldValueBlock(options),
@@ -1361,6 +1658,15 @@ squel.flavours.postgres = (_squel) => {
1361
1658
  cls.DefaultQueryBuilderOptions.numberedParametersStartAt = 1;
1362
1659
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1363
1660
  cls.DefaultQueryBuilderOptions.useAsForTableAliasNames = true;
1661
+
1662
+ class PostgresOnConflictUpdateHelper {
1663
+ builder;
1664
+ block;
1665
+ constructor(builder, block) {
1666
+ this.builder = builder;
1667
+ this.block = block;
1668
+ }
1669
+ }
1364
1670
  cls.PostgresOnConflictKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1365
1671
  _onConflict;
1366
1672
  _dupFields;
@@ -1371,17 +1677,46 @@ squel.flavours.postgres = (_squel) => {
1371
1677
  }
1372
1678
  onConflict(conflictFields, fields) {
1373
1679
  this._onConflict = true;
1374
- if (!conflictFields)
1375
- return;
1376
- if (!_isArray(conflictFields)) {
1377
- conflictFields = [conflictFields];
1680
+ if (conflictFields) {
1681
+ if (!_isArray(conflictFields)) {
1682
+ conflictFields = [conflictFields];
1683
+ }
1684
+ this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1378
1685
  }
1379
- this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1380
1686
  if (fields) {
1381
1687
  Object.keys(fields).forEach((key) => {
1382
1688
  this._set(key, fields[key]);
1383
1689
  });
1384
1690
  }
1691
+ return this._queryBuilder;
1692
+ }
1693
+ doUpdate() {
1694
+ const helper = new PostgresOnConflictUpdateHelper(this._queryBuilder, this);
1695
+ return new Proxy(helper, {
1696
+ get(target, prop, receiver) {
1697
+ if (prop === "set") {
1698
+ return (field, value, options) => {
1699
+ target.block._set(field, value, options);
1700
+ return receiver;
1701
+ };
1702
+ }
1703
+ const val = target.builder[prop];
1704
+ if (typeof val === "function") {
1705
+ return (...args) => {
1706
+ const ret = val.apply(target.builder, args);
1707
+ return ret === target.builder ? receiver : ret;
1708
+ };
1709
+ }
1710
+ return val;
1711
+ }
1712
+ });
1713
+ }
1714
+ doNothing() {
1715
+ this._onConflict = true;
1716
+ this._fields = [];
1717
+ this._values = [[]];
1718
+ this._valueOptions = [[]];
1719
+ return this._queryBuilder;
1385
1720
  }
1386
1721
  _toParamString(options = {}) {
1387
1722
  let totalStr = "";
@@ -1411,69 +1746,6 @@ squel.flavours.postgres = (_squel) => {
1411
1746
  return returned;
1412
1747
  }
1413
1748
  };
1414
- cls.ReturningBlock = class extends cls.Block {
1415
- _fields;
1416
- constructor(options) {
1417
- super(options);
1418
- this._fields = [];
1419
- }
1420
- returning(field, alias = null, options = {}) {
1421
- alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1422
- field = this._sanitizeField(field);
1423
- const existingField = this._fields.filter((f) => f.name === field && f.alias === alias);
1424
- if (existingField.length)
1425
- return this;
1426
- this._fields.push({ name: field, alias, options });
1427
- }
1428
- _toParamString(options = {}) {
1429
- const { buildParameterized } = options;
1430
- let totalStr = "";
1431
- const totalValues = [];
1432
- for (const field of this._fields) {
1433
- totalStr = _pad(totalStr, ", ");
1434
- const { name, alias, options: fieldOptions } = field;
1435
- if (typeof name === "string") {
1436
- totalStr += this._formatFieldName(name, fieldOptions);
1437
- } else {
1438
- const ret = name._toParamString({ nested: true, buildParameterized });
1439
- totalStr += ret.text;
1440
- ret.values.forEach((v) => totalValues.push(v));
1441
- }
1442
- if (alias)
1443
- totalStr += ` AS ${this._formatFieldAlias(alias)}`;
1444
- }
1445
- return {
1446
- text: totalStr.length > 0 ? `RETURNING ${totalStr}` : "",
1447
- values: totalValues
1448
- };
1449
- }
1450
- };
1451
- cls.WithBlock = class extends cls.Block {
1452
- _tables;
1453
- constructor(options) {
1454
- super(options);
1455
- this._tables = [];
1456
- }
1457
- with(alias, table) {
1458
- this._tables.push({ alias, table });
1459
- }
1460
- _toParamString(options = {}) {
1461
- const parts = [];
1462
- const values = [];
1463
- for (const { alias, table } of this._tables) {
1464
- const ret = table._toParamString({
1465
- buildParameterized: options.buildParameterized,
1466
- nested: true
1467
- });
1468
- parts.push(`${alias} AS ${ret.text}`);
1469
- ret.values.forEach((v) => values.push(v));
1470
- }
1471
- return {
1472
- text: parts.length ? `WITH ${parts.join(", ")}` : "",
1473
- values
1474
- };
1475
- }
1476
- };
1477
1749
  cls.UsingBlock = class extends cls.AbstractTableBlock {
1478
1750
  constructor(options) {
1479
1751
  super({ ...options, prefix: "USING" });
@@ -1587,6 +1859,7 @@ squel.flavours.mssql = (_squel) => {
1587
1859
  cls.DefaultQueryBuilderOptions.replaceSingleQuotes = true;
1588
1860
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1589
1861
  cls.DefaultQueryBuilderOptions.numberedParametersPrefix = "@";
1862
+ cls.DefaultQueryBuilderOptions.useRecursiveKeyword = false;
1590
1863
  _squel.registerValueHandler(Date, (value) => {
1591
1864
  const date = value;
1592
1865
  return `'${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()} ${date.getUTCHours()}:${date.getUTCMinutes()}:${date.getUTCSeconds()}'`;
@@ -1686,19 +1959,36 @@ squel.flavours.mssql = (_squel) => {
1686
1959
  super(options);
1687
1960
  this._outputs = [];
1688
1961
  }
1689
- output(fields) {
1690
- if (typeof fields === "string") {
1691
- this._outputs.push(`INSERTED.${this._sanitizeField(fields)}`);
1692
- } else {
1693
- fields.forEach((f) => {
1694
- this._outputs.push(`INSERTED.${this._sanitizeField(f)}`);
1962
+ outputs(outputs) {
1963
+ for (const output in outputs) {
1964
+ this.output(output, outputs[output]);
1965
+ }
1966
+ }
1967
+ output(output, alias = null) {
1968
+ if (typeof output === "string") {
1969
+ output = this._sanitizeField(output);
1970
+ alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1971
+ this._outputs.push({
1972
+ name: `INSERTED.${output}`,
1973
+ alias
1974
+ });
1975
+ } else if (Array.isArray(output)) {
1976
+ output.forEach((f) => {
1977
+ this.output(f);
1695
1978
  });
1696
1979
  }
1697
1980
  }
1698
1981
  _toParamString(options) {
1699
1982
  const ret = super._toParamString(options);
1700
1983
  if (ret.text.length && this._outputs.length > 0) {
1701
- const innerStr = `OUTPUT ${this._outputs.join(", ")} `;
1984
+ const parts = this._outputs.map((o) => {
1985
+ let str = o.name;
1986
+ if (o.alias) {
1987
+ str += ` AS ${this._formatFieldAlias(o.alias)}`;
1988
+ }
1989
+ return str;
1990
+ });
1991
+ const innerStr = `OUTPUT ${parts.join(", ")} `;
1702
1992
  const valuesPos = ret.text.indexOf("VALUES");
1703
1993
  ret.text = ret.text.substring(0, valuesPos) + innerStr + ret.text.substring(valuesPos);
1704
1994
  }
@@ -1743,6 +2033,7 @@ squel.flavours.mssql = (_squel) => {
1743
2033
  constructor(options, blocks = null) {
1744
2034
  const limitOffsetTopBlock = new cls.MssqlLimitOffsetTopBlock(options);
1745
2035
  blocks = blocks || [
2036
+ new cls.WithBlock(options),
1746
2037
  new cls.StringBlock(options, "SELECT"),
1747
2038
  new cls.DistinctBlock(options),
1748
2039
  limitOffsetTopBlock.TOP(),
@@ -1763,6 +2054,7 @@ squel.flavours.mssql = (_squel) => {
1763
2054
  cls.Update = class extends cls.QueryBuilder {
1764
2055
  constructor(options, blocks = null) {
1765
2056
  blocks = blocks || [
2057
+ new cls.WithBlock(options),
1766
2058
  new cls.StringBlock(options, "UPDATE"),
1767
2059
  new cls.MssqlUpdateTopBlock(options),
1768
2060
  new cls.UpdateTableBlock(options),
@@ -1776,6 +2068,7 @@ squel.flavours.mssql = (_squel) => {
1776
2068
  cls.Delete = class extends cls.QueryBuilder {
1777
2069
  constructor(options, blocks = null) {
1778
2070
  blocks = blocks || [
2071
+ new cls.WithBlock(options),
1779
2072
  new cls.StringBlock(options, "DELETE"),
1780
2073
  new cls.TargetTableBlock(options),
1781
2074
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
@@ -1791,6 +2084,7 @@ squel.flavours.mssql = (_squel) => {
1791
2084
  cls.Insert = class extends cls.QueryBuilder {
1792
2085
  constructor(options, blocks = null) {
1793
2086
  blocks = blocks || [
2087
+ new cls.WithBlock(options),
1794
2088
  new cls.StringBlock(options, "INSERT"),
1795
2089
  new cls.IntoTableBlock(options),
1796
2090
  new cls.MssqlInsertFieldValueBlock(options),
@@ -1799,6 +2093,199 @@ squel.flavours.mssql = (_squel) => {
1799
2093
  super(options, blocks);
1800
2094
  }
1801
2095
  };
2096
+ cls.MergeIntoBlock = class extends cls.Block {
2097
+ _table = null;
2098
+ _alias = null;
2099
+ into(table, alias = null) {
2100
+ this._table = this._sanitizeTable(table);
2101
+ this._alias = alias ? this._sanitizeTableAlias(alias) : null;
2102
+ }
2103
+ _toParamString() {
2104
+ if (!this._table)
2105
+ throw new Error("into() needs to be called");
2106
+ let str = this._formatTableName(this._table);
2107
+ if (this._alias) {
2108
+ str += ` AS ${this._formatTableAlias(this._alias)}`;
2109
+ }
2110
+ return { text: str, values: [] };
2111
+ }
2112
+ };
2113
+ cls.MergeUsingBlock = class extends cls.Block {
2114
+ _source = null;
2115
+ _alias = null;
2116
+ _condition = null;
2117
+ using(source, alias = null, condition = null) {
2118
+ this._source = typeof source === "string" ? this._sanitizeTable(source) : this._sanitizeBaseBuilder(source);
2119
+ this._alias = alias ? this._sanitizeTableAlias(alias) : null;
2120
+ this._condition = condition ? this._sanitizeExpression(condition) : null;
2121
+ }
2122
+ _toParamString(options = {}) {
2123
+ if (!this._source)
2124
+ throw new Error("using() needs to be called");
2125
+ let sourceStr = "";
2126
+ const values = [];
2127
+ if (typeof this._source === "string") {
2128
+ sourceStr = this._formatTableName(this._source);
2129
+ } else {
2130
+ const ret = this._source._toParamString({
2131
+ buildParameterized: options.buildParameterized,
2132
+ nested: true
2133
+ });
2134
+ sourceStr = ret.text;
2135
+ ret.values.forEach((v) => values.push(v));
2136
+ }
2137
+ if (this._alias) {
2138
+ sourceStr += ` AS ${this._formatTableAlias(this._alias)}`;
2139
+ }
2140
+ let conditionStr = "";
2141
+ if (this._condition) {
2142
+ let ret;
2143
+ if (typeof this._condition === "string") {
2144
+ ret = this._buildString(this._condition, [], {
2145
+ buildParameterized: options.buildParameterized
2146
+ });
2147
+ } else {
2148
+ ret = this._condition._toParamString({
2149
+ buildParameterized: options.buildParameterized
2150
+ });
2151
+ }
2152
+ conditionStr = ` ON ${this._applyNestingFormatting(ret.text)}`;
2153
+ ret.values.forEach((v) => values.push(v));
2154
+ }
2155
+ return {
2156
+ text: `USING ${sourceStr}${conditionStr}`,
2157
+ values
2158
+ };
2159
+ }
2160
+ };
2161
+
2162
+ class MergeMatchedClauseHelper {
2163
+ builder;
2164
+ clause;
2165
+ constructor(builder, clause) {
2166
+ this.builder = builder;
2167
+ this.clause = clause;
2168
+ }
2169
+ update(fields) {
2170
+ this.clause.action = { type: "UPDATE", fields };
2171
+ return this.builder;
2172
+ }
2173
+ delete() {
2174
+ this.clause.action = { type: "DELETE" };
2175
+ return this.builder;
2176
+ }
2177
+ }
2178
+
2179
+ class MergeNotMatchedClauseHelper {
2180
+ builder;
2181
+ clause;
2182
+ constructor(builder, clause) {
2183
+ this.builder = builder;
2184
+ this.clause = clause;
2185
+ }
2186
+ insert(fields) {
2187
+ this.clause.action = { type: "INSERT", fields };
2188
+ return this.builder;
2189
+ }
2190
+ }
2191
+ cls.MergeWhenBlock = class extends cls.Block {
2192
+ _clauses;
2193
+ constructor(options) {
2194
+ super(options);
2195
+ this._clauses = [];
2196
+ }
2197
+ whenMatched(condition = null) {
2198
+ const clause = { type: "MATCHED", condition, action: null };
2199
+ this._clauses.push(clause);
2200
+ return new MergeMatchedClauseHelper(this._queryBuilder, clause);
2201
+ }
2202
+ whenNotMatched(condition = null) {
2203
+ const clause = { type: "NOT_MATCHED", condition, action: null };
2204
+ this._clauses.push(clause);
2205
+ return new MergeNotMatchedClauseHelper(this._queryBuilder, clause);
2206
+ }
2207
+ _toParamString(options = {}) {
2208
+ let totalStr = "";
2209
+ const totalValues = [];
2210
+ for (const clause of this._clauses) {
2211
+ if (!clause.action)
2212
+ continue;
2213
+ totalStr = _pad(totalStr, " ");
2214
+ let condStr = "";
2215
+ if (clause.condition) {
2216
+ const ret = this._buildString(clause.condition, [], {
2217
+ buildParameterized: options.buildParameterized
2218
+ });
2219
+ condStr = ` AND ${ret.text}`;
2220
+ ret.values.forEach((v) => totalValues.push(v));
2221
+ }
2222
+ let actionStr = "";
2223
+ if (clause.action.type === "UPDATE") {
2224
+ let setStr = "";
2225
+ for (const key of Object.keys(clause.action.fields)) {
2226
+ setStr = _pad(setStr, ", ");
2227
+ const val = clause.action.fields[key];
2228
+ if (val && typeof val._toParamString === "function") {
2229
+ const ret = val._toParamString({
2230
+ buildParameterized: options.buildParameterized
2231
+ });
2232
+ setStr += `${this._formatFieldName(key)} = ${ret.text}`;
2233
+ ret.values.forEach((v) => totalValues.push(v));
2234
+ } else {
2235
+ const ret = this._buildString(`${this._formatFieldName(key)} = ${this.options.parameterCharacter}`, [val], {
2236
+ buildParameterized: options.buildParameterized
2237
+ });
2238
+ setStr += ret.text;
2239
+ ret.values.forEach((v) => totalValues.push(v));
2240
+ }
2241
+ }
2242
+ actionStr = `THEN UPDATE SET ${setStr}`;
2243
+ } else if (clause.action.type === "DELETE") {
2244
+ actionStr = "THEN DELETE";
2245
+ } else if (clause.action.type === "INSERT") {
2246
+ const cols = Object.keys(clause.action.fields).map((c) => this._formatFieldName(c)).join(", ");
2247
+ let valsStr = "";
2248
+ for (const key of Object.keys(clause.action.fields)) {
2249
+ valsStr = _pad(valsStr, ", ");
2250
+ const val = clause.action.fields[key];
2251
+ if (val && typeof val._toParamString === "function") {
2252
+ const ret = val._toParamString({
2253
+ buildParameterized: options.buildParameterized
2254
+ });
2255
+ valsStr += ret.text;
2256
+ ret.values.forEach((v) => totalValues.push(v));
2257
+ } else {
2258
+ const ret = this._buildString(this.options.parameterCharacter, [val], {
2259
+ buildParameterized: options.buildParameterized
2260
+ });
2261
+ valsStr += ret.text;
2262
+ ret.values.forEach((v) => totalValues.push(v));
2263
+ }
2264
+ }
2265
+ actionStr = `THEN INSERT (${cols}) VALUES (${valsStr})`;
2266
+ }
2267
+ const whenWord = clause.type === "MATCHED" ? "WHEN MATCHED" : "WHEN NOT MATCHED";
2268
+ totalStr += `${whenWord}${condStr} ${actionStr}`;
2269
+ }
2270
+ return {
2271
+ text: totalStr.length ? `${totalStr};` : "",
2272
+ values: totalValues
2273
+ };
2274
+ }
2275
+ };
2276
+ cls.Merge = class extends cls.QueryBuilder {
2277
+ constructor(options, blocks = null) {
2278
+ blocks = blocks || [
2279
+ new cls.WithBlock(options),
2280
+ new cls.StringBlock(options, "MERGE INTO"),
2281
+ new cls.MergeIntoBlock(options),
2282
+ new cls.MergeUsingBlock(options),
2283
+ new cls.MergeWhenBlock(options)
2284
+ ];
2285
+ super(options, blocks);
2286
+ }
2287
+ };
2288
+ _squel.merge = (options, blocks) => new cls.Merge(options, blocks);
1802
2289
  };
1803
2290
 
1804
2291
  // src/index.ts
@@ -1808,4 +2295,4 @@ export {
1808
2295
  src_default as default
1809
2296
  };
1810
2297
 
1811
- //# debugId=F51DFA53E8AD876F64756E2164756E21
2298
+ //# debugId=4FE4237F5E06625564756E2164756E21