rawsql-ts 0.11.42-beta → 0.11.44-beta

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 (278) hide show
  1. package/README.md +12 -13
  2. package/dist/esm/index.js +18 -0
  3. package/dist/esm/index.js.map +1 -1
  4. package/dist/esm/index.min.js +23 -18
  5. package/dist/esm/index.min.js.map +4 -4
  6. package/dist/esm/src/index.d.ts +18 -0
  7. package/dist/esm/src/index.js +18 -0
  8. package/dist/esm/src/index.js.map +1 -1
  9. package/dist/esm/src/models/BinarySelectQuery.d.ts +25 -1
  10. package/dist/esm/src/models/BinarySelectQuery.js +28 -0
  11. package/dist/esm/src/models/BinarySelectQuery.js.map +1 -1
  12. package/dist/esm/src/models/Clause.d.ts +14 -2
  13. package/dist/esm/src/models/Clause.js +26 -1
  14. package/dist/esm/src/models/Clause.js.map +1 -1
  15. package/dist/esm/src/models/CreateTableQuery.d.ts +99 -5
  16. package/dist/esm/src/models/CreateTableQuery.js +85 -10
  17. package/dist/esm/src/models/CreateTableQuery.js.map +1 -1
  18. package/dist/esm/src/models/DDLStatements.d.ts +157 -0
  19. package/dist/esm/src/models/DDLStatements.js +141 -0
  20. package/dist/esm/src/models/DDLStatements.js.map +1 -0
  21. package/dist/esm/src/models/DeleteQuery.d.ts +17 -0
  22. package/dist/esm/src/models/DeleteQuery.js +16 -0
  23. package/dist/esm/src/models/DeleteQuery.js.map +1 -0
  24. package/dist/esm/src/models/InsertQuery.d.ts +7 -1
  25. package/dist/esm/src/models/InsertQuery.js +6 -2
  26. package/dist/esm/src/models/InsertQuery.js.map +1 -1
  27. package/dist/esm/src/models/MergeQuery.d.ts +63 -0
  28. package/dist/esm/src/models/MergeQuery.js +94 -0
  29. package/dist/esm/src/models/MergeQuery.js.map +1 -0
  30. package/dist/esm/src/models/SelectQuery.d.ts +37 -1
  31. package/dist/esm/src/models/SelectQuery.js +4 -1
  32. package/dist/esm/src/models/SelectQuery.js.map +1 -1
  33. package/dist/esm/src/models/SimpleSelectQuery.d.ts +29 -1
  34. package/dist/esm/src/models/SimpleSelectQuery.js +32 -0
  35. package/dist/esm/src/models/SimpleSelectQuery.js.map +1 -1
  36. package/dist/esm/src/models/SqlComponent.d.ts +2 -1
  37. package/dist/esm/src/models/SqlComponent.js +1 -1
  38. package/dist/esm/src/models/SqlComponent.js.map +1 -1
  39. package/dist/esm/src/models/SqlPrintToken.d.ts +33 -0
  40. package/dist/esm/src/models/SqlPrintToken.js +32 -0
  41. package/dist/esm/src/models/SqlPrintToken.js.map +1 -1
  42. package/dist/esm/src/models/ValuesQuery.d.ts +25 -1
  43. package/dist/esm/src/models/ValuesQuery.js +28 -0
  44. package/dist/esm/src/models/ValuesQuery.js.map +1 -1
  45. package/dist/esm/src/parsers/AlterTableParser.d.ts +25 -0
  46. package/dist/esm/src/parsers/AlterTableParser.js +428 -0
  47. package/dist/esm/src/parsers/AlterTableParser.js.map +1 -0
  48. package/dist/esm/src/parsers/CreateIndexParser.d.ts +16 -0
  49. package/dist/esm/src/parsers/CreateIndexParser.js +237 -0
  50. package/dist/esm/src/parsers/CreateIndexParser.js.map +1 -0
  51. package/dist/esm/src/parsers/CreateTableParser.d.ts +41 -0
  52. package/dist/esm/src/parsers/CreateTableParser.js +734 -0
  53. package/dist/esm/src/parsers/CreateTableParser.js.map +1 -0
  54. package/dist/esm/src/parsers/DeleteClauseParser.d.ts +11 -0
  55. package/dist/esm/src/parsers/DeleteClauseParser.js +33 -0
  56. package/dist/esm/src/parsers/DeleteClauseParser.js.map +1 -0
  57. package/dist/esm/src/parsers/DeleteQueryParser.d.ts +16 -0
  58. package/dist/esm/src/parsers/DeleteQueryParser.js +73 -0
  59. package/dist/esm/src/parsers/DeleteQueryParser.js.map +1 -0
  60. package/dist/esm/src/parsers/DropConstraintParser.d.ts +12 -0
  61. package/dist/esm/src/parsers/DropConstraintParser.js +47 -0
  62. package/dist/esm/src/parsers/DropConstraintParser.js.map +1 -0
  63. package/dist/esm/src/parsers/DropIndexParser.d.ts +12 -0
  64. package/dist/esm/src/parsers/DropIndexParser.js +69 -0
  65. package/dist/esm/src/parsers/DropIndexParser.js.map +1 -0
  66. package/dist/esm/src/parsers/DropTableParser.d.ts +12 -0
  67. package/dist/esm/src/parsers/DropTableParser.js +59 -0
  68. package/dist/esm/src/parsers/DropTableParser.js.map +1 -0
  69. package/dist/esm/src/parsers/FunctionExpressionParser.d.ts +4 -0
  70. package/dist/esm/src/parsers/FunctionExpressionParser.js +25 -8
  71. package/dist/esm/src/parsers/FunctionExpressionParser.js.map +1 -1
  72. package/dist/esm/src/parsers/InsertQueryParser.js +103 -31
  73. package/dist/esm/src/parsers/InsertQueryParser.js.map +1 -1
  74. package/dist/esm/src/parsers/MergeQueryParser.d.ts +26 -0
  75. package/dist/esm/src/parsers/MergeQueryParser.js +479 -0
  76. package/dist/esm/src/parsers/MergeQueryParser.js.map +1 -0
  77. package/dist/esm/src/parsers/ReturningClauseParser.js +50 -7
  78. package/dist/esm/src/parsers/ReturningClauseParser.js.map +1 -1
  79. package/dist/esm/src/parsers/SelectClauseParser.js +3 -3
  80. package/dist/esm/src/parsers/SelectClauseParser.js.map +1 -1
  81. package/dist/esm/src/parsers/SelectQueryParser.d.ts +4 -0
  82. package/dist/esm/src/parsers/SelectQueryParser.js +4 -0
  83. package/dist/esm/src/parsers/SelectQueryParser.js.map +1 -1
  84. package/dist/esm/src/parsers/SetClauseParser.js +97 -15
  85. package/dist/esm/src/parsers/SetClauseParser.js.map +1 -1
  86. package/dist/esm/src/parsers/SqlParser.d.ts +38 -0
  87. package/dist/esm/src/parsers/SqlParser.js +344 -0
  88. package/dist/esm/src/parsers/SqlParser.js.map +1 -0
  89. package/dist/esm/src/parsers/SqlPrintTokenParser.d.ts +68 -21
  90. package/dist/esm/src/parsers/SqlPrintTokenParser.js +1145 -254
  91. package/dist/esm/src/parsers/SqlPrintTokenParser.js.map +1 -1
  92. package/dist/esm/src/parsers/SqlTokenizer.d.ts +24 -2
  93. package/dist/esm/src/parsers/SqlTokenizer.js +135 -74
  94. package/dist/esm/src/parsers/SqlTokenizer.js.map +1 -1
  95. package/dist/esm/src/parsers/UpdateQueryParser.js +11 -1
  96. package/dist/esm/src/parsers/UpdateQueryParser.js.map +1 -1
  97. package/dist/esm/src/parsers/UsingClauseParser.d.ts +11 -0
  98. package/dist/esm/src/parsers/UsingClauseParser.js +29 -0
  99. package/dist/esm/src/parsers/UsingClauseParser.js.map +1 -0
  100. package/dist/esm/src/parsers/ValueParser.js +5 -1
  101. package/dist/esm/src/parsers/ValueParser.js.map +1 -1
  102. package/dist/esm/src/parsers/ValuesQueryParser.d.ts +0 -2
  103. package/dist/esm/src/parsers/ValuesQueryParser.js +5 -45
  104. package/dist/esm/src/parsers/ValuesQueryParser.js.map +1 -1
  105. package/dist/esm/src/parsers/utils/LexemeCommentUtils.d.ts +6 -0
  106. package/dist/esm/src/parsers/utils/LexemeCommentUtils.js +26 -0
  107. package/dist/esm/src/parsers/utils/LexemeCommentUtils.js.map +1 -0
  108. package/dist/esm/src/tokenReaders/CommandTokenReader.js +49 -2
  109. package/dist/esm/src/tokenReaders/CommandTokenReader.js.map +1 -1
  110. package/dist/esm/src/tokenReaders/LiteralTokenReader.js +8 -5
  111. package/dist/esm/src/tokenReaders/LiteralTokenReader.js.map +1 -1
  112. package/dist/esm/src/tokenReaders/OperatorTokenReader.js +10 -1
  113. package/dist/esm/src/tokenReaders/OperatorTokenReader.js.map +1 -1
  114. package/dist/esm/src/tokenReaders/TypeTokenReader.js +11 -1
  115. package/dist/esm/src/tokenReaders/TypeTokenReader.js.map +1 -1
  116. package/dist/esm/src/transformers/InsertQuerySelectValuesConverter.d.ts +18 -0
  117. package/dist/esm/src/transformers/InsertQuerySelectValuesConverter.js +118 -0
  118. package/dist/esm/src/transformers/InsertQuerySelectValuesConverter.js.map +1 -0
  119. package/dist/esm/src/transformers/LinePrinter.d.ts +2 -0
  120. package/dist/esm/src/transformers/LinePrinter.js +34 -1
  121. package/dist/esm/src/transformers/LinePrinter.js.map +1 -1
  122. package/dist/esm/src/transformers/OnelineFormattingHelper.d.ts +29 -0
  123. package/dist/esm/src/transformers/OnelineFormattingHelper.js +88 -0
  124. package/dist/esm/src/transformers/OnelineFormattingHelper.js.map +1 -0
  125. package/dist/esm/src/transformers/QueryBuilder.d.ts +47 -13
  126. package/dist/esm/src/transformers/QueryBuilder.js +424 -62
  127. package/dist/esm/src/transformers/QueryBuilder.js.map +1 -1
  128. package/dist/esm/src/transformers/SqlFormatter.d.ts +13 -3
  129. package/dist/esm/src/transformers/SqlFormatter.js +13 -4
  130. package/dist/esm/src/transformers/SqlFormatter.js.map +1 -1
  131. package/dist/esm/src/transformers/SqlPrinter.d.ts +63 -10
  132. package/dist/esm/src/transformers/SqlPrinter.js +954 -64
  133. package/dist/esm/src/transformers/SqlPrinter.js.map +1 -1
  134. package/dist/esm/src/types/Formatting.d.ts +8 -0
  135. package/dist/esm/src/types/Formatting.js +2 -0
  136. package/dist/esm/src/types/Formatting.js.map +1 -0
  137. package/dist/esm/src/utils/ParserStringUtils.d.ts +6 -0
  138. package/dist/esm/src/utils/ParserStringUtils.js +28 -0
  139. package/dist/esm/src/utils/ParserStringUtils.js.map +1 -0
  140. package/dist/esm/tsconfig.browser.tsbuildinfo +1 -1
  141. package/dist/index.min.js +22 -17
  142. package/dist/index.min.js.map +4 -4
  143. package/dist/src/index.d.ts +18 -0
  144. package/dist/src/index.js +18 -0
  145. package/dist/src/index.js.map +1 -1
  146. package/dist/src/models/BinarySelectQuery.d.ts +25 -1
  147. package/dist/src/models/BinarySelectQuery.js +28 -0
  148. package/dist/src/models/BinarySelectQuery.js.map +1 -1
  149. package/dist/src/models/Clause.d.ts +14 -2
  150. package/dist/src/models/Clause.js +29 -2
  151. package/dist/src/models/Clause.js.map +1 -1
  152. package/dist/src/models/CreateTableQuery.d.ts +99 -5
  153. package/dist/src/models/CreateTableQuery.js +90 -11
  154. package/dist/src/models/CreateTableQuery.js.map +1 -1
  155. package/dist/src/models/DDLStatements.d.ts +157 -0
  156. package/dist/src/models/DDLStatements.js +153 -0
  157. package/dist/src/models/DDLStatements.js.map +1 -0
  158. package/dist/src/models/DeleteQuery.d.ts +17 -0
  159. package/dist/src/models/DeleteQuery.js +20 -0
  160. package/dist/src/models/DeleteQuery.js.map +1 -0
  161. package/dist/src/models/InsertQuery.d.ts +7 -1
  162. package/dist/src/models/InsertQuery.js +6 -2
  163. package/dist/src/models/InsertQuery.js.map +1 -1
  164. package/dist/src/models/MergeQuery.d.ts +63 -0
  165. package/dist/src/models/MergeQuery.js +104 -0
  166. package/dist/src/models/MergeQuery.js.map +1 -0
  167. package/dist/src/models/SelectQuery.d.ts +37 -1
  168. package/dist/src/models/SelectQuery.js +7 -1
  169. package/dist/src/models/SelectQuery.js.map +1 -1
  170. package/dist/src/models/SimpleSelectQuery.d.ts +29 -1
  171. package/dist/src/models/SimpleSelectQuery.js +32 -0
  172. package/dist/src/models/SimpleSelectQuery.js.map +1 -1
  173. package/dist/src/models/SqlComponent.d.ts +2 -1
  174. package/dist/src/models/SqlComponent.js +1 -1
  175. package/dist/src/models/SqlComponent.js.map +1 -1
  176. package/dist/src/models/SqlPrintToken.d.ts +33 -0
  177. package/dist/src/models/SqlPrintToken.js +32 -0
  178. package/dist/src/models/SqlPrintToken.js.map +1 -1
  179. package/dist/src/models/ValuesQuery.d.ts +25 -1
  180. package/dist/src/models/ValuesQuery.js +28 -0
  181. package/dist/src/models/ValuesQuery.js.map +1 -1
  182. package/dist/src/parsers/AlterTableParser.d.ts +25 -0
  183. package/dist/src/parsers/AlterTableParser.js +432 -0
  184. package/dist/src/parsers/AlterTableParser.js.map +1 -0
  185. package/dist/src/parsers/CreateIndexParser.d.ts +16 -0
  186. package/dist/src/parsers/CreateIndexParser.js +241 -0
  187. package/dist/src/parsers/CreateIndexParser.js.map +1 -0
  188. package/dist/src/parsers/CreateTableParser.d.ts +41 -0
  189. package/dist/src/parsers/CreateTableParser.js +738 -0
  190. package/dist/src/parsers/CreateTableParser.js.map +1 -0
  191. package/dist/src/parsers/DeleteClauseParser.d.ts +11 -0
  192. package/dist/src/parsers/DeleteClauseParser.js +37 -0
  193. package/dist/src/parsers/DeleteClauseParser.js.map +1 -0
  194. package/dist/src/parsers/DeleteQueryParser.d.ts +16 -0
  195. package/dist/src/parsers/DeleteQueryParser.js +77 -0
  196. package/dist/src/parsers/DeleteQueryParser.js.map +1 -0
  197. package/dist/src/parsers/DropConstraintParser.d.ts +12 -0
  198. package/dist/src/parsers/DropConstraintParser.js +51 -0
  199. package/dist/src/parsers/DropConstraintParser.js.map +1 -0
  200. package/dist/src/parsers/DropIndexParser.d.ts +12 -0
  201. package/dist/src/parsers/DropIndexParser.js +73 -0
  202. package/dist/src/parsers/DropIndexParser.js.map +1 -0
  203. package/dist/src/parsers/DropTableParser.d.ts +12 -0
  204. package/dist/src/parsers/DropTableParser.js +63 -0
  205. package/dist/src/parsers/DropTableParser.js.map +1 -0
  206. package/dist/src/parsers/FunctionExpressionParser.d.ts +4 -0
  207. package/dist/src/parsers/FunctionExpressionParser.js +25 -8
  208. package/dist/src/parsers/FunctionExpressionParser.js.map +1 -1
  209. package/dist/src/parsers/InsertQueryParser.js +103 -31
  210. package/dist/src/parsers/InsertQueryParser.js.map +1 -1
  211. package/dist/src/parsers/MergeQueryParser.d.ts +26 -0
  212. package/dist/src/parsers/MergeQueryParser.js +483 -0
  213. package/dist/src/parsers/MergeQueryParser.js.map +1 -0
  214. package/dist/src/parsers/ReturningClauseParser.js +50 -7
  215. package/dist/src/parsers/ReturningClauseParser.js.map +1 -1
  216. package/dist/src/parsers/SelectClauseParser.js +2 -2
  217. package/dist/src/parsers/SelectClauseParser.js.map +1 -1
  218. package/dist/src/parsers/SelectQueryParser.d.ts +4 -0
  219. package/dist/src/parsers/SelectQueryParser.js +4 -0
  220. package/dist/src/parsers/SelectQueryParser.js.map +1 -1
  221. package/dist/src/parsers/SetClauseParser.js +97 -15
  222. package/dist/src/parsers/SetClauseParser.js.map +1 -1
  223. package/dist/src/parsers/SqlParser.d.ts +38 -0
  224. package/dist/src/parsers/SqlParser.js +353 -0
  225. package/dist/src/parsers/SqlParser.js.map +1 -0
  226. package/dist/src/parsers/SqlPrintTokenParser.d.ts +68 -21
  227. package/dist/src/parsers/SqlPrintTokenParser.js +1143 -252
  228. package/dist/src/parsers/SqlPrintTokenParser.js.map +1 -1
  229. package/dist/src/parsers/SqlTokenizer.d.ts +24 -2
  230. package/dist/src/parsers/SqlTokenizer.js +139 -74
  231. package/dist/src/parsers/SqlTokenizer.js.map +1 -1
  232. package/dist/src/parsers/UpdateQueryParser.js +11 -1
  233. package/dist/src/parsers/UpdateQueryParser.js.map +1 -1
  234. package/dist/src/parsers/UsingClauseParser.d.ts +11 -0
  235. package/dist/src/parsers/UsingClauseParser.js +33 -0
  236. package/dist/src/parsers/UsingClauseParser.js.map +1 -0
  237. package/dist/src/parsers/ValueParser.js +5 -1
  238. package/dist/src/parsers/ValueParser.js.map +1 -1
  239. package/dist/src/parsers/ValuesQueryParser.d.ts +0 -2
  240. package/dist/src/parsers/ValuesQueryParser.js +5 -45
  241. package/dist/src/parsers/ValuesQueryParser.js.map +1 -1
  242. package/dist/src/parsers/utils/LexemeCommentUtils.d.ts +6 -0
  243. package/dist/src/parsers/utils/LexemeCommentUtils.js +29 -0
  244. package/dist/src/parsers/utils/LexemeCommentUtils.js.map +1 -0
  245. package/dist/src/tokenReaders/CommandTokenReader.js +49 -2
  246. package/dist/src/tokenReaders/CommandTokenReader.js.map +1 -1
  247. package/dist/src/tokenReaders/LiteralTokenReader.js +8 -5
  248. package/dist/src/tokenReaders/LiteralTokenReader.js.map +1 -1
  249. package/dist/src/tokenReaders/OperatorTokenReader.js +10 -1
  250. package/dist/src/tokenReaders/OperatorTokenReader.js.map +1 -1
  251. package/dist/src/tokenReaders/TypeTokenReader.js +11 -1
  252. package/dist/src/tokenReaders/TypeTokenReader.js.map +1 -1
  253. package/dist/src/transformers/InsertQuerySelectValuesConverter.d.ts +18 -0
  254. package/dist/src/transformers/InsertQuerySelectValuesConverter.js +122 -0
  255. package/dist/src/transformers/InsertQuerySelectValuesConverter.js.map +1 -0
  256. package/dist/src/transformers/LinePrinter.d.ts +2 -0
  257. package/dist/src/transformers/LinePrinter.js +34 -1
  258. package/dist/src/transformers/LinePrinter.js.map +1 -1
  259. package/dist/src/transformers/OnelineFormattingHelper.d.ts +29 -0
  260. package/dist/src/transformers/OnelineFormattingHelper.js +92 -0
  261. package/dist/src/transformers/OnelineFormattingHelper.js.map +1 -0
  262. package/dist/src/transformers/QueryBuilder.d.ts +47 -13
  263. package/dist/src/transformers/QueryBuilder.js +433 -60
  264. package/dist/src/transformers/QueryBuilder.js.map +1 -1
  265. package/dist/src/transformers/SqlFormatter.d.ts +13 -3
  266. package/dist/src/transformers/SqlFormatter.js +20 -6
  267. package/dist/src/transformers/SqlFormatter.js.map +1 -1
  268. package/dist/src/transformers/SqlPrinter.d.ts +63 -10
  269. package/dist/src/transformers/SqlPrinter.js +954 -64
  270. package/dist/src/transformers/SqlPrinter.js.map +1 -1
  271. package/dist/src/types/Formatting.d.ts +8 -0
  272. package/dist/src/types/Formatting.js +3 -0
  273. package/dist/src/types/Formatting.js.map +1 -0
  274. package/dist/src/utils/ParserStringUtils.d.ts +6 -0
  275. package/dist/src/utils/ParserStringUtils.js +31 -0
  276. package/dist/src/utils/ParserStringUtils.js.map +1 -0
  277. package/dist/tsconfig.tsbuildinfo +1 -1
  278. package/package.json +1 -1
@@ -1,6 +1,10 @@
1
1
  import { SqlPrintTokenType, SqlPrintTokenContainerType } from "../models/SqlPrintToken";
2
2
  import { LinePrinter } from "./LinePrinter";
3
3
  import { resolveIndentCharOption, resolveNewlineOption } from "./FormatOptionResolver";
4
+ import { OnelineFormattingHelper, } from "./OnelineFormattingHelper";
5
+ const CREATE_TABLE_SINGLE_PAREN_KEYWORDS = new Set(['unique', 'check', 'key', 'index']);
6
+ const CREATE_TABLE_MULTI_PAREN_KEYWORDS = new Set(['primary key', 'foreign key', 'unique key']);
7
+ const CREATE_TABLE_PAREN_KEYWORDS_WITH_IDENTIFIER = new Set(['references']);
4
8
  /**
5
9
  * SqlPrinter formats a SqlPrintToken tree into a SQL string with flexible style options.
6
10
  *
@@ -29,6 +33,12 @@ export class SqlPrinter {
29
33
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
30
34
  /** Track whether we are currently inside a WITH clause for full-oneline formatting */
31
35
  this.insideWithClause = false;
36
+ /** Tracks nesting depth while formatting MERGE WHEN predicate segments */
37
+ this.mergeWhenPredicateDepth = 0;
38
+ /** Pending line comment that needs a forced newline before next token */
39
+ this.pendingLineCommentBreak = null;
40
+ /** Accumulates lines when reconstructing multi-line block comments inside CommentBlocks */
41
+ this.smartCommentBlockBuilder = null;
32
42
  // Resolve logical options to their control character representations before applying defaults.
33
43
  const resolvedIndentChar = resolveIndentCharOption(options === null || options === void 0 ? void 0 : options.indentChar);
34
44
  const resolvedNewline = resolveNewlineOption(options === null || options === void 0 ? void 0 : options.newline);
@@ -43,17 +53,29 @@ export class SqlPrinter {
43
53
  this.andBreak = (_e = options === null || options === void 0 ? void 0 : options.andBreak) !== null && _e !== void 0 ? _e : 'none';
44
54
  this.orBreak = (_f = options === null || options === void 0 ? void 0 : options.orBreak) !== null && _f !== void 0 ? _f : 'none';
45
55
  this.keywordCase = (_g = options === null || options === void 0 ? void 0 : options.keywordCase) !== null && _g !== void 0 ? _g : 'none';
46
- this.exportComment = (_h = options === null || options === void 0 ? void 0 : options.exportComment) !== null && _h !== void 0 ? _h : false;
47
- this.strictCommentPlacement = (_j = options === null || options === void 0 ? void 0 : options.strictCommentPlacement) !== null && _j !== void 0 ? _j : false;
48
- this.withClauseStyle = (_k = options === null || options === void 0 ? void 0 : options.withClauseStyle) !== null && _k !== void 0 ? _k : 'standard';
49
- this.commentStyle = (_l = options === null || options === void 0 ? void 0 : options.commentStyle) !== null && _l !== void 0 ? _l : 'block';
50
- this.parenthesesOneLine = (_m = options === null || options === void 0 ? void 0 : options.parenthesesOneLine) !== null && _m !== void 0 ? _m : false;
51
- this.betweenOneLine = (_o = options === null || options === void 0 ? void 0 : options.betweenOneLine) !== null && _o !== void 0 ? _o : false;
52
- this.valuesOneLine = (_p = options === null || options === void 0 ? void 0 : options.valuesOneLine) !== null && _p !== void 0 ? _p : false;
53
- this.joinOneLine = (_q = options === null || options === void 0 ? void 0 : options.joinOneLine) !== null && _q !== void 0 ? _q : false;
54
- this.caseOneLine = (_r = options === null || options === void 0 ? void 0 : options.caseOneLine) !== null && _r !== void 0 ? _r : false;
55
- this.subqueryOneLine = (_s = options === null || options === void 0 ? void 0 : options.subqueryOneLine) !== null && _s !== void 0 ? _s : false;
56
- this.indentNestedParentheses = (_t = options === null || options === void 0 ? void 0 : options.indentNestedParentheses) !== null && _t !== void 0 ? _t : false;
56
+ this.commentExportMode = this.resolveCommentExportMode(options === null || options === void 0 ? void 0 : options.exportComment);
57
+ this.withClauseStyle = (_h = options === null || options === void 0 ? void 0 : options.withClauseStyle) !== null && _h !== void 0 ? _h : 'standard';
58
+ this.commentStyle = (_j = options === null || options === void 0 ? void 0 : options.commentStyle) !== null && _j !== void 0 ? _j : 'block';
59
+ this.parenthesesOneLine = (_k = options === null || options === void 0 ? void 0 : options.parenthesesOneLine) !== null && _k !== void 0 ? _k : false;
60
+ this.betweenOneLine = (_l = options === null || options === void 0 ? void 0 : options.betweenOneLine) !== null && _l !== void 0 ? _l : false;
61
+ this.valuesOneLine = (_m = options === null || options === void 0 ? void 0 : options.valuesOneLine) !== null && _m !== void 0 ? _m : false;
62
+ this.joinOneLine = (_o = options === null || options === void 0 ? void 0 : options.joinOneLine) !== null && _o !== void 0 ? _o : false;
63
+ this.caseOneLine = (_p = options === null || options === void 0 ? void 0 : options.caseOneLine) !== null && _p !== void 0 ? _p : false;
64
+ this.subqueryOneLine = (_q = options === null || options === void 0 ? void 0 : options.subqueryOneLine) !== null && _q !== void 0 ? _q : false;
65
+ this.indentNestedParentheses = (_r = options === null || options === void 0 ? void 0 : options.indentNestedParentheses) !== null && _r !== void 0 ? _r : false;
66
+ this.insertColumnsOneLine = (_s = options === null || options === void 0 ? void 0 : options.insertColumnsOneLine) !== null && _s !== void 0 ? _s : false;
67
+ this.whenOneLine = (_t = options === null || options === void 0 ? void 0 : options.whenOneLine) !== null && _t !== void 0 ? _t : false;
68
+ const onelineOptions = {
69
+ parenthesesOneLine: this.parenthesesOneLine,
70
+ betweenOneLine: this.betweenOneLine,
71
+ valuesOneLine: this.valuesOneLine,
72
+ joinOneLine: this.joinOneLine,
73
+ caseOneLine: this.caseOneLine,
74
+ subqueryOneLine: this.subqueryOneLine,
75
+ insertColumnsOneLine: this.insertColumnsOneLine,
76
+ withClauseStyle: this.withClauseStyle,
77
+ };
78
+ this.onelineHelper = new OnelineFormattingHelper(onelineOptions);
57
79
  this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
58
80
  // Initialize
59
81
  this.indentIncrementContainers = new Set((_u = options === null || options === void 0 ? void 0 : options.indentIncrementContainerTypes) !== null && _u !== void 0 ? _u : [
@@ -76,7 +98,11 @@ export class SqlPrinter {
76
98
  SqlPrintTokenContainerType.CaseThenValue,
77
99
  SqlPrintTokenContainerType.ElseClause,
78
100
  SqlPrintTokenContainerType.CaseElseValue,
79
- SqlPrintTokenContainerType.SimpleSelectQuery
101
+ SqlPrintTokenContainerType.SimpleSelectQuery,
102
+ SqlPrintTokenContainerType.CreateTableDefinition,
103
+ SqlPrintTokenContainerType.AlterTableStatement,
104
+ SqlPrintTokenContainerType.IndexColumnList,
105
+ SqlPrintTokenContainerType.SetClause
80
106
  // Note: CommentBlock is intentionally excluded from indentIncrementContainers
81
107
  // because it serves as a grouping mechanism without affecting indentation.
82
108
  // CaseExpression, SwitchCaseArgument, CaseKeyValuePair, and ElseClause
@@ -97,13 +123,50 @@ export class SqlPrinter {
97
123
  // initialize
98
124
  this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
99
125
  this.insideWithClause = false; // Reset WITH clause context
126
+ this.pendingLineCommentBreak = null;
127
+ this.smartCommentBlockBuilder = null;
100
128
  if (this.linePrinter.lines.length > 0 && level !== this.linePrinter.lines[0].level) {
101
129
  this.linePrinter.lines[0].level = level;
102
130
  }
103
131
  this.appendToken(token, level, undefined, 0, false);
104
132
  return this.linePrinter.print();
105
133
  }
106
- appendToken(token, level, parentContainerType, caseContextDepth = 0, indentParentActive = false) {
134
+ // Resolve legacy boolean values into explicit comment export modes.
135
+ resolveCommentExportMode(option) {
136
+ if (option === undefined) {
137
+ return 'none';
138
+ }
139
+ if (option === true) {
140
+ return 'full';
141
+ }
142
+ if (option === false) {
143
+ return 'none';
144
+ }
145
+ return option;
146
+ }
147
+ // Determine whether the current mode allows emitting inline comments.
148
+ rendersInlineComments() {
149
+ return this.commentExportMode === 'full';
150
+ }
151
+ // Decide if a comment block or token should be rendered given its context.
152
+ shouldRenderComment(token, context) {
153
+ if (context === null || context === void 0 ? void 0 : context.forceRender) {
154
+ return this.commentExportMode !== 'none';
155
+ }
156
+ switch (this.commentExportMode) {
157
+ case 'full':
158
+ return true;
159
+ case 'none':
160
+ return false;
161
+ case 'header-only':
162
+ return token.isHeaderComment === true;
163
+ case 'top-header-only':
164
+ return token.isHeaderComment === true && Boolean(context === null || context === void 0 ? void 0 : context.isTopLevelContainer);
165
+ default:
166
+ return false;
167
+ }
168
+ }
169
+ appendToken(token, level, parentContainerType, caseContextDepth = 0, indentParentActive = false, commentContext) {
107
170
  // Track WITH clause context for full-oneline formatting
108
171
  const wasInsideWithClause = this.insideWithClause;
109
172
  if (token.containerType === SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
@@ -112,6 +175,71 @@ export class SqlPrinter {
112
175
  if (this.shouldSkipToken(token)) {
113
176
  return;
114
177
  }
178
+ const containerIsTopLevel = parentContainerType === undefined;
179
+ let leadingCommentCount = 0;
180
+ // Collect leading comment blocks with context so we can respect the export mode.
181
+ const leadingCommentContexts = [];
182
+ if (token.innerTokens && token.innerTokens.length > 0) {
183
+ while (leadingCommentCount < token.innerTokens.length) {
184
+ const leadingCandidate = token.innerTokens[leadingCommentCount];
185
+ if (leadingCandidate.containerType !== SqlPrintTokenContainerType.CommentBlock) {
186
+ break;
187
+ }
188
+ const context = {
189
+ position: 'leading',
190
+ isTopLevelContainer: containerIsTopLevel,
191
+ };
192
+ const shouldRender = this.shouldRenderComment(leadingCandidate, context);
193
+ leadingCommentContexts.push({ token: leadingCandidate, context, shouldRender });
194
+ leadingCommentCount++;
195
+ }
196
+ }
197
+ const hasRenderableLeadingComment = leadingCommentContexts.some(item => item.shouldRender);
198
+ const leadingCommentIndentLevel = hasRenderableLeadingComment
199
+ ? this.getLeadingCommentIndentLevel(parentContainerType, level)
200
+ : null;
201
+ if (hasRenderableLeadingComment
202
+ && !this.isOnelineMode()
203
+ && this.shouldAddNewlineBeforeLeadingComments(parentContainerType)) {
204
+ const currentLine = this.linePrinter.getCurrentLine();
205
+ if (currentLine.text.trim().length > 0) {
206
+ // Align the newline before leading comments with the intended comment indentation.
207
+ this.linePrinter.appendNewline(leadingCommentIndentLevel !== null && leadingCommentIndentLevel !== void 0 ? leadingCommentIndentLevel : level);
208
+ }
209
+ }
210
+ for (const leading of leadingCommentContexts) {
211
+ if (!leading.shouldRender) {
212
+ continue;
213
+ }
214
+ // Keep leading comment processing aligned with its computed indentation level.
215
+ this.appendToken(leading.token, leadingCommentIndentLevel !== null && leadingCommentIndentLevel !== void 0 ? leadingCommentIndentLevel : level, token.containerType, caseContextDepth, indentParentActive, leading.context);
216
+ }
217
+ if (this.smartCommentBlockBuilder && token.containerType !== SqlPrintTokenContainerType.CommentBlock && token.type !== SqlPrintTokenType.commentNewline) {
218
+ this.flushSmartCommentBlockBuilder();
219
+ }
220
+ if (this.pendingLineCommentBreak !== null) {
221
+ if (!this.isOnelineMode()) {
222
+ this.linePrinter.appendNewline(this.pendingLineCommentBreak);
223
+ }
224
+ const shouldSkipToken = token.type === SqlPrintTokenType.commentNewline;
225
+ this.pendingLineCommentBreak = null;
226
+ if (shouldSkipToken) {
227
+ return;
228
+ }
229
+ }
230
+ // Fallback context applies when the caller did not provide comment metadata.
231
+ const effectiveCommentContext = commentContext !== null && commentContext !== void 0 ? commentContext : {
232
+ position: 'inline',
233
+ isTopLevelContainer: containerIsTopLevel,
234
+ };
235
+ if (token.containerType === SqlPrintTokenContainerType.CommentBlock) {
236
+ if (!this.shouldRenderComment(token, effectiveCommentContext)) {
237
+ return;
238
+ }
239
+ const commentLevel = this.getCommentBaseIndentLevel(level, parentContainerType);
240
+ this.handleCommentBlockContainer(token, commentLevel, effectiveCommentContext);
241
+ return;
242
+ }
115
243
  const current = this.linePrinter.getCurrentLine();
116
244
  const isCaseContext = this.isCaseContext(token.containerType);
117
245
  const nextCaseContextDepth = isCaseContext ? caseContextDepth + 1 : caseContextDepth;
@@ -124,7 +252,7 @@ export class SqlPrinter {
124
252
  this.handleCommaToken(token, level, parentContainerType);
125
253
  }
126
254
  else if (token.type === SqlPrintTokenType.parenthesis) {
127
- this.handleParenthesisToken(token, level, indentParentActive);
255
+ this.handleParenthesisToken(token, level, indentParentActive, parentContainerType);
128
256
  }
129
257
  else if (token.type === SqlPrintTokenType.operator && token.text.toLowerCase() === 'and') {
130
258
  this.handleAndOperatorToken(token, level, parentContainerType, caseContextDepth);
@@ -132,37 +260,34 @@ export class SqlPrinter {
132
260
  else if (token.type === SqlPrintTokenType.operator && token.text.toLowerCase() === 'or') {
133
261
  this.handleOrOperatorToken(token, level, parentContainerType, caseContextDepth);
134
262
  }
135
- else if (token.containerType === "JoinClause") {
263
+ else if (token.containerType === SqlPrintTokenContainerType.JoinClause) {
136
264
  this.handleJoinClauseToken(token, level);
137
265
  }
138
266
  else if (token.type === SqlPrintTokenType.comment) {
139
- // Handle comments as regular tokens - let the standard processing handle everything
140
- if (this.exportComment) {
141
- // Note: Smart comment processing is handled at SqlPrintTokenParser level
142
- // via positioned comments system, so we don't need additional processing here
143
- this.linePrinter.appendText(token.text);
267
+ if (this.shouldRenderComment(token, effectiveCommentContext)) {
268
+ const commentLevel = this.getCommentBaseIndentLevel(level, parentContainerType);
269
+ this.printCommentToken(token.text, commentLevel, parentContainerType);
144
270
  }
145
271
  }
146
272
  else if (token.type === SqlPrintTokenType.space) {
147
273
  this.handleSpaceToken(token, parentContainerType);
148
274
  }
149
275
  else if (token.type === SqlPrintTokenType.commentNewline) {
150
- this.handleCommentNewlineToken(token, level);
276
+ if (this.whenOneLine && parentContainerType === SqlPrintTokenContainerType.MergeWhenClause) {
277
+ return;
278
+ }
279
+ const commentLevel = this.getCommentBaseIndentLevel(level, parentContainerType);
280
+ this.handleCommentNewlineToken(token, commentLevel);
151
281
  }
152
282
  else if (token.containerType === SqlPrintTokenContainerType.CommonTable && this.withClauseStyle === 'cte-oneline') {
153
283
  this.handleCteOnelineToken(token, level);
154
284
  return; // Return early to avoid processing innerTokens
155
285
  }
156
- else if ((token.containerType === SqlPrintTokenContainerType.ParenExpression && this.parenthesesOneLine && !shouldIndentNested) ||
157
- (token.containerType === SqlPrintTokenContainerType.BetweenExpression && this.betweenOneLine) ||
158
- (token.containerType === SqlPrintTokenContainerType.Values && this.valuesOneLine) ||
159
- (token.containerType === SqlPrintTokenContainerType.JoinOnClause && this.joinOneLine) ||
160
- (token.containerType === SqlPrintTokenContainerType.CaseExpression && this.caseOneLine) ||
161
- (token.containerType === SqlPrintTokenContainerType.InlineQuery && this.subqueryOneLine)) {
286
+ else if (this.shouldFormatContainerAsOneline(token, shouldIndentNested)) {
162
287
  this.handleOnelineToken(token, level);
163
288
  return; // Return early to avoid processing innerTokens
164
289
  }
165
- else {
290
+ else if (!this.tryAppendInsertClauseTokenText(token.text, parentContainerType)) {
166
291
  this.linePrinter.appendText(token.text);
167
292
  }
168
293
  // append keyword tokens(not indented)
@@ -176,6 +301,8 @@ export class SqlPrinter {
176
301
  let increasedIndent = false;
177
302
  const shouldIncreaseIndent = this.indentIncrementContainers.has(token.containerType) || shouldIndentNested;
178
303
  const delayIndentNewline = shouldIndentNested && token.containerType === SqlPrintTokenContainerType.ParenExpression;
304
+ const isAlterTableStatement = token.containerType === SqlPrintTokenContainerType.AlterTableStatement;
305
+ let deferAlterTableIndent = false;
179
306
  if (!this.isOnelineMode() && shouldIncreaseIndent) {
180
307
  if (this.insideWithClause && this.withClauseStyle === 'full-oneline') {
181
308
  // Keep everything on one line for full-oneline WITH clauses.
@@ -185,15 +312,99 @@ export class SqlPrinter {
185
312
  increasedIndent = true;
186
313
  }
187
314
  else if (current.text !== '') {
188
- innerLevel = level + 1;
315
+ if (isAlterTableStatement) {
316
+ // Delay the first line break so ALTER TABLE keeps the table name on the opening line.
317
+ innerLevel = level + 1;
318
+ increasedIndent = true;
319
+ deferAlterTableIndent = true;
320
+ }
321
+ else {
322
+ let targetIndentLevel = level + 1;
323
+ if (token.containerType === SqlPrintTokenContainerType.SetClause &&
324
+ parentContainerType === SqlPrintTokenContainerType.MergeUpdateAction) {
325
+ targetIndentLevel = level + 2;
326
+ }
327
+ if (this.shouldAlignCreateTableSelect(token.containerType, parentContainerType)) {
328
+ innerLevel = level;
329
+ increasedIndent = false;
330
+ this.linePrinter.appendNewline(level);
331
+ }
332
+ else {
333
+ innerLevel = targetIndentLevel;
334
+ increasedIndent = true;
335
+ this.linePrinter.appendNewline(innerLevel);
336
+ }
337
+ }
338
+ }
339
+ else if (token.containerType === SqlPrintTokenContainerType.SetClause) {
340
+ innerLevel = parentContainerType === SqlPrintTokenContainerType.MergeUpdateAction ? level + 2 : level + 1;
189
341
  increasedIndent = true;
190
- this.linePrinter.appendNewline(innerLevel);
342
+ current.level = innerLevel;
191
343
  }
192
344
  }
193
- for (let i = 0; i < token.innerTokens.length; i++) {
345
+ const isMergeWhenClause = this.whenOneLine && token.containerType === SqlPrintTokenContainerType.MergeWhenClause;
346
+ let mergePredicateActive = isMergeWhenClause;
347
+ let alterTableTableRendered = false;
348
+ let alterTableIndentInserted = false;
349
+ for (let i = leadingCommentCount; i < token.innerTokens.length; i++) {
194
350
  const child = token.innerTokens[i];
351
+ const nextChild = token.innerTokens[i + 1];
352
+ const previousEntry = this.findPreviousSignificantToken(token.innerTokens, i);
353
+ const previousChild = previousEntry === null || previousEntry === void 0 ? void 0 : previousEntry.token;
354
+ const priorEntry = previousEntry ? this.findPreviousSignificantToken(token.innerTokens, previousEntry.index) : undefined;
355
+ const priorChild = priorEntry === null || priorEntry === void 0 ? void 0 : priorEntry.token;
356
+ const childIsAction = this.isMergeActionContainer(child);
357
+ const nextIsAction = this.isMergeActionContainer(nextChild);
358
+ const inMergePredicate = mergePredicateActive && !childIsAction;
359
+ if (isAlterTableStatement) {
360
+ if (child.containerType === SqlPrintTokenContainerType.QualifiedName) {
361
+ // Track when the table name has been printed so we can defer indentation until after it.
362
+ alterTableTableRendered = true;
363
+ }
364
+ else if (deferAlterTableIndent && alterTableTableRendered && !alterTableIndentInserted) {
365
+ if (!this.isOnelineMode()) {
366
+ this.linePrinter.appendNewline(innerLevel);
367
+ }
368
+ alterTableIndentInserted = true;
369
+ deferAlterTableIndent = false;
370
+ if (!this.isOnelineMode() && child.type === SqlPrintTokenType.space) {
371
+ // Drop the space token because we already emitted a newline.
372
+ continue;
373
+ }
374
+ }
375
+ }
376
+ if (child.type === SqlPrintTokenType.space) {
377
+ if (this.shouldConvertSpaceToClauseBreak(token.containerType, nextChild)) {
378
+ if (!this.isOnelineMode()) {
379
+ // Use a dedicated indent resolver so clause breaks can shift indentation for nested blocks.
380
+ const clauseBreakIndent = this.getClauseBreakIndentLevel(token.containerType, innerLevel);
381
+ this.linePrinter.appendNewline(clauseBreakIndent);
382
+ }
383
+ if (isMergeWhenClause && nextIsAction) {
384
+ mergePredicateActive = false;
385
+ }
386
+ continue;
387
+ }
388
+ this.handleSpaceToken(child, token.containerType, nextChild, previousChild, priorChild);
389
+ continue;
390
+ }
195
391
  const childIndentParentActive = token.containerType === SqlPrintTokenContainerType.ParenExpression ? shouldIndentNested : indentParentActive;
196
- this.appendToken(child, innerLevel, token.containerType, nextCaseContextDepth, childIndentParentActive);
392
+ if (inMergePredicate) {
393
+ this.mergeWhenPredicateDepth++;
394
+ }
395
+ const childCommentContext = child.containerType === SqlPrintTokenContainerType.CommentBlock
396
+ ? { position: 'inline', isTopLevelContainer: containerIsTopLevel }
397
+ : undefined;
398
+ this.appendToken(child, innerLevel, token.containerType, nextCaseContextDepth, childIndentParentActive, childCommentContext);
399
+ if (inMergePredicate) {
400
+ this.mergeWhenPredicateDepth--;
401
+ }
402
+ if (childIsAction && isMergeWhenClause) {
403
+ mergePredicateActive = false;
404
+ }
405
+ }
406
+ if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
407
+ this.flushSmartCommentBlockBuilder();
197
408
  }
198
409
  // Exit WITH clause context when we finish processing WithClause container
199
410
  if (token.containerType === SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
@@ -243,11 +454,13 @@ export class SqlPrinter {
243
454
  }
244
455
  handleKeywordToken(token, level, parentContainerType, caseContextDepth = 0) {
245
456
  const lower = token.text.toLowerCase();
246
- if (lower === 'and' && this.andBreak !== 'none') {
457
+ if (lower === 'and' &&
458
+ (this.andBreak !== 'none' || (this.whenOneLine && parentContainerType === SqlPrintTokenContainerType.MergeWhenClause))) {
247
459
  this.handleAndOperatorToken(token, level, parentContainerType, caseContextDepth);
248
460
  return;
249
461
  }
250
- else if (lower === 'or' && this.orBreak !== 'none') {
462
+ else if (lower === 'or' &&
463
+ (this.orBreak !== 'none' || (this.whenOneLine && parentContainerType === SqlPrintTokenContainerType.MergeWhenClause))) {
251
464
  this.handleOrOperatorToken(token, level, parentContainerType, caseContextDepth);
252
465
  return;
253
466
  }
@@ -256,18 +469,50 @@ export class SqlPrinter {
256
469
  this.linePrinter.appendText(text);
257
470
  return;
258
471
  }
472
+ this.ensureSpaceBeforeKeyword();
259
473
  this.linePrinter.appendText(text);
260
474
  }
475
+ ensureSpaceBeforeKeyword() {
476
+ const currentLine = this.linePrinter.getCurrentLine();
477
+ if (currentLine.text === '') {
478
+ return;
479
+ }
480
+ const lastChar = currentLine.text[currentLine.text.length - 1];
481
+ if (lastChar === '(') {
482
+ return;
483
+ }
484
+ this.ensureTrailingSpace();
485
+ }
486
+ ensureTrailingSpace() {
487
+ const currentLine = this.linePrinter.getCurrentLine();
488
+ if (currentLine.text === '') {
489
+ return;
490
+ }
491
+ if (!currentLine.text.endsWith(' ')) {
492
+ currentLine.text += ' ';
493
+ }
494
+ currentLine.text = currentLine.text.replace(/\s+$/, ' ');
495
+ }
496
+ /**
497
+ * Normalizes INSERT column list token text when one-line formatting is active.
498
+ */
499
+ tryAppendInsertClauseTokenText(text, parentContainerType) {
500
+ const currentLineText = this.linePrinter.getCurrentLine().text;
501
+ const result = this.onelineHelper.formatInsertClauseToken(text, parentContainerType, currentLineText, () => this.ensureTrailingSpace());
502
+ if (!result.handled) {
503
+ return false;
504
+ }
505
+ if (result.text) {
506
+ this.linePrinter.appendText(result.text);
507
+ }
508
+ return true;
509
+ }
261
510
  handleCommaToken(token, level, parentContainerType) {
262
511
  const text = token.text;
263
512
  const isWithinWithClause = parentContainerType === SqlPrintTokenContainerType.WithClause;
264
- const isWithinValuesClause = parentContainerType === SqlPrintTokenContainerType.Values;
265
- let effectiveCommaBreak = this.commaBreak;
266
- if (isWithinWithClause) {
267
- effectiveCommaBreak = this.cteCommaBreak;
268
- }
269
- else if (isWithinValuesClause) {
270
- effectiveCommaBreak = this.valuesCommaBreak;
513
+ let effectiveCommaBreak = this.onelineHelper.resolveCommaBreak(parentContainerType, this.commaBreak, this.cteCommaBreak, this.valuesCommaBreak);
514
+ if (parentContainerType === SqlPrintTokenContainerType.SetClause) {
515
+ effectiveCommaBreak = 'before';
271
516
  }
272
517
  // Skip comma newlines when inside WITH clause with full-oneline style
273
518
  if (this.insideWithClause && this.withClauseStyle === 'full-oneline') {
@@ -285,6 +530,14 @@ export class SqlPrinter {
285
530
  }
286
531
  if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
287
532
  this.linePrinter.appendNewline(level);
533
+ if (this.newline === ' ') {
534
+ // Remove the spacer introduced by space newlines so commas attach directly to the preceding token.
535
+ this.linePrinter.trimTrailingWhitespaceFromPreviousLine();
536
+ }
537
+ if (parentContainerType === SqlPrintTokenContainerType.InsertClause) {
538
+ // Align comma-prefixed column entries under the INSERT column indentation.
539
+ this.linePrinter.getCurrentLine().level = level + 1;
540
+ }
288
541
  }
289
542
  this.linePrinter.appendText(text);
290
543
  if (previousCommaBreak !== 'before') {
@@ -296,6 +549,9 @@ export class SqlPrinter {
296
549
  if (previousCommaBreak !== 'after') {
297
550
  this.linePrinter.commaBreak = 'after';
298
551
  }
552
+ if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
553
+ this.linePrinter.appendNewline(level);
554
+ }
299
555
  this.linePrinter.appendText(text);
300
556
  if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
301
557
  this.linePrinter.appendNewline(level);
@@ -310,6 +566,9 @@ export class SqlPrinter {
310
566
  this.linePrinter.commaBreak = 'none';
311
567
  }
312
568
  this.linePrinter.appendText(text);
569
+ if (this.onelineHelper.isInsertClauseOneline(parentContainerType)) {
570
+ this.ensureTrailingSpace();
571
+ }
313
572
  if (previousCommaBreak !== 'none') {
314
573
  this.linePrinter.commaBreak = previousCommaBreak;
315
574
  }
@@ -324,6 +583,11 @@ export class SqlPrinter {
324
583
  this.linePrinter.appendText(text);
325
584
  return;
326
585
  }
586
+ if (this.whenOneLine &&
587
+ (parentContainerType === SqlPrintTokenContainerType.MergeWhenClause || this.mergeWhenPredicateDepth > 0)) {
588
+ this.linePrinter.appendText(text);
589
+ return;
590
+ }
327
591
  if (this.andBreak === 'before') {
328
592
  // Skip newline when inside WITH clause with full-oneline style
329
593
  if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
@@ -342,20 +606,32 @@ export class SqlPrinter {
342
606
  this.linePrinter.appendText(text);
343
607
  }
344
608
  }
345
- handleParenthesisToken(token, level, indentParentActive) {
609
+ handleParenthesisToken(token, level, indentParentActive, parentContainerType) {
346
610
  if (token.text === '(') {
347
611
  this.linePrinter.appendText(token.text);
348
- if (indentParentActive && !this.isOnelineMode()) {
349
- if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
612
+ if ((parentContainerType === SqlPrintTokenContainerType.InsertClause ||
613
+ parentContainerType === SqlPrintTokenContainerType.MergeInsertAction) &&
614
+ this.insertColumnsOneLine) {
615
+ return;
616
+ }
617
+ if (!this.isOnelineMode()) {
618
+ if (this.shouldBreakAfterOpeningParen(parentContainerType)) {
619
+ this.linePrinter.appendNewline(level + 1);
620
+ }
621
+ else if (indentParentActive && !(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
350
622
  this.linePrinter.appendNewline(level);
351
623
  }
352
624
  }
353
625
  return;
354
626
  }
355
- if (token.text === ')' && indentParentActive && !this.isOnelineMode()) {
356
- // Align closing parenthesis with the outer indentation level when nested groups expand.
357
- const closingLevel = Math.max(level - 1, 0);
358
- if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
627
+ if (token.text === ')' && !this.isOnelineMode()) {
628
+ if (this.shouldBreakBeforeClosingParen(parentContainerType)) {
629
+ this.linePrinter.appendNewline(Math.max(level, 0));
630
+ this.linePrinter.appendText(token.text);
631
+ return;
632
+ }
633
+ if (indentParentActive && !(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
634
+ const closingLevel = Math.max(level - 1, 0);
359
635
  this.linePrinter.appendNewline(closingLevel);
360
636
  }
361
637
  }
@@ -368,6 +644,11 @@ export class SqlPrinter {
368
644
  this.linePrinter.appendText(text);
369
645
  return;
370
646
  }
647
+ if (this.whenOneLine &&
648
+ (parentContainerType === SqlPrintTokenContainerType.MergeWhenClause || this.mergeWhenPredicateDepth > 0)) {
649
+ this.linePrinter.appendText(text);
650
+ return;
651
+ }
371
652
  if (this.orBreak === 'before') {
372
653
  // Insert a newline before OR unless WITH full-oneline mode suppresses breaks.
373
654
  if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
@@ -417,34 +698,490 @@ export class SqlPrinter {
417
698
  }
418
699
  handleJoinClauseToken(token, level) {
419
700
  const text = this.applyKeywordCase(token.text);
420
- // before join clause, add newline (skip when inside WITH clause with full-oneline style)
421
- if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
701
+ // before join clause, add newline when multiline formatting is allowed
702
+ if (this.onelineHelper.shouldInsertJoinNewline(this.insideWithClause)) {
422
703
  this.linePrinter.appendNewline(level);
423
704
  }
424
705
  this.linePrinter.appendText(text);
425
706
  }
707
+ /**
708
+ * Decides whether the current container should collapse into a single line.
709
+ */
710
+ shouldFormatContainerAsOneline(token, shouldIndentNested) {
711
+ return this.onelineHelper.shouldFormatContainer(token, shouldIndentNested);
712
+ }
713
+ /**
714
+ * Detects an INSERT column list that must stay on a single line.
715
+ */
716
+ isInsertClauseOneline(parentContainerType) {
717
+ return this.onelineHelper.isInsertClauseOneline(parentContainerType);
718
+ }
426
719
  /**
427
720
  * Handles space tokens with context-aware filtering.
428
721
  * Skips spaces in CommentBlocks when in specific CTE modes to prevent duplication.
429
722
  */
430
- handleSpaceToken(token, parentContainerType) {
431
- if (this.shouldSkipCommentBlockSpace(parentContainerType)) {
723
+ handleSpaceToken(token, parentContainerType, nextToken, previousToken, priorToken) {
724
+ if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
725
+ this.flushSmartCommentBlockBuilder();
726
+ }
727
+ const currentLineText = this.linePrinter.getCurrentLine().text;
728
+ if (this.onelineHelper.shouldSkipInsertClauseSpace(parentContainerType, nextToken, currentLineText)) {
729
+ return;
730
+ }
731
+ if (this.onelineHelper.shouldSkipCommentBlockSpace(parentContainerType, this.insideWithClause)) {
432
732
  const currentLine = this.linePrinter.getCurrentLine();
433
733
  if (currentLine.text !== '' && !currentLine.text.endsWith(' ')) {
434
734
  this.linePrinter.appendText(' ');
435
735
  }
436
736
  return;
437
737
  }
738
+ // Skip redundant spaces before structural parentheses in CREATE TABLE DDL.
739
+ if (this.shouldSkipSpaceBeforeParenthesis(parentContainerType, nextToken, previousToken, priorToken)) {
740
+ return;
741
+ }
438
742
  this.linePrinter.appendText(token.text);
439
743
  }
440
- /**
441
- * Determines whether to skip space tokens in CommentBlocks.
442
- * Prevents duplicate spacing in CTE full-oneline mode only.
443
- */
444
- shouldSkipCommentBlockSpace(parentContainerType) {
445
- return parentContainerType === SqlPrintTokenContainerType.CommentBlock &&
446
- this.insideWithClause &&
447
- this.withClauseStyle === 'full-oneline';
744
+ findPreviousSignificantToken(tokens, index) {
745
+ for (let i = index - 1; i >= 0; i--) {
746
+ const candidate = tokens[i];
747
+ if (candidate.type === SqlPrintTokenType.space || candidate.type === SqlPrintTokenType.commentNewline) {
748
+ continue;
749
+ }
750
+ if (candidate.type === SqlPrintTokenType.comment && !this.rendersInlineComments()) {
751
+ continue;
752
+ }
753
+ return { token: candidate, index: i };
754
+ }
755
+ return undefined;
756
+ }
757
+ shouldSkipSpaceBeforeParenthesis(parentContainerType, nextToken, previousToken, priorToken) {
758
+ if (!nextToken || nextToken.type !== SqlPrintTokenType.parenthesis || nextToken.text !== '(') {
759
+ return false;
760
+ }
761
+ if (!parentContainerType || !this.isCreateTableSpacingContext(parentContainerType)) {
762
+ return false;
763
+ }
764
+ if (!previousToken) {
765
+ return false;
766
+ }
767
+ if (this.isCreateTableNameToken(previousToken, parentContainerType)) {
768
+ return true;
769
+ }
770
+ if (this.isCreateTableConstraintKeyword(previousToken, parentContainerType)) {
771
+ return true;
772
+ }
773
+ if (priorToken && this.isCreateTableConstraintKeyword(priorToken, parentContainerType)) {
774
+ if (this.isIdentifierAttachedToConstraint(previousToken, priorToken, parentContainerType)) {
775
+ return true;
776
+ }
777
+ }
778
+ return false;
779
+ }
780
+ shouldAlignCreateTableSelect(containerType, parentContainerType) {
781
+ return containerType === SqlPrintTokenContainerType.SimpleSelectQuery &&
782
+ parentContainerType === SqlPrintTokenContainerType.CreateTableQuery;
783
+ }
784
+ isCreateTableSpacingContext(parentContainerType) {
785
+ switch (parentContainerType) {
786
+ case SqlPrintTokenContainerType.CreateTableQuery:
787
+ case SqlPrintTokenContainerType.CreateTableDefinition:
788
+ case SqlPrintTokenContainerType.TableConstraintDefinition:
789
+ case SqlPrintTokenContainerType.ColumnConstraintDefinition:
790
+ case SqlPrintTokenContainerType.ReferenceDefinition:
791
+ return true;
792
+ default:
793
+ return false;
794
+ }
795
+ }
796
+ isCreateTableNameToken(previousToken, parentContainerType) {
797
+ if (parentContainerType !== SqlPrintTokenContainerType.CreateTableQuery) {
798
+ return false;
799
+ }
800
+ return previousToken.containerType === SqlPrintTokenContainerType.QualifiedName;
801
+ }
802
+ isCreateTableConstraintKeyword(token, parentContainerType) {
803
+ if (token.type !== SqlPrintTokenType.keyword) {
804
+ return false;
805
+ }
806
+ const text = token.text.toLowerCase();
807
+ if (parentContainerType === SqlPrintTokenContainerType.ReferenceDefinition) {
808
+ return CREATE_TABLE_PAREN_KEYWORDS_WITH_IDENTIFIER.has(text);
809
+ }
810
+ if (CREATE_TABLE_SINGLE_PAREN_KEYWORDS.has(text)) {
811
+ return true;
812
+ }
813
+ if (CREATE_TABLE_MULTI_PAREN_KEYWORDS.has(text)) {
814
+ return true;
815
+ }
816
+ return false;
817
+ }
818
+ isIdentifierAttachedToConstraint(token, keywordToken, parentContainerType) {
819
+ if (!token) {
820
+ return false;
821
+ }
822
+ if (parentContainerType === SqlPrintTokenContainerType.ReferenceDefinition) {
823
+ return token.containerType === SqlPrintTokenContainerType.QualifiedName &&
824
+ CREATE_TABLE_PAREN_KEYWORDS_WITH_IDENTIFIER.has(keywordToken.text.toLowerCase());
825
+ }
826
+ if (parentContainerType === SqlPrintTokenContainerType.TableConstraintDefinition ||
827
+ parentContainerType === SqlPrintTokenContainerType.ColumnConstraintDefinition) {
828
+ const normalized = keywordToken.text.toLowerCase();
829
+ if (CREATE_TABLE_SINGLE_PAREN_KEYWORDS.has(normalized) ||
830
+ CREATE_TABLE_MULTI_PAREN_KEYWORDS.has(normalized)) {
831
+ return token.containerType === SqlPrintTokenContainerType.IdentifierString;
832
+ }
833
+ }
834
+ return false;
835
+ }
836
+ printCommentToken(text, level, parentContainerType) {
837
+ const trimmed = text.trim();
838
+ if (!trimmed) {
839
+ return;
840
+ }
841
+ if (this.commentStyle === 'smart' && parentContainerType === SqlPrintTokenContainerType.CommentBlock) {
842
+ if (this.handleSmartCommentBlockToken(text, trimmed, level)) {
843
+ return;
844
+ }
845
+ }
846
+ if (this.commentStyle === 'smart') {
847
+ const normalized = this.normalizeCommentForSmart(trimmed);
848
+ if (normalized.lines.length > 1 || normalized.forceBlock) {
849
+ const blockText = this.buildBlockComment(normalized.lines, level);
850
+ this.linePrinter.appendText(blockText);
851
+ }
852
+ else {
853
+ const content = normalized.lines[0];
854
+ const lineText = content ? `-- ${content}` : '--';
855
+ if (parentContainerType === SqlPrintTokenContainerType.CommentBlock) {
856
+ this.linePrinter.appendText(lineText);
857
+ this.pendingLineCommentBreak = this.resolveCommentIndentLevel(level, parentContainerType);
858
+ }
859
+ else {
860
+ this.linePrinter.appendText(lineText);
861
+ const effectiveLevel = this.resolveCommentIndentLevel(level, parentContainerType);
862
+ this.linePrinter.appendNewline(effectiveLevel);
863
+ }
864
+ }
865
+ }
866
+ else {
867
+ if (trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
868
+ if (/\r?\n/.test(trimmed)) {
869
+ // Keep multi-line block comments intact by normalizing line endings once.
870
+ const newlineReplacement = this.isOnelineMode() ? ' ' : (typeof this.newline === 'string' ? this.newline : '\n');
871
+ const normalized = trimmed.replace(/\r?\n/g, newlineReplacement);
872
+ this.linePrinter.appendText(normalized);
873
+ }
874
+ else {
875
+ this.linePrinter.appendText(trimmed);
876
+ }
877
+ }
878
+ else {
879
+ this.linePrinter.appendText(trimmed);
880
+ }
881
+ if (trimmed.startsWith('--')) {
882
+ if (parentContainerType === SqlPrintTokenContainerType.CommentBlock) {
883
+ this.pendingLineCommentBreak = this.resolveCommentIndentLevel(level, parentContainerType);
884
+ }
885
+ else {
886
+ const effectiveLevel = this.resolveCommentIndentLevel(level, parentContainerType);
887
+ this.linePrinter.appendNewline(effectiveLevel);
888
+ }
889
+ }
890
+ }
891
+ }
892
+ handleSmartCommentBlockToken(raw, trimmed, level) {
893
+ if (!this.smartCommentBlockBuilder) {
894
+ if (trimmed === '/*') {
895
+ // Begin assembling a multi-line block comment that is emitted as split tokens
896
+ this.smartCommentBlockBuilder = { lines: [], level, mode: 'block' };
897
+ return true;
898
+ }
899
+ const lineContent = this.extractLineCommentContent(trimmed);
900
+ if (lineContent !== null) {
901
+ this.smartCommentBlockBuilder = {
902
+ lines: [lineContent],
903
+ level,
904
+ mode: 'line',
905
+ };
906
+ return true;
907
+ }
908
+ return false;
909
+ }
910
+ if (this.smartCommentBlockBuilder.mode === 'block') {
911
+ if (trimmed === '*/') {
912
+ const { lines, level: blockLevel } = this.smartCommentBlockBuilder;
913
+ const blockText = this.buildBlockComment(lines, blockLevel);
914
+ this.linePrinter.appendText(blockText);
915
+ this.pendingLineCommentBreak = blockLevel;
916
+ this.smartCommentBlockBuilder = null;
917
+ return true;
918
+ }
919
+ this.smartCommentBlockBuilder.lines.push(this.normalizeSmartBlockLine(raw));
920
+ return true;
921
+ }
922
+ const content = this.extractLineCommentContent(trimmed);
923
+ if (content !== null) {
924
+ this.smartCommentBlockBuilder.lines.push(content);
925
+ return true;
926
+ }
927
+ this.flushSmartCommentBlockBuilder();
928
+ return false;
929
+ }
930
+ handleCommentBlockContainer(token, level, context) {
931
+ var _a;
932
+ if (this.commentStyle !== 'smart') {
933
+ const rawLines = this.extractRawCommentBlockLines(token);
934
+ if (rawLines.length > 0) {
935
+ const normalizedBlocks = rawLines.map(line => `/* ${line} */`).join(' ');
936
+ const hasTrailingSpace = (_a = token.innerTokens) === null || _a === void 0 ? void 0 : _a.some(child => child.type === SqlPrintTokenType.space && child.text.includes(' '));
937
+ this.linePrinter.appendText(hasTrailingSpace ? `${normalizedBlocks} ` : normalizedBlocks);
938
+ return;
939
+ }
940
+ for (const child of token.innerTokens) {
941
+ // Force inner comment tokens to render once the block is approved.
942
+ const childContext = {
943
+ position: context.position,
944
+ isTopLevelContainer: context.isTopLevelContainer,
945
+ forceRender: true,
946
+ };
947
+ this.appendToken(child, level, token.containerType, 0, false, childContext);
948
+ }
949
+ return;
950
+ }
951
+ const lines = this.collectCommentBlockLines(token);
952
+ if (lines.length === 0 && !this.smartCommentBlockBuilder) {
953
+ // No meaningful content; treat as empty line comment to preserve spacing
954
+ this.smartCommentBlockBuilder = {
955
+ lines: [''],
956
+ level,
957
+ mode: 'line',
958
+ };
959
+ return;
960
+ }
961
+ if (!this.smartCommentBlockBuilder || this.smartCommentBlockBuilder.mode !== 'line') {
962
+ this.smartCommentBlockBuilder = {
963
+ lines: [...lines],
964
+ level,
965
+ mode: 'line',
966
+ };
967
+ }
968
+ else {
969
+ this.smartCommentBlockBuilder.lines.push(...lines);
970
+ }
971
+ }
972
+ normalizeSmartBlockLine(raw) {
973
+ // Remove trailing whitespace that only carries formatting artifacts
974
+ let line = raw.replace(/\s+$/g, '');
975
+ if (!line) {
976
+ return '';
977
+ }
978
+ if (line.startsWith(' ')) {
979
+ line = line.slice(2);
980
+ }
981
+ if (line.startsWith('* ')) {
982
+ return line.slice(2);
983
+ }
984
+ if (line === '*') {
985
+ return '';
986
+ }
987
+ if (line.startsWith('*')) {
988
+ return line.slice(1);
989
+ }
990
+ return line;
991
+ }
992
+ extractLineCommentContent(trimmed) {
993
+ if (trimmed.startsWith('--')) {
994
+ return trimmed.slice(2).trimStart();
995
+ }
996
+ if (trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
997
+ const inner = trimmed.slice(2, -2).trim();
998
+ return inner;
999
+ }
1000
+ return null;
1001
+ }
1002
+ flushSmartCommentBlockBuilder() {
1003
+ var _a;
1004
+ if (!this.smartCommentBlockBuilder) {
1005
+ return;
1006
+ }
1007
+ const { lines, level, mode } = this.smartCommentBlockBuilder;
1008
+ if (mode === 'line') {
1009
+ const meaningfulLineCount = lines.filter(line => line.trim() !== '').length;
1010
+ if (meaningfulLineCount > 1) {
1011
+ const blockText = this.buildBlockComment(lines, level);
1012
+ this.linePrinter.appendText(blockText);
1013
+ }
1014
+ else {
1015
+ const content = (_a = lines[0]) !== null && _a !== void 0 ? _a : '';
1016
+ const lineText = content ? `-- ${content}` : '--';
1017
+ this.linePrinter.appendText(lineText);
1018
+ }
1019
+ if (!this.isOnelineMode()) {
1020
+ this.linePrinter.appendNewline(level);
1021
+ }
1022
+ this.pendingLineCommentBreak = null;
1023
+ }
1024
+ this.smartCommentBlockBuilder = null;
1025
+ }
1026
+ collectCommentBlockLines(token) {
1027
+ var _a;
1028
+ const lines = [];
1029
+ let collectingBlock = false;
1030
+ for (const child of (_a = token.innerTokens) !== null && _a !== void 0 ? _a : []) {
1031
+ if (child.type === SqlPrintTokenType.comment) {
1032
+ const trimmed = child.text.trim();
1033
+ if (trimmed === '/*') {
1034
+ collectingBlock = true;
1035
+ continue;
1036
+ }
1037
+ if (trimmed === '*/') {
1038
+ collectingBlock = false;
1039
+ continue;
1040
+ }
1041
+ if (collectingBlock) {
1042
+ lines.push(this.normalizeSmartBlockLine(child.text));
1043
+ continue;
1044
+ }
1045
+ const content = this.extractLineCommentContent(trimmed);
1046
+ if (content !== null) {
1047
+ lines.push(content);
1048
+ }
1049
+ }
1050
+ }
1051
+ return lines;
1052
+ }
1053
+ extractRawCommentBlockLines(token) {
1054
+ var _a;
1055
+ const lines = [];
1056
+ let collectingBlock = false;
1057
+ for (const child of (_a = token.innerTokens) !== null && _a !== void 0 ? _a : []) {
1058
+ if (child.type === SqlPrintTokenType.comment) {
1059
+ const text = child.text;
1060
+ const trimmed = text.trim();
1061
+ if (trimmed === '/*') {
1062
+ collectingBlock = true;
1063
+ continue;
1064
+ }
1065
+ if (trimmed === '*/') {
1066
+ collectingBlock = false;
1067
+ continue;
1068
+ }
1069
+ if (collectingBlock) {
1070
+ if (trimmed.length > 0) {
1071
+ lines.push(trimmed);
1072
+ }
1073
+ continue;
1074
+ }
1075
+ }
1076
+ }
1077
+ return lines;
1078
+ }
1079
+ normalizeCommentForSmart(text) {
1080
+ const trimmed = text.trim();
1081
+ let source = trimmed;
1082
+ let forceBlock = false;
1083
+ if (trimmed.startsWith('--')) {
1084
+ source = trimmed.slice(2);
1085
+ }
1086
+ else if (trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
1087
+ const inner = trimmed.slice(2, -2);
1088
+ const normalizedInner = inner.replace(/\r?\n/g, '\n');
1089
+ if (normalizedInner.includes('\n')) {
1090
+ forceBlock = true;
1091
+ source = inner;
1092
+ }
1093
+ else {
1094
+ source = inner;
1095
+ if (!source.trim()) {
1096
+ source = trimmed;
1097
+ }
1098
+ }
1099
+ }
1100
+ const escaped = this.escapeCommentDelimiters(source);
1101
+ const normalized = escaped.replace(/\r?\n/g, '\n');
1102
+ const rawSegments = normalized.split('\n');
1103
+ const processedLines = [];
1104
+ const processedRaw = [];
1105
+ for (const segment of rawSegments) {
1106
+ const rawTrimmed = segment.trim();
1107
+ const sanitized = this.sanitizeCommentLine(segment);
1108
+ if (sanitized.length > 0) {
1109
+ processedLines.push(sanitized);
1110
+ processedRaw.push(rawTrimmed);
1111
+ }
1112
+ }
1113
+ let lines = processedLines;
1114
+ if (lines.length === 0) {
1115
+ lines = [''];
1116
+ }
1117
+ if (!forceBlock && lines.length === 1 && !lines[0] && trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
1118
+ const escapedFull = this.escapeCommentDelimiters(trimmed);
1119
+ lines = [this.sanitizeCommentLine(escapedFull)];
1120
+ }
1121
+ if (!forceBlock && lines.length > 1) {
1122
+ forceBlock = true;
1123
+ }
1124
+ lines = lines.map((line, index) => {
1125
+ var _a;
1126
+ if (/^[-=_+*#]+$/.test(line)) {
1127
+ const rawLine = (_a = processedRaw[index]) !== null && _a !== void 0 ? _a : line;
1128
+ const normalizedRaw = rawLine.replace(/\s+/g, '');
1129
+ if (normalizedRaw.length >= line.length) {
1130
+ return normalizedRaw;
1131
+ }
1132
+ }
1133
+ return line;
1134
+ });
1135
+ return { lines, forceBlock };
1136
+ }
1137
+ buildBlockComment(lines, level) {
1138
+ var _a, _b, _c;
1139
+ if (lines.length <= 1) {
1140
+ const content = (_a = lines[0]) !== null && _a !== void 0 ? _a : '';
1141
+ return content ? `/* ${content} */` : '/* */';
1142
+ }
1143
+ const newline = this.newline === ' ' ? '\n' : this.newline;
1144
+ const currentLevel = (_c = (_b = this.linePrinter.getCurrentLine()) === null || _b === void 0 ? void 0 : _b.level) !== null && _c !== void 0 ? _c : level;
1145
+ const baseIndent = this.getIndentString(currentLevel);
1146
+ const unitIndent = ' ';
1147
+ const innerIndent = baseIndent + unitIndent;
1148
+ const body = lines.map(line => `${innerIndent}${line}`).join(newline);
1149
+ const closing = `${baseIndent}*/`;
1150
+ return `/*${newline}${body}${newline}${closing}`;
1151
+ }
1152
+ getIndentString(level) {
1153
+ if (level <= 0) {
1154
+ return '';
1155
+ }
1156
+ if (this.indentSize <= 0) {
1157
+ return ' '.repeat(level);
1158
+ }
1159
+ const unit = typeof this.indentChar === 'string' ? this.indentChar : '';
1160
+ return unit.repeat(this.indentSize * level);
1161
+ }
1162
+ sanitizeCommentLine(content) {
1163
+ let sanitized = content;
1164
+ sanitized = sanitized.replace(/\u2028|\u2029/g, ' ');
1165
+ sanitized = sanitized.replace(/\s+/g, ' ').trim();
1166
+ return sanitized;
1167
+ }
1168
+ escapeCommentDelimiters(content) {
1169
+ return content
1170
+ .replace(/\/\*/g, '\\/\\*')
1171
+ .replace(/\*\//g, '*\\/');
1172
+ }
1173
+ getCommentBaseIndentLevel(level, parentContainerType) {
1174
+ if (!parentContainerType) {
1175
+ return level;
1176
+ }
1177
+ const clauseAlignedLevel = this.getClauseBreakIndentLevel(parentContainerType, level);
1178
+ return Math.max(level, clauseAlignedLevel);
1179
+ }
1180
+ resolveCommentIndentLevel(level, parentContainerType) {
1181
+ var _a;
1182
+ const baseLevel = this.getCommentBaseIndentLevel(level, parentContainerType);
1183
+ const currentLevel = (_a = this.linePrinter.getCurrentLine().level) !== null && _a !== void 0 ? _a : baseLevel;
1184
+ return Math.max(baseLevel, currentLevel);
448
1185
  }
449
1186
  /**
450
1187
  * Handles commentNewline tokens with conditional newline behavior.
@@ -453,6 +1190,14 @@ export class SqlPrinter {
453
1190
  * Skips newlines in CTE modes (full-oneline, cte-oneline) to maintain one-line format.
454
1191
  */
455
1192
  handleCommentNewlineToken(token, level) {
1193
+ if (this.smartCommentBlockBuilder) {
1194
+ return;
1195
+ }
1196
+ if (this.pendingLineCommentBreak !== null) {
1197
+ this.linePrinter.appendNewline(this.pendingLineCommentBreak);
1198
+ this.pendingLineCommentBreak = null;
1199
+ return;
1200
+ }
456
1201
  if (this.shouldSkipCommentNewline()) {
457
1202
  return;
458
1203
  }
@@ -468,6 +1213,39 @@ export class SqlPrinter {
468
1213
  return (this.insideWithClause && this.withClauseStyle === 'full-oneline') ||
469
1214
  this.withClauseStyle === 'cte-oneline';
470
1215
  }
1216
+ shouldAddNewlineBeforeLeadingComments(parentType) {
1217
+ if (!parentType) {
1218
+ return false;
1219
+ }
1220
+ if (parentType === SqlPrintTokenContainerType.TupleExpression) {
1221
+ return true;
1222
+ }
1223
+ if (parentType === SqlPrintTokenContainerType.InsertClause ||
1224
+ parentType === SqlPrintTokenContainerType.MergeInsertAction) {
1225
+ return !this.insertColumnsOneLine;
1226
+ }
1227
+ if (parentType === SqlPrintTokenContainerType.SetClause) {
1228
+ return true;
1229
+ }
1230
+ if (parentType === SqlPrintTokenContainerType.SelectClause) {
1231
+ return true;
1232
+ }
1233
+ return false;
1234
+ }
1235
+ getLeadingCommentIndentLevel(parentType, currentLevel) {
1236
+ if (parentType === SqlPrintTokenContainerType.TupleExpression) {
1237
+ return currentLevel + 1;
1238
+ }
1239
+ if (parentType === SqlPrintTokenContainerType.InsertClause ||
1240
+ parentType === SqlPrintTokenContainerType.MergeInsertAction ||
1241
+ parentType === SqlPrintTokenContainerType.SelectClause) {
1242
+ return currentLevel + 1;
1243
+ }
1244
+ if (parentType === SqlPrintTokenContainerType.SetClause) {
1245
+ return currentLevel + 1;
1246
+ }
1247
+ return currentLevel;
1248
+ }
471
1249
  /**
472
1250
  * Determines if the printer is in oneliner mode.
473
1251
  * Oneliner mode uses single spaces instead of actual newlines.
@@ -500,10 +1278,10 @@ export class SqlPrinter {
500
1278
  andBreak: this.andBreak,
501
1279
  orBreak: this.orBreak,
502
1280
  keywordCase: this.keywordCase,
503
- exportComment: false,
504
- strictCommentPlacement: this.strictCommentPlacement,
1281
+ exportComment: 'none',
505
1282
  withClauseStyle: 'standard', // Prevent recursive processing
506
1283
  indentNestedParentheses: false,
1284
+ insertColumnsOneLine: this.insertColumnsOneLine,
507
1285
  });
508
1286
  }
509
1287
  /**
@@ -516,6 +1294,117 @@ export class SqlPrinter {
516
1294
  const cleanedResult = this.cleanDuplicateSpaces(onelineResult);
517
1295
  this.linePrinter.appendText(cleanedResult);
518
1296
  }
1297
+ getClauseBreakIndentLevel(parentType, level) {
1298
+ if (!parentType) {
1299
+ return level;
1300
+ }
1301
+ switch (parentType) {
1302
+ case SqlPrintTokenContainerType.MergeWhenClause:
1303
+ // Actions under WHEN clauses should be indented one level deeper than the WHEN line.
1304
+ return level + 1;
1305
+ case SqlPrintTokenContainerType.MergeUpdateAction:
1306
+ case SqlPrintTokenContainerType.MergeDeleteAction:
1307
+ case SqlPrintTokenContainerType.MergeInsertAction:
1308
+ // Keep MERGE actions and their follow-up keywords (e.g., VALUES, WHERE) aligned with the action keyword.
1309
+ return level + 1;
1310
+ default:
1311
+ return level;
1312
+ }
1313
+ }
1314
+ isMergeActionContainer(token) {
1315
+ if (!token) {
1316
+ return false;
1317
+ }
1318
+ switch (token.containerType) {
1319
+ case SqlPrintTokenContainerType.MergeUpdateAction:
1320
+ case SqlPrintTokenContainerType.MergeDeleteAction:
1321
+ case SqlPrintTokenContainerType.MergeInsertAction:
1322
+ case SqlPrintTokenContainerType.MergeDoNothingAction:
1323
+ return true;
1324
+ default:
1325
+ return false;
1326
+ }
1327
+ }
1328
+ shouldBreakAfterOpeningParen(parentType) {
1329
+ if (!parentType) {
1330
+ return false;
1331
+ }
1332
+ if (parentType === SqlPrintTokenContainerType.InsertClause ||
1333
+ parentType === SqlPrintTokenContainerType.MergeInsertAction) {
1334
+ return !this.isInsertClauseOneline(parentType);
1335
+ }
1336
+ return false;
1337
+ }
1338
+ shouldBreakBeforeClosingParen(parentType) {
1339
+ if (!parentType) {
1340
+ return false;
1341
+ }
1342
+ if (parentType === SqlPrintTokenContainerType.InsertClause ||
1343
+ parentType === SqlPrintTokenContainerType.MergeInsertAction) {
1344
+ return !this.isInsertClauseOneline(parentType);
1345
+ }
1346
+ return false;
1347
+ }
1348
+ shouldConvertSpaceToClauseBreak(parentType, nextToken) {
1349
+ if (!parentType || !nextToken) {
1350
+ return false;
1351
+ }
1352
+ const nextKeyword = nextToken.type === SqlPrintTokenType.keyword ? nextToken.text.toLowerCase() : null;
1353
+ const nextContainer = nextToken.containerType;
1354
+ if (parentType === SqlPrintTokenContainerType.MergeQuery) {
1355
+ // Break before USING blocks and before each WHEN clause to mirror statement structure.
1356
+ if (nextKeyword === 'using') {
1357
+ return true;
1358
+ }
1359
+ if (nextContainer === SqlPrintTokenContainerType.MergeWhenClause) {
1360
+ return true;
1361
+ }
1362
+ }
1363
+ if (parentType === SqlPrintTokenContainerType.MergeWhenClause) {
1364
+ // Force the action to start on the next line with additional indentation.
1365
+ if (nextContainer === SqlPrintTokenContainerType.MergeUpdateAction ||
1366
+ nextContainer === SqlPrintTokenContainerType.MergeDeleteAction ||
1367
+ nextContainer === SqlPrintTokenContainerType.MergeInsertAction ||
1368
+ nextContainer === SqlPrintTokenContainerType.MergeDoNothingAction) {
1369
+ return true;
1370
+ }
1371
+ }
1372
+ if (parentType === SqlPrintTokenContainerType.UpdateQuery) {
1373
+ if (nextKeyword === 'set' || nextKeyword === 'from' || nextKeyword === 'where' || nextKeyword === 'returning') {
1374
+ return true;
1375
+ }
1376
+ }
1377
+ if (parentType === SqlPrintTokenContainerType.InsertQuery) {
1378
+ if (nextKeyword === 'returning') {
1379
+ return true;
1380
+ }
1381
+ if (nextKeyword && (nextKeyword.startsWith('select') || nextKeyword.startsWith('values'))) {
1382
+ return true;
1383
+ }
1384
+ if (nextContainer === SqlPrintTokenContainerType.ValuesQuery || nextContainer === SqlPrintTokenContainerType.SimpleSelectQuery) {
1385
+ return true;
1386
+ }
1387
+ if (nextContainer === SqlPrintTokenContainerType.InsertClause) {
1388
+ return true;
1389
+ }
1390
+ }
1391
+ if (parentType === SqlPrintTokenContainerType.DeleteQuery) {
1392
+ if (nextKeyword === 'using' || nextKeyword === 'where' || nextKeyword === 'returning') {
1393
+ return true;
1394
+ }
1395
+ }
1396
+ if (parentType === SqlPrintTokenContainerType.MergeUpdateAction || parentType === SqlPrintTokenContainerType.MergeDeleteAction) {
1397
+ if (nextKeyword === 'where') {
1398
+ return true;
1399
+ }
1400
+ }
1401
+ if (parentType === SqlPrintTokenContainerType.MergeInsertAction) {
1402
+ if (nextKeyword && (nextKeyword.startsWith('values') || nextKeyword === 'default values')) {
1403
+ return true;
1404
+ }
1405
+ }
1406
+ return false;
1407
+ }
519
1408
  /**
520
1409
  * Creates a unified SqlPrinter instance configured for oneline formatting.
521
1410
  * Works for all oneline options: parentheses, BETWEEN, VALUES, JOIN, CASE, subqueries.
@@ -532,8 +1421,8 @@ export class SqlPrinter {
532
1421
  andBreak: 'none', // Disable AND-based line breaks
533
1422
  orBreak: 'none', // Disable OR-based line breaks
534
1423
  keywordCase: this.keywordCase,
535
- exportComment: this.exportComment,
536
- strictCommentPlacement: this.strictCommentPlacement,
1424
+ exportComment: this.commentExportMode,
1425
+ commentStyle: this.commentStyle,
537
1426
  withClauseStyle: 'standard',
538
1427
  parenthesesOneLine: false, // Prevent recursive processing (avoid infinite loops)
539
1428
  betweenOneLine: false, // Prevent recursive processing (avoid infinite loops)
@@ -542,6 +1431,7 @@ export class SqlPrinter {
542
1431
  caseOneLine: false, // Prevent recursive processing (avoid infinite loops)
543
1432
  subqueryOneLine: false, // Prevent recursive processing (avoid infinite loops)
544
1433
  indentNestedParentheses: false,
1434
+ insertColumnsOneLine: this.insertColumnsOneLine,
545
1435
  });
546
1436
  }
547
1437
  /**