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(
......
This diff is collapsed.
This diff is collapsed.
...@@ -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