rawsql-ts 0.24.1 → 0.24.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.min.js +7 -7
- package/dist/esm/index.min.js.map +2 -2
- package/dist/esm/parsers/CommandExpressionParser.d.ts +2 -0
- package/dist/esm/parsers/CommandExpressionParser.js +49 -4
- package/dist/esm/parsers/CommandExpressionParser.js.map +1 -1
- package/dist/esm/parsers/HavingParser.js +6 -0
- package/dist/esm/parsers/HavingParser.js.map +1 -1
- package/dist/esm/parsers/JoinOnClauseParser.js +6 -0
- package/dist/esm/parsers/JoinOnClauseParser.js.map +1 -1
- package/dist/esm/parsers/LimitClauseParser.js +6 -0
- package/dist/esm/parsers/LimitClauseParser.js.map +1 -1
- package/dist/esm/parsers/OffsetClauseParser.js +6 -0
- package/dist/esm/parsers/OffsetClauseParser.js.map +1 -1
- package/dist/esm/parsers/OrderByClauseParser.d.ts +2 -0
- package/dist/esm/parsers/OrderByClauseParser.js +42 -29
- package/dist/esm/parsers/OrderByClauseParser.js.map +1 -1
- package/dist/esm/parsers/SqlPrintTokenParser.d.ts +3 -0
- package/dist/esm/parsers/SqlPrintTokenParser.js +70 -6
- package/dist/esm/parsers/SqlPrintTokenParser.js.map +1 -1
- package/dist/esm/parsers/ValueParser.js +5 -3
- package/dist/esm/parsers/ValueParser.js.map +1 -1
- package/dist/esm/transformers/SqlFormatter.d.ts +7 -1
- package/dist/esm/transformers/SqlFormatter.js.map +1 -1
- package/dist/esm/transformers/SqlPrinter.d.ts +32 -2
- package/dist/esm/transformers/SqlPrinter.js +255 -33
- package/dist/esm/transformers/SqlPrinter.js.map +1 -1
- package/dist/index.min.js +7 -7
- package/dist/index.min.js.map +2 -2
- package/dist/parsers/CommandExpressionParser.js +49 -4
- package/dist/parsers/CommandExpressionParser.js.map +1 -1
- package/dist/parsers/HavingParser.js +6 -0
- package/dist/parsers/HavingParser.js.map +1 -1
- package/dist/parsers/JoinOnClauseParser.js +6 -0
- package/dist/parsers/JoinOnClauseParser.js.map +1 -1
- package/dist/parsers/LimitClauseParser.js +6 -0
- package/dist/parsers/LimitClauseParser.js.map +1 -1
- package/dist/parsers/OffsetClauseParser.js +6 -0
- package/dist/parsers/OffsetClauseParser.js.map +1 -1
- package/dist/parsers/OrderByClauseParser.js +42 -29
- package/dist/parsers/OrderByClauseParser.js.map +1 -1
- package/dist/parsers/SqlPrintTokenParser.js +71 -6
- package/dist/parsers/SqlPrintTokenParser.js.map +1 -1
- package/dist/parsers/ValueParser.js +5 -3
- package/dist/parsers/ValueParser.js.map +1 -1
- package/dist/src/parsers/CommandExpressionParser.d.ts +2 -0
- package/dist/src/parsers/OrderByClauseParser.d.ts +2 -0
- package/dist/src/parsers/SqlPrintTokenParser.d.ts +3 -0
- package/dist/src/transformers/SqlFormatter.d.ts +7 -1
- package/dist/src/transformers/SqlPrinter.d.ts +32 -2
- package/dist/transformers/SqlFormatter.js.map +1 -1
- package/dist/transformers/SqlPrinter.js +255 -33
- package/dist/transformers/SqlPrinter.js.map +1 -1
- package/dist/tsconfig.browser.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -30,15 +30,21 @@ export class SqlPrinter {
|
|
|
30
30
|
* @param options Optional style settings for pretty printing
|
|
31
31
|
*/
|
|
32
32
|
constructor(options) {
|
|
33
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
33
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
34
34
|
/** Track whether we are currently inside a WITH clause for full-oneline formatting */
|
|
35
35
|
this.insideWithClause = false;
|
|
36
36
|
/** Tracks nesting depth while formatting MERGE WHEN predicate segments */
|
|
37
37
|
this.mergeWhenPredicateDepth = 0;
|
|
38
|
+
/** Tracks nesting depth while formatting JOIN ON condition segments */
|
|
39
|
+
this.joinOnClauseDepth = 0;
|
|
40
|
+
/** Containers whose one-line rendering was rejected by oneLineMaxLength */
|
|
41
|
+
this.expandedOneLineFallbackTokens = new WeakSet();
|
|
38
42
|
/** Pending line comment that needs a forced newline before next token */
|
|
39
43
|
this.pendingLineCommentBreak = null;
|
|
40
44
|
/** Accumulates lines when reconstructing multi-line block comments inside CommentBlocks */
|
|
41
45
|
this.smartCommentBlockBuilder = null;
|
|
46
|
+
/** Tracks function calls whose arguments must expand because rendered comments are present */
|
|
47
|
+
this.commentedFunctionCallDepth = 0;
|
|
42
48
|
// Resolve logical options to their control character representations before applying defaults.
|
|
43
49
|
const resolvedIndentChar = resolveIndentCharOption(options === null || options === void 0 ? void 0 : options.indentChar);
|
|
44
50
|
const resolvedNewline = resolveNewlineOption(options === null || options === void 0 ? void 0 : options.newline);
|
|
@@ -52,19 +58,22 @@ export class SqlPrinter {
|
|
|
52
58
|
this.valuesCommaBreak = (_d = options === null || options === void 0 ? void 0 : options.valuesCommaBreak) !== null && _d !== void 0 ? _d : this.commaBreak;
|
|
53
59
|
this.andBreak = (_e = options === null || options === void 0 ? void 0 : options.andBreak) !== null && _e !== void 0 ? _e : 'none';
|
|
54
60
|
this.orBreak = (_f = options === null || options === void 0 ? void 0 : options.orBreak) !== null && _f !== void 0 ? _f : 'none';
|
|
55
|
-
this.
|
|
61
|
+
this.joinOnBreak = (_g = options === null || options === void 0 ? void 0 : options.joinOnBreak) !== null && _g !== void 0 ? _g : 'none';
|
|
62
|
+
this.keywordCase = (_h = options === null || options === void 0 ? void 0 : options.keywordCase) !== null && _h !== void 0 ? _h : 'none';
|
|
56
63
|
this.commentExportMode = this.resolveCommentExportMode(options === null || options === void 0 ? void 0 : options.exportComment);
|
|
57
|
-
this.withClauseStyle = (
|
|
58
|
-
this.commentStyle = (
|
|
59
|
-
this.parenthesesOneLine = (
|
|
60
|
-
this.betweenOneLine = (
|
|
61
|
-
this.valuesOneLine = (
|
|
62
|
-
this.joinOneLine = (
|
|
63
|
-
this.caseOneLine = (
|
|
64
|
-
this.subqueryOneLine = (
|
|
65
|
-
this.indentNestedParentheses = (
|
|
66
|
-
this.insertColumnsOneLine = (
|
|
67
|
-
this.whenOneLine = (
|
|
64
|
+
this.withClauseStyle = (_j = options === null || options === void 0 ? void 0 : options.withClauseStyle) !== null && _j !== void 0 ? _j : 'standard';
|
|
65
|
+
this.commentStyle = (_k = options === null || options === void 0 ? void 0 : options.commentStyle) !== null && _k !== void 0 ? _k : 'block';
|
|
66
|
+
this.parenthesesOneLine = (_l = options === null || options === void 0 ? void 0 : options.parenthesesOneLine) !== null && _l !== void 0 ? _l : false;
|
|
67
|
+
this.betweenOneLine = (_m = options === null || options === void 0 ? void 0 : options.betweenOneLine) !== null && _m !== void 0 ? _m : false;
|
|
68
|
+
this.valuesOneLine = (_o = options === null || options === void 0 ? void 0 : options.valuesOneLine) !== null && _o !== void 0 ? _o : false;
|
|
69
|
+
this.joinOneLine = (_p = options === null || options === void 0 ? void 0 : options.joinOneLine) !== null && _p !== void 0 ? _p : false;
|
|
70
|
+
this.caseOneLine = (_q = options === null || options === void 0 ? void 0 : options.caseOneLine) !== null && _q !== void 0 ? _q : false;
|
|
71
|
+
this.subqueryOneLine = (_r = options === null || options === void 0 ? void 0 : options.subqueryOneLine) !== null && _r !== void 0 ? _r : false;
|
|
72
|
+
this.indentNestedParentheses = (_s = options === null || options === void 0 ? void 0 : options.indentNestedParentheses) !== null && _s !== void 0 ? _s : false;
|
|
73
|
+
this.insertColumnsOneLine = (_t = options === null || options === void 0 ? void 0 : options.insertColumnsOneLine) !== null && _t !== void 0 ? _t : false;
|
|
74
|
+
this.whenOneLine = (_u = options === null || options === void 0 ? void 0 : options.whenOneLine) !== null && _u !== void 0 ? _u : false;
|
|
75
|
+
this.oneLineMaxLength = this.normalizeOneLineMaxLength(options === null || options === void 0 ? void 0 : options.oneLineMaxLength);
|
|
76
|
+
this.joinConditionContinuationIndent = (_v = options === null || options === void 0 ? void 0 : options.joinConditionContinuationIndent) !== null && _v !== void 0 ? _v : false;
|
|
68
77
|
const onelineOptions = {
|
|
69
78
|
parenthesesOneLine: this.parenthesesOneLine,
|
|
70
79
|
betweenOneLine: this.betweenOneLine,
|
|
@@ -78,7 +87,7 @@ export class SqlPrinter {
|
|
|
78
87
|
this.onelineHelper = new OnelineFormattingHelper(onelineOptions);
|
|
79
88
|
this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
|
|
80
89
|
// Initialize
|
|
81
|
-
this.indentIncrementContainers = new Set((
|
|
90
|
+
this.indentIncrementContainers = new Set((_w = options === null || options === void 0 ? void 0 : options.indentIncrementContainerTypes) !== null && _w !== void 0 ? _w : [
|
|
82
91
|
SqlPrintTokenContainerType.SelectClause,
|
|
83
92
|
SqlPrintTokenContainerType.ReturningClause,
|
|
84
93
|
SqlPrintTokenContainerType.FromClause,
|
|
@@ -124,8 +133,11 @@ export class SqlPrinter {
|
|
|
124
133
|
// initialize
|
|
125
134
|
this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
|
|
126
135
|
this.insideWithClause = false; // Reset WITH clause context
|
|
136
|
+
this.joinOnClauseDepth = 0;
|
|
127
137
|
this.pendingLineCommentBreak = null;
|
|
128
138
|
this.smartCommentBlockBuilder = null;
|
|
139
|
+
this.expandedOneLineFallbackTokens = new WeakSet();
|
|
140
|
+
this.commentedFunctionCallDepth = 0;
|
|
129
141
|
if (this.linePrinter.lines.length > 0 && level !== this.linePrinter.lines[0].level) {
|
|
130
142
|
this.linePrinter.lines[0].level = level;
|
|
131
143
|
}
|
|
@@ -168,6 +180,7 @@ export class SqlPrinter {
|
|
|
168
180
|
}
|
|
169
181
|
}
|
|
170
182
|
appendToken(token, level, parentContainerType, caseContextDepth = 0, indentParentActive = false, commentContext, previousSiblingWasOpenParen = false) {
|
|
183
|
+
var _a;
|
|
171
184
|
// Track WITH clause context for full-oneline formatting
|
|
172
185
|
const wasInsideWithClause = this.insideWithClause;
|
|
173
186
|
if (token.containerType === SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
|
|
@@ -196,12 +209,16 @@ export class SqlPrinter {
|
|
|
196
209
|
}
|
|
197
210
|
}
|
|
198
211
|
const hasRenderableLeadingComment = leadingCommentContexts.some(item => item.shouldRender);
|
|
212
|
+
const leadingCommentFollowsLogicalOperator = hasRenderableLeadingComment && this.currentLineEndsWithLogicalOperator();
|
|
199
213
|
const leadingCommentIndentLevel = hasRenderableLeadingComment
|
|
200
|
-
? this.getLeadingCommentIndentLevel(
|
|
214
|
+
? this.getLeadingCommentIndentLevel(token.containerType === SqlPrintTokenContainerType.SelectItem
|
|
215
|
+
? token.containerType
|
|
216
|
+
: parentContainerType, level)
|
|
201
217
|
: null;
|
|
202
218
|
if (hasRenderableLeadingComment
|
|
203
219
|
&& !this.isOnelineMode()
|
|
204
|
-
&& this.shouldAddNewlineBeforeLeadingComments(parentContainerType)
|
|
220
|
+
&& this.shouldAddNewlineBeforeLeadingComments(parentContainerType)
|
|
221
|
+
&& !this.shouldKeepLeadingCommentOnCommaLine()) {
|
|
205
222
|
const currentLine = this.linePrinter.getCurrentLine();
|
|
206
223
|
if (currentLine.text.trim().length > 0) {
|
|
207
224
|
// Align the newline before leading comments with the intended comment indentation.
|
|
@@ -214,13 +231,26 @@ export class SqlPrinter {
|
|
|
214
231
|
}
|
|
215
232
|
// Keep leading comment processing aligned with its computed indentation level.
|
|
216
233
|
this.appendToken(leading.token, leadingCommentIndentLevel !== null && leadingCommentIndentLevel !== void 0 ? leadingCommentIndentLevel : level, token.containerType, caseContextDepth, indentParentActive, leading.context, false);
|
|
234
|
+
if (token.containerType === SqlPrintTokenContainerType.SelectItem &&
|
|
235
|
+
((_a = this.smartCommentBlockBuilder) === null || _a === void 0 ? void 0 : _a.mode) === 'line') {
|
|
236
|
+
this.flushSmartCommentBlockBuilder();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (leadingCommentFollowsLogicalOperator &&
|
|
240
|
+
this.pendingLineCommentBreak === null &&
|
|
241
|
+
!this.isOnelineMode() &&
|
|
242
|
+
this.linePrinter.getCurrentLine().text.trim().endsWith('*/')) {
|
|
243
|
+
this.linePrinter.appendNewline(level + 1);
|
|
217
244
|
}
|
|
218
245
|
if (this.smartCommentBlockBuilder && token.containerType !== SqlPrintTokenContainerType.CommentBlock && token.type !== SqlPrintTokenType.commentNewline) {
|
|
219
246
|
this.flushSmartCommentBlockBuilder();
|
|
220
247
|
}
|
|
221
248
|
if (this.pendingLineCommentBreak !== null) {
|
|
222
249
|
if (!this.isOnelineMode()) {
|
|
223
|
-
|
|
250
|
+
const pendingBreakLevel = leadingCommentFollowsLogicalOperator
|
|
251
|
+
? this.pendingLineCommentBreak + 1
|
|
252
|
+
: this.pendingLineCommentBreak;
|
|
253
|
+
this.linePrinter.appendNewline(pendingBreakLevel);
|
|
224
254
|
}
|
|
225
255
|
const shouldSkipToken = token.type === SqlPrintTokenType.commentNewline;
|
|
226
256
|
this.pendingLineCommentBreak = null;
|
|
@@ -237,14 +267,22 @@ export class SqlPrinter {
|
|
|
237
267
|
if (!this.shouldRenderComment(token, effectiveCommentContext)) {
|
|
238
268
|
return;
|
|
239
269
|
}
|
|
270
|
+
if (this.shouldKeepLeadingCommentOnCommaLine()) {
|
|
271
|
+
this.ensureTrailingSpace();
|
|
272
|
+
}
|
|
240
273
|
const commentLevel = this.getCommentBaseIndentLevel(level, parentContainerType);
|
|
274
|
+
if (parentContainerType === SqlPrintTokenContainerType.SelectItem &&
|
|
275
|
+
effectiveCommentContext.position === 'leading' &&
|
|
276
|
+
this.linePrinter.getCurrentLine().text.trim() === '') {
|
|
277
|
+
this.linePrinter.getCurrentLine().level = commentLevel;
|
|
278
|
+
}
|
|
241
279
|
this.handleCommentBlockContainer(token, commentLevel, effectiveCommentContext);
|
|
242
280
|
return;
|
|
243
281
|
}
|
|
244
282
|
const current = this.linePrinter.getCurrentLine();
|
|
245
283
|
const isCaseContext = this.isCaseContext(token.containerType);
|
|
246
284
|
const nextCaseContextDepth = isCaseContext ? caseContextDepth + 1 : caseContextDepth;
|
|
247
|
-
|
|
285
|
+
let shouldIndentNested = this.shouldIndentNestedParentheses(token, previousSiblingWasOpenParen);
|
|
248
286
|
// Handle different token types
|
|
249
287
|
if (token.type === SqlPrintTokenType.keyword) {
|
|
250
288
|
this.handleKeywordToken(token, level, parentContainerType, caseContextDepth);
|
|
@@ -252,6 +290,9 @@ export class SqlPrinter {
|
|
|
252
290
|
else if (token.type === SqlPrintTokenType.comma) {
|
|
253
291
|
this.handleCommaToken(token, level, parentContainerType);
|
|
254
292
|
}
|
|
293
|
+
else if (token.type === SqlPrintTokenType.argumentSplitter) {
|
|
294
|
+
this.handleArgumentSplitterToken(token, level, parentContainerType);
|
|
295
|
+
}
|
|
255
296
|
else if (token.type === SqlPrintTokenType.parenthesis) {
|
|
256
297
|
this.handleParenthesisToken(token, level, indentParentActive, parentContainerType);
|
|
257
298
|
}
|
|
@@ -281,16 +322,25 @@ export class SqlPrinter {
|
|
|
281
322
|
this.handleCommentNewlineToken(token, commentLevel);
|
|
282
323
|
}
|
|
283
324
|
else if (token.containerType === SqlPrintTokenContainerType.CommonTable && this.withClauseStyle === 'cte-oneline') {
|
|
284
|
-
this.
|
|
285
|
-
|
|
325
|
+
if (this.tryHandleCteOnelineToken(token, level)) {
|
|
326
|
+
return; // Return early to avoid processing innerTokens
|
|
327
|
+
}
|
|
286
328
|
}
|
|
287
|
-
else if (this.shouldFormatContainerAsOneline(token, shouldIndentNested)) {
|
|
288
|
-
this.handleOnelineToken(token, level);
|
|
329
|
+
else if (this.shouldFormatContainerAsOneline(token, shouldIndentNested) && this.tryHandleOnelineToken(token, level)) {
|
|
289
330
|
return; // Return early to avoid processing innerTokens
|
|
290
331
|
}
|
|
291
332
|
else if (!this.tryAppendInsertClauseTokenText(token.text, parentContainerType)) {
|
|
292
333
|
this.linePrinter.appendText(token.text);
|
|
293
334
|
}
|
|
335
|
+
if (token.containerType === SqlPrintTokenContainerType.JoinOnClause &&
|
|
336
|
+
this.joinOnBreak === 'before' &&
|
|
337
|
+
!this.isOnelineMode() &&
|
|
338
|
+
this.linePrinter.getCurrentLine().text.trim().length > 0) {
|
|
339
|
+
this.linePrinter.appendNewline(level + 1);
|
|
340
|
+
}
|
|
341
|
+
if (this.expandedOneLineFallbackTokens.has(token)) {
|
|
342
|
+
shouldIndentNested = true;
|
|
343
|
+
}
|
|
294
344
|
// append keyword tokens(not indented)
|
|
295
345
|
if (token.keywordTokens && token.keywordTokens.length > 0) {
|
|
296
346
|
for (let i = 0; i < token.keywordTokens.length; i++) {
|
|
@@ -304,6 +354,9 @@ export class SqlPrinter {
|
|
|
304
354
|
const delayIndentNewline = shouldIndentNested && token.containerType === SqlPrintTokenContainerType.ParenExpression;
|
|
305
355
|
const isAlterTableStatement = token.containerType === SqlPrintTokenContainerType.AlterTableStatement;
|
|
306
356
|
let deferAlterTableIndent = false;
|
|
357
|
+
if (token.containerType === SqlPrintTokenContainerType.JoinOnClause && this.joinOnBreak === 'before' && !this.isOnelineMode()) {
|
|
358
|
+
innerLevel = level + 1;
|
|
359
|
+
}
|
|
307
360
|
const alignExplainChild = this.shouldAlignExplainStatementChild(parentContainerType, token.containerType);
|
|
308
361
|
if (alignExplainChild) {
|
|
309
362
|
// Keep EXPLAIN target statements flush left so they render like standalone statements.
|
|
@@ -356,6 +409,15 @@ export class SqlPrinter {
|
|
|
356
409
|
let mergePredicateActive = isMergeWhenClause;
|
|
357
410
|
let alterTableTableRendered = false;
|
|
358
411
|
let alterTableIndentInserted = false;
|
|
412
|
+
const enteredJoinOnClause = token.containerType === SqlPrintTokenContainerType.JoinOnClause;
|
|
413
|
+
if (enteredJoinOnClause) {
|
|
414
|
+
this.joinOnClauseDepth++;
|
|
415
|
+
}
|
|
416
|
+
const enteredCommentedFunctionCall = this.shouldExpandCommentedFunctionCall(token);
|
|
417
|
+
if (enteredCommentedFunctionCall) {
|
|
418
|
+
this.commentedFunctionCallDepth++;
|
|
419
|
+
}
|
|
420
|
+
const enteredLogicalOperatorWithComment = this.isLogicalOperatorWithComment(token);
|
|
359
421
|
for (let i = leadingCommentCount; i < token.innerTokens.length; i++) {
|
|
360
422
|
const child = token.innerTokens[i];
|
|
361
423
|
const nextChild = token.innerTokens[i + 1];
|
|
@@ -406,7 +468,10 @@ export class SqlPrinter {
|
|
|
406
468
|
const childCommentContext = child.containerType === SqlPrintTokenContainerType.CommentBlock
|
|
407
469
|
? { position: 'inline', isTopLevelContainer: containerIsTopLevel }
|
|
408
470
|
: undefined;
|
|
409
|
-
|
|
471
|
+
const childLevel = enteredCommentedFunctionCall && child.containerType === SqlPrintTokenContainerType.ValueList
|
|
472
|
+
? innerLevel + 1
|
|
473
|
+
: innerLevel;
|
|
474
|
+
this.appendToken(child, childLevel, token.containerType, nextCaseContextDepth, childIndentParentActive, childCommentContext, previousChildWasOpenParen);
|
|
410
475
|
if (inMergePredicate) {
|
|
411
476
|
this.mergeWhenPredicateDepth--;
|
|
412
477
|
}
|
|
@@ -414,9 +479,24 @@ export class SqlPrinter {
|
|
|
414
479
|
mergePredicateActive = false;
|
|
415
480
|
}
|
|
416
481
|
}
|
|
482
|
+
if (enteredLogicalOperatorWithComment && !this.isOnelineMode()) {
|
|
483
|
+
const currentLine = this.linePrinter.getCurrentLine();
|
|
484
|
+
if (currentLine.text.trim() === '') {
|
|
485
|
+
currentLine.level = level + 1;
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
this.linePrinter.appendNewline(level + 1);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
417
491
|
if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
|
|
418
492
|
this.flushSmartCommentBlockBuilder();
|
|
419
493
|
}
|
|
494
|
+
if (enteredJoinOnClause) {
|
|
495
|
+
this.joinOnClauseDepth--;
|
|
496
|
+
}
|
|
497
|
+
if (enteredCommentedFunctionCall) {
|
|
498
|
+
this.commentedFunctionCallDepth--;
|
|
499
|
+
}
|
|
420
500
|
// Exit WITH clause context when we finish processing WithClause container
|
|
421
501
|
if (token.containerType === SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
|
|
422
502
|
this.insideWithClause = false;
|
|
@@ -444,6 +524,27 @@ export class SqlPrinter {
|
|
|
444
524
|
return false;
|
|
445
525
|
}
|
|
446
526
|
}
|
|
527
|
+
shouldExpandCommentedFunctionCall(token) {
|
|
528
|
+
return this.commentExportMode !== 'none' &&
|
|
529
|
+
token.containerType === SqlPrintTokenContainerType.FunctionCall &&
|
|
530
|
+
token.innerTokens.some(child => child.containerType === SqlPrintTokenContainerType.ValueList &&
|
|
531
|
+
this.containsCommentBlock(child));
|
|
532
|
+
}
|
|
533
|
+
containsCommentBlock(token) {
|
|
534
|
+
if (token.containerType === SqlPrintTokenContainerType.CommentBlock) {
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
537
|
+
return token.innerTokens.some(child => this.containsCommentBlock(child));
|
|
538
|
+
}
|
|
539
|
+
isLogicalOperatorWithComment(token) {
|
|
540
|
+
return this.containsCommentBlock(token) &&
|
|
541
|
+
token.type === SqlPrintTokenType.operator &&
|
|
542
|
+
['and', 'or'].includes(token.text.toLowerCase());
|
|
543
|
+
}
|
|
544
|
+
currentLineEndsWithLogicalOperator() {
|
|
545
|
+
const trimmed = this.linePrinter.getCurrentLine().text.trim().toLowerCase();
|
|
546
|
+
return trimmed === 'and' || trimmed === 'or';
|
|
547
|
+
}
|
|
447
548
|
isCaseContext(containerType) {
|
|
448
549
|
switch (containerType) {
|
|
449
550
|
case SqlPrintTokenContainerType.CaseExpression:
|
|
@@ -603,6 +704,14 @@ export class SqlPrinter {
|
|
|
603
704
|
this.linePrinter.appendText(text);
|
|
604
705
|
}
|
|
605
706
|
}
|
|
707
|
+
handleArgumentSplitterToken(token, level, parentContainerType) {
|
|
708
|
+
this.linePrinter.appendText(token.text);
|
|
709
|
+
if (this.commentedFunctionCallDepth > 0 &&
|
|
710
|
+
parentContainerType === SqlPrintTokenContainerType.ValueList &&
|
|
711
|
+
!this.isOnelineMode()) {
|
|
712
|
+
this.linePrinter.appendNewline(level);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
606
715
|
handleAndOperatorToken(token, level, parentContainerType, caseContextDepth = 0) {
|
|
607
716
|
const text = this.applyKeywordCase(token.text);
|
|
608
717
|
if (caseContextDepth > 0) {
|
|
@@ -617,7 +726,7 @@ export class SqlPrinter {
|
|
|
617
726
|
if (this.andBreak === 'before') {
|
|
618
727
|
// Skip newline when inside WITH clause with full-oneline style
|
|
619
728
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
620
|
-
this.linePrinter.appendNewline(level);
|
|
729
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
621
730
|
}
|
|
622
731
|
this.linePrinter.appendText(text);
|
|
623
732
|
}
|
|
@@ -625,7 +734,7 @@ export class SqlPrinter {
|
|
|
625
734
|
this.linePrinter.appendText(text);
|
|
626
735
|
// Skip newline when inside WITH clause with full-oneline style
|
|
627
736
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
628
|
-
this.linePrinter.appendNewline(level);
|
|
737
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
629
738
|
}
|
|
630
739
|
}
|
|
631
740
|
else {
|
|
@@ -635,6 +744,12 @@ export class SqlPrinter {
|
|
|
635
744
|
handleParenthesisToken(token, level, indentParentActive, parentContainerType) {
|
|
636
745
|
if (token.text === '(') {
|
|
637
746
|
this.linePrinter.appendText(token.text);
|
|
747
|
+
if (this.commentedFunctionCallDepth > 0 &&
|
|
748
|
+
parentContainerType === SqlPrintTokenContainerType.FunctionCall &&
|
|
749
|
+
!this.isOnelineMode()) {
|
|
750
|
+
this.linePrinter.appendNewline(level + 1);
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
638
753
|
if ((parentContainerType === SqlPrintTokenContainerType.InsertClause ||
|
|
639
754
|
parentContainerType === SqlPrintTokenContainerType.MergeInsertAction) &&
|
|
640
755
|
this.insertColumnsOneLine) {
|
|
@@ -644,19 +759,29 @@ export class SqlPrinter {
|
|
|
644
759
|
if (this.shouldBreakAfterOpeningParen(parentContainerType)) {
|
|
645
760
|
this.linePrinter.appendNewline(level + 1);
|
|
646
761
|
}
|
|
647
|
-
else if (indentParentActive &&
|
|
762
|
+
else if (indentParentActive &&
|
|
763
|
+
parentContainerType === SqlPrintTokenContainerType.ParenExpression &&
|
|
764
|
+
!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
648
765
|
this.linePrinter.appendNewline(level);
|
|
649
766
|
}
|
|
650
767
|
}
|
|
651
768
|
return;
|
|
652
769
|
}
|
|
653
770
|
if (token.text === ')' && !this.isOnelineMode()) {
|
|
771
|
+
if (this.commentedFunctionCallDepth > 0 &&
|
|
772
|
+
parentContainerType === SqlPrintTokenContainerType.FunctionCall) {
|
|
773
|
+
this.linePrinter.appendNewline(level);
|
|
774
|
+
this.linePrinter.appendText(token.text);
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
654
777
|
if (this.shouldBreakBeforeClosingParen(parentContainerType)) {
|
|
655
778
|
this.linePrinter.appendNewline(Math.max(level, 0));
|
|
656
779
|
this.linePrinter.appendText(token.text);
|
|
657
780
|
return;
|
|
658
781
|
}
|
|
659
|
-
if (indentParentActive &&
|
|
782
|
+
if (indentParentActive &&
|
|
783
|
+
parentContainerType === SqlPrintTokenContainerType.ParenExpression &&
|
|
784
|
+
!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
660
785
|
const closingLevel = Math.max(level - 1, 0);
|
|
661
786
|
this.linePrinter.appendNewline(closingLevel);
|
|
662
787
|
}
|
|
@@ -678,7 +803,7 @@ export class SqlPrinter {
|
|
|
678
803
|
if (this.orBreak === 'before') {
|
|
679
804
|
// Insert a newline before OR unless WITH full-oneline mode suppresses breaks.
|
|
680
805
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
681
|
-
this.linePrinter.appendNewline(level);
|
|
806
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
682
807
|
}
|
|
683
808
|
this.linePrinter.appendText(text);
|
|
684
809
|
}
|
|
@@ -686,13 +811,22 @@ export class SqlPrinter {
|
|
|
686
811
|
this.linePrinter.appendText(text);
|
|
687
812
|
// Break after OR when multi-line formatting is active.
|
|
688
813
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
689
|
-
this.linePrinter.appendNewline(level);
|
|
814
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
690
815
|
}
|
|
691
816
|
}
|
|
692
817
|
else {
|
|
693
818
|
this.linePrinter.appendText(text);
|
|
694
819
|
}
|
|
695
820
|
}
|
|
821
|
+
getJoinConditionContinuationLevel(level) {
|
|
822
|
+
if (this.joinOnClauseDepth === 0) {
|
|
823
|
+
return level;
|
|
824
|
+
}
|
|
825
|
+
if (this.joinOnBreak === 'before') {
|
|
826
|
+
return level;
|
|
827
|
+
}
|
|
828
|
+
return this.joinConditionContinuationIndent ? level + 1 : level;
|
|
829
|
+
}
|
|
696
830
|
/**
|
|
697
831
|
* Decide whether a parentheses group should increase indentation when inside nested structures.
|
|
698
832
|
* We only expand groups that contain further parentheses so simple comparisons stay compact.
|
|
@@ -704,6 +838,9 @@ export class SqlPrinter {
|
|
|
704
838
|
if (token.containerType !== SqlPrintTokenContainerType.ParenExpression) {
|
|
705
839
|
return false;
|
|
706
840
|
}
|
|
841
|
+
if (this.expandedOneLineFallbackTokens.has(token)) {
|
|
842
|
+
return true;
|
|
843
|
+
}
|
|
707
844
|
// Look for nested parentheses containers. If present, indent to highlight grouping.
|
|
708
845
|
return previousSiblingWasOpenParen || token.innerTokens.some((child) => this.containsParenExpression(child));
|
|
709
846
|
}
|
|
@@ -750,6 +887,12 @@ export class SqlPrinter {
|
|
|
750
887
|
if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
|
|
751
888
|
this.flushSmartCommentBlockBuilder();
|
|
752
889
|
}
|
|
890
|
+
if (this.commentedFunctionCallDepth > 0 &&
|
|
891
|
+
parentContainerType === SqlPrintTokenContainerType.ValueList &&
|
|
892
|
+
(previousToken === null || previousToken === void 0 ? void 0 : previousToken.type) === SqlPrintTokenType.argumentSplitter &&
|
|
893
|
+
!this.isOnelineMode()) {
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
753
896
|
const currentLineText = this.linePrinter.getCurrentLine().text;
|
|
754
897
|
if (this.onelineHelper.shouldSkipInsertClauseSpace(parentContainerType, nextToken, currentLineText)) {
|
|
755
898
|
return;
|
|
@@ -974,6 +1117,11 @@ export class SqlPrinter {
|
|
|
974
1117
|
}
|
|
975
1118
|
return;
|
|
976
1119
|
}
|
|
1120
|
+
const emptyBlockCommentText = this.getEmptyBlockCommentText(token);
|
|
1121
|
+
if (emptyBlockCommentText !== null) {
|
|
1122
|
+
this.linePrinter.appendText(emptyBlockCommentText);
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
977
1125
|
const lines = this.collectCommentBlockLines(token);
|
|
978
1126
|
if (lines.length === 0 && !this.smartCommentBlockBuilder) {
|
|
979
1127
|
// No meaningful content; treat as empty line comment to preserve spacing
|
|
@@ -995,6 +1143,18 @@ export class SqlPrinter {
|
|
|
995
1143
|
this.smartCommentBlockBuilder.lines.push(...lines);
|
|
996
1144
|
}
|
|
997
1145
|
}
|
|
1146
|
+
getEmptyBlockCommentText(token) {
|
|
1147
|
+
var _a;
|
|
1148
|
+
const commentTokens = ((_a = token.innerTokens) !== null && _a !== void 0 ? _a : []).filter(child => child.type === SqlPrintTokenType.comment);
|
|
1149
|
+
if (commentTokens.length !== 1) {
|
|
1150
|
+
return null;
|
|
1151
|
+
}
|
|
1152
|
+
const trimmed = commentTokens[0].text.trim();
|
|
1153
|
+
if (!trimmed.startsWith('/*') || !trimmed.endsWith('*/')) {
|
|
1154
|
+
return null;
|
|
1155
|
+
}
|
|
1156
|
+
return trimmed.slice(2, -2).trim() === '' ? trimmed : null;
|
|
1157
|
+
}
|
|
998
1158
|
normalizeSmartBlockLine(raw) {
|
|
999
1159
|
// Remove trailing whitespace that only carries formatting artifacts
|
|
1000
1160
|
let line = raw.replace(/\s+$/g, '');
|
|
@@ -1070,7 +1230,12 @@ export class SqlPrinter {
|
|
|
1070
1230
|
}
|
|
1071
1231
|
const content = this.extractLineCommentContent(trimmed);
|
|
1072
1232
|
if (content !== null) {
|
|
1073
|
-
|
|
1233
|
+
if (!content && trimmed.startsWith('/*') && trimmed.endsWith('*/')) {
|
|
1234
|
+
lines.push(this.sanitizeCommentLine(this.escapeCommentDelimiters(trimmed)));
|
|
1235
|
+
}
|
|
1236
|
+
else {
|
|
1237
|
+
lines.push(content);
|
|
1238
|
+
}
|
|
1074
1239
|
}
|
|
1075
1240
|
}
|
|
1076
1241
|
}
|
|
@@ -1256,6 +1421,10 @@ export class SqlPrinter {
|
|
|
1256
1421
|
if (parentType === SqlPrintTokenContainerType.SelectClause) {
|
|
1257
1422
|
return true;
|
|
1258
1423
|
}
|
|
1424
|
+
if (parentType === SqlPrintTokenContainerType.OrderByItem ||
|
|
1425
|
+
parentType === SqlPrintTokenContainerType.GroupByClause) {
|
|
1426
|
+
return true;
|
|
1427
|
+
}
|
|
1259
1428
|
if (parentType === SqlPrintTokenContainerType.ExplainStatement) {
|
|
1260
1429
|
// Ensure EXPLAIN targets print header comments on a dedicated line.
|
|
1261
1430
|
return true;
|
|
@@ -1266,6 +1435,13 @@ export class SqlPrinter {
|
|
|
1266
1435
|
return false;
|
|
1267
1436
|
}
|
|
1268
1437
|
getLeadingCommentIndentLevel(parentType, currentLevel) {
|
|
1438
|
+
if (parentType === SqlPrintTokenContainerType.SelectItem) {
|
|
1439
|
+
return currentLevel;
|
|
1440
|
+
}
|
|
1441
|
+
if (parentType === SqlPrintTokenContainerType.OrderByItem ||
|
|
1442
|
+
parentType === SqlPrintTokenContainerType.GroupByClause) {
|
|
1443
|
+
return currentLevel;
|
|
1444
|
+
}
|
|
1269
1445
|
if (parentType === SqlPrintTokenContainerType.TupleExpression) {
|
|
1270
1446
|
return currentLevel + 1;
|
|
1271
1447
|
}
|
|
@@ -1280,6 +1456,12 @@ export class SqlPrinter {
|
|
|
1280
1456
|
}
|
|
1281
1457
|
return currentLevel;
|
|
1282
1458
|
}
|
|
1459
|
+
shouldKeepLeadingCommentOnCommaLine() {
|
|
1460
|
+
if (this.commaBreak !== 'before') {
|
|
1461
|
+
return false;
|
|
1462
|
+
}
|
|
1463
|
+
return this.linePrinter.getCurrentLine().text.trim() === ',';
|
|
1464
|
+
}
|
|
1283
1465
|
/**
|
|
1284
1466
|
* Determines if the printer is in oneliner mode.
|
|
1285
1467
|
* Oneliner mode uses single spaces instead of actual newlines.
|
|
@@ -1287,16 +1469,36 @@ export class SqlPrinter {
|
|
|
1287
1469
|
isOnelineMode() {
|
|
1288
1470
|
return this.newline === ' ';
|
|
1289
1471
|
}
|
|
1472
|
+
normalizeOneLineMaxLength(value) {
|
|
1473
|
+
if (value === undefined || !Number.isFinite(value) || value <= 0) {
|
|
1474
|
+
return undefined;
|
|
1475
|
+
}
|
|
1476
|
+
const normalized = Math.floor(value);
|
|
1477
|
+
return normalized > 0 ? normalized : undefined;
|
|
1478
|
+
}
|
|
1479
|
+
fitsOneLineMaxLength(text) {
|
|
1480
|
+
if (this.oneLineMaxLength === undefined) {
|
|
1481
|
+
return true;
|
|
1482
|
+
}
|
|
1483
|
+
const currentLine = this.linePrinter.getCurrentLine();
|
|
1484
|
+
const indentWidth = currentLine.level * this.indentSize * String(this.indentChar).length;
|
|
1485
|
+
return indentWidth + currentLine.text.length + text.length <= this.oneLineMaxLength;
|
|
1486
|
+
}
|
|
1290
1487
|
/**
|
|
1291
1488
|
* Handles CTE tokens with one-liner formatting.
|
|
1292
1489
|
* Creates a nested SqlPrinter instance for proper CTE oneline formatting.
|
|
1293
1490
|
*/
|
|
1294
|
-
|
|
1491
|
+
tryHandleCteOnelineToken(token, level) {
|
|
1295
1492
|
const onelinePrinter = this.createCteOnelinePrinter();
|
|
1296
1493
|
const onelineResult = onelinePrinter.print(token, level);
|
|
1297
1494
|
let cleanedResult = this.cleanDuplicateSpaces(onelineResult);
|
|
1298
1495
|
cleanedResult = cleanedResult.replace(/\(\s+/g, '(').replace(/\s+\)/g, ' )');
|
|
1299
|
-
|
|
1496
|
+
const trimmedResult = cleanedResult.trim();
|
|
1497
|
+
if (!this.fitsOneLineMaxLength(trimmedResult)) {
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
this.linePrinter.appendText(trimmedResult);
|
|
1501
|
+
return true;
|
|
1300
1502
|
}
|
|
1301
1503
|
/**
|
|
1302
1504
|
* Creates a SqlPrinter instance configured for CTE oneline formatting.
|
|
@@ -1322,11 +1524,31 @@ export class SqlPrinter {
|
|
|
1322
1524
|
* Handles tokens with oneline formatting (parentheses, BETWEEN, VALUES, JOIN, CASE, subqueries).
|
|
1323
1525
|
* Creates a unified oneline printer that formats everything as one line regardless of content type.
|
|
1324
1526
|
*/
|
|
1325
|
-
|
|
1527
|
+
tryHandleOnelineToken(token, level) {
|
|
1326
1528
|
const onelinePrinter = this.createOnelinePrinter();
|
|
1327
1529
|
const onelineResult = onelinePrinter.print(token, level);
|
|
1328
1530
|
const cleanedResult = this.cleanDuplicateSpaces(onelineResult);
|
|
1531
|
+
if (!this.fitsOneLineMaxLength(cleanedResult)) {
|
|
1532
|
+
if (this.isBooleanParenExpression(token)) {
|
|
1533
|
+
this.expandedOneLineFallbackTokens.add(token);
|
|
1534
|
+
}
|
|
1535
|
+
return false;
|
|
1536
|
+
}
|
|
1329
1537
|
this.linePrinter.appendText(cleanedResult);
|
|
1538
|
+
return true;
|
|
1539
|
+
}
|
|
1540
|
+
isBooleanParenExpression(token) {
|
|
1541
|
+
if (token.containerType !== SqlPrintTokenContainerType.ParenExpression) {
|
|
1542
|
+
return false;
|
|
1543
|
+
}
|
|
1544
|
+
return this.containsLogicalOperator(token);
|
|
1545
|
+
}
|
|
1546
|
+
containsLogicalOperator(token) {
|
|
1547
|
+
if ((token.type === SqlPrintTokenType.operator || token.type === SqlPrintTokenType.keyword) &&
|
|
1548
|
+
['and', 'or'].includes(token.text.toLowerCase())) {
|
|
1549
|
+
return true;
|
|
1550
|
+
}
|
|
1551
|
+
return token.innerTokens.some((child) => this.containsLogicalOperator(child));
|
|
1330
1552
|
}
|
|
1331
1553
|
getClauseBreakIndentLevel(parentType, level) {
|
|
1332
1554
|
if (!parentType) {
|