Skip to content

Commit 8bbc1d8

Browse files
committed
#2027 sqlCache retains data (and other properties), possible memory leak #2027
- Remove the `data` property from the sql cache after executing the query
1 parent 0dd3a6f commit 8bbc1d8

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

src/17alasql.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,23 @@ alasql.exec = function (sql, params, cb, scope) {
244244
}
245245
};
246246

247+
/**
248+
* Clears any unneeded properties from a given AST statement closure used for caching
249+
* @param {Object} statement the statement to cleanup
250+
*/
251+
function cleanupCache(statement) {
252+
if (!statement) {
253+
return;
254+
}
255+
if (!alasql.options.cache) {
256+
return;
257+
}
258+
// cleanup the table data to prevent storing this information in the SQL cache
259+
if (statement && statement.query && statement.query.data) {
260+
statement.query.data = [];
261+
}
262+
}
263+
247264
/**
248265
Run SQL statement on specific database
249266
*/
@@ -259,7 +276,9 @@ alasql.dexec = function (databaseid, sql, params, cb, scope) {
259276
let statement = db.sqlCache[hh];
260277
// If database structure was not changed since last time return cache
261278
if (statement && db.dbversion === statement.dbversion) {
262-
return statement(params, cb);
279+
var res = statement(params, cb);
280+
cleanupCache(statement);
281+
return res;
263282
}
264283
}
265284

@@ -302,6 +321,7 @@ alasql.dexec = function (databaseid, sql, params, cb, scope) {
302321
db.sqlCache[hh] = statement;
303322
}
304323
var res = (alasql.res = statement(params, cb, scope));
324+
cleanupCache(statement);
305325
return res;
306326
}
307327
alasql.precompile(ast.statements[0], alasql.useid, params);

test/test2027.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const alasql = require('../dist/alasql.js');
2+
3+
if (typeof exports === 'object') {
4+
var assert = require('assert');
5+
}
6+
7+
describe('Test 2007 - SQL cache', function () {
8+
before(function () {
9+
alasql('create database test');
10+
alasql('use test');
11+
});
12+
13+
after(function () {
14+
alasql('drop database test');
15+
});
16+
17+
it('A) Execute query and assert cache for `data` afterwards', () => {
18+
alasql('CREATE TABLE osoby (id INT, meno STRING)');
19+
alasql('INSERT INTO osoby VALUES (1, "John"), (2, "Jane"), (3, "Jake")');
20+
alasql('SELECT * FROM osoby');
21+
22+
assert.deepEqual(alasql.databases["test"].sqlCache["-169125189"].query.data, []);
23+
24+
// Execute same query from cache again, the cache is hit now
25+
alasql('SELECT * FROM osoby');
26+
27+
// Cache should still be empty for "data"
28+
assert.deepEqual(alasql.databases["test"].sqlCache["-169125189"].query.data, []);
29+
});
30+
});

0 commit comments

Comments
 (0)