From 89e25c2c9bfa9fa44a34cf54927e677301286faf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 09:56:30 +0000 Subject: [PATCH 1/4] Initial plan From 8818702d439acfa20943814ed118542b63ba4d5f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 10:01:40 +0000 Subject: [PATCH 2/4] Add test167B.js to verify SEARCH DISTINCT and SELECT DISTINCT issues Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> --- test/test167B.js | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 test/test167B.js diff --git a/test/test167B.js b/test/test167B.js new file mode 100644 index 0000000000..79b65913b4 --- /dev/null +++ b/test/test167B.js @@ -0,0 +1,87 @@ +if (typeof exports === 'object') { + var assert = require('assert'); + var alasql = require('..'); +} + +describe('Test 167B - SEARCH DISTINCT and SELECT DISTINCT functions', function () { + it('1. Basic DISTINCT comparison', function (done) { + var data = [{a: 1}, {a: 2}, {a: 1}]; + + var res1 = alasql('SELECT * FROM ?', [data]); + var res2 = alasql('SELECT DISTINCT * FROM ?', [data]); + var res3 = alasql('SELECT COLUMN DISTINCT _ FROM ?', [data]); + var res4 = alasql('SEARCH DISTINCT(/) FROM ?', [data]); + + console.log('res1 (SELECT *):', JSON.stringify(res1)); + console.log('res2 (SELECT DISTINCT *):', JSON.stringify(res2)); + console.log('res3 (SELECT COLUMN DISTINCT _):', JSON.stringify(res3)); + console.log('res4 (SEARCH DISTINCT(/)):', JSON.stringify(res4)); + + // res1 should have all 3 items + assert.equal(res1.length, 3); + + // res2, res3, res4 should all have 2 distinct items + assert.equal(res2.length, 2, 'SELECT DISTINCT * should return 2 items'); + assert.equal(res3.length, 2, 'SELECT COLUMN DISTINCT _ should return 2 items'); + assert.equal(res4.length, 2, 'SEARCH DISTINCT(/) should return 2 items'); + + done(); + }); + + it('2. DISTINCT with different middle value (issue b)', function (done) { + var data = [{a: 1}, {b: 2}, {a: 1}]; + + var res3 = alasql('SELECT COLUMN DISTINCT _ FROM ?', [data]); + var res4 = alasql('SEARCH DISTINCT(/) FROM ?', [data]); + + console.log('res3 (SELECT COLUMN DISTINCT _) with mixed data:', JSON.stringify(res3)); + console.log('res4 (SEARCH DISTINCT(/)) with mixed data:', JSON.stringify(res4)); + + // Should return 2 distinct objects: {a:1} and {b:2} + assert.equal(res3.length, 2, 'SELECT COLUMN DISTINCT _ should return 2 items'); + assert.equal(res4.length, 2, 'SEARCH DISTINCT(/) should return 2 items'); + + // Check that we have both distinct objects + var hasA1 = res3.some(function (item) { + return item.a === 1 && !item.b; + }); + var hasB2 = res3.some(function (item) { + return item.b === 2 && !item.a; + }); + + assert(hasA1, 'Result should contain {a:1}'); + assert(hasB2, 'Result should contain {b:2}'); + + done(); + }); + + it('3. SEARCH DISTINCT vs SELECT DISTINCT consistency', function (done) { + var data = [{a: 1}, {b: 2}, {a: 1}]; + + var res2 = alasql('SELECT DISTINCT * FROM ?', [data]); + var res4 = alasql('SEARCH DISTINCT(/) FROM ?', [data]); + + console.log('res2 (SELECT DISTINCT *):', JSON.stringify(res2)); + console.log('res4 (SEARCH DISTINCT(/)):', JSON.stringify(res4)); + + // Results should be the same + assert.deepEqual(res2, res4, 'SELECT DISTINCT * and SEARCH DISTINCT(/) should produce same results'); + + done(); + }); + + it('4. SELECT COLUMN DISTINCT _ with arrays', function (done) { + var data = [1, 2, 1, 3, 2]; + + var res = alasql('SELECT COLUMN DISTINCT _ FROM ?', [data]); + console.log('SELECT COLUMN DISTINCT _ from array:', JSON.stringify(res)); + + // Should return distinct values: [1, 2, 3] + assert.equal(res.length, 3, 'Should return 3 distinct values'); + assert(res.includes(1), 'Should include 1'); + assert(res.includes(2), 'Should include 2'); + assert(res.includes(3), 'Should include 3'); + + done(); + }); +}); From 059673aba119131b9f7bd976252e9ce23be19606 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 10:06:38 +0000 Subject: [PATCH 3/4] Fix DISTINCT handling for objects in SELECT and SELECT COLUMN queries Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> --- src/38query.js | 4 +++- src/40select.js | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/38query.js b/src/38query.js index 81de5bf31d..ea013597cf 100755 --- a/src/38query.js +++ b/src/38query.js @@ -376,7 +376,9 @@ function doDistinct(query) { for (var i = 0, ilen = query.data.length; i < ilen; i++) { var uix = keys .map(function (k) { - return query.data[i][k]; + var val = query.data[i][k]; + // Properly serialize objects for comparison + return typeof val === 'object' ? JSON.stringify(val) : val; }) .join('`'); uniq[uix] = query.data[i]; diff --git a/src/40select.js b/src/40select.js index 72968a5308..01c86cc5c2 100755 --- a/src/40select.js +++ b/src/40select.js @@ -460,6 +460,11 @@ function modify(query, res) { ar.push(res[i][key]); } + // Apply DISTINCT if specified + if (query.distinct) { + ar = alasql.utils.distinctArray(ar); + } + return ar; case 'MATRIX': From 7d43b9d5d8069fa4f540d091998eb5a3f9a2550f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 13:29:27 +0000 Subject: [PATCH 4/4] Remove async done callbacks from sync tests in test167B.js Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> --- test/test167B.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/test/test167B.js b/test/test167B.js index 79b65913b4..4459235b1d 100644 --- a/test/test167B.js +++ b/test/test167B.js @@ -4,7 +4,7 @@ if (typeof exports === 'object') { } describe('Test 167B - SEARCH DISTINCT and SELECT DISTINCT functions', function () { - it('1. Basic DISTINCT comparison', function (done) { + it('1. Basic DISTINCT comparison', () => { var data = [{a: 1}, {a: 2}, {a: 1}]; var res1 = alasql('SELECT * FROM ?', [data]); @@ -24,11 +24,9 @@ describe('Test 167B - SEARCH DISTINCT and SELECT DISTINCT functions', function ( assert.equal(res2.length, 2, 'SELECT DISTINCT * should return 2 items'); assert.equal(res3.length, 2, 'SELECT COLUMN DISTINCT _ should return 2 items'); assert.equal(res4.length, 2, 'SEARCH DISTINCT(/) should return 2 items'); - - done(); }); - it('2. DISTINCT with different middle value (issue b)', function (done) { + it('2. DISTINCT with different middle value (issue b)', () => { var data = [{a: 1}, {b: 2}, {a: 1}]; var res3 = alasql('SELECT COLUMN DISTINCT _ FROM ?', [data]); @@ -51,11 +49,9 @@ describe('Test 167B - SEARCH DISTINCT and SELECT DISTINCT functions', function ( assert(hasA1, 'Result should contain {a:1}'); assert(hasB2, 'Result should contain {b:2}'); - - done(); }); - it('3. SEARCH DISTINCT vs SELECT DISTINCT consistency', function (done) { + it('3. SEARCH DISTINCT vs SELECT DISTINCT consistency', () => { var data = [{a: 1}, {b: 2}, {a: 1}]; var res2 = alasql('SELECT DISTINCT * FROM ?', [data]); @@ -65,12 +61,14 @@ describe('Test 167B - SEARCH DISTINCT and SELECT DISTINCT functions', function ( console.log('res4 (SEARCH DISTINCT(/)):', JSON.stringify(res4)); // Results should be the same - assert.deepEqual(res2, res4, 'SELECT DISTINCT * and SEARCH DISTINCT(/) should produce same results'); - - done(); + assert.deepEqual( + res2, + res4, + 'SELECT DISTINCT * and SEARCH DISTINCT(/) should produce same results' + ); }); - it('4. SELECT COLUMN DISTINCT _ with arrays', function (done) { + it('4. SELECT COLUMN DISTINCT _ with arrays', () => { var data = [1, 2, 1, 3, 2]; var res = alasql('SELECT COLUMN DISTINCT _ FROM ?', [data]); @@ -81,7 +79,5 @@ describe('Test 167B - SEARCH DISTINCT and SELECT DISTINCT functions', function ( assert(res.includes(1), 'Should include 1'); assert(res.includes(2), 'Should include 2'); assert(res.includes(3), 'Should include 3'); - - done(); }); });