@@ -49,7 +49,7 @@ describe('SelectQuery toSimpleQuery() conversion', () => {
49
49
50
50
test ( 'should enable CTE management on converted BinarySelectQuery' , ( ) => {
51
51
// Test that converted binary query supports CTE operations
52
- const query1 = SelectQueryParser . parse ( 'SELECT id FROM users' ) ;
52
+ const query1 = SelectQueryParser . parse ( 'SELECT id FROM users' ) . toSimpleQuery ( ) ;
53
53
const query2 = SelectQueryParser . parse ( 'SELECT id FROM customers' ) ;
54
54
const binaryQuery = query1 . toUnion ( query2 ) ;
55
55
const cteQuery = SelectQueryParser . parse ( 'SELECT id FROM accounts WHERE active = true' ) ;
@@ -65,7 +65,7 @@ describe('SelectQuery toSimpleQuery() conversion', () => {
65
65
66
66
test ( 'should produce valid SQL with complex UNION and CTE' , ( ) => {
67
67
// Test full workflow: UNION -> toSimpleQuery -> addCTE -> format
68
- const query1 = SelectQueryParser . parse ( 'SELECT id, name FROM employees' ) ;
68
+ const query1 = SelectQueryParser . parse ( 'SELECT id, name FROM employees' ) . toSimpleQuery ( ) ;
69
69
const query2 = SelectQueryParser . parse ( 'SELECT id, name FROM contractors' ) ;
70
70
const binaryQuery = query1 . toUnionAll ( query2 ) ;
71
71
const cteQuery = SelectQueryParser . parse ( 'SELECT id FROM departments WHERE active = true' ) ;
@@ -84,7 +84,7 @@ describe('SelectQuery toSimpleQuery() conversion', () => {
84
84
describe ( 'Method chaining patterns' , ( ) => {
85
85
test ( 'should support fluent API: binary -> toSimpleQuery -> CTE operations' , ( ) => {
86
86
// Test the recommended usage pattern
87
- const query1 = SelectQueryParser . parse ( 'SELECT id FROM table1' ) ;
87
+ const query1 = SelectQueryParser . parse ( 'SELECT id FROM table1' ) . toSimpleQuery ( ) ;
88
88
const query2 = SelectQueryParser . parse ( 'SELECT id FROM table2' ) ;
89
89
const cte1 = SelectQueryParser . parse ( 'SELECT id FROM temp1' ) ;
90
90
const cte2 = SelectQueryParser . parse ( 'SELECT id FROM temp2' ) ;
@@ -100,6 +100,115 @@ describe('SelectQuery toSimpleQuery() conversion', () => {
100
100
} ) ;
101
101
} ) ;
102
102
103
+ describe ( 'BinarySelectQuery ORDER BY handling' , ( ) => {
104
+ // NOTE: In SQL standard, ORDER BY in UNION context applies to the entire result set.
105
+ // Table prefixes (e.g., "a.column") would be invalid SQL syntax in ORDER BY clauses
106
+ // following UNION operations. Only column names without prefixes or positional notation
107
+ // (ORDER BY 1, 2) are valid. This implementation correctly handles valid SQL cases.
108
+
109
+ test ( 'should move ORDER BY from right query to SimpleQuery when converting' , ( ) => {
110
+ // Test ORDER BY removal from right query and movement to SimpleQuery
111
+ const query1 = SelectQueryParser . parse ( 'SELECT id, name FROM users' ) . toSimpleQuery ( ) ;
112
+ const query2 = SelectQueryParser . parse ( 'SELECT id, name FROM customers ORDER BY name ASC' ) ;
113
+ const binaryQuery = query1 . toUnion ( query2 ) ;
114
+
115
+ const result = binaryQuery . toSimpleQuery ( ) ;
116
+ const formatted = formatter . format ( result ) ;
117
+
118
+ // ORDER BY should be at SimpleQuery level, not in the subquery
119
+ expect ( result . orderByClause ) . not . toBeNull ( ) ;
120
+
121
+ // Verify ORDER BY is at the outermost level (after the subquery)
122
+ // Should be: SELECT * FROM (...) AS "bq" ORDER BY "name"
123
+ const sql = formatted . formattedSql . trim ( ) ;
124
+ expect ( sql ) . toMatch ( / \) \s + a s \s + " b q " \s + o r d e r \s + b y \s + " n a m e " / i) ;
125
+
126
+ // The binary query itself should no longer have ORDER BY on the right side
127
+ const binaryFormatted = formatter . format ( binaryQuery ) ;
128
+ // Should not contain ORDER BY before UNION
129
+ expect ( binaryFormatted . formattedSql ) . not . toMatch ( / o r d e r \s + b y \s + [ ^ ) ] + \) \s * $ / i) ;
130
+ } ) ;
131
+
132
+ test ( 'should handle multiple ORDER BY clauses correctly' , ( ) => {
133
+ // Test when both queries have ORDER BY - should use right query's ORDER BY
134
+ const query1 = SelectQueryParser . parse ( 'SELECT id, name FROM users ORDER BY id DESC' ) . toSimpleQuery ( ) ;
135
+ const query2 = SelectQueryParser . parse ( 'SELECT id, name FROM customers ORDER BY name ASC, id DESC' ) ;
136
+ const binaryQuery = query1 . toUnion ( query2 ) ;
137
+
138
+ const result = binaryQuery . toSimpleQuery ( ) ;
139
+ const formatted = formatter . format ( result ) ;
140
+
141
+ // Should have ORDER BY at SimpleQuery level from right query
142
+ expect ( result . orderByClause ) . not . toBeNull ( ) ;
143
+
144
+ // Verify ORDER BY is moved to outermost level and contains columns from right query
145
+ const sql = formatted . formattedSql . trim ( ) ;
146
+ expect ( sql ) . toMatch ( / \) \s + a s \s + " b q " \s + o r d e r \s + b y \s + " n a m e " [ ^ , ] * , \s * " i d " / i) ;
147
+
148
+ // Original binary query should have ORDER BY removed from right side
149
+ const binaryFormatted = formatter . format ( binaryQuery ) ;
150
+ // Left query still has its ORDER BY (not removed)
151
+ expect ( binaryFormatted . formattedSql ) . toContain ( 'order by "id" desc union' ) ;
152
+ // But right query's ORDER BY should be removed
153
+ expect ( binaryFormatted . formattedSql ) . not . toMatch ( / c u s t o m e r s .* o r d e r \s + b y .* $ / i) ;
154
+ } ) ;
155
+
156
+ test ( 'should work with nested binary queries' , ( ) => {
157
+ // Test ORDER BY handling with nested binary operations
158
+ const query1 = SelectQueryParser . parse ( 'SELECT id FROM table1' ) . toSimpleQuery ( ) ;
159
+ const query2 = SelectQueryParser . parse ( 'SELECT id FROM table2 ORDER BY id ASC' ) ;
160
+ const query3 = SelectQueryParser . parse ( 'SELECT id FROM table3' ) ;
161
+
162
+ const binaryQuery1 = query1 . toUnion ( query2 ) ;
163
+ const binaryQuery2 = binaryQuery1 . toSimpleQuery ( ) . toUnion ( query3 ) ;
164
+
165
+ const result = binaryQuery2 . toSimpleQuery ( ) ;
166
+ const formatted = formatter . format ( result ) ;
167
+
168
+ // Should extract ORDER BY from the rightmost query that has it
169
+ expect ( result . orderByClause ) . not . toBeNull ( ) ;
170
+
171
+ // ORDER BY should be at the outermost level
172
+ const sql = formatted . formattedSql . trim ( ) ;
173
+ expect ( sql ) . toMatch ( / \) \s + a s \s + " b q " \s + o r d e r \s + b y \s + " i d " / i) ;
174
+
175
+ // Verify the nested structure doesn't have ORDER BY in the middle
176
+ expect ( sql ) . not . toMatch ( / t a b l e 2 .* o r d e r .* u n i o n / i) ;
177
+ } ) ;
178
+
179
+ test ( 'should handle case with no ORDER BY in any query' , ( ) => {
180
+ // Test when no queries have ORDER BY
181
+ const query1 = SelectQueryParser . parse ( 'SELECT id FROM users' ) . toSimpleQuery ( ) ;
182
+ const query2 = SelectQueryParser . parse ( 'SELECT id FROM customers' ) ;
183
+ const binaryQuery = query1 . toUnion ( query2 ) ;
184
+
185
+ const result = binaryQuery . toSimpleQuery ( ) ;
186
+
187
+ // Should have no ORDER BY clause
188
+ expect ( result . orderByClause ) . toBeNull ( ) ;
189
+ } ) ;
190
+
191
+ test ( 'should verify ORDER BY is actually removed from original query' , ( ) => {
192
+ // Create queries and verify ORDER BY removal
193
+ const query1 = SelectQueryParser . parse ( 'SELECT id FROM users' ) . toSimpleQuery ( ) ;
194
+ const query2 = SelectQueryParser . parse ( 'SELECT id FROM customers ORDER BY id DESC' ) . toSimpleQuery ( ) ;
195
+
196
+ // Store original ORDER BY state
197
+ expect ( query2 . orderByClause ) . not . toBeNull ( ) ;
198
+ const originalOrderBy = query2 . orderByClause ;
199
+
200
+ const binaryQuery = query1 . toUnion ( query2 ) ;
201
+ const result = binaryQuery . toSimpleQuery ( ) ;
202
+
203
+ // Original query should have ORDER BY removed
204
+ expect ( query2 . orderByClause ) . toBeNull ( ) ;
205
+
206
+ // Result should have the ORDER BY
207
+ expect ( result . orderByClause ) . not . toBeNull ( ) ;
208
+ expect ( result . orderByClause ) . toBe ( originalOrderBy ) ;
209
+ } ) ;
210
+ } ) ;
211
+
103
212
describe ( 'ValuesQuery.toSimpleQuery()' , ( ) => {
104
213
test ( 'should convert ValuesQuery to SimpleSelectQuery' , ( ) => {
105
214
// Test conversion of VALUES query
0 commit comments