Skip to content

Commit 847004a

Browse files
Fixed bug preventing correct parsing of connect descriptors with both
ADDRESS and ADDRESS_LIST components at the same level.
1 parent cda4cb0 commit 847004a

File tree

4 files changed

+57
-2
lines changed

4 files changed

+57
-2
lines changed

‎doc/src/release_notes.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Thin Mode Changes
2929
REF CURSOR to a PL/SQL block that closes it.
3030
#) Fixed bug preventing binding OUT data of type
3131
:data:`~oracledb.DB_TYPE_UROWID` that exceed 3950 bytes in length.
32+
#) Fixed bug preventing correct parsing of connect descriptors with both
33+
ADDRESS and ADDRESS_LIST components at the same level.
3234

3335
Thick Mode Changes
3436
++++++++++++++++++

‎src/oracledb/base_impl.pxd‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ cdef class ConnectParamsImpl:
188188
bytearray _token_obfuscator
189189
bytearray _private_key
190190
bytearray _private_key_obfuscator
191+
bint _has_components
191192

192193
cdef int _check_credentials(self) except -1
193194
cdef int _copy(self, ConnectParamsImpl other_params) except -1

‎src/oracledb/impl/base/connect_params.pyx‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ cdef uint32_t DEFAULT_PORT = 1521
6767
cdef double DEFAULT_TCP_CONNECT_TIMEOUT = 60
6868

6969

70+
cdef int _add_container(dict args, str name, object value) except -1:
71+
"""
72+
Adds a container to the arguments.
73+
"""
74+
if name == "address" and "address_list" in args:
75+
value = dict(address=[value])
76+
name = "address_list"
77+
elif name == "address_list" and "address" in args:
78+
args[name] = [dict(address=[v]) for v in args["address"]]
79+
del args["address"]
80+
args.setdefault(name, []).append(value)
81+
82+
7083
cdef dict _parse_connect_descriptor(str data, dict args):
7184
"""
7285
Internal method which parses a connect descriptor containing name-value
@@ -104,7 +117,7 @@ cdef dict _parse_connect_descriptor(str data, dict args):
104117
data = data[end_pos + 1:].strip()
105118
name = ALTERNATIVE_PARAM_NAMES.get(name, name)
106119
if name in CONTAINER_PARAM_NAMES:
107-
args.setdefault(name, []).append(value)
120+
_add_container(args, name, value)
108121
else:
109122
args[name] = value
110123
return args
@@ -156,6 +169,8 @@ cdef class ConnectParamsImpl:
156169
self._default_address.set_from_args(args)
157170
_set_bool_param(args, "externalauth", &self.externalauth)
158171
self._set_access_token_param(args.get("access_token"))
172+
if args:
173+
self._has_components = True
159174

160175
cdef int _check_credentials(self) except -1:
161176
"""
@@ -329,6 +344,7 @@ cdef class ConnectParamsImpl:
329344
# to be a full connect descriptor
330345
if connect_string.startswith("("):
331346
_parse_connect_descriptor(connect_string, args)
347+
self._has_components = True
332348
return self._process_connect_descriptor(args)
333349

334350
# otherwise, see if the connect string is an EasyConnect string
@@ -373,6 +389,9 @@ cdef class ConnectParamsImpl:
373389
_parse_connect_descriptor(connect_string, args)
374390
self._process_connect_descriptor(args)
375391

392+
# mark that object has components
393+
self._has_components = True
394+
376395
cdef int _process_connect_descriptor(self, dict args) except -1:
377396
"""
378397
Internal method used for processing the parsed connect descriptor into
@@ -519,7 +538,7 @@ cdef class ConnectParamsImpl:
519538
will be a connect string built up from the components supplied when the
520539
object was built.
521540
"""
522-
if self._default_address.host is not None:
541+
if self._has_components:
523542
return self.description_list.build_connect_string()
524543

525544
def get_full_user(self):

‎tests/test_4500_connect_params.py‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,5 +520,38 @@ def test_4533_easy_connect_with_pool_parameters(self):
520520
self.assertEqual(params.cclass, cclass)
521521
self.assertEqual(params.purity, purity_int)
522522

523+
def test_4534_connect_descriptor_small_container_first(self):
524+
"4534 - test connect descriptor with different containers (small 1st)"
525+
connect_string = """
526+
(DESCRIPTION=
527+
(ADDRESS=(PROTOCOL=tcp)(HOST=host1)(PORT=1521))
528+
(ADDRESS_LIST=
529+
(ADDRESS=(PROTOCOL=tcp)(HOST=host2a)(PORT=1522))
530+
(ADDRESS=(PROTOCOL=tcp)(HOST=host2b)(PORT=1523)))
531+
(ADDRESS=(PROTOCOL=tcp)(HOST=host3)(PORT=1524))
532+
(CONNECT_DATA=(SERVICE_NAME=my_service_34))
533+
)"""
534+
params = oracledb.ConnectParams()
535+
params.parse_connect_string(connect_string)
536+
self.assertEqual(params.host, ["host1", "host2a", "host2b", "host3"])
537+
538+
def test_4535_connect_descriptor_small_container_second(self):
539+
"4535 - test connect descriptor with different containers (small 2nd)"
540+
connect_string = """
541+
(DESCRIPTION=
542+
(ADDRESS_LIST=
543+
(ADDRESS=(PROTOCOL=tcp)(HOST=host1a)(PORT=1532))
544+
(ADDRESS=(PROTOCOL=tcp)(HOST=host1b)(PORT=1533)))
545+
(ADDRESS=(PROTOCOL=tcp)(HOST=host2)(PORT=1534))
546+
(ADDRESS_LIST=
547+
(ADDRESS=(PROTOCOL=tcp)(HOST=host3a)(PORT=1535))
548+
(ADDRESS=(PROTOCOL=tcp)(HOST=host3b)(PORT=1536)))
549+
(CONNECT_DATA=(SERVICE_NAME=my_service_34))
550+
)"""
551+
params = oracledb.ConnectParams()
552+
params.parse_connect_string(connect_string)
553+
self.assertEqual(params.host,
554+
["host1a", "host1b", "host2", "host3a", "host3b"])
555+
523556
if __name__ == "__main__":
524557
test_env.run_test_cases()

0 commit comments

Comments
 (0)