The complete connect string is now sent to the server instead of just

the actual components being used. This is important for some
configurations.
This commit is contained in:
Anthony Tuininga 2022-11-07 10:34:53 -07:00
parent 62d7800f7a
commit 25d5468439
7 changed files with 20 additions and 18 deletions

View File

@ -31,6 +31,8 @@ Thin Mode Changes
:data:`~oracledb.DB_TYPE_UROWID` that exceed 3950 bytes in length. :data:`~oracledb.DB_TYPE_UROWID` that exceed 3950 bytes in length.
#) Fixed bug preventing correct parsing of connect descriptors with both #) Fixed bug preventing correct parsing of connect descriptors with both
ADDRESS and ADDRESS_LIST components at the same level. 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 Thick Mode Changes
++++++++++++++++++ ++++++++++++++++++

View File

@ -136,7 +136,7 @@ cdef class Description:
public str wallet_location public str wallet_location
cdef str _build_duration_str(self, double value) 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: cdef class DescriptionList:

View File

@ -707,7 +707,7 @@ cdef class Description:
return f"{value_minutes}min" return f"{value_minutes}min"
return f"{value_int}" 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. Build a connect string from the components.
""" """
@ -728,10 +728,14 @@ cdef class Description:
parts.append(f"(POOL_CONNECTION_CLASS={self.cclass})") parts.append(f"(POOL_CONNECTION_CLASS={self.cclass})")
if self.purity != 0: if self.purity != 0:
parts.append(f"(POOL_PURITY={self.purity})") parts.append(f"(POOL_PURITY={self.purity})")
if cid is not None:
parts.append(f"(CID={cid})")
connect_data = f'(CONNECT_DATA={"".join(parts)})' connect_data = f'(CONNECT_DATA={"".join(parts)})'
# build security segment, if applicable # 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: if self.ssl_server_cert_dn is not None:
parts.append(f"(SSL_SERVER_CERT_DN={self.ssl_server_cert_dn})") parts.append(f"(SSL_SERVER_CERT_DN={self.ssl_server_cert_dn})")
if self.wallet_location is not None: if self.wallet_location is not None:

View File

@ -91,6 +91,7 @@ cdef class ThinConnImpl(BaseConnImpl):
cdef int _connect_with_address(self, Address address, cdef int _connect_with_address(self, Address address,
Description description, Description description,
ConnectParamsImpl params, ConnectParamsImpl params,
str connect_string,
bint raise_exception) except -1: bint raise_exception) except -1:
""" """
Internal method used for connecting with the given description and Internal method used for connecting with the given description and
@ -98,7 +99,7 @@ cdef class ThinConnImpl(BaseConnImpl):
""" """
try: try:
self._protocol._connect_phase_one(self, params, description, self._protocol._connect_phase_one(self, params, description,
address) address, connect_string)
except exceptions.DatabaseError: except exceptions.DatabaseError:
if raise_exception: if raise_exception:
raise raise
@ -130,10 +131,12 @@ cdef class ThinConnImpl(BaseConnImpl):
uint32_t num_attempts = description.retry_count + 1 uint32_t num_attempts = description.retry_count + 1
uint32_t num_lists = len(address_lists) uint32_t num_lists = len(address_lists)
AddressList address_list AddressList address_list
str connect_string
Address address Address address
# Retry connecting to the socket if an attempt fails and retry_count # Retry connecting to the socket if an attempt fails and retry_count
# is specified in the connect string. If an attempt succeeds, return # is specified in the connect string. If an attempt succeeds, return
# the socket and the valid address object. # the socket and the valid address object.
connect_string = _get_connect_data(description)
for i in range(num_attempts): for i in range(num_attempts):
# Iterate through each address_list in the description. If the # Iterate through each address_list in the description. If the
# description level load_balance is on, keep track of the least # 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 j == num_lists - 1 \
and k == num_addresses - 1 and k == num_addresses - 1
self._connect_with_address(address, description, params, self._connect_with_address(address, description, params,
raise_exc) connect_string, raise_exc)
if self._protocol._in_connect: if self._protocol._in_connect:
continue continue
address_list.lru_index = (idx1 + 1) % num_addresses address_list.lru_index = (idx1 + 1) % num_addresses

View File

@ -120,17 +120,18 @@ cdef class Protocol:
ThinConnImpl conn_impl, ThinConnImpl conn_impl,
ConnectParamsImpl params, ConnectParamsImpl params,
Description description, Description description,
Address address) except -1: Address address,
str connect_string) except -1:
""" """
Method for performing the required steps for establishing a connection Method for performing the required steps for establishing a connection
within the scope of a retry. If the listener refuses the connection, a within the scope of a retry. If the listener refuses the connection, a
retry will be performed, if retry_count is set. retry will be performed, if retry_count is set.
""" """
cdef: cdef:
str connect_string, host, redirect_data
ConnectMessage connect_message = None ConnectMessage connect_message = None
object ssl_context, connect_info object ssl_context, connect_info
ConnectParamsImpl temp_params ConnectParamsImpl temp_params
str host, redirect_data
Address temp_address Address temp_address
uint8_t packet_type uint8_t packet_type
int port, pos int port, pos
@ -143,7 +144,6 @@ cdef class Protocol:
host = address.host host = address.host
port = address.port port = address.port
self._connect_tcp(params, description, address, host, 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 # send connect message and process response; this may request the
# message to be resent multiple times; if a redirect packet is # message to be resent multiple times; if a redirect packet is

View File

@ -88,22 +88,15 @@ cdef object _encode_rowid(Rowid *rowid):
return buf[:TNS_MAX_ROWID_LENGTH].decode() 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. Return the connect data required by the listener in order to connect.
""" """
constants = _connect_constants 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})" + \ cid = f"(PROGRAM={constants.sanitized_program_name})" + \
f"(HOST={constants.sanitized_machine_name})" + \ f"(HOST={constants.sanitized_machine_name})" + \
f"(USER={constants.sanitized_user_name})" f"(USER={constants.sanitized_user_name})"
return f"(DESCRIPTION=(ADDRESS=(PROTOCOL={address.protocol.upper()})" + \ return description.build_connect_string(cid)
f"(HOST={address.host})(PORT={address.port}))" + \
f"(CONNECT_DATA={identity}{server_type}(CID={cid})))"
def _print_packet(operation, socket_fileno, data): def _print_packet(operation, socket_fileno, data):

View File

@ -481,7 +481,7 @@ class TestCase(test_env.BaseTestCase):
f"(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)" + \ f"(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)" + \
f"(HOST={host})(PORT=1521)))(CONNECT_DATA=" + \ f"(HOST={host})(PORT=1521)))(CONNECT_DATA=" + \
f"(SERVICE_NAME={service_name}))" + \ 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) self.assertEqual(params.get_connect_string(), connect_string)
def test_4532_multiple_alias_entry_tnsnames(self): def test_4532_multiple_alias_entry_tnsnames(self):