Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
olapy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
2
Merge Requests
2
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
olapy
Commits
64486df0
Commit
64486df0
authored
Mar 17, 2017
by
Stefane Fermigier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
"On rows".
parent
26bd503c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
439 additions
and
255 deletions
+439
-255
olapy/core/mdx/executor/execute.py
olapy/core/mdx/executor/execute.py
+78
-32
olapy/core/services/xmla.py
olapy/core/services/xmla.py
+20
-13
olapy/core/services/xmla_discover_tools.py
olapy/core/services/xmla_discover_tools.py
+69
-47
olapy/core/services/xmla_execute_tools.py
olapy/core/services/xmla_execute_tools.py
+272
-161
tests/test_xmla_notox.py
tests/test_xmla_notox.py
+0
-2
No files found.
olapy/core/mdx/executor/execute.py
View file @
64486df0
...
@@ -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_tupl
es = self.decorticate_query(self.mdx_query)
query_ax
es = 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_tupl
es)
tables_n_columns = self.get_tables_and_columns(
query_ax
es)
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(),
...
...
olapy/core/services/xmla.py
View file @
64486df0
...
@@ -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
(
...
...
olapy/core/services/xmla_discover_tools.py
View file @
64486df0
...
@@ -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
'[]'
)))
olapy/core/services/xmla_execute_tools.py
View file @
64486df0
...
@@ -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
,
axis
0
)
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>
...
...
tests/test_xmla_notox.py
View file @
64486df0
...
@@ -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
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment