Commit 64486df0 authored by Stefane Fermigier's avatar Stefane Fermigier

"On rows".

parent 26bd503c
...@@ -127,6 +127,23 @@ class MdxEngine: ...@@ -127,6 +127,23 @@ class MdxEngine:
""" """
return os.path.join(self.cube_path, self.cube) return os.path.join(self.cube_path, self.cube)
# TODO temporary function
def get_tuples(self, query, start=None, stop=None):
# TODO use grako instead and remove regex
regex = "(\[[\w\d ]+\](\.\[[\w\d\.\- ]+\])*\.?((Members)|(\[Q\d\]))?)"
if start is not None:
start = query.index(start)
if stop is not None:
stop = query.index(stop)
# clean the query (from All, Members...)
return [[
tup_att.replace('All ', '').replace('[', "").replace("]", "")
for tup_att in tup[0].replace('.Members', '').split('.')
] for tup in re.compile(regex).findall(query[start:stop])
if len(tup[0].split('.')) > 1]
# TODO temporary function # TODO temporary function
def decorticate_query(self, query): def decorticate_query(self, query):
""" """
...@@ -135,16 +152,38 @@ class MdxEngine: ...@@ -135,16 +152,38 @@ class MdxEngine:
:return: all tuples in the query :return: all tuples in the query
""" """
# TODO use grako instead and remove regex tuples_on_mdx_query = self.get_tuples(query)
regex = "(\[[\w\d ]+\](\.\[[\w\d\.\- ]+\])*\.?((Members)|(\[Q\d\]))?)"
# clean the query on_rows = []
tuples_on_mdx_query = [[ on_columns = []
tup_att.replace('All ', '').replace('[', "").replace("]", "") on_where = []
for tup_att in tup[0].replace('.Members', '').split('.')
] for tup in re.compile(regex).findall(query)
if len(tup[0].split('.')) > 1]
return tuples_on_mdx_query # ON ROWS
if 'ON ROWS' in query:
stop = 'ON ROWS'
if 'ON COLUMNS' in query:
start = 'ON COLUMNS'
else:
start = 'SELECT'
on_rows = self.get_tuples(query, start, stop)
# ON COLUMNS
if 'ON COLUMNS' in query:
start = 'SELECT'
stop = 'ON COLUMNS'
on_columns = self.get_tuples(query, start, stop)
# WHERE
if 'WHERE' in query:
start = 'FROM'
on_where = self.get_tuples(query, start)
return {
'all': tuples_on_mdx_query,
'columns': on_columns,
'rows': on_rows,
'where': on_where
}
def change_measures(self, tuples_on_mdx): def change_measures(self, tuples_on_mdx):
""" """
...@@ -161,6 +200,7 @@ class MdxEngine: ...@@ -161,6 +200,7 @@ class MdxEngine:
] ]
def get_tables_and_columns(self, tuple_as_list): def get_tables_and_columns(self, tuple_as_list):
# TODO update docstring
""" """
get used dimensions and columns in the MDX Query (useful for DataFrame -> xmla response transformation) get used dimensions and columns in the MDX Query (useful for DataFrame -> xmla response transformation)
...@@ -178,23 +218,31 @@ class MdxEngine: ...@@ -178,23 +218,31 @@ class MdxEngine:
Facts : ['Amount','Count'] Facts : ['Amount','Count']
} }
""" """
tables_columns = OrderedDict()
axes = {}
# TODO optimize # TODO optimize
measures = [] for axis, tuples in tuple_as_list.items():
for tupl in tuple_as_list: measures = []
tables_columns = OrderedDict()
# if we have measures in columns or rows axes like : # if we have measures in columns or rows axes like :
# SELECT {[Measures].[Amount],[Measures].[Count]} ON COLUMNS # SELECT {[Measures].[Amount],[Measures].[Count]} ON COLUMNS
# we have to add measures directly to tables_columns # we have to add measures directly to tables_columns
if tupl[0].upper() == 'MEASURES': for tupl in tuples:
measures.append(tupl[-1]) if tupl[0].upper() == 'MEASURES':
tables_columns.update({self.facts: measures}) if tupl[-1] not in measures:
else: measures.append(tupl[-1])
tables_columns.update({ tables_columns.update({self.facts: measures})
tupl[0]: else:
self.tables_loaded[tupl[0]].columns[:len(tupl[2:])] continue
}) else:
tables_columns.update({
return tables_columns tupl[0]:
self.tables_loaded[tupl[0]].columns[:len(tupl[2:])]
})
axes.update({axis: tables_columns})
return axes
def execute_one_tuple(self, tuple_as_list, Dataframe_in, columns_to_keep): def execute_one_tuple(self, tuple_as_list, Dataframe_in, columns_to_keep):
""" """
...@@ -397,24 +445,21 @@ class MdxEngine: ...@@ -397,24 +445,21 @@ class MdxEngine:
""" """
# use measures that exists on where or insides axes # use measures that exists on where or insides axes
all_tuples = self.decorticate_query(self.mdx_query) query_axes = self.decorticate_query(self.mdx_query)
if self.change_measures(all_tuples): if self.change_measures(query_axes['all']):
self.measures = self.change_measures(all_tuples) self.measures = self.change_measures(query_axes['all'])
# get only used columns and dimensions for all query # get only used columns and dimensions for all query
start_df = self.load_star_schema_dataframe start_df = self.load_star_schema_dataframe
tables_n_columns = self.get_tables_and_columns(all_tuples) tables_n_columns = self.get_tables_and_columns(query_axes)
columns_to_keep = { columns_to_keep = OrderedDict(
table: columns (table, columns) for table, columns in tables_n_columns['all'].items() if table != self.facts)
for table, columns in tables_n_columns.items()
if table != self.facts
}
# if we have measures on axes we have to ignore them # if we have measures on axes we have to ignore them
tuples_on_mdx_query = [ tuples_on_mdx_query = [
tup for tup in all_tuples if tup[0].upper() != 'MEASURES' tup for tup in query_axes['all'] if tup[0].upper() != 'MEASURES'
] ]
# if we have tuples in axes # if we have tuples in axes
# to avoid prob with query like this: SELECT FROM [Sales] WHERE ([Measures].[Amount]) # to avoid prob with query like this: SELECT FROM [Sales] WHERE ([Measures].[Amount])
...@@ -469,6 +514,7 @@ class MdxEngine: ...@@ -469,6 +514,7 @@ class MdxEngine:
df = pd.concat(self.add_missed_column(df, next_df)) df = pd.concat(self.add_missed_column(df, next_df))
# TODO groupby in web demo (remove it for more performance) # TODO groupby in web demo (remove it for more performance)
# TODO margins=True for columns total !!!!!
return { return {
'result': 'result':
df.drop_duplicates().replace(np.nan, -1).groupby(cols).sum(), df.drop_duplicates().replace(np.nan, -1).groupby(cols).sum(),
......
...@@ -81,22 +81,27 @@ class XmlaProviderService(ServiceBase): ...@@ -81,22 +81,27 @@ class XmlaProviderService(ServiceBase):
return discover_tools.discover_mdschema_measures__response(request) return discover_tools.discover_mdschema_measures__response(request)
elif request.RequestType == "MDSCHEMA_DIMENSIONS": elif request.RequestType == "MDSCHEMA_DIMENSIONS":
return discover_tools.discover_mdschema_dimensions_response(request) return discover_tools.discover_mdschema_dimensions_response(
request)
elif request.RequestType == "MDSCHEMA_HIERARCHIES": elif request.RequestType == "MDSCHEMA_HIERARCHIES":
return discover_tools.discover_mdschema_hierarchies_response(request) return discover_tools.discover_mdschema_hierarchies_response(
request)
elif request.RequestType == "MDSCHEMA_LEVELS": elif request.RequestType == "MDSCHEMA_LEVELS":
return discover_tools.discover_mdschema_levels__response(request) return discover_tools.discover_mdschema_levels__response(request)
elif request.RequestType == "MDSCHEMA_MEASUREGROUPS": elif request.RequestType == "MDSCHEMA_MEASUREGROUPS":
return discover_tools.discover_mdschema_measuresgroups_response(request) return discover_tools.discover_mdschema_measuresgroups_response(
request)
elif request.RequestType == "MDSCHEMA_MEASUREGROUP_DIMENSIONS": elif request.RequestType == "MDSCHEMA_MEASUREGROUP_DIMENSIONS":
return discover_tools.discover_mdschema_measuresgroups_dimensions_response(request) return discover_tools.discover_mdschema_measuresgroups_dimensions_response(
request)
elif request.RequestType == "MDSCHEMA_PROPERTIES": elif request.RequestType == "MDSCHEMA_PROPERTIES":
return discover_tools.discover_mdschema_properties_response(request) return discover_tools.discover_mdschema_properties_response(
request)
elif request.RequestType == "MDSCHEMA_MEMBERS": elif request.RequestType == "MDSCHEMA_MEMBERS":
return discover_tools.discover_mdschema_members_response(request) return discover_tools.discover_mdschema_members_response(request)
...@@ -127,7 +132,8 @@ class XmlaProviderService(ServiceBase): ...@@ -127,7 +132,8 @@ class XmlaProviderService(ServiceBase):
</return> </return>
""") """)
else: else:
XmlaProviderService.discover_tools.change_catalogue(request.Properties.PropertyList.Catalog) XmlaProviderService.discover_tools.change_catalogue(
request.Properties.PropertyList.Catalog)
executer = XmlaProviderService.discover_tools.executer executer = XmlaProviderService.discover_tools.executer
executer.mdx_query = request.Command.Statement executer.mdx_query = request.Command.Statement
df = executer.execute_mdx() df = executer.execute_mdx()
...@@ -143,33 +149,34 @@ class XmlaProviderService(ServiceBase): ...@@ -143,33 +149,34 @@ class XmlaProviderService(ServiceBase):
<Cube> <Cube>
<CubeName>Sales</CubeName> <CubeName>Sales</CubeName>
<LastDataUpdate <LastDataUpdate
xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">{6}</LastDataUpdate> xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">{7}</LastDataUpdate>
<LastSchemaUpdate <LastSchemaUpdate
xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">{6}</LastSchemaUpdate> xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">{7}</LastSchemaUpdate>
</Cube> </Cube>
</CubeInfo> </CubeInfo>
<AxesInfo> <AxesInfo>
{1} {1}
</AxesInfo>
{2} {2}
</AxesInfo>
{3}
</OlapInfo> </OlapInfo>
<Axes> <Axes>
{3}
{4} {4}
{5}
</Axes> </Axes>
<CellData> <CellData>
{5} {6}
</CellData> </CellData>
</root> </root>
</return> </return>
""".format(execute_xsd, """.format(execute_xsd,
xmla_tools.generate_axes_info(df), xmla_tools.generate_axes_info(df),
xmla_tools.generate_axes_info_slicer(df),
xmla_tools.generate_cell_info(), xmla_tools.generate_cell_info(),
xmla_tools.generate_xs0(df), xmla_tools.generate_xs0(df),
xmla_tools.generate_slicer_axis(df), xmla_tools.generate_slicer_axis(df),
xmla_tools.generate_cell_data(df), xmla_tools.generate_cell_data(df),
datetime.now().strftime('%Y-%m-%dT%H:%M:%S') datetime.now().strftime('%Y-%m-%dT%H:%M:%S')))
))
application = Application( application = Application(
......
...@@ -16,13 +16,16 @@ class XmlaDiscoverTools(): ...@@ -16,13 +16,16 @@ class XmlaDiscoverTools():
""" """
XmlaDiscoverTools for generating xmla discover responses XmlaDiscoverTools for generating xmla discover responses
""" """
def __init__(self): def __init__(self):
# right now the catalogue_name and cube name are the same # right now the catalogue_name and cube name are the same
self.catalogues = MdxEngine.get_cubes_names() self.catalogues = MdxEngine.get_cubes_names()
self.selected_catalogue = self.catalogues[0] self.selected_catalogue = self.catalogues[0]
self.executer = MdxEngine(self.selected_catalogue) self.executer = MdxEngine(self.selected_catalogue)
self.star_schema_dataframe = self.executer.load_star_schema_dataframe[ self.star_schema_dataframe = self.executer.load_star_schema_dataframe[[
[col for col in self.executer.load_star_schema_dataframe.columns if col[-3:] != "_id"]] col for col in self.executer.load_star_schema_dataframe.columns
if col[-3:] != "_id"
]]
self.SessionId = uuid.uuid1() self.SessionId = uuid.uuid1()
def change_catalogue(self, new_catalogue): def change_catalogue(self, new_catalogue):
...@@ -37,7 +40,11 @@ class XmlaDiscoverTools(): ...@@ -37,7 +40,11 @@ class XmlaDiscoverTools():
self.selected_catalogue = new_catalogue self.selected_catalogue = new_catalogue
self.executer = MdxEngine(new_catalogue) self.executer = MdxEngine(new_catalogue)
self.star_schema_dataframe = self.executer.load_star_schema_dataframe[ self.star_schema_dataframe = self.executer.load_star_schema_dataframe[
[col for col in self.executer.load_star_schema_dataframe.columns if col[-3:] != "_id"]] [
col
for col in self.executer.load_star_schema_dataframe.columns
if col[-3:] != "_id"
]]
def discover_datasources_response(self): def discover_datasources_response(self):
return etree.fromstring(""" return etree.fromstring("""
...@@ -60,7 +67,8 @@ class XmlaDiscoverTools(): ...@@ -60,7 +67,8 @@ class XmlaDiscoverTools():
</return>""") </return>""")
def discover_properties_response(self, request): def discover_properties_response(self, request):
def get_props(xsd, PropertyName, PropertyDescription, PropertyType, PropertyAccessType, IsRequired, Value): def get_props(xsd, PropertyName, PropertyDescription, PropertyType,
PropertyAccessType, IsRequired, Value):
return etree.fromstring(""" return etree.fromstring("""
<return> <return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset" <root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset"
...@@ -77,7 +85,8 @@ class XmlaDiscoverTools(): ...@@ -77,7 +85,8 @@ class XmlaDiscoverTools():
</row> </row>
</root> </root>
</return> </return>
""".format(PropertyName, PropertyDescription, PropertyType, PropertyAccessType, IsRequired, Value)) """.format(PropertyName, PropertyDescription, PropertyType,
PropertyAccessType, IsRequired, Value))
if request.Restrictions.RestrictionList.PropertyName == 'Catalog': if request.Restrictions.RestrictionList.PropertyName == 'Catalog':
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
...@@ -85,48 +94,53 @@ class XmlaDiscoverTools(): ...@@ -85,48 +94,53 @@ class XmlaDiscoverTools():
value = self.selected_catalogue value = self.selected_catalogue
else: else:
value = "olapy Unspecified Catalog" value = "olapy Unspecified Catalog"
return get_props(discover_preperties_xsd, 'Catalog', 'Catalog', 'string', 'ReadWrite', 'false', value) return get_props(discover_preperties_xsd, 'Catalog', 'Catalog',
'string', 'ReadWrite', 'false', value)
elif request.Restrictions.RestrictionList.PropertyName == 'ServerName': elif request.Restrictions.RestrictionList.PropertyName == 'ServerName':
return get_props(discover_preperties_xsd, 'ServerName', 'ServerName', 'string', 'Read', 'false', 'Mouadh') return get_props(discover_preperties_xsd, 'ServerName',
'ServerName', 'string', 'Read', 'false', 'Mouadh')
elif request.Restrictions.RestrictionList.PropertyName == 'ProviderVersion': elif request.Restrictions.RestrictionList.PropertyName == 'ProviderVersion':
return get_props(discover_preperties_xsd, 'ProviderVersion', 'ProviderVersion', 'string', 'Read', 'false', return get_props(discover_preperties_xsd, 'ProviderVersion',
'ProviderVersion', 'string', 'Read', 'false',
'0.02 08-Mar-2016 08:41:28 GMT') '0.02 08-Mar-2016 08:41:28 GMT')
elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxSubqueries': elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxSubqueries':
if 'Unspecified' in request.Properties.PropertyList.Catalog: if 'Unspecified' in request.Properties.PropertyList.Catalog:
return get_props(discover_preperties_xsd, 'MdpropMdxSubqueries', 'MdpropMdxSubqueries', 'int', 'Read', return get_props(discover_preperties_xsd,
'false', '15') 'MdpropMdxSubqueries', 'MdpropMdxSubqueries',
'int', 'Read', 'false', '15')
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(request.Properties.PropertyList.Catalog)
return get_props(discover_preperties_xsd, 'MdpropMdxSubqueries', 'MdpropMdxSubqueries', 'int', 'Read', return get_props(discover_preperties_xsd,
'false', '15') 'MdpropMdxSubqueries', 'MdpropMdxSubqueries',
'int', 'Read', 'false', '15')
elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxDrillFunctions': elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxDrillFunctions':
if 'Unspecified' in request.Properties.PropertyList.Catalog: if 'Unspecified' in request.Properties.PropertyList.Catalog:
return get_props(discover_preperties_xsd, 'MdpropMdxDrillFunctions', 'MdpropMdxDrillFunctions', 'int', return get_props(
'Read', discover_preperties_xsd, 'MdpropMdxDrillFunctions',
'false', '3') 'MdpropMdxDrillFunctions', 'int', 'Read', 'false', '3')
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(request.Properties.PropertyList.Catalog)
return get_props(discover_preperties_xsd, 'MdpropMdxDrillFunctions', 'MdpropMdxDrillFunctions', 'int', return get_props(
'Read', discover_preperties_xsd, 'MdpropMdxDrillFunctions',
'false', '3') 'MdpropMdxDrillFunctions', 'int', 'Read', 'false', '3')
elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxNamedSets': elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxNamedSets':
if 'Unspecified' in request.Properties.PropertyList.Catalog: if 'Unspecified' in request.Properties.PropertyList.Catalog:
return get_props(discover_preperties_xsd, 'MdpropMdxNamedSets', 'MdpropMdxNamedSets', 'int', return get_props(discover_preperties_xsd, 'MdpropMdxNamedSets',
'Read', 'MdpropMdxNamedSets', 'int', 'Read', 'false',
'false', '15') '15')
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(request.Properties.PropertyList.Catalog)
return get_props(discover_preperties_xsd, 'MdpropMdxNamedSets', 'MdpropMdxNamedSets', 'int', return get_props(discover_preperties_xsd, 'MdpropMdxNamedSets',
'Read', 'MdpropMdxNamedSets', 'int', 'Read', 'false',
'false', '15') '15')
return etree.fromstring(""" return etree.fromstring("""
<return> <return>
...@@ -1693,7 +1707,8 @@ class XmlaDiscoverTools(): ...@@ -1693,7 +1707,8 @@ class XmlaDiscoverTools():
</row> </row>
</root> </root>
</return> </return>
""".format(self.selected_catalogue, self.selected_catalogue)) """.format(self.selected_catalogue,
self.selected_catalogue))
return etree.fromstring(""" return etree.fromstring("""
<return> <return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset" <root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset"
...@@ -1761,7 +1776,8 @@ class XmlaDiscoverTools(): ...@@ -1761,7 +1776,8 @@ class XmlaDiscoverTools():
if request.Restrictions.RestrictionList.CUBE_NAME == self.selected_catalogue: if request.Restrictions.RestrictionList.CUBE_NAME == self.selected_catalogue:
if request.Restrictions.RestrictionList.MEASURE_VISIBILITY == 3: if request.Restrictions.RestrictionList.MEASURE_VISIBILITY == 3:
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(
request.Properties.PropertyList.Catalog)
for mes in self.executer.measures: for mes in self.executer.measures:
measures += """ measures += """
<row> <row>
...@@ -1796,10 +1812,12 @@ class XmlaDiscoverTools(): ...@@ -1796,10 +1812,12 @@ class XmlaDiscoverTools():
if request.Restrictions.RestrictionList.CUBE_NAME == self.selected_catalogue: if request.Restrictions.RestrictionList.CUBE_NAME == self.selected_catalogue:
if request.Restrictions.RestrictionList.CATALOG_NAME == self.selected_catalogue: if request.Restrictions.RestrictionList.CATALOG_NAME == self.selected_catalogue:
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(
request.Properties.PropertyList.Catalog)
rows = "" rows = ""
ord = 1 ord = 1
for tables in self.executer.get_all_tables_names(ignore_fact=True): for tables in self.executer.get_all_tables_names(
ignore_fact=True):
rows += """ rows += """
<row> <row>
<CATALOG_NAME>{0}</CATALOG_NAME> <CATALOG_NAME>{0}</CATALOG_NAME>
...@@ -1815,9 +1833,7 @@ class XmlaDiscoverTools(): ...@@ -1815,9 +1833,7 @@ class XmlaDiscoverTools():
<IS_READWRITE>false</IS_READWRITE> <IS_READWRITE>false</IS_READWRITE>
<DIMENSION_UNIQUE_SETTINGS>1</DIMENSION_UNIQUE_SETTINGS> <DIMENSION_UNIQUE_SETTINGS>1</DIMENSION_UNIQUE_SETTINGS>
<DIMENSION_IS_VISIBLE>true</DIMENSION_IS_VISIBLE> <DIMENSION_IS_VISIBLE>true</DIMENSION_IS_VISIBLE>
</row>""".format(self.selected_catalogue, </row>""".format(self.selected_catalogue, tables, ord)
tables,
ord)
ord += 1 ord += 1
rows += """ rows += """
...@@ -1880,9 +1896,8 @@ class XmlaDiscoverTools(): ...@@ -1880,9 +1896,8 @@ class XmlaDiscoverTools():
<HIERARCHY_ORIGIN>1</HIERARCHY_ORIGIN> <HIERARCHY_ORIGIN>1</HIERARCHY_ORIGIN>
<INSTANCE_SELECTION>0</INSTANCE_SELECTION> <INSTANCE_SELECTION>0</INSTANCE_SELECTION>
</row> </row>
""".format( """.format(self.selected_catalogue, table_name,
self.selected_catalogue, table_name, df.columns[0], df.columns[0], df.iloc[0][0])
df.iloc[0][0])
# self.executer.get_attribute_column_rm_id(tables, column, 0)) # self.executer.get_attribute_column_rm_id(tables, column, 0))
rows += """ rows += """
...@@ -1907,7 +1922,8 @@ class XmlaDiscoverTools(): ...@@ -1907,7 +1922,8 @@ class XmlaDiscoverTools():
<HIERARCHY_ORIGIN>1</HIERARCHY_ORIGIN> <HIERARCHY_ORIGIN>1</HIERARCHY_ORIGIN>
<INSTANCE_SELECTION>0</INSTANCE_SELECTION> <INSTANCE_SELECTION>0</INSTANCE_SELECTION>
</row> </row>
""".format(self.selected_catalogue, self.executer.measures[0]) """.format(self.selected_catalogue,
self.executer.measures[0])
return etree.fromstring(""" return etree.fromstring("""
<return> <return>
...@@ -1946,10 +1962,8 @@ class XmlaDiscoverTools(): ...@@ -1946,10 +1962,8 @@ class XmlaDiscoverTools():
<HIERARCHY_ORIGIN>1</HIERARCHY_ORIGIN> <HIERARCHY_ORIGIN>1</HIERARCHY_ORIGIN>
<INSTANCE_SELECTION>0</INSTANCE_SELECTION> <INSTANCE_SELECTION>0</INSTANCE_SELECTION>
</row> </row>
""".format(self.selected_catalogue, """.format(self.selected_catalogue, table_name,
table_name, df.columns[0], df.iloc[0][0])
df.columns[0],
df.iloc[0][0])
rows += """ rows += """
<row> <row>
...@@ -1989,9 +2003,11 @@ class XmlaDiscoverTools(): ...@@ -1989,9 +2003,11 @@ class XmlaDiscoverTools():
if request.Restrictions.RestrictionList.CUBE_NAME == self.selected_catalogue: if request.Restrictions.RestrictionList.CUBE_NAME == self.selected_catalogue:
if request.Restrictions.RestrictionList.CATALOG_NAME == self.selected_catalogue: if request.Restrictions.RestrictionList.CATALOG_NAME == self.selected_catalogue:
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(
request.Properties.PropertyList.Catalog)
rows = "" rows = ""
for tables in self.executer.get_all_tables_names(ignore_fact=True): for tables in self.executer.get_all_tables_names(
ignore_fact=True):
l_nb = 0 l_nb = 0
for col in self.executer.tables_loaded[tables].columns: for col in self.executer.tables_loaded[tables].columns:
rows += """ rows += """
...@@ -2013,7 +2029,8 @@ class XmlaDiscoverTools(): ...@@ -2013,7 +2029,8 @@ class XmlaDiscoverTools():
<LEVEL_KEY_CARDINALITY>1</LEVEL_KEY_CARDINALITY> <LEVEL_KEY_CARDINALITY>1</LEVEL_KEY_CARDINALITY>
<LEVEL_ORIGIN>2</LEVEL_ORIGIN> <LEVEL_ORIGIN>2</LEVEL_ORIGIN>
</row> </row>
""".format(self.selected_catalogue, tables, col, l_nb) """.format(self.selected_catalogue, tables, col,
l_nb)
l_nb += 1 l_nb += 1
rows += """ rows += """
...@@ -2074,7 +2091,8 @@ class XmlaDiscoverTools(): ...@@ -2074,7 +2091,8 @@ class XmlaDiscoverTools():
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(request.Properties.PropertyList.Catalog)
rows = "" rows = ""
for tables in self.executer.get_all_tables_names(ignore_fact=True): for tables in self.executer.get_all_tables_names(
ignore_fact=True):
rows += """ rows += """
<row> <row>
<CATALOG_NAME>{0}</CATALOG_NAME> <CATALOG_NAME>{0}</CATALOG_NAME>
...@@ -2210,7 +2228,8 @@ class XmlaDiscoverTools(): ...@@ -2210,7 +2228,8 @@ class XmlaDiscoverTools():
</row> </row>
</root> </root>
</return> </return>
""".format(self.selected_catalogue, mdschema_properties_PROPERTIES_xsd)) """.format(self.selected_catalogue,
mdschema_properties_PROPERTIES_xsd))
elif request.Restrictions.RestrictionList.PROPERTY_TYPE == 1: elif request.Restrictions.RestrictionList.PROPERTY_TYPE == 1:
return etree.fromstring(""" return etree.fromstring("""
<return> <return>
...@@ -2228,7 +2247,8 @@ class XmlaDiscoverTools(): ...@@ -2228,7 +2247,8 @@ class XmlaDiscoverTools():
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(request.Properties.PropertyList.Catalog)
if request.Restrictions.RestrictionList.TREE_OP == 8: if request.Restrictions.RestrictionList.TREE_OP == 8:
separed_tuple = request.Restrictions.RestrictionList.MEMBER_UNIQUE_NAME.split(".") separed_tuple = request.Restrictions.RestrictionList.MEMBER_UNIQUE_NAME.split(
".")
joined = ".".join(separed_tuple[:-1]) joined = ".".join(separed_tuple[:-1])
# exple # exple
# separed_tuple -> [Product].[Product].[Company].[Crazy Development] # separed_tuple -> [Product].[Product].[Company].[Crazy Development]
...@@ -2262,5 +2282,7 @@ class XmlaDiscoverTools(): ...@@ -2262,5 +2282,7 @@ class XmlaDiscoverTools():
</root> </root>
</return> </return>
""".format(self.selected_catalogue, separed_tuple[ """.format(self.selected_catalogue, separed_tuple[
0], joined, request.Restrictions.RestrictionList.MEMBER_UNIQUE_NAME, ''.join( 0], joined, request.Restrictions.RestrictionList.
c for c in separed_tuple[-1] if c not in '[]'))) MEMBER_UNIQUE_NAME, ''.join(
c for c in separed_tuple[-1]
if c not in '[]')))
...@@ -2,6 +2,8 @@ from __future__ import absolute_import, division, print_function ...@@ -2,6 +2,8 @@ from __future__ import absolute_import, division, print_function
from collections import OrderedDict from collections import OrderedDict
import itertools
class XmlaExecuteTools(): class XmlaExecuteTools():
""" """
...@@ -51,14 +53,14 @@ class XmlaExecuteTools(): ...@@ -51,14 +53,14 @@ class XmlaExecuteTools():
""" """
# TODO new version with facts as splited df maybe # TODO new version with facts as splited df maybe
DataFrames = OrderedDict() return OrderedDict(
[DataFrames.update({key: mdx_execution_result['result'].reset_index()[list(value)]}) for key, value in (key, mdx_execution_result['result'].reset_index()[list(value)])
mdx_execution_result['columns_desc'].items() if key != self.executer.facts] for key, value in mdx_execution_result['columns_desc']['all']
return DataFrames .items())
def get_tuple_without_nan(self, tuple): def get_tuple_without_nan(self, tuple):
""" """
remove nan from tuple remove nan from tuple.
example example
in : in :
...@@ -73,53 +75,127 @@ class XmlaExecuteTools(): ...@@ -73,53 +75,127 @@ class XmlaExecuteTools():
:return: tuple as list without -1 :return: tuple as list without -1
""" """
for index, att in enumerate(tuple[::-1]): for index, att in enumerate(tuple[::-1]):
if att != -1: if att != -1:
return tuple[:len(tuple) - index] return tuple[:len(tuple) - index]
return tuple
def check_measures_only_selected(self, mdx_execution_result):
"""
check if mdx query contains only measures
:param mdx_execution_result: mdx_execute() result return tuple
:return: True | False
"""
return len(mdx_execution_result['columns_desc'].keys()) == 1 and mdx_execution_result['columns_desc'].keys()[
0] == self.executer.facts
def generate_xs0_measures_only(self, mdx_execution_result): def generate_xs0_one_axis(self,
mdx_execution_result,
splited_df,
mdx_query_axis='all',
axis="Axis0"):
""" """
generate xs0 if only measures exists in the mdx query :param mdx_execution_result:
:param splited_df:
:param mdx_execution_result: mdx_execute() result :return:
:return: xs0 xml as string
""" """
axis0 = "" axis0 = ""
if len(mdx_execution_result['columns_desc'][self.executer.facts]) > 1: # only measure selected
for column in mdx_execution_result['result'].columns: if mdx_execution_result['columns_desc'][
mdx_query_axis].keys() == [self.executer.facts]:
if len(mdx_execution_result['columns_desc'][mdx_query_axis][
self.executer.facts]) == 1:
# to ignore for tupls in itertools.chain(*tuples)
tuples = []
else:
# ['Facts', 'Amount', 'Amount']
tuples = [[[[self.executer.facts] + [mes] + [mes]]]
for mes in self.executer.measures]
first_att = 3
# query with on columns and on rows (without measure)
elif mdx_execution_result['columns_desc'][
'columns'] and mdx_execution_result['columns_desc']['rows']:
# ['Geography','America']
tuples = [
zip(* [[[key] + list(row)
for row in splited_df[key].itertuples(index=False)]
for key in splited_df.keys()
if key is not self.executer.facts])
]
first_att = 2
# query with on columns and on rows (many measures selected)
else:
# ['Geography','Amount','America']
tuples = [
zip(* [[[key] + [mes] + list(row)
for row in splited_df[key].itertuples(index=False)]
for key in splited_df.keys()
if key is not self.executer.facts])
for mes in self.executer.measures
]
first_att = 3
for tupls in itertools.chain(*tuples):
axis0 += "<Tuple>\n"
# [u'Geography', u'Amount', 'America']
# tupls[0][1] --> Measure
if tupls[0][1] in self.executer.measures and len(
self.executer.measures) > 1:
axis0 += """
<Member Hierarchy="[Measures]">
<UName>[Measures].[{0}]</UName>
<Caption>{0}</Caption>
<LName>[Measures]</LName>
<LNum>0</LNum>
<DisplayInfo>0</DisplayInfo>
<HIERARCHY_UNIQUE_NAME>[Measures]</HIERARCHY_UNIQUE_NAME>
</Member>
""".format(tupls[0][1])
if len(tupls) == 1:
axis0 += "</Tuple>\n"
continue
for tupl in tupls:
tuple_without_minus_1 = self.get_tuple_without_nan(tupl)
axis0 += """
<Member Hierarchy="[{0}].[{0}]">
<UName>[{0}].[{0}].[{1}].{2}</UName>
<Caption>{3}</Caption>
<LName>[{0}].[{0}].[{1}]</LName>
<LNum>{4}</LNum>
<DisplayInfo>131076</DisplayInfo>""".format(
tuple_without_minus_1[0], splited_df[tuple_without_minus_1[
0]].columns[len(tuple_without_minus_1) - first_att],
'.'.join([
'[' + str(i) + ']'
for i in tuple_without_minus_1[first_att - 1:]
]), tuple_without_minus_1[-1],
len(tuple_without_minus_1) - first_att)
# PARENT_UNIQUE_NAME must be before HIERARCHY_UNIQUE_NAME
if len(tuple_without_minus_1[first_att - 1:]) > 1:
axis0 += """
<PARENT_UNIQUE_NAME>[{0}].[{0}].[{1}].{2}</PARENT_UNIQUE_NAME>""".format(
tuple_without_minus_1[0],
splited_df[tuple_without_minus_1[0]].columns[0],
'.'.join([
'[' + str(i) + ']'
for i in tuple_without_minus_1[first_att - 1:-1]
]))
axis0 += """ axis0 += """
<Tuple> <HIERARCHY_UNIQUE_NAME>[{0}].[{0}]</HIERARCHY_UNIQUE_NAME>
<Member Hierarchy="[Measures]"> </Member>
<UName>[Measures].[{0}]</UName> """.format(tuple_without_minus_1[0])
<Caption>{0}</Caption>
<LName>[Measures]</LName> axis0 += "</Tuple>\n"
<LNum>0</LNum>
<DisplayInfo>0</DisplayInfo>
<HIERARCHY_UNIQUE_NAME>[Measures]</HIERARCHY_UNIQUE_NAME>
</Member>
</Tuple>
""".format(column)
if axis0: if axis0:
axis0 = """ axis0 = """
<Axis name="Axis0"> <Axis name="{0}">
<Tuples> <Tuples>
{0} {1}
</Tuples> </Tuples>
</Axis> </Axis>
""".format(axis0) """.format(axis, axis0)
return axis0 return axis0
...@@ -175,79 +251,49 @@ class XmlaExecuteTools(): ...@@ -175,79 +251,49 @@ class XmlaExecuteTools():
:param mdx_execution_result: mdx_execute() result :param mdx_execution_result: mdx_execute() result
:return: xs0 xml as string :return: xs0 xml as string
""" """
# TODO must be OPTIMIZED every time !!!!! # TODO must be OPTIMIZED every time!!!!!
# only measures selected
if self.check_measures_only_selected(mdx_execution_result):
return self.generate_xs0_measures_only(mdx_execution_result)
dfs = self.split_DataFrame(mdx_execution_result) dfs = self.split_DataFrame(mdx_execution_result)
axis0 = "" if mdx_execution_result['columns_desc'][
keys_without_fact = [key for key in mdx_execution_result['columns_desc'].keys() if 'rows'] and mdx_execution_result['columns_desc']['columns']:
key != self.executer.facts]
# every selected measure return """
for mes in self.executer.measures: {0}
for row in zip(*([list(row) for row in dfs[key].itertuples(index=False)] for key in dfs.keys())): {1}
axis0 += "<Tuple>\n" """.format(
if len(self.executer.measures) > 1: self.generate_xs0_one_axis(
axis0 += """ mdx_execution_result,
<Member Hierarchy="[Measures]"> dfs,
<UName>[Measures].[{0}]</UName> mdx_query_axis='columns',
<Caption>{0}</Caption> axis="Axis0"),
<LName>[Measures]</LName> self.generate_xs0_one_axis(
<LNum>0</LNum> mdx_execution_result,
<DisplayInfo>0</DisplayInfo> dfs,
<HIERARCHY_UNIQUE_NAME>[Measures]</HIERARCHY_UNIQUE_NAME> mdx_query_axis='rows',
</Member> axis="Axis1"))
""".format(mes)
for index, tupl in enumerate(row): # only one measure selected
tuple_without_minus_1 = self.get_tuple_without_nan(tupl) elif not mdx_execution_result['columns_desc'][
# tuple without parent 'rows'] and not mdx_execution_result['columns_desc']['columns'] and\
axis0 += """ mdx_execution_result['columns_desc']['where']:
<Member Hierarchy="[{0}].[{0}]"> return """
<UName>[{0}].[{0}].[{1}].{2}</UName> {0}
<Caption>{3}</Caption> """.format(
<LName>[{0}].[{0}].[{1}]</LName> self.generate_xs0_one_axis(
<LNum>{4}</LNum> mdx_execution_result,
<DisplayInfo>131076</DisplayInfo>""".format( dfs,
keys_without_fact[index], mdx_query_axis='where',
dfs[keys_without_fact[index]].columns[len(tuple_without_minus_1) - 1], axis="Axis0"))
'.'.join(['[' + str(i) + ']' for i in tuple_without_minus_1]),
tuple_without_minus_1[-1], # one axis
len(tuple_without_minus_1) - 1 return self.generate_xs0_one_axis(
) mdx_execution_result, dfs, mdx_query_axis='columns', axis="Axis0")
# PARENT_UNIQUE_NAME must be before HIERARCHY_UNIQUE_NAME
if len(tuple_without_minus_1) > 1:
axis0 += """
<PARENT_UNIQUE_NAME>[{0}].[{0}].[{1}].{2}</PARENT_UNIQUE_NAME>""".format(
keys_without_fact[index],
dfs[keys_without_fact[index]].columns[0],
'.'.join(['[' + str(i) + ']' for i in tuple_without_minus_1[:-1]])
)
axis0 += """
<HIERARCHY_UNIQUE_NAME>[{0}].[{0}]</HIERARCHY_UNIQUE_NAME>
</Member>
""".format(keys_without_fact[index])
axis0 += "</Tuple>\n"
if axis0:
axis0 = """
<Axis name="Axis0">
<Tuples>
{0}
</Tuples>
</Axis>
""".format(axis0)
return axis0
# TODO maybe fusion with generate xs0 for less iteration # TODO maybe fusion with generate xs0 for less iteration
def generate_cell_data(self, mdx_execution_result): def generate_cell_data(self, mdx_execution_result):
""" """
examle of CellData:: examle of CellData::
<Cell CellOrdinal="0"> <Cell CellOrdinal="0">
<Value xsi:type="xsi:long">768</Value> <Value xsi:type="xsi:long">768</Value>
</Cell> </Cell>
...@@ -271,7 +317,81 @@ class XmlaExecuteTools(): ...@@ -271,7 +317,81 @@ class XmlaExecuteTools():
index += 1 index += 1
return cell_data return cell_data
def generate_axes_info(self, mdx_execution_result): def generate_axes_info_slicer(self, mdx_execution_result):
"""
Not used dimensions
example AxisInfo::
<AxesInfo>
<AxisInfo name="SlicerAxis">
<HierarchyInfo name="[Time].[Time]">
<UName name="[Time].[Time].[MEMBER_UNIQUE_NAME]" type="xs:string"/>
<Caption name="[Time].[Time].[MEMBER_CAPTION]" type="xs:string"/>
<LName name="[Time].[Time].[LEVEL_UNIQUE_NAME]" type="xs:string"/>
<LNum name="[Time].[Time].[LEVEL_NUMBER]" type="xs:int"/>
<DisplayInfo name="[Time].[Time].[DISPLAY_INFO]" type="xs:unsignedInt"/>
</HierarchyInfo>
<HierarchyInfo name="[Measures]">
<UName name="[Measures].[MEMBER_UNIQUE_NAME]" type="xs:string"/>
<Caption name="[Measures].[MEMBER_CAPTION]" type="xs:string"/>
<LName name="[Measures].[LEVEL_UNIQUE_NAME]" type="xs:string"/>
<LNum name="[Measures].[LEVEL_NUMBER]" type="xs:int"/>
<DisplayInfo name="[Measures].[DISPLAY_INFO]" type="xs:unsignedInt"/>
</HierarchyInfo>
</AxisInfo>
</AxesInfo>
:param mdx_execution_result: mdx_execute() result
:return: AxisInfo as string
"""
all_dimensions_names = self.executer.get_all_tables_names(
ignore_fact=True)
all_dimensions_names.append('Measures')
hierarchy_info_slicer = ""
slicer_list = list(
set(all_dimensions_names) - set([
table_name
for table_name in mdx_execution_result['columns_desc']['all']
]))
# we have to write measures after dimensions !
if 'Measures' in slicer_list:
slicer_list.insert(
len(slicer_list),
slicer_list.pop(slicer_list.index('Measures')))
for dim_diff in slicer_list:
to_write = "[{0}].[{0}]".format(dim_diff)
if dim_diff == 'Measures':
# if measures > 1 we don't have to write measure
if len(self.executer.measures) > 1:
continue
else:
to_write = "[Measures]"
hierarchy_info_slicer += """
<HierarchyInfo name="{0}">
<UName name="{0}.[MEMBER_UNIQUE_NAME]" type="xs:string"/>
<Caption name="{0}.[MEMBER_CAPTION]" type="xs:string"/>
<LName name="{0}.[LEVEL_UNIQUE_NAME]" type="xs:string"/>
<LNum name="{0}.[LEVEL_NUMBER]" type="xs:int"/>
<DisplayInfo name="{0}.[DISPLAY_INFO]" type="xs:unsignedInt"/>
</HierarchyInfo>
""".format(to_write)
if hierarchy_info_slicer:
hierarchy_info_slicer = "<AxisInfo name='SlicerAxis'>\n" + hierarchy_info_slicer + "\n</AxisInfo>\n"
return hierarchy_info_slicer
def generate_one_axis_info(self,
mdx_execution_result,
mdx_query_axis='columns',
Axis='Axis0'):
""" """
example AxisInfo:: example AxisInfo::
...@@ -298,81 +418,67 @@ class XmlaExecuteTools(): ...@@ -298,81 +418,67 @@ class XmlaExecuteTools():
<HIERARCHY_UNIQUE_NAME name="[Product].[Product].[HIERARCHY_UNIQUE_NAME]" type="xs:string"/> <HIERARCHY_UNIQUE_NAME name="[Product].[Product].[HIERARCHY_UNIQUE_NAME]" type="xs:string"/>
</HierarchyInfo> </HierarchyInfo>
</AxisInfo> </AxisInfo>
<AxisInfo name="SlicerAxis">
<HierarchyInfo name="[Time].[Time]">
<UName name="[Time].[Time].[MEMBER_UNIQUE_NAME]" type="xs:string"/>
<Caption name="[Time].[Time].[MEMBER_CAPTION]" type="xs:string"/>
<LName name="[Time].[Time].[LEVEL_UNIQUE_NAME]" type="xs:string"/>
<LNum name="[Time].[Time].[LEVEL_NUMBER]" type="xs:int"/>
<DisplayInfo name="[Time].[Time].[DISPLAY_INFO]" type="xs:unsignedInt"/>
</HierarchyInfo>
<HierarchyInfo name="[Measures]">
<UName name="[Measures].[MEMBER_UNIQUE_NAME]" type="xs:string"/>
<Caption name="[Measures].[MEMBER_CAPTION]" type="xs:string"/>
<LName name="[Measures].[LEVEL_UNIQUE_NAME]" type="xs:string"/>
<LNum name="[Measures].[LEVEL_NUMBER]" type="xs:int"/>
<DisplayInfo name="[Measures].[DISPLAY_INFO]" type="xs:unsignedInt"/>
</HierarchyInfo>
</AxisInfo>
</AxesInfo> </AxesInfo>
:param mdx_execution_result: mdx_execute() result :param mdx_execution_result:
:return: AxisInfo as string :param mdx_query_axis: columns or rows (columns by default)
:param Axis: Axis0 or Axis1 (Axis0 by default)
:return:
""" """
# TODO reduce complexity
all_dimensions_names = self.executer.get_all_tables_names(ignore_fact=True) all_dimensions_names = self.executer.get_all_tables_names(
ignore_fact=True)
hierarchy_info = "" hierarchy_info = ""
all_dimensions_names.append('Measures') all_dimensions_names.append('Measures')
for table_name in mdx_execution_result['columns_desc'][mdx_query_axis]:
for table_name in mdx_execution_result['columns_desc']:
to_write = "[{0}].[{0}]".format(table_name) to_write = "[{0}].[{0}]".format(table_name)
# measures must be added to axis0 if measures selected > 1 # measures must be added to axis0 if measures selected > 1
if table_name == self.executer.facts and len(mdx_execution_result['columns_desc'][table_name]) > 1: if table_name == self.executer.facts and len(mdx_execution_result[
'columns_desc'][mdx_query_axis][table_name]) > 1:
to_write = "[Measures]" to_write = "[Measures]"
all_dimensions_names.remove('Measures') all_dimensions_names.remove('Measures')
elif table_name == self.executer.facts: elif table_name == self.executer.facts:
continue continue
hierarchy_info += """ hierarchy_info += """
<HierarchyInfo name="{0}"> <HierarchyInfo name="{0}">
<UName name="{0}.[MEMBER_UNIQUE_NAME]" type="xs:string"/> <UName name="{0}.[MEMBER_UNIQUE_NAME]" type="xs:string"/>
<Caption name="{0}.[MEMBER_CAPTION]" type="xs:string"/> <Caption name="{0}.[MEMBER_CAPTION]" type="xs:string"/>
<LName name="{0}.[LEVEL_UNIQUE_NAME]" type="xs:string"/> <LName name="{0}.[LEVEL_UNIQUE_NAME]" type="xs:string"/>
<LNum name="{0}.[LEVEL_NUMBER]" type="xs:int"/> <LNum name="{0}.[LEVEL_NUMBER]" type="xs:int"/>
<DisplayInfo name="{0}.[DISPLAY_INFO]" type="xs:unsignedInt"/> <DisplayInfo name="{0}.[DISPLAY_INFO]" type="xs:unsignedInt"/>
<PARENT_UNIQUE_NAME name="{0}.[PARENT_UNIQUE_NAME]" type="xs:string"/> <PARENT_UNIQUE_NAME name="{0}.[PARENT_UNIQUE_NAME]" type="xs:string"/>
<HIERARCHY_UNIQUE_NAME name="{0}.[HIERARCHY_UNIQUE_NAME]" type="xs:string"/> <HIERARCHY_UNIQUE_NAME name="{0}.[HIERARCHY_UNIQUE_NAME]" type="xs:string"/>
</HierarchyInfo> </HierarchyInfo>
""".format(to_write) """.format(to_write)
if hierarchy_info: if hierarchy_info:
hierarchy_info = "<AxisInfo name='Axis0'>\n" + hierarchy_info + "\n</AxisInfo>\n" hierarchy_info = """
<AxisInfo name='{0}'>
{1}
</AxisInfo>
""".format(Axis, hierarchy_info)
hierarchy_info_slicer = "" return hierarchy_info
slicer_list = list(set(all_dimensions_names) - set(
[table_name for table_name in mdx_execution_result['columns_desc']]))
# we have to write measures after dimensions ! def generate_axes_info(self, mdx_execution_result):
if 'Measures' in slicer_list: """
slicer_list.insert(len(slicer_list), slicer_list.pop(slicer_list.index('Measures'))) :param mdx_execution_result: mdx_execute() result
for dim_diff in slicer_list: :return: AxisInfo as string
to_write = "[{0}].[{0}]".format(dim_diff) """
if dim_diff == 'Measures':
to_write = "[Measures]"
hierarchy_info_slicer += """
<HierarchyInfo name="{0}">
<UName name="{0}.[MEMBER_UNIQUE_NAME]" type="xs:string"/>
<Caption name="{0}.[MEMBER_CAPTION]" type="xs:string"/>
<LName name="{0}.[LEVEL_UNIQUE_NAME]" type="xs:string"/>
<LNum name="{0}.[LEVEL_NUMBER]" type="xs:int"/>
<DisplayInfo name="{0}.[DISPLAY_INFO]" type="xs:unsignedInt"/>
</HierarchyInfo>
""".format(to_write)
if hierarchy_info_slicer: if mdx_execution_result['columns_desc']['rows']:
hierarchy_info_slicer = "<AxisInfo name='SlicerAxis'>\n" + hierarchy_info_slicer + "\n</AxisInfo>\n" return """
{0}
{1}
""".format(
self.generate_one_axis_info(
mdx_execution_result,
mdx_query_axis='columns',
Axis='Axis0'),
self.generate_one_axis_info(
mdx_execution_result, mdx_query_axis='rows', Axis='Axis1'))
return hierarchy_info + '\n' + hierarchy_info_slicer return self.generate_one_axis_info(mdx_execution_result)
def generate_cell_info(self): def generate_cell_info(self):
return """ return """
...@@ -416,8 +522,13 @@ class XmlaExecuteTools(): ...@@ -416,8 +522,13 @@ class XmlaExecuteTools():
""" """
tuple = "" tuple = ""
# not used dimensions # not used dimensions
for dim_diff in list(set(self.executer.get_all_tables_names(ignore_fact=True)) - set( for dim_diff in list(
[table_name for table_name in mdx_execution_result['columns_desc']])): set(self.executer.get_all_tables_names(ignore_fact=True)) -
set([
table_name
for table_name in mdx_execution_result['columns_desc'][
'all']
])):
tuple += """ tuple += """
<Member Hierarchy="[{0}].[{0}]"> <Member Hierarchy="[{0}].[{0}]">
<UName>[{0}].[{0}].[{1}].[{2}]</UName> <UName>[{0}].[{0}].[{1}].[{2}]</UName>
......
...@@ -266,8 +266,6 @@ def test_query2(conn): ...@@ -266,8 +266,6 @@ def test_query2(conn):
DisplayInfo='131076', DisplayInfo='131076',
PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[Europe]', PARENT_UNIQUE_NAME='[Geography].[Geography].[Continent].[Europe]',
HIERARCHY_UNIQUE_NAME='[Geography].[Geography]')) HIERARCHY_UNIQUE_NAME='[Geography].[Geography]'))
print([Member(**dict(co)) for co in columns])
print(mems)
assert [Member(**dict(co)) for co in columns] == mems assert [Member(**dict(co)) for co in columns] == mems
assert values == [768, 768, 768, 255, 4, 3, 2, 1, 248] assert values == [768, 768, 768, 255, 4, 3, 2, 1, 248]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment