This topic walks you through connecting to OceanBase Database's Oracle mode using the Python cx_Oracle driver. cx_Oracle is Oracle's official Python database interface, fully compatible with Oracle OCI, and enables seamless connectivity to OceanBase’s Oracle tenants.
Prerequisites
- You have installed Python 3.7 or later.
- You have installed OceanBase Database and created an Oracle-compatible tenant.
- You have installed the libobclient and OBCI components.
Procedure
Follow these steps to connect to OceanBase Database's Oracle-compatible mode using the cx_Oracle driver.
Step 1: Install the Python 3.7 environment
Make sure that the system has installed Python 3.7 or later. You can run the following command to check the Python version:
python3 --version
If not, install Python 3.7 based on your operating system.
Step 2: Install the libobclient and OBCI components
Install the OceanBase client components, including libobclient and OBCI:
# Uninstall the old version (if any)
rpm -e libobclient
rpm -e obci
# Install the new version
rpm -ivh libobclient-2.2.11-42025062010.el7.x86_64.rpm
rpm -ivh obci-2.1.1-342025070917.el7.x86_64.rpm
Notice
Make sure that your libobclient version is 2.2.11 or higher, and your OBCI version is 2.1.1 or higher. Using earlier versions may result in connection failures or unexpected behavior.
Step 3: Install the cx_Oracle driver
Decompress and install the cx_Oracle driver:
# Switch to the driver installation directory
cd /directory/of/cx_Oracle-8.3.0.tar.gz
# Decompress the cx_Oracle driver package
tar -xvf cx_Oracle-8.3.0.tar.gz
# Go to the decompressed directory
cd cx_Oracle-8.3.0
# Install the cx_Oracle driver
python3 setup.py install
After the installation is completed, the cx_Oracle module is generated in the /usr/local/lib/python3.7/site-packages/ directory.
Step 4: Configure the environment variables
Set the LD_LIBRARY_PATH environment variable to make sure that Python can find the OceanBase client library:
export LD_LIBRARY_PATH=/u01/obclient/lib/:$LD_LIBRARY_PATH
We recommend that you add this configuration to your shell configuration file (such as ~/.bashrc or ~/.zshrc) to make it permanently effective.
Step 5: Write a test program
Create a file named test_oracle.py and paste the following code:
import cx_Oracle
# Database connection information
username = 'test@oracle'
password = 'test'
oracle_connection = 'xxx.xxx.xxx.xxx:2881/TEST'
# Create a database connection
conn = cx_Oracle.connect(username, password, oracle_connection)
def exec_sql(sql):
"""Execute an SQL statement."""
cur = conn.cursor()
try:
cur.execute(sql)
conn.commit()
print(f"SQL executed successfully: {sql}")
except Exception as e:
print(f"SQL execution failed: {sql}")
print(f"Error message: {e}")
finally:
cur.close()
def print_data(sql):
"""Query and print data."""
cur = conn.cursor()
try:
cur.execute(sql)
data = cur.fetchall()
print(f"Query result: {data}")
return data
except Exception as e:
print(f"Query failed: {sql}")
print(f"Error message: {e}")
return None
finally:
cur.close()
def test_char_types():
"""Test character types."""
print("\n=== Testing character types ===")
exec_sql("DROP TABLE test_char")
exec_sql("""
CREATE TABLE test_char (
id INT,
a VARCHAR2(20),
b CHAR(10),
c NCHAR(10),
d NVARCHAR2(10)
)
""")
exec_sql("INSERT INTO test_char VALUES (1, 'hello', 'adffdf', '2df4d', 'dsf44f')")
print_data("SELECT * FROM test_char")
def test_number_types():
"""Test numeric types."""
print("\n=== Testing numeric types ===")
exec_sql("DROP TABLE test_number")
exec_sql("""
CREATE TABLE test_number (
a NUMBER,
b FLOAT(126),
c BINARY_FLOAT,
d BINARY_DOUBLE
)
""")
exec_sql("INSERT INTO test_number VALUES (12.32, 12.34, 14.23, 123.3433)")
print_data("SELECT * FROM test_number")
def test_time_types():
"""Test time types."""
print("\n=== Testing time types ===")
exec_sql("DROP TABLE test_time")
exec_sql("""
CREATE TABLE test_time (
a DATE,
b TIMESTAMP,
c TIMESTAMP WITH TIME ZONE,
d TIMESTAMP WITH LOCAL TIME ZONE
)
""")
exec_sql("""
INSERT INTO test_time VALUES (
TIMESTAMP'2022-08-29 14:44:30',
TIMESTAMP'2022-08-29 14:44:30',
TIMESTAMP'2022-08-29 14:44:30',
TIMESTAMP'2022-08-29 14:44:30'
)
""")
print_data("SELECT * FROM test_time")
def test_lob_types():
"""Test LOB types."""
print("\n=== Testing LOB types ===")
exec_sql("DROP TABLE test_lob")
exec_sql("""
CREATE TABLE test_lob (
a CLOB,
b BLOB,
c RAW(100)
)
""")
exec_sql("INSERT INTO test_lob VALUES ('sdfdslkfjldsf', '31323334353637', '31323334')")
print_data("SELECT * FROM test_lob")
def main():
"""Main function."""
try:
print("Starting to test the connection to OceanBase Database in Oracle-compatible mode...")
# Test various data types
test_char_types()
test_number_types()
test_time_types()
test_lob_types()
print("\nAll tests completed!")
except Exception as e:
print(f"An error occurred during testing: {e}")
finally:
# Close the database connection
if conn:
conn.close()
print("Database connection closed")
if __name__ == "__main__":
main()
Step 6: Run the test program
Run the test program in the command line:
python3 test_oracle.py
The program will sequentially test data operations for character types, numeric types, time types, and LOB types, and output the execution results.
Connection pool support
Starting with OBCI 2.1.1, the connection pool feature is supported. You can use a connection pool to enhance your application's performance and concurrency.
import cx_Oracle
from cx_Oracle import SessionPool
def test_simple_pool():
"""Test connection pool."""
try:
print("Creating connection pool...")
# Create connection pool
pool = SessionPool(
user="test@oracle",
password="test",
dsn="xxx.xxx.xxx.xxx:2881/TEST",
min=2,
max=5,
increment=1
)
print(f"Connection pool created successfully!")
print(f"- Minimum connections: {pool.min}")
print(f"- Maximum connections: {pool.max}")
print(f"- Increment: {pool.increment}")
print("\nTesting connection pool usage...")
# Acquire connection from the pool
with pool.acquire() as connection:
with connection.cursor() as cursor:
# Execute query
cursor.execute("SELECT COUNT(*) FROM test_char")
result = cursor.fetchone()
print(f"Number of records in test_char table: {result[0]}")
# Execute another query
cursor.execute("SELECT * FROM test_char WHERE id = 1")
data = cursor.fetchone()
print(f"Query result: {data}")
print(f"\nConnection pool status:")
print(f"- Current open connections: {pool.opened}")
print(f"- Current busy connections: {pool.busy}")
print("\nConnection pool test completed successfully!")
# Note: Do not call pool.close() to avoid segmentation faults
except Exception as e:
print(f"Error occurred: {e}")
if __name__ == "__main__":
test_simple_pool()