UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

767 lines (728 loc) • 35.8 kB
/** * DevExtreme (ui/pivot_grid/xmla_store/xmla_store.js) * Version: 18.1.3 * Build date: Tue May 15 2018 * * Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var $ = require("../../../core/renderer"), window = require("../../../core/utils/window").getWindow(), Class = require("../../../core/class"), stringFormat = require("../../../core/utils/string").format, errors = require("../../../data/errors").errors, noop = require("../../../core/utils/common").noop, typeUtils = require("../../../core/utils/type"), iteratorUtils = require("../../../core/utils/iterator"), inArray = require("../../../core/utils/array").inArray, pivotGridUtils = require("../ui.pivot_grid.utils"), deferredUtils = require("../../../core/utils/deferred"), when = deferredUtils.when, Deferred = deferredUtils.Deferred, getLanguageId = require("../../../localization/language_codes").getLanguageId; exports.XmlaStore = Class.inherit(function() { var discover = '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body><Discover xmlns="urn:schemas-microsoft-com:xml-analysis"><RequestType>{2}</RequestType><Restrictions><RestrictionList><CATALOG_NAME>{0}</CATALOG_NAME><CUBE_NAME>{1}</CUBE_NAME></RestrictionList></Restrictions><Properties><PropertyList><Catalog>{0}</Catalog>{3}</PropertyList></Properties></Discover></Body></Envelope>', execute = '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"><Body><Execute xmlns="urn:schemas-microsoft-com:xml-analysis"><Command><Statement>{0}</Statement></Command><Properties><PropertyList><Catalog>{1}</Catalog><ShowHiddenCubes>True</ShowHiddenCubes><SspropInitAppName>Microsoft SQL Server Management Studio</SspropInitAppName><Timeout>3600</Timeout>{2}</PropertyList></Properties></Execute></Body></Envelope>', mdx = "SELECT {2} FROM {0} {1} CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS", mdxFilterSelect = "(SELECT {0} FROM {1})", mdxWith = "{0} {1} as {2}", mdxSlice = "WHERE ({0})", mdxNonEmpty = "NonEmpty({0}, {1})", mdxAxis = "{0} DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME, MEMBER_VALUE ON {1}", mdxCrossJoin = "CrossJoin({0})", mdxSet = "{{0}}", each = iteratorUtils.each, MEASURE_DEMENSION_KEY = "DX_MEASURES", MD_DIMTYPE_MEASURE = "2"; function execXMLA(requestOptions, data) { var deferred = new Deferred, beforeSend = requestOptions.beforeSend, ajaxSettings = { url: requestOptions.url, dataType: "text", data: data, headers: { "Content-Type": "text/xml" }, xhrFields: {}, method: "POST" }; if (typeUtils.isFunction(beforeSend)) { beforeSend(ajaxSettings) } pivotGridUtils.sendRequest(ajaxSettings).fail(function() { deferred.reject(arguments) }).done(function(text) { var parser = new window.DOMParser; var xml; try { try { xml = parser.parseFromString(text, "text/xml") } catch (e) { xml = void 0 } if (!xml || xml.getElementsByTagName("parsererror").length || 0 === xml.childNodes.length) { throw new errors.Error("E4023", text) } } catch (e) { deferred.reject({ statusText: e.message, stack: e.stack, responseText: text }) } deferred.resolve(xml) }); return deferred } function getLocaleIdProperty() { var languageId = getLanguageId(); if (void 0 !== languageId) { return stringFormat("<LocaleIdentifier>{0}</LocaleIdentifier>", languageId) } return "" } function mdxDescendants(level, levelMember, nextLevel) { var memberExpression = levelMember ? levelMember : level; return "Descendants({" + memberExpression + "}, " + nextLevel + ", SELF_AND_BEFORE)" } function getAllMember(dimension) { return (dimension.hierarchyName || dimension.dataField) + ".[All]" } function getAllMembers(field) { return field.dataField + ".allMembers" } function crossJoinElements(elements) { var elementsString = elements.join(","); return elements.length > 1 ? stringFormat(mdxCrossJoin, elementsString) : elementsString } function union(elements) { var elementsString = elements.join(","); return elements.length > 1 ? "Union(" + elementsString + ")" : elementsString } function generateCrossJoin(path, expandLevel, expandAllCount, expandIndex, slicePath, options, axisName) { var dataField, allMember, hierarchyName, arg, prevDimension, prevHierarchyName, isLastDimensionInGroup, isFirstDimensionInGroup, expandAllIndex, field, member, i, crossJoinArgs = [], dimensions = options[axisName], fields = []; for (i = expandIndex; i <= expandLevel; i++) { field = dimensions[i]; dataField = field.dataField; prevHierarchyName = dimensions[i - 1] && dimensions[i - 1].hierarchyName; hierarchyName = field.hierarchyName; isLastDimensionInGroup = !hierarchyName || !dimensions[i + 1] || dimensions[i + 1].hierarchyName !== hierarchyName; expandAllIndex = path.length + expandAllCount + expandIndex; arg = null; fields.push(field); if (i < path.length) { if (isLastDimensionInGroup) { arg = "(" + dataField + "." + preparePathValue(path[i], dataField) + ")" } } else { if (i <= expandAllIndex) { if (0 === i && 0 === expandAllCount) { allMember = getAllMember(dimensions[expandIndex]); if (!hierarchyName) { arg = getAllMembers(dimensions[expandIndex]) } else { arg = allMember + "," + dimensions[expandIndex].dataField } } else { if (hierarchyName) { member = preparePathValue(slicePath[slicePath.length - 1]); if (isLastDimensionInGroup || i === expandAllIndex) { if (prevHierarchyName === hierarchyName) { if (slicePath.length) { prevDimension = dimensions[slicePath.length - 1] } if (!prevDimension || prevDimension.hierarchyName !== hierarchyName) { prevDimension = dimensions[i - 1]; member = "" } arg = mdxDescendants(prevDimension.dataField, member, dataField) } else { arg = getAllMembers(field) } } } else { arg = getAllMembers(field) } } } else { isFirstDimensionInGroup = !hierarchyName || prevHierarchyName !== hierarchyName; if (isFirstDimensionInGroup) { arg = "(" + getAllMember(field) + ")" } } } if (arg) { arg = stringFormat(mdxSet, arg); crossJoinArgs.push(arg) } } return crossJoinElements(crossJoinArgs) } function fillCrossJoins(crossJoins, path, expandLevel, expandIndex, slicePath, options, axisName, cellsString) { var dimensionIndex, expandAllCount = -1, dimensions = options[axisName]; do { expandAllCount++; dimensionIndex = path.length + expandAllCount + expandIndex; crossJoins.push(stringFormat(mdxNonEmpty, generateCrossJoin(path, expandLevel, expandAllCount, expandIndex, slicePath, options, axisName), cellsString)) } while (dimensions[dimensionIndex] && dimensions[dimensionIndex + 1] && dimensions[dimensionIndex].expanded) } function declare(expression, withArray, name, type) { name = name || "[DX_Set_" + withArray.length + "]"; type = type || "set"; withArray.push(stringFormat(mdxWith, type, name, expression)); return name } function generateAxisMdx(options, axisName, cells, withArray, parseOptions) { var dimensions = options[axisName], crossJoins = [], path = [], expandedPaths = [], expandIndex = 0, expandLevel = 0, result = [], cellsString = stringFormat(mdxSet, cells.join(",")); if (dimensions && dimensions.length) { if (options.headerName === axisName) { path = options.path; expandIndex = path.length } else { expandedPaths = ("columns" === axisName ? options.columnExpandedPaths : options.rowExpandedPaths) || expandedPaths } expandLevel = pivotGridUtils.getExpandedLevel(options, axisName); fillCrossJoins(crossJoins, [], expandLevel, expandIndex, path, options, axisName, cellsString); each(expandedPaths, function(_, expandedPath) { fillCrossJoins(crossJoins, expandedPath, expandLevel, expandIndex, expandedPath, options, axisName, cellsString) }); for (var i = expandLevel; i >= path.length; i--) { if (dimensions[i].hierarchyName) { parseOptions.visibleLevels[dimensions[i].hierarchyName] = parseOptions.visibleLevels[dimensions[i].hierarchyName] || []; parseOptions.visibleLevels[dimensions[i].hierarchyName].push(dimensions[i].dataField) } } } if (crossJoins.length) { result.push(declare(union(crossJoins), withArray, "[DX_" + axisName + "]")) } if ("columns" === axisName && cells.length && !options.skipValues) { result.push(cellsString) } return stringFormat(mdxAxis, crossJoinElements(result), axisName) } function generateAxisFieldsFilter(fields) { var filterMembers = []; each(fields, function(_, field) { var filterStringExpression, dataField = field.dataField, filterExpression = [], filterValues = field.filterValues || []; if (field.hierarchyName && typeUtils.isNumeric(field.groupIndex)) { return } each(filterValues, function(_, filterValue) { var filterMdx = dataField + "." + preparePathValue(Array.isArray(filterValue) ? filterValue[filterValue.length - 1] : filterValue, dataField); if ("exclude" === field.filterType) { filterExpression.push(filterMdx + ".parent"); filterMdx = "Descendants(" + filterMdx + ")" } filterExpression.push(filterMdx) }); if (filterValues.length) { filterStringExpression = stringFormat(mdxSet, filterExpression.join(",")); if ("exclude" === field.filterType) { filterStringExpression = "Except(" + getAllMembers(field) + "," + filterStringExpression + ")" } filterMembers.push(filterStringExpression) } }); return filterMembers.length ? crossJoinElements(filterMembers) : "" } function generateFrom(columnsFilter, rowsFilter, filter, cubeName) { var from = "[" + cubeName + "]"; each([columnsFilter, rowsFilter, filter], function(_, filter) { if (filter) { from = stringFormat(mdxFilterSelect, filter + "on 0", from) } }); return from } function generateMdxCore(axisStrings, withArray, columns, rows, filters, slice, cubeName) { var mdxString = "", withString = (withArray.length ? "with " + withArray.join(" ") : "") + " "; if (axisStrings.length) { mdxString = withString + stringFormat(mdx, generateFrom(generateAxisFieldsFilter(columns), generateAxisFieldsFilter(rows), generateAxisFieldsFilter(filters || []), cubeName), slice.length ? stringFormat(mdxSlice, slice.join(",")) : "", axisStrings.join(",")) } return mdxString } function prepareDataFields(withArray, valueFields) { return iteratorUtils.map(valueFields, function(cell) { if (typeUtils.isString(cell.expression)) { declare(cell.expression, withArray, cell.dataField, "member") } return cell.dataField }) } function generateMDX(options, cubeName, parseOptions) { var columns = options.columns || [], rows = options.rows || [], values = options.values && options.values.length ? options.values : [{ dataField: "[Measures]" }], slice = [], withArray = [], axisStrings = [], dataFields = prepareDataFields(withArray, values); parseOptions.measureCount = options.skipValues ? 1 : values.length; parseOptions.visibleLevels = {}; if (options.headerName && options.path) { each(options.path, function(index, value) { var dimension = options[options.headerName][index]; if (!dimension.hierarchyName || dimension.hierarchyName !== options[options.headerName][index + 1].hierarchyName) { slice.push(dimension.dataField + "." + preparePathValue(value, dimension.dataField)) } }) } if (columns.length || dataFields.length) { axisStrings.push(generateAxisMdx(options, "columns", dataFields, withArray, parseOptions)) } if (rows.length) { axisStrings.push(generateAxisMdx(options, "rows", dataFields, withArray, parseOptions)) } return generateMdxCore(axisStrings, withArray, columns, rows, options.filters, slice, cubeName) } function createDrillDownAxisSlice(slice, fields, path) { each(path, function(index, value) { var field = fields[index]; if (field.hierarchyName && (fields[index + 1] || {}).hierarchyName === field.hierarchyName) { return } slice.push(field.dataField + "." + preparePathValue(value, field.dataField)) }) } function generateDrillDownMDX(options, cubeName, params) { var coreMDX, columns = options.columns || [], rows = options.rows || [], values = options.values && options.values.length ? options.values : [{ dataField: "[Measures]" }], slice = [], withArray = [], axisStrings = [], dataFields = prepareDataFields(withArray, values), maxRowCount = params.maxRowCount, customColumns = params.customColumns || [], customColumnsString = customColumns.length > 0 ? " return " + customColumns.join(",") : ""; createDrillDownAxisSlice(slice, columns, params.columnPath || []); createDrillDownAxisSlice(slice, rows, params.rowPath || []); if (columns.length || columns.length || dataFields.length) { axisStrings.push([(dataFields[params.dataIndex] || dataFields[0]) + " on 0"]) } coreMDX = generateMdxCore(axisStrings, withArray, columns, rows, options.filters, slice, cubeName); return coreMDX ? "drillthrough" + (maxRowCount > 0 ? " maxrows " + maxRowCount : "") + coreMDX + customColumnsString : coreMDX } function getNumber(str) { return parseInt(str, 10) } function parseValue(valueText) { return typeUtils.isNumeric(valueText) ? parseFloat(valueText) : valueText } function getFirstChild(node, tagName) { return (node.getElementsByTagName(tagName) || [])[0] } function getFirstChildText(node, childTagName) { return getNodeText(getFirstChild(node, childTagName)) } function parseAxes(xml, skipValues) { var axes = []; each(xml.getElementsByTagName("Axis"), function(_, axisElement) { var name = axisElement.getAttribute("name"), axis = [], index = 0; if (0 === name.indexOf("Axis") && typeUtils.isNumeric(getNumber(name.substr(4)))) { axes.push(axis); each(axisElement.getElementsByTagName("Tuple"), function(_, tupleElement) { var tuple, level, i, tupleMembers = tupleElement.childNodes, levelSum = 0, members = [], membersCount = skipValues ? tupleMembers.length : tupleMembers.length - 1, isAxisWithMeasure = 1 === axes.length; if (isAxisWithMeasure) { membersCount-- } axis.push(members); for (i = membersCount; i >= 0; i--) { tuple = tupleMembers[i]; level = getNumber(getFirstChildText(tuple, "LNum")); members[i] = { caption: getFirstChildText(tuple, "Caption"), value: parseValue(getFirstChildText(tuple, "MEMBER_VALUE")), level: level, index: index++, hasValue: !levelSum && (!!level || 0 === i), name: getFirstChildText(tuple, "UName"), hierarchyName: tupleMembers[i].getAttribute("Hierarchy"), parentName: getFirstChildText(tuple, "PARENT_UNIQUE_NAME"), levelName: getFirstChildText(tuple, "LName") }; levelSum += level } }) } }); while (axes.length < 2) { axes.push([ [{ level: 0 }] ]) } return axes } function getNodeText(node) { return node && node && (node.textContent || node.text || node.innerHTML) || "" } function parseCells(xml, axes, measureCount) { var measureIndex, row, cells = [], cell = [], index = 0, cellsOriginal = [], cellElements = xml.getElementsByTagName("Cell"), errorDictionary = {}; for (var i = 0; i < cellElements.length; i++) { var xmlCell = cellElements[i], valueElement = xmlCell.getElementsByTagName("Value")[0], errorElements = valueElement && valueElement.getElementsByTagName("Error") || [], text = 0 === errorElements.length ? getNodeText(valueElement) : "#N/A", value = parseFloat(text), isNumeric = text - value + 1 > 0, cellOrdinal = getNumber(xmlCell.getAttribute("CellOrdinal")); if (errorElements.length) { errorDictionary[getNodeText(errorElements[0].getElementsByTagName("ErrorCode")[0])] = getNodeText(errorElements[0].getElementsByTagName("Description")[0]) } cellsOriginal[cellOrdinal] = { value: isNumeric ? value : text || null } } each(axes[1], function() { row = []; cells.push(row); each(axes[0], function() { measureIndex = index % measureCount; if (0 === measureIndex) { cell = []; row.push(cell) } cell.push(cellsOriginal[index] ? cellsOriginal[index].value : null); index++ }) }); Object.keys(errorDictionary).forEach(function(key) { errors.log("W4002", errorDictionary[key]) }); return cells } function preparePathValue(pathValue, dataField) { if (pathValue) { pathValue = typeUtils.isString(pathValue) && pathValue.indexOf("&[") !== -1 ? pathValue : "[" + pathValue + "]"; if (dataField && 0 === pathValue.indexOf(dataField + ".")) { pathValue = pathValue.slice(dataField.length + 1, pathValue.length) } } return pathValue } function getItem(hash, name, member, index) { var item = hash[name]; if (!item) { item = {}; hash[name] = item } if (!item.value && member) { item.text = member.caption; item.value = member.value; item.key = name ? name : ""; item.levelName = member.levelName; item.hierarchyName = member.hierarchyName; item.parentName = member.parentName; item.index = index; item.level = member.level } return item } function getVisibleChildren(item, visibleLevels) { var result = [], children = item.children && (item.children.length ? item.children : iteratorUtils.map(item.children.grandTotalHash || [], function(e) { return e.children })), firstChild = children && children[0]; if (firstChild && (visibleLevels[firstChild.hierarchyName] && inArray(firstChild.levelName, visibleLevels[firstChild.hierarchyName]) !== -1 || !visibleLevels[firstChild.hierarchyName] || 0 === firstChild.level)) { var newChildren = iteratorUtils.map(children, function(child) { return child.hierarchyName === firstChild.hierarchyName ? child : null }); newChildren.grandTotalHash = children.grandTotalHash; return newChildren } else { if (firstChild) { for (var i = 0; i < children.length; i++) { if (children[i].hierarchyName === firstChild.hierarchyName) { result.push.apply(result, getVisibleChildren(children[i], visibleLevels)) } } } } return result } function processMember(dataIndex, member, parentItem) { var currentItem, children = parentItem.children = parentItem.children || [], hash = children.hash = children.hash || {}, grandTotalHash = children.grandTotalHash = children.grandTotalHash || {}; if (member.parentName) { parentItem = getItem(hash, member.parentName); children = parentItem.children = parentItem.children || [] } currentItem = getItem(hash, member.name, member, dataIndex); if (member.hasValue && !currentItem.added) { currentItem.index = dataIndex; currentItem.added = true; children.push(currentItem) } if ((!parentItem.value || !parentItem.parentName) && member.parentName) { grandTotalHash[member.parentName] = parentItem } else { if (grandTotalHash[parentItem.name]) { delete grandTotalHash[member.parentName] } } return currentItem } function getGrandTotalIndex(parentItem, visibleLevels) { var grandTotalIndex; if (1 === parentItem.children.length && "" === parentItem.children[0].parentName) { grandTotalIndex = parentItem.children[0].index; var grandTotalHash = parentItem.children.grandTotalHash; parentItem.children = parentItem.children[0].children || []; parentItem.children.grandTotalHash = grandTotalHash; parentItem.children = getVisibleChildren(parentItem, visibleLevels) } else { if (0 === parentItem.children.length) { grandTotalIndex = 0 } } return grandTotalIndex } function fillDataSourceAxes(dataSourceAxis, axisTuples, measureCount, visibleLevels) { var grandTotalIndex, result = []; each(axisTuples, function(tupleIndex, members) { var parentItem = { children: result }, dataIndex = typeUtils.isDefined(measureCount) ? Math.floor(tupleIndex / measureCount) : tupleIndex; each(members, function(_, member) { parentItem = processMember(dataIndex, member, parentItem) }) }); var parentItem = { children: result }; parentItem.children = getVisibleChildren(parentItem, visibleLevels); grandTotalIndex = getGrandTotalIndex(parentItem, visibleLevels); pivotGridUtils.foreachTree(parentItem.children, function(items) { var item = items[0], children = getVisibleChildren(item, visibleLevels); if (children.length) { item.children = children } else { delete item.children } delete item.levelName; delete item.hierarchyName; delete item.added; delete item.parentName; delete item.level }, true); each(parentItem.children || [], function(_, e) { dataSourceAxis.push(e) }); return grandTotalIndex } function checkError(xml) { var description, error, faultElementNS = xml.getElementsByTagName("soap:Fault"), faultElement = xml.getElementsByTagName("Fault"), errorElement = $([].slice.call(faultElement.length ? faultElement : faultElementNS)).find("Error"); if (errorElement.length) { description = errorElement.attr("Description"); error = new errors.Error("E4000", description); errors.log("E4000", description); return error } return null } function parseResult(xml, parseOptions) { var axes, dataSource = { columns: [], rows: [] }, measureCount = parseOptions.measureCount; axes = parseAxes(xml, parseOptions.skipValues); dataSource.grandTotalColumnIndex = fillDataSourceAxes(dataSource.columns, axes[0], measureCount, parseOptions.visibleLevels); dataSource.grandTotalRowIndex = fillDataSourceAxes(dataSource.rows, axes[1], void 0, parseOptions.visibleLevels); dataSource.values = parseCells(xml, axes, measureCount); return dataSource } function parseDiscoverRowSet(xml, schema, dimensions) { var result = [], isMeasure = "MEASURE" === schema, displayFolderField = isMeasure ? "MEASUREGROUP_NAME" : schema + "_DISPLAY_FOLDER"; each(xml.getElementsByTagName("row"), function(_, row) { var hierarchyName = "LEVEL" === schema ? getFirstChildText(row, "HIERARCHY_UNIQUE_NAME") : void 0, levelNumber = getFirstChildText(row, "LEVEL_NUMBER"); if (("0" !== levelNumber || "true" !== getFirstChildText(row, schema + "_IS_VISIBLE")) && getFirstChildText(row, "DIMENSION_TYPE") !== MD_DIMTYPE_MEASURE) { var dimension = isMeasure ? MEASURE_DEMENSION_KEY : getFirstChildText(row, "DIMENSION_UNIQUE_NAME"), dataField = getFirstChildText(row, schema + "_UNIQUE_NAME"); result.push({ dimension: dimensions.names[dimension] || dimension, groupIndex: levelNumber ? getNumber(levelNumber) - 1 : void 0, dataField: dataField, caption: getFirstChildText(row, schema + "_CAPTION"), hierarchyName: hierarchyName, groupName: hierarchyName, displayFolder: getFirstChildText(row, displayFolderField), isMeasure: isMeasure, isDefault: !!dimensions.defaultHierarchies[dataField] }) } }); return result } function parseDimensionsDiscoverRowSet(xml) { var result = { names: {}, defaultHierarchies: {} }; each($(xml).find("row"), function() { var $row = $(this), type = $row.children("DIMENSION_TYPE").text(), dimensionName = type === MD_DIMTYPE_MEASURE ? MEASURE_DEMENSION_KEY : $row.children("DIMENSION_UNIQUE_NAME").text(); result.names[dimensionName] = $row.children("DIMENSION_CAPTION").text(); result.defaultHierarchies[$row.children("DEFAULT_HIERARCHY").text()] = true }); return result } function parseStringWithUnicodeSymbols(str) { str = str.replace(/_x(....)_/g, function(whole, group1) { return String.fromCharCode(parseInt(group1, 16)) }); var stringArray = str.match(/\[.+?\]/gi); if (stringArray && stringArray.length) { str = stringArray[stringArray.length - 1] } return str.replace(/\[/gi, "").replace(/\]/gi, "").replace(/\$/gi, "").replace(/\./gi, " ") } function parseDrillDownRowSet(xml) { var rows = xml.getElementsByTagName("row"), result = [], columnNames = {}; for (var i = 0; i < rows.length; i++) { var children = rows[i].childNodes, item = {}; for (var j = 0; j < children.length; j++) { var tagName = children[j].tagName, name = columnNames[tagName] = columnNames[tagName] || parseStringWithUnicodeSymbols(tagName); item[name] = getNodeText(children[j]) } result.push(item) } return result } function sendQuery(storeOptions, mdxString) { mdxString = $("<div>").text(mdxString).html(); return execXMLA(storeOptions, stringFormat(execute, mdxString, storeOptions.catalog, getLocaleIdProperty())) } return { ctor: function(options) { this._options = options }, getFields: function() { var options = this._options, catalog = options.catalog, cube = options.cube, localeIdProperty = getLocaleIdProperty(), dimensionsRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_DIMENSIONS", localeIdProperty)), measuresRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_MEASURES", localeIdProperty)), hierarchiesRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_HIERARCHIES", localeIdProperty)), levelsRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_LEVELS", localeIdProperty)), result = new Deferred; when(dimensionsRequest, measuresRequest, hierarchiesRequest, levelsRequest).done(function(dimensionsResponse, measuresResponse, hierarchiesResponse, levelsResponse) { var dimensions = parseDimensionsDiscoverRowSet(dimensionsResponse), hierarchies = parseDiscoverRowSet(hierarchiesResponse, "HIERARCHY", dimensions), levels = parseDiscoverRowSet(levelsResponse, "LEVEL", dimensions), fields = parseDiscoverRowSet(measuresResponse, "MEASURE", dimensions).concat(hierarchies), levelsByHierarchy = {}; each(levels, function(_, level) { levelsByHierarchy[level.hierarchyName] = levelsByHierarchy[level.hierarchyName] || []; levelsByHierarchy[level.hierarchyName].push(level) }); each(hierarchies, function(_, hierarchy) { if (levelsByHierarchy[hierarchy.dataField] && levelsByHierarchy[hierarchy.dataField].length > 1) { hierarchy.groupName = hierarchy.hierarchyName = hierarchy.dataField; fields.push.apply(fields, levelsByHierarchy[hierarchy.hierarchyName]) } }); result.resolve(fields) }).fail(result.reject); return result }, load: function(options) { var result = new Deferred, storeOptions = this._options, parseOptions = { skipValues: options.skipValues }, mdxString = generateMDX(options, storeOptions.cube, parseOptions); if (mdxString) { when(sendQuery(storeOptions, mdxString)).done(function(executeXml) { var error = checkError(executeXml); if (!error) { result.resolve(parseResult(executeXml, parseOptions)) } else { result.reject(error) } }).fail(result.reject) } else { result.resolve({ columns: [], rows: [], values: [], grandTotalColumnIndex: 0, grandTotalRowIndex: 0 }) } return result }, supportSorting: function() { return true }, getDrillDownItems: function(options, params) { var result = new Deferred, storeOptions = this._options, mdxString = generateDrillDownMDX(options, storeOptions.cube, params); if (mdxString) { when(sendQuery(storeOptions, mdxString)).done(function(executeXml) { var error = checkError(executeXml); if (!error) { result.resolve(parseDrillDownRowSet(executeXml)) } else { result.reject(error) } }).fail(result.reject) } else { result.resolve([]) } return result }, key: noop, filter: noop } }()).include(pivotGridUtils.storeDrillDownMixin);