diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst index 717c0a9..c08e608 100644 --- a/doc/src/release_notes.rst +++ b/doc/src/release_notes.rst @@ -31,6 +31,8 @@ Thin Mode Changes :data:`~oracledb.DB_TYPE_UROWID` that exceed 3950 bytes in length. #) Fixed bug preventing correct parsing of connect descriptors with both ADDRESS and ADDRESS_LIST components at the same level. +#) The complete connect string is now sent to the server instead of just the + actual components being used. This is important for some configurations. Thick Mode Changes ++++++++++++++++++ diff --git a/src/oracledb/base_impl.pxd b/src/oracledb/base_impl.pxd index 70219b0..c37c1a0 100644 --- a/src/oracledb/base_impl.pxd +++ b/src/oracledb/base_impl.pxd @@ -136,7 +136,7 @@ cdef class Description: public str wallet_location cdef str _build_duration_str(self, double value) - cdef str build_connect_string(self) + cdef str build_connect_string(self, str cid=*) cdef class DescriptionList: diff --git a/src/oracledb/impl/base/connect_params.pyx b/src/oracledb/impl/base/connect_params.pyx index 3a017f9..b0f26f1 100644 --- a/src/oracledb/impl/base/connect_params.pyx +++ b/src/oracledb/impl/base/connect_params.pyx @@ -707,7 +707,7 @@ cdef class Description: return f"{value_minutes}min" return f"{value_int}" - cdef str build_connect_string(self): + cdef str build_connect_string(self, str cid=None): """ Build a connect string from the components. """ @@ -728,10 +728,14 @@ cdef class Description: parts.append(f"(POOL_CONNECTION_CLASS={self.cclass})") if self.purity != 0: parts.append(f"(POOL_PURITY={self.purity})") + if cid is not None: + parts.append(f"(CID={cid})") connect_data = f'(CONNECT_DATA={"".join(parts)})' # build security segment, if applicable - parts = [f"(SSL_SERVER_DN_MATCH={self.ssl_server_dn_match})"] + parts = [] + if self.ssl_server_dn_match: + parts.append("(SSL_SERVER_DN_MATCH=ON)") if self.ssl_server_cert_dn is not None: parts.append(f"(SSL_SERVER_CERT_DN={self.ssl_server_cert_dn})") if self.wallet_location is not None: diff --git a/src/oracledb/impl/thin/connection.pyx b/src/oracledb/impl/thin/connection.pyx index f836bc6..4f08cb4 100644 --- a/src/oracledb/impl/thin/connection.pyx +++ b/src/oracledb/impl/thin/connection.pyx @@ -91,6 +91,7 @@ cdef class ThinConnImpl(BaseConnImpl): cdef int _connect_with_address(self, Address address, Description description, ConnectParamsImpl params, + str connect_string, bint raise_exception) except -1: """ Internal method used for connecting with the given description and @@ -98,7 +99,7 @@ cdef class ThinConnImpl(BaseConnImpl): """ try: self._protocol._connect_phase_one(self, params, description, - address) + address, connect_string) except exceptions.DatabaseError: if raise_exception: raise @@ -130,10 +131,12 @@ cdef class ThinConnImpl(BaseConnImpl): uint32_t num_attempts = description.retry_count + 1 uint32_t num_lists = len(address_lists) AddressList address_list + str connect_string Address address # Retry connecting to the socket if an attempt fails and retry_count # is specified in the connect string. If an attempt succeeds, return # the socket and the valid address object. + connect_string = _get_connect_data(description) for i in range(num_attempts): # Iterate through each address_list in the description. If the # description level load_balance is on, keep track of the least @@ -161,7 +164,7 @@ cdef class ThinConnImpl(BaseConnImpl): and j == num_lists - 1 \ and k == num_addresses - 1 self._connect_with_address(address, description, params, - raise_exc) + connect_string, raise_exc) if self._protocol._in_connect: continue address_list.lru_index = (idx1 + 1) % num_addresses diff --git a/src/oracledb/impl/thin/protocol.pyx b/src/oracledb/impl/thin/protocol.pyx index a3389b3..ed59791 100644 --- a/src/oracledb/impl/thin/protocol.pyx +++ b/src/oracledb/impl/thin/protocol.pyx @@ -120,17 +120,18 @@ cdef class Protocol: ThinConnImpl conn_impl, ConnectParamsImpl params, Description description, - Address address) except -1: + Address address, + str connect_string) except -1: """ Method for performing the required steps for establishing a connection within the scope of a retry. If the listener refuses the connection, a retry will be performed, if retry_count is set. """ cdef: - str connect_string, host, redirect_data ConnectMessage connect_message = None object ssl_context, connect_info ConnectParamsImpl temp_params + str host, redirect_data Address temp_address uint8_t packet_type int port, pos @@ -143,7 +144,6 @@ cdef class Protocol: host = address.host port = address.port self._connect_tcp(params, description, address, host, port) - connect_string = _get_connect_data(address, description) # send connect message and process response; this may request the # message to be resent multiple times; if a redirect packet is diff --git a/src/oracledb/impl/thin/utils.pyx b/src/oracledb/impl/thin/utils.pyx index 3730de8..ecbafd5 100644 --- a/src/oracledb/impl/thin/utils.pyx +++ b/src/oracledb/impl/thin/utils.pyx @@ -88,22 +88,15 @@ cdef object _encode_rowid(Rowid *rowid): return buf[:TNS_MAX_ROWID_LENGTH].decode() -def _get_connect_data(address, description): +cdef str _get_connect_data(Description description): """ Return the connect data required by the listener in order to connect. """ constants = _connect_constants - server_type = f"(SERVER={description.server_type})" \ - if description.server_type is not None else "" - identity = f"(SERVICE_NAME={description.service_name})" \ - if description.service_name is not None or \ - description.sid is None else f"(SID={description.sid})" cid = f"(PROGRAM={constants.sanitized_program_name})" + \ f"(HOST={constants.sanitized_machine_name})" + \ f"(USER={constants.sanitized_user_name})" - return f"(DESCRIPTION=(ADDRESS=(PROTOCOL={address.protocol.upper()})" + \ - f"(HOST={address.host})(PORT={address.port}))" + \ - f"(CONNECT_DATA={identity}{server_type}(CID={cid})))" + return description.build_connect_string(cid) def _print_packet(operation, socket_fileno, data): diff --git a/tests/test_4500_connect_params.py b/tests/test_4500_connect_params.py index 2e65479..685a31f 100644 --- a/tests/test_4500_connect_params.py +++ b/tests/test_4500_connect_params.py @@ -481,7 +481,7 @@ class TestCase(test_env.BaseTestCase): f"(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)" + \ f"(HOST={host})(PORT=1521)))(CONNECT_DATA=" + \ f"(SERVICE_NAME={service_name}))" + \ - f"(SECURITY=(SSL_SERVER_DN_MATCH=True)))" + f"(SECURITY=(SSL_SERVER_DN_MATCH=ON)))" self.assertEqual(params.get_connect_string(), connect_string) def test_4532_multiple_alias_entry_tnsnames(self):