odoo/addons/olap/olap.py

2216 lines
95 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import psycopg2
import sqlalchemy
import time
from pyparsing import *
import wizard
import pooler
from osv import osv
from osv import fields, osv
import netsvc
import cube
import os
import tools
import base64
from cube import levels
class olap_fact_database(osv.osv):
""" Olap Fact Database """
_name = "olap.fact.database"
_description = "Olap Fact Database"
def _connection_get(self, cr, uid, ids, field_name, arg, context = {}):
""" Return a connection string url needed by SQL Alchemy. Exemple:
'postgres://scott:tiger@localhost:5432/mydatabase'
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of connections IDs
@param arg: list of tuples of form [(name_of_the_field, operator, value), ...].
@param context: A standard dictionary for contextual values
"""
res = {}
for obj in self.browse(cr, uid, ids, context):
res[obj.id] = '%s://%s:%s@%s:%d/%s' % (obj.type, obj.db_login, \
obj.db_password, obj.db_host, obj.db_port, obj.db_name)
return res
def test_connection(self, cr, uid, ids, context = {}):
""" Test connection for postgres Or ,MySql Or ,Oracle
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Test Connections IDs
@param context: A standard dictionary for contextual values
"""
try:
self_obj = self.browse(cr, uid, ids, context)
for obj in self_obj:
host = obj.db_host
port = obj.db_port
db_name = obj.db_name
user = obj.db_login
password = obj.db_password
type = obj.type
if type == 'postgres':
tdb = psycopg2.connect('host=%s port=%s dbname=%s user=%s \
password=%s' % (host,port,db_name,user,password))
elif type == 'mysql':
try:
import MySQLdb
tdb = MySQLdb.connect(host = host, port = port, db = db, user = user, passwd = passwd)
except Exception,e:
raise osv.except_osv('Error (MySQLdb) : ', e)
elif type == 'oracle':
try:
import cx_Oracle
tdb = cx_Oracle.connect(user, password, host)
except Exception,e:
raise osv.except_osv('Error (cx_Oracle) : ', e)
except Exception,e:
raise osv.except_osv('Error !', e)
raise osv.except_osv('Message', 'Connection Successful !')
return True
_columns = {
'name': fields.char('Fact name', size = 64, required = True),
'db_name': fields.char('Database name', size = 64, required = True , \
help = "Name of the database to be used for analysis."),
'db_login': fields.char('Database login', size = 64, required = True,\
help = "Login for the database name specified."),
'db_password': fields.char('Database password', size = 64,\
invisible = True, required = True, help = "Password for the login."),
'db_host': fields.char('Database host', size = 64, required = True ,\
help= "Give hostname to make connection to the database."),
'db_port': fields.integer('Database port', required = True, \
help = " Port to be used in connection"),
'type': fields.selection([('mysql', 'MySQL'), ('postgres', 'PostgreSQL'),\
('oracle', 'Oracle')], 'Database type', required = True),
'connection_type': fields.selection([('socket', 'Socket'), ('port', 'Port')],\
'Connection type', required = True),
'connection_url': fields.function(_connection_get, method = True, \
type = 'char', string = 'Connection URL', size = 128),
'table_ids': fields.one2many('olap.database.tables', 'fact_database_id', 'Tables'),
'loaded': fields.boolean('Loaded', readonly = True),
}
_defaults = {
'type': lambda * args: 'postgres',
'connection_type': lambda * args: 'port',
'db_host': lambda * args: 'localhost',
'db_name': lambda * args: 'terp',
'db_port': lambda * args: '5432',
'loaded' : lambda * args: False,
}
olap_fact_database()
class olap_schema(osv.osv ):
""" Olap Schema """
_name = "olap.schema"
_description = "Olap Schema"
def _app_detect(self, cr, uid, ids, field_name, arg, context = {}):
"""
Return a Application type
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Detected Applications IDs
@param context: A standard dictionary for contextual values
"""
res = {}
app_objs = self.pool.get('olap.application')
app_ids = app_objs.search(cr, uid, [])
app_res = app_objs.browse(cr, uid, app_ids)
for obj in self.browse(cr, uid, ids, context):
if obj.database_id.type == 'postgres':
e = sqlalchemy.create_engine(obj.database_id.connection_url)
for app_obj in app_res:
try:
result = e.execute(app_obj.query)
if result:
res[obj.id] = app_obj.name + ' Application'
continue
except:
continue
if not res.has_key(obj.id):
res[obj.id] = "Unknown Application"
else:
res[obj.id] = "Unknown Application"
return res
_columns = {
'name': fields.char('Schema name',size = 64,required = True),
'note': fields.text('Schema description'),
'cube_ids': fields.one2many('olap.cube', 'schema_id', 'Cubes'),
'database_id': fields.many2one('olap.fact.database', 'Database Connection', required = True),
'loaded': fields.boolean('Loading Datastructure', readonly = True),
'configure': fields.boolean('Configuring Datastructure', readonly = True),
'ready': fields.boolean('Ready', readonly = True),
'state': fields.selection([
('none', 'Nothing has been Configured'),
('dbconnect', 'Database Connected'),
('dbload', 'The Structure is Loaded'),
('dbconfigure', 'The Structure is Configured.'),
('dbready', 'Schema is ready to use'),
('done', 'We Can Start building Cube'),
], 'Schema State', readonly = True),
'app_detect': fields.function(_app_detect, method = True, type = 'char', \
string = 'Connection URL', size = 128),
}
_defaults = {
'loaded' : lambda * args: False,
'state': lambda * a: 'none',
'configure': lambda * a: False,
'ready': lambda * a: False
}
def action_dbconnect(self, cr, uid, ids, context = {}):
""" Connect DB with postgres ,Or MySql,Or Orcale
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Database Connection actions IDs
@param context: A standard dictionary for contextual values
"""
schema = self.browse(cr, uid, ids, context)[0]
type = schema.database_id.type
maxconn = 64
try:
if type == 'postgres':
host = schema.database_id.db_host and "host=%s" % schema.database_id.db_host or ''
port = schema.database_id.db_port and "port=%s" % schema.database_id.db_port or ''
name = schema.database_id.db_name and "dbname=%s" % schema.database_id.db_name or ''
user = schema.database_id.db_login and "user=%s" % schema.database_id.db_login or ''
password = schema.database_id.db_password and \
"password=%s" % schema.database_id.db_password or ''
tdb = psycopg2.connect('%s %s %s %s %s' % (host, port, name, user, password))
elif type == 'mysql':
try:
host = schema.database_id.db_host or ''
port = schema.database_id.db_port or ''
db = schema.database_id.db_name or ''
user = schema.database_id.db_login or ''
passwd = schema.database_id.db_password or ''
tdb = MySQLdb.connect(host = host, port = port, db = db, user = user, passwd = passwd)
except Exception, e:
raise osv.except_osv('Error (MySQLdb) : ', e)
elif type == 'oracle':
try:
host = schema.database_id.db_host or ''
port = schema.database_id.db_port or ''
db = schema.database_id.db_name or ''
user = schema.database_id.db_name.upper() or ''
password = int(schema.database_id.db_password) or ''
tdb = cx_Oracle.connect(user, password, host)
except Exception, e:
raise osv.except_osv('Error (cx_Oracle) : ', e)
for id in ids:
self.write(cr, uid, id, {'state': 'dbconnect'})
except Exception, e:
raise osv.except_osv('BI Error !', e)
return True
def action_dbload(self, cr, uid, ids, context = {}):
""" Load DB
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Database Load Actions IDs
@param context: A standard dictionary for contextual values
"""
for id in ids:
id_change = self.browse(cr, uid, id)
self.write(cr, uid, id, {'loaded': True})
self.write(cr, uid, id, {'state': 'dbload'})
return True
def action_dbconfigure(self, cr, uid, ids, context = {}):
""" Configure with Database
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Database Configuraion Actions IDs
@param context: A standard dictionary for contextual values
"""
for id in ids:
id_browsed = self.browse(cr, uid, id)
if not id_browsed.state == 'dbconfigure':
self.write(cr, uid, id, {'state': 'dbconfigure'})
self.write(cr, uid, id, {'configure': True})
return True
def action_dbready(self, cr, uid, ids, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Database Actions IDs
@param context: A standard dictionary for contextual values """
for id in ids:
self.write(cr, uid, id, {'ready': True})
self.write(cr, uid, id, {'state': 'done'})
return True
def action_done(self, cr, uid, ids, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Actions IDs
@param context: A standard dictionary for contextual values """
for id in ids:
self.write(cr, uid, id, {'state': 'done'})
return True
def create_xml_schema(self, cr, uid, xml_schema, context = {}):
"""
This function fill in the database according to a XML schema.
Exemple of schema:
<Schema>
<Cube name="Sales">
<Table name="sales_fact_1997"/>
<Dimension name="Gender" foreignKey="customer_id">
<Hierarchy hasAll="true" allMemberName="All Genders" primaryKey="customer_id">
<Table name="customer"/>
<Level name="Gender" column="gender" uniqueMembers="true"/>
</Hierarchy>
</Dimension>
<Dimension name="Time" foreignKey="time_id">
<Hierarchy hasAll="false" primaryKey="time_id">
<Table name="time_by_day"/>
<Level name="Year" column="the_year" type="Numeric" uniqueMembers="true"/>
<Level name="Quarter" column="quarter" uniqueMembers="false"/>
<Level name="Month" column="month_of_year" type="Numeric" uniqueMembers="false"/>
</Hierarchy>
</Dimension>
<Measure name="Store Sales" column="store_sales" aggregator="sum" formatString="#,###.##"/>
<Measure name="Store Cost" column="store_cost" aggregator="sum" formatString="#,###.00"/>
<CalculatedMember name="Profit" dimension="Measures" formula="[Measures].
[Store Sales]-[Measures].[Store Cost]">
<CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
</CalculatedMember>
</Cube>
</Schema
"""
raise 'Not implemented !'
def request(self, cr, uid, name, request, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Requests IDs
@param context: A standard dictionary for contextual values
"""
ids = self.search(cr, uid, [('name', '=', name)])
if not ids:
raise 'Schema not found !'
schema = self.browse(cr, uid, ids[0], context)
mdx_parser = cube.mdx_parser()
mdx = mdx_parser.parse(request)
mdx.preprocess()
validate, cubex = mdx.validate(schema)
res_comp = self.pool.get('res.company').search(cr, uid, ([]))
res_comp = self.pool.get('res.company').browse(cr, uid, res_comp)
currency = res_comp[0].currency_id.name
data = mdx.run(currency)
if cubex.query_log:
log = context.get('log')
if log:
connection = schema.database_id.connection_url
mdx.log(cr, uid, cubex, request, context)
return cube.mdx_output(data)
olap_schema()
class olap_database_tables(osv.osv):
"""Database Tables"""
_name = "olap.database.tables"
_description = "Olap Database Tables"
_columns = {
'table_db_name': fields.char('Table Name', size = 64, required = True, readonly = True),
'name': fields.char('End-User Name', size = 64, required = True),
'columns': fields.one2many('olap.database.columns', 'table_id', 'Columns'),
'fact_database_id': fields.many2one('olap.fact.database', 'Database Id',\
required = True, ondelete = 'cascade', readonly = True),
'active': fields.boolean('Active'),
'hide': fields.boolean('Hidden'),
}
_defaults = {
'active': lambda * args: True,
'hide': lambda * args: False
}
def name_get(self, cr, uid, ids, context = {}):
""" Get Database Name
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Names IDs
@param context: A standard dictionary for contextual values
"""
result = []
for t in self.browse(cr, uid, ids, context):
if t.name <> t.table_db_name:
result.append((t.id, t.name + ' (' + t.table_db_name + ')'))
else:
result.append((t.id, t.name))
return result
def show_col_view(self, cr, uid, ids, context = {}):
""" Open Tree View of Database Columns
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Columns IDs
@param context: A standard dictionary for contextual values
"""
ids_cols = self.pool.get('olap.database.columns').search(cr, uid, ([('table_id', '=', ids[0])]))
id = self.pool.get('ir.ui.view').search(cr, uid, \
([('name', '=', 'olap.database.columns.tree')]), context = {})[0]
return {
'domain': "[('id','in', [" + ','.join(map(str, ids_cols)) + "])]",
'name': 'Database Columns',
'view_type': 'form',
'view_mode': 'tree',
'res_model': 'olap.database.columns',
'views': [(id, 'tree'), (False, 'form')],
'type': 'ir.actions.act_window',
}
def hide_col(self, cr, uid, ids, context = {}):
# To hide all the related columns also
""" Hide all the related columns
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Hide Columns IDs
@param context: A standard dictionary for contextual values
"""
for id in ids:
self.write(cr, uid, id, {'hide': True})
return {}
def show_col(self, cr, uid, ids, context = {}):
# To show or unhide all the columns also
""" show all the related columns
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Columns IDs
@param context: A standard dictionary for contextual values """
for id in ids:
self.write(cr, uid, id, {'hide': False})
return {}
olap_database_tables()
class olap_database_columns(osv.osv):
""" Database Columns """
_name = "olap.database.columns"
_description = "Olap Database Columns"
datatypes = {
'timestamp': 'TimeStamp without Time Zone',
'timestampz': 'TimeStamp with Time Zone',
'numeric': 'Numeric',
'int': 'Integer',
'float8': 'Double Precesion',
'varchar': 'Character Varying',
'bool': 'Boolean',
'bytea': 'Byte A',
'int2': 'Small Integer',
'int4': 'Integer',
'int8': 'Big Integer',
'text': 'Text',
'date': 'Date',
'time': 'TimeStamp without Time Zone',
'number': 'NUMBER',
}
def _datatypes_get(self, *args, **argv):
"""
@param self: The object pointer
@param *args: For Positional Argument
@param **args: For Keyword Argument
"""
return self.datatypes.items()
_columns = {
'column_db_name': fields.char('Column DBName', size = 64, required = True, readonly = True),
'name': fields.char('Column Name', size = 64, required = True),
'table_id': fields.many2one('olap.database.tables', 'Table Id',\
required = True, ondelete = 'cascade', select = True, readonly = True),
'primary_key': fields.boolean('Primary Key'),
'type': fields.selection(_datatypes_get, 'Type', size = 64, required = True, readonly = True),
'related_to': fields.many2one('olap.database.tables', 'Related To', required = False, readonly = True),
'active': fields.boolean('Active'),
'hide': fields.boolean('Hidden'),
}
_defaults = {
'hide': lambda * args: False,
'active': lambda * args: True,
'primary_key': lambda * args: False,
}
def name_get(self, cr, uid, ids, context = {}):
""" Get Database Column
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Names IDs
@param context: A standard dictionary for contextual values
"""
result = []
for t in self.browse(cr, uid, ids, context):
if t.name <> t.column_db_name:
result.append((t.id, t.table_id.table_db_name + ' (' + t.name + ')'))
else:
result.append((t.id, t.table_id.table_db_name + ' (' + t.name + ')'))
return result
def search(self, cr, uid, args, offset = 0, limit = None, order = None,
context = None, count = False):
""" olap search method.
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param user: the current users ID for security checks,
@param args: list of tuples of form [(name_of_the_field, operator, value), ...].
@param offset: The Number of Results to Pass
@param limit: The Number of Results to Return
@param context: A standard dictionary for contextual values
"""
if not context:
return super(olap_database_columns, self).search(cr, uid, args, offset, limit,
order, context = context, count = count)
col_pool = self.pool.get('olap.database.columns')
if context and context.has_key('fk') and context['fk']:
if context.has_key('dim_x') and context['dim_x']:
dim_obj = self.pool.get('olap.dimension').browse(cr, uid, int(context['dim_x']))
make_ids = []
make_ids.append(dim_obj.cube_id.table_id.column_link_id.table_id.id)
for lines in dim_obj.cube_id.table_id.line_ids:
make_ids.append(lines.field_id.related_to.id)
make_ids.append(lines.field_id.table_id.id)
args = [('table_id', 'in', make_ids), ('related_to', '<>', False), \
('hide', '<>', True), ('active', '<>', False)]
return super(olap_database_columns, self).search(cr, uid, args, \
offset, limit, order, context = context, count = count)
if args and context and context.has_key('flag') and context['flag']:
ids = args[0][2][0][2]
if ids:
col_obj = col_pool.browse(cr, uid, ids)
make_ids = []
for lines in col_obj:
make_ids.append(lines.related_to.id)
link_id = col_pool.browse(cr, uid, int(context['link_col']))
make_ids.append(link_id.table_id.id)
args = ['|', ('table_id', 'in', make_ids), ('related_to', 'in', make_ids), \
('primary_key', '<>', True), ('hide', '<>', True), ('active', '<>', False)]
ids = super(olap_database_columns, self).search(cr, uid, args, \
offset, limit, order, context = context, count = count)
return ids
elif context and context.has_key('master_dim') and context['master_dim']:
make_ids = []
col_obj = col_pool.browse(cr, uid, int(context['link_col']))
args = ['|', ('table_id', '=', col_obj.related_to.id), \
('related_to', '=', col_obj.table_id.id), ('hide', '<>', True), ('active', '<>', False)]
return super(olap_database_columns, self).search(cr, uid, args, \
offset, limit, order, context = context, count = count)
else:
col = col_pool.browse(cr, uid, int(context['link_col']))
base_table = col.table_id
args = ['|', ('table_id', '=', base_table.id), \
('related_to', '=', base_table.id), ('hide', '<>', True), ('active', '<>', False)]
return super(olap_database_columns, self).search(cr, uid, args, \
offset, limit, order, context = context, count = count)
if context and context.has_key('filter_cols_cube'):
cube_obj = self.pool.get('olap.cube').browse(cr, uid, int(context['filter_cols_cube']))
make_ids = []
make_ids.append(cube_obj.table_id.column_link_id.related_to.id)
for lines in cube_obj.table_id.line_ids:
make_ids.append(lines.table_id.id)
if make_ids and cube_obj.table_id.line_ids:
make_ids.append(cube_obj.table_id.line_ids[len(cube_obj.table_id.line_ids) - 1].field_id.related_to.id)
args = [('table_id', 'in', make_ids), ('related_to', '=', False), \
('primary_key', '<>', True), \
('type', 'not in', ['date', 'timestamp', 'timestampz', 'time']), \
('hide', '<>', True), ('active', '<>', False)]
ids = super(olap_database_columns, self).search(cr, uid, args, offset, limit,
order, context = context, count = count)
return ids
elif context and context.has_key('filter_cols_hier'):
hier_obj = self.pool.get('olap.hierarchy').browse(cr, uid, int(context['filter_cols_hier']))
make_ids = []
if hier_obj.table_id.line_ids:
for lines in hier_obj.table_id.line_ids:
make_ids.append(lines.field_id.related_to.id)
if make_ids:
make_ids.append(hier_obj.table_id.column_link_id.related_to.id)
make_ids.append(hier_obj.table_id.column_link_id.table_id.id)
args = [('table_id', 'in', make_ids), ('hide', '<>', True), ('active', '<>', False)]
ids = super(olap_database_columns, self).search(cr, uid, args, offset, limit,
order, context = context, count = count)
return ids
else:
args = [('table_id', '=', hier_obj.table_id.column_link_id.related_to.id)]
ids = super(olap_database_columns, self).search(cr, uid, args, offset, limit,
order, context = context, count = count)
return ids
elif context and context.has_key('fk') and context['fk']:
args = [('primary_key', '=', True), ('hide', '<>', True), ('active', '<>', False)]
else:
if context and context.has_key('master_dim') and context['master_dim']:
dim_obj = self.pool.get('olap.dimension').browse(cr, uid, int(context['master_dim']))
lines = dim_obj.cube_id.table_id.line_ids
table_ids = []
for line in lines:
table_ids.append(line.table_id.id)
args = [('table_id', 'in', table_ids), ('related_to', '<>', False), \
('hide', '<>', True), ('active', '<>', False)]
elif context and context.has_key('master_schema') and context['master_schema']:
args = [('primary_key', '=', 'True')]
return super(olap_database_columns, self).search(cr, uid, args, offset, limit,
order, context = context, count = count)
def hide_col(self, cr, uid, ids, context = {}):
""" Hide all the related columns
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Hide Columns IDs
@param context: A standard dictionary for contextual values
"""
for id in ids:
self.write(cr, uid, id, {'hide':True})
return {}
def show_col(self, cr, uid, ids, context = {}):
""" show all the related columns
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of columns IDs
@param context: A standard dictionary for contextual values
"""
for id in ids:
self.write(cr, uid, id, {'hide': True})
return {}
def field_add(self, cr, uid, ids, context = {}):
""" Add all the Related Field
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Fields IDs
@param context: A standard dictionary for contextual values
"""
col_data = self.pool.get('olap.database.columns').read(cr, uid, ids, [], context)[0]
ctx_list = []
if col_data['related_to']:
table_id = col_data['related_to'][0]
else:
table_id = col_data['table_id'][0]
if context['parent_id']:
parent_id = context['parent_id']
val = {
'cube_table_id': parent_id,
'table_id': table_id,
'field_id': ids[0]
}
id = self.pool.get('olap.cube.table.line').create(cr, uid, val, context)
else:
parent_id = self.pool.get('olap.cube.table').create(cr, uid, \
{'name': col_data['table_id'][1]}, context)
ctx_list = [('client', 'web'), ('app', 'bi'), ('id', parent_id)]
return ctx_list
def make_hierarchy(self, cr, uid, ids, context = {}):
""" Make Hierarchy on the cube
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Hierarchys IDs
@param context: A standard dictionary for contextual values
"""
col_data = self.pool.get('olap.database.columns').read(cr, uid, ids, [], context)[0]
ctx_list = []
if context and context.has_key('hier_parent_id')and context['hier_parent_id']:
hier_obj = self.pool.get('olap.hierarchy').browse(cr, uid, context['hier_parent_id'])
pk_table = hier_obj.table_id.name
elif context and context.has_key('hier_parent_table'):
cube_table_obj = self.pool.get('olap.cube.table').browse(cr, uid, context['hier_parent_table'])
pk_table = cube_table_obj.name
val = {
'field_name': col_data['name'],
'name': col_data['name'],
'primary_key_table': pk_table
}
if context['hier_parent_id']:
id = self.pool.get('olap.hierarchy').write(cr, uid, context['hier_parent_id'], val, context)
else:
if context['parent_name']: val['name'] = context['parent_name']
if context['parent_dimension']:val['dimension_id'] = context['parent_dimension']
if context['hier_parent_table']: val['table_id'] = context['hier_parent_table']
if context['parent_field_name']: val['field_name'] = context['parent_field_name']
if context['parent_level']: val['level_ids'] = conext['parent_level']
if context['parent_member_all']: val['member_all'] = context['parent_member_all']
if context['parent_member_default']: val['member_default'] = context['parent_member_default']
if context['parent_type']: val['type'] = context['parent_type']
val['primary_key_table'] = col_data['table_id'][1]
id = self.pool.get('olap.hierarchy').create(cr, uid, val, context)
ctx_list = [('client', 'web'), ('app', 'bi'), ('id', id)]
return ctx_list
olap_database_columns()
class olap_cube_table(osv.osv):
""" Cube Table """
_name = "olap.cube.table"
_description = "Olap cube table"
def write(self, cr, uid, ids, vals, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Cube Tables IDs
@param vals: Get the Value's of cube table
@param context: A standard dictionary for contextual values
"""
if vals and vals.get('available_table_ids', 0) and context and \
(context.has_key('master_dim') or context.has_key('d_id') or \
context.has_key('parent_schema_id')):
new_fields = vals['available_table_ids'][0][2]
final = []
for data in self.browse(cr, uid, ids):
orignal_lines = []
for line in data.line_ids:
orignal_lines.append(line.id)
orignal_fields = []
for line in data.line_ids:
orignal_fields.append(line.field_id.id)
if len(orignal_fields) < len(new_fields):
if new_fields[:len(orignal_fields)] == orignal_fields:
new_fields = new_fields[len(orignal_fields):]
cols_obj = self.pool.get('olap.database.columns').browse(cr, uid, new_fields)
val = {}
val['cube_table_id'] = ids[0]
for col in cols_obj:
val['table_id'] = col.table_id.id
val['field_id'] = col.id
id = self.pool.get('olap.cube.table.line').create(cr, uid, val, context = context)
else:
cols_obj = self.pool.get('olap.database.columns').unlink(cr, uid, orignal_lines)
cols_obj = self.pool.get('olap.database.columns').browse(cr, uid, new_fields)
val = {}
val['cube_table_id'] = ids[0]
for col in cols_obj:
val['table_id'] = col.table_id.id
val['field_id'] = col.id
id = self.pool.get('olap.cube.table.line').create(cr, uid, val, context = context)
elif len(orignal_fields) > len(new_fields):
if orignal_fields[:len(new_fields)] == new_fields:
remove_id = orignal_lines[len(new_fields):]
id = self.pool.get('olap.cube.table.line').unlink(cr,\
uid, remove_id, context = context)
else:
val = {}
id = self.pool.get('olap.cube.table.line').unlink(cr, \
uid, orignal_lines , context = context)
cols_obj = self.pool.get('olap.database.columns').browse(cr, uid, new_fields)
val = {}
val['cube_table_id'] = ids[0]
for col in cols_obj:
val['table_id'] = col.table_id.id
val['field_id'] = col.id
id = self.pool.get('olap.cube.table.line').create(cr, uid, val, context = context)
return super(olap_cube_table, self).write(cr, uid, ids, vals, context)
def create(self, cr, uid, vals, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param vals: Get the Value's of cube table
@param context: A standard dictionary for contextual values
"""
cube_table_id = super(olap_cube_table, self).create(cr, uid, vals, context)
if vals and vals.get('available_table_ids', 0) and context and \
(context.has_key('d_id') or context.has_key('parent_schema_id') or \
context.has_key('master_dim') or context.has_key('d_id')):
lines_ids = vals['available_table_ids'][0][2]
cols_obj = self.pool.get('olap.database.columns').browse(cr, uid, lines_ids)
val = {}
val['cube_table_id'] = cube_table_id
for col in cols_obj:
val['table_id'] = col.table_id.id
val['field_id'] = col.id
id = self.pool.get('olap.cube.table.line').create(cr, uid, val, context = context)
return cube_table_id
def search(self, cr, uid, args, offset = 0, limit = None, order = None,
context = None, count = False):
""" olap search method.
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param user: the current users ID for security checks,
@param args: list of tuples of form [(name_of_the_field, operator, value), ...].
@param offset: The Number of Results to Pass
@param limit: The Number of Results to Return
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('parent_schema_id'):
args = [('schema_id', '=', context['parent_schema_id'])]
if context and context.has_key('d_id'):
dim_obj = self.pool.get('olap.dimension').browse(cr, uid, int(context['d_id']))
args = [('schema_id', '=', dim_obj.cube_id.schema_id.id)]
return super(olap_cube_table, self).search(cr, uid, args, offset, limit, \
order, context = context, count = count)
def _available_table_get(self, cr, uid, ids, name, arg, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Available Tables IDs
@param arg: list of tuples of form [(name_of_the_field, operator, value), ...]
@param context: A standard dictionary for contextual values
"""
result = {}
parent_table_id = []
parent_table_ids = []
field_obj = self.pool.get('olap.database.columns')
for table in self.browse(cr, uid, ids, context):
if table.line_ids:
ids = []
ids = map(lambda x: x.field_id.id, table.line_ids)
result[table.id] = ids
else:
result[table.id] = []
return result
def _set_schema(self, cr, uid, context = {}):
""" Set Schema for cube table
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('d_id'):
dim_obj = self.pool.get('olap.dimension').browse(cr, uid, int(context['d_id']))
return dim_obj.cube_id.schema_id.id
if context and context.has_key('parent_schema_id'):
return context['parent_schema_id']
def _set_name(self, cr, uid, context = {}):
""" set name for cube table
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('d_id'):
dim_obj = self.pool.get('olap.dimension').browse(cr, uid, int(context['d_id']))
return dim_obj.cubeAid.table_id.name
def _get_id(self, cr, uid, ids, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('d_id'):
dim_obj = self.pool.get('olap.dimension').browse(cr, uid, int(context['d_id']))
table_id = self.pool.get('olap.database.tables').search(cr, uid, \
[('table_db_name', 'in', [dim_obj.cube_id.table_id.name]), \
('fact_database_id', '=', dim_obj.cube_id.schema_id.database_id.id)])
col_ids = self.pool.get('olap.database.columns').search(cr, uid, \
[('table_id', 'in', table_id), ('hide', '<>', True), ('related_to', '<>', False)])
else:
col_ids = self.pool.get('olap.database.columns').search(cr, uid, \
[('primary_key', '=', True), ('hide', '<>', True)])
return col_ids
def _def_set(self, cr, uid, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
return []
_columns = {
'name': fields.char('Table name', size = 64, required = True),
'line_ids': fields.one2many('olap.cube.table.line', 'cube_table_id',\
'Database Tables', required = True),
'schema_id': fields.many2one('olap.schema', 'Schema id', ondelete = 'cascade'),
'column_link_id': fields.many2one('olap.database.columns', 'Relational Column' , required = True),
'available_table_ids': fields.function(
_available_table_get,
method = True,
relation = 'olap.database.columns',
string = 'Available Tables',
type = "many2many"
),
}
_defaults = {
'schema_id': _set_schema,
}
def field_add(self, cr, uid, ids, context = {}):
""" Add the Field for the cube table
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of cube tables IDs
@param context: A standard dictionary for contextual values
"""
return {}
olap_cube_table()
class olap_cube_table_line(osv.osv):
""" Cube Table Line """
_name = "olap.cube.table.line"
_description = "Olap cube table"
_rec_name = 'table_id'
_columns = {
'cube_table_id': fields.many2one('olap.cube.table', 'Cube Table',\
required = True, ondelete = 'cascade'),
'table_id': fields.many2one('olap.database.tables', 'Database Table',\
required = True, ondelete = 'cascade'),
'field_id': fields.many2one('olap.database.columns', 'Link Field'),
}
# Set the Table when changing field_id
def onchange_field_id(self, *args, **argv):
"""
@param self: The object pointer
@param *args: For Positional Argument
@param **argv: For Keyword Argument
"""
pass
olap_cube_table_line()
class olap_cube(osv.osv):
""" Olap Cube """
_name = "olap.cube"
_description = "Olap cube"
def _set_schema(self, cr, uid, context = {}):
""" set schema for olap cube
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('schema_id'):
return context['schema_id']
return False
_columns = {
'name': fields.char('Cube name', size = 64, required = True),
'table_id': fields.many2one('olap.cube.table', 'Fact table', size = 64,\
required = True, help="Table(s) for cube."),
'schema_id': fields.many2one('olap.schema', 'Schema', readonly = True),
'dimension_ids': fields.one2many('olap.dimension', 'cube_id', 'Dimensions'),
'measure_ids': fields.one2many('olap.measure', 'cube_id', 'Measures'),
'query_log': fields.boolean('Query Logging', help = "Enabling this will \
log all the queries in the browser"),
'query_ids': fields.one2many('olap.query.logs', 'cube_id', 'Queries'),
}
_defaults = {
'schema_id': _set_schema
}
olap_cube()
class olap_query_logs(osv.osv):
""" Query Logs """
_name = "olap.query.logs"
_description = "Olap query logs"
_columns = {
'user_id': fields.many2one('res.users', 'OpenERP SA User'),
'query': fields.text('Query', required = True),
'time': fields.datetime('Time', required = True),
'result_size': fields.integer('Result Size', readonly = True),
'cube_id': fields.many2one('olap.cube', 'Cube', required = True),
'count': fields.integer('Count', readonly=True),
'schema_id': fields.many2one('olap.schema', 'Schema', readonly = True),
}
_defaults = {
'count':lambda * args: 0
}
olap_query_logs()
class olap_dimension(osv.osv):
""" Olap Dimension """
_name = "olap.dimension"
_description = "Olap dimension"
def _set_cube(self, cr, uid, context = {}):
""" set cube for Olap Dimension
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('cube_id'):
return context['cube_id']
return False
_columns = {
'name': fields.char('Dimension name', size = 64, required = True),
'cube_id': fields.many2one('olap.cube', 'Cube', required = True),
'hierarchy_ids': fields.one2many('olap.hierarchy', 'dimension_id', 'Hierarchies'),
}
_defaults = {
'cube_id': _set_cube,
}
olap_dimension()
class olap_hierarchy(osv.osv):
""" Olap Hierarchy """
_name = "olap.hierarchy"
_description = "Olap hierarchy"
_order = "sequence, id"
hierarchy_type = {
'date': 'Date',
'date_year': 'Year of Date',
'date_quarter': 'Quarter of Date',
'date_month': 'Month of Date',
'many2one': 'Many2one'
}
def _set_dimension(self, cr, uid, context = {}):
""" set Dimension for Olap Hierarchy
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('dimension_id'):
return context['dimension_id']
return False
def _set_name(self, cr, uid, context = {}):
""" set name for Olap Hierarchy
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('dimension_id'):
dim_obj = self.pool.get('olap.dimension').browse(cr, uid, int(context['dimension_id']))
return dim_obj.name
return False
def _hierarchy_get(self, *args, **argv):
"""
@param self: The object pointer
@param *args: For Positional Argument
@param **args: For Keyword Argument
"""
return self.hierarchy_type.items()
_columns = {
'name': fields.char('Hierarchy name', size = 64, required = True),
'primary_key': fields.char('Primary key', size = 64),
'primary_key_table': fields.char('Primary key table', size = 64),
'sequence': fields.integer('Sequence', required = True),
'dimension_id': fields.many2one('olap.dimension', 'Dimension', required = True),
'level_ids': fields.one2many('olap.level', 'hierarchy_id', 'Levels'),
'table_id': fields.many2one('olap.cube.table', 'Fact table(s)', \
required = True , help ="Table(s) to make hierarchy on the cube."),
}
_defaults = {
'sequence': lambda * args: 1,
'primary_key': lambda * args: 'id',
'dimension_id': _set_dimension,
'name': _set_name
}
olap_hierarchy()
class olap_level(osv.osv):
""" Olap Level """
_name = "olap.level"
_description = "Olap level"
_order = "sequence, id"
_types = {
'normal': levels.level_normal(),
'date_year': levels.level_date_year(),
'date_quarter': levels.level_date_quarter(),
'date_month': levels.level_date_month()
}
def _set_hierarchy(self, cr, uid, context = {}):
""" set Hierarchy for Olap Level
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('hierarchy_id'):
return context['hierarchy_id']
return False
def _set_name(self, cr, uid, context = {}):
""" set name for Olap Level
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('hierarchy_id'):
hier_obj = self.pool.get('olap.hierarchy').browse(cr, uid, int(context['hierarchy_id']))
return hier_obj.name
def onchange_column_name(self, cr, uid, ids, column, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Olap Levels IDs
@param context: A standard dictionary for contextual values
"""
if not column:
return {}
val = {}
col = self.pool.get('olap.database.columns').browse(cr, uid, column)
val['table_name'] = col.table_id.table_db_name
val['column_id_name'] = col.column_db_name
if (col.type == 'date'):
val['type'] = 'date_year'
return {'value': val}
def _type_get(self, cr, uid, *args, **argv):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param *args: For Positional Argument
@param **args: For Keyword Argument
"""
keys = self._types.keys()
return map(lambda x: (x,x),keys)
_columns = {
'name': fields.char('Level name', size = 64, required = True),
'column_name': fields.many2one('olap.database.columns', 'Columns Name', required = True),
'column_id_name': fields.char('Column ID', size = 64, required = True),
'type': fields.selection(selection = _type_get, string = 'Level class', size = 64, required = True),
'table_name': fields.char('Table name', size = 64, required = True, \
help = "The name of the table on which the column is defined.\
If False, take the table from the hierarchy."),
'sequence': fields.integer('Sequence', required = True),
'hierarchy_id': fields.many2one('olap.hierarchy', 'Hierarchy', required = True),
}
_defaults = {
'column_id_name': lambda * args: 'name',
'sequence': lambda * args: '1',
'type': lambda * args:'normal',
'hierarchy_id': _set_hierarchy,
'name': _set_name
}
olap_level()
class olap_measure(osv.osv):
""" Olap Measure """
_name = "olap.measure"
_description = "Olap measure"
def _set_cube(self, cr, uid, context = {}):
""" set cube for Olap Measure
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
if context and context.has_key('cube_id'):
return context['cube_id']
return False
def onchange_measure_name(self, cr, uid, ids, column, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Olap Measures IDs
@param context: A standard dictionary for contextual values
"""
val = {}
if not column:
return {}
col = self.pool.get('olap.database.columns').browse(cr, uid, column)
val['table_name'] = col.table_id.table_db_name
val['value_column_id_name'] = col.column_db_name
val['name'] = col.column_db_name
return {'value': val}
_columns = {
'name': fields.char('Measure name', size = 64, required = True),
'cube_id': fields.many2one('olap.cube', 'Cube', required = True),
'value_column': fields.many2one('olap.database.columns', 'Fact Table Column'),
'value_column_id_name': fields.char('Column ID', size = 64),
'table_name': fields.char('Table name', size = 64, help = "The name of \
the table on which the column is defined. If False, take the table from the cube."),
'measure_type': fields.selection([('fact_column', 'Fact Table Column'),\
('sql_expr', 'SQL Expression')],\
'Measure Type', required = True,\
help = "Select between auto column or sql expression for the measures"),
'value_sql': fields.text('SQL Expression', help = "You can \
provide valid sql expression. Make sure it have \
function with fully qualified column name like \
(sum,avg ...)(tablename.columnname (+,- ...) tablename.columnname)"),
'agregator': fields.selection([('sum', 'Sum'), ('count', 'count'),\
('avg', 'Average')], 'Agregator', required = True),
'datatype': fields.selection([('int', 'Integer'), ('float', 'Float')], 'Datatype', required = True),
'formatstring': fields.selection([
('none', 'None (0000.00)'),
('cr_prefix', 'Prefix Default Currency (EUR 0000.00)'),
('cr_postfix', 'Postfix Default Currency(0000.00 EUR)'),
('cr_prefix_comma', 'Prefix Default Currency with comma seperator (EUR 0,000.00)'),
('cr_postfix_comma', 'Postfix Default Currency with comma seperator (0,000.00 EUR)'),
('comma_sep', 'Comma Seperator (0,000)')
], 'Format string', required = True, help=" Let you specify how the measure to be displayed in cube browser"),
}
_defaults = {
'agregator': lambda * args: 'sum',
'datatype': lambda * args: 'float',
'formatstring': lambda * args: 'none',
'cube_id': _set_cube,
'measure_type': lambda * args:'fact_column',
}
olap_measure()
class olap_application(osv.osv):
""" Olap Application """
_name = "olap.application"
_description = "Olap application"
_columns = {
'name': fields.char('Application name', size = 64, required = True),
'query': fields.text('Application Query'),
'table_ids': fields.one2many('olap.application.table', 'application_id', 'Tables'),
'field_ids': fields.one2many('olap.application.field', 'application_id', 'Fields'),
}
olap_application()
class olap_application_table(osv.osv):
""" Application Table """
_name = "olap.application.table"
_description = "Olap application table"
_columns = {
'name': fields.char('Application table name', size = 64, required = True),
'table_name': fields.char('Table name', size = 64, required = True),
'is_hidden': fields.boolean('Hidden'),
'application_id': fields.many2one('olap.application', 'Application Id', required = True),
}
olap_application_table()
class olap_application_field(osv.osv):
""" Application Field """
_name = "olap.application.field"
_description = "Olap application field"
_columns = {
'name': fields.char('Application field name', size = 64, required = True),
'table_name': fields.char('Application table name', size = 64),
'field_name': fields.char('Field name', size = 64),
'is_hidden': fields.boolean('Hidden'),
'application_id': fields.many2one('olap.application', 'Application Id', required = True),
}
olap_application_field()
class olap_saved_query(osv.osv):
""" Olap Saved Query """
_name = "olap.saved.query"
_decription = "Olap Saved Query"
_columns = {
'name': fields.text('Query Name', size = 64),
'user_id': fields.many2one('res.users', 'User'),
'query': fields.text('Query', required = True),
'cube_id': fields.many2one('olap.cube', 'Cube', required = True),
'mdx_id': fields.char('Module', size=64),
'schema_id': fields.many2one('olap.schema', 'Schema', required = True),
'time': fields.datetime('Time', required = True),
'axis_keys': fields.text('Axis Keys'),
}
olap_saved_query()
# Wizard for the Load Data Structure
# Replacement for the Load Wizard according to the new structure
class bi_load_db_wizard(osv.osv_memory):
_name = 'bi.load.db.wizard'
def _get_fact_table(self, cr, uid, ctx):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ctx: A standard dictionary for contextual values
"""
if ctx and ctx.has_key('active_id'):
schema_obj = self.pool.get('olap.schema').browse(cr, uid, ctx['active_id'])
return schema_obj.name
return False
def _get_db_name(self, cr, uid, ctx):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ctx: A standard dictionary for contextual values
"""
if ctx and ctx.has_key('active_id'):
schema_obj = self.pool.get('olap.schema').browse(cr, uid, ctx['active_id'])
return schema_obj.database_id.name
return False
_columns = {
'fact_table': fields.char('Fact Name' , size = 64, readonly = True),
'db_name': fields.char('Database Name', size = 64, readonly = True)
}
_defaults = {
'fact_table': _get_fact_table,
'db_name': _get_db_name,
}
def action_load(self, cr, uid, ids, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: Load Actions IDs
@param context: A standard dictionary for contextual values
"""
data = context and context.get('active_id', False) or False
if context and context.has_key('active_id'):
lines = self.pool.get('olap.schema').browse(cr, uid, data)
pool = pooler.get_pool(cr.dbname)
id_db = lines.database_id.id
type = lines.database_id.type
db_name = lines.database_id.db_name
tobj = pool.get('olap.database.tables')
tcol = pool.get('olap.database.columns')
if type == 'postgres':
host = lines.database_id.db_host and "host=%s" % lines.database_id.db_host or ''
port = lines.database_id.db_port and "port=%s" % lines.database_id.db_port or ''
name = lines.database_id.db_name and "dbname=%s" % lines.database_id.db_name or ''
user = lines.database_id.db_login and "user=%s" % lines.database_id.db_login or ''
password = lines.database_id.db_password and \
"password=%s" % lines.database_id.db_password or ''
tdb = psycopg2.connect('%s %s %s %s %s' % (host, port, name, user, password))
cr_db = tdb.cursor()
cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d',(id_db,))
tables = dict(cr.fetchall())
tables_id = map(lambda x: str(tables[x]), tables)
print 'Creating / Updating Tables...'
cr_db.execute("select table_name, table_catalog from \
INFORMATION_SCHEMA.tables as a where a.table_schema = 'public'")
for table in cr_db.fetchall():
val = {
'fact_database_id': id_db,
'table_db_name': table[0]
}
if table[0] in tables.keys():
table_id = tobj.write(cr, uid, [tables[table[0]]], val, context)
else:
val['name'] = table[0]
tables[val['name']] = tobj.create(cr, uid, val, context)
print 'Creating / Updating Columns ....'
cols = {}
if tables_id:
cr.execute('select column_db_name,id,table_id from \
olap_database_columns where table_id in (' + ','.join(tables_id) + ')')
else:
cr.execute("select olap_database_columns.column_db_name,\
olap_database_columns.id, olap_database_columns.table_id \
from olap_database_columns join olap_database_tables \
on olap_database_columns.table_id = olap_database_tables.id \
where olap_database_tables.fact_database_id=%d", (id_db,))
table_col = {}
cols_name = {}
for x in tables:
table_col[str(tables[x])] = [{}]
for data in cr.fetchall():
cols[str(data[1])] = (data[0], int(data[2]))
table_col[str(data[2])][0][data[0]] = data[1]
cols_name[str(data[0])] = (data[1], int(data[2]))
cr_db.execute("""SELECT
table_name, column_name, udt_name
from
INFORMATION_SCHEMA.columns
WHERE table_schema = 'public'""")
for col in cr_db.fetchall():
val = {
'table_id': tables[col[0]],
'column_db_name': col[1],
'type': col[2],
}
id_made = filter(lambda x:(int(cols[x][1]) == int(tables[col[0]])), cols)
if col[0] in tables.keys() and col[1] in cols_name.keys() and id_made:
if table_col[str(tables[col[0]])][0] and col[1] in \
table_col[str(tables[col[0]])][0].keys():
col_id = tcol.write(cr, uid, table_col[str(tables[col[0]])][0][col[1]], val, context)
else:
val['name'] = col[1]
id_made = tcol.create(cr, uid, val, context)
cols[str(id_made)] = (val['name'], int(val['table_id']))
else:
val['name'] = col[1]
id_made = tcol.create(cr, uid, val, context)
cols[str(id_made)] = (val['name'], int(val['table_id']))
print 'Creating / Updating Constraints...'
cr_db.execute("""select
table_name,column_name
from
INFORMATION_schema.key_column_usage
where
constraint_name in (
select constraint_name from INFORMATION_SCHEMA .table_constraints
where
constraint_type = 'PRIMARY KEY')""")
print "Updating the Primary Key Constraint"
for constraint in cr_db.fetchall():
val = {
'primary_key': True
}
id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[0]])and(constraint[1] == cols[x][0])), cols)
col_id = tcol.write(cr, uid, int(id_to_write[0]), val, context)
print "Updating the Foreign key constraint"
cr_db.execute("""select
constraint_name,table_name
from
INFORMATION_schema.constraint_column_usage
where
constraint_name in (
select constraint_name from INFORMATION_SCHEMA.table_constraints
where
constraint_type = 'FOREIGN KEY')""")
for_key = dict(cr_db.fetchall())
cr_db.execute("""select
table_name,column_name,constraint_name
from
INFORMATION_schema.key_column_usage
where
constraint_name IN (
select constraint_name from INFORMATION_SCHEMA.table_constraints
where
constraint_type = 'FOREIGN KEY')""")
for constraint in cr_db.fetchall():
val = {
'related_to': tables[for_key[constraint[2]]]
}
id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[0]])\
and (constraint[1] == cols[x][0])), cols)
if id_to_write:
col_id = tcol.write(cr, uid, int(id_to_write[0]), val, context)
elif type == 'mysql':
try:
import MySQLdb
host = lines.database_id.db_host or ''
port = lines.database_id.db_port or ''
db = lines.database_id.db_name or ''
user = lines.database_id.db_login or ''
passwd = lines.database_id.db_password or ''
tdb = MySQLdb.connect(host = host, port = port, db = db, user = user, passwd = passwd)
except Exception, e:
raise osv.except_osv('MySQLdb Packages Not Installed.', e)
cr_db = tdb.cursor()
cr.execute('select table_db_name,id from olap_database_tables \
where fact_database_id=%d', (id_db,))
tables = dict(cr.fetchall())
tables_id = map(lambda x: str(tables[x]), tables)
cols = {}
if tables_id:
cr.execute('select column_db_name,id,table_id from \
olap_database_columns where table_id IN (' + ','.join(tables_id) + ')')
else:
cr.execute('select column_db_name,id,table_id from olap_database_columns')
for data in cr.fetchall():
cols[str(data[1])] = (data[0], int(data[2]))
cr_db.execute("select table_name, table_catalog from \
INFORMATION_SCHEMA.tables where table_schema =%s", (db_name))
for table in cr_db.fetchall():
val = {
'fact_database_id': id_db,
'table_db_name': table[0]
}
if table[0] in tables.keys():
table_id = tobj.write(cr, uid, [tables[table[0]]], val, context)
else:
val['name'] = table[0]
tables[val['name']] = tobj.create(cr, uid, val, context)
cr_db.execute("""SELECT
table_name, column_name, data_type
from
INFORMATION_SCHEMA.columns
WHERE table_schema = %s""", (db_name))
for col in cr_db.fetchall():
val = {
'table_id': tables[col[0]],
'column_db_name': col[1],
'type': col[2],
}
id_made = filter(lambda x:(int(cols[x][1]) == int(tables[col[0]])), cols)
if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
col_id = tcol.write(cr, uid, cols[tables[str(col[0])]], val, context)
else:
val['name'] = col[1]
id_made = tcol.create(cr, uid, val, context)
cols[str(id_made)] = (val['name'], int(val['table_id']))
cr_db.execute("""select
REFERENCED_COLUMN_NAME,REFERENCED_TABLE_NAME,COLUMN_NAME,TABLE_NAME
from
INFORMATION_schema.key_column_usage
where table_schema= %s and
constraint_name IN (
select constraint_name from INFORMATION_SCHEMA .table_constraints
where
constraint_type IN ('PRIMARY KEY','FOREIGN KEY'))
""", (db_name))
for constraint in cr_db.fetchall():
if constraint[0]:
val = {
'related_to': tables[constraint[1]]
}
else:
val = {
'primary_key': True
}
id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[3]])and \
(constraint[2] == cols[x][0])), cols)
col_id = tcol.write(cr, uid, int(id_to_write[0]), val, context)
elif type == 'oracle':
try:
import cx_Oracle
host = lines.database_id.db_host or ''
port = lines.database_id.db_port or ''
db = lines.database_id.db_name or ''
user = lines.database_id.db_login.upper() or ''
passwd = lines.database_id.db_password or ''
tdb = cx_Oracle.connect(user, passwrd, host)
except Exception, e:
raise osv.except_osv('cx_Oracle Packages Not Installed.', e)
cr_db = tdb.cursor()
cr.execute('select table_db_name,id from olap_database_tables \
where fact_database_id=%d', (id_db,))
tables = dict(cr.fetchall())
tables_id = map(lambda x: str(tables[x]), tables)
cols = {}
if tables_id:
cr.execute('select column_db_name,id,table_id from \
olap_database_columns where table_id IN (' + ','.join(tables_id) + ')')
else:
cr.execute('select column_db_name,id,table_id from olap_database_columns')
for data in cr.fetchall():
cols[str(data[1])] = (data[0], int(data[2]))
cr_db.execute("select table_name from all_tables where owner =%s", (user))
temp = cr_db.fetchall()
for table in temp:
val = {
'fact_database_id': id_db,
'table_db_name': table[0]
}
if table[0] in tables.keys():
table_id = tobj.write(cr, uid, [tables[table[0]]], val, context)
else:
val['name'] = table[0]
tables[val['name']] = tobj.create(cr, uid, val, context)
cr_db.execute("""SELECT
table_name, column_name, data_type
from
all_tab_columns
WHERE owner = %s""", (user))
temp = cr_db.fetchall()
for col in temp:
if col[2] == 'NUMBER':
type_col = 'numeric'
elif col[2] == 'DATE':
type_col = 'date'
elif col[2] == 'VARCHAR2':
type_col = 'varchar'
else:
type_col = col[2]
val = {
'table_id': tables[col[0]],
'column_db_name': col[1],
'type': type_col,
}
id_made = filter(lambda x:(int(cols[x][1]) == int(tables[col[0]])), cols)
if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
col_id = tcol.write(cr, uid, cols[tables[str(col[0])]], val, context)
else:
val['name'] = col[1]
id_made = tcol.create(cr, uid, val, context)
cols[str(id_made)] = (val['name'], int(val['table_id']))
cr_db.execute("""select
table_name,column_name,constraint_name
from
all_cons_columns
where
constraint_name in (
select constraint_name from all_constraints
where
constraint_type = 'P' and owner= %s)
""", (user))
temp = cr_db.fetchall()
pk_table = {}
for constraint in temp:
val = {
'primary_key' : True
}
pk_table[constraint[2]] = constraint[0]
id_to_write = filter(lambda x : (int(cols[x][1]) == int(tables[constraint[0]])\
and(constraint[1] == cols[x][0])), cols)
col_id = tcol.write(cr, uid, int(id_to_write[0]), val, context)
cr_db.execute("""select
constraint_name,r_constraint_name from all_constraints
where
constraint_type = 'R' and owner = %s
""", (user))
constraints_map = {}
for data in cr_db.fetchall():
constraints_map[data[0]] = data[1]
cr_db.execute("""select
table_name,column_name,constraint_name
from
all_cons_columns
where
constraint_name IN (
select constraint_name from all_constraints
where
constraint_type = 'R' and owner = %s)
""", (user))
temp = cr_db.fetchall()
for constraint in temp:
rel_constraint_name = constraints_map[constraint[2]]
req_table = pk_table[rel_constraint_name]
val = {
'related_to' : tables[req_table]
}
id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[0]])\
and (constraint[1] == cols[x][0])), cols)
col_id = tcol.write(cr, uid, int(id_to_write[0]), val, context)
data = context and context.get('active_id', False) or False
temp = pooler.get_pool(cr.dbname).get('olap.fact.database').write(cr, uid, [id_db], {'loaded':True})
wf_service = netsvc.LocalService('workflow')
wf_service.trg_validate(uid, 'olap.schema', data, 'dbload', cr)
model_data_ids = self.pool.get('ir.model.data').search(cr, uid, \
[('model', '=', 'ir.ui.view'), ('name', '=', 'view_olap_schema_form')])
resource_id = self.pool.get('ir.model.data').read(cr, uid, \
model_data_ids, fields = ['res_id'])[0]['res_id']
return {'type': 'ir.actions.act_window_close' }
def action_cancel(self, cr, uid, ids, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of create menus IDs
@param context: A standard dictionary for contextual values
"""
return {'type': 'ir.actions.act_window_close' }
bi_load_db_wizard()
# Wizard for the Automatic Application Configuration
# Replacement for the Load Wizard according to the new structure
class bi_auto_configure_wizard(osv.osv_memory):
_name = 'bi.auto.configure.wizard'
def _get_name(self, cr, uid, context):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
data = context and context.get('active_id', False) or False
if context and context.has_key('active_id'):
schema_obj = self.pool.get('olap.schema').browse(cr, uid, data)
return schema_obj.name
return False
_columns = {
'name': fields.char('Fact Name' , size = 64, readonly = True),
}
_defaults = {
'name': _get_name,
}
def action_load(self, cr, uid, ids, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of create menus IDs
@param context: A standard dictionary for contextual values
"""
vals = {}
apptabnew_vals = {}
appfieldnew_vals = {}
data = context and context.get('active_id', False) or False
ids = pooler.get_pool(cr.dbname).get('olap.schema').browse(cr, uid, data)
if ids.app_detect == "Unknown Application":
raise wizard.except_wizard('Warning', 'The Application is Unknown,\
we can not configure it automatically.')
else:
app_objs = pooler.get_pool(cr.dbname).get('olap.application')
app_ids = app_objs.search(cr, uid, [])
app_res = app_objs.browse(cr, uid, app_ids)
app_id = ''
for x_app in app_res:
app_id = x_app['id']
apptab_objs = pooler.get_pool(cr.dbname).get('olap.application.table')
apptab_ids = apptab_objs.search(cr, uid, [])
apptab_res = apptab_objs.browse(cr, uid, apptab_ids)
apptab_name = []
map_apptab_name = {}
map_apptab_name_id = {}
for aptab in apptab_res:
apptab_name.append(aptab.name)
map_apptab_name_id[aptab.table_name] = aptab
appfield_objs = pooler.get_pool(cr.dbname).get('olap.application.field')
appfield_ids = appfield_objs.search(cr, uid, [])
appfield_res = appfield_objs.browse(cr, uid, appfield_ids)
appfield_data_res = appfield_objs.browse(cr, uid, appfield_ids)
appcol_name = []
for apcol in appfield_res:
appcol_name.append(apcol.name)
dbtab_obj = pooler.get_pool(cr.dbname).get('olap.database.tables')
id_tables = dbtab_obj.search(cr, uid, [('fact_database_id', '=', ids.database_id.id)])
tables_main = dbtab_obj.read(cr, uid, id_tables, context = {'wizard':True})
for tables in tables_main:
end_user_name = {'name':(" ").join(map(lambda x:x.capitalize(), \
tables['table_db_name'].split("_")))}
table_new = dbtab_obj.write(cr, uid, tables['id'], end_user_name)
if not(tables['table_db_name'].startswith('ir') or \
tables['table_db_name'].startswith('wkf') or \
tables['table_db_name'].startswith('res_groups') or \
tables['table_db_name'].startswith('res_role')) and \
tables['table_db_name'] not in ['inherit', 'user_rule_group_rel',\
'group_rule_group_rel']:
vals = {}
if len(apptab_ids) == 0 and (tables['table_db_name'] not in apptab_name):
vals['table_name'] = tables['table_db_name']
vals['name'] = (" ").join(map(lambda x:x.capitalize(), tables['name'].split("_")))
vals['is_hidden'] = tables['hide']
vals['application_id'] = app_id
table_new = dbtab_obj.write(cr, uid, tables['id'], {'hide':False})
apptab_new_obj = apptab_objs.create(cr, uid, vals)
else:
if map_apptab_name_id.has_key(tables['table_db_name']):
app_table = map_apptab_name_id[tables['table_db_name']]
if ((app_table['table_name'] == tables['table_db_name']) \
and not (app_table['table_name'] == tables['name'])):
vals['name'] = (" ").join(map(lambda x:x.capitalize(), \
tables['name'].split("_")))
vals['is_hidden'] = tables['hide']
tables_obj_new = apptab_objs.write(cr, uid, app_table['id'], vals)
else:
vals['table_name'] = tables['table_db_name']
vals['name'] = (" ").join(map(lambda x:x.capitalize(), \
tables['table_db_name'].split("_")))
vals['is_hidden'] = tables['hide']
vals['application_id'] = app_id
apptab_new_obj = apptab_objs.create(cr, uid, vals)
id_columns = pooler.get_pool(cr.dbname).get('olap.database.columns').search(cr, uid, \
[('table_id', 'in', id_tables)])
columns = pooler.get_pool(cr.dbname).get('olap.database.columns').read(cr, uid, id_columns, [])
for columns in columns:
vals = {}
if len(appfield_ids) == 0 and (columns['column_db_name'] not in appcol_name):
vals['field_name'] = columns['column_db_name']
vals['table_name'] = columns['table_id'][1]
vals['name'] = (" ").join(map(lambda x:x.capitalize(), columns['name'].split("_")))
vals['is_hidden'] = columns['hide']
vals['application_id'] = x_app['id']
appfield_new_obj = appfield_objs.create(cr, uid, vals)
else:
filter_column = filter(lambda x: columns['column_db_name'] == x['field_name'] \
and columns['table_id'][1] == x['table_name'], appfield_data_res)
if map_apptab_name_id.has_key(columns['table_id'][1]) and filter_column:
table_id_write = map_apptab_name_id[columns['table_id'][1]]
vals['name'] = (" ").join(map(lambda x:x.capitalize(), columns['name'].split("_")))
vals['is_hidden'] = columns['hide']
appfield_new_obj = appfield_objs.write(cr, uid, filter_column[0]['id'], vals)
else:
vals['field_name'] = columns['column_db_name']
vals['table_name'] = columns['table_id'][1]
vals['name'] = (" ").join(map(lambda x:x.capitalize(), columns['name'].split("_")))
vals['is_hidden'] = columns['hide']
vals['application_id'] = x_app['id']
appfield_new_obj = appfield_objs.create(cr, uid, vals)
database_tables = pooler.get_pool(cr.dbname).get('olap.database.tables')
id_tables = database_tables.search(cr, uid, [('fact_database_id', '=', ids.database_id.id)])
tables = database_tables.read(cr, uid, id_tables, [])
make_id = []
for table in tables:
vals = {}
if (table['table_db_name'].startswith('ir') or \
table['table_db_name'].startswith('wkf')) or \
(table['table_db_name'].startswith('res_groups')) or \
(table['table_db_name'] in \
['inherit', 'res_roles', 'user_rule_group_rel', \
'res_roles_users_rel', 'group_rule_group_rel']):
vals['hide'] = True
vals['active'] = False
make_id.append(table['id'])
database_tables.write(cr, uid, table['id'], vals)
database_columns = pooler.get_pool(cr.dbname).get('olap.database.columns')
id_columns = database_columns.search(cr, uid, [('table_id', 'in', make_id)])
columns = database_columns.read(cr, uid, id_columns, [])
for col in columns:
val = {}
vals['hide'] = True
vals['active'] = False
database_columns.write(cr, uid, col['id'], vals)
data = context and context.get('active_id', False) or False
wf_service = netsvc.LocalService('workflow')
wf_service.trg_validate(uid, 'olap.schema', data, 'dbconfigure', cr)
model_data_ids = self.pool.get('ir.model.data').search(cr, uid, \
[('model', '=', 'ir.ui.view'), ('name', '=', 'view_olap_schema_form')])
resource_id = self.pool.get('ir.model.data').read(cr, uid, \
model_data_ids, fields = ['res_id'])[0]['res_id']
return {'type': 'ir.actions.act_window_close' }
def action_cancel(self, cr, uid, ids, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of create menus IDs
@param context: A standard dictionary for contextual values
"""
return {'type': 'ir.actions.act_window_close' }
bi_auto_configure_wizard()
class olap_warehouse_wizard(osv.osv_memory):
""" Warehouse """
_name = "olap.warehouse.wizard"
_description = "Olap Warehouse"
def _get_queries(self, cr, uid, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
query_obj = self.pool.get('olap.query.logs')
qry_ids = query_obj.search(cr, uid, [('user_id', '=', uid), ('count', '>=', 3)])
if qry_ids:
query = ''
for id in query_obj.browse(cr, uid, qry_ids, context):
if query == '':
query = id.query
else:
query = query + '\n'+id.query
return query
else:
return ''
def action_ok(self, cr, uid, ids, context = {}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of Actions IDs
@param context: A standard dictionary for contextual values
"""
return {'type': 'ir.actions.act_window_close' }
_columns = {
'query': fields.text('Query', readonly=True),
}
_defaults = {
'query': _get_queries,
}
olap_warehouse_wizard()
class olap_parameters_config_wizard(osv.osv_memory):
""" Apply Parameters for configuration """
_name = "olap.parameters.config.wizard"
_description = "Olap Server Parameters"
def _get_host(self, cr, uid, context = None):
""" Get Host ID
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
obj = self.pool.get('olap')
objid = self.pool.get('ir.model.data')
aid = objid._get_id(cr, uid, 'olap', 'menu_url_cube_browser')
aid = objid.browse(cr, uid, aid, context = context).res_id
aid = self.pool.get('ir.actions.url').browse(cr, uid, aid, context = context)
s_p = Literal("http://").suppress() + Word(alphanums + "_" + ".") +\
Literal(":").suppress() + Word(nums) + Literal("/").suppress()\
+ Word(alphanums + "_" + " ").suppress()
return s_p.parseString(aid.url)[0]
def _get_port(self, cr, uid, context = None):
""" Get Port
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param context: A standard dictionary for contextual values
"""
obj = self.pool.get('olap')
objid = self.pool.get('ir.model.data')
aid = objid._get_id(cr, uid, 'olap', 'menu_url_cube_browser')
aid = objid.browse(cr, uid, aid, context = context).res_id
aid = self.pool.get('ir.actions.url').browse(cr, uid, aid, context = context)
s_p = Literal("http://").suppress() + Word(alphanums + "_" + ".") + \
Literal(":").suppress() + Word(nums) + Literal("/").suppress() + \
Word(alphanums + "_" + " ").suppress()
return s_p.parseString(aid.url)[1]
def _get_image(self, cr, uid, context=None):
path = os.path.join('base','res','config_pixmaps/1.png')
file_data = tools.file_open(path,'rb').read()
return base64.encodestring(file_data)
def _progress(self, cr, uid, context=None):
total = self.pool.get('ir.actions.todo')\
.search_count(cr, uid, [], context)
open = self.pool.get('ir.actions.todo')\
.search_count(cr, uid, [('state','<>','open')], context)
if total:
return round(open*90./total)
return 100.
_columns = {
'host_name': fields.char('Server Name', size = 64, help = "Put here the server address or IP \
Put localhost if its not clear.", required = True),
'host_port': fields.char('Port', size = 4, help = "Put the port for the server. Put 8080 if \
its not clear.", required = True),
'config_logo': fields.binary('Image', readonly=True),
'progress': fields.float('Configuration Progress', readonly=True),
}
_defaults = {
'host_name': _get_host,
'host_port': _get_port,
'progress': _progress,
'config_logo': _get_image,
}
def action_cancel(self, cr, uid, ids, conect = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of olap parameters IDs
@param context: A standard dictionary for contextual values
"""
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
def action_config(self, cr, uid, ids, context = None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of create menus IDs
@param context: A standard dictionary for contextual values
"""
conf = self.browse(cr, uid, ids[0], context)
obj = self.pool.get('olap')
objid = self.pool.get('ir.model.data')
aid = objid._get_id(cr, uid, 'olap', 'menu_url_cube_browser')
aid = objid.browse(cr, uid, aid, context = context).res_id
self.pool.get('ir.actions.url').write(cr, uid, [aid],\
{'url': 'http://' + (conf.host_name or 'localhost')\
+ ':' + (conf.host_port or '8080') + '/browser'})
aid = objid._get_id(cr, uid, 'olap', 'menu_url_cube_designer')
aid = objid.browse(cr, uid, aid, context = context).res_id
self.pool.get('ir.actions.url').write(cr, uid, [aid],\
{'url': 'http://' + (conf.host_name or 'localhost') +\
':' + (conf.host_port or '8080') + '/designer'})
return {
'view_type': 'form',
"view_mode": 'form',
'res_model': 'ir.actions.configuration.wizard',
'type': 'ir.actions.act_window',
'target':'new',
}
olap_parameters_config_wizard()
# vim: ts=4 sts=4 sw=4 si et