Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c36f52415e | ||
|
|
2ee2c5bb55 | ||
|
|
dccb557cd7 | ||
|
|
4570d17ce1 | ||
|
|
b3b3abcdb8 | ||
|
|
6639664b3f | ||
|
|
b99db7cb69 | ||
|
|
3e94e3288f | ||
|
|
1115f9fba2 | ||
|
|
24dde1e4d0 | ||
|
|
7d4caf6974 | ||
|
|
e4ba68850c | ||
|
|
e2154f6561 | ||
|
|
778860c81f | ||
|
|
ee3c56efba | ||
|
|
5dc328724a | ||
|
|
c77ea49594 | ||
|
|
73aa159b98 | ||
|
|
b7d7cffb67 | ||
|
|
eba8db292c | ||
|
|
d5391ef15b | ||
|
|
685cbb1eec | ||
|
|
5842a239fd | ||
|
|
285363aa40 | ||
|
|
92e130d8de | ||
|
|
f674f90eba | ||
|
|
0542b65cbb | ||
|
|
60fa94781e | ||
|
|
38d57533c2 | ||
|
|
e3d6da06a7 | ||
|
|
3af05bb734 | ||
|
|
ffd58cc7ca | ||
|
|
e103c52d27 | ||
|
|
46a4defab7 | ||
|
|
00a71af95d | ||
|
|
2fb8036740 | ||
|
|
6902a8c9b3 | ||
|
|
fd8be0352f | ||
|
|
c19a345f6c | ||
|
|
bdc3ecff5a | ||
|
|
6c4ec29e18 | ||
|
|
412712e62e | ||
|
|
0edcb30f75 | ||
|
|
c0f49b3acb | ||
|
|
b926244085 | ||
|
|
d21136b475 | ||
|
|
8788aaaf25 | ||
|
|
120e800089 | ||
|
|
92dc4b148c | ||
|
|
755dfe6822 | ||
|
|
b787ee1033 | ||
|
|
9ee3612da0 | ||
|
|
fe0b0a9c50 | ||
|
|
dea19f20dd | ||
|
|
f9f70cc6e7 | ||
|
|
23ef1157cb | ||
|
|
8ca4d537ce | ||
|
|
98d5731555 | ||
|
|
5da8929a5d | ||
|
|
e198bafac1 | ||
|
|
dd731399dc | ||
|
|
66fd899ffb | ||
|
|
bca8a33417 | ||
|
|
a11c8d882e | ||
|
|
c5bed48d61 | ||
|
|
98b7d12796 | ||
|
|
93dd8a2213 | ||
|
|
4e4a223f24 | ||
|
|
4a73f3874d | ||
|
|
bc845b2e8d | ||
|
|
83eceb349c | ||
|
|
bb518f0744 | ||
|
|
08ad961123 | ||
|
|
146d494cae | ||
|
|
bb40ecf7c2 | ||
|
|
7de9f64f2a | ||
|
|
0bb6178d49 | ||
|
|
084b3e94a6 | ||
|
|
a0445b5cdd | ||
|
|
1d4ddd373b | ||
|
|
92795963ae | ||
|
|
ecbae52abe | ||
|
|
57cba3d511 | ||
|
|
7902b276ad |
19
.jshintrc
@@ -82,13 +82,14 @@
|
||||
// "wsh" : false, // Windows Scripting Host
|
||||
// "yui" : false, // Yahoo User Interface
|
||||
|
||||
// Custom Globals
|
||||
"globals" : { // additional predefined global variables
|
||||
"describe": true,
|
||||
"before": true,
|
||||
"after": true,
|
||||
"beforeEach": true,
|
||||
"afterEach": true,
|
||||
"it": true
|
||||
}
|
||||
// Custom predefined global variables
|
||||
"predef": [
|
||||
"-console", // disallows console, use debug
|
||||
"beforeEach",
|
||||
"afterEach",
|
||||
"before",
|
||||
"after",
|
||||
"describe",
|
||||
"it"
|
||||
]
|
||||
}
|
||||
|
||||
99
NEWS.md
@@ -1,5 +1,104 @@
|
||||
# Changelog
|
||||
|
||||
## 2.40.0
|
||||
|
||||
Released 2016-05-10
|
||||
|
||||
Enhancements:
|
||||
- Use original query from source nodes #444
|
||||
|
||||
New features:
|
||||
- Allow override zoom+center or bbox for static named maps previews #443
|
||||
- Analysis layers can have a sql_wrap option to wrap node queries #441
|
||||
|
||||
|
||||
## 2.39.0
|
||||
|
||||
Released 2016-05-05
|
||||
|
||||
Announcements:
|
||||
- Upgrades step-profiler to 0.3.0 to avoid dots in json keys #438
|
||||
- Use a more aggressive cache control header for node status endpoint
|
||||
|
||||
|
||||
## 2.38.1
|
||||
|
||||
Released 2016-05-05
|
||||
|
||||
Announcements:
|
||||
- Fixes problem in turbo-carto dependency
|
||||
- Removes console usages
|
||||
|
||||
|
||||
## 2.38.0
|
||||
|
||||
Released 2016-05-05
|
||||
|
||||
Announcements:
|
||||
- Upgrades turbo-carto to [0.7.0](https://github.com/CartoDB/turbo-carto/releases/tag/0.7.0)
|
||||
|
||||
|
||||
## 2.37.0
|
||||
|
||||
Released 2016-05-03
|
||||
|
||||
Announcements:
|
||||
- Upgrades camshaft to [0.6.0](https://github.com/CartoDB/camshaft/releases/tag/0.6.0)
|
||||
|
||||
|
||||
## 2.36.1
|
||||
|
||||
Released 2016-04-29
|
||||
|
||||
Announcements:
|
||||
- Upgrades camshaft to [0.5.1](https://github.com/CartoDB/camshaft/releases/tag/0.5.1)
|
||||
|
||||
|
||||
## 2.36.0
|
||||
|
||||
Released 2016-04-28
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [1.19.0](https://github.com/CartoDB/Windshaft/releases/tag/1.19.0)
|
||||
|
||||
|
||||
## 2.35.0
|
||||
|
||||
Released 2016-04-27
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [1.18.0](https://github.com/CartoDB/Windshaft/releases/tag/1.18.0)
|
||||
- Appends columns to layers from associated dataviews
|
||||
|
||||
|
||||
## 2.34.1
|
||||
|
||||
Released 2016-04-27
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [1.17.3](https://github.com/CartoDB/Windshaft/releases/tag/1.17.3)
|
||||
|
||||
|
||||
## 2.34.0
|
||||
|
||||
Released 2016-04-27
|
||||
|
||||
Enhancements:
|
||||
- Adds support to return multiple errors in BaseController.sendError #423
|
||||
- Starts using turbo-carto dependency
|
||||
|
||||
Announcements:
|
||||
- Upgrades windshaft to [1.17.2](https://github.com/CartoDB/Windshaft/releases/tag/1.17.2)
|
||||
|
||||
|
||||
## 2.33.1
|
||||
|
||||
Released 2016-04-20
|
||||
|
||||
Bug fixes:
|
||||
- Support unneeded schema names in overviews queries #421
|
||||
|
||||
|
||||
## 2.33.0
|
||||
|
||||
Released 2016-04-20
|
||||
|
||||
17
app.js
@@ -14,6 +14,11 @@ if ( process.argv[2] ) {
|
||||
ENVIRONMENT = 'development';
|
||||
}
|
||||
|
||||
// jshint undef:false
|
||||
var log = console.log.bind(console);
|
||||
var logError = console.error.bind(console);
|
||||
// jshint undef:true
|
||||
|
||||
var availableEnvironments = {
|
||||
production: true,
|
||||
staging: true,
|
||||
@@ -22,8 +27,8 @@ var availableEnvironments = {
|
||||
|
||||
// sanity check
|
||||
if (!availableEnvironments[ENVIRONMENT]){
|
||||
console.error('node app.js [environment]');
|
||||
console.error('environments: %s', Object.keys(availableEnvironments).join(', '));
|
||||
logError('node app.js [environment]');
|
||||
logError('environments: %s', Object.keys(availableEnvironments).join(', '));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -58,10 +63,10 @@ if ( global.environment.log_filename ) {
|
||||
// See cwd inlog4js.configure call below
|
||||
logdir = path.resolve(__dirname, logdir);
|
||||
if ( ! fs.existsSync(logdir) ) {
|
||||
console.error("Log filename directory does not exist: " + logdir);
|
||||
logError("Log filename directory does not exist: " + logdir);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log("Logs will be written to " + global.environment.log_filename);
|
||||
log("Logs will be written to " + global.environment.log_filename);
|
||||
log4js_config.appenders.push(
|
||||
{ type: "file", filename: global.environment.log_filename }
|
||||
);
|
||||
@@ -94,7 +99,7 @@ var listener = server.listen(serverOptions.bind.port, serverOptions.bind.host, b
|
||||
var version = require("./package").version;
|
||||
|
||||
listener.on('listening', function() {
|
||||
console.log(
|
||||
log(
|
||||
"Windshaft tileserver %s started on %s:%s PID=%d (%s)",
|
||||
version, serverOptions.bind.host, serverOptions.bind.port, process.pid, ENVIRONMENT
|
||||
);
|
||||
@@ -111,7 +116,7 @@ process.on('SIGHUP', function() {
|
||||
global.log4js.clearAndShutdownAppenders(function() {
|
||||
global.log4js.configure(log4js_config);
|
||||
global.logger = global.log4js.getLogger();
|
||||
console.log('Log files reloaded');
|
||||
log('Log files reloaded');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -163,6 +163,10 @@ var config = {
|
||||
// Returning the portion of a geometry falling within a rectangle
|
||||
// It will only work if snapToGrid is enabled
|
||||
clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5
|
||||
// geometries will be simplified using ST_RemoveRepeatedPoints
|
||||
// which cost is no more expensive than snapping and results are
|
||||
// much closer to the original geometry
|
||||
removeRepeatedPoints: false // this requires postgis >=2.2
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -157,6 +157,10 @@ var config = {
|
||||
// Returning the portion of a geometry falling within a rectangle
|
||||
// It will only work if snapToGrid is enabled
|
||||
clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5
|
||||
// geometries will be simplified using ST_RemoveRepeatedPoints
|
||||
// which cost is no more expensive than snapping and results are
|
||||
// much closer to the original geometry
|
||||
removeRepeatedPoints: false // this requires postgis >=2.2
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -157,6 +157,10 @@ var config = {
|
||||
// Returning the portion of a geometry falling within a rectangle
|
||||
// It will only work if snapToGrid is enabled
|
||||
clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5
|
||||
// geometries will be simplified using ST_RemoveRepeatedPoints
|
||||
// which cost is no more expensive than snapping and results are
|
||||
// much closer to the original geometry
|
||||
removeRepeatedPoints: false // this requires postgis >=2.2
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -156,7 +156,11 @@ var config = {
|
||||
// SQL queries will be wrapped with ST_ClipByBox2D
|
||||
// Returning the portion of a geometry falling within a rectangle
|
||||
// It will only work if snapToGrid is enabled
|
||||
clipByBox2d: false // this requires postgis >=2.2 and geos >=3.5
|
||||
clipByBox2d: false, // this requires postgis >=2.2 and geos >=3.5
|
||||
// geometries will be simplified using ST_RemoveRepeatedPoints
|
||||
// which cost is no more expensive than snapping and results are
|
||||
// much closer to the original geometry
|
||||
removeRepeatedPoints: false // this requires postgis >=2.2
|
||||
}
|
||||
},
|
||||
http: {
|
||||
|
||||
@@ -451,6 +451,7 @@ callback({
|
||||
```
|
||||
|
||||
## CartoDB.js for Named Maps
|
||||
|
||||
You can use a Named Map that you created (which is defined by its `name`), to create a map using CartoDB.js. This is achieved by adding the [`namedmap` type](http://docs.cartodb.com/cartodb-platform/cartodb-js/layer-source-object/#named-maps-layer-source-object-type-namedmap) layer source object to draw the Named Map.
|
||||
|
||||
```javascript
|
||||
@@ -478,16 +479,48 @@ You can use a Named Map that you created (which is defined by its `name`), to cr
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Instantiating a Named Map over a `createLayer` does not require an API Key and by default, does not include auth tokens. _If_ you defined auth tokens for the Named Map configuration, then you will have to include them.
|
||||
|
||||
[CartoDB.js](http://docs.cartodb.com/cartodb-platform/cartodb-js/) has methods for accessing your Named Maps.
|
||||
|
||||
1. [layer.setParams()](http://docs.cartodb.com/cartodb-platform/cartodb-js/api-methods/#layersetparamskey-value) allows you to change the template variables (in the placeholders object) via JavaScript
|
||||
|
||||
**Note:** The CartoDB.js `layer.setParams()` function is not supported when using Named Maps for Torque.
|
||||
**Note:** The CartoDB.js `layer.setParams()` function is not supported when using Named Maps for Torque. Alternatively, you can create a [Torque layer in a Named Map](http://bl.ocks.org/iriberri/de37be6406f9cc7cfe5a)
|
||||
|
||||
2. [layer.setAuthToken()](http://docs.cartodb.com/cartodb-platform/cartodb-js/api-methods/#layersetauthtokenauthtoken) allows you to set the auth tokens to create the layer
|
||||
|
||||
### Torque Layer in a Named Map
|
||||
|
||||
If you are creating a Torque layer in a Named Map without using the Torque.js library, you can apply the Torque layer by applying the following code with CartoDBjs:
|
||||
|
||||
```javascript
|
||||
// add cartodb layer with one sublayer
|
||||
cartodb.createLayer(map, {
|
||||
user_name: '{username}',
|
||||
type: 'torque',
|
||||
order: 1,
|
||||
options: {
|
||||
query: "",
|
||||
table_name: "named_map_tutorial_table",
|
||||
user_name: "{username}",
|
||||
tile_style: 'Map { -torque-frame-count:512; -torque-animation-duration:10; -torque-time-attribute:"cartodb_id"; -torque-aggregation-function:"count(cartodb_id)"; -torque-resolution:2; -torque-data-aggregation:linear; } #named_map_tutorial_table_copy{ comp-op: lighter; marker-fill-opacity: 0.9; marker-line-color: #FFF; marker-line-width: 1.5; marker-line-opacity: 1; marker-type: ellipse; marker-width: 6; marker-fill: #FF9900; } #named_map_tutorial_table_copy[frame-offset=1] { marker-width:8; marker-fill-opacity:0.45; } #named_map_tutorial_table_copy[frame-offset=2] { marker-width:10; marker-fill-opacity:0.225; }'
|
||||
|
||||
},
|
||||
named_map: {
|
||||
name: "{namedmap_example}",
|
||||
layers: [{
|
||||
layer_name: "t"
|
||||
}]
|
||||
}
|
||||
})
|
||||
.addTo(map)
|
||||
.done(function(layer) {
|
||||
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
#### Examples of Named Maps created with CartoDB.js
|
||||
|
||||
- [Named Map selectors with interaction](http://bl.ocks.org/ohasselblad/515a8af1f99d5e690484)
|
||||
|
||||
@@ -49,8 +49,6 @@ bbox | the bounding box in WGS 84 (EPSG:4326), comma separated values for:
|
||||
width | the width in pixels for the output image
|
||||
height | the height in pixels for the output image
|
||||
format | the format for the image, supported types: `png`, `jpg`
|
||||
|
||||
format | the bounding box in WGS 84 (EPSG:4326), comma separated values for:
|
||||
--- | ---
|
||||
|_ jpg | will have a default quality of 85.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
function OverviewsMetadataApi(pgQueryRunner) {
|
||||
this.pgQueryRunner = pgQueryRunner;
|
||||
this.pgQueryRunner = pgQueryRunner;
|
||||
}
|
||||
|
||||
module.exports = OverviewsMetadataApi;
|
||||
@@ -22,22 +22,25 @@ function prepareSql(sql) {
|
||||
}
|
||||
|
||||
OverviewsMetadataApi.prototype.getOverviewsMetadata = function (username, sql, callback) {
|
||||
var query = 'SELECT * FROM CDB_Overviews(CDB_QueryTablesText($windshaft$' + prepareSql(sql) + '$windshaft$))';
|
||||
// FIXME: Currently using internal function _cdb_schema_name
|
||||
// CDB_Overviews should provide the schema information directly.
|
||||
var query = 'SELECT *, _cdb_schema_name(base_table)' +
|
||||
' FROM CDB_Overviews(CDB_QueryTablesText($windshaft$' + prepareSql(sql) + '$windshaft$))';
|
||||
this.pgQueryRunner.run(username, query, function handleOverviewsRows(err, rows) {
|
||||
if (err){
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
var metadata = {};
|
||||
rows.forEach(function(row) {
|
||||
var metadata = rows.reduce(function(metadata, row){
|
||||
var table = row.base_table;
|
||||
var table_metadata = metadata[table];
|
||||
if ( !table_metadata ) {
|
||||
table_metadata = metadata[table] = {};
|
||||
var schema = row._cdb_schema_name;
|
||||
if ( !metadata[table] ) {
|
||||
metadata[table] = {};
|
||||
}
|
||||
table_metadata[row.z] = { table: row.overview_table };
|
||||
});
|
||||
metadata[table][row.z] = { table: row.overview_table };
|
||||
metadata[table].schema = schema;
|
||||
return metadata;
|
||||
}, {});
|
||||
return callback(null, metadata);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ var queue = require('queue-async');
|
||||
var LruCache = require("lru-cache");
|
||||
|
||||
function NamedMapProviderCache(templateMaps, pgConnection, metadataBackend, userLimitsApi, overviewsAdapter,
|
||||
turboCartocssAdapter) {
|
||||
turboCartoAdapter) {
|
||||
this.templateMaps = templateMaps;
|
||||
this.pgConnection = pgConnection;
|
||||
this.metadataBackend = metadataBackend;
|
||||
@@ -18,7 +18,7 @@ function NamedMapProviderCache(templateMaps, pgConnection, metadataBackend, user
|
||||
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
|
||||
this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter();
|
||||
this.overviewsAdapter = overviewsAdapter;
|
||||
this.turboCartocssAdapter = turboCartocssAdapter;
|
||||
this.turboCartoAdapter = turboCartoAdapter;
|
||||
|
||||
this.providerCache = new LruCache({ max: 2000 });
|
||||
}
|
||||
@@ -38,7 +38,7 @@ NamedMapProviderCache.prototype.get = function(user, templateId, config, authTok
|
||||
this.userLimitsApi,
|
||||
this.namedLayersAdapter,
|
||||
this.overviewsAdapter,
|
||||
this.turboCartocssAdapter,
|
||||
this.turboCartoAdapter,
|
||||
this.analysisMapConfigAdapter,
|
||||
user,
|
||||
templateId,
|
||||
|
||||
@@ -14,6 +14,9 @@ var REQUEST_QUERY_PARAMS_WHITELIST = [
|
||||
'api_key',
|
||||
'auth_token',
|
||||
'callback',
|
||||
'zoom',
|
||||
'lon',
|
||||
'lat',
|
||||
// widgets & filters
|
||||
'filters', // json
|
||||
'own_filter', // 0, 1
|
||||
@@ -197,7 +200,10 @@ BaseController.prototype.send = function(req, res, body, status, headers) {
|
||||
// jshint maxcomplexity:6
|
||||
|
||||
BaseController.prototype.sendError = function(req, res, err, label) {
|
||||
var allErrors = Array.isArray(err) ? err : [err];
|
||||
label = label || 'UNKNOWN';
|
||||
err = allErrors[0] || new Error(label);
|
||||
allErrors[0] = err;
|
||||
|
||||
var statusCode = findStatusCode(err);
|
||||
|
||||
@@ -208,7 +214,7 @@ BaseController.prototype.sendError = function(req, res, err, label) {
|
||||
statusCode = 200;
|
||||
}
|
||||
|
||||
var errorResponseBody = { errors: [errorMessage(err)] };
|
||||
var errorResponseBody = { errors: allErrors.map(errorMessage) };
|
||||
|
||||
this.send(req, res, errorResponseBody, statusCode);
|
||||
};
|
||||
|
||||
@@ -116,7 +116,10 @@ LayergroupController.prototype.analysisNodeStatus = function(req, res) {
|
||||
if (err) {
|
||||
self.sendError(req, res, err, 'GET NODE STATUS');
|
||||
} else {
|
||||
self.sendResponse(req, res, nodeStatus, 200);
|
||||
self.sendResponse(req, res, nodeStatus, 200, {
|
||||
'Cache-Control': 'public,max-age=5',
|
||||
'Last-Modified': new Date().toUTCString()
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -30,13 +30,13 @@ var CreateLayergroupMapConfigProvider = require('../models/mapconfig/create_laye
|
||||
* @param {UserLimitsApi} userLimitsApi
|
||||
* @param {LayergroupAffectedTables} layergroupAffectedTables
|
||||
* @param {MapConfigOverviewsAdapter} overviewsAdapter
|
||||
* @param {TurboCartocssAdapter} turboCartoCssAdapter
|
||||
* @param {TurboCartoAdapter} turboCartoAdapter
|
||||
* @param {AnalysisBackend} analysisBackend
|
||||
* @constructor
|
||||
*/
|
||||
function MapController(authApi, pgConnection, templateMaps, mapBackend, metadataBackend,
|
||||
surrogateKeysCache, userLimitsApi, layergroupAffectedTables,
|
||||
overviewsAdapter, turboCartoCssAdapter, analysisBackend) {
|
||||
overviewsAdapter, turboCartoAdapter, analysisBackend) {
|
||||
|
||||
BaseController.call(this, authApi, pgConnection);
|
||||
|
||||
@@ -47,7 +47,7 @@ function MapController(authApi, pgConnection, templateMaps, mapBackend, metadata
|
||||
this.surrogateKeysCache = surrogateKeysCache;
|
||||
this.userLimitsApi = userLimitsApi;
|
||||
this.layergroupAffectedTables = layergroupAffectedTables;
|
||||
this.turboCartoCssAdapter = turboCartoCssAdapter;
|
||||
this.turboCartoAdapter = turboCartoAdapter;
|
||||
|
||||
this.analysisMapConfigAdapter = new AnalysisMapConfigAdapter(analysisBackend);
|
||||
this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps);
|
||||
@@ -163,7 +163,7 @@ MapController.prototype.create = function(req, res, prepareConfigFn) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
self.analysisMapConfigAdapter.getLayers(analysisConfiguration, requestMapConfig, filters, this);
|
||||
self.analysisMapConfigAdapter.getMapConfig(analysisConfiguration, requestMapConfig, filters, this);
|
||||
},
|
||||
function beforeLayergroupCreate(err, requestMapConfig, _analysesResults) {
|
||||
assert.ifError(err);
|
||||
@@ -197,11 +197,11 @@ MapController.prototype.create = function(req, res, prepareConfigFn) {
|
||||
return next(null, requestMapConfig, datasource);
|
||||
});
|
||||
},
|
||||
function parseTurboCartoCss(err, requestMapConfig, datasource) {
|
||||
function parseTurboCarto(err, requestMapConfig, datasource) {
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
self.turboCartoCssAdapter.getLayers(req.context.user, requestMapConfig.layers, function (err, layers) {
|
||||
self.turboCartoAdapter.getLayers(req.context.user, requestMapConfig.layers, function (err, layers) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
@@ -263,7 +263,7 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
|
||||
self.userLimitsApi,
|
||||
self.namedLayersAdapter,
|
||||
self.overviewsAdapter,
|
||||
self.turboCartoCssAdapter,
|
||||
self.turboCartoAdapter,
|
||||
self.analysisMapConfigAdapter,
|
||||
cdbuser,
|
||||
req.params.template_id,
|
||||
@@ -293,7 +293,9 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn
|
||||
var templateHash = self.templateMaps.fingerPrint(mapConfigProvider.template).substring(0, 8);
|
||||
layergroup.layergroupid = cdbuser + '@' + templateHash + '@' + layergroup.layergroupid;
|
||||
|
||||
addWidgetsUrl(req.context.user, layergroup);
|
||||
addWidgetsUrl(cdbuser, layergroup);
|
||||
addDataviewsUrls(cdbuser, layergroup, mapConfig.obj());
|
||||
addAnalysesMetadata(cdbuser, layergroup, mapConfigProvider.analysesResults);
|
||||
|
||||
res.set('X-Layergroup-Id', layergroup.layergroupid);
|
||||
self.surrogateKeysCache.tag(res, new NamedMapsCacheEntry(cdbuser, mapConfigProvider.getTemplateName()));
|
||||
@@ -371,7 +373,7 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, an
|
||||
// TODO this should take into account several URL patterns
|
||||
addWidgetsUrl(username, layergroup);
|
||||
addDataviewsUrls(username, layergroup, mapconfig.obj());
|
||||
addAnalysesMetadata(username, layergroup, analysesResults);
|
||||
addAnalysesMetadata(username, layergroup, analysesResults, true);
|
||||
if (req.method === 'GET') {
|
||||
var ttl = global.environment.varnish.layergroupTtl || 86400;
|
||||
res.set('Cache-Control', 'public,max-age='+ttl+',must-revalidate');
|
||||
@@ -390,9 +392,10 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, an
|
||||
);
|
||||
};
|
||||
|
||||
function addAnalysesMetadata(username, layergroup, analysesResults) {
|
||||
function addAnalysesMetadata(username, layergroup, analysesResults, includeQuery) {
|
||||
includeQuery = includeQuery || false;
|
||||
analysesResults = analysesResults || [];
|
||||
layergroup.metadata.analyses = layergroup.metadata.analyses || [];
|
||||
layergroup.metadata.analyses = [];
|
||||
|
||||
analysesResults.forEach(function(analysis) {
|
||||
var nodes = analysis.getSortedNodes();
|
||||
@@ -402,9 +405,11 @@ function addAnalysesMetadata(username, layergroup, analysesResults) {
|
||||
var nodeResource = layergroup.layergroupid + '/analysis/node/' + node.id();
|
||||
nodesIdMap[node.params.id] = {
|
||||
status: node.getStatus(),
|
||||
query: node.getQuery(),
|
||||
url: getUrls(username, nodeResource)
|
||||
};
|
||||
if (includeQuery) {
|
||||
nodesIdMap[node.params.id].query = node.getQuery();
|
||||
}
|
||||
}
|
||||
|
||||
return nodesIdMap;
|
||||
|
||||
@@ -140,7 +140,7 @@ NamedMapsController.prototype.staticMap = function(req, res) {
|
||||
function prepareImageOptions(err, _namedMapProvider) {
|
||||
assert.ifError(err);
|
||||
namedMapProvider = _namedMapProvider;
|
||||
self.getStaticImageOptions(cdbUser, namedMapProvider, this);
|
||||
self.getStaticImageOptions(cdbUser, req.params, namedMapProvider, this);
|
||||
},
|
||||
function getImage(err, imageOpts) {
|
||||
assert.ifError(err);
|
||||
@@ -192,9 +192,37 @@ var DEFAULT_ZOOM_CENTER = {
|
||||
}
|
||||
};
|
||||
|
||||
NamedMapsController.prototype.getStaticImageOptions = function(cdbUser, namedMapProvider, callback) {
|
||||
function numMapper(n) {
|
||||
return +n;
|
||||
}
|
||||
|
||||
NamedMapsController.prototype.getStaticImageOptions = function(cdbUser, params, namedMapProvider, callback) {
|
||||
var self = this;
|
||||
|
||||
if ([params.zoom, params.lon, params.lat].map(numMapper).every(Number.isFinite)) {
|
||||
return callback(null, {
|
||||
zoom: params.zoom,
|
||||
center: {
|
||||
lng: params.lon,
|
||||
lat: params.lat
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (params.bbox) {
|
||||
var bbox = params.bbox.split(',').map(numMapper);
|
||||
if (bbox.length === 4 && bbox.every(Number.isFinite)) {
|
||||
return callback(null, {
|
||||
bounds: {
|
||||
west: bbox[0],
|
||||
south: bbox[1],
|
||||
east: bbox[2],
|
||||
north: bbox[3]
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
step(
|
||||
function getTemplate() {
|
||||
namedMapProvider.getTemplate(this);
|
||||
@@ -205,6 +233,9 @@ NamedMapsController.prototype.getStaticImageOptions = function(cdbUser, namedMap
|
||||
if (template.view) {
|
||||
var zoomCenter = templateZoomCenter(template.view);
|
||||
if (zoomCenter) {
|
||||
if (Number.isFinite(+params.zoom)) {
|
||||
zoomCenter.zoom = +params.zoom;
|
||||
}
|
||||
return zoomCenter;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,12 @@ var layerQueryTemplate = dot.template([
|
||||
'FROM ({{=it._query}}) _cdb_analysis_query'
|
||||
].join('\n'));
|
||||
|
||||
function layerQuery(query, columnNames) {
|
||||
var _columns = ['ST_Transform(the_geom, 3857) the_geom_webmercator'].concat(skipColumns(columnNames));
|
||||
return layerQueryTemplate({ _query: query, _columns: _columns.join(', ') });
|
||||
function layerQuery(node) {
|
||||
if (node.type === 'source') {
|
||||
return node.getQuery();
|
||||
}
|
||||
var _columns = ['ST_Transform(the_geom, 3857) the_geom_webmercator'].concat(skipColumns(node.getColumns()));
|
||||
return layerQueryTemplate({ _query: node.getQuery(), _columns: _columns.join(', ') });
|
||||
}
|
||||
|
||||
function appendFiltersToNodes(requestMapConfig, dataviewsFiltersBySourceId) {
|
||||
@@ -66,7 +69,7 @@ function getFilter(dataview, params) {
|
||||
};
|
||||
}
|
||||
|
||||
AnalysisMapConfigAdapter.prototype.getLayers = function(analysisConfiguration, requestMapConfig, filters, callback) {
|
||||
AnalysisMapConfigAdapter.prototype.getMapConfig = function(analysisConfiguration, requestMapConfig, filters, callback) {
|
||||
// jshint maxcomplexity:7
|
||||
var self = this;
|
||||
filters = filters || {};
|
||||
@@ -79,6 +82,11 @@ AnalysisMapConfigAdapter.prototype.getLayers = function(analysisConfiguration, r
|
||||
debug(dataviewsFilters);
|
||||
var dataviews = requestMapConfig.dataviews || {};
|
||||
|
||||
var errors = getDataviewsErrors(dataviews);
|
||||
if (errors.length > 0) {
|
||||
return callback(errors);
|
||||
}
|
||||
|
||||
var dataviewsFiltersBySourceId = Object.keys(dataviewsFilters).reduce(function(bySourceId, dataviewName) {
|
||||
var dataview = dataviews[dataviewName];
|
||||
if (dataview) {
|
||||
@@ -127,16 +135,94 @@ AnalysisMapConfigAdapter.prototype.getLayers = function(analysisConfiguration, r
|
||||
return sourceId2Query;
|
||||
}, {});
|
||||
|
||||
requestMapConfig.layers = requestMapConfig.layers.map(function(layer) {
|
||||
if (layer.options.source && layer.options.source.id) {
|
||||
var layerNode = sourceId2Node[layer.options.source.id];
|
||||
layer.options.sql = layerQuery(layerNode.getQuery(), layerNode.getColumns());
|
||||
var missingNodesErrors = [];
|
||||
|
||||
requestMapConfig.layers = requestMapConfig.layers.map(function(layer, layerIndex) {
|
||||
if (getLayerSourceId(layer)) {
|
||||
var layerSourceId = getLayerSourceId(layer);
|
||||
var layerNode = sourceId2Node[layerSourceId];
|
||||
if (layerNode) {
|
||||
var analysisSql = layerQuery(layerNode);
|
||||
var sqlQueryWrap = layer.options.sql_wrap;
|
||||
if (sqlQueryWrap) {
|
||||
analysisSql = sqlQueryWrap.replace(/<%=\s*sql\s*%>/g, analysisSql);
|
||||
}
|
||||
layer.options.sql = analysisSql;
|
||||
var layerDataviews = getLayerDataviews(layer, dataviews);
|
||||
layer.options.columns = layerDataviews.reduce(function(columns, dataview) {
|
||||
return columns.concat(getDataviewColumns(dataview));
|
||||
}, []);
|
||||
} else {
|
||||
missingNodesErrors.push(
|
||||
new Error('Missing analysis node.id="' + layerSourceId +'" for layer='+layerIndex)
|
||||
);
|
||||
}
|
||||
}
|
||||
return layer;
|
||||
});
|
||||
|
||||
debug('mapconfig output', JSON.stringify(requestMapConfig, null, 4));
|
||||
|
||||
if (missingNodesErrors.length > 0) {
|
||||
return callback(missingNodesErrors);
|
||||
}
|
||||
|
||||
return callback(null, requestMapConfig, analysesResults);
|
||||
});
|
||||
};
|
||||
|
||||
function getLayerSourceId(layer) {
|
||||
return layer.options.source && layer.options.source.id;
|
||||
}
|
||||
|
||||
function getDataviewSourceId(dataview) {
|
||||
return dataview.source && dataview.source.id;
|
||||
}
|
||||
|
||||
function getLayerDataviews(layer, dataviews) {
|
||||
var layerDataviews = [];
|
||||
|
||||
var layerSourceId = getLayerSourceId(layer);
|
||||
if (layerSourceId) {
|
||||
var dataviewsList = getDataviewsList(dataviews);
|
||||
dataviewsList.forEach(function(dataview) {
|
||||
if (getDataviewSourceId(dataview) === layerSourceId) {
|
||||
layerDataviews.push(dataview);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return layerDataviews;
|
||||
}
|
||||
|
||||
function getDataviewColumns(dataview) {
|
||||
var columns = [];
|
||||
var options = dataview.options;
|
||||
['column', 'aggregationColumn'].forEach(function(opt) {
|
||||
if (options.hasOwnProperty(opt)) {
|
||||
columns.push(options[opt]);
|
||||
}
|
||||
});
|
||||
return columns;
|
||||
}
|
||||
|
||||
function getDataviewsList(dataviews) {
|
||||
return Object.keys(dataviews).map(function(dataviewKey) { return dataviews[dataviewKey]; });
|
||||
}
|
||||
|
||||
function getDataviewsErrors(dataviews) {
|
||||
var errors = [];
|
||||
|
||||
Object.keys(dataviews).forEach(function(dataviewName) {
|
||||
var dataview = dataviews[dataviewName];
|
||||
if (!dataview.hasOwnProperty('source') || !dataview.source.id) {
|
||||
errors.push(new Error('Dataview "' + dataviewName + '" is missing `source.id` attribute'));
|
||||
}
|
||||
|
||||
if (!dataview.type) {
|
||||
errors.push(new Error('Dataview "' + dataviewName + '" is missing `type` attribute'));
|
||||
}
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@ var QueryTables = require('cartodb-query-tables');
|
||||
* @type {NamedMapMapConfigProvider}
|
||||
*/
|
||||
function NamedMapMapConfigProvider(templateMaps, pgConnection, metadataBackend, userLimitsApi,
|
||||
namedLayersAdapter, overviewsAdapter, turboCartoCssAdapter, analysisMapConfigAdapter,
|
||||
namedLayersAdapter, overviewsAdapter, turboCartoAdapter, analysisMapConfigAdapter,
|
||||
owner, templateId, config, authToken, params) {
|
||||
this.templateMaps = templateMaps;
|
||||
this.pgConnection = pgConnection;
|
||||
this.metadataBackend = metadataBackend;
|
||||
this.userLimitsApi = userLimitsApi;
|
||||
this.namedLayersAdapter = namedLayersAdapter;
|
||||
this.turboCartoCssAdapter = turboCartoCssAdapter;
|
||||
this.turboCartoAdapter = turboCartoAdapter;
|
||||
this.analysisMapConfigAdapter = analysisMapConfigAdapter;
|
||||
this.overviewsAdapter = overviewsAdapter;
|
||||
|
||||
@@ -41,6 +41,7 @@ function NamedMapMapConfigProvider(templateMaps, pgConnection, metadataBackend,
|
||||
this.mapConfig = null;
|
||||
this.rendererParams = null;
|
||||
this.context = {};
|
||||
this.analysesResults = [];
|
||||
}
|
||||
|
||||
module.exports = NamedMapMapConfigProvider;
|
||||
@@ -118,11 +119,12 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
self.analysisMapConfigAdapter.getLayers(analysisConfiguration, requestMapConfig, filters, this);
|
||||
self.analysisMapConfigAdapter.getMapConfig(analysisConfiguration, requestMapConfig, filters, this);
|
||||
},
|
||||
function prepareLayergroup(err, _mapConfig) {
|
||||
function prepareLayergroup(err, _mapConfig, analysesResults) {
|
||||
assert.ifError(err);
|
||||
var next = this;
|
||||
self.analysesResults = analysesResults || [];
|
||||
self.namedLayersAdapter.getLayers(self.owner, _mapConfig.layers, self.pgConnection,
|
||||
function(err, layers, datasource) {
|
||||
if (err) {
|
||||
@@ -152,11 +154,11 @@ NamedMapMapConfigProvider.prototype.getMapConfig = function(callback) {
|
||||
return next(null, _mapConfig, datasource);
|
||||
});
|
||||
},
|
||||
function parseTurboCartoCss(err, _mapConfig, datasource) {
|
||||
function parseTurboCarto(err, _mapConfig, datasource) {
|
||||
assert.ifError(err);
|
||||
var next = this;
|
||||
|
||||
self.turboCartoCssAdapter.getLayers(self.owner, _mapConfig.layers, function (err, layers) {
|
||||
self.turboCartoAdapter.getLayers(self.owner, _mapConfig.layers, function (err, layers) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ var bodyParser = require('body-parser');
|
||||
var RedisPool = require('redis-mpool');
|
||||
var cartodbRedis = require('cartodb-redis');
|
||||
var _ = require('underscore');
|
||||
var debug = require('debug')('windshaft:cartodb');
|
||||
|
||||
var controller = require('./controllers');
|
||||
|
||||
@@ -34,8 +35,8 @@ var timeoutErrorTile = require('fs').readFileSync(timeoutErrorTilePath, {encodin
|
||||
|
||||
var MapConfigOverviewsAdapter = require('./models/mapconfig_overviews_adapter');
|
||||
|
||||
var TurboCartocssParser = require('./utils/style/turbo-cartocss-parser');
|
||||
var TurboCartocssAdapter = require('./utils/style/turbo-cartocss-adapter');
|
||||
var TurboCartoParser = require('./utils/style/turbo-carto-parser');
|
||||
var TurboCartoAdapter = require('./utils/style/turbo-carto-adapter');
|
||||
|
||||
module.exports = function(serverOptions) {
|
||||
// Make stats client globally accessible
|
||||
@@ -149,8 +150,8 @@ module.exports = function(serverOptions) {
|
||||
|
||||
var overviewsAdapter = new MapConfigOverviewsAdapter(overviewsMetadataApi);
|
||||
|
||||
var turboCartoCssParser = new TurboCartocssParser(pgQueryRunner);
|
||||
var turboCartocssAdapter = new TurboCartocssAdapter(turboCartoCssParser);
|
||||
var turboCartoParser = new TurboCartoParser(pgQueryRunner);
|
||||
var turboCartoAdapter = new TurboCartoAdapter(turboCartoParser);
|
||||
|
||||
var namedMapProviderCache = new NamedMapProviderCache(
|
||||
templateMaps,
|
||||
@@ -158,7 +159,7 @@ module.exports = function(serverOptions) {
|
||||
metadataBackend,
|
||||
userLimitsApi,
|
||||
overviewsAdapter,
|
||||
turboCartocssAdapter
|
||||
turboCartoAdapter
|
||||
);
|
||||
|
||||
['update', 'delete'].forEach(function(eventType) {
|
||||
@@ -198,7 +199,7 @@ module.exports = function(serverOptions) {
|
||||
userLimitsApi,
|
||||
layergroupAffectedTablesCache,
|
||||
overviewsAdapter,
|
||||
turboCartocssAdapter,
|
||||
turboCartoAdapter,
|
||||
analysisBackend
|
||||
).register(app);
|
||||
|
||||
@@ -231,7 +232,7 @@ function validateOptions(opts) {
|
||||
|
||||
// Be nice and warn if configured mapnik version is != instaled mapnik version
|
||||
if (mapnik.versions.mapnik !== opts.grainstore.mapnik_version) {
|
||||
console.warn('WARNING: detected mapnik version (' + mapnik.versions.mapnik + ')' +
|
||||
debug('WARNING: detected mapnik version (' + mapnik.versions.mapnik + ')' +
|
||||
' != configured mapnik version (' + opts.grainstore.mapnik_version + ')');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ function overviews_view_for_table(table, overviews_metadata, indent) {
|
||||
|
||||
indent = indent || ' ';
|
||||
for (var z in overviews_metadata) {
|
||||
if (overviews_metadata.hasOwnProperty(z)) {
|
||||
if (overviews_metadata.hasOwnProperty(z) && z !== 'schema') {
|
||||
sorted_overviews.push([z, overviews_metadata[z].table]);
|
||||
}
|
||||
}
|
||||
@@ -39,11 +39,11 @@ function overviews_view_for_table(table, overviews_metadata, indent) {
|
||||
overview_layers.push(["_vovw_z > " + z_lo, table]);
|
||||
|
||||
selects = overview_layers.map(function(condition_table) {
|
||||
condition = condition_table[0];
|
||||
ov_table = TableNameParser.parse(condition_table[1]);
|
||||
ov_table.schema = ov_table.schema || parsed_table.schema;
|
||||
var ov_identifier = TableNameParser.table_identifier(ov_table);
|
||||
return indent + "SELECT * FROM " + ov_identifier + ", _vovw_scale WHERE " + condition;
|
||||
condition = condition_table[0];
|
||||
ov_table = TableNameParser.parse(condition_table[1]);
|
||||
ov_table.schema = ov_table.schema || parsed_table.schema;
|
||||
var ov_identifier = TableNameParser.table_identifier(ov_table);
|
||||
return indent + "SELECT * FROM " + ov_identifier + ", _vovw_scale WHERE " + condition;
|
||||
});
|
||||
|
||||
return selects.join("\n"+indent+"UNION ALL\n");
|
||||
@@ -90,13 +90,13 @@ function replace_table_in_query(sql, old_table_name, replacement) {
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
// to match a table name without schema
|
||||
// name should not begin right after a dot (i.e. have a explicit schema)
|
||||
// nor be part of another name
|
||||
// since the pattern matches the first character of the table
|
||||
// it must be put back in the replacement text
|
||||
replacement = '$01'+replacement;
|
||||
return '([^\.a-z0-9_]|^)';
|
||||
// to match a table name without schema
|
||||
// name should not begin right after a dot (i.e. have a explicit schema)
|
||||
// nor be part of another name
|
||||
// since the pattern matches the first character of the table
|
||||
// it must be put back in the replacement text
|
||||
replacement = '$01'+replacement;
|
||||
return '([^\.a-z0-9_]|^)';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,8 +127,16 @@ function overviews_query(query, overviews, zoom_level_expression) {
|
||||
if (overviews.hasOwnProperty(table)) {
|
||||
var table_overviews = overviews[table];
|
||||
var table_view = overviews_view_name(table);
|
||||
var schema = table_overviews.schema;
|
||||
replacement = "(\n" + overviews_view_for_table(table, table_overviews) + "\n ) AS " + table_view;
|
||||
replaced_query = replace_table_in_query(replaced_query, table, replacement);
|
||||
var parsed_table = TableNameParser.parse(table);
|
||||
if (!parsed_table.schema && schema) {
|
||||
// replace also the qualified table name, if the table wasn't qualified
|
||||
parsed_table.schema = schema;
|
||||
table = TableNameParser.table_identifier(parsed_table);
|
||||
replaced_query = replace_table_in_query(replaced_query, table, replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( replaced_query !== query ) {
|
||||
@@ -168,18 +176,19 @@ OverviewsQueryRewriter.prototype.query = function(query, data) {
|
||||
};
|
||||
|
||||
OverviewsQueryRewriter.prototype.is_supported_query = function(sql) {
|
||||
var basic_query = /\s*SELECT\s+[\*a-z0-9_,\s]+?\s+FROM\s+((\"[^"]+\"|[a-z0-9_]+)\.)?(\"[^"]+\"|[a-z0-9_]+)\s*;?\s*/i;
|
||||
var unwrapped_query = new RegExp("^"+basic_query.source+"$", 'i');
|
||||
// queries for named maps are wrapped like this:
|
||||
var wrapped_query = new RegExp(
|
||||
"^\\s*SELECT\\s+\\*\\s+FROM\\s+\\(" +
|
||||
basic_query.source +
|
||||
"\\)\\s+AS\\s+wrapped_query\\s+WHERE\\s+\\d+=1\\s*$",
|
||||
'i'
|
||||
);
|
||||
return !!(sql.match(unwrapped_query) || sql.match(wrapped_query));
|
||||
var basic_query =
|
||||
/\s*SELECT\s+[\*a-z0-9_,\s]+?\s+FROM\s+((\"[^"]+\"|[a-z0-9_]+)\.)?(\"[^"]+\"|[a-z0-9_]+)\s*;?\s*/i;
|
||||
var unwrapped_query = new RegExp("^"+basic_query.source+"$", 'i');
|
||||
// queries for named maps are wrapped like this:
|
||||
var wrapped_query = new RegExp(
|
||||
"^\\s*SELECT\\s+\\*\\s+FROM\\s+\\(" +
|
||||
basic_query.source +
|
||||
"\\)\\s+AS\\s+wrapped_query\\s+WHERE\\s+\\d+=1\\s*$",
|
||||
'i'
|
||||
);
|
||||
return !!(sql.match(unwrapped_query) || sql.match(wrapped_query));
|
||||
};
|
||||
|
||||
OverviewsQueryRewriter.prototype.overviews_metadata = function(data) {
|
||||
return data && data.overviews;
|
||||
return data && data.overviews;
|
||||
};
|
||||
|
||||
@@ -2,26 +2,26 @@
|
||||
|
||||
var queue = require('queue-async');
|
||||
|
||||
function TurboCartocssAdapter(turboCartocssParser) {
|
||||
this.turboCartocssParser = turboCartocssParser;
|
||||
function TurboCartoAdapter(turboCartoParser) {
|
||||
this.turboCartoParser = turboCartoParser;
|
||||
}
|
||||
|
||||
module.exports = TurboCartocssAdapter;
|
||||
module.exports = TurboCartoAdapter;
|
||||
|
||||
TurboCartocssAdapter.prototype.getLayers = function (username, layers, callback) {
|
||||
TurboCartoAdapter.prototype.getLayers = function (username, layers, callback) {
|
||||
var self = this;
|
||||
|
||||
if (!layers || layers.length === 0) {
|
||||
return callback(null, layers);
|
||||
}
|
||||
|
||||
var parseCartoCssQueue = queue(layers.length);
|
||||
var parseCartoQueue = queue(layers.length);
|
||||
|
||||
layers.forEach(function(layer) {
|
||||
parseCartoCssQueue.defer(self._parseCartoCss.bind(self), username, layer);
|
||||
parseCartoQueue.defer(self._parseCartoCss.bind(self), username, layer);
|
||||
});
|
||||
|
||||
parseCartoCssQueue.awaitAll(function (err, layers) {
|
||||
parseCartoQueue.awaitAll(function (err, layers) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
@@ -30,15 +30,15 @@ TurboCartocssAdapter.prototype.getLayers = function (username, layers, callback)
|
||||
});
|
||||
};
|
||||
|
||||
TurboCartocssAdapter.prototype._parseCartoCss = function (username, layer, callback) {
|
||||
TurboCartoAdapter.prototype._parseCartoCss = function (username, layer, callback) {
|
||||
if (isNotLayerToParseCartocss(layer)) {
|
||||
return process.nextTick(function () {
|
||||
callback(null, layer);
|
||||
});
|
||||
}
|
||||
|
||||
this.turboCartocssParser.process(username, layer.options.cartocss, layer.options.sql, function (err, cartocss) {
|
||||
// Ignore turbo-cartocss errors and continue
|
||||
this.turboCartoParser.process(username, layer.options.cartocss, layer.options.sql, function (err, cartocss) {
|
||||
// Ignore turbo-carto errors and continue
|
||||
if (!err && cartocss) {
|
||||
layer.options.cartocss = cartocss;
|
||||
}
|
||||
15
lib/cartodb/utils/style/turbo-carto-parser.js
Normal file
@@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
var turboCarto = require('turbo-carto');
|
||||
var PostgresDatasource = require('./postgres-datasource');
|
||||
|
||||
function TurboCartoParser (pgQueryRunner) {
|
||||
this.pgQueryRunner = pgQueryRunner;
|
||||
}
|
||||
|
||||
module.exports = TurboCartoParser;
|
||||
|
||||
TurboCartoParser.prototype.process = function (username, cartocss, sql, callback) {
|
||||
var datasource = new PostgresDatasource(this.pgQueryRunner, username, sql);
|
||||
turboCarto(cartocss, datasource, callback);
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var turboCartoCss = require('turbo-cartocss');
|
||||
var PostgresDatasource = require('./postgres-datasource');
|
||||
|
||||
function TurboCartocssParser (pgQueryRunner) {
|
||||
this.pgQueryRunner = pgQueryRunner;
|
||||
}
|
||||
|
||||
module.exports = TurboCartocssParser;
|
||||
|
||||
TurboCartocssParser.prototype.process = function (username, cartocss, sql, callback) {
|
||||
var datasource = new PostgresDatasource(this.pgQueryRunner, username, sql);
|
||||
turboCartoCss(cartocss, datasource, callback);
|
||||
};
|
||||
676
npm-shrinkwrap.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "windshaft-cartodb",
|
||||
"version": "2.33.0",
|
||||
"version": "2.40.0",
|
||||
"dependencies": {
|
||||
"body-parser": {
|
||||
"version": "1.14.2",
|
||||
@@ -89,14 +89,14 @@
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.10",
|
||||
"from": "mime-types@>=2.1.2 <2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz",
|
||||
"version": "2.1.11",
|
||||
"from": "mime-types@>=2.1.10 <2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.22.0",
|
||||
"from": "mime-db@>=1.22.0 <1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz"
|
||||
"version": "1.23.0",
|
||||
"from": "mime-db@>=1.23.0 <1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,9 +105,9 @@
|
||||
}
|
||||
},
|
||||
"camshaft": {
|
||||
"version": "0.5.0",
|
||||
"from": "camshaft@0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.5.0.tgz",
|
||||
"version": "0.6.0",
|
||||
"from": "camshaft@0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/camshaft/-/camshaft-0.6.0.tgz",
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
@@ -174,9 +174,9 @@
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"from": "process-nextick-args@>=1.0.6 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz"
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
@@ -395,26 +395,29 @@
|
||||
}
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.7.4",
|
||||
"version": "1.8.3",
|
||||
"from": "sshpk@>=1.7.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.7.4.tgz",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz",
|
||||
"dependencies": {
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"from": "asn1@>=0.2.3 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz"
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"from": "assert-plus@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.13.0",
|
||||
"from": "dashdash@>=1.10.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.13.0.tgz",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"from": "assert-plus@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
"version": "1.13.1",
|
||||
"from": "dashdash@>=1.12.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.13.1.tgz"
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.6",
|
||||
"from": "getpass@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz"
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.0",
|
||||
@@ -422,9 +425,9 @@
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz"
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.3",
|
||||
"from": "tweetnacl@>=0.13.0 <1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz"
|
||||
"version": "0.13.3",
|
||||
"from": "tweetnacl@>=0.13.0 <0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz"
|
||||
},
|
||||
"jodid25519": {
|
||||
"version": "1.0.2",
|
||||
@@ -433,7 +436,7 @@
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"from": "ecc-jsbn@>=0.0.1 <1.0.0",
|
||||
"from": "ecc-jsbn@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz"
|
||||
}
|
||||
}
|
||||
@@ -456,14 +459,14 @@
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.10",
|
||||
"version": "2.1.11",
|
||||
"from": "mime-types@>=2.1.7 <2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.22.0",
|
||||
"from": "mime-db@>=1.22.0 <1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz"
|
||||
"version": "1.23.0",
|
||||
"from": "mime-db@>=1.23.0 <1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -473,9 +476,9 @@
|
||||
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz"
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"from": "oauth-sign@>=0.8.1 <0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.1.tgz"
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz"
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.1.0",
|
||||
@@ -493,9 +496,9 @@
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz"
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.3",
|
||||
"from": "tunnel-agent@>=0.4.1 <0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz"
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -599,14 +602,14 @@
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz",
|
||||
"dependencies": {
|
||||
"mime-types": {
|
||||
"version": "2.1.10",
|
||||
"version": "2.1.11",
|
||||
"from": "mime-types@>=2.1.6 <2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.22.0",
|
||||
"from": "mime-db@>=1.22.0 <1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz"
|
||||
"version": "1.23.0",
|
||||
"from": "mime-db@>=1.23.0 <1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -788,14 +791,14 @@
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.10",
|
||||
"version": "2.1.11",
|
||||
"from": "mime-types@>=2.1.6 <2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.22.0",
|
||||
"from": "mime-db@>=1.22.0 <1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz"
|
||||
"version": "1.23.0",
|
||||
"from": "mime-db@>=1.23.0 <1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -952,9 +955,9 @@
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.7",
|
||||
"from": "process-nextick-args@>=1.0.6 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz"
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
@@ -992,7 +995,7 @@
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
"from": "async@>=1.5.2 <2.0.0",
|
||||
"from": "async@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz"
|
||||
}
|
||||
}
|
||||
@@ -1003,14 +1006,14 @@
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.10",
|
||||
"version": "2.1.11",
|
||||
"from": "mime-types@>=2.1.2 <2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.11.tgz",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.22.0",
|
||||
"from": "mime-db@>=1.22.0 <1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz"
|
||||
"version": "1.23.0",
|
||||
"from": "mime-db@>=1.23.0 <1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.23.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1025,9 +1028,9 @@
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz"
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.3",
|
||||
"from": "tunnel-agent@>=0.4.0 <0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz"
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.2.2",
|
||||
@@ -1057,9 +1060,9 @@
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.1",
|
||||
"version": "0.8.2",
|
||||
"from": "oauth-sign@>=0.8.0 <0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.1.tgz"
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz"
|
||||
},
|
||||
"hawk": {
|
||||
"version": "3.1.3",
|
||||
@@ -1227,96 +1230,32 @@
|
||||
"resolved": "https://registry.npmjs.org/step/-/step-0.0.6.tgz"
|
||||
},
|
||||
"step-profiler": {
|
||||
"version": "0.2.1",
|
||||
"from": "step-profiler@>=0.2.1 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/step-profiler/-/step-profiler-0.2.1.tgz"
|
||||
"version": "0.3.0",
|
||||
"from": "step-profiler@>=0.3.0 <0.4.0"
|
||||
},
|
||||
"turbo-cartocss": {
|
||||
"version": "0.4.0",
|
||||
"from": "turbo-cartocss@0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/turbo-cartocss/-/turbo-cartocss-0.4.0.tgz",
|
||||
"turbo-carto": {
|
||||
"version": "0.7.1",
|
||||
"from": "turbo-carto@0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/turbo-carto/-/turbo-carto-0.7.1.tgz",
|
||||
"dependencies": {
|
||||
"browser-request": {
|
||||
"version": "0.3.3",
|
||||
"from": "browser-request@>=0.3.3 <0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz"
|
||||
},
|
||||
"colorbrewer": {
|
||||
"version": "0.0.2",
|
||||
"from": "colorbrewer@0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/colorbrewer/-/colorbrewer-0.0.2.tgz"
|
||||
"version": "1.0.0",
|
||||
"from": "colorbrewer@1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/colorbrewer/-/colorbrewer-1.0.0.tgz"
|
||||
},
|
||||
"cartocolor": {
|
||||
"version": "1.0.2",
|
||||
"from": "cartocolor@1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/cartocolor/-/cartocolor-1.0.2.tgz"
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "3.1.2",
|
||||
"from": "es6-promise@>=3.0.2 <4.0.0",
|
||||
"from": "es6-promise@3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.1.2.tgz"
|
||||
},
|
||||
"less": {
|
||||
"version": "2.6.1",
|
||||
"from": "less@>=2.5.3 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-2.6.1.tgz",
|
||||
"dependencies": {
|
||||
"errno": {
|
||||
"version": "0.1.4",
|
||||
"from": "errno@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz",
|
||||
"dependencies": {
|
||||
"prr": {
|
||||
"version": "0.0.0",
|
||||
"from": "prr@>=0.0.0 <0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.3",
|
||||
"from": "graceful-fs@>=4.1.2 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.3.tgz"
|
||||
},
|
||||
"image-size": {
|
||||
"version": "0.4.0",
|
||||
"from": "image-size@>=0.4.0 <0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.4.0.tgz"
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.3.4",
|
||||
"from": "mime@>=1.2.11 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz"
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"from": "mkdirp@>=0.5.0 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"from": "minimist@0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"promise": {
|
||||
"version": "7.1.1",
|
||||
"from": "promise@>=7.1.1 <8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/promise/-/promise-7.1.1.tgz",
|
||||
"dependencies": {
|
||||
"asap": {
|
||||
"version": "2.0.3",
|
||||
"from": "asap@>=2.0.3 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.3.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.3",
|
||||
"from": "source-map@>=0.5.3 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.3.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"version": "5.0.19",
|
||||
"from": "postcss@>=5.0.13 <6.0.0",
|
||||
"from": "postcss@5.0.19",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-5.0.19.tgz",
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
@@ -1332,9 +1271,9 @@
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.3",
|
||||
"version": "0.5.6",
|
||||
"from": "source-map@>=0.5.1 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.3.tgz"
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz"
|
||||
},
|
||||
"js-base64": {
|
||||
"version": "2.1.9",
|
||||
@@ -1345,405 +1284,8 @@
|
||||
},
|
||||
"postcss-value-parser": {
|
||||
"version": "3.3.0",
|
||||
"from": "postcss-value-parser@>=3.2.3 <4.0.0",
|
||||
"from": "postcss-value-parser@3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz"
|
||||
},
|
||||
"querystring": {
|
||||
"version": "0.2.0",
|
||||
"from": "querystring@>=0.2.0 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz"
|
||||
},
|
||||
"request": {
|
||||
"version": "2.72.0",
|
||||
"from": "request@>=2.67.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.72.0.tgz",
|
||||
"dependencies": {
|
||||
"aws-sign2": {
|
||||
"version": "0.6.0",
|
||||
"from": "aws-sign2@>=0.6.0 <0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz"
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.3.2",
|
||||
"from": "aws4@>=1.2.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.3.2.tgz",
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "4.0.1",
|
||||
"from": "lru-cache@>=4.0.0 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz",
|
||||
"dependencies": {
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"from": "pseudomap@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz"
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.0.0",
|
||||
"from": "yallist@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.1.2",
|
||||
"from": "bl@>=1.1.2 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz",
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "2.0.6",
|
||||
"from": "readable-stream@>=2.0.5 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
|
||||
"dependencies": {
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"from": "core-util-is@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@>=2.0.1 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"from": "isarray@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.6",
|
||||
"from": "process-nextick-args@>=1.0.6 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz"
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"from": "string_decoder@>=0.10.0 <0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"from": "util-deprecate@>=1.0.1 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.11.0",
|
||||
"from": "caseless@>=0.11.0 <0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz"
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.5",
|
||||
"from": "combined-stream@>=1.0.5 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
|
||||
"dependencies": {
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"from": "delayed-stream@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.0",
|
||||
"from": "extend@>=3.0.0 <3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"from": "forever-agent@>=0.6.1 <0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz"
|
||||
},
|
||||
"form-data": {
|
||||
"version": "1.0.0-rc4",
|
||||
"from": "form-data@>=1.0.0-rc3 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc4.tgz",
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
"from": "async@>=1.5.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "2.0.6",
|
||||
"from": "har-validator@>=2.0.6 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"from": "chalk@>=1.1.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"from": "ansi-styles@>=2.2.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"from": "escape-string-regexp@>=1.0.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
|
||||
},
|
||||
"has-ansi": {
|
||||
"version": "2.0.0",
|
||||
"from": "has-ansi@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0",
|
||||
"from": "ansi-regex@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"from": "strip-ansi@>=3.0.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.0.0",
|
||||
"from": "ansi-regex@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"from": "supports-color@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.9.0",
|
||||
"from": "commander@>=2.9.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
|
||||
"dependencies": {
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1",
|
||||
"from": "graceful-readlink@>=1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-my-json-valid": {
|
||||
"version": "2.13.1",
|
||||
"from": "is-my-json-valid@>=2.12.4 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.13.1.tgz",
|
||||
"dependencies": {
|
||||
"generate-function": {
|
||||
"version": "2.0.0",
|
||||
"from": "generate-function@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz"
|
||||
},
|
||||
"generate-object-property": {
|
||||
"version": "1.2.0",
|
||||
"from": "generate-object-property@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
|
||||
"dependencies": {
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"from": "is-property@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsonpointer": {
|
||||
"version": "2.0.0",
|
||||
"from": "jsonpointer@2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz"
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.1",
|
||||
"from": "xtend@>=4.0.0 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pinkie-promise": {
|
||||
"version": "2.0.1",
|
||||
"from": "pinkie-promise@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
|
||||
"dependencies": {
|
||||
"pinkie": {
|
||||
"version": "2.0.4",
|
||||
"from": "pinkie@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"hawk": {
|
||||
"version": "3.1.3",
|
||||
"from": "hawk@>=3.1.3 <3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
|
||||
"dependencies": {
|
||||
"hoek": {
|
||||
"version": "2.16.3",
|
||||
"from": "hoek@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz"
|
||||
},
|
||||
"boom": {
|
||||
"version": "2.10.1",
|
||||
"from": "boom@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz"
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "2.0.5",
|
||||
"from": "cryptiles@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz"
|
||||
},
|
||||
"sntp": {
|
||||
"version": "1.0.9",
|
||||
"from": "sntp@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.1.1",
|
||||
"from": "http-signature@>=1.1.0 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "0.2.0",
|
||||
"from": "assert-plus@>=0.2.0 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz"
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.2.2",
|
||||
"from": "jsprim@>=1.2.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.2.2.tgz",
|
||||
"dependencies": {
|
||||
"extsprintf": {
|
||||
"version": "1.0.2",
|
||||
"from": "extsprintf@1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz"
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.2",
|
||||
"from": "json-schema@0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz"
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.3.6",
|
||||
"from": "verror@1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.7.4",
|
||||
"from": "sshpk@>=1.7.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.7.4.tgz",
|
||||
"dependencies": {
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"from": "asn1@>=0.2.3 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz"
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.13.0",
|
||||
"from": "dashdash@>=1.10.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.13.0.tgz",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"from": "assert-plus@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.0",
|
||||
"from": "jsbn@>=0.1.0 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz"
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.3",
|
||||
"from": "tweetnacl@>=0.13.0 <1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz"
|
||||
},
|
||||
"jodid25519": {
|
||||
"version": "1.0.2",
|
||||
"from": "jodid25519@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz"
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"from": "ecc-jsbn@>=0.0.1 <1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"from": "is-typedarray@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz"
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"from": "isstream@>=0.1.2 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz"
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"from": "json-stringify-safe@>=5.0.1 <5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz"
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.10",
|
||||
"from": "mime-types@>=2.1.7 <2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.10.tgz",
|
||||
"dependencies": {
|
||||
"mime-db": {
|
||||
"version": "1.22.0",
|
||||
"from": "mime-db@>=1.22.0 <1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.22.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-uuid": {
|
||||
"version": "1.4.7",
|
||||
"from": "node-uuid@>=1.4.7 <1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz"
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.1",
|
||||
"from": "oauth-sign@>=0.8.1 <0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.1.tgz"
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.1.0",
|
||||
"from": "qs@>=6.1.0 <6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.1.0.tgz"
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"from": "stringstream@>=0.0.4 <0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz"
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.2.2",
|
||||
"from": "tough-cookie@>=2.2.0 <2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz"
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.4.2",
|
||||
"from": "tunnel-agent@>=0.4.1 <0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1753,9 +1295,9 @@
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz"
|
||||
},
|
||||
"windshaft": {
|
||||
"version": "1.17.1",
|
||||
"from": "windshaft@1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/windshaft/-/windshaft-1.17.1.tgz",
|
||||
"version": "1.19.0",
|
||||
"from": "windshaft@1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/windshaft/-/windshaft-1.19.0.tgz",
|
||||
"dependencies": {
|
||||
"abaculus": {
|
||||
"version": "1.1.0-cdb4",
|
||||
@@ -1776,8 +1318,8 @@
|
||||
},
|
||||
"carto": {
|
||||
"version": "0.15.1-cdb1",
|
||||
"from": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1",
|
||||
"resolved": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb1",
|
||||
"from": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb2",
|
||||
"resolved": "https://github.com/CartoDB/carto/tarball/0.15.1-cdb2",
|
||||
"dependencies": {
|
||||
"mapnik-reference": {
|
||||
"version": "6.0.5",
|
||||
@@ -1803,11 +1345,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "3.1.2",
|
||||
"from": "es6-promise@>=3.1.2 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.1.2.tgz"
|
||||
},
|
||||
"grainstore": {
|
||||
"version": "1.1.1",
|
||||
"from": "grainstore@1.1.1",
|
||||
@@ -4631,47 +4168,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"version": "5.0.19",
|
||||
"from": "postcss@>=5.0.18 <6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-5.0.19.tgz",
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "3.1.2",
|
||||
"from": "supports-color@>=3.1.2 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
|
||||
"dependencies": {
|
||||
"has-flag": {
|
||||
"version": "1.0.0",
|
||||
"from": "has-flag@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.3",
|
||||
"from": "source-map@>=0.5.1 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.3.tgz"
|
||||
},
|
||||
"js-base64": {
|
||||
"version": "2.1.9",
|
||||
"from": "js-base64@>=2.1.9 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"postcss-each": {
|
||||
"version": "0.9.1",
|
||||
"from": "postcss-each@>=0.9.1 <0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-each/-/postcss-each-0.9.1.tgz",
|
||||
"dependencies": {
|
||||
"postcss-simple-vars": {
|
||||
"version": "1.2.0",
|
||||
"from": "postcss-simple-vars@>=1.2.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-1.2.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.0.3",
|
||||
"from": "semver@>=5.0.3 <5.1.0",
|
||||
|
||||
118
package.json
@@ -1,61 +1,61 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "windshaft-cartodb",
|
||||
"version": "2.33.0",
|
||||
"description": "A map tile server for CartoDB",
|
||||
"keywords": [
|
||||
"cartodb"
|
||||
],
|
||||
"url": "https://github.com/CartoDB/Windshaft-cartodb",
|
||||
"license": "BSD-3-Clause",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/CartoDB/Windshaft-cartodb.git"
|
||||
},
|
||||
"author": "Vizzuality <contact@vizzuality.com> (http://vizzuality.com)",
|
||||
"contributors": [
|
||||
"Simon Tokumine <simon@vizzuality.com>",
|
||||
"Javi Santana <jsantana@vizzuality.com>",
|
||||
"Sandro Santilli <strk@vizzuality.com>"
|
||||
],
|
||||
"dependencies": {
|
||||
"express": "~4.13.3",
|
||||
"body-parser": "~1.14.0",
|
||||
"debug": "~2.2.0",
|
||||
"step-profiler": "~0.2.1",
|
||||
"node-statsd": "~0.0.7",
|
||||
"underscore" : "~1.6.0",
|
||||
"dot": "~1.0.2",
|
||||
"windshaft": "1.17.1",
|
||||
"step": "~0.0.6",
|
||||
"queue-async": "~1.0.7",
|
||||
"request": "~2.62.0",
|
||||
"cartodb-redis": "~0.13.0",
|
||||
"cartodb-psql": "~0.6.1",
|
||||
"camshaft": "0.5.0",
|
||||
"fastly-purge": "~1.0.1",
|
||||
"redis-mpool": "~0.4.0",
|
||||
"lru-cache": "2.6.5",
|
||||
"lzma": "~1.3.7",
|
||||
"log4js": "https://github.com/CartoDB/log4js-node/tarball/cdb",
|
||||
"cartodb-query-tables": "~0.1.0",
|
||||
"turbo-cartocss": "0.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "~0.3.6",
|
||||
"mocha": "~1.21.4",
|
||||
"nock": "~2.11.0",
|
||||
"jshint": "~2.6.0",
|
||||
"redis": "~0.8.6",
|
||||
"strftime": "~0.8.2",
|
||||
"semver": "~1.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "make pre-install",
|
||||
"test": "make test-all"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8 <0.11",
|
||||
"npm": ">=2.14.16"
|
||||
}
|
||||
"private": true,
|
||||
"name": "windshaft-cartodb",
|
||||
"version": "2.40.0",
|
||||
"description": "A map tile server for CartoDB",
|
||||
"keywords": [
|
||||
"cartodb"
|
||||
],
|
||||
"url": "https://github.com/CartoDB/Windshaft-cartodb",
|
||||
"license": "BSD-3-Clause",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/CartoDB/Windshaft-cartodb.git"
|
||||
},
|
||||
"author": "Vizzuality <contact@vizzuality.com> (http://vizzuality.com)",
|
||||
"contributors": [
|
||||
"Simon Tokumine <simon@vizzuality.com>",
|
||||
"Javi Santana <jsantana@vizzuality.com>",
|
||||
"Sandro Santilli <strk@vizzuality.com>"
|
||||
],
|
||||
"dependencies": {
|
||||
"body-parser": "~1.14.0",
|
||||
"camshaft": "0.6.0",
|
||||
"cartodb-psql": "~0.6.1",
|
||||
"cartodb-query-tables": "~0.1.0",
|
||||
"cartodb-redis": "~0.13.0",
|
||||
"debug": "~2.2.0",
|
||||
"dot": "~1.0.2",
|
||||
"express": "~4.13.3",
|
||||
"fastly-purge": "~1.0.1",
|
||||
"log4js": "https://github.com/CartoDB/log4js-node/tarball/cdb",
|
||||
"lru-cache": "2.6.5",
|
||||
"lzma": "~1.3.7",
|
||||
"node-statsd": "~0.0.7",
|
||||
"queue-async": "~1.0.7",
|
||||
"redis-mpool": "~0.4.0",
|
||||
"request": "~2.62.0",
|
||||
"step": "~0.0.6",
|
||||
"step-profiler": "~0.3.0",
|
||||
"turbo-carto": "0.7.1",
|
||||
"underscore": "~1.6.0",
|
||||
"windshaft": "1.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"istanbul": "~0.4.3",
|
||||
"jshint": "~2.6.0",
|
||||
"mocha": "~1.21.4",
|
||||
"nock": "~2.11.0",
|
||||
"redis": "~0.8.6",
|
||||
"semver": "~1.1.4",
|
||||
"strftime": "~0.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"preinstall": "make pre-install",
|
||||
"test": "make test-all"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8 <0.11",
|
||||
"npm": ">=2.14.16"
|
||||
}
|
||||
}
|
||||
|
||||
81
test/acceptance/analysis/analysis-layers-geojson.js
Normal file
@@ -0,0 +1,81 @@
|
||||
require('../../support/test_helper');
|
||||
|
||||
var assert = require('../../support/assert');
|
||||
var TestClient = require('../../support/test-client');
|
||||
|
||||
describe('analysis-layers-dataviews-geojson', function() {
|
||||
|
||||
function createMapConfig(layers, dataviews, analysis) {
|
||||
return {
|
||||
version: '1.5.0',
|
||||
layers: layers,
|
||||
dataviews: dataviews || {},
|
||||
analyses: analysis || []
|
||||
};
|
||||
}
|
||||
|
||||
var CARTOCSS = [
|
||||
"#points {",
|
||||
" marker-fill-opacity: 1.0;",
|
||||
" marker-line-color: #FFF;",
|
||||
" marker-line-width: 0.5;",
|
||||
" marker-line-opacity: 1.0;",
|
||||
" marker-placement: point;",
|
||||
" marker-type: ellipse;",
|
||||
" marker-width: 8;",
|
||||
" marker-fill: red;",
|
||||
" marker-allow-overlap: true;",
|
||||
"}"
|
||||
].join('\n');
|
||||
|
||||
var mapConfig = createMapConfig(
|
||||
[
|
||||
{
|
||||
"type": "cartodb",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "2570e105-7b37-40d2-bdf4-1af889598745"
|
||||
},
|
||||
"cartocss": CARTOCSS,
|
||||
"cartocss_version": "2.3.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
{
|
||||
pop_max_histogram: {
|
||||
source: {
|
||||
id: '2570e105-7b37-40d2-bdf4-1af889598745'
|
||||
},
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'pop_max'
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
"id": "2570e105-7b37-40d2-bdf4-1af889598745",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from populated_places_simple_reduced"
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
it('should get pop_max column from dataview', function(done) {
|
||||
var testClient = new TestClient(mapConfig, 1234);
|
||||
|
||||
testClient.getTile(0, 0, 0, {format: 'geojson', layers: 0}, function(err, res, geojson) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
assert.ok(Array.isArray(geojson.features));
|
||||
assert.ok(geojson.features.length > 0);
|
||||
var feature = geojson.features[0];
|
||||
assert.ok(feature.properties.hasOwnProperty('pop_max'), 'Missing pop_max property');
|
||||
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -3,6 +3,7 @@ require('../../support/test_helper');
|
||||
var assert = require('../../support/assert');
|
||||
var TestClient = require('../../support/test-client');
|
||||
var dot = require('dot');
|
||||
var debug = require('debug')('windshaft:cartodb:test');
|
||||
|
||||
describe('analysis-layers use cases', function() {
|
||||
|
||||
@@ -649,7 +650,7 @@ describe('analysis-layers use cases', function() {
|
||||
|
||||
useCases.forEach(function(useCase, imageIdx) {
|
||||
if (!!useCase.skip) {
|
||||
console.log(JSON.stringify(useCase.mapConfig, null, 4));
|
||||
debug(JSON.stringify(useCase.mapConfig, null, 4));
|
||||
}
|
||||
it.skip('should implement use case: "' + useCase.desc + '"', function(done) {
|
||||
|
||||
|
||||
@@ -184,4 +184,187 @@ describe('analysis-layers', function() {
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should retrieve enough metadata about analyses', function(done) {
|
||||
var useCase = useCases[1];
|
||||
|
||||
// No API key here
|
||||
var testClient = new TestClient(useCase.mapConfig, 1234);
|
||||
|
||||
testClient.getLayergroup(function(err, layergroupResult) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
assert.ok(
|
||||
Array.isArray(layergroupResult.metadata.analyses),
|
||||
'Missing "analyses" array metadata from: ' + JSON.stringify(layergroupResult)
|
||||
);
|
||||
var analyses = layergroupResult.metadata.analyses;
|
||||
assert.equal(analyses.length, 1, 'Invalid number of analyses in metadata');
|
||||
var nodes = analyses[0].nodes;
|
||||
var nodesIds = Object.keys(nodes);
|
||||
assert.deepEqual(nodesIds, ['2570e105-7b37-40d2-bdf4-1af889598745', 'HEAD']);
|
||||
nodesIds.forEach(function(nodeId) {
|
||||
var node = nodes[nodeId];
|
||||
assert.ok(node.hasOwnProperty('url'), 'Missing "url" attribute in node');
|
||||
assert.ok(node.hasOwnProperty('status'), 'Missing "status" attribute in node');
|
||||
assert.ok(node.hasOwnProperty('query'), 'Missing "status" attribute in node');
|
||||
});
|
||||
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have analysis metadata when dataviews point to source node', function(done) {
|
||||
var useCase = {
|
||||
desc: 'basic source-id mapnik layer',
|
||||
fixture: 'basic-source-id-mapnik-layer.png',
|
||||
mapConfig: mapConfig(
|
||||
[
|
||||
{
|
||||
"type": "cartodb",
|
||||
"options": {
|
||||
"sql": "select * from populated_places_simple_reduced",
|
||||
"cartocss": DEFAULT_MULTITYPE_STYLE,
|
||||
"cartocss_version": "2.3.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "cartodb",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "2570e105-7b37-40d2-bdf4-1af889598745"
|
||||
},
|
||||
"cartocss": DEFAULT_MULTITYPE_STYLE,
|
||||
"cartocss_version": "2.3.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "cartodb",
|
||||
"options": {
|
||||
"sql": "select * from populated_places_simple_reduced",
|
||||
"cartocss": DEFAULT_MULTITYPE_STYLE,
|
||||
"cartocss_version": "2.3.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
{
|
||||
pop_max_histogram: {
|
||||
source: {
|
||||
id: '2570e105-7b37-40d2-bdf4-1af889598745'
|
||||
},
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'pop_max'
|
||||
}
|
||||
},
|
||||
scalerank_histogram: {
|
||||
source: {
|
||||
id: '2570e105-7b37-40d2-bdf4-1af889598745'
|
||||
},
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'scalerank'
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
{
|
||||
"id": "2570e105-7b37-40d2-bdf4-1af889598745",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from populated_places_simple_reduced"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
};
|
||||
|
||||
var testClient = new TestClient(useCase.mapConfig, 1234);
|
||||
|
||||
testClient.getLayergroup(function(err, layergroupResult) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
assert.ok(
|
||||
Array.isArray(layergroupResult.metadata.analyses),
|
||||
'Missing "analyses" array metadata from: ' + JSON.stringify(layergroupResult)
|
||||
);
|
||||
var analyses = layergroupResult.metadata.analyses;
|
||||
assert.equal(analyses.length, 1, 'Invalid number of analyses in metadata');
|
||||
var nodes = analyses[0].nodes;
|
||||
|
||||
var nodesIds = Object.keys(nodes);
|
||||
assert.deepEqual(nodesIds, ['2570e105-7b37-40d2-bdf4-1af889598745']);
|
||||
nodesIds.forEach(function(nodeId) {
|
||||
var node = nodes[nodeId];
|
||||
assert.ok(node.hasOwnProperty('url'), 'Missing "url" attribute in node');
|
||||
assert.ok(node.hasOwnProperty('status'), 'Missing "status" attribute in node');
|
||||
assert.ok(node.hasOwnProperty('query'), 'Missing "status" attribute in node');
|
||||
});
|
||||
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should response with custom cache headers for node status endpoints', function(done) {
|
||||
var useCase = useCases[1];
|
||||
|
||||
// No API key here
|
||||
var testClient = new TestClient(useCase.mapConfig, 1234);
|
||||
|
||||
testClient.getNodeStatus('HEAD', function(err, response, nodeStatus) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
assert.equal(nodeStatus.status, 'ready');
|
||||
|
||||
var headers = response.headers;
|
||||
|
||||
assert.equal(headers['cache-control'], 'public,max-age=5');
|
||||
|
||||
var lastModified = new Date(headers['last-modified']);
|
||||
var tenSecondsInMs = 1e5;
|
||||
assert.ok(Date.now() - lastModified.getTime() < tenSecondsInMs);
|
||||
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('should wrap queries from analyses', function(done) {
|
||||
var testClient = new TestClient(mapConfig(
|
||||
[
|
||||
{
|
||||
"type": "cartodb",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "2570e105-7b37-40d2-bdf4-1af889598745"
|
||||
},
|
||||
"sql_wrap": "SELECT * FROM (<%= sql %>) __wrapped WHERE adm0cap = 1",
|
||||
"cartocss": DEFAULT_MULTITYPE_STYLE,
|
||||
"cartocss_version": "2.3.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
{},
|
||||
[
|
||||
{
|
||||
"id": "2570e105-7b37-40d2-bdf4-1af889598745",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from populated_places_simple_reduced"
|
||||
}
|
||||
}
|
||||
]
|
||||
), 1234);
|
||||
|
||||
var tile = TILE_ANALYSIS_TABLES;
|
||||
testClient.getTile(tile.z, tile.x, tile.y, function(err, res, image) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
var fixturePath = './test/fixtures/analysis/adm0cap-source-id-mapnik-layer.png';
|
||||
assert.imageIsSimilarToFile(image, fixturePath, IMAGE_TOLERANCE_PER_MIL, function(err) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
67
test/acceptance/analysis/error-cases.js
Normal file
@@ -0,0 +1,67 @@
|
||||
require('../../support/test_helper');
|
||||
|
||||
var assert = require('../../support/assert');
|
||||
var TestClient = require('../../support/test-client');
|
||||
|
||||
describe('analysis-layers error cases', function() {
|
||||
function createMapConfig(layers, dataviews, analysis) {
|
||||
return {
|
||||
version: '1.5.0',
|
||||
layers: layers,
|
||||
dataviews: dataviews || {},
|
||||
analyses: analysis || []
|
||||
};
|
||||
}
|
||||
|
||||
var ERROR_RESPONSE = {
|
||||
status: 400,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
}
|
||||
};
|
||||
|
||||
it('should handle missing analysis nodes for layers', function(done) {
|
||||
var mapConfig = createMapConfig(
|
||||
[
|
||||
{
|
||||
"type": "cartodb",
|
||||
"options": {
|
||||
"source": {
|
||||
"id": "INVALID-SOURCE-ID"
|
||||
},
|
||||
"cartocss": '#polygons { polygon-fill: red; }',
|
||||
"cartocss_version": "2.3.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
{},
|
||||
[
|
||||
{
|
||||
"id": "HEAD",
|
||||
"type": "buffer",
|
||||
"params": {
|
||||
"source": {
|
||||
"id": "2570e105-7b37-40d2-bdf4-1af889598745",
|
||||
"type": "source",
|
||||
"params": {
|
||||
"query": "select * from populated_places_simple_reduced"
|
||||
}
|
||||
},
|
||||
"radius": 50000
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
var testClient = new TestClient(mapConfig, 1234);
|
||||
|
||||
testClient.getLayergroup(ERROR_RESPONSE, function(err, layergroupResult) {
|
||||
assert.ok(!err, err);
|
||||
|
||||
assert.equal(layergroupResult.errors.length, 1);
|
||||
assert.equal(layergroupResult.errors[0], 'Missing analysis node.id="INVALID-SOURCE-ID" for layer=0');
|
||||
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -40,6 +40,17 @@ describe('named-maps analysis', function() {
|
||||
}
|
||||
}
|
||||
],
|
||||
dataviews: {
|
||||
pop_max_histogram: {
|
||||
source: {
|
||||
id: 'HEAD'
|
||||
},
|
||||
type: 'histogram',
|
||||
options: {
|
||||
column: 'pop_max'
|
||||
}
|
||||
}
|
||||
},
|
||||
analyses: [
|
||||
{
|
||||
"id": "HEAD",
|
||||
@@ -115,6 +126,22 @@ describe('named-maps analysis', function() {
|
||||
assert.ok(layergroup.hasOwnProperty('layergroupid'), "Missing 'layergroupid' from: " + res.body);
|
||||
layergroupid = layergroup.layergroupid;
|
||||
|
||||
assert.ok(
|
||||
Array.isArray(layergroup.metadata.analyses),
|
||||
'Missing "analyses" array metadata from: ' + res.body
|
||||
);
|
||||
var analyses = layergroup.metadata.analyses;
|
||||
assert.equal(analyses.length, 1, 'Invalid number of analyses in metadata');
|
||||
var nodes = analyses[0].nodes;
|
||||
var nodesIds = Object.keys(nodes);
|
||||
assert.deepEqual(nodesIds, ['2570e105-7b37-40d2-bdf4-1af889598745', 'HEAD']);
|
||||
nodesIds.forEach(function(nodeId) {
|
||||
var node = nodes[nodeId];
|
||||
assert.ok(node.hasOwnProperty('url'), 'Missing "url" attribute in node');
|
||||
assert.ok(node.hasOwnProperty('status'), 'Missing "status" attribute in node');
|
||||
assert.ok(!node.hasOwnProperty('query'), 'Unexpected "query" attribute in node');
|
||||
});
|
||||
|
||||
keysToDelete['map_cfg|' + LayergroupToken.parse(layergroup.layergroupid).token] = 0;
|
||||
keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
|
||||
@@ -185,4 +212,34 @@ describe('named-maps analysis', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('should be able to retrieve dataviews from analysis', function(done) {
|
||||
assert.response(
|
||||
server,
|
||||
{
|
||||
url: '/api/v1/map/' + layergroupid + '/dataview/pop_max_histogram',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: username
|
||||
}
|
||||
},
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
}
|
||||
},
|
||||
function(res, err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var dataview = JSON.parse(res.body);
|
||||
assert.equal(dataview.type, 'histogram');
|
||||
assert.equal(dataview.bins_start, 0);
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
var qs = require('querystring');
|
||||
var testHelper = require('../support/test_helper');
|
||||
var RedisPool = require('redis-mpool');
|
||||
|
||||
@@ -53,10 +54,18 @@ describe('named maps static view', function() {
|
||||
templateMaps.delTemplate(username, templateName, done);
|
||||
});
|
||||
|
||||
function getStaticMap(callback) {
|
||||
function getStaticMap(params, callback) {
|
||||
if (!callback) {
|
||||
callback = params;
|
||||
params = null;
|
||||
}
|
||||
|
||||
var url = '/api/v1/map/static/named/' + templateName + '/640/480.png';
|
||||
|
||||
if (params !== null) {
|
||||
url += '?' + qs.stringify(params);
|
||||
}
|
||||
|
||||
var requestOptions = {
|
||||
url: url,
|
||||
method: 'GET',
|
||||
@@ -163,4 +172,30 @@ describe('named maps static view', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return override zoom', function (done) {
|
||||
var view = {
|
||||
bounds: {
|
||||
west: 0,
|
||||
south: 0,
|
||||
east: 45,
|
||||
north: 45
|
||||
},
|
||||
zoom: 4,
|
||||
center: {
|
||||
lng: 40,
|
||||
lat: 20
|
||||
}
|
||||
};
|
||||
templateMaps.addTemplate(username, createTemplate(view), function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
getStaticMap({ zoom: 3 }, function(err, img) {
|
||||
assert.ok(!err);
|
||||
img.save('/tmp/static.png');
|
||||
assert.imageIsSimilarToFile(img, previewFixture('override-zoom'), IMAGE_TOLERANCE, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -48,63 +48,64 @@ describe('overviews metadata', function() {
|
||||
|
||||
it("layers with and without overviews", function(done) {
|
||||
|
||||
var layergroup = {
|
||||
version: '1.0.0',
|
||||
layers: [overviews_layer, non_overviews_layer]
|
||||
};
|
||||
var layergroup = {
|
||||
version: '1.0.0',
|
||||
layers: [overviews_layer, non_overviews_layer]
|
||||
};
|
||||
|
||||
var layergroup_url = '/api/v1/map';
|
||||
var layergroup_url = '/api/v1/map';
|
||||
|
||||
var expected_token;
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(layergroup)
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
assert.equal(res.headers['x-layergroup-id'], parsedBody.layergroupid);
|
||||
expected_token = parsedBody.layergroupid;
|
||||
next(null, res);
|
||||
});
|
||||
},
|
||||
function do_get_mapconfig(err)
|
||||
{
|
||||
assert.ifError(err);
|
||||
var next = this;
|
||||
var expected_token;
|
||||
step(
|
||||
function do_post()
|
||||
{
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: layergroup_url,
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(layergroup)
|
||||
}, {}, function(res) {
|
||||
assert.equal(res.statusCode, 200, res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
assert.equal(res.headers['x-layergroup-id'], parsedBody.layergroupid);
|
||||
expected_token = parsedBody.layergroupid;
|
||||
next(null, res);
|
||||
});
|
||||
},
|
||||
function do_get_mapconfig(err)
|
||||
{
|
||||
assert.ifError(err);
|
||||
var next = this;
|
||||
|
||||
var mapStore = new windshaft.storage.MapStore({
|
||||
pool: redisPool,
|
||||
expire_time: 500000
|
||||
});
|
||||
mapStore.load(LayergroupToken.parse(expected_token).token, function(err, mapConfig) {
|
||||
assert.ifError(err);
|
||||
assert.deepEqual(non_overviews_layer, mapConfig._cfg.layers[1]);
|
||||
assert.equal(mapConfig._cfg.layers[0].type, 'cartodb');
|
||||
assert.ok(mapConfig._cfg.layers[0].options.query_rewrite_data);
|
||||
var expected_data = {
|
||||
overviews: {
|
||||
test_table_overviews: {
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(mapConfig._cfg.layers[0].options.query_rewrite_data, expected_data);
|
||||
});
|
||||
var mapStore = new windshaft.storage.MapStore({
|
||||
pool: redisPool,
|
||||
expire_time: 500000
|
||||
});
|
||||
mapStore.load(LayergroupToken.parse(expected_token).token, function(err, mapConfig) {
|
||||
assert.ifError(err);
|
||||
assert.deepEqual(non_overviews_layer, mapConfig._cfg.layers[1]);
|
||||
assert.equal(mapConfig._cfg.layers[0].type, 'cartodb');
|
||||
assert.ok(mapConfig._cfg.layers[0].options.query_rewrite_data);
|
||||
var expected_data = {
|
||||
overviews: {
|
||||
test_table_overviews: {
|
||||
schema: 'public',
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(mapConfig._cfg.layers[0].options.query_rewrite_data, expected_data);
|
||||
});
|
||||
|
||||
next(err);
|
||||
},
|
||||
function finish(err) {
|
||||
keysToDelete['map_cfg|' + LayergroupToken.parse(expected_token).token] = 0;
|
||||
keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
done(err);
|
||||
}
|
||||
);
|
||||
next(err);
|
||||
},
|
||||
function finish(err) {
|
||||
keysToDelete['map_cfg|' + LayergroupToken.parse(expected_token).token] = 0;
|
||||
keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
done(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,116 +59,117 @@ describe('overviews metadata for named maps', function() {
|
||||
};
|
||||
|
||||
it("should add overviews data to layers", function(done) {
|
||||
step(
|
||||
function postTemplate()
|
||||
{
|
||||
var next = this;
|
||||
step(
|
||||
function postTemplate()
|
||||
{
|
||||
var next = this;
|
||||
|
||||
assert.response(server, {
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template)
|
||||
}, {}, function(res, err) {
|
||||
next(err, res);
|
||||
});
|
||||
},
|
||||
function checkTemplate(err, res) {
|
||||
assert.ifError(err);
|
||||
assert.response(server, {
|
||||
url: '/api/v1/map/named?api_key=1234',
|
||||
method: 'POST',
|
||||
headers: {host: 'localhost', 'Content-Type': 'application/json' },
|
||||
data: JSON.stringify(template)
|
||||
}, {}, function(res, err) {
|
||||
next(err, res);
|
||||
});
|
||||
},
|
||||
function checkTemplate(err, res) {
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
assert.equal(res.statusCode, 200);
|
||||
assert.deepEqual(JSON.parse(res.body), {
|
||||
template_id: templateId
|
||||
});
|
||||
next(null);
|
||||
},
|
||||
function instantiateTemplate(err) {
|
||||
assert.ifError(err);
|
||||
var next = this;
|
||||
assert.equal(res.statusCode, 200);
|
||||
assert.deepEqual(JSON.parse(res.body), {
|
||||
template_id: templateId
|
||||
});
|
||||
next(null);
|
||||
},
|
||||
function instantiateTemplate(err) {
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: '/api/v1/map/named/' + templateId,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}, {},
|
||||
function(res, err) {
|
||||
return next(err, res);
|
||||
});
|
||||
var next = this;
|
||||
assert.response(server, {
|
||||
url: '/api/v1/map/named/' + templateId,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}, {},
|
||||
function(res, err) {
|
||||
return next(err, res);
|
||||
});
|
||||
|
||||
},
|
||||
function checkInstanciation(err, res) {
|
||||
assert.ifError(err);
|
||||
},
|
||||
function checkInstanciation(err, res) {
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
var next = this;
|
||||
|
||||
assert.equal(res.statusCode, 200);
|
||||
assert.equal(res.statusCode, 200);
|
||||
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
|
||||
keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
|
||||
keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
keysToDelete['map_cfg|' + LayergroupToken.parse(parsedBody.layergroupid).token] = 0;
|
||||
keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
|
||||
assert.ok(parsedBody.layergroupid);
|
||||
assert.ok(parsedBody.last_updated);
|
||||
assert.ok(parsedBody.layergroupid);
|
||||
assert.ok(parsedBody.last_updated);
|
||||
|
||||
next(null, parsedBody.layergroupid);
|
||||
},
|
||||
next(null, parsedBody.layergroupid);
|
||||
},
|
||||
|
||||
function checkMapconfig(err, layergroupId)
|
||||
{
|
||||
assert.ifError(err);
|
||||
function checkMapconfig(err, layergroupId)
|
||||
{
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
var next = this;
|
||||
|
||||
var mapStore = new windshaft.storage.MapStore({
|
||||
pool: redisPool,
|
||||
expire_time: 500000
|
||||
});
|
||||
mapStore.load(LayergroupToken.parse(layergroupId).token, function(err, mapConfig) {
|
||||
assert.ifError(err);
|
||||
assert.deepEqual(non_overviews_layer, mapConfig._cfg.layers[1]);
|
||||
assert.equal(mapConfig._cfg.layers[0].type, 'cartodb');
|
||||
assert.ok(mapConfig._cfg.layers[0].options.query_rewrite_data);
|
||||
var expected_data = {
|
||||
overviews: {
|
||||
test_table_overviews: {
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(mapConfig._cfg.layers[0].options.query_rewrite_data, expected_data);
|
||||
});
|
||||
var mapStore = new windshaft.storage.MapStore({
|
||||
pool: redisPool,
|
||||
expire_time: 500000
|
||||
});
|
||||
mapStore.load(LayergroupToken.parse(layergroupId).token, function(err, mapConfig) {
|
||||
assert.ifError(err);
|
||||
assert.deepEqual(non_overviews_layer, mapConfig._cfg.layers[1]);
|
||||
assert.equal(mapConfig._cfg.layers[0].type, 'cartodb');
|
||||
assert.ok(mapConfig._cfg.layers[0].options.query_rewrite_data);
|
||||
var expected_data = {
|
||||
overviews: {
|
||||
test_table_overviews: {
|
||||
schema: 'public',
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(mapConfig._cfg.layers[0].options.query_rewrite_data, expected_data);
|
||||
});
|
||||
|
||||
next(err);
|
||||
},
|
||||
function deleteTemplate(err) {
|
||||
assert.ifError(err);
|
||||
next(err);
|
||||
},
|
||||
function deleteTemplate(err) {
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
var next = this;
|
||||
|
||||
assert.response(server, {
|
||||
url: '/api/v1/map/named/' + templateId + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: { host: 'localhost' }
|
||||
}, {}, function (res, err) {
|
||||
next(err, res);
|
||||
});
|
||||
},
|
||||
function checkDeleteTemplate(err, res) {
|
||||
assert.ifError(err);
|
||||
assert.equal(res.statusCode, 204);
|
||||
assert.ok(!res.body);
|
||||
assert.response(server, {
|
||||
url: '/api/v1/map/named/' + templateId + '?api_key=1234',
|
||||
method: 'DELETE',
|
||||
headers: { host: 'localhost' }
|
||||
}, {}, function (res, err) {
|
||||
next(err, res);
|
||||
});
|
||||
},
|
||||
function checkDeleteTemplate(err, res) {
|
||||
assert.ifError(err);
|
||||
assert.equal(res.statusCode, 204);
|
||||
assert.ok(!res.body);
|
||||
|
||||
return null;
|
||||
},
|
||||
function finish(err) {
|
||||
done(err);
|
||||
}
|
||||
);
|
||||
return null;
|
||||
},
|
||||
function finish(err) {
|
||||
done(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var assert = require('../support/assert');
|
||||
var TestClient = require('../support/test-client');
|
||||
var assert = require('../../support/assert');
|
||||
var TestClient = require('../../support/test-client');
|
||||
|
||||
var IMAGE_TOLERANCE_PER_MIL = 20;
|
||||
|
||||
@@ -38,7 +38,7 @@ function makeMapconfig(cartocss) {
|
||||
};
|
||||
}
|
||||
|
||||
describe('turbo-cartocss for anonymous maps', function() {
|
||||
describe('turbo-carto for anonymous maps', function() {
|
||||
describe('parsing ramp function with colorbrewer for greens and mapnik renderer', function () {
|
||||
beforeEach(function () {
|
||||
var turboCartocss = '#layer { marker-fill: ramp([price], colorbrewer(Greens)); }';
|
||||
@@ -49,8 +49,8 @@ describe('turbo-cartocss for anonymous maps', function() {
|
||||
this.testClient.drain(done);
|
||||
});
|
||||
|
||||
it('should get a tile with turbo-cartocss parsed properly', function (done) {
|
||||
var fixturePath = 'test_turbo_cartocss_greens_13_4011_3088.png';
|
||||
it('should get a tile with turbo-carto parsed properly', function (done) {
|
||||
var fixturePath = 'test_turbo_carto_greens_13_4011_3088.png';
|
||||
this.testClient.getTile(13, 4011, 3088, imageCompareFn(fixturePath, done));
|
||||
});
|
||||
});
|
||||
@@ -65,8 +65,8 @@ describe('turbo-cartocss for anonymous maps', function() {
|
||||
this.testClient.drain(done);
|
||||
});
|
||||
|
||||
it('should get a tile with turbo-cartocss parsed properly', function (done) {
|
||||
var fixtureFileName = 'test_turbo_cartocss_reds_13_4011_3088.png';
|
||||
it('should get a tile with turbo-carto parsed properly', function (done) {
|
||||
var fixtureFileName = 'test_turbo_carto_reds_13_4011_3088.png';
|
||||
this.testClient.getTile(13, 4011, 3088, imageCompareFn(fixtureFileName, done));
|
||||
});
|
||||
});
|
||||
@@ -115,12 +115,12 @@ describe('turbo-cartocss for anonymous maps', function() {
|
||||
this.testClient.drain(done);
|
||||
});
|
||||
|
||||
it('should get a tile with turbo-cartocss parsed properly', function (done) {
|
||||
it('should get a tile with turbo-carto parsed properly', function (done) {
|
||||
var z = 2;
|
||||
var x = 2;
|
||||
var y = 1;
|
||||
|
||||
var pngFixture = 'torque/populated_places_simple_reduced-turbo-cartocss-' + [z, x, y].join('.') + '.png';
|
||||
var pngFixture = 'torque/populated_places_simple_reduced-turbo-carto-' + [z, x, y].join('.') + '.png';
|
||||
|
||||
this.testClient.getTile(z, x, y, { layers: 0, format: 'torque.png' }, imageCompareFn(pngFixture, done));
|
||||
});
|
||||
@@ -1,14 +1,14 @@
|
||||
var assert = require('../support/assert');
|
||||
var assert = require('../../support/assert');
|
||||
var step = require('step');
|
||||
var LayergroupToken = require('../../lib/cartodb/models/layergroup_token');
|
||||
var testHelper = require(__dirname + '/../support/test_helper');
|
||||
var CartodbWindshaft = require(__dirname + '/../../lib/cartodb/server');
|
||||
var serverOptions = require(__dirname + '/../../lib/cartodb/server_options');
|
||||
var LayergroupToken = require('../../../lib/cartodb/models/layergroup_token');
|
||||
var testHelper = require('../../support/test_helper');
|
||||
var CartodbWindshaft = require('../../../lib/cartodb/server');
|
||||
var serverOptions = require('../../../lib/cartodb/server_options');
|
||||
var server = new CartodbWindshaft(serverOptions);
|
||||
var mapnik = require('windshaft').mapnik;
|
||||
var IMAGE_TOLERANCE_PER_MIL = 10;
|
||||
|
||||
describe('turbo-cartocss for named maps', function() {
|
||||
describe('turbo-carto for named maps', function() {
|
||||
|
||||
var keysToDelete;
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('turbo-cartocss for named maps', function() {
|
||||
testHelper.deleteRedisKeys(keysToDelete, done);
|
||||
});
|
||||
|
||||
var templateId = 'turbo-cartocss-template-1';
|
||||
var templateId = 'turbo-carto-template-1';
|
||||
|
||||
var template = {
|
||||
version: '0.0.1',
|
||||
@@ -65,7 +65,7 @@ describe('turbo-cartocss for named maps', function() {
|
||||
var templateParamsReds = { color: 'Reds' };
|
||||
var templateParamsBlues = { color: 'Blues' };
|
||||
|
||||
it('should create a template with turbo-cartocss parsed properly', function (done) {
|
||||
it('should create a template with turbo-carto parsed properly', function (done) {
|
||||
step(
|
||||
function postTemplate() {
|
||||
var next = this;
|
||||
@@ -144,7 +144,7 @@ describe('turbo-cartocss for named maps', function() {
|
||||
assert.equal(res.statusCode, 200);
|
||||
assert.equal(res.headers['content-type'], 'image/png');
|
||||
|
||||
var fixturePath = './test/fixtures/turbo-cartocss-named-maps-reds.png';
|
||||
var fixturePath = './test/fixtures/turbo-carto-named-maps-reds.png';
|
||||
var image = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
|
||||
|
||||
assert.imageIsSimilarToFile(image, fixturePath, IMAGE_TOLERANCE_PER_MIL, next);
|
||||
@@ -203,7 +203,7 @@ describe('turbo-cartocss for named maps', function() {
|
||||
assert.equal(res.statusCode, 200);
|
||||
assert.equal(res.headers['content-type'], 'image/png');
|
||||
|
||||
var fixturePath = './test/fixtures/turbo-cartocss-named-maps-blues.png';
|
||||
var fixturePath = './test/fixtures/turbo-carto-named-maps-blues.png';
|
||||
var image = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
|
||||
|
||||
assert.imageIsSimilarToFile(image, fixturePath, IMAGE_TOLERANCE_PER_MIL, next);
|
||||
@@ -1,7 +1,7 @@
|
||||
require('../support/test_helper');
|
||||
require('../../support/test_helper');
|
||||
|
||||
var assert = require('../support/assert');
|
||||
var TestClient = require('../support/test-client');
|
||||
var assert = require('../../support/assert');
|
||||
var TestClient = require('../../support/test-client');
|
||||
|
||||
function makeMapconfig(cartocss) {
|
||||
return {
|
||||
@@ -31,7 +31,7 @@ function makeMapconfig(cartocss) {
|
||||
};
|
||||
}
|
||||
|
||||
describe('turbo-cartocss regressions', function() {
|
||||
describe('turbo-carto regressions', function() {
|
||||
|
||||
var cartocss = [
|
||||
"/** simple visualization */",
|
||||
@@ -114,6 +114,34 @@ describe('histogram widgets', function() {
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
|
||||
it("should expose a filtered histogram using dataviews for filtering", function(done) {
|
||||
var params = {
|
||||
filters: {
|
||||
dataviews: {
|
||||
country_places_histogram: { min: 4000000 }
|
||||
}
|
||||
}
|
||||
};
|
||||
var testClient = new TestClient(histogramMapConfig);
|
||||
testClient.getWidget('country_places_histogram', params, function(err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var histogram = JSON.parse(res.body);
|
||||
// notice min value
|
||||
assert.deepEqual(histogram.bins[0], {
|
||||
bin: 0,
|
||||
freq: 62,
|
||||
min: 4000000,
|
||||
max: 9276403,
|
||||
avg: 5815009.596774193
|
||||
});
|
||||
|
||||
testClient.drain(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ describe('named-maps widgets', function() {
|
||||
}
|
||||
);
|
||||
},
|
||||
function fetchTile(err, res) {
|
||||
function finish(err, res) {
|
||||
assert.ifError(err);
|
||||
|
||||
layergroup = JSON.parse(res.body);
|
||||
|
||||
BIN
test/fixtures/analysis/adm0cap-source-id-mapnik-layer.png
vendored
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
test/fixtures/previews/populated_places_simple_reduced-override-zoom.png
vendored
Normal file
|
After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 356 B After Width: | Height: | Size: 356 B |
|
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 349 B |
@@ -73,12 +73,13 @@ describe('MapConfigOverviewsAdapter', function() {
|
||||
assert.equal(layers[0].options.cartocss_version, cartocss_version);
|
||||
assert.ok(layers[0].options.query_rewrite_data);
|
||||
var expected_data = {
|
||||
overviews: {
|
||||
test_table_overviews: {
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
overviews: {
|
||||
test_table_overviews: {
|
||||
schema: 'public',
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
assert.deepEqual(layers[0].options.query_rewrite_data, expected_data);
|
||||
done();
|
||||
|
||||
@@ -40,8 +40,9 @@ describe('OverviewsMetadataApi', function() {
|
||||
|
||||
assert.deepEqual(result, {
|
||||
'test_table_overviews': {
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
schema: 'public',
|
||||
1: { table: '_vovw_1_test_table_overviews' },
|
||||
2: { table: '_vovw_2_test_table_overviews' }
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
var qs = require('querystring');
|
||||
var step = require('step');
|
||||
var urlParser = require('url');
|
||||
|
||||
var mapnik = require('windshaft').mapnik;
|
||||
|
||||
@@ -313,13 +314,15 @@ TestClient.prototype.getTile = function(z, x, y, params, callback) {
|
||||
assert.response(server, request, expectedResponse, function(res, err) {
|
||||
assert.ifError(err);
|
||||
|
||||
var image;
|
||||
var obj;
|
||||
|
||||
if (isPng) {
|
||||
image = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
|
||||
obj = mapnik.Image.fromBytes(new Buffer(res.body, 'binary'));
|
||||
} else {
|
||||
obj = JSON.parse(res.body);
|
||||
}
|
||||
|
||||
next(null, res, image);
|
||||
next(null, res, obj);
|
||||
});
|
||||
},
|
||||
function finish(err, res, image) {
|
||||
@@ -377,6 +380,94 @@ TestClient.prototype.getLayergroup = function(expectedResponse, callback) {
|
||||
);
|
||||
};
|
||||
|
||||
TestClient.prototype.getNodeStatus = function(nodeName, callback) {
|
||||
var self = this;
|
||||
|
||||
var url = '/api/v1/map';
|
||||
|
||||
if (this.apiKey) {
|
||||
url += '?' + qs.stringify({api_key: this.apiKey});
|
||||
}
|
||||
|
||||
var layergroupId;
|
||||
var nodes = {};
|
||||
step(
|
||||
function createLayergroup() {
|
||||
var next = this;
|
||||
assert.response(server,
|
||||
{
|
||||
url: url,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
host: 'localhost',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(self.mapConfig)
|
||||
},
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
}
|
||||
},
|
||||
function(res, err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
var parsedBody = JSON.parse(res.body);
|
||||
|
||||
nodes = parsedBody.metadata.analyses.reduce(function(nodes, analysis) {
|
||||
return Object.keys(analysis.nodes).reduce(function(nodes, nodeName) {
|
||||
var node = analysis.nodes[nodeName];
|
||||
nodes[nodeName] = node.url.http;
|
||||
return nodes;
|
||||
}, nodes);
|
||||
}, nodes);
|
||||
|
||||
return next(null, parsedBody.layergroupid);
|
||||
}
|
||||
);
|
||||
},
|
||||
function getNodeStatusResult(err, _layergroupId) {
|
||||
assert.ifError(err);
|
||||
|
||||
var next = this;
|
||||
layergroupId = _layergroupId;
|
||||
|
||||
url = urlParser.parse(nodes[nodeName]).path;
|
||||
|
||||
if (self.apiKey) {
|
||||
url += '?' + qs.stringify({api_key: self.apiKey});
|
||||
}
|
||||
|
||||
var request = {
|
||||
url: url,
|
||||
method: 'GET',
|
||||
headers: {
|
||||
host: 'localhost'
|
||||
}
|
||||
};
|
||||
|
||||
var expectedResponse = {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
}
|
||||
};
|
||||
|
||||
assert.response(server, request, expectedResponse, function(res, err) {
|
||||
assert.ifError(err);
|
||||
next(null, res, JSON.parse(res.body));
|
||||
});
|
||||
},
|
||||
function finish(err, res, image) {
|
||||
self.keysToDelete['map_cfg|' + LayergroupToken.parse(layergroupId).token] = 0;
|
||||
self.keysToDelete['user:localhost:mapviews:global'] = 5;
|
||||
return callback(err, res, image);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
TestClient.prototype.drain = function(callback) {
|
||||
helper.deleteRedisKeys(this.keysToDelete, callback);
|
||||
};
|
||||
|
||||
@@ -3,11 +3,11 @@ require('../../support/test_helper');
|
||||
var assert = require('assert');
|
||||
var OverviewsQueryRewriter = require('../../../lib/cartodb/utils/overviews_query_rewriter');
|
||||
var overviewsQueryRewriter = new OverviewsQueryRewriter({
|
||||
zoom_level: 'ZoomLevel()'
|
||||
zoom_level: 'ZoomLevel()'
|
||||
});
|
||||
|
||||
function normalize_whitespace(txt) {
|
||||
return txt.replace(/\s+/g, " ").trim();
|
||||
return txt.replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
// compare SQL statements ignoring whitespace
|
||||
@@ -17,410 +17,462 @@ function assertSameSql(sql1, 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 if no overviews data is present', function(){
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
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' }
|
||||
it('does not alter queries which don\'t use overviews', function(){
|
||||
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();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
assert.equal(overviews_sql, sql);
|
||||
});
|
||||
|
||||
// jshint multistr:true
|
||||
// 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' }
|
||||
it('generates query with single overview layer for level 0', function(){
|
||||
var sql = "SELECT * FROM table1";
|
||||
var data = {
|
||||
overviews: {
|
||||
table1: {
|
||||
0: { table: 'table1_ov0' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM table1_ov0, _vovw_scale WHERE _vovw_z = 0\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 0\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM table1_ov0, _vovw_scale WHERE _vovw_z = 0\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 0\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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' }
|
||||
it('generates query with single overview layer for level >0', function(){
|
||||
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 )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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' }
|
||||
it('generates query with multiple overview layers for all levels up to N', function(){
|
||||
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 )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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' }
|
||||
it('generates query with multiple overview layers for random levels', function(){
|
||||
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 )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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' }
|
||||
it('generates query for a table with explicit schema', function(){
|
||||
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 )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM public.table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM public.table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM public.table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM public.table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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' }
|
||||
it('generates query for a table with explicit schema in the overviews info', function(){
|
||||
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 )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM public.table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM public.table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM public.table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM public.table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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"' }
|
||||
it('uses schema name from overviews', function(){
|
||||
var sql = "SELECT * FROM public.table1";
|
||||
var data = {
|
||||
overviews: {
|
||||
'table1': {
|
||||
schema: 'public',
|
||||
2: { table: 'table1_ov2' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS \"_vovw_table 1\"\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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' }
|
||||
it('ignores schema name from overviews if not necessary', function(){
|
||||
var sql = "SELECT * FROM table1";
|
||||
var data = {
|
||||
overviews: {
|
||||
'table1': {
|
||||
schema: 'public',
|
||||
2: { table: 'table1_ov2' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS _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 )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
it('uses redundant schema information', function(){
|
||||
var sql = "SELECT * FROM public.table1";
|
||||
var data = {
|
||||
overviews: {
|
||||
'public.table1': {
|
||||
schema: 'public',
|
||||
2: { table: 'table1_ov2' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS \"_vovw_table 1\"\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
SELECT * FROM public.table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM public.table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
|
||||
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' }
|
||||
it('generates query for a table that needs quoting with explicit schema', function(){
|
||||
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 )\
|
||||
SELECT column1, column2, column3 FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS \"_vovw_table 1\"\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
it('generates query using overviews for queries with a semicolon', function(done){
|
||||
var sql = "SELECT column1, column2, column3 FROM table1;";
|
||||
var data = {
|
||||
overviews: {
|
||||
table1: {
|
||||
2: { table: 'table1_ov2' }
|
||||
it('generates query for a table with explicit schema that needs quoting', function(){
|
||||
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 overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT column1, column2, column3 FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1;\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
|
||||
it('generates query using overviews for queries with extra whitespace', function(done){
|
||||
var sql = " SELECT column1,column2, column3 FROM table1 ";
|
||||
var data = {
|
||||
overviews: {
|
||||
table1: {
|
||||
2: { table: 'table1_ov2' }
|
||||
it('generates query for a table with explicit schema both needing quoting', function(){
|
||||
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 )\
|
||||
SELECT column1,column2, column3 FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (\
|
||||
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\
|
||||
) AS \"_vovw_table 1\"\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
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' }
|
||||
|
||||
it('generates query using overviews for queries with selected columns', function(){
|
||||
var sql = "SELECT column1, column2, column3 FROM table1";
|
||||
var data = {
|
||||
overviews: {
|
||||
table1: {
|
||||
2: { table: 'table1_ov2' }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
assert.equal(overviews_sql, sql);
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT column1, column2, column3 FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_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);
|
||||
|
||||
sql = "SELECT table1.*, column1, column2, column3 FROM table1";
|
||||
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
assert.equal(overviews_sql, sql);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
it('generates overviews for wrapped query', function(done){
|
||||
var sql = "SELECT * FROM (SELECT * FROM table1) AS wrapped_query WHERE 1=1";
|
||||
var data = {
|
||||
overviews: {
|
||||
table1: {
|
||||
0: { table: 'table1_ov0' },
|
||||
1: { table: 'table1_ov1' },
|
||||
2: { table: 'table1_ov2' }
|
||||
it('generates query using overviews for queries with a semicolon', function(){
|
||||
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 )\
|
||||
SELECT * FROM (SELECT * FROM (\
|
||||
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, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1) AS wrapped_query WHERE 1=1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
done();
|
||||
});
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT column1, column2, column3 FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1;\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
it('generates query using overviews for queries with extra whitespace', function(){
|
||||
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 )\
|
||||
SELECT column1,column2, column3 FROM (\
|
||||
SELECT * FROM table1_ov2, _vovw_scale WHERE _vovw_z <= 2\
|
||||
UNION ALL\
|
||||
SELECT * FROM table1, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
|
||||
it('does not alter queries which have not the simple supported form', function(){
|
||||
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);
|
||||
|
||||
sql = "SELECT table1.*, column1, column2, column3 FROM table1";
|
||||
overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
assert.equal(overviews_sql, sql);
|
||||
});
|
||||
|
||||
it('generates overviews for wrapped query', function(){
|
||||
var sql = "SELECT * FROM (SELECT * FROM table1) AS wrapped_query WHERE 1=1";
|
||||
var data = {
|
||||
overviews: {
|
||||
table1: {
|
||||
0: { table: 'table1_ov0' },
|
||||
1: { table: 'table1_ov1' },
|
||||
2: { table: 'table1_ov2' }
|
||||
}
|
||||
}
|
||||
};
|
||||
var overviews_sql = overviewsQueryRewriter.query(sql, data);
|
||||
var expected_sql = "\
|
||||
WITH\
|
||||
_vovw_scale AS ( SELECT ZoomLevel() AS _vovw_z )\
|
||||
SELECT * FROM (SELECT * FROM (\
|
||||
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, _vovw_scale WHERE _vovw_z > 2\
|
||||
) AS _vovw_table1) AS wrapped_query WHERE 1=1\
|
||||
";
|
||||
assertSameSql(overviews_sql, expected_sql);
|
||||
});
|
||||
});
|
||||
|
||||