Skip to content

Commit 86e8e46

Browse files
Copilotmathiasrw
andauthored
Fix subqueries for CREATE VIEW to close #1154 (#2406)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: mathiasrw <[email protected]> Co-authored-by: Mathias Wulff <[email protected]>
1 parent 4ebca81 commit 86e8e46

File tree

4 files changed

+66
-2
lines changed

4 files changed

+66
-2
lines changed

src/41exists.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ yy.ExistsValue = class ExistsValue {
3232
alasql.precompile = function (statement, databaseid, params) {
3333
if (!statement) return;
3434
statement.params = params;
35+
// For CREATE VIEW statements, move queries to the select object
36+
// so they can be compiled later when the view is first used
37+
if (statement.view && statement.select && statement.queries) {
38+
statement.select.queries = statement.queries;
39+
return;
40+
}
3541
if (statement.queries) {
3642
statement.queriesfn = statement.queries.map(function (q) {
3743
var nq = q.compile(databaseid || statement.database.databaseid);

src/420from.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,12 @@ yy.Select.prototype.compileFrom = function (query) {
7171
};
7272
} else if (alasql.databases[source.databaseid].tables[source.tableid].view) {
7373
source.datafn = (query, params, cb, idx, alasql) => {
74-
let res = alasql.databases[source.databaseid].tables[source.tableid].select(params);
74+
let table = alasql.databases[source.databaseid].tables[source.tableid];
75+
// Lazily compile the view's select on first use
76+
if (!table.select && table.viewSelect) {
77+
table.select = table.viewSelect.compile(table.viewDatabaseid);
78+
}
79+
let res = table.select(params);
7580
if (cb) res = cb(res, idx, query);
7681
return res;
7782
};

src/60createtable.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
317317
//Used in 420from queryfn when table.view = true!
318318
if (this.view && this.select) {
319319
table.view = true;
320-
table.select = this.select.compile(this.table.databaseid || databaseid);
320+
// Store the uncompiled select statement and databaseid for lazy compilation
321+
table.viewSelect = this.select;
322+
table.viewDatabaseid = this.table.databaseid || databaseid;
321323
}
322324

323325
if (db.engineid) {

test/test1154.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
}
5+
6+
describe('Test 950 - CREATE VIEW with subquery', function () {
7+
const test = '950';
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) Create tables', function () {
19+
alasql('create table sub_table(id int)');
20+
alasql('create table from_table(id int)');
21+
alasql('insert into sub_table values (1), (2), (3)');
22+
alasql('insert into from_table values (100)');
23+
});
24+
25+
it('B) Test the query works without view', function () {
26+
var result = alasql('select (select count(id) from sub_table) as amount from from_table');
27+
assert.deepEqual(result, [{amount: 3}]);
28+
});
29+
30+
it('C) Create view with subquery', function () {
31+
// This should not throw "Table does not exist: sub_table" error
32+
alasql(
33+
'create view new_view as select (select count(id) from sub_table) as amount from from_table'
34+
);
35+
});
36+
37+
it('D) Query from view', function () {
38+
var result = alasql('select * from new_view');
39+
assert.deepEqual(result, [{amount: 3}]);
40+
});
41+
42+
it('E) View should reflect data changes', function () {
43+
alasql('insert into sub_table values (4), (5)');
44+
var result = alasql('select * from new_view');
45+
assert.deepEqual(result, [{amount: 5}]);
46+
});
47+
48+
it('F) Drop view', function () {
49+
alasql('drop view new_view');
50+
});
51+
});

0 commit comments

Comments
 (0)