'use strict'; var BaseOverviewsDataview = require('./base'); var BaseDataview = require('../formula'); var debug = require('debug')('windshaft:widget:formula:overview'); const utils = require('../../../utils/query-utils'); var dot = require('dot'); dot.templateSettings.strip = false; const VALID_OPERATIONS = { count: true, sum: true, avg: true }; /** Formulae to calculate the end result using _feature_count from the overview table*/ function dataviewResult(ctx) { switch (ctx.operation) { case 'count': return `sum(_feature_count)`; case 'sum': return `sum(${utils.handleFloatColumn(ctx)}*_feature_count)`; case 'avg': return `sum(${utils.handleFloatColumn(ctx)}*_feature_count)/sum(_feature_count) `; } return `${ctx.operation}(${utils.handleFloatColumn(ctx)})`; } const formulaQueryTpl = ctx => `SELECT ${dataviewResult(ctx)} AS result, ${utils.countNULLs(ctx)} AS nulls_count ${ctx.isFloatColumn ? `,${utils.countInfinites(ctx)} AS infinities_count,` : ``} ${ctx.isFloatColumn ? `${utils.countNaNs(ctx)} AS nans_count` : ``} FROM (${ctx.query}) __cdb_formula`; function Formula(query, options, queryRewriter, queryRewriteData, params, queries) { BaseOverviewsDataview.call(this, query, options, BaseDataview, queryRewriter, queryRewriteData, params, queries); this.column = options.column || '1'; this.operation = options.operation; this._isFloatColumn = null; this.queries = queries; } Formula.prototype = Object.create(BaseOverviewsDataview.prototype); Formula.prototype.constructor = Formula; module.exports = Formula; Formula.prototype.sql = function (psql, override, callback) { var self = this; if (!VALID_OPERATIONS[this.operation]) { return this.defaultSql(psql, override, callback); } if (this._isFloatColumn === null) { this._isFloatColumn = false; this.getColumnType(psql, this.column, this.queries.no_filters, function (err, type) { if (!err && !!type) { self._isFloatColumn = type.float; } self.sql(psql, override, callback); }); return null; } var formulaSql = formulaQueryTpl({ isFloatColumn: this._isFloatColumn, query: this.rewrittenQuery(this.query), operation: this.operation, column: this.column }); callback = callback || override; debug(formulaSql); return callback(null, formulaSql, { usesOverviews: true }); };