rawsql-ts 0.24.2 → 0.24.4

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.
Files changed (83) hide show
  1. package/README.md +10 -1
  2. package/dist/esm/index.min.js +9 -9
  3. package/dist/esm/index.min.js.map +2 -2
  4. package/dist/esm/models/ValueComponent.d.ts +2 -1
  5. package/dist/esm/models/ValueComponent.js +2 -1
  6. package/dist/esm/models/ValueComponent.js.map +1 -1
  7. package/dist/esm/parsers/CommandExpressionParser.d.ts +2 -0
  8. package/dist/esm/parsers/CommandExpressionParser.js +49 -4
  9. package/dist/esm/parsers/CommandExpressionParser.js.map +1 -1
  10. package/dist/esm/parsers/HavingParser.js +6 -0
  11. package/dist/esm/parsers/HavingParser.js.map +1 -1
  12. package/dist/esm/parsers/JoinOnClauseParser.js +6 -0
  13. package/dist/esm/parsers/JoinOnClauseParser.js.map +1 -1
  14. package/dist/esm/parsers/LimitClauseParser.js +6 -0
  15. package/dist/esm/parsers/LimitClauseParser.js.map +1 -1
  16. package/dist/esm/parsers/OffsetClauseParser.js +6 -0
  17. package/dist/esm/parsers/OffsetClauseParser.js.map +1 -1
  18. package/dist/esm/parsers/OrderByClauseParser.d.ts +2 -0
  19. package/dist/esm/parsers/OrderByClauseParser.js +42 -29
  20. package/dist/esm/parsers/OrderByClauseParser.js.map +1 -1
  21. package/dist/esm/parsers/ParameterDecorator.d.ts +2 -2
  22. package/dist/esm/parsers/ParameterDecorator.js +1 -1
  23. package/dist/esm/parsers/ParameterDecorator.js.map +1 -1
  24. package/dist/esm/parsers/ParameterExpressionParser.js +2 -1
  25. package/dist/esm/parsers/ParameterExpressionParser.js.map +1 -1
  26. package/dist/esm/parsers/SqlPrintTokenParser.d.ts +18 -4
  27. package/dist/esm/parsers/SqlPrintTokenParser.js +135 -18
  28. package/dist/esm/parsers/SqlPrintTokenParser.js.map +1 -1
  29. package/dist/esm/parsers/ValueParser.js +5 -3
  30. package/dist/esm/parsers/ValueParser.js.map +1 -1
  31. package/dist/esm/transformers/FormatOptionResolver.js +1 -0
  32. package/dist/esm/transformers/FormatOptionResolver.js.map +1 -1
  33. package/dist/esm/transformers/LinePrinter.d.ts +1 -1
  34. package/dist/esm/transformers/OnelineFormattingHelper.d.ts +1 -0
  35. package/dist/esm/transformers/OnelineFormattingHelper.js.map +1 -1
  36. package/dist/esm/transformers/SqlFormatter.d.ts +9 -5
  37. package/dist/esm/transformers/SqlFormatter.js +4 -4
  38. package/dist/esm/transformers/SqlFormatter.js.map +1 -1
  39. package/dist/esm/transformers/SqlPrinter.d.ts +26 -2
  40. package/dist/esm/transformers/SqlPrinter.js +325 -26
  41. package/dist/esm/transformers/SqlPrinter.js.map +1 -1
  42. package/dist/index.min.js +9 -9
  43. package/dist/index.min.js.map +2 -2
  44. package/dist/models/ValueComponent.js +2 -1
  45. package/dist/models/ValueComponent.js.map +1 -1
  46. package/dist/parsers/CommandExpressionParser.js +49 -4
  47. package/dist/parsers/CommandExpressionParser.js.map +1 -1
  48. package/dist/parsers/HavingParser.js +6 -0
  49. package/dist/parsers/HavingParser.js.map +1 -1
  50. package/dist/parsers/JoinOnClauseParser.js +6 -0
  51. package/dist/parsers/JoinOnClauseParser.js.map +1 -1
  52. package/dist/parsers/LimitClauseParser.js +6 -0
  53. package/dist/parsers/LimitClauseParser.js.map +1 -1
  54. package/dist/parsers/OffsetClauseParser.js +6 -0
  55. package/dist/parsers/OffsetClauseParser.js.map +1 -1
  56. package/dist/parsers/OrderByClauseParser.js +42 -29
  57. package/dist/parsers/OrderByClauseParser.js.map +1 -1
  58. package/dist/parsers/ParameterDecorator.js +1 -1
  59. package/dist/parsers/ParameterDecorator.js.map +1 -1
  60. package/dist/parsers/ParameterExpressionParser.js +2 -1
  61. package/dist/parsers/ParameterExpressionParser.js.map +1 -1
  62. package/dist/parsers/SqlPrintTokenParser.js +136 -18
  63. package/dist/parsers/SqlPrintTokenParser.js.map +1 -1
  64. package/dist/parsers/ValueParser.js +5 -3
  65. package/dist/parsers/ValueParser.js.map +1 -1
  66. package/dist/src/models/ValueComponent.d.ts +2 -1
  67. package/dist/src/parsers/CommandExpressionParser.d.ts +2 -0
  68. package/dist/src/parsers/OrderByClauseParser.d.ts +2 -0
  69. package/dist/src/parsers/ParameterDecorator.d.ts +2 -2
  70. package/dist/src/parsers/SqlPrintTokenParser.d.ts +18 -4
  71. package/dist/src/transformers/LinePrinter.d.ts +1 -1
  72. package/dist/src/transformers/OnelineFormattingHelper.d.ts +1 -0
  73. package/dist/src/transformers/SqlFormatter.d.ts +9 -5
  74. package/dist/src/transformers/SqlPrinter.d.ts +26 -2
  75. package/dist/transformers/FormatOptionResolver.js +1 -0
  76. package/dist/transformers/FormatOptionResolver.js.map +1 -1
  77. package/dist/transformers/OnelineFormattingHelper.js.map +1 -1
  78. package/dist/transformers/SqlFormatter.js +5 -3
  79. package/dist/transformers/SqlFormatter.js.map +1 -1
  80. package/dist/transformers/SqlPrinter.js +325 -26
  81. package/dist/transformers/SqlPrinter.js.map +1 -1
  82. package/dist/tsconfig.browser.tsbuildinfo +1 -1
  83. package/package.json +2 -2
@@ -21,6 +21,7 @@ var ParameterStyle;
21
21
  ParameterStyle["Anonymous"] = "anonymous";
22
22
  ParameterStyle["Indexed"] = "indexed";
23
23
  ParameterStyle["Named"] = "named";
24
+ ParameterStyle["Original"] = "original";
24
25
  })(ParameterStyle || (exports.ParameterStyle = ParameterStyle = {}));
25
26
  exports.PRESETS = {
26
27
  mysql: {
@@ -141,6 +142,7 @@ class SqlPrintTokenParser {
141
142
  this._selfHandlingComponentTypes = new Set([
142
143
  SelectQuery_1.SimpleSelectQuery.kind,
143
144
  Clause_1.SelectItem.kind,
145
+ Clause_1.OrderByItem.kind,
144
146
  ValueComponent_1.CaseKeyValuePair.kind,
145
147
  ValueComponent_1.SwitchCaseArgument.kind,
146
148
  ValueComponent_1.ColumnReference.kind,
@@ -157,9 +159,10 @@ class SqlPrintTokenParser {
157
159
  return this._selfHandlingComponentTypes;
158
160
  }
159
161
  constructor(options) {
160
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
162
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
161
163
  this.handlers = new Map();
162
164
  this.index = 1;
165
+ this.listContinuationCommentComponents = new WeakSet();
163
166
  this.joinConditionContexts = [];
164
167
  if (options === null || options === void 0 ? void 0 : options.preset) {
165
168
  const preset = options.preset;
@@ -177,9 +180,10 @@ class SqlPrintTokenParser {
177
180
  });
178
181
  this.castStyle = (_j = options === null || options === void 0 ? void 0 : options.castStyle) !== null && _j !== void 0 ? _j : 'standard';
179
182
  this.constraintStyle = (_k = options === null || options === void 0 ? void 0 : options.constraintStyle) !== null && _k !== void 0 ? _k : 'postgres';
180
- this.sourceAliasStyle = (_l = options === null || options === void 0 ? void 0 : options.sourceAliasStyle) !== null && _l !== void 0 ? _l : 'as';
181
- this.orderByDefaultDirectionStyle = (_m = options === null || options === void 0 ? void 0 : options.orderByDefaultDirectionStyle) !== null && _m !== void 0 ? _m : 'omit';
182
- this.normalizeJoinConditionOrder = (_o = options === null || options === void 0 ? void 0 : options.joinConditionOrderByDeclaration) !== null && _o !== void 0 ? _o : false;
183
+ this.sourceAliasStyle = this.normalizeAliasKeywordStyle(options === null || options === void 0 ? void 0 : options.sourceAliasStyle);
184
+ this.columnAliasStyle = this.normalizeAliasKeywordStyle(options === null || options === void 0 ? void 0 : options.columnAliasStyle);
185
+ this.orderByDefaultDirectionStyle = (_l = options === null || options === void 0 ? void 0 : options.orderByDefaultDirectionStyle) !== null && _l !== void 0 ? _l : 'omit';
186
+ this.normalizeJoinConditionOrder = (_m = options === null || options === void 0 ? void 0 : options.joinConditionOrderByDeclaration) !== null && _m !== void 0 ? _m : false;
183
187
  this.handlers.set(ValueComponent_1.ValueList.kind, (expr) => this.visitValueList(expr));
184
188
  this.handlers.set(ValueComponent_1.ColumnReference.kind, (expr) => this.visitColumnReference(expr));
185
189
  this.handlers.set(ValueComponent_1.QualifiedName.kind, (expr) => this.visitQualifiedName(expr));
@@ -349,6 +353,7 @@ class SqlPrintTokenParser {
349
353
  }
350
354
  visitQualifiedName(arg) {
351
355
  const token = new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.container, '', SqlPrintToken_1.SqlPrintTokenContainerType.QualifiedName);
356
+ const hasOwnComments = this.hasPositionedComments(arg) || this.hasLegacyComments(arg);
352
357
  if (arg.namespaces) {
353
358
  for (let i = 0; i < arg.namespaces.length; i++) {
354
359
  token.innerTokens.push(arg.namespaces[i].accept(this));
@@ -369,7 +374,7 @@ class SqlPrintTokenParser {
369
374
  arg.name.positionedComments = originalNameComments;
370
375
  arg.name.comments = originalNameLegacyComments;
371
376
  // Apply the name's comments to the qualified name token
372
- if (this.hasPositionedComments(arg.name) || this.hasLegacyComments(arg.name)) {
377
+ if (!hasOwnComments && (this.hasPositionedComments(arg.name) || this.hasLegacyComments(arg.name))) {
373
378
  this.addComponentComments(token, arg.name);
374
379
  }
375
380
  // Also handle any comments directly on the QualifiedName itself
@@ -390,7 +395,13 @@ class SqlPrintTokenParser {
390
395
  for (let i = 0; i < arg.order.length; i++) {
391
396
  if (i > 0)
392
397
  token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());
393
- token.innerTokens.push(this.visit(arg.order[i]));
398
+ const item = arg.order[i];
399
+ token.innerTokens.push(this.visit(item));
400
+ if (!(item instanceof Clause_1.OrderByItem) &&
401
+ this.orderByDefaultDirectionStyle === 'explicit') {
402
+ token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
403
+ token.innerTokens.push(new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.keyword, 'asc'));
404
+ }
394
405
  }
395
406
  return token;
396
407
  }
@@ -419,6 +430,10 @@ class SqlPrintTokenParser {
419
430
  token.innerTokens.push(new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.keyword, 'nulls last'));
420
431
  }
421
432
  }
433
+ if (arg.comments && arg.comments.length > 0) {
434
+ token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
435
+ token.innerTokens.push(...this.createInlineCommentSequence(arg.comments));
436
+ }
422
437
  return token;
423
438
  }
424
439
  parse(arg) {
@@ -427,7 +442,7 @@ class SqlPrintTokenParser {
427
442
  const token = this.visit(arg);
428
443
  const paramsRaw = ParameterCollector_1.ParameterCollector.collect(arg).sort((a, b) => { var _a, _b; return ((_a = a.index) !== null && _a !== void 0 ? _a : 0) - ((_b = b.index) !== null && _b !== void 0 ? _b : 0); });
429
444
  const style = this.parameterDecorator.style;
430
- if (style === ParameterStyle.Named) {
445
+ if (style === ParameterStyle.Named || style === ParameterStyle.Original) {
431
446
  // Named: { name: value, ... }
432
447
  const paramsObj = {};
433
448
  for (const p of paramsRaw) {
@@ -897,7 +912,18 @@ class SqlPrintTokenParser {
897
912
  }
898
913
  visitColumnReference(arg) {
899
914
  const token = new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.container, '', SqlPrintToken_1.SqlPrintTokenContainerType.ColumnReference);
915
+ const hasOwnComments = this.hasPositionedComments(arg) || this.hasLegacyComments(arg);
916
+ const originalNamePositionedComments = arg.qualifiedName.name.positionedComments;
917
+ const originalNameComments = arg.qualifiedName.name.comments;
918
+ if (hasOwnComments) {
919
+ arg.qualifiedName.name.positionedComments = null;
920
+ arg.qualifiedName.name.comments = null;
921
+ }
900
922
  token.innerTokens.push(arg.qualifiedName.accept(this));
923
+ if (hasOwnComments) {
924
+ arg.qualifiedName.name.positionedComments = originalNamePositionedComments;
925
+ arg.qualifiedName.name.comments = originalNameComments;
926
+ }
901
927
  this.addComponentComments(token, arg);
902
928
  return token;
903
929
  }
@@ -1063,7 +1089,9 @@ class SqlPrintTokenParser {
1063
1089
  visitParameterExpression(arg) {
1064
1090
  // Create a parameter token and decorate it using the parameterDecorator
1065
1091
  arg.index = this.index;
1066
- const text = this.parameterDecorator.decorate(arg.name.value, arg.index);
1092
+ const text = this.parameterDecorator.style === ParameterStyle.Original && arg.sourceText
1093
+ ? arg.sourceText
1094
+ : this.parameterDecorator.decorate(arg.name.value, arg.index);
1067
1095
  const token = new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.parameter, text);
1068
1096
  this.addComponentComments(token, arg);
1069
1097
  this.index++;
@@ -1169,6 +1197,7 @@ class SqlPrintTokenParser {
1169
1197
  return token;
1170
1198
  }
1171
1199
  visitParenExpression(arg) {
1200
+ var _a, _b;
1172
1201
  const token = new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.container, '', SqlPrintToken_1.SqlPrintTokenContainerType.ParenExpression);
1173
1202
  // Handle positioned comments for ParenExpression - check both self and inner expression
1174
1203
  const hasOwnComments = arg.positionedComments && arg.positionedComments.length > 0;
@@ -1181,6 +1210,12 @@ class SqlPrintTokenParser {
1181
1210
  innerAfterComments = arg.expression.getPositionedComments('after');
1182
1211
  arg.expression.positionedComments = null;
1183
1212
  }
1213
+ if (hasOwnComments && innerBeforeComments.length > 0) {
1214
+ const innerBeforeSet = new Set(innerBeforeComments);
1215
+ arg.positionedComments = (_b = (_a = arg.positionedComments) === null || _a === void 0 ? void 0 : _a.map(comment => comment.position === 'after'
1216
+ ? { ...comment, comments: comment.comments.filter(value => !innerBeforeSet.has(value)) }
1217
+ : comment).filter(comment => comment.comments.length > 0)) !== null && _b !== void 0 ? _b : null;
1218
+ }
1184
1219
  // Build basic structure first
1185
1220
  token.innerTokens.push(SqlPrintTokenParser.PAREN_OPEN_TOKEN);
1186
1221
  token.innerTokens.push(this.visit(arg.expression));
@@ -1234,6 +1269,7 @@ class SqlPrintTokenParser {
1234
1269
  const token = new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.container, '', SqlPrintToken_1.SqlPrintTokenContainerType.CaseExpression);
1235
1270
  // Handle positioned comments for CaseExpression (unified spec: positioned comments only)
1236
1271
  if (arg.positionedComments && arg.positionedComments.length > 0) {
1272
+ this.removeCaseAfterCommentsDuplicatedOnFirstWhen(arg);
1237
1273
  this.addPositionedCommentsToToken(token, arg);
1238
1274
  // Clear positioned comments to prevent duplicate processing
1239
1275
  arg.positionedComments = null;
@@ -1246,7 +1282,6 @@ class SqlPrintTokenParser {
1246
1282
  promotedComments.push(...this.collectCaseLeadingCommentBlocks(conditionToken));
1247
1283
  }
1248
1284
  const switchToken = this.visit(arg.switchCase);
1249
- promotedComments.push(...this.collectCaseLeadingCommentsFromSwitch(switchToken));
1250
1285
  if (promotedComments.length > 0) {
1251
1286
  token.innerTokens.push(...promotedComments);
1252
1287
  }
@@ -1269,6 +1304,32 @@ class SqlPrintTokenParser {
1269
1304
  }
1270
1305
  return token;
1271
1306
  }
1307
+ removeCaseAfterCommentsDuplicatedOnFirstWhen(arg) {
1308
+ var _a, _b;
1309
+ if (!arg.positionedComments || arg.positionedComments.length === 0) {
1310
+ return;
1311
+ }
1312
+ const firstWhenComments = new Set(((_b = (_a = arg.switchCase.cases[0]) === null || _a === void 0 ? void 0 : _a.getPositionedComments('before')) !== null && _b !== void 0 ? _b : [])
1313
+ .map(comment => this.normalizeCommentSignature(comment)));
1314
+ if (firstWhenComments.size === 0) {
1315
+ return;
1316
+ }
1317
+ const retained = [];
1318
+ for (const entry of arg.positionedComments) {
1319
+ if (entry.position !== 'after') {
1320
+ retained.push(entry);
1321
+ continue;
1322
+ }
1323
+ const comments = entry.comments.filter(comment => !firstWhenComments.has(this.normalizeCommentSignature(comment)));
1324
+ if (comments.length > 0) {
1325
+ retained.push({ ...entry, comments });
1326
+ }
1327
+ }
1328
+ arg.positionedComments = retained.length > 0 ? retained : null;
1329
+ }
1330
+ normalizeCommentSignature(comment) {
1331
+ return comment.replace(/\s+/g, ' ').trim();
1332
+ }
1272
1333
  extractSwitchAfterComments(arg) {
1273
1334
  if (!arg.positionedComments || arg.positionedComments.length === 0) {
1274
1335
  return [];
@@ -1590,11 +1651,13 @@ class SqlPrintTokenParser {
1590
1651
  // Add positioned comments in recorded order
1591
1652
  const beforeComments = arg.getPositionedComments('before');
1592
1653
  const afterComments = arg.getPositionedComments('after');
1654
+ const duplicateCaseAfterComments = arg.value instanceof ValueComponent_1.CaseExpression
1655
+ ? this.collectCaseSelectItemDuplicateAfterComments(arg.value)
1656
+ : new Set();
1593
1657
  if (beforeComments.length > 0) {
1594
- if (arg.value instanceof ValueComponent_1.CaseExpression) {
1658
+ if (arg.value instanceof ValueComponent_1.CaseExpression || this.listContinuationCommentComponents.has(arg)) {
1595
1659
  const commentBlocks = this.createCommentBlocks(beforeComments);
1596
1660
  token.innerTokens.push(...commentBlocks);
1597
- token.innerTokens.push(new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.commentNewline, ''));
1598
1661
  }
1599
1662
  else {
1600
1663
  const commentTokens = this.createInlineCommentSequence(beforeComments);
@@ -1603,9 +1666,12 @@ class SqlPrintTokenParser {
1603
1666
  }
1604
1667
  }
1605
1668
  token.innerTokens.push(this.visit(arg.value));
1606
- if (afterComments.length > 0 && !isParenExpression) {
1669
+ const visibleAfterComments = arg.value instanceof ValueComponent_1.CaseExpression
1670
+ ? this.filterCaseSelectItemDuplicateAfterComments(afterComments, duplicateCaseAfterComments)
1671
+ : afterComments;
1672
+ if (visibleAfterComments.length > 0 && !isParenExpression) {
1607
1673
  token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
1608
- const commentTokens = this.createInlineCommentSequence(afterComments);
1674
+ const commentTokens = this.createInlineCommentSequence(visibleAfterComments);
1609
1675
  token.innerTokens.push(...commentTokens);
1610
1676
  }
1611
1677
  // Restore original positioned comments to avoid side effects
@@ -1625,6 +1691,8 @@ class SqlPrintTokenParser {
1625
1691
  token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
1626
1692
  // Handle AS keyword positioned comments (before AS)
1627
1693
  const asKeywordPositionedComments = 'asKeywordPositionedComments' in arg ? arg.asKeywordPositionedComments : null;
1694
+ const asKeywordComments = 'asKeywordComments' in arg ? arg.asKeywordComments : null;
1695
+ const shouldPrintAsKeyword = this.shouldPrintColumnAliasKeyword(asKeywordPositionedComments, asKeywordComments);
1628
1696
  if (asKeywordPositionedComments) {
1629
1697
  const beforeComments = asKeywordPositionedComments.filter((pc) => pc.position === 'before');
1630
1698
  if (beforeComments.length > 0) {
@@ -1635,9 +1703,11 @@ class SqlPrintTokenParser {
1635
1703
  }
1636
1704
  }
1637
1705
  }
1638
- token.innerTokens.push(new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.keyword, 'as'));
1706
+ if (shouldPrintAsKeyword) {
1707
+ token.innerTokens.push(new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.keyword, 'as'));
1708
+ }
1639
1709
  // Handle AS keyword positioned comments (after AS)
1640
- if (asKeywordPositionedComments) {
1710
+ if (shouldPrintAsKeyword && asKeywordPositionedComments) {
1641
1711
  const afterComments = asKeywordPositionedComments.filter((pc) => pc.position === 'after');
1642
1712
  if (afterComments.length > 0) {
1643
1713
  token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
@@ -1648,13 +1718,14 @@ class SqlPrintTokenParser {
1648
1718
  }
1649
1719
  }
1650
1720
  // Fallback: Add AS keyword legacy comments if present
1651
- const asKeywordComments = 'asKeywordComments' in arg ? arg.asKeywordComments : null;
1652
1721
  if (asKeywordComments && asKeywordComments.length > 0) {
1653
1722
  token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
1654
1723
  const commentTokens = this.createInlineCommentSequence(asKeywordComments);
1655
1724
  token.innerTokens.push(...commentTokens);
1656
1725
  }
1657
- token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
1726
+ if (shouldPrintAsKeyword) {
1727
+ token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
1728
+ }
1658
1729
  // Visit identifier to get alias with proper spacing
1659
1730
  const identifierToken = this.visit(arg.identifier);
1660
1731
  token.innerTokens.push(identifierToken);
@@ -1679,6 +1750,34 @@ class SqlPrintTokenParser {
1679
1750
  }
1680
1751
  return token;
1681
1752
  }
1753
+ collectCaseSelectItemDuplicateAfterComments(value) {
1754
+ const promoted = new Set();
1755
+ if (value.comments) {
1756
+ for (const comment of value.comments) {
1757
+ promoted.add(comment);
1758
+ }
1759
+ }
1760
+ const firstCase = value.switchCase.cases[0];
1761
+ if (firstCase === null || firstCase === void 0 ? void 0 : firstCase.positionedComments) {
1762
+ for (const positionedComment of firstCase.positionedComments) {
1763
+ if (positionedComment.position === 'before') {
1764
+ for (const comment of positionedComment.comments) {
1765
+ promoted.add(comment);
1766
+ }
1767
+ }
1768
+ }
1769
+ }
1770
+ return promoted;
1771
+ }
1772
+ filterCaseSelectItemDuplicateAfterComments(afterComments, promoted) {
1773
+ if (afterComments.length === 0) {
1774
+ return afterComments;
1775
+ }
1776
+ if (promoted.size === 0) {
1777
+ return afterComments;
1778
+ }
1779
+ return afterComments.filter(comment => !promoted.has(comment));
1780
+ }
1682
1781
  visitSelectClause(arg) {
1683
1782
  const token = new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.keyword, 'select', SqlPrintToken_1.SqlPrintTokenContainerType.SelectClause);
1684
1783
  // Handle positioned comments for SelectClause (unified spec)
@@ -1714,6 +1813,14 @@ class SqlPrintTokenParser {
1714
1813
  for (let i = 0; i < arg.items.length; i++) {
1715
1814
  if (i > 0) {
1716
1815
  token.innerTokens.push(...SqlPrintTokenParser.commaSpaceTokens());
1816
+ this.listContinuationCommentComponents.add(arg.items[i]);
1817
+ try {
1818
+ token.innerTokens.push(this.visit(arg.items[i]));
1819
+ }
1820
+ finally {
1821
+ this.listContinuationCommentComponents.delete(arg.items[i]);
1822
+ }
1823
+ continue;
1717
1824
  }
1718
1825
  token.innerTokens.push(this.visit(arg.items[i]));
1719
1826
  }
@@ -1793,12 +1900,23 @@ class SqlPrintTokenParser {
1793
1900
  }
1794
1901
  }
1795
1902
  appendSourceAliasKeyword(token) {
1796
- if (this.sourceAliasStyle === 'implicit') {
1903
+ if (this.sourceAliasStyle === 'omit') {
1797
1904
  return;
1798
1905
  }
1799
1906
  token.innerTokens.push(new SqlPrintToken_1.SqlPrintToken(SqlPrintToken_1.SqlPrintTokenType.keyword, 'as'));
1800
1907
  token.innerTokens.push(SqlPrintTokenParser.SPACE_TOKEN);
1801
1908
  }
1909
+ shouldPrintColumnAliasKeyword(asKeywordPositionedComments, asKeywordComments) {
1910
+ if (this.columnAliasStyle === 'explicit') {
1911
+ return true;
1912
+ }
1913
+ const hasPositionedComments = Array.isArray(asKeywordPositionedComments) && asKeywordPositionedComments.length > 0;
1914
+ const hasLegacyComments = Array.isArray(asKeywordComments) && asKeywordComments.length > 0;
1915
+ return hasPositionedComments || hasLegacyComments;
1916
+ }
1917
+ normalizeAliasKeywordStyle(style) {
1918
+ return style === 'implicit' || style === 'omit' ? 'omit' : 'explicit';
1919
+ }
1802
1920
  visitFromClause(arg) {
1803
1921
  // Build a declaration order map so JOIN ON operands can be normalized later.
1804
1922
  let contextPushed = false;