Query utils: Use webmercator utils, reuse code and always substitute tokens
This commit is contained in:
parent
bdbe132311
commit
63b6af2ac7
@ -1,48 +1,41 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const SubstitutionTokens = require('./substitution-tokens');
|
const windshaftUtils = require('windshaft').utils;
|
||||||
|
|
||||||
function prepareQuery(sql) {
|
module.exports.extractTableNames = function (query) {
|
||||||
var affectedTableRegexCache = {
|
|
||||||
bbox: /!bbox!/g,
|
|
||||||
scale_denominator: /!scale_denominator!/g,
|
|
||||||
pixel_width: /!pixel_width!/g,
|
|
||||||
pixel_height: /!pixel_height!/g
|
|
||||||
};
|
|
||||||
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.extractTableNames = function extractTableNames(query) {
|
|
||||||
return [
|
return [
|
||||||
'SELECT * FROM CDB_QueryTablesText($windshaft$',
|
'SELECT * FROM CDB_QueryTablesText($windshaft$',
|
||||||
prepareQuery(query),
|
substituteDummyTokens(query),
|
||||||
'$windshaft$) as tablenames'
|
'$windshaft$) as tablenames'
|
||||||
].join('');
|
].join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports.getQueryActualRowCount = function (query) {
|
module.exports.getQueryActualRowCount = function (query) {
|
||||||
return `select COUNT(*) AS rows FROM (${query}) AS __cdb_query`;
|
return `select COUNT(*) AS rows FROM (${substituteDummyTokens(query)}) AS __cdb_query`;
|
||||||
};
|
};
|
||||||
|
|
||||||
function getQueryRowEstimation(query) {
|
function getQueryRowEstimation(query) {
|
||||||
return 'select CDB_EstimateRowCount($windshaft$' + query + '$windshaft$) as rows';
|
return 'select CDB_EstimateRowCount($windshaft$' + substituteDummyTokens(query) + '$windshaft$) as rows';
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getQueryRowEstimation = getQueryRowEstimation;
|
module.exports.getQueryRowEstimation = getQueryRowEstimation;
|
||||||
|
|
||||||
|
function getQueryGeometryType(query, geometryColumn) {
|
||||||
|
return `
|
||||||
|
SELECT ST_GeometryType(${geometryColumn}) AS geom_type
|
||||||
|
FROM (${substituteDummyTokens(query)}) AS __cdb_query
|
||||||
|
WHERE ${geometryColumn} IS NOT NULL
|
||||||
|
LIMIT 1
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
module.exports.getQueryGeometryType = getQueryGeometryType;
|
||||||
|
|
||||||
module.exports.getAggregationMetadata = ctx => `
|
module.exports.getAggregationMetadata = ctx => `
|
||||||
WITH
|
WITH
|
||||||
rowEstimation AS (
|
rowEstimation AS (
|
||||||
${getQueryRowEstimation(ctx.query)}
|
${getQueryRowEstimation(ctx.query)}
|
||||||
),
|
),
|
||||||
geometryType AS (
|
geometryType AS (
|
||||||
SELECT ST_GeometryType(${ctx.geometryColumn}) as geom_type
|
${getQueryGeometryType(ctx.query, ctx.geometryColumn)}
|
||||||
FROM (${ctx.query}) AS __cdb_query WHERE ${ctx.geometryColumn} IS NOT NULL LIMIT 1
|
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
rows AS count,
|
rows AS count,
|
||||||
@ -85,7 +78,7 @@ module.exports.getQueryTopCategories = function (query, column, topN, includeNul
|
|||||||
const where = includeNulls ? '' : `WHERE ${column} IS NOT NULL`;
|
const where = includeNulls ? '' : `WHERE ${column} IS NOT NULL`;
|
||||||
return `
|
return `
|
||||||
SELECT ${column} AS category, COUNT(*) AS frequency
|
SELECT ${column} AS category, COUNT(*) AS frequency
|
||||||
FROM (${query}) AS __cdb_query
|
FROM (${substituteDummyTokens(query)}) AS __cdb_query
|
||||||
${where}
|
${where}
|
||||||
GROUP BY ${column} ORDER BY 2 DESC
|
GROUP BY ${column} ORDER BY 2 DESC
|
||||||
LIMIT ${topN}
|
LIMIT ${topN}
|
||||||
@ -116,7 +109,7 @@ module.exports.getQuerySample = function (query, sampleProb, limit = null, rando
|
|||||||
SELECT setseed(${randomSeed})
|
SELECT setseed(${randomSeed})
|
||||||
)
|
)
|
||||||
SELECT ${columnSelector(columns)}
|
SELECT ${columnSelector(columns)}
|
||||||
FROM (${query}) AS __cdb_query
|
FROM (${substituteDummyTokens(query)}) AS __cdb_query
|
||||||
WHERE random() < ${sampleProb}
|
WHERE random() < ${sampleProb}
|
||||||
${limitClause}
|
${limitClause}
|
||||||
`;
|
`;
|
||||||
@ -157,19 +150,11 @@ function simpleQueryTable(sql) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.getQueryGeometryType = function (query, geometryColumn) {
|
|
||||||
return `
|
|
||||||
SELECT ST_GeometryType(${geometryColumn}) AS geom_type
|
|
||||||
FROM (${query}) AS __cdb_query
|
|
||||||
WHERE ${geometryColumn} IS NOT NULL
|
|
||||||
LIMIT 1
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function getQueryLimited(query, limit = 0) {
|
function getQueryLimited(query, limit = 0) {
|
||||||
return `
|
return `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM (${query}) AS __cdb_query
|
FROM (${substituteDummyTokens(query)}) AS __cdb_query
|
||||||
LIMIT ${limit}
|
LIMIT ${limit}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -181,32 +166,32 @@ function queryPromise(dbConnection, query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function substituteDummyTokens(sql) {
|
function substituteDummyTokens(sql) {
|
||||||
return sql && SubstitutionTokens.replace(sql, {
|
return subsituteTokensForZoom(sql, 0);
|
||||||
bbox: 'ST_MakeEnvelope(0,0,0,0)',
|
|
||||||
scale_denominator: '0',
|
|
||||||
pixel_width: '1',
|
|
||||||
pixel_height: '1'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function subsituteTokensForZoom(sql, zoom, singleTile=false) {
|
function subsituteTokensForZoom(sql, zoom) {
|
||||||
const tileRes = 256;
|
if (!sql) {
|
||||||
const wmSize = 6378137.0*2*Math.PI;
|
return undefined;
|
||||||
const nTiles = Math.pow(2, zoom);
|
|
||||||
const tileSize = wmSize / nTiles;
|
|
||||||
const resolution = tileSize / tileRes;
|
|
||||||
const scaleDenominator = resolution / 0.00028;
|
|
||||||
const x0 = -wmSize/2, y0 = -wmSize/2;
|
|
||||||
let bbox = `ST_MakeEnvelope(${x0}, ${y0}, ${x0+wmSize}, ${y0+wmSize})`;
|
|
||||||
if (singleTile) {
|
|
||||||
bbox = `ST_MakeEnvelope(${x0}, ${y0}, ${x0 + tileSize}, ${y0 + tileSize})`;
|
|
||||||
}
|
}
|
||||||
return SubstitutionTokens.replace(sql, {
|
const affectedTableRegexCache = {
|
||||||
bbox: bbox,
|
bbox: /!bbox!/g,
|
||||||
scale_denominator: scaleDenominator,
|
scale_denominator: /!scale_denominator!/g,
|
||||||
pixel_width: resolution,
|
pixel_width: /!pixel_width!/g,
|
||||||
pixel_height: resolution
|
pixel_height: /!pixel_height!/g
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const webmercator = new windshaftUtils.WebMercatorHelper();
|
||||||
|
const resolution = webmercator.getResolution({ z : zoom });
|
||||||
|
const scaleDenominator = resolution.dividedBy(0.00028);
|
||||||
|
// We always use the whole world as the bbox
|
||||||
|
const extent = webmercator.getExtent({ x : 0, y : 0, z : 0 });
|
||||||
|
|
||||||
|
return sql
|
||||||
|
.replace(affectedTableRegexCache.bbox,
|
||||||
|
`ST_MakeEnvelope(${extent.xmin}, ${extent.ymin}, ${extent.xmax}, ${extent.ymax}, 3857)`)
|
||||||
|
.replace(affectedTableRegexCache.scale_denominator, scaleDenominator)
|
||||||
|
.replace(affectedTableRegexCache.pixel_width, resolution)
|
||||||
|
.replace(affectedTableRegexCache.pixel_height, resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.queryPromise = queryPromise;
|
module.exports.queryPromise = queryPromise;
|
||||||
|
Loading…
Reference in New Issue
Block a user