Skip to content

Commit 7020237

Browse files
Copilotmathiasrw
andauthored
Support computed columns after select * for RECORDSET to fix #2070 (#2299)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: mathiasrw <[email protected]> Co-authored-by: Mathias Wulff <[email protected]>
1 parent cc5ff17 commit 7020237

File tree

2 files changed

+139
-1
lines changed

2 files changed

+139
-1
lines changed

src/40select.js

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,42 @@ function modify(query, res) {
525525

526526
var modifier = query.modifier || alasql.options.modifier;
527527
var columns = query.columns;
528-
if (typeof columns === 'undefined' || columns.length == 0) {
528+
529+
// If dirtyColumns is true, we need to merge columns from data with existing columns
530+
// This happens when SELECT * is used with dynamic data sources (like parameters)
531+
if (query.dirtyColumns && res.length > 0) {
532+
var allcol = {};
533+
// First, scan the data to find all column names
534+
for (var i = Math.min(res.length, alasql.options.columnlookup || 10) - 1; 0 <= i; i--) {
535+
for (var key in res[i]) {
536+
allcol[key] = true;
537+
}
538+
}
539+
540+
// Create columns from data
541+
var dataColumns = Object.keys(allcol).map(function (columnid) {
542+
return {columnid: columnid};
543+
});
544+
545+
// If we don't have any columns yet, just use the data columns
546+
if (!columns || columns.length === 0) {
547+
columns = dataColumns;
548+
} else {
549+
// We have some columns (e.g., from explicit column expressions),
550+
// merge them with data columns, avoiding duplicates
551+
var existingColumnIds = {};
552+
columns.forEach(function (col) {
553+
existingColumnIds[col.columnid] = true;
554+
});
555+
556+
// Add data columns that aren't already in the list
557+
dataColumns.forEach(function (col) {
558+
if (!existingColumnIds[col.columnid]) {
559+
columns.push(col);
560+
}
561+
});
562+
}
563+
} else if (typeof columns === 'undefined' || columns.length === 0) {
529564
// Try to create columns
530565
if (res.length > 0) {
531566
var allcol = {};

test/test2070.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
}
5+
6+
describe('Test 2070 - RECORDSET OF with wildcard and additional columns', function () {
7+
it('1. RECORDSET OF SELECT t.*, additional_column returns all columns', function (done) {
8+
var data = [
9+
{a: 1, b: 10},
10+
{a: 2, b: 20},
11+
{a: 1, b: 30},
12+
];
13+
var res = alasql('RECORDSET OF SELECT t.*, 1 as rn FROM ? t', [data]);
14+
15+
var expected = {
16+
columns: [{columnid: 'rn'}, {columnid: 'a'}, {columnid: 'b'}],
17+
data: [
18+
{rn: 1, a: 1, b: 10},
19+
{rn: 1, a: 2, b: 20},
20+
{rn: 1, a: 1, b: 30},
21+
],
22+
};
23+
24+
assert.deepEqual(res, expected);
25+
done();
26+
});
27+
28+
it('2. RECORDSET OF SELECT *, additional_column returns all columns', function (done) {
29+
var data = [
30+
{a: 1, b: 10},
31+
{a: 2, b: 20},
32+
];
33+
var res = alasql('RECORDSET OF SELECT *, 1 as rn FROM ? t', [data]);
34+
35+
var expected = {
36+
columns: [{columnid: 'rn'}, {columnid: 'a'}, {columnid: 'b'}],
37+
data: [
38+
{rn: 1, a: 1, b: 10},
39+
{rn: 1, a: 2, b: 20},
40+
],
41+
};
42+
43+
assert.deepEqual(res, expected);
44+
done();
45+
});
46+
47+
it('3. RECORDSET OF SELECT t.* still works correctly', function (done) {
48+
var data = [
49+
{a: 1, b: 10},
50+
{a: 2, b: 20},
51+
];
52+
var res = alasql('RECORDSET OF SELECT t.* FROM ? t', [data]);
53+
54+
var expected = {
55+
columns: [{columnid: 'a'}, {columnid: 'b'}],
56+
data: [
57+
{a: 1, b: 10},
58+
{a: 2, b: 20},
59+
],
60+
};
61+
62+
assert.deepEqual(res, expected);
63+
done();
64+
});
65+
66+
it('4. RECORDSET OF SELECT explicit columns works correctly', function (done) {
67+
var data = [
68+
{a: 1, b: 10},
69+
{a: 2, b: 20},
70+
];
71+
var res = alasql('RECORDSET OF SELECT a, b, 1 as rn FROM ? t', [data]);
72+
73+
var expected = {
74+
columns: [{columnid: 'a'}, {columnid: 'b'}, {columnid: 'rn'}],
75+
data: [
76+
{a: 1, b: 10, rn: 1},
77+
{a: 2, b: 20, rn: 1},
78+
],
79+
};
80+
81+
assert.deepEqual(res, expected);
82+
done();
83+
});
84+
85+
it('5. RECORDSET OF SELECT with multiple additional columns', function (done) {
86+
var data = [
87+
{a: 1, b: 10},
88+
{a: 2, b: 20},
89+
];
90+
var res = alasql('RECORDSET OF SELECT t.*, 1 as rn, 2 as seq FROM ? t', [data]);
91+
92+
var expected = {
93+
columns: [{columnid: 'rn'}, {columnid: 'seq'}, {columnid: 'a'}, {columnid: 'b'}],
94+
data: [
95+
{rn: 1, seq: 2, a: 1, b: 10},
96+
{rn: 1, seq: 2, a: 2, b: 20},
97+
],
98+
};
99+
100+
assert.deepEqual(res, expected);
101+
done();
102+
});
103+
});

0 commit comments

Comments
 (0)