123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- 'use strict';
- /*
- *+------------------------------------------------------------------------+
- *| Licensed Materials - Property of IBM
- *| IBM Cognos Products: Dashboard
- *| (C) Copyright IBM Corp. 2013, 2020
- *|
- *| US Government Users Restricted Rights - Use, duplication or disclosure
- *| restricted by GSA ADP Schedule Contract with IBM Corp.
- *+------------------------------------------------------------------------+
- */
- // The VisQueryExecution object manages a set of queries that are needed to provide the data for a visualization.
- define(['jquery', 'underscore', './VisQueryBuilder', '../../../lib/@waca/core-client/js/core-client/ui/core/Class', './CommonQueryBuilder', './legacy/QueryManager', '../../../widgets/livewidget/nls/StringResources', '../../../dataSources/utils/DatasourceUtil', './postprocess/VisQueryPostProcessHelper'], function ($, _, VisQueryBuilder, Class, CommonQueryBuilder, QueryManager, StringResources, DatasourceUtil, PostProcessHelper) {
- 'use strict';
- var VisQueryExecution = null; // class declaration
- VisQueryExecution = Class.extend({
- init: function init(options) {
- console.debug('visQueryExecution (lw) init');
- VisQueryExecution.inherited('init', this, arguments);
- options = options || {};
- this.queryService = options.queryService;
- this.ownerWidget = options.ownerWidget;
- this.metadataAPI = options.metadataAPI;
- this.pageContext = options.pageContext;
- this.visAPI = options.visAPI;
- this._commonQueryHelper = options.queryHelper;
- //Optionally, override this function to perform operations on the data prior to post processing.
- this._callUnprocessedResultDataHandlers = options.callUnprocessedResultDataHandlers || this._callUnprocessedResultDataHandlers;
- this._queryManager = new QueryManager({
- 'queryService': this.queryService,
- 'visAPI': this.visAPI,
- 'dashboardAPI': this.ownerWidget && this.ownerWidget.getDashboardApi && this.ownerWidget.getDashboardApi(),
- 'postProcessCallback': this.postProcess.bind(this),
- '_callUnprocessedResultDataHandlers': this._callUnprocessedResultDataHandlers.bind(this)
- });
- if (!this.visQueryBuilder) {
- var cbGetNLT = this.ownerWidget && this.ownerWidget.getFeature && this.ownerWidget.getFeature.bind(this.ownerWidget, 'vis-chart-insights');
- this.visQueryBuilder = new VisQueryBuilder({
- 'visAPI': this.visAPI,
- 'getNLT': cbGetNLT
- });
- }
- //The _queryChangedCompareString is used to avoid querying in cases where a spec change has no impact on the query definition (or result)
- this._queryChangedCompareString = null;
- },
- /**
- * Ensure that the slots are up-to-date and prepare the data (if necessary).
- * @param localFiltersOnly (optional) if set, only local filters will be passed to the queryDefinition. If not set, both local and cross-widget filters are passed.
- * @returns a promise.
- */
- execute: function execute(queryContext) {
- if (queryContext.isInvalidReason) {
- queryContext.cbQueryFailed({
- reason: queryContext.isInvalidReason
- });
- return Promise.reject();
- }
- return this.getQueryOptionsArray(queryContext).then(function (result) {
- result = result || {};
- // Compare with the main data query.
- // Auxiliary queries (ie. summaries) can be ignored.
- var aQueryOptionsArray = result.aQueryOptionsArray;
- if (!queryContext.auxQuery) {
- this._queryChangedCompareString = this._buildQueryChangedCompareString(aQueryOptionsArray);
- }
- return this._doExecute(queryContext, aQueryOptionsArray).then(function (resultData) {
- if (resultData) {
- resultData.synchDataFilterEntries = result.synchDataFilterEntries;
- }
- return resultData;
- });
- }.bind(this));
- },
- //This function can be overridden in constructor options to perform tasks on un-postprocessed data.
- _callUnprocessedResultDataHandlers: function _callUnprocessedResultDataHandlers() {},
- postProcess: function postProcess(resultDataEntry) {
- PostProcessHelper.postProcessMeasuresAsSeries(resultDataEntry, this);
- PostProcessHelper.postProcessAggregatedSort(resultDataEntry, this);
- PostProcessHelper.postProcessCustomSort(resultDataEntry, this);
- PostProcessHelper.postProcessAutobinningAxisLabels(resultDataEntry, this);
- },
- _doExecute: function _doExecute(queryContext, queryOptions) {
- var _this = this;
- return this.getQueryManager().whenQueryResultsReady(queryContext.renderContext, queryOptions, queryContext.sender, queryContext.useAPI, queryContext.auxQuery).catch(function (jqXHR) {
- return Promise.reject(_this._queryFailed(jqXHR));
- });
- },
- getQueryOptionsArray: function getQueryOptionsArray(queryContext) {
- //lat/long TODO, This is array of query definition
- //Lat/Long new query Definition Object
- return this._createQueryDefinition(queryContext).then(function (result) {
- result = result || {};
- var visQueryDefinition = result.visQueryDefinition;
- var aQueryOptionsArray = [];
- var oSpecsForQueryDefinition = visQueryDefinition.getQueryDefinitions(); // hand back
- _.each(oSpecsForQueryDefinition, function (oDef) {
- var oQueryDefObj = this.getQueryDefinition();
- oQueryDefObj.setQueryDataItems(oDef.getDataItems());
- oQueryDefObj.setQueryProjections(oDef.getProjections());
- //TopBottom queries need to be 'scoped' to items on the current page (tab)
- oQueryDefObj.setTopBottomQueryPageScope(queryContext.scope);
- var initialQueryOptions = queryContext.queryOptions ? _.clone(queryContext.queryOptions) : {};
- var queryOptions = _.extend(initialQueryOptions, oQueryDefObj.build(initialQueryOptions, this.ownerWidget.visAPI));
- // Set filters to query spec
- var filters = oDef.getFilters();
- if (filters && filters.length) {
- queryOptions.querySpec.filters = filters;
- }
- queryOptions.sourceIdOrModule = this.metadataAPI.getModule();
- if (queryOptions.querySpec.queryHints) {
- _.extend(queryOptions.querySpec.queryHints, oDef.getQueryHints());
- } else {
- queryOptions.querySpec.queryHints = oDef.getQueryHints();
- }
- if (queryContext.queryOptions && queryContext.queryOptions.needsUnaggregatedForm) {
- queryOptions.querySpec.type = 'detail';
- }
- // Pass the functions to handle prompt fault.
- queryOptions.promptControlFunctions = {
- 'preparePromptSpec': this.preparePromptSpec.bind(this),
- 'whenSingleItemQueryReady': this._commonQueryHelper.whenSingleItemQueryReady.bind(this._commonQueryHelper, queryOptions.sourceIdOrModule),
- 'whenColumnsMinMaxQueryReady': this._commonQueryHelper.whenColumnsMinMaxQueryReady.bind(this._commonQueryHelper, queryOptions.sourceIdOrModule),
- 'getPromptSpec': this.getPromptSpec.bind(this),
- 'savePromptSpec': this.savePromptSpec.bind(this),
- 'updatePromptSpecCache': this.updatePromptSpecCache.bind(this),
- 'onCancelPromptDialog': this.onCancelPromptDialog.bind(this),
- 'onUnSupportedPromptType': this.ownerWidget.onUnSupportedPrompt.bind(this, StringResources.get('unSupportedPromptType'))
- };
- queryOptions.layerId = oDef.getLayerId();
- if (this.ownerWidget && this.ownerWidget.isPreview) {
- queryOptions.isPreview = true;
- }
- aQueryOptionsArray.push(queryOptions);
- }, this);
- return { aQueryOptionsArray: aQueryOptionsArray, synchDataFilterEntries: result.synchDataFilterEntries };
- }.bind(this));
- },
- _buildQueryChangedCompareString: function _buildQueryChangedCompareString(results) {
- var queryChangedCompareString = '';
- _.each(results, function (result) {
- queryChangedCompareString += JSON.stringify(result.querySpec);
- });
- return queryChangedCompareString;
- },
- queryChanged: function queryChanged(queryContext) {
- return this.getQueryOptionsArray(queryContext).then(function (result) {
- var queryUrl = this._buildQueryChangedCompareString(result.aQueryOptionsArray);
- return {
- isRenderNeeded: this._queryChangedCompareString !== queryUrl,
- synchDataFilterEntries: result.synchDataFilterEntries
- };
- }.bind(this));
- },
- _createQueryDefinition: function _createQueryDefinition() {
- var _this2 = this;
- var queryContext = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- queryContext.queryOptions = queryContext.queryOptions || {};
- queryContext.queryOptions.addExtraQueryDataItem = CommonQueryBuilder.addExtraQueryDataItem.bind(this, this.ownerWidget.model.getDataItemIdsMap(), queryContext.queryOptions);
- var visQueryDefinition = this.visQueryBuilder.create(queryContext);
- queryContext.metadataAPI = this.metadataAPI;
- var netPageContext = this._getNetPageContext(this.ownerWidget.visAPI.getDefinition().reactToExternalBrushing);
- var binningInfos = [];
- var aFilters = CommonQueryBuilder.buildFilterFromPageContext(netPageContext, queryContext, binningInfos);
- var extraQueryDataItems = queryContext.queryOptions.extraDataItems && queryContext.queryOptions.extraDataItems.length ? queryContext.queryOptions.extraDataItems : null;
- _.each(visQueryDefinition.getQueryDefinitions(), function (queryDefinition) {
- _this2._addBinningDataItemSpecIfNeedit(queryDefinition._dataItems, binningInfos);
- // Add extra query data items required by filter expression, if not already added
- if (extraQueryDataItems) {
- queryDefinition._dataItems = _.uniq(queryDefinition._dataItems.concat(extraQueryDataItems), false, function (dataItem) {
- return dataItem.id;
- });
- }
- queryDefinition.addFilters(aFilters);
- });
- return Promise.resolve({ visQueryDefinition: visQueryDefinition, synchDataFilterEntries: null });
- },
- _addBinningDataItemSpecIfNeedit: function _addBinningDataItemSpecIfNeedit(dataItems, binningInfos) {
- if (binningInfos) {
- CommonQueryBuilder.addBinningDataItemIfNeedit(dataItems, binningInfos);
- }
- },
- _isDifferentModule: function _isDifferentModule(queryContext) {
- queryContext = queryContext || {};
- if (!queryContext.sourceIds && !queryContext.assetIds) {
- return false;
- } else {
- return this.ownerWidget.idsNotInModule(queryContext.sourceIds, queryContext.assetIds);
- }
- },
- _getTableRef: function _getTableRef() {
- var tableRef = null;
- var visualization = this.ownerWidget.content.getFeature('Visualization');
- var datasource = visualization.getDataSource();
- if (datasource) {
- var slots = visualization.getSlots();
- var dataItems = slots.getDataItemList();
- tableRef = DatasourceUtil.getTableRef(datasource, dataItems.map(function (dataItem) {
- return dataItem.getColumnId();
- }));
- }
- return tableRef;
- },
- _getNetPageContext: function _getNetPageContext(reactToExternalBrushing) {
- var _this3 = this;
- var param = {
- scope: this.ownerWidget.getContainerPageId(),
- eventGroupId: this.ownerWidget.getEventGroupId(),
- sourceId: this.metadataAPI.getModule().getSourceId()
- };
- if (reactToExternalBrushing === false) {
- param.origin = 'filter';
- }
- var netPageContext = this.pageContext && this.pageContext.getNetPageContext(param) || [];
- // Longer term - this filtering should be removed. The query service will ignore filters that don't apply
- // (instead of throwing an error) and return messages indicating that certain filters are being ignored.
- // Shorter term - we may need to compare table references to avoid errors but if there is no table ref,
- // just let it pass through (e.g. for a global calculation) and let the query service handle it.
- var tableRef = this._getTableRef();
- var isEmptyTableRef = function isEmptyTableRef(aTableRef) {
- return !aTableRef || _.every(aTableRef, function (ref) {
- return _.isEmpty(ref);
- });
- };
- var haveTableJoin = function haveTableJoin(pageContext) {
- if (isEmptyTableRef(tableRef)) {
- return true;
- }
- var pageContextTableRef = DatasourceUtil.getPageContextItemTableRef(_this3.metadataAPI.getModule(), pageContext);
- return isEmptyTableRef(pageContextTableRef) || DatasourceUtil.haveTableJoinsInSameDataSource(_this3.metadataAPI.getModule(), pageContextTableRef, tableRef);
- };
- netPageContext = netPageContext.filter(function (pageContext) {
- // Don't send anything page context entries that tables are no joined, otherwise get error from such as:
- // "code": "XQE-MSR-0008",
- // "details": "XQE-MSR-0008 In module \"newModel\", the following query subjects are not joined: \"Page_1\", \"Page_2\", \"Synch Source 2.xlsx\".\r\n\t
- // TODO - livewidget_cleanup -- this code used the old slot API -- verifdy if this is this dead code ?
- return DatasourceUtil.mustVerifyJoinTablesInSameDataSource(_this3.metadataAPI.getModule(), pageContext, _this3.visAPI.getDataSlots()) ? haveTableJoin(pageContext) : true;
- });
- return netPageContext;
- },
- _getNetPageContextFromOtherModules: function _getNetPageContextFromOtherModules() {
- var _this4 = this;
- var netPageContext = [];
- if (this.pageContext) {
- var currentSourceId = this.metadataAPI.getModule().getSourceId();
- var tableRef = this._getTableRef();
- var options = {
- scope: this.ownerWidget.getContainerPageId(),
- eventGroupId: this.ownerWidget.getEventGroupId(),
- origin: 'filter'
- };
- var pageContext = this.pageContext.getNetPageContextItems(options);
- netPageContext = pageContext.filter(function (context) {
- var otherTableRef = DatasourceUtil.getPageContextItemTableRef(_this4.metadataAPI.getModule(), context.getPageContextSpec());
- return context.getSourceId() !== currentSourceId || !DatasourceUtil.haveTableJoinsInSameDataSource(_this4.metadataAPI.getModule(), otherTableRef, tableRef);
- });
- }
- return netPageContext;
- },
- _queryFailed: function _queryFailed(failure) {
- var knownFailures = ['unSupportedPromptType', 'cancelPromptDialog', 'promptingIsDisabled'];
- if (knownFailures.indexOf(failure.message) !== -1) {
- // this failure will be handled in Explore
- return failure;
- }
- var oDS = this.metadataAPI.getModule();
- var msg = 'dwErrorRunningQuery';
- var code = void 0;
- if (failure.reason === 'staleRequest') {
- msg = 'dwErrorStaleRequest';
- } else if (failure.reason === 'geoQueryFail') {
- msg = 'dwErrorGeoData';
- } else if (failure.reason === 'cancelPromptSignon') {
- msg = 'dwPromptSignonCancelWarning';
- } else if (failure.responseJSON && failure.responseJSON.errors) {
- var oErr = failure.responseJSON.errors[0];
- code = oErr && oErr.code;
- if (code === 'DSS-GEN-0002') {
- this._hasUnavailableMetadataColumns = true;
- //M31 FIXME?
- //this.trigger('hasUnavailableMetadataColumns');
- return;
- } else if (code === 'DSS-GEN-0001') {
- msg = StringResources.get('errorSourceNotFound', {
- sourceName: oDS.getSourceName() || oDS.getSourceId()
- });
- } else if (code === 'XQE-PLN-0226') {
- msg = StringResources.get('errorActionNotSupported', {
- sourceName: oDS.getSourceName() || oDS.getSourceId()
- });
- } else if (oErr && oErr.message) {
- msg = oErr.message;
- }
- }
- var oParam = {};
- if (oDS) {
- oParam = {
- 'datasetName': oDS.getSourceName() || oDS.getSourceId()
- };
- }
- if (failure.reason !== 'staleRequest') {
- this.visAPI.setInvalidReason({
- msg: msg,
- code: code
- });
- }
- return _.extend(new Error(), {
- msg: msg,
- param: oParam,
- hasUnavailableMetadataColumns: this._hasUnavailableMetadataColumns,
- errorInfo: failure
- });
- },
- getQueryService: function getQueryService() {
- return this.queryService;
- },
- /**
- * @return the query manager object which owns the query definition and results of
- * this widget's query.
- */
- getQueryManager: function getQueryManager() {
- return this._queryManager;
- },
- /**
- * @returns the query definition object which defines fields for the query.
- */
- getQueryDefinition: function getQueryDefinition() {
- return this.getQueryManager().getQueryDefinition();
- },
- /**
- * @returns the query results object which owns field values from the last executed query
- */
- getQueryResults: function getQueryResults() {
- return this.getQueryManager().getQueryResults();
- },
- savePromptSpec: function savePromptSpec(queryOptions) {
- this.ownerWidget.savePromptSpec(queryOptions);
- },
- getPromptSpec: function getPromptSpec(promptName) {
- return this.ownerWidget.getPromptSpec(promptName);
- },
- onCancelPromptDialog: function onCancelPromptDialog() {
- this.ownerWidget.onCancelPromptDialog();
- },
- updatePromptSpecCache: function updatePromptSpecCache(queryOptions) {
- var currPromptSpecs = queryOptions && queryOptions.querySpec ? queryOptions.querySpec.parameterValues : null;
- // When the query is nativeQuery, i.e. internally generated queries, we should not update saved prompts.
- // If UI knows which prompt is referenced by which data item, nativeQuery can be removed.
- if (!this.ownerWidget || queryOptions && queryOptions.nativeQuery) {
- return;
- }
- var savedSpecs = this.getPromptSpec();
- var newSpecs;
- if (savedSpecs) {
- if (currPromptSpecs && currPromptSpecs.length > 0) {
- var promptNames = _.pluck(currPromptSpecs, 'name');
- newSpecs = _.pick(savedSpecs, promptNames);
- }
- this.ownerWidget.setPromptSpecs(newSpecs);
- }
- },
- // this is called by reprompt.
- getPromptQueries: function getPromptQueries() {
- var module = this.metadataAPI.getModule();
- return {
- 'whenSingleItemQueryReady': this._commonQueryHelper.whenSingleItemQueryReady.bind(this._commonQueryHelper, module),
- 'whenColumnsMinMaxQueryReady': this._commonQueryHelper.whenColumnsMinMaxQueryReady.bind(this._commonQueryHelper, module),
- 'savePromptSpec': this.savePromptSpec.bind(this),
- 'updatePromptSpecCache': this.updatePromptSpecCache.bind(this)
- };
- },
- // TODO This function should be moved to PromptManager once we support OLAP prompts
- // and get rid of OLAP metadata checking (querySpecInvolvesOlapColumn).
- preparePromptSpec: function preparePromptSpec(jqXHR) {
- var errors = jqXHR.responseJSON.errors;
- var error = errors.length > 0 ? errors[0] : null;
- if (!error || !error.code) {
- return;
- }
- var params = error.parameters;
- if (!params || params.length === 0) {
- return;
- }
- var code = error.code;
- var aParamInfo = [];
- switch (code) {
- case 'QF-888':
- if (this.querySpecInvolvesOlapColumn()) {
- aParamInfo.push({
- involvesOlapColumn: true
- });
- } else {
- _.each(params, function (param) {
- param.value.name = param.name;
- param.value.errorCode = code;
- // TODO this part should be removed once the prompt fault has the query item ID refering the prompt.
- param.value.isMultiPrompt = params.length > 1;
- if (param.value.capabilities.optional) {
- // Do not prompt for optional prompt and save it with nil value so xqe will ignore this prompt.
- var optionalPrompt = _.extend(param.value, { values: [{ 'mun': 'nil' }] });
- this.ownerWidget.savePromptSpec(optionalPrompt);
- } else {
- aParamInfo.push(param.value);
- }
- }.bind(this));
- }
- break;
- default:
- break;
- }
- return aParamInfo;
- },
- querySpecInvolvesOlapColumn: function querySpecInvolvesOlapColumn() {
- var hasOlapColumn = false;
- var dataItemAPIs = this.ownerWidget.content.getFeature('Visualization').getSlots().getDataItemList();
- if (dataItemAPIs && dataItemAPIs.length > 0) {
- for (var i = 0; i < dataItemAPIs.length; ++i) {
- if (this._isOlapColumn(dataItemAPIs[i].getColumnId())) {
- hasOlapColumn = true;
- break;
- }
- }
- }
- return hasOlapColumn;
- },
- _isOlapColumn: function _isOlapColumn(columnId) {
- var metadataColumn = this.metadataAPI.getMetadataColumn(columnId);
- return metadataColumn && typeof metadataColumn.isOlapColumn === 'function' ? metadataColumn.isOlapColumn() : false;
- }
- });
- return VisQueryExecution;
- });
- //# sourceMappingURL=VisQueryExecution.js.map
|