'use strict'; /** * Licensed Materials - Property of IBM * IBM Cognos Products: Dashboard * (C) Copyright IBM Corp. 2017, 2019 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. * * @module /dashboard/data/QueryDefinition * @see QueryDefinition */ define(['underscore', '../../../../filters/Filters', '../QueryFilterSpec', '../../../../lib/@waca/dashboard-common/dist/core/Model', '../CommonQueryBuilder'], function (_, Filters, QueryFilterSpec, Model, CommonQueryBuilder) { 'use strict'; /** * The QueryDefinition object is responsible for providing an interface between how a caller sees data * and the query engine needs data (in dimensions-first order). * * In general, it allows a caller to define an arbitrary 'field order'. In the case of widgets, this * order would correspond to slot/slot mapping order depending on the application and type of slot. * * That same order is available through the QueryResults object. */ // Declare the class var PROP_ID_SUPPRESSION = 'suppression'; var SUPPRESSION_NONE = 'none'; var QueryDefinition = null; QueryDefinition = Model.extend({ filters: null, localFilters: null, //If not specified in query options, the query row limit is this value. DEFAULT_QUERY_ROW_LIMIT: 3000, DEFAULT_QUERY_HINT_REALTIME_REFRESH: false, init: function init(options) { QueryDefinition.inherited('init', this, arguments); this.dashboardAPI = options.dashboardAPI; this.logger = options.logger; this._topBottomQueryPageScope = null; //If not set, top bottom queries will be scoped to all pages. this._queryDataItems = []; this._queryProjections = []; }, /** * @param {Array} QueryDataItems **/ setQueryDataItems: function setQueryDataItems(queryDataItems) { this._queryDataItems = queryDataItems; }, getQueryDataItems: function getQueryDataItems() { return this._queryDataItems; }, setQueryProjections: function setQueryProjections(projections) { this._queryProjections = projections; }, getQueryProjections: function getQueryProjections() { return this._queryProjections; }, /** * because widget-to-widget filters only affect values of widgets on a particular page (tab), * topBottom queries need to be 'scoped' to collect items on this widget's page only. * @param topBottomQueryPageScope - the id of a parent object that must match when collecting items (set to null if no scope is needed). */ setTopBottomQueryPageScope: function setTopBottomQueryPageScope(topBottomQueryPageScope) { this._topBottomQueryPageScope = topBottomQueryPageScope; }, _canQuery: function _canQuery(slotAPI) { return !(slotAPI.isMultiMeasuresSeries() && !slotAPI.isStacked()); }, _LayersHaveCategoricalSlots: function _LayersHaveCategoricalSlots(visAPI) { var _this = this; var aSlotGroups = visAPI.getSlotInfoForEachView(); _.each(aSlotGroups, function (entry) { var oCategorySlots = _.find(entry.slotAPIs, function (slotAPI) { return slotAPI.getFinalSlotType() === 'category' && _this._canQuery(slotAPI); }); entry.hasCategoricalSlots = oCategorySlots !== undefined; }); return aSlotGroups; }, /** * Construct the query specs needed for the current visualization. * @param queryOptions - options on the query (shouldAxisScalesBeFixed, dataRowLimit etc.) * @param visApi - visApi * @returns querySpec - the query spec to retrieve the needed data set, topBottomQuery - * query to get the top and bottom values for each ordinal field if needed. * TODO: Should move this to a more central place. */ build: function build(queryOptions, visAPI) { // build the query queryOptions = queryOptions || {}; //QueryOptions should always be defined even if members are not. var queryDescriptor = this._buildEndorQuerySpec(); var topBottomQuery = void 0; var containsCategorySlots = this._LayersHaveCategoricalSlots(visAPI); /* If we do not have any dimensions (a summary view for instance) we do * not need to do top and bottom queries (shouldAxisScaleBeFixed will be false). */ if (queryOptions.shouldAxisScaleBeFixed && containsCategorySlots) { var aItemsToExclude = []; _.each(visAPI.getDataSlots(), function (slot) { //By definition, items in certain slots should not be added to top bottom queries if (slot.getDefinition().useInTopBottomQueries === false) { aItemsToExclude = aItemsToExclude.concat(slot.getDataItemRefs()); } else if (slot.isStacked()) { // If the slot is stacked and has multiple data items then we can not add it to the min max query // In this scenario the slot is shown as a nested set of data items and we need to remove using the id. aItemsToExclude = aItemsToExclude.concat(slot.getId()); } }); // Make one query to get min and max only with the fields from the current widget, plus the global filters and slicers (filters from other widgets). topBottomQuery = CommonQueryBuilder.buildMinMaxQueryFromDataItems(queryDescriptor.querySpec, { 'itemsToExclude': aItemsToExclude }, this.logger); } this._setSuppresion(queryDescriptor, visAPI); return { querySpec: queryDescriptor.querySpec, endPoint: 'data', topBottomQuery: topBottomQuery }; }, _setSuppresion: function _setSuppresion(queryDescriptor, visAPI) { if (queryDescriptor && queryDescriptor.querySpec) { var contentAPI = visAPI.ownerWidget.content; var suppression = contentAPI && contentAPI.getPropertyValue(PROP_ID_SUPPRESSION); if (suppression === SUPPRESSION_NONE) { queryDescriptor.querySpec.suppress = [SUPPRESSION_NONE]; if (!queryDescriptor.querySpec.queryHints) { queryDescriptor.querySpec.queryHints = {}; } queryDescriptor.querySpec.queryHints.suppress = SUPPRESSION_NONE; } } }, //TODO: Merge this API for Endor release _buildEndorQuerySpec: function _buildEndorQuerySpec() { var oQuerySpec = {}; oQuerySpec.version = '1'; oQuerySpec.dataItems = this._queryDataItems; oQuerySpec.projections = this._queryProjections; oQuerySpec.limit = 3000; //TODO: Capped as 3000 as limited as of Pre-Endor return { querySpec: oQuerySpec }; }, /** * @returns the query URL string that is equivalent to the output of build. */ buildURL: function buildURL() { var queryDescriptor = this._buildEndorQuerySpec(); return JSON.stringify(queryDescriptor.querySpec); } }); return QueryDefinition; }); //# sourceMappingURL=QueryDefinition.js.map