Files
tryton/trytond/sql_db.py
T
ced@b2ck.com 26af46b439 - Add workflow module
- Move workflow -> wkf_service
- Fix load xml file for inner module
- Add xml view for menu
- Add property object
2007-12-10 21:17:22 +01:00

188 lines
7.1 KiB
Python

import psycopg
import re
import os
from mx import DateTime as mdt
import zipfile
import version
from config import CONFIG
RE_FROM = re.compile('.* from "?([a-zA-Z_0-9]+)"? .*$')
RE_INTO = re.compile('.* into "?([a-zA-Z_0-9]+)"? .*$')
class FakeCursor:
nbr = 0
_tables = {}
sql_from_log = {}
sql_into_log = {}
sql_log = False
count = 0
def __init__(self, database, con, dbname):
self.db = database
self.obj = database.cursor()
self.con = con
self.dbname = dbname
def execute(self, sql, params=None):
if not params:
params = ()
def base_string(string):
if isinstance(string, unicode):
return string.encode('utf-8')
return string
para = [base_string(string) for string in params]
if isinstance(sql, unicode):
sql = sql.encode('utf-8')
if self.sql_log:
now = mdt.now()
if para:
res = self.obj.execute(sql, para)
else:
res = self.obj.execute(sql)
if self.sql_log:
self.count += 1
res_from = RE_FROM.match(sql.lower())
if res_from:
self.sql_from_log.setdefault(res_from.group(1), [0, 0])
self.sql_from_log[res_from.group(1)][0] += 1
self.sql_from_log[res_from.group(1)][1] += mdt.now() - now
res_into = RE_INTO.match(sql.lower())
if res_into:
self.sql_into_log.setdefault(res_into.group(1), [0, 0])
self.sql_into_log[res_into.group(1)][0] += 1
self.sql_into_log[res_into.group(1)][1] += mdt.now() - now
return res
def print_log(self, sql_type='from'):
print "SQL LOG %s:" % (sql_type,)
if sql_type == 'from':
logs = self.sql_from_log.items()
else:
logs = self.sql_into_log.items()
logs.sort(lambda x, y: cmp(x[1][1], y[1][1]))
amount = 0
for log in logs:
print "table:", log[0], ":", str(log[1][1]), "/", log[1][0]
amount += log[1][1]
print "SUM:%s/%d"% (amount, self.count)
def close(self):
if self.sql_log:
self.print_log('from')
self.print_log('into')
self.obj.close()
# This force the cursor to be freed, and thus, available again. It is
# important because otherwise we can overload the server very easily
# because of a cursor shortage (because cursors are not garbage
# collected as fast as they should). The problem is probably due in
# part because browse records keep a reference to the cursor.
del self.obj
def __getattr__(self, name):
return getattr(self.obj, name)
class FakeDB:
def __init__(self, truedb, dbname):
self.truedb = truedb
self.dbname = dbname
def cursor(self):
return FakeCursor(self.truedb, {}, self.dbname)
def db_connect(db_name, serialize=0):
host = CONFIG['db_host'] and "host=%s" % CONFIG['db_host'] or ''
port = CONFIG['db_port'] and "port=%s" % CONFIG['db_port'] or ''
name = "dbname=%s" % db_name
user = CONFIG['db_user'] and "user=%s" % CONFIG['db_user'] or ''
password = CONFIG['db_password'] \
and "password=%s" % CONFIG['db_password'] or ''
maxconn = int(CONFIG['db_maxconn']) or 64
tdb = psycopg.connect('%s %s %s %s %s' % (host, port, name, user, password),
serialize=serialize, maxconn=maxconn)
fdb = FakeDB(tdb, db_name)
return fdb
def init_db(cursor):
sql_file = os.path.join(os.path.dirname(__file__), 'init.sql')
for line in file(sql_file).read().split(';'):
if (len(line)>0) and (not line.isspace()):
cursor.execute(line)
opj = os.path.join
addons_path = os.path.join(os.path.dirname(__file__), 'addons')
for i in (os.listdir(addons_path) + ['ir', 'workflow', 'res']):
terp_file = opj(addons_path, i, '__terp__.py')
mod_path = opj(addons_path, i)
if i in ('ir', 'workflow', 'res'):
root_path = os.path.dirname(__file__)
terp_file = opj(root_path, i, '__terp__.py')
mod_path = opj(root_path, i)
info = {}
if os.path.isfile(terp_file) \
and not os.path.isfile(opj(addons_path, i + '.zip')):
info = eval(file(terp_file).read())
elif zipfile.is_zipfile(mod_path):
zfile = zipfile.ZipFile(mod_path)
i = os.path.splitext(i)[0]
info = eval(zfile.read(opj(i, '__terp__.py')))
if info:
categs = info.get('category', 'Uncategorized').split('/')
p_id = None
while categs:
if p_id is not None:
cursor.execute('SELECT id ' \
'FROM ir_module_category ' \
'WHERE name = %s AND parent_id = %d',
(categs[0], p_id))
else:
cursor.execute('SELECT id ' \
'FROM ir_module_category ' \
'WHERE name = %s AND parent_id is NULL',
(categs[0],))
c_id = cursor.fetchone()
if not c_id:
cursor.execute(
'SELECT NEXTVAL(\'ir_module_category_id_seq\')')
c_id = cursor.fetchone()[0]
cursor.execute('INSERT INTO ir_module_category ' \
'(id, name, parent_id) ' \
'VALUES (%d, %s, %d)', (c_id, categs[0], p_id))
else:
c_id = c_id[0]
p_id = c_id
categs = categs[1:]
active = info.get('active', False)
installable = info.get('installable', True)
if installable:
if active:
state = 'to install'
else:
state = 'uninstalled'
else:
state = 'uninstallable'
cursor.execute('SELECT NEXTVAL(\'ir_module_module_id_seq\')')
module_id = cursor.fetchone()[0]
cursor.execute('INSERT INTO ir_module_module ' \
'(id, author, latest_version, website, name, shortdesc, ' \
'description, category_id, state) ' \
'VALUES (%d, %s, %s, %s, %s, %s, %s, %d, %s)',
(module_id, info.get('author', ''),
version.VERSION.rsplit('.', 1)[0] + '.' + info.get('version', ''),
info.get('website', ''), i, info.get('name', False),
info.get('description', ''), p_id, state))
dependencies = info.get('depends', [])
for dependency in dependencies:
cursor.execute('INSERT INTO ir_module_module_dependency ' \
'(module_id, name) VALUES (%s, %s)',
(module_id, dependency))
psycopg.register_type(psycopg.new_type((1082,), "date", lambda x:x))
psycopg.register_type(psycopg.new_type((1083,), "time", lambda x:x))
psycopg.register_type(psycopg.new_type((1114,), "datetime", lambda x:x))