UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

895 lines (865 loc) • 43.2 kB
/** * DevExtreme (esm/__internal/grids/pivot_grid/xmla_store/module.js) * Version: 22.1.9 * Build date: Tue Apr 18 2023 * * Copyright (c) 2012 - 2023 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import $ from "../../../../core/renderer"; import { getWindow } from "../../../../core/utils/window"; import Class from "../../../../core/class"; import { format as stringFormat } from "../../../../core/utils/string"; import { errors } from "../../../../data/errors"; import { noop } from "../../../../core/utils/common"; import { extend } from "../../../../core/utils/extend"; import { isFunction, isNumeric, isDefined, isString } from "../../../../core/utils/type"; import { map, each } from "../../../../core/utils/iterator"; import { when, Deferred } from "../../../../core/utils/deferred"; import { getLanguageId } from "../../../../localization/language_codes"; import pivotGridUtils, { getExpandedLevel, storeDrillDownMixin, foreachTree } from "../module_widget_utils"; const window = getWindow(); const XmlaStore = Class.inherit(function() { const 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>'; function execXMLA(requestOptions, data) { const deferred = new Deferred; const { beforeSend: beforeSend } = requestOptions; const ajaxSettings = { url: requestOptions.url, dataType: "text", data: data, headers: { "Content-Type": "text/xml" }, xhrFields: {}, method: "POST" }; if (isFunction(beforeSend)) { beforeSend(ajaxSettings) } pivotGridUtils.sendRequest(ajaxSettings).fail((function() { deferred.reject(arguments) })).done(text => { const parser = new window.DOMParser; let 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() { const languageId = getLanguageId(); if (void 0 !== languageId) { return stringFormat("<LocaleIdentifier>{0}</LocaleIdentifier>", languageId) } return "" } function mdxDescendants(level, levelMember, nextLevel) { const memberExpression = levelMember || level; return `Descendants({${memberExpression}}, ${nextLevel}, SELF_AND_BEFORE)` } function getAllMember(dimension) { return (dimension.hierarchyName || dimension.dataField) + ".[All]" } function getAllMembers(field) { let result = field.dataField + ".allMembers"; let { searchValue: searchValue } = field; if (searchValue) { searchValue = searchValue.replace(/'/g, "''"); result = `Filter(${result}, instr(${field.dataField}.currentmember.member_caption,'${searchValue}') > 0)` } return result } function crossJoinElements(elements) { const elementsString = elements.join(","); return elements.length > 1 ? stringFormat("CrossJoin({0})", elementsString) : elementsString } function generateCrossJoin(path, expandLevel, expandAllCount, expandIndex, slicePath, options, axisName, take) { const crossJoinArgs = []; const dimensions = options[axisName]; const fields = []; let arg; let prevDimension; let member; for (let i = expandIndex; i <= expandLevel; i += 1) { const field = dimensions[i]; const { dataField: dataField } = field; const prevHierarchyName = dimensions[i - 1] && dimensions[i - 1].hierarchyName; const { hierarchyName: hierarchyName } = field; const isLastDimensionInGroup = !hierarchyName || !dimensions[i + 1] || dimensions[i + 1].hierarchyName !== hierarchyName; const 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) { const 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 { const isFirstDimensionInGroup = !hierarchyName || prevHierarchyName !== hierarchyName; if (isFirstDimensionInGroup) { arg = `(${getAllMember(field)})` } } if (arg) { arg = stringFormat("{{0}}", arg); if (take) { const sortBy = (field.hierarchyName || field.dataField) + ("displayText" === field.sortBy ? ".MEMBER_CAPTION" : ".MEMBER_VALUE"); arg = stringFormat("Order({0}, {1}, {2})", arg, sortBy, "desc" === field.sortOrder ? "DESC" : "ASC") } crossJoinArgs.push(arg) } } return crossJoinElements(crossJoinArgs) } function fillCrossJoins(crossJoins, path, expandLevel, expandIndex, slicePath, options, axisName, cellsString, take, totalsOnly) { let expandAllCount = -1; const dimensions = options[axisName]; let dimensionIndex; do { expandAllCount += 1; dimensionIndex = path.length + expandAllCount + expandIndex; let crossJoin = generateCrossJoin(path, expandLevel, expandAllCount, expandIndex, slicePath, options, axisName, take); if (!take && !totalsOnly) { crossJoin = stringFormat("NonEmpty({0}, {1})", crossJoin, cellsString) } crossJoins.push(crossJoin) } 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("{0} {1} as {2}", type, name, expression)); return name } function generateAxisMdx(options, axisName, cells, withArray, parseOptions) { const dimensions = options[axisName]; const crossJoins = []; let path = []; let expandedPaths = []; let expandIndex = 0; let expandLevel = 0; const result = []; const cellsString = stringFormat("{{0}}", cells.join(",")); if (dimensions && dimensions.length) { if (options.headerName === axisName) { path = options.path; expandIndex = path.length } else if (options.headerName && options.oppositePath) { path = options.oppositePath; expandIndex = path.length } else { expandedPaths = ("columns" === axisName ? options.columnExpandedPaths : options.rowExpandedPaths) || expandedPaths } expandLevel = getExpandedLevel(options, axisName); fillCrossJoins(crossJoins, [], expandLevel, expandIndex, path, options, axisName, cellsString, "rows" === axisName ? options.rowTake : options.columnTake, options.totalsOnly); each(expandedPaths, (_, expandedPath) => { fillCrossJoins(crossJoins, expandedPath, expandLevel, expandIndex, expandedPath, options, axisName, cellsString) }); for (let i = expandLevel; i >= path.length; i -= 1) { 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) { let expression = function(elements) { const elementsString = elements.join(","); return elements.length > 1 ? `Union(${elementsString})` : elementsString }(crossJoins); if ("rows" === axisName && options.rowTake) { expression = stringFormat("Subset({0}, {1}, {2})", expression, options.rowSkip > 0 ? options.rowSkip + 1 : 0, options.rowSkip > 0 ? options.rowTake : options.rowTake + 1) } if ("columns" === axisName && options.columnTake) { expression = stringFormat("Subset({0}, {1}, {2})", expression, options.columnSkip > 0 ? options.columnSkip + 1 : 0, options.columnSkip > 0 ? options.columnTake : options.columnTake + 1) } const axisSet = `[DX_${axisName}]`; result.push(declare(expression, withArray, axisSet)); if (options.totalsOnly) { result.push(declare(`COUNT(${axisSet})`, withArray, `[DX_${axisName}_count]`, "member")) } } if ("columns" === axisName && cells.length && !options.skipValues) { result.push(cellsString) } return stringFormat("{0} DIMENSION PROPERTIES PARENT_UNIQUE_NAME,HIERARCHY_UNIQUE_NAME, MEMBER_VALUE ON {1}", crossJoinElements(result), axisName) } function generateAxisFieldsFilter(fields) { const filterMembers = []; each(fields, (_, field) => { const { dataField: dataField } = field; const filterExpression = []; const filterValues = field.filterValues || []; let filterStringExpression; if (field.hierarchyName && isNumeric(field.groupIndex)) { return } each(filterValues, (_, filterValue) => { let 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("{{0}}", filterExpression.join(",")); if ("exclude" === field.filterType) { filterStringExpression = `Except(${getAllMembers(field)},${filterStringExpression})` } filterMembers.push(filterStringExpression) } }); return filterMembers.length ? crossJoinElements(filterMembers) : "" } function generateMdxCore(axisStrings, withArray, columns, rows, filters, slice, cubeName, options = {}) { let mdxString = ""; const withString = (withArray.length ? "with " + withArray.join(" ") : "") + " "; if (axisStrings.length) { let select; if (options.totalsOnly) { const countMembers = []; if (rows.length) { countMembers.push("[DX_rows_count]") } if (columns.length) { countMembers.push("[DX_columns_count]") } select = `{${countMembers.join(",")}} on columns` } else { select = axisStrings.join(",") } mdxString = withString + stringFormat("SELECT {2} FROM {0} {1} CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS", function(columnsFilter, rowsFilter, filter, cubeName) { let from = `[${cubeName}]`; each([columnsFilter, rowsFilter, filter], (_, filter) => { if (filter) { from = stringFormat("(SELECT {0} FROM {1})", filter + "on 0", from) } }); return from }(generateAxisFieldsFilter(columns), generateAxisFieldsFilter(rows), generateAxisFieldsFilter(filters || []), cubeName), slice.length ? stringFormat("WHERE ({0})", slice.join(",")) : "", select) } return mdxString } function prepareDataFields(withArray, valueFields) { return map(valueFields, cell => { if (isString(cell.expression)) { declare(cell.expression, withArray, cell.dataField, "member") } return cell.dataField }) } function addSlices(slices, options, headerName, path) { each(path, (index, value) => { const dimension = options[headerName][index]; if (!dimension.hierarchyName || dimension.hierarchyName !== options[headerName][index + 1].hierarchyName) { slices.push(`${dimension.dataField}.${preparePathValue(value,dimension.dataField)}`) } }) } function generateMDX(options, cubeName, parseOptions) { const columns = options.columns || []; const rows = options.rows || []; const values = options.values && options.values.length ? options.values : [{ dataField: "[Measures]" }]; const slice = []; const withArray = []; const axisStrings = []; const dataFields = prepareDataFields(withArray, values); parseOptions.measureCount = options.skipValues ? 1 : values.length; parseOptions.visibleLevels = {}; if (options.headerName && options.path) { addSlices(slice, options, options.headerName, options.path) } if (options.headerName && options.oppositePath) { addSlices(slice, options, "rows" === options.headerName ? "columns" : "rows", options.oppositePath) } 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, options) } function createDrillDownAxisSlice(slice, fields, path) { each(path, (index, value) => { const field = fields[index]; if (field.hierarchyName && (fields[index + 1] || {}).hierarchyName === field.hierarchyName) { return } slice.push(`${field.dataField}.${preparePathValue(value,field.dataField)}`) }) } function getNumber(str) { return parseInt(str, 10) } function getFirstChildText(node, childTagName) { return getNodeText(function(node, tagName) { return (node.getElementsByTagName(tagName) || [])[0] }(node, childTagName)) } function getNodeText(node) { return node && (node.textContent || node.text || node.innerHTML) || "" } function parseCells(xml, axes, measureCount) { const cells = []; let cell = []; let index = 0; const cellsOriginal = []; const cellElements = xml.getElementsByTagName("Cell"); const errorDictionary = {}; for (let i = 0; i < cellElements.length; i += 1) { const xmlCell = cellElements[i]; const valueElement = xmlCell.getElementsByTagName("Value")[0]; const errorElements = valueElement && valueElement.getElementsByTagName("Error") || []; const text = 0 === errorElements.length ? getNodeText(valueElement) : "#N/A"; const value = parseFloat(text); const isNumeric = text - value + 1 > 0; const 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], () => { const row = []; cells.push(row); each(axes[0], () => { const measureIndex = index % measureCount; if (0 === measureIndex) { cell = []; row.push(cell) } cell.push(cellsOriginal[index] ? cellsOriginal[index].value : null); index += 1 }) }); Object.keys(errorDictionary).forEach(key => { errors.log("W4002", errorDictionary[key]) }); return cells } function preparePathValue(pathValue, dataField) { if (pathValue) { pathValue = isString(pathValue) && pathValue.includes("&") ? pathValue : `[${pathValue}]`; if (dataField && 0 === pathValue.indexOf(dataField + ".")) { pathValue = pathValue.slice(dataField.length + 1, pathValue.length) } } return pathValue } function getItem(hash, name, member, index) { let item = hash[name]; if (!item) { item = {}; hash[name] = item } if (!isDefined(item.value) && member) { item.text = member.caption; item.value = member.value; item.key = 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) { const result = []; const children = item.children && (item.children.length ? item.children : Object.keys(item.children.grandTotalHash || {}).reduce((result, name) => result.concat(item.children.grandTotalHash[name].children), [])); const firstChild = children && children[0]; if (firstChild && (visibleLevels[firstChild.hierarchyName] && visibleLevels[firstChild.hierarchyName].includes(firstChild.levelName) || !visibleLevels[firstChild.hierarchyName] || 0 === firstChild.level)) { const newChildren = children.filter(child => child.hierarchyName === firstChild.hierarchyName); newChildren.grandTotalHash = children.grandTotalHash; return newChildren } if (firstChild) { for (let i = 0; i < children.length; i += 1) { if (children[i].hierarchyName === firstChild.hierarchyName) { result.push.apply(result, getVisibleChildren(children[i], visibleLevels)) } } } return result } function fillDataSourceAxes(dataSourceAxis, axisTuples, measureCount, visibleLevels) { const result = []; each(axisTuples, (tupleIndex, members) => { let parentItem = { children: result }; const dataIndex = isDefined(measureCount) ? Math.floor(tupleIndex / measureCount) : tupleIndex; each(members, (_, member) => { parentItem = function(dataIndex, member, parentItem) { let children = parentItem.children = parentItem.children || []; const hash = children.hash = children.hash || {}; const grandTotalHash = children.grandTotalHash = children.grandTotalHash || {}; if (member.parentName) { parentItem = getItem(hash, member.parentName); children = parentItem.children = parentItem.children || [] } const 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 }(dataIndex, member, parentItem) }) }); const parentItem = { children: result }; parentItem.children = getVisibleChildren(parentItem, visibleLevels); const grandTotalIndex = function(parentItem, visibleLevels) { let grandTotalIndex; if (1 === parentItem.children.length && "" === parentItem.children[0].parentName) { grandTotalIndex = parentItem.children[0].index; const { grandTotalHash: grandTotalHash } = parentItem.children; 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 }(parentItem, visibleLevels); foreachTree(parentItem.children, items => { const item = items[0]; const 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 || [], (_, e) => { dataSourceAxis.push(e) }); return grandTotalIndex } function checkError(xml) { const faultElementNS = xml.getElementsByTagName("soap:Fault"); const faultElement = xml.getElementsByTagName("Fault"); const errorElement = $([].slice.call(faultElement.length ? faultElement : faultElementNS)).find("Error"); if (errorElement.length) { const description = errorElement.attr("Description"); const error = new errors.Error("E4000", description); errors.log("E4000", description); return error } return null } function parseResult(xml, parseOptions) { const dataSource = { columns: [], rows: [] }; const { measureCount: measureCount } = parseOptions; const axes = function(xml, skipValues) { const axes = []; each(xml.getElementsByTagName("Axis"), (_, axisElement) => { const name = axisElement.getAttribute("name"); const axis = []; let index = 0; if (0 === name.indexOf("Axis") && isNumeric(getNumber(name.substr(4)))) { axes.push(axis); each(axisElement.getElementsByTagName("Tuple"), (_, tupleElement) => { const tupleMembers = tupleElement.childNodes; let levelSum = 0; const members = []; let membersCount = skipValues ? tupleMembers.length : tupleMembers.length - 1; const isAxisWithMeasure = 1 === axes.length; if (isAxisWithMeasure) { membersCount -= 1 } axis.push(members); for (let i = membersCount; i >= 0; i -= 1) { const tuple = tupleMembers[i]; const level = getNumber(getFirstChildText(tuple, "LNum")); members[i] = { caption: getFirstChildText(tuple, "Caption"), value: (valueText = getFirstChildText(tuple, "MEMBER_VALUE"), isNumeric(valueText) ? parseFloat(valueText) : valueText), 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 } var valueText }) } }); while (axes.length < 2) { axes.push([ [{ level: 0 }] ]) } return axes }(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, translatedDisplayFolders) { const result = []; const isMeasure = "MEASURE" === schema; const displayFolderField = isMeasure ? "MEASUREGROUP_NAME" : schema + "_DISPLAY_FOLDER"; each(xml.getElementsByTagName("row"), (_, row) => { const hierarchyName = "LEVEL" === schema ? getFirstChildText(row, "HIERARCHY_UNIQUE_NAME") : void 0; const levelNumber = getFirstChildText(row, "LEVEL_NUMBER"); let displayFolder = getFirstChildText(row, displayFolderField); if (isMeasure) { displayFolder = translatedDisplayFolders[displayFolder] || displayFolder } if (("0" !== levelNumber || "true" !== getFirstChildText(row, schema + "_IS_VISIBLE")) && "2" !== getFirstChildText(row, "DIMENSION_TYPE")) { const dimension = isMeasure ? "DX_MEASURES" : getFirstChildText(row, "DIMENSION_UNIQUE_NAME"); const 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: displayFolder, isMeasure: isMeasure, isDefault: !!dimensions.defaultHierarchies[dataField] }) } }); return result } function parseStringWithUnicodeSymbols(str) { str = str.replace(/_x(....)_/g, (_, group1) => String.fromCharCode(parseInt(group1, 16))); const stringArray = str.match(/\[.+?\]/gi); if (stringArray && stringArray.length) { str = stringArray[stringArray.length - 1] } return str.replace(/\[/gi, "").replace(/\]/gi, "").replace(/\$/gi, "").replace(/\./gi, " ") } function sendQuery(storeOptions, mdxString) { mdxString = $("<div>").text(mdxString).html(); return execXMLA(storeOptions, stringFormat('<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>', mdxString, storeOptions.catalog, getLocaleIdProperty())) } return { ctor(options) { this._options = options }, getFields() { const options = this._options; const { catalog: catalog } = options; const { cube: cube } = options; const localeIdProperty = getLocaleIdProperty(); const dimensionsRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_DIMENSIONS", localeIdProperty)); const measuresRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_MEASURES", localeIdProperty)); const hierarchiesRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_HIERARCHIES", localeIdProperty)); const levelsRequest = execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_LEVELS", localeIdProperty)); const result = new Deferred; when(dimensionsRequest, measuresRequest, hierarchiesRequest, levelsRequest).then((dimensionsResponse, measuresResponse, hierarchiesResponse, levelsResponse) => { execXMLA(options, stringFormat(discover, catalog, cube, "MDSCHEMA_MEASUREGROUPS", localeIdProperty)).done(measureGroupsResponse => { const dimensions = function(xml) { const result = { names: {}, defaultHierarchies: {} }; each($(xml).find("row"), (function() { const $row = $(this); const type = $row.children("DIMENSION_TYPE").text(); const dimensionName = "2" === type ? "DX_MEASURES" : $row.children("DIMENSION_UNIQUE_NAME").text(); result.names[dimensionName] = $row.children("DIMENSION_CAPTION").text(); result.defaultHierarchies[$row.children("DEFAULT_HIERARCHY").text()] = true })); return result }(dimensionsResponse); const hierarchies = parseDiscoverRowSet(hierarchiesResponse, "HIERARCHY", dimensions); const levels = parseDiscoverRowSet(levelsResponse, "LEVEL", dimensions); const measureGroups = function(xml) { const measureGroups = {}; each(xml.getElementsByTagName("row"), (_, row) => { measureGroups[getFirstChildText(row, "MEASUREGROUP_NAME")] = getFirstChildText(row, "MEASUREGROUP_CAPTION") }); return measureGroups }(measureGroupsResponse); const fields = parseDiscoverRowSet(measuresResponse, "MEASURE", dimensions, measureGroups).concat(hierarchies); const levelsByHierarchy = {}; each(levels, (_, level) => { levelsByHierarchy[level.hierarchyName] = levelsByHierarchy[level.hierarchyName] || []; levelsByHierarchy[level.hierarchyName].push(level) }); each(hierarchies, (_, 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) }).fail(result.reject); return result }, load(options) { const result = new Deferred; const storeOptions = this._options; const parseOptions = { skipValues: options.skipValues }; const mdxString = generateMDX(options, storeOptions.cube, parseOptions); let rowCountMdx; if (options.rowSkip || options.rowTake || options.columnTake || options.columnSkip) { rowCountMdx = generateMDX(extend({}, options, { totalsOnly: true, rowSkip: null, rowTake: null, columnSkip: null, columnTake: null }), storeOptions.cube, {}) } const load = () => { if (mdxString) { when(sendQuery(storeOptions, mdxString), rowCountMdx && sendQuery(storeOptions, rowCountMdx)).done((executeXml, rowCountXml) => { const error = checkError(executeXml) || rowCountXml && checkError(rowCountXml); if (!error) { const response = parseResult(executeXml, parseOptions); if (rowCountXml) { ! function(data, options, totalCountXml) { const axes = []; const columnOptions = options.columns || []; const rowOptions = options.rows || []; if (columnOptions.length) { axes.push({}) } if (rowOptions.length) { axes.push({}) } const cells = parseCells(totalCountXml, [ [{}], [{}, {}] ], 1); if (!columnOptions.length && rowOptions.length) { data.rowCount = Math.max(cells[0][0][0] - 1, 0) } if (!rowOptions.length && columnOptions.length) { data.columnCount = Math.max(cells[0][0][0] - 1, 0) } if (rowOptions.length && columnOptions.length) { data.rowCount = Math.max(cells[0][0][0] - 1, 0); data.columnCount = Math.max(cells[1][0][0] - 1, 0) } if (void 0 !== data.rowCount && options.rowTake) { data.rows = [...Array(options.rowSkip)].concat(data.rows); data.rows.length = data.rowCount; for (let i = 0; i < data.rows.length; i += 1) { data.rows[i] = data.rows[i] || {} } } if (void 0 !== data.columnCount && options.columnTake) { data.columns = [...Array(options.columnSkip)].concat(data.columns); data.columns.length = data.columnCount; for (let i = 0; i < data.columns.length; i += 1) { data.columns[i] = data.columns[i] || {} } } }(response, options, rowCountXml) } result.resolve(response) } else { result.reject(error) } }).fail(result.reject) } else { result.resolve({ columns: [], rows: [], values: [], grandTotalColumnIndex: 0, grandTotalRowIndex: 0 }) } }; if (options.delay) { setTimeout(load, options.delay) } else { load() } return result }, supportPaging: () => true, getDrillDownItems(options, params) { const result = new Deferred; const storeOptions = this._options; const mdxString = function(options, cubeName, params) { const columns = options.columns || []; const rows = options.rows || []; const values = options.values && options.values.length ? options.values : [{ dataField: "[Measures]" }]; const slice = []; const withArray = []; const axisStrings = []; const dataFields = prepareDataFields(withArray, values); const { maxRowCount: maxRowCount } = params; const customColumns = params.customColumns || []; const customColumnsString = customColumns.length > 0 ? " return " + customColumns.join(",") : ""; createDrillDownAxisSlice(slice, columns, params.columnPath || []); createDrillDownAxisSlice(slice, rows, params.rowPath || []); if (columns.length || dataFields.length) { axisStrings.push([(dataFields[params.dataIndex] || dataFields[0]) + " on 0"]) } const coreMDX = generateMdxCore(axisStrings, withArray, columns, rows, options.filters, slice, cubeName); return coreMDX ? `drillthrough${maxRowCount>0?" maxrows "+maxRowCount:""}${coreMDX}${customColumnsString}` : coreMDX }(options, storeOptions.cube, params); if (mdxString) { when(sendQuery(storeOptions, mdxString)).done(executeXml => { const error = checkError(executeXml); if (!error) { result.resolve(function(xml) { const rows = xml.getElementsByTagName("row"); const result = []; const columnNames = {}; for (let i = 0; i < rows.length; i += 1) { const children = rows[i].childNodes; const item = {}; for (let j = 0; j < children.length; j += 1) { const { tagName: tagName } = children[j]; const name = columnNames[tagName] = columnNames[tagName] || parseStringWithUnicodeSymbols(tagName); item[name] = getNodeText(children[j]) } result.push(item) } return result }(executeXml)) } else { result.reject(error) } }).fail(result.reject) } else { result.resolve([]) } return result }, key: noop, filter: noop } }()).include(storeDrillDownMixin); export default { XmlaStore: XmlaStore }; export { XmlaStore };