Remove sql_db and add database in backend

This commit is contained in:
Cédric Krier committed 2009-02-04 15:29:28 +01:00
1 parent 0448226997
commit f63aaa316d
12 files changed
+443 -303

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ setup(name=PACKAGE,
VERSION.rsplit('.', 1)[0] + '/',
packages=find_packages(exclude=['*.modules.*', 'modules.*', 'modules']),
package_data={
'trytond': ['init.sql'],
'trytond.backend.postgresql': ['init.sql'],
'trytond.ir': ['*.xml', '*.csv'],
'trytond.ir.module': ['*.xml'],
'trytond.ir.ui': ['*.xml', '*.rng', '*.rnc'],
+113
View File
@@ -0,0 +1,113 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
DatabaseIntegrityError = None
class DatabaseInterface(object):
'''
Define generic interface for database connection
'''
def __init__(self, database_name=None):
self.database_name = database_name
def connect(self):
'''
Connect to the database
:return: the database
'''
raise
def cursor(self, autocommit=False):
'''
Retreive a cursor on the database
:param autocommit: a boolean to active autocommit
:return: a Cursor
'''
raise
def close(self):
'''
Close all connection
'''
raise
def create(self, cursor, database_name):
'''
Create a database
:param database_name: the database name
'''
raise
def drop(self, cursor, database_name):
'''
Drop a database
:param cursor: a cursor on an other database
:param database_name: the database name
'''
raise
@staticmethod
def list(cursor):
'''
Get the list of database
:return: a list of database name
'''
raise
@staticmethod
def init(cursor):
'''
Initialize a database
:param cursor: a cursor on the database
'''
raise
class CursorInterface(object):
'''
Define generic interface for database cursor
'''
sql_log = False
IN_MAX = 1000
def __init__(self):
raise
def execute(self, sql, params=None):
'''
Execute a query
:param sql: a sql query string
:param params: a tuple or list of parameters
'''
raise
def close(self):
'''
Close the cursor
'''
raise
def commit(self):
'''
Commit the cursor
'''
raise
def rollback(self):
'''
Rollback the cursor
'''
raise
def test(self):
'''
Test if it is a Tryton database.
'''
raise
+1
View File
@@ -1,5 +1,6 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from database import *
from fields import *
from table import *
+284
View File
@@ -0,0 +1,284 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from trytond.backend.database import DatabaseInterface, CursorInterface
from trytond.config import CONFIG
from trytond.security import Session
from psycopg2.pool import ThreadedConnectionPool
from psycopg2.extensions import cursor
from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
from psycopg2.extensions import register_type, register_adapter
from psycopg2.extensions import UNICODE, AsIs
from psycopg2 import IntegrityError as DatabaseIntegrityError
import time
import logging
import re
import os
if os.name == 'posix':
import pwd
RE_FROM = re.compile('.* from "?([a-zA-Z_0-9]+)"?.*$')
RE_INTO = re.compile('.* into "?([a-zA-Z_0-9]+)"?.*$')
class Database(DatabaseInterface):
def __init__(self, database_name='template1'):
super(Database, self).__init__(database_name=database_name)
self._connpool = None
def connect(self):
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" % self.database_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
dsn = '%s %s %s %s %s' % (host, port, name, user, password)
self._connpool = ThreadedConnectionPool(0, maxconn, dsn)
return self
def cursor(self, autocommit=False):
if self._connpool is None:
self.connect()
conn = self._connpool.getconn()
if autocommit:
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
else:
conn.set_isolation_level(ISOLATION_LEVEL_SERIALIZABLE)
return Cursor(self._connpool, conn, self.database_name)
def close(self):
if self._connpool is None:
return
self._connpool.closeall()
self._connpool = None
def create(self, cursor, database_name):
cursor.execute('CREATE DATABASE "' + database_name + '" ' \
'TEMPLATE template0 ENCODING \'unicode\'')
def drop(self, cursor, database_name):
cursor.execute('DROP DATABASE "' + database_name + '"')
@staticmethod
def list(cursor):
db_user = CONFIG['db_user']
if not db_user and os.name == 'posix':
db_user = pwd.getpwuid(os.getuid())[0]
if not db_user:
cursor.execute("SELECT usename " \
"FROM pg_user " \
"WHERE usesysid = (" \
"SELECT datdba " \
"FROM pg_database " \
"WHERE datname = %s)",
(tools.CONFIG["db_name"],))
res = cursor.fetchone()
db_user = res and res[0]
if db_user:
cursor.execute("SELECT datname " \
"FROM pg_database " \
"WHERE datdba = (" \
"SELECT usesysid " \
"FROM pg_user " \
"WHERE usename=%s) " \
"AND datname not in " \
"('template0', 'template1', 'postgres') " \
"ORDER BY datname",
(db_user,))
else:
cursor.execute("SELECT datname " \
"FROM pg_database " \
"WHERE datname not in " \
"('template0', 'template1','postgres') " \
"ORDER BY datname")
res = []
for db_name, in cursor.fetchall():
try:
database = Database(db_name).connect()
except:
continue
cursor2 = database.cursor()
if cursor2.test():
res.append(db_name)
cursor2.close()
database.close()
return res
@staticmethod
def init(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)
for i in ('ir', 'workflow', 'res', 'webdav'):
root_path = os.path.join(os.path.dirname(__file__), '..', '..')
tryton_file = os.path.join(root_path, i, '__tryton__.py')
mod_path = os.path.join(root_path, i)
info = eval(file(tryton_file).read())
active = info.get('active', False)
if active:
state = 'to install'
else:
state = 'uninstalled'
cursor.execute('SELECT NEXTVAL(\'ir_module_module_id_seq\')')
module_id = cursor.fetchone()[0]
cursor.execute('INSERT INTO ir_module_module ' \
'(id, author, website, name, shortdesc, ' \
'description, state) ' \
'VALUES (%s, %s, %s, %s, %s, %s, %s)',
(module_id, info.get('author', ''),
info.get('website', ''), i, info.get('name', False),
info.get('description', ''), state))
dependencies = info.get('depends', [])
for dependency in dependencies:
cursor.execute('INSERT INTO ir_module_module_dependency ' \
'(module, name) VALUES (%s, %s)',
(module_id, dependency))
class _Cursor(cursor):
def __build_dict(self, row):
res = {}
for i in range(len(self.description)):
res[self.description[i][0]] = row[i]
return res
def dictfetchone(self):
row = self.fetchone()
if row:
return self.__build_dict(row)
else:
return row
def dictfetchmany(self, size):
res = []
rows = self.fetchmany(size)
for row in rows:
res.append(self.__build_dict(row))
return res
def dictfetchall(self):
res = []
rows = self.fetchall()
for row in rows:
res.append(self.__build_dict(row))
return res
class Cursor(CursorInterface):
def __init__(self, connpool, conn, database_name):
self._connpool = connpool
self._conn = conn
self.database_name = database_name
self.dbname = self.database_name #XX to remove
self.cursor = conn.cursor(cursor_factory=_Cursor)
self.sql_from_log = {}
self.sql_into_log = {}
self.count = {
'from': 0,
'into': 0,
}
def __getattr__(self, name):
return getattr(self.cursor, name)
def execute(self, sql, params=None):
if params is None:
params = ()
if self.sql_log:
now = time.time()
try:
if params:
res = self.cursor.execute(sql, params)
else:
res = self.cursor.execute(sql)
except:
logger = logging.getLogger('sql')
logger.error('Wrong SQL: ' + sql % tuple("'%s'" % unicode(x)
for x in params or []))
raise
if self.sql_log:
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
self.count['from'] += 1
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
self.count['into'] += 1
return res
def _print_log(self, sql_type='from'):
logger = logging.getLogger('sql')
logger.info("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:
logger.info("table:", log[0], ":", str(log[1][1]), "/", log[1][0])
amount += log[1][1]
logger.info("SUM:%s/%d"% (amount, self.count[sql_type]))
def close(self):
if self.sql_log:
self._print_log('from')
self._print_log('into')
self.cursor.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.cursor
self._connpool.putconn(self._conn)
def commit(self):
self._conn.commit()
def rollback(self):
self._conn.rollback()
def test(self):
self.cursor.execute("SELECT relname " \
"FROM pg_class " \
"WHERE relkind = 'r' AND relname in (" \
"'inherit', "
"'ir_model', "
"'ir_model_field', "
"'ir_ui_view', "
"'ir_ui_menu', "
"'res_user', "
"'res_group', "
"'res_group_user_rel', "
"'wkf', "
"'wkf_activity', "
"'wkf_transition', "
"'wkf_instance', "
"'wkf_workitem', "
"'wkf_witm_trans', "
"'ir_module_module', "
"'ir_module_module_dependency, '"
"'ir_translation, '"
"'ir_lang'"
")")
return len(self.cursor.fetchall()) != 0
register_type(UNICODE)
register_adapter(Session, AsIs)
File renamed without changes.
+3 -3
View File
@@ -5,9 +5,9 @@
from orm import ORM
from trytond.netsvc import Service, LocalService
from trytond import pooler
from trytond.backend import DatabaseIntegrityError
import copy
import sys
from trytond.sql_db import IntegrityError
import traceback
from trytond.tools import Cache, find_language_context
import time
@@ -54,7 +54,7 @@ class OSVService(Service):
traceback.format_exception(*sys.exc_info()))
logger = logging.getLogger("web-service")
logger.error('Exception in call: \n' + tb_s)
if isinstance(exception, IntegrityError):
if isinstance(exception, DatabaseIntegrityError):
for key in self._sql_errors.keys():
if key in exception[0]:
msg = self._sql_errors[key]
@@ -105,7 +105,7 @@ class OSVService(Service):
traceback.format_exception(*sys.exc_info()))
logger = logging.getLogger()
logger.error('Exception in call: \n' + tb_s)
if isinstance(exception, IntegrityError):
if isinstance(exception, DatabaseIntegrityError):
for key in self._sql_errors.keys():
if key in exception[0]:
raise Exception('UserError', 'Constraint Error',
+4 -3
View File
@@ -1,6 +1,6 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from trytond.sql_db import db_connect
from trytond.backend import Database
import logging
from threading import RLock
@@ -25,7 +25,7 @@ def get_db_and_pool(db_name, update_module=False, wizard=False, report=False,
else:
logging.getLogger('pooler').info(
'Connecting to %s' % (db_name))
database = db_connect(db_name)
database = Database(db_name).connect()
cursor = database.cursor()
if not cursor.test():
raise Exception('UserError', 'Invalid database!')
@@ -105,7 +105,8 @@ def get_db_only(db_name, verbose=True, blocking=True):
if verbose:
logging.getLogger('pooler').info(
'Connecting to %s' % (db_name))
database = db_connect(db_name)
database = Database(db_name)
database.connect()
_DB[db_name] = database
finally:
lock.release()
+2 -2
View File
@@ -28,7 +28,7 @@ import tempfile
from genshi.filters import Translator
import traceback
from trytond.config import CONFIG
from trytond.sql_db import IntegrityError
from trytond.backend import DatabaseIntegrityError
import inspect
import mx.DateTime
import logging
@@ -64,7 +64,7 @@ class ReportService(Service):
traceback.format_exception(*sys.exc_info()))
logging.getLogger("web-service").error(
'Exception in call: ' + tb_s)
if isinstance(exception, IntegrityError):
if isinstance(exception, DatabaseIntegrityError):
pool = pooler.get_pool(cursor.dbname)
for key in pool._sql_errors.keys():
if key in exception[0]:
+2 -2
View File
@@ -12,7 +12,7 @@ import netsvc
import time
import psycopg2
import pooler
import sql_db
from backend import Database
import config
from config import CONFIG
import web_service
@@ -98,7 +98,7 @@ class TrytonServer(object):
if CONFIG['init']:
if not cursor.test():
self.logger.info("init db")
sql_db.init_db(cursor)
Database.init(cursor)
init[db_name] = True
cursor.commit()
cursor.close()
-225
View File
@@ -1,225 +0,0 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from psycopg2.pool import ThreadedConnectionPool
from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE, cursor, AsIs
from psycopg2 import IntegrityError
import psycopg2
import re
import os
from mx import DateTime as mdt
import zipfile
import version
from config import CONFIG
import logging
from trytond.security import Session
from trytond.backend.postgresql import *
RE_FROM = re.compile('.* from "?([a-zA-Z_0-9]+)"?.*$')
RE_INTO = re.compile('.* into "?([a-zA-Z_0-9]+)"?.*$')
class tryton_cursor(cursor):
def __build_dict(self, row):
res = {}
for i in range(len(self.description)):
res[self.description[i][0]] = row[i]
return res
def dictfetchone(self):
row = self.fetchone()
if row:
return self.__build_dict(row)
else:
return row
def dictfetchmany(self, size):
res = []
rows = self.fetchmany(size)
for row in rows:
res.append(self.__build_dict(row))
return res
def dictfetchall(self):
res = []
rows = self.fetchall()
for row in rows:
res.append(self.__build_dict(row))
return res
class FakeCursor(object):
nbr = 0
_tables = {}
sql_log = False
IN_MAX = 1000
def __init__(self, connpool, conn, dbname, cursor_factory):
self._connpool = connpool
self.conn = conn
self.cursor_factory = cursor_factory
self.cursor = conn.cursor(cursor_factory=self.cursor_factory)
self.dbname = dbname
self.sql_from_log = {}
self.sql_into_log = {}
self.count = {
'from': 0,
'into': 0,
}
def execute(self, sql, params=None):
if not params:
params = ()
if self.sql_log:
now = mdt.now()
try:
if params:
res = self.cursor.execute(sql, params)
else:
res = self.cursor.execute(sql)
except:
logger = logging.getLogger('sql')
logger.error('Wrong SQL: ' + sql % tuple("'%s'" % unicode(x)
for x in params or []))
raise
if self.sql_log:
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
self.count['from'] += 1
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
self.count['into'] += 1
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[sql_type])
def close(self):
if self.sql_log:
self.print_log('from')
self.print_log('into')
self.cursor.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.cursor
self._connpool.putconn(self.conn)
def commit(self):
self.conn.commit()
def rollback(self):
self.conn.rollback()
def __getattr__(self, name):
return getattr(self.cursor, name)
def test(self):
'''
Test if it is a Tryton database.
'''
self.cursor.execute("SELECT relname " \
"FROM pg_class " \
"WHERE relkind = 'r' AND relname in (" \
"'inherit', "
"'ir_model', "
"'ir_model_field', "
"'ir_ui_view', "
"'ir_ui_menu', "
"'res_user', "
"'res_group', "
"'res_group_user_rel', "
"'wkf', "
"'wkf_activity', "
"'wkf_transition', "
"'wkf_instance', "
"'wkf_workitem', "
"'wkf_witm_trans', "
"'ir_module_module', "
"'ir_module_module_dependency, '"
"'ir_translation, '"
"'ir_lang'"
")")
return len(self.cursor.fetchall()) != 0
class FakeDB:
def __init__(self, connpool, dbname):
self._connpool = connpool
self.dbname = dbname
def cursor(self, cursor_factory=tryton_cursor):
conn = self._connpool.getconn()
conn.set_isolation_level(ISOLATION_LEVEL_SERIALIZABLE)
return FakeCursor(self._connpool, conn, self.dbname,
cursor_factory=cursor_factory)
def close(self):
self._connpool.closeall()
def db_connect(db_name):
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
dsn = '%s %s %s %s %s' % (host, port, name, user, password)
connpool = ThreadedConnectionPool(0, maxconn, dsn)
return FakeDB(connpool, db_name)
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)
for i in ('ir', 'workflow', 'res', 'webdav'):
root_path = os.path.dirname(__file__)
tryton_file = os.path.join(root_path, i, '__tryton__.py')
mod_path = os.path.join(root_path, i)
info = eval(file(tryton_file).read())
active = info.get('active', False)
if active:
state = 'to install'
else:
state = 'uninstalled'
cursor.execute('SELECT NEXTVAL(\'ir_module_module_id_seq\')')
module_id = cursor.fetchone()[0]
cursor.execute('INSERT INTO ir_module_module ' \
'(id, author, website, name, shortdesc, ' \
'description, state) ' \
'VALUES (%s, %s, %s, %s, %s, %s, %s)',
(module_id, info.get('author', ''),
info.get('website', ''), i, info.get('name', False),
info.get('description', ''), state))
dependencies = info.get('depends', [])
for dependency in dependencies:
cursor.execute('INSERT INTO ir_module_module_dependency ' \
'(module, name) VALUES (%s, %s)',
(module_id, dependency))
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_adapter(Session,
psycopg2.extensions.AsIs)
+31 -65
View File
@@ -5,12 +5,11 @@ import logging
import threading
from trytond.netsvc import Service
from trytond import security
from trytond import sql_db
from trytond.backend import Database
from trytond import pooler
from trytond import tools
import base64
import os
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
import sha
@@ -33,23 +32,30 @@ class DB(Service):
res = False
logger = logging.getLogger('web-service')
database = sql_db.db_connect('template1')
cursor = database.cursor()
cursor.conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
database = Database().connect()
cursor = database.cursor(autocommit=True)
try:
try:
cursor.execute('CREATE DATABASE "' + db_name + '" '\
'TEMPLATE template0 ENCODING \'unicode\'')
database.create(cursor, db_name)
cursor.commit()
cursor.close()
database.close()
cursor = sql_db.db_connect(db_name).cursor()
sql_db.init_db(cursor)
database = Database(db_name).connect()
cursor = database.cursor()
database.init(cursor)
cursor.commit()
cursor.close()
database.close()
cursor = None
database = None
pool = pooler.get_pool(db_name, update_module=True, lang=[lang])
cursor = sql_db.db_connect(db_name).cursor()
database = Database(db_name).connect()
cursor = database.cursor()
#XXX replace with model write
if lang != 'en_US':
cursor.execute('UPDATE ir_lang ' \
'SET translatable = True ' \
@@ -79,6 +85,8 @@ class DB(Service):
finally:
if cursor:
cursor.close()
if database:
database.close()
return res
def drop(self, password, db_name):
@@ -86,12 +94,11 @@ class DB(Service):
pooler.close_db(db_name)
logger = logging.getLogger('web-service')
database = sql_db.db_connect('template1')
cursor = database.cursor()
cursor.conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
database = Database().connect()
cursor = database.cursor(autocommit=True)
try:
try:
cursor.execute('DROP DATABASE "' + db_name + '"')
database.drop(cursor, db_name)
cursor.commit()
except:
logger.error('DROP DB: %s failed' % (db_name,))
@@ -104,6 +111,7 @@ class DB(Service):
logger.info('DROP DB: %s' % (db_name))
finally:
cursor.close()
database.close()
return True
def dump(self, password, db_name):
@@ -146,13 +154,12 @@ class DB(Service):
'RESTORE DB: %s doesn\'t work with password' % (db_name,))
raise Exception, "Couldn't restore database with password"
database = sql_db.db_connect('template1')
cursor = database.cursor()
cursor.conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
cursor.execute('CREATE DATABASE "' + db_name + '" ' \
'TEMPLATE template0 ENCODING \'unicode\'')
database = Database().connect()
cursor = database.cursor(autocommit=True)
database.create(cursor, db_name)
cursor.commit()
cursor.close()
database.close()
cmd = ['pg_restore']
if tools.CONFIG['db_user']:
@@ -190,62 +197,21 @@ class DB(Service):
def db_exist(self, db_name):
try:
database = sql_db.db_connect(db_name)
database = Database(db_name).connect()
cursor = database.cursor()
cursor.close()
database.close()
return True
except:
return False
def list(self):
database = sql_db.db_connect('template1')
database = Database().connect()
try:
cursor = database.cursor()
db_user = tools.CONFIG["db_user"]
if not db_user and os.name == 'posix':
import pwd
db_user = pwd.getpwuid(os.getuid())[0]
if not db_user:
cursor.execute("SELECT usename " \
"FROM pg_user " \
"WHERE usesysid = (" \
"SELECT datdba " \
"FROM pg_database " \
"WHERE datname = %s)",
(tools.CONFIG["db_name"],))
res = cursor.fetchone()
db_user = res and res[0]
if db_user:
cursor.execute("SELECT datname " \
"FROM pg_database " \
"WHERE datdba = (" \
"SELECT usesysid " \
"FROM pg_user " \
"WHERE usename=%s) " \
"AND datname not in " \
"('template0', 'template1', 'postgres') " \
"ORDER BY datname",
(db_user,))
else:
cursor.execute("SELECT datname " \
"FROM pg_database " \
"WHERE datname not in " \
"('template0', 'template1','postgres') " \
"ORDER BY datname")
res = []
for db_name, in cursor.fetchall():
database = pooler.get_db_only(db_name, verbose=False,
blocking=False)
if not database:
continue
cursor2 = database.cursor()
if not cursor2.test():
cursor2.close()
pooler.close_db(db_name)
else:
cursor2.close()
res.append(db_name)
res = database.list(cursor)
cursor.close()
database.close()
except:
res = []
return res
+2 -2
View File
@@ -7,7 +7,7 @@ from xml import dom
from trytond.osv import OSV
from trytond.config import CONFIG
import sys
from trytond.sql_db import IntegrityError
from trytond.backend import DatabaseIntegrityError
import traceback
import logging
@@ -42,7 +42,7 @@ class WizardService(Service):
traceback.format_exception(*sys.exc_info()))
logging.getLogger("web-service").error(
'Exception in call: ' + tb_s)
if isinstance(exception, IntegrityError):
if isinstance(exception, DatabaseIntegrityError):
pool = pooler.get_pool(cursor.dbname)
for key in pool._sql_errors.keys():
if key in exception[0]: