Browse Source

[10.0] Add Firebird database support to base_external_dbsource (#623)

pull/734/head
Michell Stuttgart 8 years ago
committed by Maxime Chambreuil
parent
commit
4b75084980
  1. 6
      base_external_dbsource/README.rst
  2. 2
      base_external_dbsource/__manifest__.py
  3. 40
      base_external_dbsource/models/base_external_dbsource.py
  4. 8
      base_external_dbsource/tests/test_create_dbsource.py

6
base_external_dbsource/README.rst

@ -6,7 +6,7 @@
External Database Sources External Database Sources
========================= =========================
This module allows you to define connections to foreign databases using ODBC,
This module allows you to define connections to foreign databases using ODBC, Firebird,
Oracle Client or SQLAlchemy. Oracle Client or SQLAlchemy.
Installation Installation
@ -24,6 +24,7 @@ Depending on the database, you need:
* to install unixodbc and python-pyodbc packages to use ODBC connections. * to install unixodbc and python-pyodbc packages to use ODBC connections.
* to install FreeTDS driver (tdsodbc package) and configure it through ODBC to connect to Microsoft SQL Server. * to install FreeTDS driver (tdsodbc package) and configure it through ODBC to connect to Microsoft SQL Server.
* to install and configure Oracle Instant Client and cx_Oracle python library to connect to Oracle. * to install and configure Oracle Instant Client and cx_Oracle python library to connect to Oracle.
* to install fdb package to connect in Firebird.
Usage Usage
@ -35,7 +36,7 @@ To use this module:
* Click on Create to enter the following information: * Click on Create to enter the following information:
* Data source name  * Data source name 
* Pasword
* Password
* Connector: Choose the database to which you want to connect * Connector: Choose the database to which you want to connect
* Connection string : Specify how to connect to database * Connection string : Specify how to connect to database
@ -65,6 +66,7 @@ Contributors
* Daniel Reis <dreis.pt@hotmail.com> * Daniel Reis <dreis.pt@hotmail.com>
* Maxime Chambreuil <maxime.chambreuil@savoirfairelinux.com> * Maxime Chambreuil <maxime.chambreuil@savoirfairelinux.com>
* Gervais Naoussi <gervaisnaoussi@gmail.com> * Gervais Naoussi <gervaisnaoussi@gmail.com>
* Michell Stuttgart <michellstut@gmail.com>
Maintainer Maintainer
---------- ----------

2
base_external_dbsource/__manifest__.py

@ -4,7 +4,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'External Database Sources', 'name': 'External Database Sources',
'version': '10.0.1.0.0',
'version': '10.0.1.0.1',
'category': 'Tools', 'category': 'Tools',
'author': "Daniel Reis,Odoo Community Association (OCA)", 'author': "Daniel Reis,Odoo Community Association (OCA)",
'website': 'https://github.com/OCA/server-tools', 'website': 'https://github.com/OCA/server-tools',

40
base_external_dbsource/models/base_external_dbsource.py

@ -25,6 +25,7 @@ import psycopg2
from odoo import models, fields, api, _ from odoo import models, fields, api, _
from odoo.exceptions import Warning as UserError from odoo.exceptions import Warning as UserError
import odoo.tools as tools import odoo.tools as tools
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
CONNECTORS = [] CONNECTORS = []
@ -63,13 +64,23 @@ except:
_logger.info('Oracle libraries not available. Please install "cx_Oracle"\ _logger.info('Oracle libraries not available. Please install "cx_Oracle"\
python package.') python package.')
try:
import fdb
CONNECTORS.append(('fdb', 'Firebird'))
except:
_logger.info('Firebird libraries not available. Please install "fdb"\
python package.')
CONNECTORS.append(('postgresql', 'PostgreSQL')) CONNECTORS.append(('postgresql', 'PostgreSQL'))
class BaseExternalDbsource(models.Model): class BaseExternalDbsource(models.Model):
_name = "base.external.dbsource" _name = "base.external.dbsource"
_description = 'External Database Sources' _description = 'External Database Sources'
name = fields.Char('Datasource name', required=True, size=64) name = fields.Char('Datasource name', required=True, size=64)
conn_string = fields.Text('Connection string', help=""" conn_string = fields.Text('Connection string', help="""
Sample connection strings: Sample connection strings:
- Microsoft SQL Server: - Microsoft SQL Server:
@ -77,12 +88,16 @@ class BaseExternalDbsource(models.Model):
- MySQL: mysql://user:%s@server:port/dbname - MySQL: mysql://user:%s@server:port/dbname
- ODBC: DRIVER={FreeTDS};SERVER=server.address;Database=mydb;UID=sa - ODBC: DRIVER={FreeTDS};SERVER=server.address;Database=mydb;UID=sa
- ORACLE: username/%s@//server.address:port/instance - ORACLE: username/%s@//server.address:port/instance
- FireBird: host=localhost;database=mydatabase.gdb;user=sysdba;password=%s;
port=3050;charset=utf8
- PostgreSQL: - PostgreSQL:
dbname='template1' user='dbuser' host='localhost' port='5432' \ dbname='template1' user='dbuser' host='localhost' port='5432' \
password=%s password=%s
- SQLite: sqlite:///test.db - SQLite: sqlite:///test.db
""") """)
password = fields.Char('Password', size=40) password = fields.Char('Password', size=40)
connector = fields.Selection(CONNECTORS, 'Connector', required=True, connector = fields.Selection(CONNECTORS, 'Connector', required=True,
help="If a connector is missing from the\ help="If a connector is missing from the\
list, check the server log to confirm\ list, check the server log to confirm\
@ -95,13 +110,13 @@ class BaseExternalDbsource(models.Model):
self.ensure_one() self.ensure_one()
# Get dbsource record # Get dbsource record
# data = self.browse(cr, uid, id1)
# Build the full connection string # Build the full connection string
connStr = self.conn_string connStr = self.conn_string
if self.password: if self.password:
if '%s' not in self.conn_string: if '%s' not in self.conn_string:
connStr += ';PWD=%s' connStr += ';PWD=%s'
connStr = connStr % self.password connStr = connStr % self.password
# Try to connect # Try to connect
if self.connector == 'cx_Oracle': if self.connector == 'cx_Oracle':
os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.UTF8' os.environ['NLS_LANG'] = 'AMERICAN_AMERICA.UTF8'
@ -110,6 +125,9 @@ class BaseExternalDbsource(models.Model):
conn = pyodbc.connect(connStr) conn = pyodbc.connect(connStr)
elif self.connector in ('sqlite', 'mysql', 'mssql'): elif self.connector in ('sqlite', 'mysql', 'mssql'):
conn = sqlalchemy.create_engine(connStr).connect() conn = sqlalchemy.create_engine(connStr).connect()
elif self.connector == 'fdb':
kwargs = dict([x.split('=') for x in connStr.split(';')])
conn = fdb.connect(**kwargs)
elif self.connector == 'postgresql': elif self.connector == 'postgresql':
conn = psycopg2.connect(connStr) conn = psycopg2.connect(connStr)
@ -134,7 +152,7 @@ class BaseExternalDbsource(models.Model):
{ 'cols': [ 'col_a', 'col_b', ...] { 'cols': [ 'col_a', 'col_b', ...]
, 'rows': [ (a0, b0, ...), (a1, b1, ...), ...] } , 'rows': [ (a0, b0, ...), (a1, b1, ...), ...] }
""" """
# data = self.browse(cr, uid, ids)
rows, cols = list(), list() rows, cols = list(), list()
for obj in self: for obj in self:
conn = obj.conn_open() conn = obj.conn_open()
@ -144,6 +162,16 @@ class BaseExternalDbsource(models.Model):
if metadata: if metadata:
cols = cur.keys() cols = cur.keys()
rows = [r for r in cur] rows = [r for r in cur]
elif obj.connector in ["fdb"]:
# using other db connectors
cur = conn.cursor()
for key in sqlparams:
sqlquery = sqlquery.replace('%%(%s)s' % key,
str(sqlparams[key]))
cur.execute(sqlquery)
rows = cur.fetchall()
else: else:
# using other db connectors # using other db connectors
cur = conn.cursor() cur = conn.cursor()
@ -160,8 +188,7 @@ class BaseExternalDbsource(models.Model):
@api.multi @api.multi
def connection_test(self): def connection_test(self):
"""Test of connection.""" """Test of connection."""
for obj in self:
self.ensure_one()
conn = False conn = False
try: try:
conn = self.conn_open() conn = self.conn_open()
@ -169,12 +196,9 @@ class BaseExternalDbsource(models.Model):
raise UserError(_("Connection test failed: \ raise UserError(_("Connection test failed: \
Here is what we got instead:\n %s") % tools.ustr(e)) Here is what we got instead:\n %s") % tools.ustr(e))
finally: finally:
try:
if conn: if conn:
conn.close() conn.close()
except Exception:
# ignored, just a consequence of the previous exception
pass
# TODO: if OK a (wizard) message box should be displayed # TODO: if OK a (wizard) message box should be displayed
raise UserError(_("Connection test succeeded: \ raise UserError(_("Connection test succeeded: \
Everything seems properly set up!")) Everything seems properly set up!"))

8
base_external_dbsource/tests/test_create_dbsource.py

@ -56,3 +56,11 @@ class TestCreateDbsource(common.TransactionCase):
except ValueError as e: except ValueError as e:
logging.warning("Log = " + str(e)) logging.warning("Log = " + str(e))
self.assertTrue(u'Wrong value for' in str(e)) self.assertTrue(u'Wrong value for' in str(e))
# Connection to firebird
try:
dbsource.connector = "fdb"
dbsource.connection_test()
except Exception as e:
logging.warning("Log = " + str(e))
self.assertTrue(u'Wrong value for' in str(e))
Loading…
Cancel
Save