Skip to content

Commit 5d0a183

Browse files
Fixed bug when a connect descriptor is used that doesn't define any
addresses (#339).
1 parent 4b9bb26 commit 5d0a183

File tree

5 files changed

+63
-14
lines changed

5 files changed

+63
-14
lines changed

doc/src/release_notes.rst

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Thin Mode Changes
2222
(`issue 336 <https://github.com/oracle/python-oracledb/issues/336>`__).
2323
#) Fixed bug when fetching LOBs after an exception has been raised
2424
(`issue 338 <https://github.com/oracle/python-oracledb/issues/338>`__).
25+
#) Fixed bug when a connect descriptor is used that doesn't define any
26+
addresses
27+
(`issue 339 <https://github.com/oracle/python-oracledb/issues/339>`__).
2528
#) Fixed bug in statement cache when the maximum number of cursors is unknown
2629
due to the database not being open.
2730
#) Fixed bug in handling redirect data with small SDU sizes.

src/oracledb/base_impl.pxd

+3-1
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ cdef class Description(ConnectParamsNode):
381381
cdef class DescriptionList(ConnectParamsNode):
382382

383383
cdef str build_connect_string(self)
384+
cdef list get_addresses(self)
384385

385386

386387
cdef class ConnectParamsImpl:
@@ -430,7 +431,8 @@ cdef class ConnectParamsImpl:
430431
cdef int _parse_connect_string(self, str connect_string) except -1
431432
cdef int _parse_easy_connect_string(self, str connect_string,
432433
object match) except -1
433-
cdef int _process_connect_descriptor(self, dict args) except -1
434+
cdef int _process_connect_descriptor(self, str connecte_string,
435+
dict args) except -1
434436
cdef int _set_access_token(self, object val, int error_num) except -1
435437
cdef int _set_access_token_param(self, object val) except -1
436438
cdef int _set_new_password(self, str password) except -1

src/oracledb/errors.py

+4
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ def _raise_err(
243243
ERR_CURSOR_HAS_BEEN_CLOSED = 2046
244244
ERR_INVALID_LOB_AMOUNT = 2047
245245
ERR_DML_RETURNING_DUP_BINDS = 2048
246+
ERR_MISSING_ADDRESS = 2049
246247

247248
# error numbers that result in NotSupportedError
248249
ERR_TIME_NOT_SUPPORTED = 3000
@@ -576,6 +577,9 @@ def _raise_err(
576577
"internal error: unknown protocol message type {message_type} "
577578
"at position {position}"
578579
),
580+
ERR_MISSING_ADDRESS: (
581+
"no addresses are defined in connect descriptor: {connect_string}"
582+
),
579583
ERR_MISSING_BIND_VALUE: (
580584
'a bind variable replacement value for placeholder ":{name}" was '
581585
"not provided"

src/oracledb/impl/base/connect_params.pyx

+25-13
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ cdef class ConnectParamsImpl:
320320
# to be a full connect descriptor
321321
if connect_string.startswith("("):
322322
_parse_connect_descriptor(connect_string, args)
323-
return self._process_connect_descriptor(args)
323+
return self._process_connect_descriptor(connect_string, args)
324324

325325
# otherwise, see if the connect string is an EasyConnect string
326326
m = re.search(EASY_CONNECT_PATTERN, connect_string)
@@ -342,7 +342,7 @@ cdef class ConnectParamsImpl:
342342
self._parse_easy_connect_string(connect_string, m)
343343
else:
344344
_parse_connect_descriptor(connect_string, args)
345-
self._process_connect_descriptor(args)
345+
self._process_connect_descriptor(connect_string, args)
346346

347347
cdef int _parse_easy_connect_string(self, str connect_string,
348348
object match) except -1:
@@ -382,26 +382,28 @@ cdef class ConnectParamsImpl:
382382
self.description_list = DescriptionList()
383383
self.description_list.children.append(description)
384384

385-
cdef int _process_connect_descriptor(self, dict args) except -1:
385+
cdef int _process_connect_descriptor(self, str connect_string,
386+
dict args) except -1:
386387
"""
387388
Internal method used for processing the parsed connect descriptor into
388389
the set of DescriptionList, Description, AddressList and Address
389390
container objects.
390391
"""
391392
cdef:
393+
DescriptionList description_list
392394
AddressList address_list
393395
Description description
394396
Address address
395-
self.description_list = DescriptionList()
397+
description_list = DescriptionList()
396398
list_args = args.get("description_list")
397399
if list_args is not None:
398-
self.description_list.set_from_args(list_args)
400+
description_list.set_from_args(list_args)
399401
else:
400402
list_args = args
401403
for desc_args in list_args.get("description", [list_args]):
402404
description = self._default_description.copy()
403405
description.set_from_description_args(desc_args)
404-
self.description_list.children.append(description)
406+
description_list.children.append(description)
405407
sub_args = desc_args.get("connect_data")
406408
if sub_args is not None:
407409
description.set_from_connect_data_args(sub_args)
@@ -416,6 +418,10 @@ cdef class ConnectParamsImpl:
416418
address = self._default_address.copy()
417419
address.set_from_args(addr_args)
418420
address_list.children.append(address)
421+
if not description_list.get_addresses():
422+
errors._raise_err(errors.ERR_MISSING_ADDRESS,
423+
connect_string=connect_string)
424+
self.description_list = description_list
419425

420426
cdef int _set_access_token(self, object val, int error_num) except -1:
421427
"""
@@ -513,13 +519,7 @@ cdef class ConnectParamsImpl:
513519
"""
514520
Return a list of the stored addresses.
515521
"""
516-
cdef:
517-
AddressList addr_list
518-
Description desc
519-
Address addr
520-
return [addr for desc in self.description_list.children \
521-
for addr_list in desc.children \
522-
for addr in addr_list.children]
522+
return self.description_list.get_addresses()
523523

524524
def get_connect_string(self):
525525
"""
@@ -980,6 +980,18 @@ cdef class DescriptionList(ConnectParamsNode):
980980
return parts[0]
981981
return f'(DESCIPTION_LIST={"".join(parts)})'
982982

983+
cdef list get_addresses(self):
984+
"""
985+
Return a list of the stored addresses.
986+
"""
987+
cdef:
988+
AddressList addr_list
989+
Description desc
990+
Address addr
991+
return [addr for desc in self.children \
992+
for addr_list in desc.children \
993+
for addr in addr_list.children]
994+
983995
def set_from_args(self, dict args):
984996
"""
985997
Set paramter values from an argument dictionary or a (DESCRIPTION_LIST)

tests/test_4500_connect_params.py

+28
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,34 @@ def test_4545(self):
729729
params.set(use_tcp_fast_open=1)
730730
self.assertTrue(params.use_tcp_fast_open)
731731

732+
def test_4546(self):
733+
"4546 - test connect descriptor without addresses defined"
734+
params = oracledb.ConnectParams()
735+
host = "host_4546"
736+
port = 4546
737+
service_name = "service_name_4546"
738+
ok_container_names = ("DESCRIPTION", "ADDRESS")
739+
options = [
740+
("DESRIPTION", "ADDRESS"),
741+
ok_container_names,
742+
("DESCRIPTION", "ADRESS"),
743+
]
744+
for option in options:
745+
desc_name, addr_name = option
746+
connect_string = (
747+
f"({desc_name}=({addr_name}=(PROTOCOL=TCP)(HOST={host})"
748+
f"(PORT={port}))(CONNECT_DATA=(SERVICE_NAME={service_name})))"
749+
)
750+
params = oracledb.ConnectParams()
751+
if option == ok_container_names:
752+
params.parse_connect_string(connect_string)
753+
self.assertEqual(params.host, host)
754+
self.assertEqual(params.port, port)
755+
self.assertEqual(params.service_name, service_name)
756+
else:
757+
with self.assertRaisesFullCode("DPY-2049"):
758+
params.parse_connect_string(connect_string)
759+
732760

733761
if __name__ == "__main__":
734762
test_env.run_test_cases()

0 commit comments

Comments
 (0)