Use early return pattern
This commit is contained in:
@@ -152,80 +152,83 @@ function _columnStats(ctx, columns, dimensions) {
|
||||
if (!columns) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (_columnsMetadataRequired(ctx.metaOptions)) {
|
||||
let queries = [];
|
||||
let aggr = [];
|
||||
if (ctx.metaOptions.columnStats) {
|
||||
queries.push(new Promise(resolve => resolve({ columns }))); // add columns as first result
|
||||
Object.keys(columns).forEach(name => {
|
||||
aggr = aggr.concat(
|
||||
columnAggregations(columns[name])
|
||||
.map(fn => `${fn}("${name}") AS "${name}_${fn}"`)
|
||||
);
|
||||
if (columns[name].type === 'string') {
|
||||
const topN = ctx.metaOptions.columnStats.topCategories || 1024;
|
||||
const includeNulls = ctx.metaOptions.columnStats.hasOwnProperty('includeNulls') ?
|
||||
ctx.metaOptions.columnStats.includeNulls :
|
||||
true;
|
||||
|
||||
// TODO: ctx.metaOptions.columnStats.maxCategories
|
||||
// => use PG stats to dismiss columns with more distinct values
|
||||
queries.push(
|
||||
queryUtils.queryPromise(
|
||||
ctx.dbConnection,
|
||||
_getSQL(ctx, sql => queryUtils.getQueryTopCategories(sql, name, topN, includeNulls))
|
||||
).then(res => ({ columns: { [name]: { categories: res.rows } } }))
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
const dimensionsStats = {};
|
||||
let dimensionsInfo = {};
|
||||
if (ctx.metaOptions.dimensions && dimensions) {
|
||||
dimensionsInfo = aggregationQuery.infoForOptions({ dimensions });
|
||||
Object.keys(dimensionsInfo).forEach(dimName => {
|
||||
const info = dimensionsInfo[dimName];
|
||||
if (info.type === 'timeDimension') {
|
||||
dimensionsStats[dimName] = {
|
||||
params: info.params
|
||||
};
|
||||
aggr = aggr.concat(
|
||||
columnAggregations(info).map(fn => `${fn}(${info.sql}) AS "${dimName}_${fn}"`)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
queries.push(
|
||||
queryUtils.queryPromise(
|
||||
ctx.dbConnection,
|
||||
_getSQL(ctx, sql => `SELECT ${aggr.join(',')} FROM (${sql}) AS __cdb_query`)
|
||||
).then(res => {
|
||||
let stats = { columns: {}, dimensions: {} };
|
||||
Object.keys(columns).forEach(name => {
|
||||
stats.columns[name] = {};
|
||||
columnAggregations(columns[name]).forEach(fn => {
|
||||
stats.columns[name][fn] = res.rows[0][`${name}_${fn}`];
|
||||
});
|
||||
});
|
||||
Object.keys(dimensionsInfo).forEach(name => {
|
||||
stats.dimensions[name] = stats.dimensions[name] || Object.assign({}, dimensionsStats[name]);
|
||||
let type = null;
|
||||
columnAggregations(dimensionsInfo[name]).forEach(fn => {
|
||||
type = type ||
|
||||
fieldTypeSafe(ctx.dbConnection, res.fields.find(f => f.name === `${name}_${fn}`));
|
||||
stats.dimensions[name][fn] = res.rows[0][`${name}_${fn}`];
|
||||
});
|
||||
stats.dimensions[name].type = type;
|
||||
});
|
||||
return stats;
|
||||
})
|
||||
);
|
||||
return Promise.all(queries).then(results => ({
|
||||
columns: mergeColumns(results.map(r => r.columns)),
|
||||
dimensions: mergeColumns(results.map( r => r.dimensions))
|
||||
}));
|
||||
if (!_columnsMetadataRequired(ctx.metaOptions)) {
|
||||
return Promise.resolve({ columns });
|
||||
}
|
||||
return Promise.resolve({ columns });
|
||||
|
||||
let queries = [];
|
||||
let aggr = [];
|
||||
if (ctx.metaOptions.columnStats) {
|
||||
queries.push(new Promise(resolve => resolve({ columns }))); // add columns as first result
|
||||
Object.keys(columns).forEach(name => {
|
||||
aggr = aggr.concat(
|
||||
columnAggregations(columns[name])
|
||||
.map(fn => `${fn}("${name}") AS "${name}_${fn}"`)
|
||||
);
|
||||
if (columns[name].type === 'string') {
|
||||
const topN = ctx.metaOptions.columnStats.topCategories || 1024;
|
||||
const includeNulls = ctx.metaOptions.columnStats.hasOwnProperty('includeNulls') ?
|
||||
ctx.metaOptions.columnStats.includeNulls :
|
||||
true;
|
||||
|
||||
// TODO: ctx.metaOptions.columnStats.maxCategories
|
||||
// => use PG stats to dismiss columns with more distinct values
|
||||
queries.push(
|
||||
queryUtils.queryPromise(
|
||||
ctx.dbConnection,
|
||||
_getSQL(ctx, sql => queryUtils.getQueryTopCategories(sql, name, topN, includeNulls))
|
||||
).then(res => ({ columns: { [name]: { categories: res.rows } } }))
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
const dimensionsStats = {};
|
||||
let dimensionsInfo = {};
|
||||
if (ctx.metaOptions.dimensions && dimensions) {
|
||||
dimensionsInfo = aggregationQuery.infoForOptions({ dimensions });
|
||||
Object.keys(dimensionsInfo).forEach(dimName => {
|
||||
const info = dimensionsInfo[dimName];
|
||||
if (info.type === 'timeDimension') {
|
||||
dimensionsStats[dimName] = {
|
||||
params: info.params
|
||||
};
|
||||
aggr = aggr.concat(
|
||||
columnAggregations(info).map(fn => `${fn}(${info.sql}) AS "${dimName}_${fn}"`)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
queries.push(
|
||||
queryUtils.queryPromise(
|
||||
ctx.dbConnection,
|
||||
_getSQL(ctx, sql => `SELECT ${aggr.join(',')} FROM (${sql}) AS __cdb_query`)
|
||||
).then(res => {
|
||||
let stats = { columns: {}, dimensions: {} };
|
||||
Object.keys(columns).forEach(name => {
|
||||
stats.columns[name] = {};
|
||||
columnAggregations(columns[name]).forEach(fn => {
|
||||
stats.columns[name][fn] = res.rows[0][`${name}_${fn}`];
|
||||
});
|
||||
});
|
||||
Object.keys(dimensionsInfo).forEach(name => {
|
||||
stats.dimensions[name] = stats.dimensions[name] || Object.assign({}, dimensionsStats[name]);
|
||||
let type = null;
|
||||
columnAggregations(dimensionsInfo[name]).forEach(fn => {
|
||||
type = type ||
|
||||
fieldTypeSafe(ctx.dbConnection, res.fields.find(f => f.name === `${name}_${fn}`));
|
||||
stats.dimensions[name][fn] = res.rows[0][`${name}_${fn}`];
|
||||
});
|
||||
stats.dimensions[name].type = type;
|
||||
});
|
||||
return stats;
|
||||
})
|
||||
);
|
||||
return Promise.all(queries).then(results => ({
|
||||
columns: mergeColumns(results.map(r => r.columns)),
|
||||
dimensions: mergeColumns(results.map( r => r.dimensions))
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
// This is adapted from SQL API:
|
||||
|
||||
Reference in New Issue
Block a user