430 lines
14 KiB
JavaScript
430 lines
14 KiB
JavaScript
|
require('../../support/test_helper');
|
||
|
|
||
|
var assert = require('assert');
|
||
|
var OverviewsQueryRewriter = require('../../../lib/cartodb/utils/overviews_query_rewriter');
|
||
|
var overviewsQueryRewriter = new OverviewsQueryRewriter({
|
||
|
zoom_level: 'ZoomLevel()'
|
||
|
});
|
||
|
|
||
|
function normalize_whitespace(txt) {
|
||
|
return txt.replace(/\s+/g, " ").trim();
|
||
|
}
|
||
|
|
||
|
// compare SQL statements ignoring whitespace
|
||
|
function assertSameSql(sql1, sql2) {
|
||
|
assert.equal(normalize_whitespace(sql1), normalize_whitespace(sql2));
|
||
|
}
|
||
|
|
||
|
describe('Overviews query rewriter', function() {
|
||
|
|
||
|
it('does not alter queries if no overviews data is present', function(done){
|
||
|
var sql = "SELECT * FROM table1";
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, {});
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, { overviews: {} });
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
|
||
|
it('does not alter queries which don\'t use overviews', function(done){
|
||
|
var sql = "SELECT * FROM table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table2: {
|
||
|
0: { table: 'table2_ov0' },
|
||
|
1: { table: 'table2_ov1' },
|
||
|
4: { table: 'table2_ov4' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
// jshint multistr:true
|
||
|
|
||
|
it('generates query with single overview layer for level 0', function(done){
|
||
|
var sql = "SELECT * FROM table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
0: { table: 'table1_ov0' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov0, _vovw_scale WHERE _vovw_z = 0\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 0\
|
||
|
)\
|
||
|
SELECT * FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query with single overview layer for level >0', function(done){
|
||
|
var sql = "SELECT * FROM table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT * FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query with multiple overview layers for all levels up to N', function(done){
|
||
|
var sql = "SELECT * FROM table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
0: { table: 'table1_ov0' },
|
||
|
1: { table: 'table1_ov1' },
|
||
|
2: { table: 'table1_ov2' },
|
||
|
3: { table: 'table1_ov3' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov0, _vovw_scale WHERE _vovw_z = 0\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1_ov1, _vovw_scale WHERE _vovw_z = 1\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z = 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1_ov3, _vovw_scale WHERE _vovw_z = 3\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 3\
|
||
|
)\
|
||
|
SELECT * FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query with multiple overview layers for random levels', function(done){
|
||
|
var sql = "SELECT * FROM table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
0: { table: 'table1_ov0' },
|
||
|
1: { table: 'table1_ov1' },
|
||
|
6: { table: 'table1_ov6' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov0, _vovw_scale WHERE _vovw_z = 0\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1_ov1, _vovw_scale WHERE _vovw_z = 1\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1_ov6, _vovw_scale WHERE _vovw_z > 1 AND _vovw_z <= 6\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 6\
|
||
|
)\
|
||
|
SELECT * FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query for a table with explicit schema', function(done){
|
||
|
var sql = "SELECT * FROM public.table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
'public.table1': {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM public.table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM public.table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT * FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query for a table with explicit schema in the overviews info', function(done){
|
||
|
var sql = "SELECT * FROM public.table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
'public.table1': {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM public.table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM public.table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT * FROM _vovw_table1\
|
||
|
";
|
||
|
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query for a table that needs quoting with explicit schema', function(done){
|
||
|
var sql = "SELECT * FROM public.\"table 1\"";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
'public."table 1"': {
|
||
|
2: { table: '"table 1_ov2"' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
\"_vovw_table 1\" AS (\
|
||
|
SELECT * FROM public.\"table 1_ov2\", _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM public.\"table 1\", _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT * FROM \"_vovw_table 1\"\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query for a table with explicit schema that needs quoting', function(done){
|
||
|
var sql = "SELECT * FROM \"user-1\".table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
'"user-1".table1': {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM \"user-1\".table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM \"user-1\".table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT * FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
|
||
|
it('generates query for a table with explicit schema both needing quoting', function(done){
|
||
|
var sql = "SELECT * FROM \"user-1\".\"table 1\"";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
'"user-1"."table 1"': {
|
||
|
2: { table: '"table 1_ov2"' }
|
||
|
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
\"_vovw_table 1\" AS (\
|
||
|
SELECT * FROM \"user-1\".\"table 1_ov2\", _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM \"user-1\".\"table 1\", _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT * FROM \"_vovw_table 1\"\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
|
||
|
it('generates query using overviews for queries with selected columns', function(done){
|
||
|
var sql = "SELECT column1, column2, column3 FROM table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT column1, column2, column3 FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query using overviews for queries with selected columns and all columns', function(done){
|
||
|
var sql = "SELECT table1.*, column1, column2, column3 FROM table1";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT _vovw_table1.*, column1, column2, column3 FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query using overviews for queries with a semicolon', function(done){
|
||
|
var sql = "SELECT table1.*, column1, column2, column3 FROM table1;";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT _vovw_table1.*, column1, column2, column3 FROM _vovw_table1;\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('generates query using overviews for queries with extra whitespace', function(done){
|
||
|
var sql = " SELECT table1.* , column1,column2, column3 FROM table1 ";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
var expected_sql = "\
|
||
|
WITH\
|
||
|
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z ),\
|
||
|
_vovw_table1 AS (\
|
||
|
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||
|
UNION ALL\
|
||
|
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||
|
)\
|
||
|
SELECT _vovw_table1.* , column1,column2, column3 FROM _vovw_table1\
|
||
|
";
|
||
|
assertSameSql(overviews_sql, expected_sql);
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
it('does not alter queries which have not the simple supported form', function(done){
|
||
|
var sql = "SELECT * FROM table1 WHERE column1='x'";
|
||
|
var data = {
|
||
|
overviews: {
|
||
|
table1: {
|
||
|
2: { table: 'table1_ov2' }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
sql = "SELECT * FROM table1 JOIN table2 ON (table1.col1=table2.col1)";
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
sql = "SELECT a+b AS c FROM table1";
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
sql = "SELECT f(a) AS b FROM table1";
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
sql = "SELECT * FROM table1 AS x";
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
sql = "WITH a AS (1) SELECT * FROM table1";
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
sql = "SELECT * FROM table1 WHERE a=1";
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
sql = "\
|
||
|
SELECT table1.* FROM table1 \
|
||
|
JOIN areas ON ST_Intersects(table1.the_geom, areas.the_geom) \
|
||
|
WHERE areas.name='A' \
|
||
|
";
|
||
|
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||
|
assert.equal(overviews_sql, sql);
|
||
|
|
||
|
done();
|
||
|
});
|
||
|
|
||
|
|
||
|
});
|