diff --git a/README.md b/README.md index 309a05bf..9a714ba3 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ Therefore there are some modules, which are "natively" supported in the library ## Python modules currently "natively" supported ### Oracle - [oracledb](https://oracle.github.io/python-oracledb/) + - Both thick and thin client modes are supported - you can select one using the `driverMode` parameter. + - However, due to current limitations of the oracledb module, **it's not possible to switch between thick and thin modes during a test execution session** - even in different suites. - [cx_Oracle](https://oracle.github.io/python-cx_Oracle/) ### MySQL - [pymysql](https://github.com/PyMySQL/PyMySQL) diff --git a/src/DatabaseLibrary/connection_manager.py b/src/DatabaseLibrary/connection_manager.py index 003a38a2..f4d05e38 100644 --- a/src/DatabaseLibrary/connection_manager.py +++ b/src/DatabaseLibrary/connection_manager.py @@ -47,11 +47,18 @@ def connect_to_database( dbCharset: Optional[str] = None, dbDriver: Optional[str] = None, dbConfigFile: Optional[str] = None, + driverMode: Optional[str] = None, ): """ Loads the DB API 2.0 module given `dbapiModuleName` then uses it to connect to the database using `dbName`, `dbUsername`, and `dbPassword`. + The `driverMode` is used to select the *oracledb* client mode. + Allowed values are: + - _thin_ (default if omitted) + - _thick_ + - _thick,lib_dir=_ + Optionally, you can specify a `dbConfigFile` wherein it will load the default property values for `dbapiModuleName`, `dbName` `dbUsername` and `dbPassword` (note: specifying `dbapiModuleName`, `dbName` @@ -186,12 +193,33 @@ def connect_to_database( self.omit_trailing_semicolon = True elif dbapiModuleName in ["oracledb"]: dbPort = dbPort or 1521 + driverMode = driverMode or "thin" oracle_connection_params = db_api_2.ConnectParams(host=dbHost, port=dbPort, service_name=dbName) + if "thick" in driverMode.lower(): + logger.info("Using thick Oracle client mode") + mode_param = driverMode.lower().split(",lib_dir=") + if len(mode_param) == 2 and mode_param[0].lower() == "thick": + lib_dir = mode_param[1] + logger.info(f"Oracle client lib dir specified: {lib_dir}") + db_api_2.init_oracle_client(lib_dir=lib_dir) + else: + logger.info("No Oracle client lib dir specified, oracledb will search it in usual places") + db_api_2.init_oracle_client() + oracle_thin_mode = False + elif "thin" in driverMode.lower(): + oracle_thin_mode = True + logger.info("Using thin Oracle client mode") + else: + raise ValueError(f"Invalid Oracle client mode provided: {driverMode}") logger.info( f"Connecting using: {dbapiModuleName}.connect(" f"user={dbUsername}, password=***, params={oracle_connection_params})" ) self._dbconnection = db_api_2.connect(user=dbUsername, password=dbPassword, params=oracle_connection_params) + assert self._dbconnection.thin == oracle_thin_mode, ( + "Expected oracledb to run in thin mode: {oracle_thin_mode}, " + f"but the connection has thin mode: {self._dbconnection.thin}" + ) self.omit_trailing_semicolon = True elif dbapiModuleName in ["teradata"]: dbPort = dbPort or 1025 diff --git a/test/tests/custom_db_tests/oracle_thick_mode.robot b/test/tests/custom_db_tests/oracle_thick_mode.robot new file mode 100644 index 00000000..e9ba1e98 --- /dev/null +++ b/test/tests/custom_db_tests/oracle_thick_mode.robot @@ -0,0 +1,65 @@ +*** Settings *** +Documentation Tests of switching between thin and thick mode of oracledb client. +... Require the oracle client libraries installed. +... See more here: https://python-oracledb.readthedocs.io/en/latest/user_guide/initialization.html#initialization +... +... Due to current limitations of the oracledb module it's not possible to switch between thick and thin modes +... during a test execution session - even in different suites. +... So theses tests should be run separated only. + +Resource ../../resources/common.resource +Test Teardown Drop Tables And Disconnect + + +*** Variables *** +${DB_MODULE} oracledb +${DB_HOST} 127.0.0.1 +${DB_PORT} 1521 +${DB_PASS} pass +${DB_USER} db_user +${DB_NAME} db +${ORACLE_LIB_DIR} ${EMPTY} + + +*** Test Cases *** +Thick Mode Without Client Dir Specified + [Documentation] No client dir --> oracledb will search it in usual places + Connect And Run Simple Query driverMode=thick + +Thick Mode With Client Dir Specified + [Documentation] Client dir specified --> oracledb will search it in this place + Connect And Run Simple Query driverMode=thick,lib_dir=${ORACLE_LIB_DIR} + +Thin Mode - Default + [Documentation] No mode specified --> thin mode is used + Connect And Run Simple Query + +Thin Mode Explicitely Specified + [Documentation] Thin mode specified --> thin mode is used + Connect And Run Simple Query driverMode=thin + +Wrong Mode + [Documentation] Wrong mode --> proper error message from the library + Run Keyword And Expect Error ValueError: Invalid Oracle client mode provided: wrong + ... Connect And Run Simple Query driverMode=wrong + + +*** Keywords *** +Connect And Run Simple Query + [Documentation] Connect using usual params and client mode if provided + [Arguments] &{Extra params} + Connect To Database + ... ${DB_MODULE} + ... ${DB_NAME} + ... ${DB_USER} + ... ${DB_PASS} + ... ${DB_HOST} + ... ${DB_PORT} + ... &{Extra params} + Create Person Table + Query SELECT * FROM person + +Drop Tables And Disconnect + [Documentation] Clean data and disconnect + Drop Tables Person And Foobar + Disconnect From Database