Skip to content

Commit d206837

Browse files
Copilotmathiasrw
andauthored
Respect ORDER BY in INTERSECT/EXCEPT queries to fix #635 (#2304)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: mathiasrw <[email protected]> Co-authored-by: Mathias Wulff <[email protected]>
1 parent 6497825 commit d206837

File tree

2 files changed

+104
-8
lines changed

2 files changed

+104
-8
lines changed

src/38query.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,12 @@ function queryfn3(query) {
161161
// TODO Simplify this part of program
162162
var ud, nd;
163163
if (query.corresponding) {
164-
if (!query.unionallfn.query.modifier) query.unionallfn.query.modifier = undefined;
164+
if (query.unionallfn.query && !query.unionallfn.query.modifier)
165+
query.unionallfn.query.modifier = undefined;
165166
ud = query.unionallfn(query.params);
166167
} else {
167-
if (!query.unionallfn.query.modifier) query.unionallfn.query.modifier = 'RECORDSET';
168+
if (query.unionallfn.query && !query.unionallfn.query.modifier)
169+
query.unionallfn.query.modifier = 'RECORDSET';
168170
nd = query.unionallfn(query.params);
169171
ud = [];
170172
ilen = nd.data.length;
@@ -187,10 +189,12 @@ function queryfn3(query) {
187189
query.data = query.data.concat(ud);
188190
} else if (query.unionfn) {
189191
if (query.corresponding) {
190-
if (!query.unionfn.query.modifier) query.unionfn.query.modifier = 'ARRAY';
192+
if (query.unionfn.query && !query.unionfn.query.modifier)
193+
query.unionfn.query.modifier = 'ARRAY';
191194
ud = query.unionfn(query.params);
192195
} else {
193-
if (!query.unionfn.query.modifier) query.unionfn.query.modifier = 'RECORDSET';
196+
if (query.unionfn.query && !query.unionfn.query.modifier)
197+
query.unionfn.query.modifier = 'RECORDSET';
194198
nd = query.unionfn(query.params);
195199
ud = [];
196200
ilen = nd.data.length;
@@ -214,10 +218,12 @@ function queryfn3(query) {
214218
query.data = arrayUnionDeep(query.data, ud);
215219
} else if (query.exceptfn) {
216220
if (query.corresponding) {
217-
if (!query.exceptfn.query.modifier) query.exceptfn.query.modifier = 'ARRAY';
221+
if (query.exceptfn.query && !query.exceptfn.query.modifier)
222+
query.exceptfn.query.modifier = 'ARRAY';
218223
var ud = query.exceptfn(query.params);
219224
} else {
220-
if (!query.exceptfn.query.modifier) query.exceptfn.query.modifier = 'RECORDSET';
225+
if (query.exceptfn.query && !query.exceptfn.query.modifier)
226+
query.exceptfn.query.modifier = 'RECORDSET';
221227
var nd = query.exceptfn(query.params);
222228
var ud = [];
223229
for (var i = 0, ilen = nd.data.length; i < ilen; i++) {
@@ -232,10 +238,12 @@ function queryfn3(query) {
232238
query.data = arrayExceptDeep(query.data, ud);
233239
} else if (query.intersectfn) {
234240
if (query.corresponding) {
235-
if (!query.intersectfn.query.modifier) query.intersectfn.query.modifier = undefined;
241+
if (query.intersectfn.query && !query.intersectfn.query.modifier)
242+
query.intersectfn.query.modifier = undefined;
236243
ud = query.intersectfn(query.params);
237244
} else {
238-
if (!query.intersectfn.query.modifier) query.intersectfn.query.modifier = 'RECORDSET';
245+
if (query.intersectfn.query && !query.intersectfn.query.modifier)
246+
query.intersectfn.query.modifier = 'RECORDSET';
239247
nd = query.intersectfn(query.params);
240248
ud = [];
241249
ilen = nd.data.length;

test/test635-B.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
}
5+
6+
describe('Test 635-B - INTERSECT/EXCEPT with ORDER BY', function () {
7+
const test = '635B';
8+
9+
before(function () {
10+
alasql('create database test' + test);
11+
alasql('use test' + test);
12+
});
13+
14+
after(function () {
15+
alasql('drop database test' + test);
16+
});
17+
18+
it('A) INTERSECT with ORDER BY on column', function () {
19+
var data = [{eventStart: 1}, {eventStart: 100}, {eventStart: 10}];
20+
var res = alasql(
21+
'SELECT eventStart FROM $0 INTERSECT SELECT eventStart FROM $0 ORDER BY eventStart',
22+
[data]
23+
);
24+
assert.deepEqual(res, [{eventStart: 1}, {eventStart: 10}, {eventStart: 100}]);
25+
});
26+
27+
it('B) EXCEPT with ORDER BY on column', function () {
28+
var data = [{eventStart: 1}, {eventStart: 100}, {eventStart: 10}, {eventStart: 60}];
29+
var res = alasql(
30+
'SELECT eventStart FROM $0 WHERE eventStart < 100 EXCEPT SELECT eventStart FROM $0 WHERE eventStart > 50 ORDER BY eventStart',
31+
[data]
32+
);
33+
assert.deepEqual(res, [{eventStart: 1}, {eventStart: 10}]);
34+
});
35+
36+
it('C) INTERSECT with SELECT * and ORDER BY', function () {
37+
alasql('CREATE TABLE Persons (eventStart INT, eventEnd INT)');
38+
alasql('INSERT INTO Persons VALUES (1000000, 1000100), (1000050, 1000150), (1000200, 1000300)');
39+
var res = alasql(
40+
'SELECT * FROM Persons INTERSECT SELECT * FROM Persons WHERE eventStart BETWEEN 1000000 AND 1000100 OR eventEnd BETWEEN 1000000 AND 1000100 ORDER BY eventStart'
41+
);
42+
assert.deepEqual(res, [
43+
{eventStart: 1000000, eventEnd: 1000100},
44+
{eventStart: 1000050, eventEnd: 1000150},
45+
]);
46+
alasql('DROP TABLE Persons');
47+
});
48+
49+
it('D) EXCEPT with SELECT * and ORDER BY', function () {
50+
alasql('CREATE TABLE Persons (eventStart INT, eventEnd INT)');
51+
alasql('INSERT INTO Persons VALUES (1000000, 1000100), (1000050, 1000150), (1000200, 1000300)');
52+
var res = alasql(
53+
'SELECT * FROM Persons EXCEPT SELECT * FROM Persons WHERE eventStart > 1000100 ORDER BY eventStart'
54+
);
55+
assert.deepEqual(res, [
56+
{eventStart: 1000000, eventEnd: 1000100},
57+
{eventStart: 1000050, eventEnd: 1000150},
58+
]);
59+
alasql('DROP TABLE Persons');
60+
});
61+
62+
it('E) INTERSECT with multiple WHERE clauses and ORDER BY (from issue)', function () {
63+
// This test validates the fix for issue #635 where ORDER BY with INTERSECT caused
64+
// "Unable to get property 'modifier' of undefined" error
65+
alasql('CREATE TABLE Persons (eventStart INT, eventEnd INT)');
66+
alasql('INSERT INTO Persons VALUES (1000000, 1000100), (1000050, 1000150), (1000200, 1000300)');
67+
// Testing the exact scenario from the issue: INTERSECT with WHERE and ORDER BY
68+
var res = alasql(
69+
'SELECT * FROM Persons INTERSECT SELECT * FROM Persons WHERE eventStart BETWEEN 1000000 AND 1000100 OR eventEnd BETWEEN 1000000 AND 1000100 ORDER BY eventStart'
70+
);
71+
// Should return rows where BOTH conditions are true (INTERSECT) and ordered by eventStart
72+
// The INTERSECT of all rows with filtered rows should give us the filtered rows
73+
assert.deepEqual(res, [
74+
{eventStart: 1000000, eventEnd: 1000100},
75+
{eventStart: 1000050, eventEnd: 1000150},
76+
]);
77+
alasql('DROP TABLE Persons');
78+
});
79+
80+
it('F) INTERSECT with ORDER BY DESC', function () {
81+
var data = [{eventStart: 1}, {eventStart: 100}, {eventStart: 10}];
82+
var res = alasql(
83+
'SELECT eventStart FROM $0 INTERSECT SELECT eventStart FROM $0 ORDER BY eventStart DESC',
84+
[data]
85+
);
86+
assert.deepEqual(res, [{eventStart: 100}, {eventStart: 10}, {eventStart: 1}]);
87+
});
88+
});

0 commit comments

Comments
 (0)