470 lines
21 KiB
Python
470 lines
21 KiB
Python
#------------------------------------------------------------------------------
|
|
# Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
#
|
|
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
|
#
|
|
# Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
|
|
# Canada. All rights reserved.
|
|
#------------------------------------------------------------------------------
|
|
|
|
"""
|
|
1100 - Module for testing connections
|
|
"""
|
|
|
|
import test_env
|
|
|
|
import cx_Oracle as oracledb
|
|
import random
|
|
import string
|
|
import threading
|
|
|
|
class TestCase(test_env.BaseTestCase):
|
|
requires_connection = False
|
|
|
|
def __connect_and_drop(self):
|
|
"""Connect to the database, perform a query and drop the connection."""
|
|
connection = test_env.get_connection(threaded=True)
|
|
cursor = connection.cursor()
|
|
cursor.execute("select count(*) from TestNumbers")
|
|
count, = cursor.fetchone()
|
|
self.assertEqual(count, 10)
|
|
|
|
def __verify_args(self, connection):
|
|
self.assertEqual(connection.username, test_env.get_main_user(),
|
|
"user name differs")
|
|
self.assertEqual(connection.tnsentry, test_env.get_connect_string(),
|
|
"tnsentry differs")
|
|
self.assertEqual(connection.dsn, test_env.get_connect_string(),
|
|
"dsn differs")
|
|
|
|
def __verify_attributes(self, connection, attrName, value, sql):
|
|
setattr(connection, attrName, value)
|
|
cursor = connection.cursor()
|
|
cursor.execute(sql)
|
|
result, = cursor.fetchone()
|
|
self.assertEqual(result, value, "%s value mismatch" % attrName)
|
|
|
|
def test_1100_all_args(self):
|
|
"1100 - connection to database with user, password, TNS separate"
|
|
connection = test_env.get_connection()
|
|
self.__verify_args(connection)
|
|
|
|
def test_1101_app_context(self):
|
|
"1101 - test use of application context"
|
|
namespace = "CLIENTCONTEXT"
|
|
app_context_entries = [
|
|
( namespace, "ATTR1", "VALUE1" ),
|
|
( namespace, "ATTR2", "VALUE2" ),
|
|
( namespace, "ATTR3", "VALUE3" )
|
|
]
|
|
connection = test_env.get_connection(appcontext=app_context_entries)
|
|
cursor = connection.cursor()
|
|
for namespace, name, value in app_context_entries:
|
|
cursor.execute("select sys_context(:1, :2) from dual",
|
|
(namespace, name))
|
|
actual_value, = cursor.fetchone()
|
|
self.assertEqual(actual_value, value)
|
|
|
|
def test_1102_app_context_negative(self):
|
|
"1102 - test invalid use of application context"
|
|
self.assertRaises(TypeError, oracledb.connect,
|
|
test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string(),
|
|
appcontext=[('userenv', 'action')])
|
|
|
|
def test_1103_attributes(self):
|
|
"1103 - test connection end-to-end tracing attributes"
|
|
connection = test_env.get_connection()
|
|
if test_env.get_client_version() >= (12, 1) \
|
|
and not self.is_on_oracle_cloud(connection):
|
|
sql = "select dbop_name from v$sql_monitor " \
|
|
"where sid = sys_context('userenv', 'sid')" \
|
|
"and status = 'EXECUTING'"
|
|
self.__verify_attributes(connection, "dbop", "oracledb_dbop", sql)
|
|
sql = "select sys_context('userenv', 'action') from dual"
|
|
self.__verify_attributes(connection, "action", "oracledb_Action", sql)
|
|
sql = "select sys_context('userenv', 'module') from dual"
|
|
self.__verify_attributes(connection, "module", "oracledb_Module", sql)
|
|
sql = "select sys_context('userenv', 'client_info') from dual"
|
|
self.__verify_attributes(connection, "clientinfo", "oracledb_cinfo",
|
|
sql)
|
|
sql = "select sys_context('userenv', 'client_identifier') from dual"
|
|
self.__verify_attributes(connection, "client_identifier",
|
|
"oracledb_cid", sql)
|
|
|
|
def test_1104_autocommit(self):
|
|
"1104 - test use of autocommit"
|
|
connection = test_env.get_connection()
|
|
cursor = connection.cursor()
|
|
other_connection = test_env.get_connection()
|
|
other_cursor = other_connection.cursor()
|
|
cursor.execute("truncate table TestTempTable")
|
|
cursor.execute("insert into TestTempTable (IntCol) values (1)")
|
|
other_cursor.execute("select IntCol from TestTempTable")
|
|
rows = other_cursor.fetchall()
|
|
self.assertEqual(rows, [])
|
|
connection.autocommit = True
|
|
cursor.execute("insert into TestTempTable (IntCol) values (2)")
|
|
other_cursor.execute("select IntCol from TestTempTable order by IntCol")
|
|
rows = other_cursor.fetchall()
|
|
self.assertEqual(rows, [(1,), (2,)])
|
|
|
|
def test_1105_bad_connect_string(self):
|
|
"1105 - connection to database with bad connect string"
|
|
self.assertRaises(oracledb.DatabaseError, oracledb.connect,
|
|
test_env.get_main_user())
|
|
self.assertRaises(oracledb.DatabaseError, oracledb.connect,
|
|
test_env.get_main_user() + "@" + \
|
|
test_env.get_connect_string())
|
|
self.assertRaises(oracledb.DatabaseError, oracledb.connect,
|
|
test_env.get_main_user() + "@" + \
|
|
test_env.get_connect_string() + "/" + \
|
|
test_env.get_main_password())
|
|
|
|
def test_1106_bad_password(self):
|
|
"1106 - connection to database with bad password"
|
|
self.assertRaises(oracledb.DatabaseError, oracledb.connect,
|
|
test_env.get_main_user(),
|
|
test_env.get_main_password() + "X",
|
|
test_env.get_connect_string())
|
|
|
|
def test_1107_change_password(self):
|
|
"1107 - test changing password"
|
|
connection = test_env.get_connection()
|
|
if self.is_on_oracle_cloud(connection):
|
|
self.skipTest("passwords on Oracle Cloud are strictly controlled")
|
|
sys_random = random.SystemRandom()
|
|
new_password = "".join(sys_random.choice(string.ascii_letters) \
|
|
for i in range(20))
|
|
connection.changepassword(test_env.get_main_password(), new_password)
|
|
cconnection = oracledb.connect(test_env.get_main_user(), new_password,
|
|
test_env.get_connect_string())
|
|
connection.changepassword(new_password, test_env.get_main_password())
|
|
|
|
def test_1108_change_password_negative(self):
|
|
"1108 - test changing password to an invalid value"
|
|
connection = test_env.get_connection()
|
|
if self.is_on_oracle_cloud(connection):
|
|
self.skipTest("passwords on Oracle Cloud are strictly controlled")
|
|
new_password = "1" * 150
|
|
self.assertRaises(oracledb.DatabaseError, connection.changepassword,
|
|
test_env.get_main_password(), new_password)
|
|
|
|
def test_1109_parse_password(self):
|
|
"1109 - test connecting with password containing / and @ symbols"
|
|
connection = test_env.get_connection()
|
|
if self.is_on_oracle_cloud(connection):
|
|
self.skipTest("passwords on Oracle Cloud are strictly controlled")
|
|
sys_random = random.SystemRandom()
|
|
chars = list(sys_random.choice(string.ascii_letters) for i in range(20))
|
|
chars[4] = "/"
|
|
chars[8] = "@"
|
|
new_password = "".join(chars)
|
|
connection.changepassword(test_env.get_main_password(), new_password)
|
|
try:
|
|
arg = "%s/%s@%s" % (test_env.get_main_user(), new_password,
|
|
test_env.get_connect_string())
|
|
oracledb.connect(arg)
|
|
finally:
|
|
connection.changepassword(new_password,
|
|
test_env.get_main_password())
|
|
|
|
def test_1110_encodings(self):
|
|
"1110 - connection with only encoding/nencoding specified should work"
|
|
connection = oracledb.connect(test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string())
|
|
encoding = connection.encoding
|
|
nencoding = connection.nencoding
|
|
alt_encoding = "ISO-8859-1"
|
|
connection = oracledb.connect(test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string(),
|
|
encoding=alt_encoding)
|
|
self.assertEqual(connection.encoding, alt_encoding)
|
|
self.assertEqual(connection.nencoding, nencoding)
|
|
connection = oracledb.connect(test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string(),
|
|
nencoding=alt_encoding)
|
|
self.assertEqual(connection.encoding, encoding)
|
|
self.assertEqual(connection.nencoding, alt_encoding)
|
|
|
|
def test_1111_different_encodings(self):
|
|
"1111 - different encodings can be specified for encoding/nencoding"
|
|
connection = oracledb.connect(test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string(),
|
|
encoding="UTF-8", nencoding="UTF-16")
|
|
value = "\u03b4\u4e2a"
|
|
cursor = connection.cursor()
|
|
nchar_var = cursor.var(oracledb.DB_TYPE_NVARCHAR, 100)
|
|
nchar_var.setvalue(0, value)
|
|
cursor.execute("select :value from dual", value=nchar_var)
|
|
result, = cursor.fetchone()
|
|
self.assertEqual(result, value)
|
|
|
|
def test_1112_exception_on_close(self):
|
|
"1112 - confirm an exception is raised after closing a connection"
|
|
connection = test_env.get_connection()
|
|
connection.close()
|
|
self.assertRaises(oracledb.InterfaceError, connection.rollback)
|
|
|
|
def test_1113_connect_with_handle(self):
|
|
"1113 - test creating a connection using a handle"
|
|
connection = test_env.get_connection()
|
|
cursor = connection.cursor()
|
|
cursor.execute("truncate table TestTempTable")
|
|
int_value = random.randint(1, 32768)
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (:val, null)""", val=int_value)
|
|
connection2 = oracledb.connect(handle = connection.handle)
|
|
cursor = connection2.cursor()
|
|
cursor.execute("select IntCol from TestTempTable")
|
|
fetched_int_value, = cursor.fetchone()
|
|
self.assertEqual(fetched_int_value, int_value)
|
|
cursor.close()
|
|
self.assertRaises(oracledb.DatabaseError, connection2.close)
|
|
connection.close()
|
|
|
|
def test_1114_make_dsn(self):
|
|
"1114 - test making a data source name from host, port and sid"
|
|
format_string = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)" + \
|
|
"(HOST=%s)(PORT=%d))(CONNECT_DATA=(SID=%s)))"
|
|
args = ("hostname", 1521, "TEST")
|
|
result = oracledb.makedsn(*args)
|
|
self.assertEqual(result, format_string % args)
|
|
|
|
def test_1115_single_arg(self):
|
|
"1115 - connection to database with user, password, DSN together"
|
|
arg = "%s/%s@%s" % (test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string())
|
|
connection = oracledb.connect(arg)
|
|
self.__verify_args(connection)
|
|
|
|
def test_1116_version(self):
|
|
"1116 - connection version is a string"
|
|
connection = test_env.get_connection()
|
|
self.assertTrue(isinstance(connection.version, str))
|
|
|
|
def test_1117_rollback_on_close(self):
|
|
"1117 - connection rolls back before close"
|
|
connection = test_env.get_connection()
|
|
cursor = connection.cursor()
|
|
cursor.execute("truncate table TestTempTable")
|
|
other_connection = test_env.get_connection()
|
|
other_cursor = other_connection.cursor()
|
|
other_cursor.execute("insert into TestTempTable (IntCol) values (1)")
|
|
other_cursor.close()
|
|
other_connection.close()
|
|
cursor.execute("select count(*) from TestTempTable")
|
|
count, = cursor.fetchone()
|
|
self.assertEqual(count, 0)
|
|
|
|
def test_1118_rollback_on_del(self):
|
|
"1118 - connection rolls back before destruction"
|
|
connection = test_env.get_connection()
|
|
cursor = connection.cursor()
|
|
cursor.execute("truncate table TestTempTable")
|
|
other_connection = test_env.get_connection()
|
|
other_cursor = other_connection.cursor()
|
|
other_cursor.execute("insert into TestTempTable (IntCol) values (1)")
|
|
del other_cursor
|
|
del other_connection
|
|
cursor.execute("select count(*) from TestTempTable")
|
|
count, = cursor.fetchone()
|
|
self.assertEqual(count, 0)
|
|
|
|
def test_1119_threading(self):
|
|
"1119 - connection to database with multiple threads"
|
|
threads = []
|
|
for i in range(20):
|
|
thread = threading.Thread(None, self.__connect_and_drop)
|
|
threads.append(thread)
|
|
thread.start()
|
|
for thread in threads:
|
|
thread.join()
|
|
|
|
def test_1120_string_format(self):
|
|
"1120 - test string format of connection"
|
|
connection = test_env.get_connection()
|
|
expected_value = "<cx_Oracle.Connection to %s@%s>" % \
|
|
(test_env.get_main_user(), test_env.get_connect_string())
|
|
self.assertEqual(str(connection), expected_value)
|
|
|
|
def test_1121_ctx_mgr_close(self):
|
|
"1121 - test context manager - close"
|
|
connection = test_env.get_connection()
|
|
with connection:
|
|
cursor = connection.cursor()
|
|
cursor.execute("truncate table TestTempTable")
|
|
cursor.execute("insert into TestTempTable (IntCol) values (1)")
|
|
connection.commit()
|
|
cursor.execute("insert into TestTempTable (IntCol) values (2)")
|
|
self.assertRaises(oracledb.InterfaceError, connection.ping)
|
|
connection = test_env.get_connection()
|
|
cursor = connection.cursor()
|
|
cursor.execute("select count(*) from TestTempTable")
|
|
count, = cursor.fetchone()
|
|
self.assertEqual(count, 1)
|
|
|
|
def test_1122_connection_attributes(self):
|
|
"1122 - test connection attribute values"
|
|
connection = oracledb.connect(test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string(),
|
|
encoding="ASCII")
|
|
self.assertEqual(connection.maxBytesPerCharacter, 1)
|
|
connection = oracledb.connect(test_env.get_main_user(),
|
|
test_env.get_main_password(),
|
|
test_env.get_connect_string(),
|
|
encoding="UTF-8")
|
|
self.assertEqual(connection.maxBytesPerCharacter, 4)
|
|
if test_env.get_client_version() >= (12, 1):
|
|
self.assertEqual(connection.ltxid, b'')
|
|
self.assertEqual(connection.current_schema, None)
|
|
connection.current_schema = "test_schema"
|
|
self.assertEqual(connection.current_schema, "test_schema")
|
|
self.assertEqual(connection.edition, None)
|
|
connection.external_name = "test_external"
|
|
self.assertEqual(connection.external_name, "test_external")
|
|
connection.internal_name = "test_internal"
|
|
self.assertEqual(connection.internal_name, "test_internal")
|
|
connection.stmtcachesize = 30
|
|
self.assertEqual(connection.stmtcachesize, 30)
|
|
self.assertRaises(TypeError, connection.stmtcachesize, 20.5)
|
|
self.assertRaises(TypeError, connection.stmtcachesize, "value")
|
|
|
|
def test_1123_closed_connection_attributes(self):
|
|
"1123 - test closed connection attribute values"
|
|
connection = test_env.get_connection()
|
|
connection.close()
|
|
attr_names = ["current_schema", "edition", "external_name",
|
|
"internal_name", "stmtcachesize"]
|
|
if test_env.get_client_version() >= (12, 1):
|
|
attr_names.append("ltxid")
|
|
for name in attr_names:
|
|
self.assertRaises(oracledb.InterfaceError, getattr, connection,
|
|
name)
|
|
|
|
def test_1124_ping(self):
|
|
"1124 - test connection ping"
|
|
connection = test_env.get_connection()
|
|
connection.ping()
|
|
|
|
def test_1125_transaction_begin(self):
|
|
"1125 - test begin, prepare, cancel transaction"
|
|
connection = test_env.get_connection()
|
|
cursor = connection.cursor()
|
|
cursor.execute("truncate table TestTempTable")
|
|
connection.begin(10, 'trxnId', 'branchId')
|
|
self.assertEqual(connection.prepare(), False)
|
|
connection.begin(10, 'trxnId', 'branchId')
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (1, 'tesName')""")
|
|
self.assertEqual(connection.prepare(), True)
|
|
connection.cancel()
|
|
connection.rollback()
|
|
cursor.execute("select count(*) from TestTempTable")
|
|
count, = cursor.fetchone()
|
|
self.assertEqual(count, 0)
|
|
|
|
def test_1126_multiple_transactions(self):
|
|
"1126 - test multiple transactions on the same connection"
|
|
connection = test_env.get_connection()
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("truncate table TestTempTable")
|
|
|
|
id_ = random.randint(0, 2 ** 128)
|
|
xid = (0x1234, "%032x" % id_, "%032x" % 9)
|
|
connection.begin(*xid)
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (1, 'tesName')""")
|
|
self.assertEqual(connection.prepare(), True)
|
|
connection.commit()
|
|
|
|
for begin_trans in (True, False):
|
|
val = 3
|
|
if begin_trans:
|
|
connection.begin()
|
|
val = 2
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (:int_val, 'tesName')""", int_val=val)
|
|
connection.commit()
|
|
|
|
expected_rows = [(1, "tesName"), (2, "tesName"), (3, "tesName")]
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("select IntCol, StringCol from TestTempTable")
|
|
self.assertEqual(cursor.fetchall(), expected_rows)
|
|
|
|
def test_1127_multiple_global_transactions(self):
|
|
"1127 - test multiple global transactions on the same connection"
|
|
connection = test_env.get_connection()
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("truncate table TestTempTable")
|
|
|
|
id_ = random.randint(0, 2 ** 128)
|
|
xid = (0x1234, "%032x" % id_, "%032x" % 9)
|
|
connection.begin(*xid)
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (1, 'tesName')""")
|
|
self.assertEqual(connection.prepare(), True)
|
|
connection.commit()
|
|
|
|
for begin_trans in (True, False):
|
|
val = 3
|
|
if begin_trans:
|
|
connection.begin()
|
|
val = 2
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (:int_val, 'tesName')""", int_val=val)
|
|
connection.commit()
|
|
|
|
id2_ = random.randint(0, 2 ** 128)
|
|
xid2 = (0x1234, "%032x" % id2_, "%032x" % 9)
|
|
connection.begin(*xid2)
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (4, 'tesName')""")
|
|
self.assertEqual(connection.prepare(), True)
|
|
connection.commit()
|
|
|
|
expected_rows = [(1, "tesName"), (2, "tesName"), (3, "tesName"),
|
|
(4, "tesName")]
|
|
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("select IntCol, StringCol from TestTempTable")
|
|
self.assertEqual(cursor.fetchall(), expected_rows)
|
|
|
|
def test_1128_exception_creating_global_txn_after_local_txn(self):
|
|
"1128 - test creating global txn after a local txn"
|
|
connection = test_env.get_connection()
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("truncate table TestTempTable")
|
|
|
|
val = 2
|
|
with connection.cursor() as cursor:
|
|
cursor.execute("""
|
|
insert into TestTempTable (IntCol, StringCol)
|
|
values (:int_val, 'tesName')""", int_val=val)
|
|
|
|
id_ = random.randint(0, 2 ** 128)
|
|
xid = (0x1234, "%032x" % id_, "%032x" % 9)
|
|
self.assertRaises(oracledb.DatabaseError, connection.begin, *xid)
|
|
|
|
if __name__ == "__main__":
|
|
test_env.run_test_cases()
|