rawsql-ts 0.24.1 → 0.24.2
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 +2 -2
- package/dist/esm/index.min.js.map +2 -2
- 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 +23 -2
- package/dist/esm/transformers/SqlPrinter.js +112 -28
- package/dist/esm/transformers/SqlPrinter.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +2 -2
- package/dist/src/transformers/SqlFormatter.d.ts +7 -1
- package/dist/src/transformers/SqlPrinter.d.ts +23 -2
- package/dist/transformers/SqlFormatter.js.map +1 -1
- package/dist/transformers/SqlPrinter.js +112 -28
- package/dist/transformers/SqlPrinter.js.map +1 -1
- package/dist/tsconfig.browser.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CastStyle, ConstraintStyle, SourceAliasStyle, OrderByDefaultDirectionStyle } from '../parsers/SqlPrintTokenParser';
|
|
2
|
-
import { CommaBreakStyle, AndBreakStyle, OrBreakStyle } from './SqlPrinter';
|
|
2
|
+
import { CommaBreakStyle, AndBreakStyle, OrBreakStyle, JoinOnBreakStyle } from './SqlPrinter';
|
|
3
3
|
import { CommentExportMode } from '../types/Formatting';
|
|
4
4
|
import { IndentCharOption, NewlineOption } from './LinePrinter';
|
|
5
5
|
import { IdentifierEscapeOption, IdentifierEscapeTarget } from './FormatOptionResolver';
|
|
@@ -49,6 +49,8 @@ export interface BaseFormattingOptions {
|
|
|
49
49
|
andBreak?: AndBreakStyle;
|
|
50
50
|
/** Style for OR line breaks */
|
|
51
51
|
orBreak?: OrBreakStyle;
|
|
52
|
+
/** Style for JOIN ON line breaks */
|
|
53
|
+
joinOnBreak?: JoinOnBreakStyle;
|
|
52
54
|
/** Whether to export comments in formatted output */
|
|
53
55
|
exportComment?: boolean | CommentExportMode;
|
|
54
56
|
/** Comment formatting style */
|
|
@@ -73,6 +75,10 @@ export interface BaseFormattingOptions {
|
|
|
73
75
|
insertColumnsOneLine?: boolean;
|
|
74
76
|
/** Keep MERGE WHEN clause predicates on one line regardless of AND break settings */
|
|
75
77
|
whenOneLine?: boolean;
|
|
78
|
+
/** Maximum rendered width for opt-in one-line constructs. Omit to keep legacy unlimited one-line behavior. */
|
|
79
|
+
oneLineMaxLength?: number;
|
|
80
|
+
/** Indent AND/OR continuation lines inside JOIN ON predicates */
|
|
81
|
+
joinConditionContinuationIndent?: boolean;
|
|
76
82
|
/** Reorder JOIN ON column comparisons to follow table declaration order */
|
|
77
83
|
joinConditionOrderByDeclaration?: boolean;
|
|
78
84
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlFormatter.js","sourceRoot":"","sources":["../../../src/transformers/SqlFormatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAmB,OAAO,EAA8E,MAAM,gCAAgC,CAAC;AAC3K,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"SqlFormatter.js","sourceRoot":"","sources":["../../../src/transformers/SqlFormatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,12 @@ export type AndBreakStyle = 'none' | 'before' | 'after';
|
|
|
24
24
|
* - 'after': Line break after OR
|
|
25
25
|
*/
|
|
26
26
|
export type OrBreakStyle = 'none' | 'before' | 'after';
|
|
27
|
+
/**
|
|
28
|
+
* JoinOnBreakStyle determines whether JOIN ON starts on the JOIN line or its own indented line.
|
|
29
|
+
* - 'none': Keep ON inline with the JOIN target
|
|
30
|
+
* - 'before': Break before ON and indent the join condition
|
|
31
|
+
*/
|
|
32
|
+
export type JoinOnBreakStyle = 'none' | 'before';
|
|
27
33
|
/**
|
|
28
34
|
* Options for configuring SqlPrinter formatting behavior
|
|
29
35
|
*/
|
|
@@ -68,6 +74,8 @@ export declare class SqlPrinter {
|
|
|
68
74
|
andBreak: AndBreakStyle;
|
|
69
75
|
/** OR break style: 'none', 'before', or 'after' */
|
|
70
76
|
orBreak: OrBreakStyle;
|
|
77
|
+
/** JOIN ON break style: 'none' or 'before' */
|
|
78
|
+
joinOnBreak: JoinOnBreakStyle;
|
|
71
79
|
/** Keyword case style: 'none', 'upper' | 'lower' */
|
|
72
80
|
keywordCase: 'none' | 'upper' | 'lower';
|
|
73
81
|
/** Comment export mode controlling how comments are emitted */
|
|
@@ -98,10 +106,18 @@ export declare class SqlPrinter {
|
|
|
98
106
|
private insertColumnsOneLine;
|
|
99
107
|
/** Whether to keep MERGE WHEN predicates on a single line */
|
|
100
108
|
private whenOneLine;
|
|
109
|
+
/** Optional maximum width for opt-in one-line constructs */
|
|
110
|
+
private oneLineMaxLength?;
|
|
111
|
+
/** Whether to indent AND/OR continuation lines inside JOIN ON predicates */
|
|
112
|
+
private joinConditionContinuationIndent;
|
|
101
113
|
/** Tracks nesting depth while formatting MERGE WHEN predicate segments */
|
|
102
114
|
private mergeWhenPredicateDepth;
|
|
115
|
+
/** Tracks nesting depth while formatting JOIN ON condition segments */
|
|
116
|
+
private joinOnClauseDepth;
|
|
103
117
|
/** Shared helper for oneline-specific formatting decisions */
|
|
104
118
|
private onelineHelper;
|
|
119
|
+
/** Containers whose one-line rendering was rejected by oneLineMaxLength */
|
|
120
|
+
private expandedOneLineFallbackTokens;
|
|
105
121
|
/** Pending line comment that needs a forced newline before next token */
|
|
106
122
|
private pendingLineCommentBreak;
|
|
107
123
|
/** Accumulates lines when reconstructing multi-line block comments inside CommentBlocks */
|
|
@@ -144,6 +160,7 @@ export declare class SqlPrinter {
|
|
|
144
160
|
private handleAndOperatorToken;
|
|
145
161
|
private handleParenthesisToken;
|
|
146
162
|
private handleOrOperatorToken;
|
|
163
|
+
private getJoinConditionContinuationLevel;
|
|
147
164
|
/**
|
|
148
165
|
* Decide whether a parentheses group should increase indentation when inside nested structures.
|
|
149
166
|
* We only expand groups that contain further parentheses so simple comparisons stay compact.
|
|
@@ -209,11 +226,13 @@ export declare class SqlPrinter {
|
|
|
209
226
|
* Oneliner mode uses single spaces instead of actual newlines.
|
|
210
227
|
*/
|
|
211
228
|
private isOnelineMode;
|
|
229
|
+
private normalizeOneLineMaxLength;
|
|
230
|
+
private fitsOneLineMaxLength;
|
|
212
231
|
/**
|
|
213
232
|
* Handles CTE tokens with one-liner formatting.
|
|
214
233
|
* Creates a nested SqlPrinter instance for proper CTE oneline formatting.
|
|
215
234
|
*/
|
|
216
|
-
private
|
|
235
|
+
private tryHandleCteOnelineToken;
|
|
217
236
|
/**
|
|
218
237
|
* Creates a SqlPrinter instance configured for CTE oneline formatting.
|
|
219
238
|
*/
|
|
@@ -222,7 +241,9 @@ export declare class SqlPrinter {
|
|
|
222
241
|
* Handles tokens with oneline formatting (parentheses, BETWEEN, VALUES, JOIN, CASE, subqueries).
|
|
223
242
|
* Creates a unified oneline printer that formats everything as one line regardless of content type.
|
|
224
243
|
*/
|
|
225
|
-
private
|
|
244
|
+
private tryHandleOnelineToken;
|
|
245
|
+
private isBooleanParenExpression;
|
|
246
|
+
private containsLogicalOperator;
|
|
226
247
|
private getClauseBreakIndentLevel;
|
|
227
248
|
private isMergeActionContainer;
|
|
228
249
|
private shouldBreakAfterOpeningParen;
|
|
@@ -30,11 +30,15 @@ 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 */
|
|
@@ -52,19 +56,22 @@ export class SqlPrinter {
|
|
|
52
56
|
this.valuesCommaBreak = (_d = options === null || options === void 0 ? void 0 : options.valuesCommaBreak) !== null && _d !== void 0 ? _d : this.commaBreak;
|
|
53
57
|
this.andBreak = (_e = options === null || options === void 0 ? void 0 : options.andBreak) !== null && _e !== void 0 ? _e : 'none';
|
|
54
58
|
this.orBreak = (_f = options === null || options === void 0 ? void 0 : options.orBreak) !== null && _f !== void 0 ? _f : 'none';
|
|
55
|
-
this.
|
|
59
|
+
this.joinOnBreak = (_g = options === null || options === void 0 ? void 0 : options.joinOnBreak) !== null && _g !== void 0 ? _g : 'none';
|
|
60
|
+
this.keywordCase = (_h = options === null || options === void 0 ? void 0 : options.keywordCase) !== null && _h !== void 0 ? _h : 'none';
|
|
56
61
|
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 = (
|
|
62
|
+
this.withClauseStyle = (_j = options === null || options === void 0 ? void 0 : options.withClauseStyle) !== null && _j !== void 0 ? _j : 'standard';
|
|
63
|
+
this.commentStyle = (_k = options === null || options === void 0 ? void 0 : options.commentStyle) !== null && _k !== void 0 ? _k : 'block';
|
|
64
|
+
this.parenthesesOneLine = (_l = options === null || options === void 0 ? void 0 : options.parenthesesOneLine) !== null && _l !== void 0 ? _l : false;
|
|
65
|
+
this.betweenOneLine = (_m = options === null || options === void 0 ? void 0 : options.betweenOneLine) !== null && _m !== void 0 ? _m : false;
|
|
66
|
+
this.valuesOneLine = (_o = options === null || options === void 0 ? void 0 : options.valuesOneLine) !== null && _o !== void 0 ? _o : false;
|
|
67
|
+
this.joinOneLine = (_p = options === null || options === void 0 ? void 0 : options.joinOneLine) !== null && _p !== void 0 ? _p : false;
|
|
68
|
+
this.caseOneLine = (_q = options === null || options === void 0 ? void 0 : options.caseOneLine) !== null && _q !== void 0 ? _q : false;
|
|
69
|
+
this.subqueryOneLine = (_r = options === null || options === void 0 ? void 0 : options.subqueryOneLine) !== null && _r !== void 0 ? _r : false;
|
|
70
|
+
this.indentNestedParentheses = (_s = options === null || options === void 0 ? void 0 : options.indentNestedParentheses) !== null && _s !== void 0 ? _s : false;
|
|
71
|
+
this.insertColumnsOneLine = (_t = options === null || options === void 0 ? void 0 : options.insertColumnsOneLine) !== null && _t !== void 0 ? _t : false;
|
|
72
|
+
this.whenOneLine = (_u = options === null || options === void 0 ? void 0 : options.whenOneLine) !== null && _u !== void 0 ? _u : false;
|
|
73
|
+
this.oneLineMaxLength = this.normalizeOneLineMaxLength(options === null || options === void 0 ? void 0 : options.oneLineMaxLength);
|
|
74
|
+
this.joinConditionContinuationIndent = (_v = options === null || options === void 0 ? void 0 : options.joinConditionContinuationIndent) !== null && _v !== void 0 ? _v : false;
|
|
68
75
|
const onelineOptions = {
|
|
69
76
|
parenthesesOneLine: this.parenthesesOneLine,
|
|
70
77
|
betweenOneLine: this.betweenOneLine,
|
|
@@ -78,7 +85,7 @@ export class SqlPrinter {
|
|
|
78
85
|
this.onelineHelper = new OnelineFormattingHelper(onelineOptions);
|
|
79
86
|
this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
|
|
80
87
|
// Initialize
|
|
81
|
-
this.indentIncrementContainers = new Set((
|
|
88
|
+
this.indentIncrementContainers = new Set((_w = options === null || options === void 0 ? void 0 : options.indentIncrementContainerTypes) !== null && _w !== void 0 ? _w : [
|
|
82
89
|
SqlPrintTokenContainerType.SelectClause,
|
|
83
90
|
SqlPrintTokenContainerType.ReturningClause,
|
|
84
91
|
SqlPrintTokenContainerType.FromClause,
|
|
@@ -124,8 +131,10 @@ export class SqlPrinter {
|
|
|
124
131
|
// initialize
|
|
125
132
|
this.linePrinter = new LinePrinter(this.indentChar, this.indentSize, this.newline, this.commaBreak);
|
|
126
133
|
this.insideWithClause = false; // Reset WITH clause context
|
|
134
|
+
this.joinOnClauseDepth = 0;
|
|
127
135
|
this.pendingLineCommentBreak = null;
|
|
128
136
|
this.smartCommentBlockBuilder = null;
|
|
137
|
+
this.expandedOneLineFallbackTokens = new WeakSet();
|
|
129
138
|
if (this.linePrinter.lines.length > 0 && level !== this.linePrinter.lines[0].level) {
|
|
130
139
|
this.linePrinter.lines[0].level = level;
|
|
131
140
|
}
|
|
@@ -244,7 +253,7 @@ export class SqlPrinter {
|
|
|
244
253
|
const current = this.linePrinter.getCurrentLine();
|
|
245
254
|
const isCaseContext = this.isCaseContext(token.containerType);
|
|
246
255
|
const nextCaseContextDepth = isCaseContext ? caseContextDepth + 1 : caseContextDepth;
|
|
247
|
-
|
|
256
|
+
let shouldIndentNested = this.shouldIndentNestedParentheses(token, previousSiblingWasOpenParen);
|
|
248
257
|
// Handle different token types
|
|
249
258
|
if (token.type === SqlPrintTokenType.keyword) {
|
|
250
259
|
this.handleKeywordToken(token, level, parentContainerType, caseContextDepth);
|
|
@@ -281,16 +290,25 @@ export class SqlPrinter {
|
|
|
281
290
|
this.handleCommentNewlineToken(token, commentLevel);
|
|
282
291
|
}
|
|
283
292
|
else if (token.containerType === SqlPrintTokenContainerType.CommonTable && this.withClauseStyle === 'cte-oneline') {
|
|
284
|
-
this.
|
|
285
|
-
|
|
293
|
+
if (this.tryHandleCteOnelineToken(token, level)) {
|
|
294
|
+
return; // Return early to avoid processing innerTokens
|
|
295
|
+
}
|
|
286
296
|
}
|
|
287
|
-
else if (this.shouldFormatContainerAsOneline(token, shouldIndentNested)) {
|
|
288
|
-
this.handleOnelineToken(token, level);
|
|
297
|
+
else if (this.shouldFormatContainerAsOneline(token, shouldIndentNested) && this.tryHandleOnelineToken(token, level)) {
|
|
289
298
|
return; // Return early to avoid processing innerTokens
|
|
290
299
|
}
|
|
291
300
|
else if (!this.tryAppendInsertClauseTokenText(token.text, parentContainerType)) {
|
|
292
301
|
this.linePrinter.appendText(token.text);
|
|
293
302
|
}
|
|
303
|
+
if (token.containerType === SqlPrintTokenContainerType.JoinOnClause &&
|
|
304
|
+
this.joinOnBreak === 'before' &&
|
|
305
|
+
!this.isOnelineMode() &&
|
|
306
|
+
this.linePrinter.getCurrentLine().text.trim().length > 0) {
|
|
307
|
+
this.linePrinter.appendNewline(level + 1);
|
|
308
|
+
}
|
|
309
|
+
if (this.expandedOneLineFallbackTokens.has(token)) {
|
|
310
|
+
shouldIndentNested = true;
|
|
311
|
+
}
|
|
294
312
|
// append keyword tokens(not indented)
|
|
295
313
|
if (token.keywordTokens && token.keywordTokens.length > 0) {
|
|
296
314
|
for (let i = 0; i < token.keywordTokens.length; i++) {
|
|
@@ -304,6 +322,9 @@ export class SqlPrinter {
|
|
|
304
322
|
const delayIndentNewline = shouldIndentNested && token.containerType === SqlPrintTokenContainerType.ParenExpression;
|
|
305
323
|
const isAlterTableStatement = token.containerType === SqlPrintTokenContainerType.AlterTableStatement;
|
|
306
324
|
let deferAlterTableIndent = false;
|
|
325
|
+
if (token.containerType === SqlPrintTokenContainerType.JoinOnClause && this.joinOnBreak === 'before' && !this.isOnelineMode()) {
|
|
326
|
+
innerLevel = level + 1;
|
|
327
|
+
}
|
|
307
328
|
const alignExplainChild = this.shouldAlignExplainStatementChild(parentContainerType, token.containerType);
|
|
308
329
|
if (alignExplainChild) {
|
|
309
330
|
// Keep EXPLAIN target statements flush left so they render like standalone statements.
|
|
@@ -356,6 +377,10 @@ export class SqlPrinter {
|
|
|
356
377
|
let mergePredicateActive = isMergeWhenClause;
|
|
357
378
|
let alterTableTableRendered = false;
|
|
358
379
|
let alterTableIndentInserted = false;
|
|
380
|
+
const enteredJoinOnClause = token.containerType === SqlPrintTokenContainerType.JoinOnClause;
|
|
381
|
+
if (enteredJoinOnClause) {
|
|
382
|
+
this.joinOnClauseDepth++;
|
|
383
|
+
}
|
|
359
384
|
for (let i = leadingCommentCount; i < token.innerTokens.length; i++) {
|
|
360
385
|
const child = token.innerTokens[i];
|
|
361
386
|
const nextChild = token.innerTokens[i + 1];
|
|
@@ -417,6 +442,9 @@ export class SqlPrinter {
|
|
|
417
442
|
if (this.smartCommentBlockBuilder && this.smartCommentBlockBuilder.mode === 'line') {
|
|
418
443
|
this.flushSmartCommentBlockBuilder();
|
|
419
444
|
}
|
|
445
|
+
if (enteredJoinOnClause) {
|
|
446
|
+
this.joinOnClauseDepth--;
|
|
447
|
+
}
|
|
420
448
|
// Exit WITH clause context when we finish processing WithClause container
|
|
421
449
|
if (token.containerType === SqlPrintTokenContainerType.WithClause && this.withClauseStyle === 'full-oneline') {
|
|
422
450
|
this.insideWithClause = false;
|
|
@@ -617,7 +645,7 @@ export class SqlPrinter {
|
|
|
617
645
|
if (this.andBreak === 'before') {
|
|
618
646
|
// Skip newline when inside WITH clause with full-oneline style
|
|
619
647
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
620
|
-
this.linePrinter.appendNewline(level);
|
|
648
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
621
649
|
}
|
|
622
650
|
this.linePrinter.appendText(text);
|
|
623
651
|
}
|
|
@@ -625,7 +653,7 @@ export class SqlPrinter {
|
|
|
625
653
|
this.linePrinter.appendText(text);
|
|
626
654
|
// Skip newline when inside WITH clause with full-oneline style
|
|
627
655
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
628
|
-
this.linePrinter.appendNewline(level);
|
|
656
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
629
657
|
}
|
|
630
658
|
}
|
|
631
659
|
else {
|
|
@@ -644,7 +672,9 @@ export class SqlPrinter {
|
|
|
644
672
|
if (this.shouldBreakAfterOpeningParen(parentContainerType)) {
|
|
645
673
|
this.linePrinter.appendNewline(level + 1);
|
|
646
674
|
}
|
|
647
|
-
else if (indentParentActive &&
|
|
675
|
+
else if (indentParentActive &&
|
|
676
|
+
parentContainerType === SqlPrintTokenContainerType.ParenExpression &&
|
|
677
|
+
!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
648
678
|
this.linePrinter.appendNewline(level);
|
|
649
679
|
}
|
|
650
680
|
}
|
|
@@ -656,7 +686,9 @@ export class SqlPrinter {
|
|
|
656
686
|
this.linePrinter.appendText(token.text);
|
|
657
687
|
return;
|
|
658
688
|
}
|
|
659
|
-
if (indentParentActive &&
|
|
689
|
+
if (indentParentActive &&
|
|
690
|
+
parentContainerType === SqlPrintTokenContainerType.ParenExpression &&
|
|
691
|
+
!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
660
692
|
const closingLevel = Math.max(level - 1, 0);
|
|
661
693
|
this.linePrinter.appendNewline(closingLevel);
|
|
662
694
|
}
|
|
@@ -678,7 +710,7 @@ export class SqlPrinter {
|
|
|
678
710
|
if (this.orBreak === 'before') {
|
|
679
711
|
// Insert a newline before OR unless WITH full-oneline mode suppresses breaks.
|
|
680
712
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
681
|
-
this.linePrinter.appendNewline(level);
|
|
713
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
682
714
|
}
|
|
683
715
|
this.linePrinter.appendText(text);
|
|
684
716
|
}
|
|
@@ -686,13 +718,22 @@ export class SqlPrinter {
|
|
|
686
718
|
this.linePrinter.appendText(text);
|
|
687
719
|
// Break after OR when multi-line formatting is active.
|
|
688
720
|
if (!(this.insideWithClause && this.withClauseStyle === 'full-oneline')) {
|
|
689
|
-
this.linePrinter.appendNewline(level);
|
|
721
|
+
this.linePrinter.appendNewline(this.getJoinConditionContinuationLevel(level));
|
|
690
722
|
}
|
|
691
723
|
}
|
|
692
724
|
else {
|
|
693
725
|
this.linePrinter.appendText(text);
|
|
694
726
|
}
|
|
695
727
|
}
|
|
728
|
+
getJoinConditionContinuationLevel(level) {
|
|
729
|
+
if (this.joinOnClauseDepth === 0) {
|
|
730
|
+
return level;
|
|
731
|
+
}
|
|
732
|
+
if (this.joinOnBreak === 'before') {
|
|
733
|
+
return level;
|
|
734
|
+
}
|
|
735
|
+
return this.joinConditionContinuationIndent ? level + 1 : level;
|
|
736
|
+
}
|
|
696
737
|
/**
|
|
697
738
|
* Decide whether a parentheses group should increase indentation when inside nested structures.
|
|
698
739
|
* We only expand groups that contain further parentheses so simple comparisons stay compact.
|
|
@@ -704,6 +745,9 @@ export class SqlPrinter {
|
|
|
704
745
|
if (token.containerType !== SqlPrintTokenContainerType.ParenExpression) {
|
|
705
746
|
return false;
|
|
706
747
|
}
|
|
748
|
+
if (this.expandedOneLineFallbackTokens.has(token)) {
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
707
751
|
// Look for nested parentheses containers. If present, indent to highlight grouping.
|
|
708
752
|
return previousSiblingWasOpenParen || token.innerTokens.some((child) => this.containsParenExpression(child));
|
|
709
753
|
}
|
|
@@ -1287,16 +1331,36 @@ export class SqlPrinter {
|
|
|
1287
1331
|
isOnelineMode() {
|
|
1288
1332
|
return this.newline === ' ';
|
|
1289
1333
|
}
|
|
1334
|
+
normalizeOneLineMaxLength(value) {
|
|
1335
|
+
if (value === undefined || !Number.isFinite(value) || value <= 0) {
|
|
1336
|
+
return undefined;
|
|
1337
|
+
}
|
|
1338
|
+
const normalized = Math.floor(value);
|
|
1339
|
+
return normalized > 0 ? normalized : undefined;
|
|
1340
|
+
}
|
|
1341
|
+
fitsOneLineMaxLength(text) {
|
|
1342
|
+
if (this.oneLineMaxLength === undefined) {
|
|
1343
|
+
return true;
|
|
1344
|
+
}
|
|
1345
|
+
const currentLine = this.linePrinter.getCurrentLine();
|
|
1346
|
+
const indentWidth = currentLine.level * this.indentSize * String(this.indentChar).length;
|
|
1347
|
+
return indentWidth + currentLine.text.length + text.length <= this.oneLineMaxLength;
|
|
1348
|
+
}
|
|
1290
1349
|
/**
|
|
1291
1350
|
* Handles CTE tokens with one-liner formatting.
|
|
1292
1351
|
* Creates a nested SqlPrinter instance for proper CTE oneline formatting.
|
|
1293
1352
|
*/
|
|
1294
|
-
|
|
1353
|
+
tryHandleCteOnelineToken(token, level) {
|
|
1295
1354
|
const onelinePrinter = this.createCteOnelinePrinter();
|
|
1296
1355
|
const onelineResult = onelinePrinter.print(token, level);
|
|
1297
1356
|
let cleanedResult = this.cleanDuplicateSpaces(onelineResult);
|
|
1298
1357
|
cleanedResult = cleanedResult.replace(/\(\s+/g, '(').replace(/\s+\)/g, ' )');
|
|
1299
|
-
|
|
1358
|
+
const trimmedResult = cleanedResult.trim();
|
|
1359
|
+
if (!this.fitsOneLineMaxLength(trimmedResult)) {
|
|
1360
|
+
return false;
|
|
1361
|
+
}
|
|
1362
|
+
this.linePrinter.appendText(trimmedResult);
|
|
1363
|
+
return true;
|
|
1300
1364
|
}
|
|
1301
1365
|
/**
|
|
1302
1366
|
* Creates a SqlPrinter instance configured for CTE oneline formatting.
|
|
@@ -1322,11 +1386,31 @@ export class SqlPrinter {
|
|
|
1322
1386
|
* Handles tokens with oneline formatting (parentheses, BETWEEN, VALUES, JOIN, CASE, subqueries).
|
|
1323
1387
|
* Creates a unified oneline printer that formats everything as one line regardless of content type.
|
|
1324
1388
|
*/
|
|
1325
|
-
|
|
1389
|
+
tryHandleOnelineToken(token, level) {
|
|
1326
1390
|
const onelinePrinter = this.createOnelinePrinter();
|
|
1327
1391
|
const onelineResult = onelinePrinter.print(token, level);
|
|
1328
1392
|
const cleanedResult = this.cleanDuplicateSpaces(onelineResult);
|
|
1393
|
+
if (!this.fitsOneLineMaxLength(cleanedResult)) {
|
|
1394
|
+
if (this.isBooleanParenExpression(token)) {
|
|
1395
|
+
this.expandedOneLineFallbackTokens.add(token);
|
|
1396
|
+
}
|
|
1397
|
+
return false;
|
|
1398
|
+
}
|
|
1329
1399
|
this.linePrinter.appendText(cleanedResult);
|
|
1400
|
+
return true;
|
|
1401
|
+
}
|
|
1402
|
+
isBooleanParenExpression(token) {
|
|
1403
|
+
if (token.containerType !== SqlPrintTokenContainerType.ParenExpression) {
|
|
1404
|
+
return false;
|
|
1405
|
+
}
|
|
1406
|
+
return this.containsLogicalOperator(token);
|
|
1407
|
+
}
|
|
1408
|
+
containsLogicalOperator(token) {
|
|
1409
|
+
if ((token.type === SqlPrintTokenType.operator || token.type === SqlPrintTokenType.keyword) &&
|
|
1410
|
+
['and', 'or'].includes(token.text.toLowerCase())) {
|
|
1411
|
+
return true;
|
|
1412
|
+
}
|
|
1413
|
+
return token.innerTokens.some((child) => this.containsLogicalOperator(child));
|
|
1330
1414
|
}
|
|
1331
1415
|
getClauseBreakIndentLevel(parentType, level) {
|
|
1332
1416
|
if (!parentType) {
|