Commit 1f41ccfc authored by Mouadh's avatar Mouadh

config_file + postgres_backend

parent de960516
<?xml version="1.0" encoding="UTF-8"?>
<cubes>
<cube>
<!-- cube name => db name -->
<name>labster</name>
<!-- source : postgres | csv -->
<source>postgres</source>
<!--
star building customized star schema
-->
<facts>
<!-- facts table name -->
<table_name>stats_line</table_name>
<keys>
<!-- ref = table_name.column -->
<column_name ref="orgunit.id">departement_id</column_name>
</keys>
<!-- specify measures explicitly -->
<measures>
<!-- by default, all number type columns in facts table, or you can specify them here -->
<name>montant</name>
<name>salaire_brut_mensuel</name>
<name>cout_total_mensuel</name>
</measures>
</facts>
<!--
end building customized star schema
-->
<!--
star building customized dimensions display in excel from the star schema
-->
<dimensions>
<dimension>
<!-- if you want to keep the same name for excel display, just use the same name in name and displayName -->
<name>stats_line</name>
<displayName>Demande</displayName>
<columns>
<!-- columns order matter -->
<name>type_demande</name>
<name>financeur</name>
<name>wf_state</name>
<name>type_recrutement</name>
</columns>
</dimension>
<dimension>
<!-- if you want to keep the same name for excel display, just use the same name in name and displayName -->
<name>orgunit</name>
<displayName>Organisation</displayName>
<columns>
<!-- columns order matter -->
<name>type</name>
<name>nom</name>
<name>sigle</name>
</columns>
</dimension>
</dimensions>
<!--
end building customized dimensions display in excel from the star schema
-->
</cube>
</cubes>
\ No newline at end of file
class ConditionError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
This diff is collapsed.
from __future__ import absolute_import, division, print_function
import os
from lxml import etree
from .models import Cube, Facts, Dimension
class ConfigParser:
def __init__(self, cube_path, file_name='cubes-config.xml'):
self.cube_path = cube_path
self.file_name = file_name
def config_file_exist(self):
return os.path.isfile(os.path.join(self.cube_path, self.file_name))
def get_cubes_names(self):
with open(os.path.join(self.cube_path, self.file_name)) as config_file:
parser = etree.XMLParser()
tree = etree.parse(config_file, parser)
try:
return {
cube.find('name').text: cube.find('source').text
for cube in tree.xpath('/cubes/cube')
}
except:
raise ('missed name or source tags')
def construct_cubes(self):
if self.config_file_exist():
try:
with open(os.path.join(self.cube_path,
self.file_name)) as config_file:
parser = etree.XMLParser()
tree = etree.parse(config_file, parser)
facts = [
Facts(
table_name=xml_facts.find('table_name').text,
keys={
key.text: key.attrib['ref']
for key in xml_facts.findall(
'keys/column_name')
},
measures=[
mes.text
for mes in xml_facts.findall('measures/name')
]) for xml_facts in tree.xpath('/cubes/cube/facts')
]
dimensions = [
Dimension(
name=xml_dimension.find('name').text,
displayName=xml_dimension.find('displayName').text,
columns=[
column_name.text
for column_name in xml_dimension.findall(
'columns/name')
])
for xml_dimension in tree.xpath(
'/cubes/cube/dimensions/dimension')
]
return [
Cube(
name=xml_cube.find('name').text,
source=xml_cube.find('source').text,
facts=facts,
dimensions=dimensions)
for xml_cube in tree.xpath('/cubes/cube')
]
except:
raise ('Bad configuration in the configuration file')
else:
raise ("Config file don't exist")
import psycopg2 as pg
class MyDB(object):
def __init__(self, username='postgres', password='root', db=None):
if db is None:
self.connection = pg.connect(
"user={0} password={1}".format(username, password))
else:
self.connection = pg.connect("user={0} password={1} dbname='{2}'".
format(username, password, db))
def __del__(self):
self.connection.close()
class Facts:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __str__(self):
return str(self.__dict__)
class Dimension:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __str__(self):
return str(self.__dict__)
class Cube:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __str__(self):
return str(self.__dict__)
# -*- encoding: utf8 -*-
from __future__ import absolute_import, division, print_function
from datetime import datetime
......@@ -82,7 +84,8 @@ class XmlaProviderService(ServiceBase):
return discover_tools.discover_mdschema_measures__response(request)
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":
return discover_tools.discover_mdschema_hierarchies_response(
......@@ -100,7 +103,8 @@ class XmlaProviderService(ServiceBase):
request)
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":
return discover_tools.discover_mdschema_members_response(request)
......@@ -137,6 +141,7 @@ class XmlaProviderService(ServiceBase):
executer.mdx_query = request.Command.Statement
df = executer.execute_mdx()
xmla_tools = XmlaExecuteTools(executer)
return etree.fromstring("""
<return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset"
......@@ -175,7 +180,16 @@ class XmlaProviderService(ServiceBase):
xmla_tools.generate_xs0(df),
xmla_tools.generate_slicer_axis(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')).replace(
'&', '&amp;'))
# Problem:
# An XML parser returns the error “xmlParseEntityRef: noname”
#
# Cause:
# There is a stray ‘&’ (ampersand character) somewhere in the XML text eg. some text & some more text
# Solution
# .replace('&', '&amp;')
application = Application(
......
# -*- encoding: utf8 -*-
from __future__ import absolute_import, division, print_function
import uuid
......@@ -5,19 +7,14 @@ import uuid
from lxml import etree
from ..mdx.executor.execute import MdxEngine
from .xmla_discover_xsds import (dbschema_catalogs_xsd, dbschema_tables_xsd,
discover_datasources_xsd,
discover_literals_xsd,
discover_preperties_xsd,
discover_schema_rowsets_xsd,
mdschema_cubes_xsd, mdschema_dimensions_xsd,
mdschema_hierarchies_xsd, mdschema_kpis_xsd,
mdschema_levels_xsd, mdschema_measures_xsd,
mdschema_measuresgroups_dimensions_xsd,
mdschema_measuresgroups_xsd,
mdschema_members_xsd,
mdschema_properties_PROPERTIES_xsd,
mdschema_sets_xsd)
from .xmla_discover_xsds import (
dbschema_catalogs_xsd, dbschema_tables_xsd, discover_datasources_xsd,
discover_literals_xsd, discover_preperties_xsd,
discover_schema_rowsets_xsd, mdschema_cubes_xsd, mdschema_dimensions_xsd,
mdschema_hierarchies_xsd, mdschema_kpis_xsd, mdschema_levels_xsd,
mdschema_measures_xsd, mdschema_measuresgroups_dimensions_xsd,
mdschema_measuresgroups_xsd, mdschema_members_xsd,
mdschema_properties_PROPERTIES_xsd, mdschema_sets_xsd)
# TODO clean
......@@ -76,7 +73,6 @@ class XmlaDiscoverTools():
</return>""")
def discover_properties_response(self, request):
def get_props(xsd, PropertyName, PropertyDescription, PropertyType,
PropertyAccessType, IsRequired, Value):
return etree.fromstring("""
......@@ -118,15 +114,15 @@ class XmlaDiscoverTools():
elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxSubqueries':
if 'Unspecified' in request.Properties.PropertyList.Catalog:
return get_props(discover_preperties_xsd, 'MdpropMdxSubqueries',
'MdpropMdxSubqueries', 'int', 'Read', 'false',
'15')
return get_props(discover_preperties_xsd,
'MdpropMdxSubqueries', 'MdpropMdxSubqueries',
'int', 'Read', 'false', '15')
if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog)
return get_props(discover_preperties_xsd, 'MdpropMdxSubqueries',
'MdpropMdxSubqueries', 'int', 'Read', 'false',
'15')
return get_props(discover_preperties_xsd,
'MdpropMdxSubqueries', 'MdpropMdxSubqueries',
'int', 'Read', 'false', '15')
elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxDrillFunctions':
if 'Unspecified' in request.Properties.PropertyList.Catalog:
......@@ -1826,8 +1822,15 @@ class XmlaDiscoverTools():
request.Properties.PropertyList.Catalog)
rows = ""
ord = 1
for tables in self.executer.get_all_tables_names(
ignore_fact=True):
# TODO in another idea, change this
# TO CHANGE NAME DISPLAY THAT EXISTS IN CONFIG FILE
if MdxEngine.dimension_display_name != []:
if tables in MdxEngine.dimension_display_name:
continue
rows += """
<row>
<CATALOG_NAME>{0}</CATALOG_NAME>
......@@ -2264,34 +2267,38 @@ class XmlaDiscoverTools():
# separed_tuple -> [Product].[Product].[Company].[Crazy Development]
# joined -> [Product].[Product].[Company]
last_attribut = ''.join(att for att in separed_tuple[-1]
if att not in '[]').replace(
'&', '&amp;')
return etree.fromstring("""
<return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
""" + mdschema_members_xsd + """
<row>
<CATALOG_NAME>{0}</CATALOG_NAME>
<CUBE_NAME>{0}</CUBE_NAME>
<DIMENSION_UNIQUE_NAME>{1}</DIMENSION_UNIQUE_NAME>
<HIERARCHY_UNIQUE_NAME>{1}.{1}</HIERARCHY_UNIQUE_NAME>
<LEVEL_UNIQUE_NAME>{2}</LEVEL_UNIQUE_NAME>
<LEVEL_NUMBER>0</LEVEL_NUMBER>
<MEMBER_ORDINAL>0</MEMBER_ORDINAL>
<MEMBER_NAME>{4}</MEMBER_NAME>
<MEMBER_UNIQUE_NAME>{3}</MEMBER_UNIQUE_NAME>
<MEMBER_TYPE>1</MEMBER_TYPE>
<MEMBER_CAPTION>{4}</MEMBER_CAPTION>
<CHILDREN_CARDINALITY>1</CHILDREN_CARDINALITY>
<PARENT_LEVEL>0</PARENT_LEVEL>
<PARENT_COUNT>0</PARENT_COUNT>
<MEMBER_KEY>{4}</MEMBER_KEY>
<IS_PLACEHOLDERMEMBER>false</IS_PLACEHOLDERMEMBER>
<IS_DATAMEMBER>false</IS_DATAMEMBER>
</row>
</root>
</return>
""".format(
self.selected_catalogue, separed_tuple[0], joined,
request.Restrictions.RestrictionList.MEMBER_UNIQUE_NAME,
''.join(c for c in separed_tuple[-1] if c not in '[]')))
<return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
""" + mdschema_members_xsd + """
<row>
<CATALOG_NAME>{0}</CATALOG_NAME>
<CUBE_NAME>{0}</CUBE_NAME>
<DIMENSION_UNIQUE_NAME>{1}</DIMENSION_UNIQUE_NAME>
<HIERARCHY_UNIQUE_NAME>{1}.{1}</HIERARCHY_UNIQUE_NAME>
<LEVEL_UNIQUE_NAME>{2}</LEVEL_UNIQUE_NAME>
<LEVEL_NUMBER>0</LEVEL_NUMBER>
<MEMBER_ORDINAL>0</MEMBER_ORDINAL>
<MEMBER_NAME>""" + last_attribut +
"""</MEMBER_NAME>
<MEMBER_UNIQUE_NAME>{3}</MEMBER_UNIQUE_NAME>
<MEMBER_TYPE>1</MEMBER_TYPE>
<MEMBER_CAPTION>""" + last_attribut +
"""</MEMBER_CAPTION>
<CHILDREN_CARDINALITY>1</CHILDREN_CARDINALITY>
<PARENT_LEVEL>0</PARENT_LEVEL>
<PARENT_COUNT>0</PARENT_COUNT>
<MEMBER_KEY>""" + last_attribut + """</MEMBER_KEY>
<IS_PLACEHOLDERMEMBER>false</IS_PLACEHOLDERMEMBER>
<IS_DATAMEMBER>false</IS_DATAMEMBER>
</row>
</root>
</return>
""".format(self.selected_catalogue, separed_tuple[0],
joined, request.Restrictions.RestrictionList.
MEMBER_UNIQUE_NAME))
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