From 95ab99be4dab164b196bac252c555c550c0cd935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Tue, 9 Feb 2016 19:06:34 +0100 Subject: [PATCH 01/22] Use new CDB_QueryTablesUpdatedAt function --- lib/cartodb/api/query_tables_api.js | 26 +++++++------------ lib/cartodb/api/tables_extent_api.js | 10 +++---- .../cache/model/database_tables_entry.js | 14 +++++----- lib/cartodb/controllers/layergroup.js | 19 ++++++++------ lib/cartodb/controllers/map.js | 26 +++++++++---------- lib/cartodb/controllers/named_maps.js | 3 +-- test/acceptance/multilayer.js | 6 ++--- 7 files changed, 49 insertions(+), 55 deletions(-) diff --git a/lib/cartodb/api/query_tables_api.js b/lib/cartodb/api/query_tables_api.js index af2fc978..c32ace7f 100644 --- a/lib/cartodb/api/query_tables_api.js +++ b/lib/cartodb/api/query_tables_api.js @@ -29,32 +29,26 @@ QueryTablesApi.prototype.getAffectedTablesInQuery = function (username, sql, cal }; QueryTablesApi.prototype.getAffectedTablesAndLastUpdatedTime = function (username, sql, callback) { - var query = [ - 'WITH querytables AS (', - 'SELECT * FROM CDB_QueryTablesText($windshaft$' + prepareSql(sql) + '$windshaft$) as tablenames', - ')', - 'SELECT (SELECT tablenames FROM querytables), EXTRACT(EPOCH FROM max(updated_at)) as max', - 'FROM CDB_TableMetadata m', - 'WHERE m.tabname = any ((SELECT tablenames from querytables)::regclass[])' - ].join(' '); + var query = + 'SELECT * FROM CDB_QueryTablesUpdatedAt($windshaft$' + prepareSql(sql) + '$windshaft$)'; this.pgQueryRunner.run(username, query, function handleAffectedTablesAndLastUpdatedTimeRows (err, rows) { - if (err || rows.length === 0) { + if (err) { var msg = err.message ? err.message : err; callback(new Error('could not fetch affected tables or last updated time: ' + msg)); return; } - var result = rows[0]; + var affectedTables = rows; - // This is an Array, so no need to split into parts - var tableNames = result.tablenames; - - var lastUpdatedTime = result.max || 0; + var updatedTimes = affectedTables.map(function getUpdateDate(table) { + return table.updated_at; + }); + var lastUpdatedTime = (affectedTables.length === 0 ? 0 : Math.max.apply(null, updatedTimes)) || 0; callback(null, { - affectedTables: tableNames, - lastUpdatedTime: lastUpdatedTime * 1000 + affectedTables: affectedTables, + lastUpdatedTime: lastUpdatedTime }); }); }; diff --git a/lib/cartodb/api/tables_extent_api.js b/lib/cartodb/api/tables_extent_api.js index d4293ed7..7b534a3f 100644 --- a/lib/cartodb/api/tables_extent_api.js +++ b/lib/cartodb/api/tables_extent_api.js @@ -13,13 +13,9 @@ module.exports = TablesExtentApi; * `table_name` format as valid input * @param {Function} callback function(err, result) {Object} result with `west`, `south`, `east`, `north` */ -TablesExtentApi.prototype.getBounds = function (username, tableNames, callback) { - var estimatedExtentSQLs = tableNames.map(function(tableName) { - var schemaTable = tableName.split('.'); - if (schemaTable.length > 1) { - return "ST_EstimatedExtent('" + schemaTable[0] + "', '" + schemaTable[1] + "', 'the_geom_webmercator')"; - } - return "ST_EstimatedExtent('" + schemaTable[0] + "', 'the_geom_webmercator')"; +TablesExtentApi.prototype.getBounds = function (username, tables, callback) { + var estimatedExtentSQLs = tables.map(function(table) { + return "ST_EstimatedExtent('" + table.schema_name + "', '" + table.table_name + "', 'the_geom_webmercator')"; }); var query = [ diff --git a/lib/cartodb/cache/model/database_tables_entry.js b/lib/cartodb/cache/model/database_tables_entry.js index 4d269137..89bf88ab 100644 --- a/lib/cartodb/cache/model/database_tables_entry.js +++ b/lib/cartodb/cache/model/database_tables_entry.js @@ -1,22 +1,24 @@ var crypto = require('crypto'); -function DatabaseTables(dbName, tableNames) { +function DatabaseTables(tables) { this.namespace = 't'; - this.dbName = dbName; - this.tableNames = tableNames; + this.tables = tables; } module.exports = DatabaseTables; DatabaseTables.prototype.key = function() { - return this.tableNames.map(function(tableName) { - return this.namespace + ':' + shortHashKey(this.dbName + ':' + tableName); + return this.tables.map(function(table) { + return this.namespace + ':' + shortHashKey(table.db_name + ':' + table.table_name + '.' + table.schema_name); }.bind(this)); }; DatabaseTables.prototype.getCacheChannel = function() { - return this.dbName + ':' + this.tableNames.join(','); + var key = this.tables.map(function(table) { + return table.db_name + ':' + table.schema_name + "." + table.table_name; + }).join(";;"); + return key; }; function shortHashKey(target) { diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index 0a7e7698..e647a046 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -320,7 +320,7 @@ LayergroupController.prototype.sendResponse = function(req, res, body, status, h global.logger.warn('ERROR generating cache channel: ' + err); } if (!!affectedTables) { - var tablesCacheEntry = new TablesCacheEntry(dbName, affectedTables); + var tablesCacheEntry = new TablesCacheEntry(affectedTables); res.set('X-Cache-Channel', tablesCacheEntry.getCacheChannel()); self.surrogateKeysCache.tag(res, tablesCacheEntry); } @@ -366,17 +366,20 @@ LayergroupController.prototype.getAffectedTables = function(user, dbName, layerg throw new Error("this request doesn't need an X-Cache-Channel generated"); } - self.queryTablesApi.getAffectedTablesInQuery(user, sql, this); // in addCacheChannel + self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(user, sql, this); // in addCacheChannel }, - function buildCacheChannel(err, tableNames) { + function buildCacheChannel(err, tables) { assert.ifError(err); + self.layergroupAffectedTables.set(dbName, layergroupId, tables.affectedTables); - self.layergroupAffectedTables.set(dbName, layergroupId, tableNames); - - return tableNames; + return tables; }, - function finish(err, affectedTables) { - callback(err, affectedTables); + function finish(err, tables) { + if(tables === undefined){ + callback(err); + }else{ + callback(err, tables.affectedTables); + } } ); }; diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index 9fad27f6..dad77dbd 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -280,20 +280,20 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la function checkCachedAffectedTables() { return self.layergroupAffectedTables.hasAffectedTables(dbName, layergroupId); }, - function getAffectedTablesAndLastUpdatedTime(err, hasCache) { + function getAffectedTablesAndLastUpdatedTime(err) { assert.ifError(err); - if (hasCache) { - var next = this; - var affectedTables = self.layergroupAffectedTables.get(dbName, layergroupId); - self.queryTablesApi.getLastUpdatedTime(username, affectedTables, function(err, lastUpdatedTime) { - if (err) { - return next(err); - } - return next(null, { affectedTables: affectedTables, lastUpdatedTime: lastUpdatedTime }); - }); - } else { + // if (hasCache) { + // var next = this; + // var affectedTables = self.layergroupAffectedTables.get(dbName, layergroupId); + // self.queryTablesApi.getLastUpdatedTime(username, affectedTables, function(err, lastUpdatedTime) { + // if (err) { + // return next(err); + // } + // return next(null, { affectedTables: affectedTables, lastUpdatedTime: lastUpdatedTime }); + // }); + // } else { self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this); - } + //} }, function handleAffectedTablesAndLastUpdatedTime(err, result) { if (req.profiler) { @@ -310,7 +310,7 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la addWidgetsUrl(username, layergroup); if (req.method === 'GET') { - var tableCacheEntry = new TablesCacheEntry(dbName, result.affectedTables); + var tableCacheEntry = new TablesCacheEntry(result.affectedTables); var ttl = global.environment.varnish.layergroupTtl || 86400; res.set('Cache-Control', 'public,max-age='+ttl+',must-revalidate'); res.set('Last-Modified', (new Date()).toUTCString()); diff --git a/lib/cartodb/controllers/named_maps.js b/lib/cartodb/controllers/named_maps.js index 004282c9..3687dc39 100644 --- a/lib/cartodb/controllers/named_maps.js +++ b/lib/cartodb/controllers/named_maps.js @@ -44,7 +44,6 @@ NamedMapsController.prototype.sendResponse = function(req, res, resource, header var self = this; - var dbName = req.params.dbname; step( function getAffectedTablesAndLastUpdatedTime() { namedMapProvider.getAffectedTablesAndLastUpdatedTime(this); @@ -66,7 +65,7 @@ NamedMapsController.prototype.sendResponse = function(req, res, resource, header } res.set('Last-Modified', lastModifiedDate.toUTCString()); - var tablesCacheEntry = new TablesCacheEntry(dbName, result.affectedTables); + var tablesCacheEntry = new TablesCacheEntry(result.affectedTables); res.set('X-Cache-Channel', tablesCacheEntry.getCacheChannel()); if (result.affectedTables.length > 0) { self.surrogateKeysCache.tag(res, tablesCacheEntry); diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index 94df8bdc..d4eac5ef 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -262,9 +262,9 @@ describe(suiteName, function() { var parsedBody = JSON.parse(res.body); expected_token = parsedBody.layergroupid.split(':')[0]; helper.checkCache(res); - helper.checkSurrogateKey(res, new TablesCacheEntry('test_windshaft_cartodb_user_1_db', [ - 'public.test_table', - 'public.test_table_2' + helper.checkSurrogateKey(res, new TablesCacheEntry([ + {db_name: "test_windshaft_cartodb_user_1_db", table_name: "test_table", schema_name: "public"}, + {db_name: "test_windshaft_cartodb_user_1_db", table_name: "test_table_2", schema_name: "public"}, ]).key().join(' ')); From b7ff554209dc7a0fc90f8f0b511c21899ed573b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Thu, 11 Feb 2016 11:45:09 +0100 Subject: [PATCH 02/22] Use new _Updated_At function and new names --- lib/cartodb/api/query_tables_api.js | 2 +- lib/cartodb/cache/model/database_tables_entry.js | 4 ++-- test/acceptance/multilayer.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/cartodb/api/query_tables_api.js b/lib/cartodb/api/query_tables_api.js index c32ace7f..a94d6411 100644 --- a/lib/cartodb/api/query_tables_api.js +++ b/lib/cartodb/api/query_tables_api.js @@ -30,7 +30,7 @@ QueryTablesApi.prototype.getAffectedTablesInQuery = function (username, sql, cal QueryTablesApi.prototype.getAffectedTablesAndLastUpdatedTime = function (username, sql, callback) { var query = - 'SELECT * FROM CDB_QueryTablesUpdatedAt($windshaft$' + prepareSql(sql) + '$windshaft$)'; + 'SELECT * FROM CDB_QueryTables_Updated_At($windshaft$' + prepareSql(sql) + '$windshaft$)'; this.pgQueryRunner.run(username, query, function handleAffectedTablesAndLastUpdatedTimeRows (err, rows) { if (err) { diff --git a/lib/cartodb/cache/model/database_tables_entry.js b/lib/cartodb/cache/model/database_tables_entry.js index 89bf88ab..60629714 100644 --- a/lib/cartodb/cache/model/database_tables_entry.js +++ b/lib/cartodb/cache/model/database_tables_entry.js @@ -10,13 +10,13 @@ module.exports = DatabaseTables; DatabaseTables.prototype.key = function() { return this.tables.map(function(table) { - return this.namespace + ':' + shortHashKey(table.db_name + ':' + table.table_name + '.' + table.schema_name); + return this.namespace + ':' + shortHashKey(table.dbname + ':' + table.table_name + '.' + table.schema_name); }.bind(this)); }; DatabaseTables.prototype.getCacheChannel = function() { var key = this.tables.map(function(table) { - return table.db_name + ':' + table.schema_name + "." + table.table_name; + return table.dbname + ':' + table.schema_name + "." + table.table_name; }).join(";;"); return key; }; diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index d4eac5ef..2611bb7f 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -263,8 +263,8 @@ describe(suiteName, function() { expected_token = parsedBody.layergroupid.split(':')[0]; helper.checkCache(res); helper.checkSurrogateKey(res, new TablesCacheEntry([ - {db_name: "test_windshaft_cartodb_user_1_db", table_name: "test_table", schema_name: "public"}, - {db_name: "test_windshaft_cartodb_user_1_db", table_name: "test_table_2", schema_name: "public"}, + {dbname: "test_windshaft_cartodb_user_1_db", table_name: "test_table", schema_name: "public"}, + {dbname: "test_windshaft_cartodb_user_1_db", table_name: "test_table_2", schema_name: "public"}, ]).key().join(' ')); From a6562850011e73bc14d6bd5b6434dfc1e3b812ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Fri, 12 Feb 2016 17:25:57 +0100 Subject: [PATCH 03/22] Run tests against master cartodb-postgresql --- test/support/prepare_db.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test/support/prepare_db.sh b/test/support/prepare_db.sh index 4f001228..8ade522f 100755 --- a/test/support/prepare_db.sh +++ b/test/support/prepare_db.sh @@ -79,10 +79,19 @@ if test x"$PREPARE_PGSQL" = xyes; then psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 psql -c "CREATE LANGUAGE plpythonu;" ${TEST_DB} - curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryStatements.sql -o sql/CDB_QueryStatements.sql - curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/cdb/scripts-available/CDB_QueryTables.sql -o sql/CDB_QueryTables.sql - cat sql/CDB_QueryStatements.sql sql/CDB_QueryTables.sql | + curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/master/scripts-available/CDB_QueryStatements.sql -o sql/CDB_QueryStatements.sql + curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/master/scripts-available/CDB_QueryTables.sql -o sql/CDB_QueryTables.sql + curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/master/scripts-available/CDB_TableMetadata.sql -o sql/CDB_TableMetadata.sql + curl -L -s https://github.com/CartoDB/cartodb-postgresql/raw/master/scripts-available/CDB_ForeignTable.sql -o sql/CDB_ForeignTable.sql + cat sql/CDB_QueryStatements.sql | + psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 + cat sql/CDB_QueryTables.sql | + psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 + cat sql/CDB_TableMetadata.sql| psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 + cat sql/CDB_ForeignTable.sql|sed -e 's/cartodb\./public./g' \ + -e "s/''cartodb''/''public''/g" | + psql -v ON_ERROR_STOP=1 ${TEST_DB} || exit 1 fi From 33ba629c6d05f651bf3b3d968bcbcf96293daf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 15 Feb 2016 13:00:21 +0100 Subject: [PATCH 04/22] Add publicuser creation to Travis config --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8492e564..db5cd52f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ addons: before_install: - npm install -g npm@2 - createdb template_postgis + - createuser publicuser - psql -c "CREATE EXTENSION postgis" template_postgis env: From 119846b56b188b4d04f89330712d3040215ec5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 15 Feb 2016 16:04:13 +0100 Subject: [PATCH 05/22] Fix specs --- test/acceptance/templates.js | 4 ++-- test/integration/query-tables-api.js | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index d4eb304b..1db9cd90 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -1393,7 +1393,7 @@ describe('template_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/176 helper.checkCache(res); var expectedSurrogateKey = [ - new TablesCacheEntry('test_windshaft_cartodb_user_1_db', ['public.test_table_private_1']).key(), + new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', table_name: 'test_table_private_1'}]).key(), new NamedMapsCacheEntry('localhost', template_acceptance_open.name).key() ].join(' '); helper.checkSurrogateKey(res, expectedSurrogateKey); @@ -1476,7 +1476,7 @@ describe('template_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/176 helper.checkCache(res); var expectedSurrogateKey = [ - new TablesCacheEntry('test_windshaft_cartodb_user_1_db', ['public.test_table_private_1']).key(), + new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', table_name: 'test_table_private_1'}]).key(), new NamedMapsCacheEntry('localhost', template_acceptance_open.name).key() ].join(' '); helper.checkSurrogateKey(res, expectedSurrogateKey); diff --git a/test/integration/query-tables-api.js b/test/integration/query-tables-api.js index d05b1ed0..c4996f0b 100644 --- a/test/integration/query-tables-api.js +++ b/test/integration/query-tables-api.js @@ -28,9 +28,8 @@ describe('QueryTablesApi', function() { var query = 'select * from test_table'; queryTablesApi.getAffectedTablesAndLastUpdatedTime('localhost', query, function(err, result) { assert.ok(!err, err); - assert.deepEqual(result, { - affectedTables: [ 'public.test_table' ], + affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", "table_name": 'test_table', updated_at: new Date(1234567890123)}], lastUpdatedTime: 1234567890123 }); @@ -44,7 +43,7 @@ describe('QueryTablesApi', function() { assert.ok(!err, err); assert.deepEqual(result, { - affectedTables: [ 'public.test_table_private_1' ], + affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", "table_name": 'test_table_private_1', updated_at: new Date(1234567890123)}], lastUpdatedTime: 1234567890123 }); From 0e83420e24a333b3ae71846104c16017a3e924c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 15 Feb 2016 16:15:43 +0100 Subject: [PATCH 06/22] Fix long line --- test/integration/query-tables-api.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/integration/query-tables-api.js b/test/integration/query-tables-api.js index c4996f0b..93ca0a07 100644 --- a/test/integration/query-tables-api.js +++ b/test/integration/query-tables-api.js @@ -29,7 +29,8 @@ describe('QueryTablesApi', function() { queryTablesApi.getAffectedTablesAndLastUpdatedTime('localhost', query, function(err, result) { assert.ok(!err, err); assert.deepEqual(result, { - affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", "table_name": 'test_table', updated_at: new Date(1234567890123)}], + affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", + "table_name": 'test_table', updated_at: new Date(1234567890123)}], lastUpdatedTime: 1234567890123 }); @@ -43,7 +44,8 @@ describe('QueryTablesApi', function() { assert.ok(!err, err); assert.deepEqual(result, { - affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", "table_name": 'test_table_private_1', updated_at: new Date(1234567890123)}], + affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", + "table_name": 'test_table_private_1', updated_at: new Date(1234567890123)}], lastUpdatedTime: 1234567890123 }); From 19596245b801f40e404d24612579bdf5e0739106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 15 Feb 2016 16:21:13 +0100 Subject: [PATCH 07/22] Fix long line --- test/acceptance/templates.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index 1db9cd90..137f5ce5 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -1393,7 +1393,8 @@ describe('template_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/176 helper.checkCache(res); var expectedSurrogateKey = [ - new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', table_name: 'test_table_private_1'}]).key(), + new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', + table_name: 'test_table_private_1'}]).key(), new NamedMapsCacheEntry('localhost', template_acceptance_open.name).key() ].join(' '); helper.checkSurrogateKey(res, expectedSurrogateKey); @@ -1476,7 +1477,8 @@ describe('template_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/176 helper.checkCache(res); var expectedSurrogateKey = [ - new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', table_name: 'test_table_private_1'}]).key(), + new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', + table_name: 'test_table_private_1'}]).key(), new NamedMapsCacheEntry('localhost', template_acceptance_open.name).key() ].join(' '); helper.checkSurrogateKey(res, expectedSurrogateKey); From 6ece30fa2c2f12c3835f4a98b0db34867c1470fc Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 17 Feb 2016 11:47:27 +0100 Subject: [PATCH 08/22] Ignore CDB_ sql files downloaded for tests --- test/support/sql/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/support/sql/.gitignore diff --git a/test/support/sql/.gitignore b/test/support/sql/.gitignore new file mode 100644 index 00000000..68d2db39 --- /dev/null +++ b/test/support/sql/.gitignore @@ -0,0 +1 @@ +CDB_*.sql From 3d0c0f34adc2a730dd00c1ae339e5c39f011efd7 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 17 Feb 2016 12:15:20 +0100 Subject: [PATCH 09/22] Use a set to compare surrogate keys, avoiding key order errors --- test/support/test_helper.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/support/test_helper.js b/test/support/test_helper.js index e44916fd..de0f7822 100644 --- a/test/support/test_helper.js +++ b/test/support/test_helper.js @@ -63,7 +63,15 @@ function checkCache(res) { function checkSurrogateKey(res, expectedKey) { assert.ok(res.headers.hasOwnProperty('surrogate-key')); - assert.equal(res.headers['surrogate-key'], expectedKey); + + function createSet(keys, key) { + keys[key] = true; + return keys; + } + var keys = res.headers['surrogate-key'].split(' ').reduce(createSet, {}); + var expectedKeys = expectedKey.split(' ').reduce(createSet, {}); + + assert.deepEqual(keys, expectedKeys); } //global afterEach to capture test suites that leave keys in redis From 587f66c23d795321b5c8ecc65fd15cfa43bcf6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Wed, 17 Feb 2016 15:36:26 +0100 Subject: [PATCH 10/22] Sort cache channels and keys alphabetically --- lib/cartodb/cache/model/database_tables_entry.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cartodb/cache/model/database_tables_entry.js b/lib/cartodb/cache/model/database_tables_entry.js index 60629714..a64c8dae 100644 --- a/lib/cartodb/cache/model/database_tables_entry.js +++ b/lib/cartodb/cache/model/database_tables_entry.js @@ -11,13 +11,13 @@ module.exports = DatabaseTables; DatabaseTables.prototype.key = function() { return this.tables.map(function(table) { return this.namespace + ':' + shortHashKey(table.dbname + ':' + table.table_name + '.' + table.schema_name); - }.bind(this)); + }.bind(this)).sort(); }; DatabaseTables.prototype.getCacheChannel = function() { var key = this.tables.map(function(table) { return table.dbname + ':' + table.schema_name + "." + table.table_name; - }).join(";;"); + }).sort().join(";;"); return key; }; From cf06ff86c2a7df53bf7afcbde89414525ef936b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 22 Feb 2016 11:40:25 +0100 Subject: [PATCH 11/22] Use node-cartodb-query-tables library --- lib/cartodb/api/query_tables_api.js | 26 -------------- lib/cartodb/backends/pg_connection.js | 35 +++++++++++++++++++ .../cache/model/database_tables_entry.js | 26 -------------- lib/cartodb/controllers/layergroup.js | 25 +++++++++---- lib/cartodb/controllers/map.js | 28 +++++++++------ lib/cartodb/controllers/named_maps.js | 15 ++++---- package.json | 1 + test/acceptance/multilayer.js | 4 +-- test/acceptance/multilayer_server.js | 13 ++++--- test/acceptance/templates.js | 6 ++-- 10 files changed, 92 insertions(+), 87 deletions(-) delete mode 100644 lib/cartodb/cache/model/database_tables_entry.js diff --git a/lib/cartodb/api/query_tables_api.js b/lib/cartodb/api/query_tables_api.js index a94d6411..bf85b1a0 100644 --- a/lib/cartodb/api/query_tables_api.js +++ b/lib/cartodb/api/query_tables_api.js @@ -53,32 +53,6 @@ QueryTablesApi.prototype.getAffectedTablesAndLastUpdatedTime = function (usernam }); }; -QueryTablesApi.prototype.getLastUpdatedTime = function (username, tableNames, callback) { - if (!Array.isArray(tableNames) || tableNames.length === 0) { - return callback(null, 0); - } - - var query = [ - 'SELECT EXTRACT(EPOCH FROM max(updated_at)) as max', - 'FROM CDB_TableMetadata m WHERE m.tabname = any (ARRAY[', - tableNames.map(function(t) { return "'" + t + "'::regclass"; }).join(','), - '])' - ].join(' '); - - this.pgQueryRunner.run(username, query, function handleLastUpdatedTimeRows (err, rows) { - if (err) { - var msg = err.message ? err.message : err; - return callback(new Error('could not fetch affected tables or last updated time: ' + msg)); - } - // when the table has not updated_at means it hasn't been changed so a default last_updated is set - var lastUpdated = 0; - if (rows.length !== 0) { - lastUpdated = rows[0].max || 0; - } - - return callback(null, lastUpdated*1000); - }); -}; function prepareSql(sql) { return sql diff --git a/lib/cartodb/backends/pg_connection.js b/lib/cartodb/backends/pg_connection.js index 2ca56f5b..d98bb703 100644 --- a/lib/cartodb/backends/pg_connection.js +++ b/lib/cartodb/backends/pg_connection.js @@ -1,5 +1,6 @@ var assert = require('assert'); var step = require('step'); +var PSQL = require('cartodb-psql'); var _ = require('underscore'); function PgConnection(metadataBackend) { @@ -99,3 +100,37 @@ PgConnection.prototype.setDBConn = function(dbowner, params, callback) { } ); }; + + +/** + * Returns a `cartodb-psql` object for a given username. + * @param {String} username + * @param {Function} callback function({Error}, {PSQL}) + */ + +PgConnection.prototype.getConnection = function(username, callback) { + var self = this; + + var params = {}; + + require('debug')('cachechan')("getConn1"); + step( + function setAuth() { + self.setDBAuth(username, params, this); + }, + function setConn(err) { + assert.ifError(err); + self.setDBConn(username, params, this); + }, + function openConnection(err) { + assert.ifError(err); + return callback(err, new PSQL({ + user: params.dbuser, + pass: params.dbpass, + host: params.dbhost, + port: params.dbport, + dbname: params.dbname + })); + } + ); +}; diff --git a/lib/cartodb/cache/model/database_tables_entry.js b/lib/cartodb/cache/model/database_tables_entry.js deleted file mode 100644 index a64c8dae..00000000 --- a/lib/cartodb/cache/model/database_tables_entry.js +++ /dev/null @@ -1,26 +0,0 @@ -var crypto = require('crypto'); - -function DatabaseTables(tables) { - this.namespace = 't'; - this.tables = tables; -} - -module.exports = DatabaseTables; - - -DatabaseTables.prototype.key = function() { - return this.tables.map(function(table) { - return this.namespace + ':' + shortHashKey(table.dbname + ':' + table.table_name + '.' + table.schema_name); - }.bind(this)).sort(); -}; - -DatabaseTables.prototype.getCacheChannel = function() { - var key = this.tables.map(function(table) { - return table.dbname + ':' + table.schema_name + "." + table.table_name; - }).sort().join(";;"); - return key; -}; - -function shortHashKey(target) { - return crypto.createHash('sha256').update(target).digest('base64').substring(0,6); -} diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index e647a046..6d393b27 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -8,7 +8,8 @@ var cors = require('../middleware/cors'); var userMiddleware = require('../middleware/user'); var MapStoreMapConfigProvider = require('../models/mapconfig/map_store_provider'); -var TablesCacheEntry = require('../cache/model/database_tables_entry'); + +var QueryTables = require('node-cartodb-query-tables'); /** * @param {AuthApi} authApi @@ -28,6 +29,7 @@ function LayergroupController(authApi, pgConnection, mapStore, tileBackend, prev widgetBackend, surrogateKeysCache, userLimitsApi, queryTablesApi, layergroupAffectedTables) { BaseController.call(this, authApi, pgConnection); + this.pgConnection = pgConnection; this.mapStore = mapStore; this.tileBackend = tileBackend; this.previewBackend = previewBackend; @@ -320,9 +322,8 @@ LayergroupController.prototype.sendResponse = function(req, res, body, status, h global.logger.warn('ERROR generating cache channel: ' + err); } if (!!affectedTables) { - var tablesCacheEntry = new TablesCacheEntry(affectedTables); - res.set('X-Cache-Channel', tablesCacheEntry.getCacheChannel()); - self.surrogateKeysCache.tag(res, tablesCacheEntry); + res.set('X-Cache-Channel', affectedTables.getCacheChannel()); + self.surrogateKeysCache.tag(res, affectedTables); } self.send(req, res, body, status, headers); } @@ -366,11 +367,21 @@ LayergroupController.prototype.getAffectedTables = function(user, dbName, layerg throw new Error("this request doesn't need an X-Cache-Channel generated"); } - self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(user, sql, this); // in addCacheChannel + step( + function getConnection() { + self.pgConnection.getConnection(user, this); + }, + function getAffectedTables(err, connection) { + assert.ifError(err); + + QueryTables.getAffectedTablesFromQuery(connection, sql, this); + }, + this + ); }, function buildCacheChannel(err, tables) { assert.ifError(err); - self.layergroupAffectedTables.set(dbName, layergroupId, tables.affectedTables); + self.layergroupAffectedTables.set(dbName, layergroupId, tables); return tables; }, @@ -378,7 +389,7 @@ LayergroupController.prototype.getAffectedTables = function(user, dbName, layerg if(tables === undefined){ callback(err); }else{ - callback(err, tables.affectedTables); + callback(err, tables); } } ); diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index a7613c2d..87fa85ea 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -2,6 +2,7 @@ var _ = require('underscore'); var assert = require('assert'); var step = require('step'); var windshaft = require('windshaft'); +var QueryTables = require('node-cartodb-query-tables'); var util = require('util'); var BaseController = require('./base'); @@ -13,7 +14,6 @@ var MapConfig = windshaft.model.MapConfig; var Datasource = windshaft.model.Datasource; var NamedMapsCacheEntry = require('../cache/model/named_maps_entry'); -var TablesCacheEntry = require('../cache/model/database_tables_entry'); var MapConfigNamedLayersAdapter = require('../models/mapconfig_named_layers_adapter'); var NamedMapMapConfigProvider = require('../models/mapconfig/named_map_provider'); @@ -329,31 +329,39 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la // return next(null, { affectedTables: affectedTables, lastUpdatedTime: lastUpdatedTime }); // }); // } else { - self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this); + // self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this); //} + step( + function getConnection() { + self.pgConnection.getConnection(username, this); + }, + function getAffectedTables(err, connection) { + assert.ifError(err); + QueryTables.getAffectedTablesFromQuery(connection, sql, this); + }, + this + ); }, function handleAffectedTablesAndLastUpdatedTime(err, result) { if (req.profiler) { req.profiler.done('queryTablesAndLastUpdated'); } assert.ifError(err); - self.layergroupAffectedTables.set(dbName, layergroupId, result.affectedTables); + self.layergroupAffectedTables.set(dbName, layergroupId, result); // last update for layergroup cache buster - layergroup.layergroupid = layergroup.layergroupid + ':' + result.lastUpdatedTime; - layergroup.last_updated = new Date(result.lastUpdatedTime).toISOString(); + layergroup.layergroupid = layergroup.layergroupid + ':' + result.getLastUpdatedAt(); + layergroup.last_updated = new Date(result.getLastUpdatedAt()).toISOString(); // TODO this should take into account several URL patterns addWidgetsUrl(username, layergroup); - if (req.method === 'GET') { - var tableCacheEntry = new TablesCacheEntry(result.affectedTables); var ttl = global.environment.varnish.layergroupTtl || 86400; res.set('Cache-Control', 'public,max-age='+ttl+',must-revalidate'); res.set('Last-Modified', (new Date()).toUTCString()); - res.set('X-Cache-Channel', tableCacheEntry.getCacheChannel()); - if (result.affectedTables && result.affectedTables.length > 0) { - self.surrogateKeysCache.tag(res, tableCacheEntry); + res.set('X-Cache-Channel', result.getCacheChannel()); + if (result.tables && result.tables.length > 0) { + self.surrogateKeysCache.tag(res, result); } } diff --git a/lib/cartodb/controllers/named_maps.js b/lib/cartodb/controllers/named_maps.js index 3687dc39..38ae91e8 100644 --- a/lib/cartodb/controllers/named_maps.js +++ b/lib/cartodb/controllers/named_maps.js @@ -9,8 +9,6 @@ var BaseController = require('./base'); var cors = require('../middleware/cors'); var userMiddleware = require('../middleware/user'); -var TablesCacheEntry = require('../cache/model/database_tables_entry'); - function NamedMapsController(authApi, pgConnection, namedMapProviderCache, tileBackend, previewBackend, surrogateKeysCache, tablesExtentApi, metadataBackend) { BaseController.call(this, authApi, pgConnection); @@ -53,22 +51,21 @@ NamedMapsController.prototype.sendResponse = function(req, res, resource, header if (err) { global.logger.log('ERROR generating cache channel: ' + err); } - if (!result || !!result.affectedTables) { + if (!result || !!result.tables) { // we increase cache control as we can invalidate it res.set('Cache-Control', 'public,max-age=31536000'); var lastModifiedDate; if (Number.isFinite(result.lastUpdatedTime)) { - lastModifiedDate = new Date(result.lastUpdatedTime); + lastModifiedDate = new Date(result.getLastUpdatedAt()); } else { lastModifiedDate = new Date(); } res.set('Last-Modified', lastModifiedDate.toUTCString()); - var tablesCacheEntry = new TablesCacheEntry(result.affectedTables); - res.set('X-Cache-Channel', tablesCacheEntry.getCacheChannel()); - if (result.affectedTables.length > 0) { - self.surrogateKeysCache.tag(res, tablesCacheEntry); + res.set('X-Cache-Channel', result.getCacheChannel()); + if (result.tables.length > 0) { + self.surrogateKeysCache.tag(res, result); } } self.send(req, res, resource, 200); @@ -230,7 +227,7 @@ NamedMapsController.prototype.getStaticImageOptions = function(cdbUser, namedMap return next(null); } - var affectedTables = affectedTablesAndLastUpdate.affectedTables || []; + var affectedTables = affectedTablesAndLastUpdate.tables || []; if (affectedTables.length === 0) { return next(null); diff --git a/package.json b/package.json index e31e26ff..d9877bb2 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "lru-cache": "2.6.5", "lzma": "~1.3.7", "log4js": "https://github.com/CartoDB/log4js-node/tarball/cdb" + "node-cartodb-query-tables": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master" }, "devDependencies": { "istanbul": "~0.3.6", diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index d4e06e52..202fb259 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -18,7 +18,7 @@ var serverOptions = require('../../lib/cartodb/server_options'); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); -var TablesCacheEntry = require('../../lib/cartodb/cache/model/database_tables_entry'); +var QueryTables = require('node-cartodb-query-tables'); ['/api/v1/map', '/user/localhost/api/v1/map'].forEach(function(layergroup_url) { @@ -262,7 +262,7 @@ describe(suiteName, function() { var parsedBody = JSON.parse(res.body); expected_token = parsedBody.layergroupid.split(':')[0]; helper.checkCache(res); - helper.checkSurrogateKey(res, new TablesCacheEntry([ + helper.checkSurrogateKey(res, new QueryTables.DatabaseTablesEntry([ {dbname: "test_windshaft_cartodb_user_1_db", table_name: "test_table", schema_name: "public"}, {dbname: "test_windshaft_cartodb_user_1_db", table_name: "test_table_2", schema_name: "public"}, ]).key().join(' ')); diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 544aea6c..2c3801e0 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -7,6 +7,7 @@ var _ = require('underscore'); var LayergroupToken = require('../../lib/cartodb/models/layergroup_token'); var PgQueryRunner = require('../../lib/cartodb/backends/pg_query_runner'); +var QueryTables = require('node-cartodb-query-tables'); var CartodbWindshaft = require('../../lib/cartodb/server'); var serverOptions = require('../../lib/cartodb/server_options'); var server = new CartodbWindshaft(serverOptions); @@ -309,6 +310,7 @@ describe('tests from old api translated to multilayer', function() { it("creates layergroup fails when postgresql queries fail to figure affected tables in query", function(done) { + var runQueryFn = PgQueryRunner.prototype.run; PgQueryRunner.prototype.run = function(username, query, callback) { return callback(new Error('fake error message'), []); @@ -343,6 +345,7 @@ describe('tests from old api translated to multilayer', function() { }); it("tile requests works when postgresql queries fail to figure affected tables in query", function(done) { + var layergroup = singleLayergroupConfig('select * from gadm4', '#gadm4 { marker-fill: red; }'); assert.response(server, { @@ -360,9 +363,11 @@ describe('tests from old api translated to multilayer', function() { keysToDelete['map_cfg|' + LayergroupToken.parse(JSON.parse(res.body).layergroupid).token] = 0; keysToDelete['user:localhost:mapviews:global'] = 5; - var runQueryFn = PgQueryRunner.prototype.run; - PgQueryRunner.prototype.run = function(username, query, callback) { - return callback(new Error('failed to query database for affected tables'), []); + var affectedFn = QueryTables.getAffectedTablesFromQuery; + QueryTables.getAffectedTablesFromQuery = function(sql, username, query, callback) { + affectedFn({query: function(query, callback) { + return callback(new Error('fake error message'), []); + }}, username, query, callback); }; // reset internal cacheChannel cache @@ -387,7 +392,7 @@ describe('tests from old api translated to multilayer', function() { }, function(res) { assert.ok(!res.headers.hasOwnProperty('x-cache-channel')); - PgQueryRunner.prototype.run = runQueryFn; + QueryTables.getAffectedTablesFromQuery = affectedFn; done(); } ); diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index 137f5ce5..4b53e0a6 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -3,8 +3,8 @@ var _ = require('underscore'); var redis = require('redis'); var step = require('step'); var strftime = require('strftime'); +var QueryTables = require('node-cartodb-query-tables'); var NamedMapsCacheEntry = require('../../lib/cartodb/cache/model/named_maps_entry'); -var TablesCacheEntry = require('../../lib/cartodb/cache/model/database_tables_entry'); var redis_stats_db = 5; // Pollute the PG environment to make sure @@ -1393,7 +1393,7 @@ describe('template_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/176 helper.checkCache(res); var expectedSurrogateKey = [ - new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', + new QueryTables.DatabaseTablesEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', table_name: 'test_table_private_1'}]).key(), new NamedMapsCacheEntry('localhost', template_acceptance_open.name).key() ].join(' '); @@ -1477,7 +1477,7 @@ describe('template_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/176 helper.checkCache(res); var expectedSurrogateKey = [ - new TablesCacheEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', + new QueryTables.DatabaseTableEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', table_name: 'test_table_private_1'}]).key(), new NamedMapsCacheEntry('localhost', template_acceptance_open.name).key() ].join(' '); From 2d6ee934485782a01a802ad5c6f8c7982ad07110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 22 Feb 2016 13:40:20 +0000 Subject: [PATCH 12/22] Delete query_tables_api.js, wrap shrinkwrap --- lib/cartodb/api/query_tables_api.js | 64 ----- npm-shrinkwrap.json | 392 ++++++++++++++-------------- 2 files changed, 199 insertions(+), 257 deletions(-) delete mode 100644 lib/cartodb/api/query_tables_api.js diff --git a/lib/cartodb/api/query_tables_api.js b/lib/cartodb/api/query_tables_api.js deleted file mode 100644 index bf85b1a0..00000000 --- a/lib/cartodb/api/query_tables_api.js +++ /dev/null @@ -1,64 +0,0 @@ -function QueryTablesApi(pgQueryRunner) { - this.pgQueryRunner = pgQueryRunner; -} - -var affectedTableRegexCache = { - bbox: /!bbox!/g, - scale_denominator: /!scale_denominator!/g, - pixel_width: /!pixel_width!/g, - pixel_height: /!pixel_height!/g -}; - -module.exports = QueryTablesApi; - - -QueryTablesApi.prototype.getAffectedTablesInQuery = function (username, sql, callback) { - var query = 'SELECT CDB_QueryTablesText($windshaft$' + prepareSql(sql) + '$windshaft$)'; - - this.pgQueryRunner.run(username, query, function handleAffectedTablesInQueryRows (err, rows) { - if (err){ - var msg = err.message ? err.message : err; - callback(new Error('could not fetch source tables: ' + msg)); - return; - } - - // This is an Array, so no need to split into parts - var tableNames = rows[0].cdb_querytablestext; - return callback(null, tableNames); - }); -}; - -QueryTablesApi.prototype.getAffectedTablesAndLastUpdatedTime = function (username, sql, callback) { - var query = - 'SELECT * FROM CDB_QueryTables_Updated_At($windshaft$' + prepareSql(sql) + '$windshaft$)'; - - this.pgQueryRunner.run(username, query, function handleAffectedTablesAndLastUpdatedTimeRows (err, rows) { - if (err) { - var msg = err.message ? err.message : err; - callback(new Error('could not fetch affected tables or last updated time: ' + msg)); - return; - } - - var affectedTables = rows; - - var updatedTimes = affectedTables.map(function getUpdateDate(table) { - return table.updated_at; - }); - var lastUpdatedTime = (affectedTables.length === 0 ? 0 : Math.max.apply(null, updatedTimes)) || 0; - - callback(null, { - affectedTables: affectedTables, - lastUpdatedTime: lastUpdatedTime - }); - }); -}; - - -function prepareSql(sql) { - return sql - .replace(affectedTableRegexCache.bbox, 'ST_MakeEnvelope(0,0,0,0)') - .replace(affectedTableRegexCache.scale_denominator, '0') - .replace(affectedTableRegexCache.pixel_width, '1') - .replace(affectedTableRegexCache.pixel_height, '1') - ; -} diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 70e7c50e..f376db31 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -4,93 +4,93 @@ "dependencies": { "body-parser": { "version": "1.14.2", - "from": "body-parser@>=1.14.0 <1.15.0", + "from": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.14.2.tgz", "dependencies": { "bytes": { "version": "2.2.0", - "from": "bytes@2.2.0", + "from": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz" }, "content-type": { "version": "1.0.1", - "from": "content-type@>=1.0.1 <1.1.0", + "from": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz" }, "depd": { "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", + "from": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" }, "http-errors": { "version": "1.3.1", - "from": "http-errors@>=1.3.1 <1.4.0", + "from": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "statuses": { "version": "1.2.1", - "from": "statuses@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" } } }, "iconv-lite": { "version": "0.4.13", - "from": "iconv-lite@0.4.13", + "from": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz" }, "on-finished": { "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", + "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "dependencies": { "ee-first": { "version": "1.1.1", - "from": "ee-first@1.1.1", + "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" } } }, "qs": { "version": "5.2.0", - "from": "qs@5.2.0", + "from": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.0.tgz" }, "raw-body": { "version": "2.1.5", - "from": "raw-body@>=2.1.5 <2.2.0", + "from": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.5.tgz", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.1.5.tgz", "dependencies": { "unpipe": { "version": "1.0.0", - "from": "unpipe@1.0.0", + "from": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" } } }, "type-is": { "version": "1.6.11", - "from": "type-is@>=1.6.10 <1.7.0", + "from": "https://registry.npmjs.org/type-is/-/type-is-1.6.11.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.11.tgz", "dependencies": { "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0", + "from": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "mime-types": { "version": "2.1.9", - "from": "mime-types@>=2.1.9 <2.2.0", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "dependencies": { "mime-db": { "version": "1.21.0", - "from": "mime-db@>=1.21.0 <1.22.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz" } } @@ -101,22 +101,22 @@ }, "cartodb-psql": { "version": "0.4.0", - "from": "cartodb-psql@>=0.4.0 <0.5.0", + "from": "https://registry.npmjs.org/cartodb-psql/-/cartodb-psql-0.4.0.tgz", "resolved": "https://registry.npmjs.org/cartodb-psql/-/cartodb-psql-0.4.0.tgz", "dependencies": { "pg": { "version": "2.6.2-cdb1", - "from": "git://github.com/CartoDB/node-postgres.git#2.6.2-cdb1", + "from": "git://github.com/CartoDB/node-postgres.git#836a2dc3131e873fc4ba20cd16e7fb69a7dca98a", "resolved": "git://github.com/CartoDB/node-postgres.git#836a2dc3131e873fc4ba20cd16e7fb69a7dca98a", "dependencies": { "generic-pool": { "version": "2.0.3", - "from": "generic-pool@2.0.3", + "from": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.3.tgz", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.3.tgz" }, "buffer-writer": { "version": "1.0.0", - "from": "buffer-writer@1.0.0", + "from": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz" } } @@ -125,37 +125,37 @@ }, "cartodb-redis": { "version": "0.13.0", - "from": "cartodb-redis@>=0.13.0 <0.14.0", + "from": "https://registry.npmjs.org/cartodb-redis/-/cartodb-redis-0.13.0.tgz", "resolved": "https://registry.npmjs.org/cartodb-redis/-/cartodb-redis-0.13.0.tgz", "dependencies": { "redis-mpool": { "version": "0.1.0", - "from": "git://github.com/CartoDB/node-redis-mpool.git#0.1.0", + "from": "git://github.com/CartoDB/node-redis-mpool.git#47510b8d4525ee24aa2e5328976372274a1d144e", "resolved": "git://github.com/CartoDB/node-redis-mpool.git#47510b8d4525ee24aa2e5328976372274a1d144e", "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@>=2.1.1 <2.2.0", + "from": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "redis": { "version": "0.12.1", - "from": "redis@>=0.12.1 <0.13.0", + "from": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz", "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" }, "hiredis": { "version": "0.1.17", - "from": "hiredis@>=0.1.17 <0.2.0", + "from": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", "dependencies": { "bindings": { "version": "1.2.1", - "from": "bindings@*", + "from": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.1.2", - "from": "nan@>=1.1.0 <1.2.0", + "from": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" } } @@ -166,228 +166,228 @@ }, "debug": { "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", + "from": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "dependencies": { "ms": { "version": "0.7.1", - "from": "ms@0.7.1", + "from": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" } } }, "dot": { "version": "1.0.3", - "from": "dot@>=1.0.2 <1.1.0", + "from": "https://registry.npmjs.org/dot/-/dot-1.0.3.tgz", "resolved": "https://registry.npmjs.org/dot/-/dot-1.0.3.tgz" }, "express": { "version": "4.13.4", - "from": "express@>=4.13.3 <4.14.0", + "from": "https://registry.npmjs.org/express/-/express-4.13.4.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.13.4.tgz", "dependencies": { "accepts": { "version": "1.2.13", - "from": "accepts@>=1.2.12 <1.3.0", + "from": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.2.13.tgz", "dependencies": { "mime-types": { "version": "2.1.9", - "from": "mime-types@>=2.1.6 <2.2.0", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "dependencies": { "mime-db": { "version": "1.21.0", - "from": "mime-db@>=1.21.0 <1.22.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz" } } }, "negotiator": { "version": "0.5.3", - "from": "negotiator@0.5.3", + "from": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.5.3.tgz" } } }, "array-flatten": { "version": "1.1.1", - "from": "array-flatten@1.1.1", + "from": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" }, "content-disposition": { "version": "0.5.1", - "from": "content-disposition@0.5.1", + "from": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" }, "content-type": { "version": "1.0.1", - "from": "content-type@>=1.0.1 <1.1.0", + "from": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz" }, "cookie": { "version": "0.1.5", - "from": "cookie@0.1.5", + "from": "https://registry.npmjs.org/cookie/-/cookie-0.1.5.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.5.tgz" }, "cookie-signature": { "version": "1.0.6", - "from": "cookie-signature@1.0.6", + "from": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" }, "depd": { "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", + "from": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" }, "escape-html": { "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", + "from": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" }, "etag": { "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", + "from": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" }, "finalhandler": { "version": "0.4.1", - "from": "finalhandler@0.4.1", + "from": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.4.1.tgz", "dependencies": { "unpipe": { "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0", + "from": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" } } }, "fresh": { "version": "0.3.0", - "from": "fresh@0.3.0", + "from": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" }, "merge-descriptors": { "version": "1.0.1", - "from": "merge-descriptors@1.0.1", + "from": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" }, "methods": { "version": "1.1.2", - "from": "methods@>=1.1.2 <1.2.0", + "from": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" }, "on-finished": { "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", + "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "dependencies": { "ee-first": { "version": "1.1.1", - "from": "ee-first@1.1.1", + "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" } } }, "parseurl": { "version": "1.3.1", - "from": "parseurl@>=1.3.1 <1.4.0", + "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" }, "path-to-regexp": { "version": "0.1.7", - "from": "path-to-regexp@0.1.7", + "from": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" }, "proxy-addr": { "version": "1.0.10", - "from": "proxy-addr@>=1.0.10 <1.1.0", + "from": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.0.10.tgz", "dependencies": { "forwarded": { "version": "0.1.0", - "from": "forwarded@>=0.1.0 <0.2.0", + "from": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" }, "ipaddr.js": { "version": "1.0.5", - "from": "ipaddr.js@1.0.5", + "from": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.0.5.tgz" } } }, "qs": { "version": "4.0.0", - "from": "qs@4.0.0", + "from": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-4.0.0.tgz" }, "range-parser": { "version": "1.0.3", - "from": "range-parser@>=1.0.3 <1.1.0", + "from": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.0.3.tgz" }, "send": { "version": "0.13.1", - "from": "send@0.13.1", + "from": "https://registry.npmjs.org/send/-/send-0.13.1.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.13.1.tgz", "dependencies": { "destroy": { "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", + "from": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" }, "http-errors": { "version": "1.3.1", - "from": "http-errors@>=1.3.1 <1.4.0", + "from": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.3.1.tgz", "dependencies": { "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "mime": { "version": "1.3.4", - "from": "mime@1.3.4", + "from": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" }, "ms": { "version": "0.7.1", - "from": "ms@0.7.1", + "from": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" }, "statuses": { "version": "1.2.1", - "from": "statuses@>=1.2.1 <1.3.0", + "from": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.2.1.tgz" } } }, "serve-static": { "version": "1.10.2", - "from": "serve-static@>=1.10.2 <1.11.0", + "from": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.2.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.10.2.tgz" }, "type-is": { "version": "1.6.11", - "from": "type-is@>=1.6.6 <1.7.0", + "from": "https://registry.npmjs.org/type-is/-/type-is-1.6.11.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.11.tgz", "dependencies": { "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0", + "from": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "mime-types": { "version": "2.1.9", - "from": "mime-types@>=2.1.6 <2.2.0", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "dependencies": { "mime-db": { "version": "1.21.0", - "from": "mime-db@>=1.21.0 <1.22.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz" } } @@ -396,19 +396,19 @@ }, "utils-merge": { "version": "1.0.0", - "from": "utils-merge@1.0.0", + "from": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" }, "vary": { "version": "1.0.1", - "from": "vary@>=1.0.1 <1.1.0", + "from": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.0.1.tgz" } } }, "fastly-purge": { "version": "1.0.1", - "from": "fastly-purge@>=1.0.1 <1.1.0", + "from": "https://registry.npmjs.org/fastly-purge/-/fastly-purge-1.0.1.tgz", "resolved": "https://registry.npmjs.org/fastly-purge/-/fastly-purge-1.0.1.tgz" }, "log4js": { @@ -418,96 +418,101 @@ "dependencies": { "async": { "version": "0.2.10", - "from": "async@>=0.2.0 <0.3.0", + "from": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz" }, "readable-stream": { "version": "1.0.33", - "from": "readable-stream@>=1.0.2 <1.1.0", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", "dependencies": { "core-util-is": { "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" }, "inherits": { "version": "2.0.1", - "from": "inherits@>=2.0.1 <2.1.0", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" } } }, "semver": { "version": "4.3.6", - "from": "semver@>=4.3.3 <4.4.0", + "from": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz" }, "underscore": { "version": "1.8.2", - "from": "underscore@1.8.2", + "from": "https://registry.npmjs.org/underscore/-/underscore-1.8.2.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.2.tgz" } } }, "lru-cache": { "version": "2.6.5", - "from": "lru-cache@2.6.5", + "from": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.6.5.tgz" }, "lzma": { "version": "1.3.7", - "from": "lzma@>=1.3.7 <1.4.0", + "from": "https://registry.npmjs.org/lzma/-/lzma-1.3.7.tgz", "resolved": "https://registry.npmjs.org/lzma/-/lzma-1.3.7.tgz" }, + "node-cartodb-query-tables": { + "version": "0.1.0", + "from": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master", + "resolved": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master" + }, "node-statsd": { "version": "0.0.7", - "from": "node-statsd@>=0.0.7 <0.1.0", + "from": "https://registry.npmjs.org/node-statsd/-/node-statsd-0.0.7.tgz", "resolved": "https://registry.npmjs.org/node-statsd/-/node-statsd-0.0.7.tgz" }, "queue-async": { "version": "1.0.7", - "from": "queue-async@>=1.0.7 <1.1.0", + "from": "https://registry.npmjs.org/queue-async/-/queue-async-1.0.7.tgz", "resolved": "https://registry.npmjs.org/queue-async/-/queue-async-1.0.7.tgz" }, "redis-mpool": { "version": "0.4.0", - "from": "redis-mpool@>=0.4.0 <0.5.0", + "from": "https://registry.npmjs.org/redis-mpool/-/redis-mpool-0.4.0.tgz", "resolved": "https://registry.npmjs.org/redis-mpool/-/redis-mpool-0.4.0.tgz", "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@>=2.1.1 <2.2.0", + "from": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "redis": { "version": "0.12.1", - "from": "redis@>=0.12.1 <0.13.0", + "from": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz", "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz" }, "hiredis": { "version": "0.1.17", - "from": "hiredis@>=0.1.17 <0.2.0", + "from": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", "resolved": "https://registry.npmjs.org/hiredis/-/hiredis-0.1.17.tgz", "dependencies": { "bindings": { "version": "1.2.1", - "from": "bindings@*", + "from": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz" }, "nan": { "version": "1.1.2", - "from": "nan@>=1.1.0 <1.2.0", + "from": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-1.1.2.tgz" } } @@ -516,47 +521,47 @@ }, "request": { "version": "2.62.0", - "from": "request@>=2.62.0 <2.63.0", + "from": "https://registry.npmjs.org/request/-/request-2.62.0.tgz", "resolved": "https://registry.npmjs.org/request/-/request-2.62.0.tgz", "dependencies": { "bl": { "version": "1.0.2", - "from": "bl@>=1.0.0 <1.1.0", + "from": "https://registry.npmjs.org/bl/-/bl-1.0.2.tgz", "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.2.tgz", "dependencies": { "readable-stream": { "version": "2.0.5", - "from": "readable-stream@>=2.0.5 <2.1.0", + "from": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.5.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.5.tgz", "dependencies": { "core-util-is": { "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", + "from": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "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", + "from": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, "isarray": { "version": "0.0.1", - "from": "isarray@0.0.1", + "from": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" }, "process-nextick-args": { "version": "1.0.6", - "from": "process-nextick-args@>=1.0.6 <1.1.0", + "from": "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.6.tgz" }, "string_decoder": { "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", + "from": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "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", + "from": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" } } @@ -565,247 +570,247 @@ }, "caseless": { "version": "0.11.0", - "from": "caseless@>=0.11.0 <0.12.0", + "from": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz" }, "extend": { "version": "3.0.0", - "from": "extend@>=3.0.0 <3.1.0", + "from": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" }, "forever-agent": { "version": "0.6.1", - "from": "forever-agent@>=0.6.0 <0.7.0", + "from": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" }, "form-data": { "version": "1.0.0-rc3", - "from": "form-data@>=1.0.0-rc1 <1.1.0", + "from": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz", "dependencies": { "async": { "version": "1.5.2", - "from": "async@>=1.4.0 <2.0.0", + "from": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz" } } }, "json-stringify-safe": { "version": "5.0.1", - "from": "json-stringify-safe@>=5.0.0 <5.1.0", + "from": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" }, "mime-types": { "version": "2.1.9", - "from": "mime-types@>=2.1.2 <2.2.0", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.9.tgz", "dependencies": { "mime-db": { "version": "1.21.0", - "from": "mime-db@>=1.21.0 <1.22.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.21.0.tgz" } } }, "node-uuid": { "version": "1.4.7", - "from": "node-uuid@>=1.4.0 <1.5.0", + "from": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz" }, "qs": { "version": "5.1.0", - "from": "qs@>=5.1.0 <5.2.0", + "from": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz" }, "tunnel-agent": { "version": "0.4.2", - "from": "tunnel-agent@>=0.4.0 <0.5.0", + "from": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz" }, "tough-cookie": { "version": "2.2.1", - "from": "tough-cookie@>=0.12.0", + "from": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.1.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.1.tgz" }, "http-signature": { "version": "0.11.0", - "from": "http-signature@>=0.11.0 <0.12.0", + "from": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz", "dependencies": { "assert-plus": { "version": "0.1.5", - "from": "assert-plus@>=0.1.5 <0.2.0", + "from": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz" }, "asn1": { "version": "0.1.11", - "from": "asn1@0.1.11", + "from": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" }, "ctype": { "version": "0.5.3", - "from": "ctype@0.5.3", + "from": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz" } } }, "oauth-sign": { "version": "0.8.1", - "from": "oauth-sign@>=0.8.0 <0.9.0", + "from": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.1.tgz", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.1.tgz" }, "hawk": { "version": "3.1.3", - "from": "hawk@>=3.1.0 <3.2.0", + "from": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "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", + "from": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" }, "boom": { "version": "2.10.1", - "from": "boom@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz" }, "cryptiles": { "version": "2.0.5", - "from": "cryptiles@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz" }, "sntp": { "version": "1.0.9", - "from": "sntp@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz" } } }, "aws-sign2": { "version": "0.5.0", - "from": "aws-sign2@>=0.5.0 <0.6.0", + "from": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" }, "stringstream": { "version": "0.0.5", - "from": "stringstream@>=0.0.4 <0.1.0", + "from": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz" }, "combined-stream": { "version": "1.0.5", - "from": "combined-stream@>=1.0.1 <1.1.0", + "from": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "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", + "from": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" } } }, "isstream": { "version": "0.1.2", - "from": "isstream@>=0.1.1 <0.2.0", + "from": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" }, "har-validator": { "version": "1.8.0", - "from": "har-validator@>=1.6.1 <2.0.0", + "from": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", "dependencies": { "bluebird": { "version": "2.10.2", - "from": "bluebird@>=2.9.30 <3.0.0", + "from": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz" }, "chalk": { "version": "1.1.1", - "from": "chalk@>=1.0.0 <2.0.0", + "from": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz", "dependencies": { "ansi-styles": { "version": "2.1.0", - "from": "ansi-styles@>=2.1.0 <3.0.0", + "from": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.1.0.tgz" }, "escape-string-regexp": { "version": "1.0.4", - "from": "escape-string-regexp@>=1.0.2 <2.0.0", + "from": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.4.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.4.tgz" }, "has-ansi": { "version": "2.0.0", - "from": "has-ansi@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "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", + "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz" } } }, "strip-ansi": { "version": "3.0.0", - "from": "strip-ansi@>=3.0.0 <4.0.0", + "from": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz", "dependencies": { "ansi-regex": { "version": "2.0.0", - "from": "ansi-regex@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", "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", + "from": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" } } }, "commander": { "version": "2.9.0", - "from": "commander@>=2.8.1 <3.0.0", + "from": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "dependencies": { "graceful-readlink": { "version": "1.0.1", - "from": "graceful-readlink@>=1.0.0", + "from": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz" } } }, "is-my-json-valid": { "version": "2.12.4", - "from": "is-my-json-valid@>=2.12.0 <3.0.0", + "from": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.4.tgz", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.12.4.tgz", "dependencies": { "generate-function": { "version": "2.0.0", - "from": "generate-function@>=2.0.0 <3.0.0", + "from": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", "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", + "from": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", "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", + "from": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz" } } }, "jsonpointer": { "version": "2.0.0", - "from": "jsonpointer@2.0.0", + "from": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-2.0.0.tgz" }, "xtend": { "version": "4.0.1", - "from": "xtend@>=4.0.0 <5.0.0", + "from": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } } @@ -816,22 +821,23 @@ }, "step": { "version": "0.0.6", - "from": "step@>=0.0.6 <0.1.0", + "from": "https://registry.npmjs.org/step/-/step-0.0.6.tgz", "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", + "from": "https://registry.npmjs.org/step-profiler/-/step-profiler-0.2.1.tgz", "resolved": "https://registry.npmjs.org/step-profiler/-/step-profiler-0.2.1.tgz" }, "underscore": { "version": "1.6.0", - "from": "underscore@>=1.6.0 <1.7.0", + "from": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz" }, "windshaft": { "version": "1.9.0", "from": "windshaft@1.9.0", + "resolved": "https://registry.npmjs.org/windshaft/-/windshaft-1.9.0.tgz", "dependencies": { "mapnik": { "version": "1.4.15-cdb6", @@ -840,17 +846,17 @@ "dependencies": { "nan": { "version": "1.2.0", - "from": "nan@>=1.2.0 <1.3.0", + "from": "https://registry.npmjs.org/nan/-/nan-1.2.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-1.2.0.tgz" }, "mapnik-vector-tile": { "version": "0.5.5", - "from": "mapnik-vector-tile@0.5.5", + "from": "https://registry.npmjs.org/mapnik-vector-tile/-/mapnik-vector-tile-0.5.5.tgz", "resolved": "https://registry.npmjs.org/mapnik-vector-tile/-/mapnik-vector-tile-0.5.5.tgz" }, "node-pre-gyp": { "version": "0.5.25", - "from": "node-pre-gyp@0.5.25", + "from": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.5.25.tgz", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.5.25.tgz", "dependencies": { "nopt": { @@ -1220,7 +1226,7 @@ }, "grainstore": { "version": "1.1.1", - "from": "grainstore@1.1.1", + "from": "https://registry.npmjs.org/grainstore/-/grainstore-1.1.1.tgz", "resolved": "https://registry.npmjs.org/grainstore/-/grainstore-1.1.1.tgz", "dependencies": { "carto": { @@ -1230,39 +1236,39 @@ "dependencies": { "underscore": { "version": "1.4.4", - "from": "underscore@>=1.4.3 <1.5.0", + "from": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz" }, "mapnik-reference": { "version": "5.0.9", - "from": "mapnik-reference@>=5.0.7 <5.1.0", + "from": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-5.0.9.tgz", "resolved": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-5.0.9.tgz" }, "xml2js": { "version": "0.2.8", - "from": "xml2js@>=0.2.4 <0.3.0", + "from": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", "dependencies": { "sax": { "version": "0.5.8", - "from": "sax@>=0.5.0 <0.6.0", + "from": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz" } } }, "optimist": { "version": "0.6.1", - "from": "optimist@>=0.6.0 <0.7.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.3", - "from": "wordwrap@>=0.0.2 <0.1.0", + "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@>=0.0.1 <0.1.0", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } @@ -1271,22 +1277,22 @@ }, "millstone": { "version": "0.6.16", - "from": "millstone@0.6.16", + "from": "https://registry.npmjs.org/millstone/-/millstone-0.6.16.tgz", "resolved": "https://registry.npmjs.org/millstone/-/millstone-0.6.16.tgz", "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@>=2.1.1 <2.2.0", + "from": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "srs": { "version": "0.4.9", - "from": "srs@>=0.4.6 <0.5.0", + "from": "https://registry.npmjs.org/srs/-/srs-0.4.9.tgz", "resolved": "https://registry.npmjs.org/srs/-/srs-0.4.9.tgz", "dependencies": { "nan": { "version": "1.8.4", - "from": "nan@>=1.8.4 <1.9.0", + "from": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" }, "node-pre-gyp": { @@ -2013,12 +2019,12 @@ }, "zipfile": { "version": "0.5.9", - "from": "zipfile@>=0.5.5 <0.6.0", + "from": "https://registry.npmjs.org/zipfile/-/zipfile-0.5.9.tgz", "resolved": "https://registry.npmjs.org/zipfile/-/zipfile-0.5.9.tgz", "dependencies": { "nan": { "version": "2.1.0", - "from": "nan@>=2.1.0 <2.2.0", + "from": "https://registry.npmjs.org/nan/-/nan-2.1.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.1.0.tgz" }, "node-pre-gyp": { @@ -2803,12 +2809,12 @@ }, "sqlite3": { "version": "3.1.1", - "from": "sqlite3@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0", + "from": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.1.tgz", "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.1.tgz", "dependencies": { "nan": { "version": "2.1.0", - "from": "nan@>=2.1.0 <2.2.0", + "from": "https://registry.npmjs.org/nan/-/nan-2.1.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.1.0.tgz" }, "node-pre-gyp": { @@ -3535,34 +3541,34 @@ }, "mime": { "version": "1.2.11", - "from": "mime@>=1.2.11 <1.3.0", + "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" }, "mkdirp": { "version": "0.5.1", - "from": "mkdirp@>=0.5.0 <0.6.0", + "from": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "dependencies": { "minimist": { "version": "0.0.8", - "from": "minimist@0.0.8", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" } } }, "optimist": { "version": "0.6.1", - "from": "optimist@>=0.6.1 <0.7.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.3", - "from": "wordwrap@>=0.0.2 <0.1.0", + "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@>=0.0.1 <0.1.0", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } @@ -3573,22 +3579,22 @@ }, "tilelive": { "version": "4.5.3", - "from": "tilelive@>=4.5.3 <4.6.0", + "from": "https://registry.npmjs.org/tilelive/-/tilelive-4.5.3.tgz", "resolved": "https://registry.npmjs.org/tilelive/-/tilelive-4.5.3.tgz", "dependencies": { "optimist": { "version": "0.6.1", - "from": "optimist@>=0.6.0 <0.7.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.3", - "from": "wordwrap@>=0.0.2 <0.1.0", + "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@>=0.0.1 <0.1.0", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } @@ -3602,12 +3608,12 @@ "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@>=2.1.1 <2.2.0", + "from": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "mime": { "version": "1.2.11", - "from": "mime@>=1.2.11 <1.3.0", + "from": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" } } @@ -3624,12 +3630,12 @@ "dependencies": { "generic-pool": { "version": "2.1.1", - "from": "generic-pool@>=2.1.1 <2.2.0", + "from": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.1.1.tgz" }, "xtend": { "version": "3.0.0", - "from": "xtend@>=3.0.0 <3.1.0", + "from": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz" } } @@ -3643,14 +3649,14 @@ "dependencies": { "nan": { "version": "1.9.0", - "from": "nan@>=1.8.4 <2.0.0", + "from": "https://registry.npmjs.org/nan/-/nan-1.9.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-1.9.0.tgz" } } }, "semver": { "version": "5.0.3", - "from": "semver@>=5.0.3 <5.1.0", + "from": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz" }, "carto": { @@ -3660,22 +3666,22 @@ "dependencies": { "mapnik-reference": { "version": "6.0.5", - "from": "mapnik-reference@>=6.0.2 <6.1.0", + "from": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-6.0.5.tgz", "resolved": "https://registry.npmjs.org/mapnik-reference/-/mapnik-reference-6.0.5.tgz" }, "optimist": { "version": "0.6.1", - "from": "optimist@>=0.6.0 <0.7.0", + "from": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "dependencies": { "wordwrap": { "version": "0.0.3", - "from": "wordwrap@>=0.0.2 <0.1.0", + "from": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz" }, "minimist": { "version": "0.0.10", - "from": "minimist@>=0.0.1 <0.1.0", + "from": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" } } @@ -3684,22 +3690,22 @@ }, "cartodb-psql": { "version": "0.6.1", - "from": "cartodb-psql@>=0.6.1 <0.7.0", + "from": "https://registry.npmjs.org/cartodb-psql/-/cartodb-psql-0.6.1.tgz", "resolved": "https://registry.npmjs.org/cartodb-psql/-/cartodb-psql-0.6.1.tgz", "dependencies": { "pg": { "version": "2.6.2-cdb3", - "from": "git://github.com/CartoDB/node-postgres.git#2.6.2-cdb3", + "from": "git://github.com/CartoDB/node-postgres.git#069c5296d1a093077feff21719641bb9e71fc50e", "resolved": "git://github.com/CartoDB/node-postgres.git#069c5296d1a093077feff21719641bb9e71fc50e", "dependencies": { "generic-pool": { "version": "2.0.3", - "from": "generic-pool@2.0.3", + "from": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.3.tgz", "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.3.tgz" }, "buffer-writer": { "version": "1.0.0", - "from": "buffer-writer@1.0.0", + "from": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.0.tgz" } } @@ -3708,7 +3714,7 @@ }, "torque.js": { "version": "2.11.4", - "from": "torque.js@>=2.11.0 <2.12.0", + "from": "https://registry.npmjs.org/torque.js/-/torque.js-2.11.4.tgz", "resolved": "https://registry.npmjs.org/torque.js/-/torque.js-2.11.4.tgz" }, "abaculus": { @@ -3718,7 +3724,7 @@ }, "sphericalmercator": { "version": "1.0.3", - "from": "sphericalmercator@1.0.3", + "from": "https://registry.npmjs.org/sphericalmercator/-/sphericalmercator-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sphericalmercator/-/sphericalmercator-1.0.3.tgz" } } From ba8e3d419e0327e6c74ac47e84233335357b482b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 22 Feb 2016 15:09:09 +0100 Subject: [PATCH 13/22] Fix package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d9877bb2..109c079a 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "redis-mpool": "~0.4.0", "lru-cache": "2.6.5", "lzma": "~1.3.7", - "log4js": "https://github.com/CartoDB/log4js-node/tarball/cdb" + "log4js": "https://github.com/CartoDB/log4js-node/tarball/cdb", "node-cartodb-query-tables": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master" }, "devDependencies": { From e67f7b0d0ec77dc34f5cec05873121ab55e736c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 22 Feb 2016 15:26:06 +0100 Subject: [PATCH 14/22] Drop old QueryTablesApi --- lib/cartodb/cache/named_map_provider_cache.js | 4 +- lib/cartodb/controllers/layergroup.js | 4 +- lib/cartodb/controllers/map.js | 17 +----- .../models/mapconfig/named_map_provider.js | 15 ++++- lib/cartodb/server.js | 6 +- test/acceptance/templates.js | 2 +- test/integration/overviews-metadata-api.js | 4 +- test/integration/query-tables-api.js | 56 ------------------- 8 files changed, 18 insertions(+), 90 deletions(-) delete mode 100644 test/integration/query-tables-api.js diff --git a/lib/cartodb/cache/named_map_provider_cache.js b/lib/cartodb/cache/named_map_provider_cache.js index 21c33142..0048cb63 100644 --- a/lib/cartodb/cache/named_map_provider_cache.js +++ b/lib/cartodb/cache/named_map_provider_cache.js @@ -7,11 +7,10 @@ var queue = require('queue-async'); var LruCache = require("lru-cache"); -function NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi, queryTablesApi) { +function NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi) { this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.userLimitsApi = userLimitsApi; - this.queryTablesApi = queryTablesApi; this.namedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps); @@ -30,7 +29,6 @@ NamedMapProviderCache.prototype.get = function(user, templateId, config, authTok this.templateMaps, this.pgConnection, this.userLimitsApi, - this.queryTablesApi, this.namedLayersAdapter, user, templateId, diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index 6d393b27..7a450bd8 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -21,12 +21,11 @@ var QueryTables = require('node-cartodb-query-tables'); * @param {WidgetBackend} widgetBackend * @param {SurrogateKeysCache} surrogateKeysCache * @param {UserLimitsApi} userLimitsApi - * @param {QueryTablesApi} queryTablesApi * @param {LayergroupAffectedTables} layergroupAffectedTables * @constructor */ function LayergroupController(authApi, pgConnection, mapStore, tileBackend, previewBackend, attributesBackend, - widgetBackend, surrogateKeysCache, userLimitsApi, queryTablesApi, layergroupAffectedTables) { + widgetBackend, surrogateKeysCache, userLimitsApi, layergroupAffectedTables) { BaseController.call(this, authApi, pgConnection); this.pgConnection = pgConnection; @@ -37,7 +36,6 @@ function LayergroupController(authApi, pgConnection, mapStore, tileBackend, prev this.widgetBackend = widgetBackend; this.surrogateKeysCache = surrogateKeysCache; this.userLimitsApi = userLimitsApi; - this.queryTablesApi = queryTablesApi; this.layergroupAffectedTables = layergroupAffectedTables; } diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index 87fa85ea..21ea9917 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -26,7 +26,6 @@ var MapConfigOverviewsAdapter = require('../models/mapconfig_overviews_adapter') * @param {TemplateMaps} templateMaps * @param {MapBackend} mapBackend * @param metadataBackend - * @param {QueryTablesApi} queryTablesApi * @param {OverviewsMetadataApi} overviewsMetadataApi * @param {SurrogateKeysCache} surrogateKeysCache * @param {UserLimitsApi} userLimitsApi @@ -34,7 +33,7 @@ var MapConfigOverviewsAdapter = require('../models/mapconfig_overviews_adapter') * @constructor */ function MapController(authApi, pgConnection, templateMaps, mapBackend, metadataBackend, - queryTablesApi, overviewsMetadataApi, + overviewsMetadataApi, surrogateKeysCache, userLimitsApi, layergroupAffectedTables) { BaseController.call(this, authApi, pgConnection); @@ -43,7 +42,6 @@ function MapController(authApi, pgConnection, templateMaps, mapBackend, metadata this.templateMaps = templateMaps; this.mapBackend = mapBackend; this.metadataBackend = metadataBackend; - this.queryTablesApi = queryTablesApi; this.overviewsMetadataApi = overviewsMetadataApi; this.surrogateKeysCache = surrogateKeysCache; this.userLimitsApi = userLimitsApi; @@ -214,7 +212,6 @@ MapController.prototype.instantiateTemplate = function(req, res, prepareParamsFn self.templateMaps, self.pgConnection, self.userLimitsApi, - self.queryTablesApi, self.namedLayersAdapter, cdbuser, req.params.template_id, @@ -319,18 +316,6 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la }, function getAffectedTablesAndLastUpdatedTime(err) { assert.ifError(err); - // if (hasCache) { - // var next = this; - // var affectedTables = self.layergroupAffectedTables.get(dbName, layergroupId); - // self.queryTablesApi.getLastUpdatedTime(username, affectedTables, function(err, lastUpdatedTime) { - // if (err) { - // return next(err); - // } - // return next(null, { affectedTables: affectedTables, lastUpdatedTime: lastUpdatedTime }); - // }); - // } else { - // self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(username, sql, this); - //} step( function getConnection() { self.pgConnection.getConnection(username, this); diff --git a/lib/cartodb/models/mapconfig/named_map_provider.js b/lib/cartodb/models/mapconfig/named_map_provider.js index 0c86ce29..2d88c436 100644 --- a/lib/cartodb/models/mapconfig/named_map_provider.js +++ b/lib/cartodb/models/mapconfig/named_map_provider.js @@ -5,17 +5,17 @@ var dot = require('dot'); var step = require('step'); var MapConfig = require('windshaft').model.MapConfig; var templateName = require('../../backends/template_maps').templateName; +var QueryTables = require('node-cartodb-query-tables'); /** * @constructor * @type {NamedMapMapConfigProvider} */ -function NamedMapMapConfigProvider(templateMaps, pgConnection, userLimitsApi, queryTablesApi, namedLayersAdapter, +function NamedMapMapConfigProvider(templateMaps, pgConnection, userLimitsApi, namedLayersAdapter, owner, templateId, config, authToken, params) { this.templateMaps = templateMaps; this.pgConnection = pgConnection; this.userLimitsApi = userLimitsApi; - this.queryTablesApi = queryTablesApi; this.namedLayersAdapter = namedLayersAdapter; this.owner = owner; @@ -256,7 +256,16 @@ NamedMapMapConfigProvider.prototype.getAffectedTablesAndLastUpdatedTime = functi }, function getAffectedTables(err, sql) { assert.ifError(err); - self.queryTablesApi.getAffectedTablesAndLastUpdatedTime(self.owner, sql, this); + step( + function getConnection() { + self.pgConnection.getConnection(self.owner, this); + }, + function getAffectedTables(err, connection) { + assert.ifError(err); + QueryTables.getAffectedTablesFromQuery(connection, sql, this); + }, + this + ); }, function finish(err, result) { self.affectedTablesAndLastUpdate = result; diff --git a/lib/cartodb/server.js b/lib/cartodb/server.js index 9f9d9f69..39884850 100644 --- a/lib/cartodb/server.js +++ b/lib/cartodb/server.js @@ -19,7 +19,6 @@ var windshaft = require('windshaft'); var mapnik = windshaft.mapnik; var TemplateMaps = require('./backends/template_maps.js'); -var QueryTablesApi = require('./api/query_tables_api'); var OverviewsMetadataApi = require('./api/overviews_metadata_api'); var UserLimitsApi = require('./api/user_limits_api'); var AuthApi = require('./api/auth_api'); @@ -52,7 +51,6 @@ module.exports = function(serverOptions) { var metadataBackend = cartodbRedis({pool: redisPool}); var pgConnection = new PgConnection(metadataBackend); var pgQueryRunner = new PgQueryRunner(pgConnection); - var queryTablesApi = new QueryTablesApi(pgQueryRunner); var overviewsMetadataApi = new OverviewsMetadataApi(pgQueryRunner); var userLimitsApi = new UserLimitsApi(metadataBackend, { limits: { @@ -142,7 +140,7 @@ module.exports = function(serverOptions) { var layergroupAffectedTablesCache = new LayergroupAffectedTablesCache(); app.layergroupAffectedTablesCache = layergroupAffectedTablesCache; - var namedMapProviderCache = new NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi, queryTablesApi); + var namedMapProviderCache = new NamedMapProviderCache(templateMaps, pgConnection, userLimitsApi); ['update', 'delete'].forEach(function(eventType) { templateMaps.on(eventType, namedMapProviderCache.invalidate.bind(namedMapProviderCache)); }); @@ -166,7 +164,6 @@ module.exports = function(serverOptions) { new windshaft.backend.Widget(), surrogateKeysCache, userLimitsApi, - queryTablesApi, layergroupAffectedTablesCache ).register(app); @@ -176,7 +173,6 @@ module.exports = function(serverOptions) { templateMaps, mapBackend, metadataBackend, - queryTablesApi, overviewsMetadataApi, surrogateKeysCache, userLimitsApi, diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index 4b53e0a6..cf2624c4 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -1477,7 +1477,7 @@ describe('template_api', function() { // See https://github.com/CartoDB/Windshaft-cartodb/issues/176 helper.checkCache(res); var expectedSurrogateKey = [ - new QueryTables.DatabaseTableEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', + new QueryTables.DatabaseTablesEntry([{dbname: 'test_windshaft_cartodb_user_1_db', schema_name: 'public', table_name: 'test_table_private_1'}]).key(), new NamedMapsCacheEntry('localhost', template_acceptance_open.name).key() ].join(' '); diff --git a/test/integration/overviews-metadata-api.js b/test/integration/overviews-metadata-api.js index 6c054d1e..f1182a6c 100644 --- a/test/integration/overviews-metadata-api.js +++ b/test/integration/overviews-metadata-api.js @@ -7,20 +7,18 @@ var cartodbRedis = require('cartodb-redis'); var PgConnection = require('../../lib/cartodb/backends/pg_connection'); var PgQueryRunner = require('../../lib/cartodb/backends/pg_query_runner'); -var QueryTablesApi = require('../../lib/cartodb/api/query_tables_api'); var OverviewsMetadataApi = require('../../lib/cartodb/api/overviews_metadata_api'); describe('OverviewsMetadataApi', function() { - var queryTablesApi, overviewsMetadataApi; + var overviewsMetadataApi; before(function() { var redisPool = new RedisPool(global.environment.redis); var metadataBackend = cartodbRedis({pool: redisPool}); var pgConnection = new PgConnection(metadataBackend); var pgQueryRunner = new PgQueryRunner(pgConnection); - queryTablesApi = new QueryTablesApi(pgQueryRunner); overviewsMetadataApi = new OverviewsMetadataApi(pgQueryRunner); }); diff --git a/test/integration/query-tables-api.js b/test/integration/query-tables-api.js deleted file mode 100644 index 93ca0a07..00000000 --- a/test/integration/query-tables-api.js +++ /dev/null @@ -1,56 +0,0 @@ -require('../support/test_helper'); - -var assert = require('assert'); - -var RedisPool = require('redis-mpool'); -var cartodbRedis = require('cartodb-redis'); - -var PgConnection = require('../../lib/cartodb/backends/pg_connection'); -var PgQueryRunner = require('../../lib/cartodb/backends/pg_query_runner'); -var QueryTablesApi = require('../../lib/cartodb/api/query_tables_api'); - - -describe('QueryTablesApi', function() { - - var queryTablesApi; - - before(function() { - var redisPool = new RedisPool(global.environment.redis); - var metadataBackend = cartodbRedis({pool: redisPool}); - var pgConnection = new PgConnection(metadataBackend); - var pgQueryRunner = new PgQueryRunner(pgConnection); - queryTablesApi = new QueryTablesApi(pgQueryRunner); - }); - - // Check test/support/sql/windshaft.test.sql to understand where the values come from. - - it('should return an object with affected tables array and last updated time', function(done) { - var query = 'select * from test_table'; - queryTablesApi.getAffectedTablesAndLastUpdatedTime('localhost', query, function(err, result) { - assert.ok(!err, err); - assert.deepEqual(result, { - affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", - "table_name": 'test_table', updated_at: new Date(1234567890123)}], - lastUpdatedTime: 1234567890123 - }); - - done(); - }); - }); - - it('should work with private tables', function(done) { - var query = 'select * from test_table_private_1'; - queryTablesApi.getAffectedTablesAndLastUpdatedTime('localhost', query, function(err, result) { - assert.ok(!err, err); - - assert.deepEqual(result, { - affectedTables: [{dbname: "test_windshaft_cartodb_user_1_db", schema_name: "public", - "table_name": 'test_table_private_1', updated_at: new Date(1234567890123)}], - lastUpdatedTime: 1234567890123 - }); - - done(); - }); - }); - -}); From 850f1cb7f4c28c06214a2fea3f386a2b29f275e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 22 Feb 2016 15:28:14 +0100 Subject: [PATCH 15/22] Remove stray spaces --- test/acceptance/multilayer_server.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 2c3801e0..2f914b0f 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -310,7 +310,6 @@ describe('tests from old api translated to multilayer', function() { it("creates layergroup fails when postgresql queries fail to figure affected tables in query", function(done) { - var runQueryFn = PgQueryRunner.prototype.run; PgQueryRunner.prototype.run = function(username, query, callback) { return callback(new Error('fake error message'), []); @@ -345,7 +344,6 @@ describe('tests from old api translated to multilayer', function() { }); it("tile requests works when postgresql queries fail to figure affected tables in query", function(done) { - var layergroup = singleLayergroupConfig('select * from gadm4', '#gadm4 { marker-fill: red; }'); assert.response(server, { From e491c0b82540f55b814dfad9430ba63a36580d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Mon, 22 Feb 2016 19:11:54 +0100 Subject: [PATCH 16/22] Rename node-cartodb-query-tables to cartodb-query-tables --- lib/cartodb/controllers/layergroup.js | 2 +- lib/cartodb/controllers/map.js | 2 +- lib/cartodb/models/mapconfig/named_map_provider.js | 2 +- npm-shrinkwrap.json | 2 +- package.json | 2 +- test/acceptance/multilayer.js | 2 +- test/acceptance/multilayer_server.js | 2 +- test/acceptance/templates.js | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index 7a450bd8..94f2903e 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -9,7 +9,7 @@ var userMiddleware = require('../middleware/user'); var MapStoreMapConfigProvider = require('../models/mapconfig/map_store_provider'); -var QueryTables = require('node-cartodb-query-tables'); +var QueryTables = require('cartodb-query-tables'); /** * @param {AuthApi} authApi diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index 21ea9917..9115646f 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -2,7 +2,7 @@ var _ = require('underscore'); var assert = require('assert'); var step = require('step'); var windshaft = require('windshaft'); -var QueryTables = require('node-cartodb-query-tables'); +var QueryTables = require('cartodb-query-tables'); var util = require('util'); var BaseController = require('./base'); diff --git a/lib/cartodb/models/mapconfig/named_map_provider.js b/lib/cartodb/models/mapconfig/named_map_provider.js index 2d88c436..3e09b466 100644 --- a/lib/cartodb/models/mapconfig/named_map_provider.js +++ b/lib/cartodb/models/mapconfig/named_map_provider.js @@ -5,7 +5,7 @@ var dot = require('dot'); var step = require('step'); var MapConfig = require('windshaft').model.MapConfig; var templateName = require('../../backends/template_maps').templateName; -var QueryTables = require('node-cartodb-query-tables'); +var QueryTables = require('cartodb-query-tables'); /** * @constructor diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index f8f38d69..4ffc51f5 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -470,7 +470,7 @@ "from": "lzma@>=1.3.7 <1.4.0", "resolved": "https://registry.npmjs.org/lzma/-/lzma-1.3.7.tgz" }, - "node-cartodb-query-tables": { + "cartodb-query-tables": { "version": "0.1.0", "from": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master", "resolved": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master" diff --git a/package.json b/package.json index 2f731440..46f11788 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "lru-cache": "2.6.5", "lzma": "~1.3.7", "log4js": "https://github.com/CartoDB/log4js-node/tarball/cdb", - "node-cartodb-query-tables": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master" + "cartodb-query-tables": "https://github.com/CartoDB/node-cartodb-query-tables/tarball/master" }, "devDependencies": { "istanbul": "~0.3.6", diff --git a/test/acceptance/multilayer.js b/test/acceptance/multilayer.js index 202fb259..a774081d 100644 --- a/test/acceptance/multilayer.js +++ b/test/acceptance/multilayer.js @@ -18,7 +18,7 @@ var serverOptions = require('../../lib/cartodb/server_options'); var server = new CartodbWindshaft(serverOptions); server.setMaxListeners(0); -var QueryTables = require('node-cartodb-query-tables'); +var QueryTables = require('cartodb-query-tables'); ['/api/v1/map', '/user/localhost/api/v1/map'].forEach(function(layergroup_url) { diff --git a/test/acceptance/multilayer_server.js b/test/acceptance/multilayer_server.js index 2f914b0f..67eaa74b 100644 --- a/test/acceptance/multilayer_server.js +++ b/test/acceptance/multilayer_server.js @@ -7,7 +7,7 @@ var _ = require('underscore'); var LayergroupToken = require('../../lib/cartodb/models/layergroup_token'); var PgQueryRunner = require('../../lib/cartodb/backends/pg_query_runner'); -var QueryTables = require('node-cartodb-query-tables'); +var QueryTables = require('cartodb-query-tables'); var CartodbWindshaft = require('../../lib/cartodb/server'); var serverOptions = require('../../lib/cartodb/server_options'); var server = new CartodbWindshaft(serverOptions); diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index cf2624c4..6326381d 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -3,7 +3,7 @@ var _ = require('underscore'); var redis = require('redis'); var step = require('step'); var strftime = require('strftime'); -var QueryTables = require('node-cartodb-query-tables'); +var QueryTables = require('cartodb-query-tables'); var NamedMapsCacheEntry = require('../../lib/cartodb/cache/model/named_maps_entry'); var redis_stats_db = 5; From 0036056c071bc3f35d15373ab9bb803adadc9c8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Mart=C3=ADnez?= Date: Tue, 23 Feb 2016 19:31:38 +0100 Subject: [PATCH 17/22] Reopen PR From 7c154dd40577b7448b129c67861fbd0ac894a2f4 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 3 Mar 2016 19:01:21 +0100 Subject: [PATCH 18/22] Add notes about why we keep feeding the layergroupAffectedTables cache --- lib/cartodb/controllers/map.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index 020a5744..e4f5db46 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -336,6 +336,7 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la req.profiler.done('queryTablesAndLastUpdated'); } assert.ifError(err); + // feed affected tables cache so it can be reused from, for instance, layergroup controller self.layergroupAffectedTables.set(dbName, layergroupId, result); // last update for layergroup cache buster From d9f6df98150840f4d995a8e24239d4b6c5b0466e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 3 Mar 2016 19:01:58 +0100 Subject: [PATCH 19/22] Remove nested step call --- lib/cartodb/controllers/map.js | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/cartodb/controllers/map.js b/lib/cartodb/controllers/map.js index e4f5db46..ff164e9c 100644 --- a/lib/cartodb/controllers/map.js +++ b/lib/cartodb/controllers/map.js @@ -315,21 +315,12 @@ MapController.prototype.afterLayergroupCreate = function(req, res, mapconfig, la var layergroupId = layergroup.layergroupid; step( - function checkCachedAffectedTables() { - return self.layergroupAffectedTables.hasAffectedTables(dbName, layergroupId); + function getPgConnection() { + self.pgConnection.getConnection(username, this); }, - function getAffectedTablesAndLastUpdatedTime(err) { + function getAffectedTablesAndLastUpdatedTime(err, connection) { assert.ifError(err); - step( - function getConnection() { - self.pgConnection.getConnection(username, this); - }, - function getAffectedTables(err, connection) { - assert.ifError(err); - QueryTables.getAffectedTablesFromQuery(connection, sql, this); - }, - this - ); + QueryTables.getAffectedTablesFromQuery(connection, sql, this); }, function handleAffectedTablesAndLastUpdatedTime(err, result) { if (req.profiler) { From baf87e90d7ea68fa4a4bde1b0f72c658ac876167 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 3 Mar 2016 19:25:32 +0100 Subject: [PATCH 20/22] Just callback as result is handled internally --- lib/cartodb/controllers/layergroup.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/cartodb/controllers/layergroup.js b/lib/cartodb/controllers/layergroup.js index 94f2903e..b6b4d640 100644 --- a/lib/cartodb/controllers/layergroup.js +++ b/lib/cartodb/controllers/layergroup.js @@ -383,12 +383,6 @@ LayergroupController.prototype.getAffectedTables = function(user, dbName, layerg return tables; }, - function finish(err, tables) { - if(tables === undefined){ - callback(err); - }else{ - callback(err, tables); - } - } + callback ); }; From 52cb224225548cef81b689f982a021ae4c61f809 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 3 Mar 2016 19:27:44 +0100 Subject: [PATCH 21/22] Add integration test with QueryTables module This tests should be better placed at cartodb-query-tables repo but it's easier to do it here. Lazy dev. --- test/integration/query-tables.js | 71 ++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 test/integration/query-tables.js diff --git a/test/integration/query-tables.js b/test/integration/query-tables.js new file mode 100644 index 00000000..59d498cc --- /dev/null +++ b/test/integration/query-tables.js @@ -0,0 +1,71 @@ +require('../support/test_helper'); + +var assert = require('assert'); + +var RedisPool = require('redis-mpool'); +var cartodbRedis = require('cartodb-redis'); + +var PgConnection = require('../../lib/cartodb/backends/pg_connection'); + +var QueryTables = require('cartodb-query-tables'); + + +describe('QueryTablesApi', function() { + + var connection; + + before(function(done) { + var redisPool = new RedisPool(global.environment.redis); + var metadataBackend = cartodbRedis({pool: redisPool}); + var pgConnection = new PgConnection(metadataBackend); + pgConnection.getConnection('localhost', function(err, pgConnection) { + if (err) { + return done(err); + } + connection = pgConnection; + + return done(); + }); + }); + + // Check test/support/sql/windshaft.test.sql to understand where the values come from. + + it('should return an object with affected tables array and last updated time', function(done) { + var query = 'select * from test_table'; + QueryTables.getAffectedTablesFromQuery(connection, query, function(err, result) { + assert.ok(!err, err); + + assert.equal(result.getLastUpdatedAt(), 1234567890123); + + assert.equal(result.tables.length, 1); + assert.deepEqual(result.tables[0], { + dbname: 'test_windshaft_cartodb_user_1_db', + schema_name: 'public', + table_name: 'test_table', + updated_at: new Date(1234567890123) + }); + + done(); + }); + }); + + it('should work with private tables', function(done) { + var query = 'select * from test_table_private_1'; + QueryTables.getAffectedTablesFromQuery(connection, query, function(err, result) { + assert.ok(!err, err); + + assert.equal(result.getLastUpdatedAt(), 1234567890123); + + assert.equal(result.tables.length, 1); + assert.deepEqual(result.tables[0], { + dbname: 'test_windshaft_cartodb_user_1_db', + schema_name: 'public', + table_name: 'test_table_private_1', + updated_at: new Date(1234567890123) + }); + + done(); + }); + }); + +}); \ No newline at end of file From df0597f12ac742e4d0f090ef0f583c9b700e9d92 Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Thu, 3 Mar 2016 19:29:42 +0100 Subject: [PATCH 22/22] Rename suite --- test/integration/query-tables.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/query-tables.js b/test/integration/query-tables.js index 59d498cc..9cd76000 100644 --- a/test/integration/query-tables.js +++ b/test/integration/query-tables.js @@ -10,7 +10,7 @@ var PgConnection = require('../../lib/cartodb/backends/pg_connection'); var QueryTables = require('cartodb-query-tables'); -describe('QueryTablesApi', function() { +describe('QueryTables', function() { var connection;