2021-11-07 22:00:21 +01:00
|
|
|
""" Oracle client """
|
|
|
|
|
|
|
|
import logging
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import cx_Oracle
|
|
|
|
|
2023-01-16 12:56:12 +01:00
|
|
|
from mylib.db import DB, DBFailToConnect
|
2021-11-07 22:00:21 +01:00
|
|
|
|
2023-01-07 02:19:18 +01:00
|
|
|
log = logging.getLogger(__name__)
|
2021-11-18 12:43:02 +01:00
|
|
|
|
|
|
|
|
2023-01-07 02:19:18 +01:00
|
|
|
class OracleDB(DB):
|
2023-01-16 12:56:12 +01:00
|
|
|
"""Oracle client"""
|
2021-11-07 22:00:21 +01:00
|
|
|
|
2023-01-07 02:19:18 +01:00
|
|
|
_dsn = None
|
|
|
|
_user = None
|
|
|
|
_pwd = None
|
|
|
|
|
|
|
|
def __init__(self, dsn, user, pwd, **kwargs):
|
2021-11-07 22:00:21 +01:00
|
|
|
self._dsn = dsn
|
|
|
|
self._user = user
|
|
|
|
self._pwd = pwd
|
2023-01-07 02:19:18 +01:00
|
|
|
super().__init__(**kwargs)
|
2021-11-07 22:00:21 +01:00
|
|
|
|
2021-11-23 13:02:46 +01:00
|
|
|
def connect(self, exit_on_error=True):
|
2023-01-16 12:56:12 +01:00
|
|
|
"""Connect to Oracle server"""
|
2021-11-07 22:00:21 +01:00
|
|
|
if self._conn is None:
|
2023-01-16 12:56:12 +01:00
|
|
|
log.info("Connect on Oracle server with DSN %s as %s", self._dsn, self._user)
|
2021-11-07 22:00:21 +01:00
|
|
|
try:
|
2023-01-16 12:56:12 +01:00
|
|
|
self._conn = cx_Oracle.connect(user=self._user, password=self._pwd, dsn=self._dsn)
|
2023-01-06 19:36:14 +01:00
|
|
|
except cx_Oracle.Error as err:
|
2021-11-07 22:00:21 +01:00
|
|
|
log.fatal(
|
2023-01-16 12:56:12 +01:00
|
|
|
"An error occured during Oracle database connection (%s@%s).",
|
|
|
|
self._user,
|
|
|
|
self._dsn,
|
|
|
|
exc_info=1,
|
2021-11-07 22:00:21 +01:00
|
|
|
)
|
2021-11-23 13:02:46 +01:00
|
|
|
if exit_on_error:
|
|
|
|
sys.exit(1)
|
|
|
|
else:
|
2023-01-16 12:56:12 +01:00
|
|
|
raise DBFailToConnect(f"{self._user}@{self._dsn}") from err
|
2021-11-07 22:00:21 +01:00
|
|
|
return True
|
|
|
|
|
|
|
|
def doSQL(self, sql, params=None):
|
|
|
|
"""
|
|
|
|
Run SQL query and commit changes (rollback on error)
|
|
|
|
|
|
|
|
:param sql: The SQL query
|
|
|
|
:param params: The SQL query's parameters as dict (optional)
|
|
|
|
|
|
|
|
:return: True on success, False otherwise
|
|
|
|
:rtype: bool
|
|
|
|
"""
|
|
|
|
if self.just_try:
|
|
|
|
log.debug("Just-try mode : do not really execute SQL query '%s'", sql)
|
|
|
|
return True
|
|
|
|
|
|
|
|
try:
|
2023-01-06 19:36:14 +01:00
|
|
|
self._log_query(sql, params)
|
2022-12-09 12:20:01 +01:00
|
|
|
with self._conn.cursor() as cursor:
|
|
|
|
if isinstance(params, dict):
|
|
|
|
cursor.execute(sql, **params)
|
|
|
|
else:
|
|
|
|
cursor.execute(sql)
|
2021-11-07 22:00:21 +01:00
|
|
|
self._conn.commit()
|
|
|
|
return True
|
2023-01-06 19:36:14 +01:00
|
|
|
except cx_Oracle.Error:
|
|
|
|
self._log_query_exception(sql, params)
|
2021-11-07 22:00:21 +01:00
|
|
|
self._conn.rollback()
|
|
|
|
return False
|
|
|
|
|
|
|
|
def doSelect(self, sql, params=None):
|
|
|
|
"""
|
|
|
|
Run SELECT SQL query and return list of selected rows as dict
|
|
|
|
|
|
|
|
:param sql: The SQL query
|
|
|
|
:param params: The SQL query's parameters as dict (optional)
|
|
|
|
|
|
|
|
:return: List of selected rows as dict on success, False otherwise
|
|
|
|
:rtype: list, bool
|
|
|
|
"""
|
|
|
|
try:
|
2023-01-06 19:36:14 +01:00
|
|
|
self._log_query(sql, params)
|
2022-12-09 12:20:01 +01:00
|
|
|
with self._conn.cursor() as cursor:
|
|
|
|
if isinstance(params, dict):
|
|
|
|
cursor.execute(sql, **params)
|
|
|
|
else:
|
|
|
|
cursor.execute(sql)
|
|
|
|
cursor.rowfactory = lambda *args: dict(
|
|
|
|
zip([d[0] for d in cursor.description], args)
|
|
|
|
)
|
|
|
|
results = cursor.fetchall()
|
2021-11-07 22:00:21 +01:00
|
|
|
return results
|
2023-01-06 19:36:14 +01:00
|
|
|
except cx_Oracle.Error:
|
|
|
|
self._log_query_exception(sql, params)
|
2021-11-07 22:00:21 +01:00
|
|
|
return False
|
|
|
|
|
|
|
|
#
|
|
|
|
# SQL helpers
|
|
|
|
#
|
|
|
|
|
2021-11-18 19:21:43 +01:00
|
|
|
@staticmethod
|
|
|
|
def format_param(param):
|
2023-01-16 12:56:12 +01:00
|
|
|
"""Format SQL query parameter for prepared query"""
|
|
|
|
return f":{param}"
|