Windshaft-cartodb/lib/backends/dataview.js

223 lines
7.6 KiB
JavaScript
Raw Normal View History

'use strict';
var _ = require('underscore');
var PSQL = require('cartodb-psql');
var BBoxFilter = require('../models/filter/bbox');
2019-12-03 01:36:41 +08:00
const CircleFilter = require('../models/filter/circle');
2019-12-03 17:58:55 +08:00
const PolygonFilter = require('../models/filter/polygon');
var DataviewFactory = require('../models/dataview/factory');
var DataviewFactoryWithOverviews = require('../models/dataview/overviews/factory');
2018-03-23 00:53:24 +08:00
const dbParamsFromReqParams = require('../utils/database-params');
var OverviewsQueryRewriter = require('../utils/overviews-query-rewriter');
var overviewsQueryRewriter = new OverviewsQueryRewriter({
zoom_level: 'cartodb.CDB_ZoomFromScale(!scale_denominator!)'
});
var dot = require('dot');
dot.templateSettings.strip = false;
2019-10-22 01:07:24 +08:00
function DataviewBackend (analysisBackend) {
this.analysisBackend = analysisBackend;
}
module.exports = DataviewBackend;
2017-10-09 22:29:35 +08:00
DataviewBackend.prototype.getDataview = function (mapConfigProvider, user, params, callback) {
2018-07-30 21:19:53 +08:00
const dataviewName = params.dataviewName;
2017-10-09 22:29:35 +08:00
2018-07-30 21:19:53 +08:00
mapConfigProvider.getMapConfig(function (err, mapConfig) {
if (err) {
return callback(err);
}
2018-07-30 21:19:53 +08:00
var dataviewDefinition = getDataviewDefinition(mapConfig.obj(), dataviewName);
if (!dataviewDefinition) {
2018-08-16 18:16:20 +08:00
const error = new Error(`Dataview '${dataviewName}' does not exist`);
2018-07-30 21:59:43 +08:00
error.type = 'dataview';
error.http_status = 400;
return callback(error);
2018-07-30 21:19:53 +08:00
}
2018-07-31 19:26:38 +08:00
if (!validFilterParams(params)) {
2018-07-30 22:00:30 +08:00
const error = new Error('Both own_filter and no_filters cannot be sent in the same request');
error.type = 'dataview';
error.http_status = 400;
2018-07-31 18:15:20 +08:00
return callback(error);
2018-07-30 21:19:53 +08:00
}
2018-03-23 00:53:24 +08:00
2018-07-31 19:33:33 +08:00
var pg;
var overrideParams;
var dataview;
2018-07-30 21:52:04 +08:00
try {
2018-07-31 19:33:33 +08:00
pg = new PSQL(dbParamsFromReqParams(params));
var query = getQueryWithFilters(dataviewDefinition, params);
var queryRewriteData = getQueryRewriteData(mapConfig, dataviewDefinition, params);
var dataviewFactory = DataviewFactoryWithOverviews.getFactory(overviewsQueryRewriter, queryRewriteData, {
bbox: params.bbox
});
dataview = dataviewFactory.getDataview(query, dataviewDefinition);
2018-07-31 19:26:38 +08:00
var ownFilter = +params.own_filter;
2018-07-30 21:52:04 +08:00
overrideParams = getOverrideParams(params, !!ownFilter);
} catch (error) {
return callback(error);
}
dataview.getResult(pg, overrideParams, function (err, dataviewResult, stats = {}) {
2018-07-30 21:19:53 +08:00
if (err) {
return callback(err);
}
return callback(null, dataviewResult, stats);
2018-07-30 21:19:53 +08:00
});
});
};
2018-07-31 19:26:38 +08:00
function validFilterParams (params) {
var ownFilter = +params.own_filter;
var noFilters = +params.no_filters;
return !(Number.isFinite(ownFilter) && Number.isFinite(noFilters));
}
function getQueryWithFilters (dataviewDefinition, params) {
var ownFilter = +params.own_filter;
var noFilters = +params.no_filters;
var query = getDataviewQuery(dataviewDefinition, ownFilter, noFilters);
if (params.bbox) {
2019-10-22 01:07:24 +08:00
var bboxFilter = new BBoxFilter({ column: 'the_geom_webmercator', srid: 3857 }, { bbox: params.bbox });
2018-07-31 19:26:38 +08:00
query = bboxFilter.sql(query);
2019-12-03 01:36:41 +08:00
} else if (params.circle) {
const circleFilter = new CircleFilter({ column: 'the_geom_webmercator', srid: 3857 }, { circle: params.circle });
query = circleFilter.sql(query);
2019-12-03 17:58:55 +08:00
} else if (params.polygon) {
const polygonFilter = new PolygonFilter({ column: 'the_geom_webmercator', srid: 3857 }, { polygon: params.polygon });
query = polygonFilter.sql(query);
2018-07-31 19:26:38 +08:00
}
return query;
}
2019-10-22 01:07:24 +08:00
function getDataviewQuery (dataviewDefinition, ownFilter, noFilters) {
2017-12-12 18:54:09 +08:00
if (noFilters) {
return dataviewDefinition.sql.no_filters;
} else if (ownFilter === 1) {
return dataviewDefinition.sql.own_filter_on;
2017-10-20 22:47:56 +08:00
} else {
return dataviewDefinition.sql.own_filter_off;
}
}
2019-10-22 01:07:24 +08:00
function getQueryRewriteData (mapConfig, dataviewDefinition, params) {
2017-06-01 00:57:38 +08:00
var sourceId = dataviewDefinition.source.id; // node.id
2019-10-22 01:07:24 +08:00
var layer = _.find(mapConfig.obj().layers, function (l) {
2017-06-01 00:57:38 +08:00
return l.options.source && (l.options.source.id === sourceId);
});
var queryRewriteData = layer && layer.options.query_rewrite_data;
if (queryRewriteData && dataviewDefinition.node.type === 'source') {
queryRewriteData = _.extend({}, queryRewriteData, {
filters: dataviewDefinition.node.filters,
unfiltered_query: dataviewDefinition.sql.own_filter_on
});
}
2017-06-01 01:00:37 +08:00
if (params.bbox && queryRewriteData) {
2019-11-14 18:36:47 +08:00
var bboxFilterDefinition = {
2017-06-01 01:00:37 +08:00
type: 'bbox',
options: {
column: 'the_geom_webmercator',
srid: 3857
},
params: {
bbox: params.bbox
}
};
2019-11-14 18:36:47 +08:00
queryRewriteData = _.extend(queryRewriteData, { bbox_filter: bboxFilterDefinition });
2017-06-01 00:57:38 +08:00
}
return queryRewriteData;
}
2019-10-22 01:07:24 +08:00
function getOverrideParams (params, ownFilter) {
var overrideParams = _.reduce(_.pick(params, 'start', 'end', 'bins', 'offset', 'categories'),
2019-10-22 01:07:24 +08:00
function castNumbers (overrides, val, k) {
2017-06-01 00:52:41 +08:00
if (!Number.isFinite(+val)) {
throw new Error('Invalid number format for parameter \'' + k + '\'');
}
overrides[k] = +val;
return overrides;
},
2019-10-22 01:07:24 +08:00
{ ownFilter: ownFilter }
2017-06-01 00:52:41 +08:00
);
2017-08-03 18:24:05 +08:00
// validation will be delegated to the proper dataview
if (params.aggregation !== undefined) {
overrideParams.aggregation = params.aggregation;
}
return overrideParams;
2017-06-01 00:52:41 +08:00
}
2017-09-29 18:32:46 +08:00
DataviewBackend.prototype.search = function (mapConfigProvider, user, dataviewName, params, callback) {
2018-07-31 17:59:39 +08:00
mapConfigProvider.getMapConfig(function (err, mapConfig) {
if (err) {
return callback(err);
}
2018-07-31 17:59:39 +08:00
var dataviewDefinition = getDataviewDefinition(mapConfig.obj(), dataviewName);
if (!dataviewDefinition) {
2018-08-16 18:16:20 +08:00
const error = new Error(`Dataview '${dataviewName}' does not exist`);
2018-07-31 17:59:39 +08:00
error.type = 'dataview';
error.http_status = 400;
return callback(error);
}
var pg;
2018-07-31 18:43:54 +08:00
var query;
var dataview;
2018-07-31 18:47:03 +08:00
var userQuery = params.q;
2018-07-31 17:59:39 +08:00
try {
pg = new PSQL(dbParamsFromReqParams(params));
2018-07-31 19:26:38 +08:00
query = getQueryWithOwnFilters(dataviewDefinition, params);
2018-07-31 18:43:54 +08:00
dataview = DataviewFactory.getDataview(query, dataviewDefinition);
2018-07-31 17:59:39 +08:00
} catch (error) {
return callback(error);
}
2018-07-31 17:59:39 +08:00
dataview.search(pg, userQuery, function (err, result) {
if (err) {
return callback(err);
}
return callback(null, result);
});
});
};
2018-07-31 19:26:38 +08:00
function getQueryWithOwnFilters (dataviewDefinition, params) {
2018-07-31 18:43:54 +08:00
var ownFilter = +params.own_filter;
ownFilter = !!ownFilter;
var query = (ownFilter) ? dataviewDefinition.sql.own_filter_on : dataviewDefinition.sql.own_filter_off;
if (params.bbox) {
var bboxFilter = new BBoxFilter({ column: 'the_geom', srid: 4326 }, { bbox: params.bbox });
query = bboxFilter.sql(query);
2019-12-03 01:36:41 +08:00
} else if (params.circle) {
const circleFilter = new CircleFilter({ column: 'the_geom', srid: 4326 }, { circle: params.circle });
query = circleFilter.sql(query);
2019-12-03 17:58:55 +08:00
} else if (params.polygon) {
const polygonFilter = new PolygonFilter({ column: 'the_geom', srid: 4326 }, { polygon: params.polygon });
query = polygonFilter.sql(query);
2018-07-31 18:43:54 +08:00
}
return query;
}
2019-10-22 01:07:24 +08:00
function getDataviewDefinition (mapConfig, dataviewName) {
var dataviews = mapConfig.dataviews || {};
return dataviews[dataviewName];
}