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/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "squel",
4
- version: "6.1.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);
@@ -1113,12 +1285,109 @@ function _buildSquel(flavour = null) {
1113
1285
  return { text: totalStr, values: totalValues };
1114
1286
  }
1115
1287
  };
1288
+ cls.ForBlock = class extends cls.Block {
1289
+ _forStr;
1290
+ constructor(options) {
1291
+ super(options);
1292
+ this._forStr = null;
1293
+ }
1294
+ for(str) {
1295
+ this._forStr = str;
1296
+ }
1297
+ _toParamString() {
1298
+ return {
1299
+ text: this._forStr !== null ? `FOR ${this._forStr}` : "",
1300
+ values: []
1301
+ };
1302
+ }
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
+ };
1116
1379
  cls.QueryBuilder = class extends cls.BaseBuilder {
1117
1380
  blocks;
1118
1381
  constructor(options, blocks) {
1119
1382
  super(options);
1120
1383
  this.blocks = blocks || [];
1121
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
+ });
1122
1391
  const exposedMethods = block.exposedMethods();
1123
1392
  for (const methodName in exposedMethods) {
1124
1393
  const methodBody = exposedMethods[methodName];
@@ -1127,7 +1396,10 @@ function _buildSquel(flavour = null) {
1127
1396
  }
1128
1397
  ((b, name, body) => {
1129
1398
  this[name] = (...args) => {
1130
- body.call(b, ...args);
1399
+ const ret = body.call(b, ...args);
1400
+ if (ret !== undefined && ret !== b) {
1401
+ return ret;
1402
+ }
1131
1403
  return this;
1132
1404
  };
1133
1405
  })(block, methodName, methodBody);
@@ -1183,6 +1455,7 @@ function _buildSquel(flavour = null) {
1183
1455
  cls.Select = class extends cls.QueryBuilder {
1184
1456
  constructor(options, blocks = null) {
1185
1457
  blocks = blocks || [
1458
+ new cls.WithBlock(options),
1186
1459
  new cls.StringBlock(options, "SELECT"),
1187
1460
  new cls.FunctionBlock(options),
1188
1461
  new cls.DistinctBlock(options),
@@ -1195,7 +1468,8 @@ function _buildSquel(flavour = null) {
1195
1468
  new cls.OrderByBlock(options),
1196
1469
  new cls.LimitBlock(options),
1197
1470
  new cls.OffsetBlock(options),
1198
- new cls.UnionBlock(options)
1471
+ new cls.UnionBlock(options),
1472
+ new cls.ForBlock(options)
1199
1473
  ];
1200
1474
  super(options, blocks);
1201
1475
  }
@@ -1203,12 +1477,14 @@ function _buildSquel(flavour = null) {
1203
1477
  cls.Update = class extends cls.QueryBuilder {
1204
1478
  constructor(options, blocks = null) {
1205
1479
  blocks = blocks || [
1480
+ new cls.WithBlock(options),
1206
1481
  new cls.StringBlock(options, "UPDATE"),
1207
1482
  new cls.UpdateTableBlock(options),
1208
1483
  new cls.SetFieldBlock(options),
1209
1484
  new cls.WhereBlock(options),
1210
1485
  new cls.OrderByBlock(options),
1211
- new cls.LimitBlock(options)
1486
+ new cls.LimitBlock(options),
1487
+ new cls.ReturningBlock(options)
1212
1488
  ];
1213
1489
  super(options, blocks);
1214
1490
  }
@@ -1216,13 +1492,15 @@ function _buildSquel(flavour = null) {
1216
1492
  cls.Delete = class extends cls.QueryBuilder {
1217
1493
  constructor(options, blocks = null) {
1218
1494
  blocks = blocks || [
1495
+ new cls.WithBlock(options),
1219
1496
  new cls.StringBlock(options, "DELETE"),
1220
1497
  new cls.TargetTableBlock(options),
1221
1498
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
1222
1499
  new cls.JoinBlock(options),
1223
1500
  new cls.WhereBlock(options),
1224
1501
  new cls.OrderByBlock(options),
1225
- new cls.LimitBlock(options)
1502
+ new cls.LimitBlock(options),
1503
+ new cls.ReturningBlock(options)
1226
1504
  ];
1227
1505
  super(options, blocks);
1228
1506
  }
@@ -1230,10 +1508,12 @@ function _buildSquel(flavour = null) {
1230
1508
  cls.Insert = class extends cls.QueryBuilder {
1231
1509
  constructor(options, blocks = null) {
1232
1510
  blocks = blocks || [
1511
+ new cls.WithBlock(options),
1233
1512
  new cls.StringBlock(options, "INSERT"),
1234
1513
  new cls.IntoTableBlock(options),
1235
1514
  new cls.InsertFieldValueBlock(options),
1236
- new cls.InsertFieldsFromQueryBlock(options)
1515
+ new cls.InsertFieldsFromQueryBlock(options),
1516
+ new cls.ReturningBlock(options)
1237
1517
  ];
1238
1518
  super(options, blocks);
1239
1519
  }
@@ -1257,6 +1537,8 @@ function _buildSquel(flavour = null) {
1257
1537
  inst.function(...args);
1258
1538
  return inst;
1259
1539
  },
1540
+ over: (funcExpr, ...funcParams) => new cls.Over(funcExpr, funcParams),
1541
+ jsonExtract: (field, path) => new cls.JsonExtract(field, path),
1260
1542
  registerValueHandler: cls.registerValueHandler
1261
1543
  };
1262
1544
  _squel.remove = _squel.delete;
@@ -1282,10 +1564,40 @@ var core_default = squel;
1282
1564
  // src/mysql.ts
1283
1565
  squel.flavours.mysql = (_squel) => {
1284
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
+ }
1285
1576
  cls.MysqlOnDuplicateKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1286
1577
  onDupUpdate(field, value, options) {
1287
1578
  this._set(field, value, options);
1288
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
+ }
1289
1601
  _toParamString(options = {}) {
1290
1602
  let totalStr = "";
1291
1603
  const totalValues = [];
@@ -1314,6 +1626,7 @@ squel.flavours.mysql = (_squel) => {
1314
1626
  cls.Insert = class extends cls.QueryBuilder {
1315
1627
  constructor(options, blocks = null) {
1316
1628
  blocks = blocks || [
1629
+ new cls.WithBlock(options),
1317
1630
  new cls.StringBlock(options, "INSERT"),
1318
1631
  new cls.IntoTableBlock(options),
1319
1632
  new cls.InsertFieldValueBlock(options),
@@ -1326,6 +1639,7 @@ squel.flavours.mysql = (_squel) => {
1326
1639
  cls.Replace = class extends cls.QueryBuilder {
1327
1640
  constructor(options, blocks = null) {
1328
1641
  blocks = blocks || [
1642
+ new cls.WithBlock(options),
1329
1643
  new cls.StringBlock(options, "REPLACE"),
1330
1644
  new cls.IntoTableBlock(options),
1331
1645
  new cls.InsertFieldValueBlock(options),
@@ -1344,6 +1658,15 @@ squel.flavours.postgres = (_squel) => {
1344
1658
  cls.DefaultQueryBuilderOptions.numberedParametersStartAt = 1;
1345
1659
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1346
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
+ }
1347
1670
  cls.PostgresOnConflictKeyUpdateBlock = class extends cls.AbstractSetFieldBlock {
1348
1671
  _onConflict;
1349
1672
  _dupFields;
@@ -1354,17 +1677,46 @@ squel.flavours.postgres = (_squel) => {
1354
1677
  }
1355
1678
  onConflict(conflictFields, fields) {
1356
1679
  this._onConflict = true;
1357
- if (!conflictFields)
1358
- return;
1359
- if (!_isArray(conflictFields)) {
1360
- conflictFields = [conflictFields];
1680
+ if (conflictFields) {
1681
+ if (!_isArray(conflictFields)) {
1682
+ conflictFields = [conflictFields];
1683
+ }
1684
+ this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1361
1685
  }
1362
- this._dupFields = conflictFields.map(this._sanitizeField.bind(this));
1363
1686
  if (fields) {
1364
1687
  Object.keys(fields).forEach((key) => {
1365
1688
  this._set(key, fields[key]);
1366
1689
  });
1367
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;
1368
1720
  }
1369
1721
  _toParamString(options = {}) {
1370
1722
  let totalStr = "";
@@ -1394,69 +1746,6 @@ squel.flavours.postgres = (_squel) => {
1394
1746
  return returned;
1395
1747
  }
1396
1748
  };
1397
- cls.ReturningBlock = class extends cls.Block {
1398
- _fields;
1399
- constructor(options) {
1400
- super(options);
1401
- this._fields = [];
1402
- }
1403
- returning(field, alias = null, options = {}) {
1404
- alias = alias ? this._sanitizeFieldAlias(alias) : alias;
1405
- field = this._sanitizeField(field);
1406
- const existingField = this._fields.filter((f) => f.name === field && f.alias === alias);
1407
- if (existingField.length)
1408
- return this;
1409
- this._fields.push({ name: field, alias, options });
1410
- }
1411
- _toParamString(options = {}) {
1412
- const { buildParameterized } = options;
1413
- let totalStr = "";
1414
- const totalValues = [];
1415
- for (const field of this._fields) {
1416
- totalStr = _pad(totalStr, ", ");
1417
- const { name, alias, options: fieldOptions } = field;
1418
- if (typeof name === "string") {
1419
- totalStr += this._formatFieldName(name, fieldOptions);
1420
- } else {
1421
- const ret = name._toParamString({ nested: true, buildParameterized });
1422
- totalStr += ret.text;
1423
- ret.values.forEach((v) => totalValues.push(v));
1424
- }
1425
- if (alias)
1426
- totalStr += ` AS ${this._formatFieldAlias(alias)}`;
1427
- }
1428
- return {
1429
- text: totalStr.length > 0 ? `RETURNING ${totalStr}` : "",
1430
- values: totalValues
1431
- };
1432
- }
1433
- };
1434
- cls.WithBlock = class extends cls.Block {
1435
- _tables;
1436
- constructor(options) {
1437
- super(options);
1438
- this._tables = [];
1439
- }
1440
- with(alias, table) {
1441
- this._tables.push({ alias, table });
1442
- }
1443
- _toParamString(options = {}) {
1444
- const parts = [];
1445
- const values = [];
1446
- for (const { alias, table } of this._tables) {
1447
- const ret = table._toParamString({
1448
- buildParameterized: options.buildParameterized,
1449
- nested: true
1450
- });
1451
- parts.push(`${alias} AS ${ret.text}`);
1452
- ret.values.forEach((v) => values.push(v));
1453
- }
1454
- return {
1455
- text: parts.length ? `WITH ${parts.join(", ")}` : "",
1456
- values
1457
- };
1458
- }
1459
- };
1460
1749
  cls.UsingBlock = class extends cls.AbstractTableBlock {
1461
1750
  constructor(options) {
1462
1751
  super({ ...options, prefix: "USING" });
@@ -1505,7 +1794,8 @@ squel.flavours.postgres = (_squel) => {
1505
1794
  new cls.OrderByBlock(options),
1506
1795
  new cls.LimitBlock(options),
1507
1796
  new cls.OffsetBlock(options),
1508
- new cls.UnionBlock(options)
1797
+ new cls.UnionBlock(options),
1798
+ new cls.ForBlock(options)
1509
1799
  ];
1510
1800
  super(options, blocks);
1511
1801
  }
@@ -1569,6 +1859,7 @@ squel.flavours.mssql = (_squel) => {
1569
1859
  cls.DefaultQueryBuilderOptions.replaceSingleQuotes = true;
1570
1860
  cls.DefaultQueryBuilderOptions.autoQuoteAliasNames = false;
1571
1861
  cls.DefaultQueryBuilderOptions.numberedParametersPrefix = "@";
1862
+ cls.DefaultQueryBuilderOptions.useRecursiveKeyword = false;
1572
1863
  _squel.registerValueHandler(Date, (value) => {
1573
1864
  const date = value;
1574
1865
  return `'${date.getUTCFullYear()}-${date.getUTCMonth() + 1}-${date.getUTCDate()} ${date.getUTCHours()}:${date.getUTCMinutes()}:${date.getUTCSeconds()}'`;
@@ -1668,19 +1959,36 @@ squel.flavours.mssql = (_squel) => {
1668
1959
  super(options);
1669
1960
  this._outputs = [];
1670
1961
  }
1671
- output(fields) {
1672
- if (typeof fields === "string") {
1673
- this._outputs.push(`INSERTED.${this._sanitizeField(fields)}`);
1674
- } else {
1675
- fields.forEach((f) => {
1676
- 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);
1677
1978
  });
1678
1979
  }
1679
1980
  }
1680
1981
  _toParamString(options) {
1681
1982
  const ret = super._toParamString(options);
1682
1983
  if (ret.text.length && this._outputs.length > 0) {
1683
- 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(", ")} `;
1684
1992
  const valuesPos = ret.text.indexOf("VALUES");
1685
1993
  ret.text = ret.text.substring(0, valuesPos) + innerStr + ret.text.substring(valuesPos);
1686
1994
  }
@@ -1725,6 +2033,7 @@ squel.flavours.mssql = (_squel) => {
1725
2033
  constructor(options, blocks = null) {
1726
2034
  const limitOffsetTopBlock = new cls.MssqlLimitOffsetTopBlock(options);
1727
2035
  blocks = blocks || [
2036
+ new cls.WithBlock(options),
1728
2037
  new cls.StringBlock(options, "SELECT"),
1729
2038
  new cls.DistinctBlock(options),
1730
2039
  limitOffsetTopBlock.TOP(),
@@ -1745,6 +2054,7 @@ squel.flavours.mssql = (_squel) => {
1745
2054
  cls.Update = class extends cls.QueryBuilder {
1746
2055
  constructor(options, blocks = null) {
1747
2056
  blocks = blocks || [
2057
+ new cls.WithBlock(options),
1748
2058
  new cls.StringBlock(options, "UPDATE"),
1749
2059
  new cls.MssqlUpdateTopBlock(options),
1750
2060
  new cls.UpdateTableBlock(options),
@@ -1758,6 +2068,7 @@ squel.flavours.mssql = (_squel) => {
1758
2068
  cls.Delete = class extends cls.QueryBuilder {
1759
2069
  constructor(options, blocks = null) {
1760
2070
  blocks = blocks || [
2071
+ new cls.WithBlock(options),
1761
2072
  new cls.StringBlock(options, "DELETE"),
1762
2073
  new cls.TargetTableBlock(options),
1763
2074
  new cls.FromTableBlock(_extend({}, options, { singleTable: true })),
@@ -1773,6 +2084,7 @@ squel.flavours.mssql = (_squel) => {
1773
2084
  cls.Insert = class extends cls.QueryBuilder {
1774
2085
  constructor(options, blocks = null) {
1775
2086
  blocks = blocks || [
2087
+ new cls.WithBlock(options),
1776
2088
  new cls.StringBlock(options, "INSERT"),
1777
2089
  new cls.IntoTableBlock(options),
1778
2090
  new cls.MssqlInsertFieldValueBlock(options),
@@ -1781,6 +2093,199 @@ squel.flavours.mssql = (_squel) => {
1781
2093
  super(options, blocks);
1782
2094
  }
1783
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);
1784
2289
  };
1785
2290
 
1786
2291
  // src/index.ts
@@ -1790,4 +2295,4 @@ export {
1790
2295
  src_default as default
1791
2296
  };
1792
2297
 
1793
- //# debugId=1734B424D7A11C2364756E2164756E21
2298
+ //# debugId=4FE4237F5E06625564756E2164756E21