@@ -50,8 +50,34 @@ CONTAINER_PARAM_NAMES = set([
5050 " security" ,
5151])
5252
53+ # DESCRIPTION parameter names that are supported by the driver; all other
54+ # key/value pairs are passed unchanged to the database
55+ DESCRIPTION_PARAM_NAMES = set ([
56+ " address" ,
57+ " address_list" ,
58+ " connect_data" ,
59+ " expire_time" ,
60+ " failover" ,
61+ " load_balance" ,
62+ " source_route" ,
63+ " retry_count" ,
64+ " retry_delay" ,
65+ " sdu" ,
66+ " tcp_connect_timeout" ,
67+ " use_sni" ,
68+ " security" ,
69+ ])
70+
71+ # extra DESCRIPTION parameter names that are passed through when detected in an
72+ # easy connect string
73+ EXTRA_DESCRIPTION_PARAM_NAMES = set ([
74+ " enable" ,
75+ " recv_buf_size" ,
76+ " send_buf_size"
77+ ])
78+
5379# CONNECT_DATA parameter names that are supported by the driver; all other
54- # simple key/value pairs are passed unchanged to the database
80+ # key/value pairs are passed unchanged to the database
5581CONNECT_DATA_PARAM_NAMES = set ([
5682 " cclass" ,
5783 " connection_id_prefix" ,
@@ -64,18 +90,30 @@ CONNECT_DATA_PARAM_NAMES = set([
6490 " use_tcp_fast_open" ,
6591])
6692
93+ # SECURITY parameter names that are supported by the driver; all other
94+ # key/value pairs are passed unchanged to the database
95+ SECURITY_PARAM_NAMES = set ([
96+ " ssl_server_cert_dn" ,
97+ " ssl_server_dn_match" ,
98+ " ssl_version" ,
99+ " wallet_location" ,
100+ ])
101+
67102# a set of parameter names supported by the driver in EasyConnect strings that
68103# are common to all drivers
69104COMMON_PARAM_NAMES = set ([
70105 " expire_time" ,
106+ " failover" ,
71107 " https_proxy" ,
72108 " https_proxy_port" ,
109+ " load_balance" ,
73110 " pool_boundary" ,
74111 " pool_connection_class" ,
75112 " pool_purity" ,
76113 " retry_count" ,
77114 " retry_delay" ,
78115 " sdu" ,
116+ " source_route" ,
79117 " ssl_server_cert_dn" ,
80118 " ssl_server_dn_match" ,
81119 " transport_connect_timeout" ,
@@ -154,7 +192,9 @@ cdef class BaseParser:
154192 cdef Py_UCS4 ch
155193 while self .temp_pos < self .num_chars:
156194 ch = self .get_current_char()
157- if not cpython.Py_UNICODE_ISALPHA(ch) and ch != ' _' and ch != ' .' :
195+ if not cpython.Py_UNICODE_ISALPHA(ch) \
196+ and not cpython.Py_UNICODE_ISDIGIT(ch) \
197+ and ch != ' _' and ch != ' .' :
158198 break
159199 self .temp_pos += 1
160200
@@ -444,9 +484,9 @@ cdef class ConnectStringParser(BaseParser):
444484 """
445485 cdef:
446486 ssize_t start_pos, end_pos = 0
487+ str name, value
447488 Py_UCS4 ch = 0
448489 bint keep
449- str name
450490
451491 # get parameter name
452492 self .skip_spaces()
@@ -459,7 +499,8 @@ cdef class ConnectStringParser(BaseParser):
459499 name = name[len (EXTENDED_PARAM_PREFIX):]
460500 keep = name in EXTENDED_PARAM_NAMES
461501 else :
462- keep = name in COMMON_PARAM_NAMES
502+ keep = name in COMMON_PARAM_NAMES \
503+ or name in EXTRA_DESCRIPTION_PARAM_NAMES
463504 name = ALTERNATIVE_PARAM_NAMES.get(name, name)
464505
465506 # look for the equals sign
@@ -495,7 +536,11 @@ cdef class ConnectStringParser(BaseParser):
495536 if end_pos > start_pos and keep:
496537 if self .parameters is None :
497538 self .parameters = {}
498- self .parameters[name] = self .data_as_str[start_pos:end_pos]
539+ value = self .data_as_str[start_pos:end_pos]
540+ if name in EXTRA_DESCRIPTION_PARAM_NAMES:
541+ self .parameters.setdefault(" extra_args" , {})[name] = value
542+ else :
543+ self .parameters[name] = value
499544 self .skip_spaces()
500545 self .pos = self .temp_pos
501546
@@ -636,19 +681,23 @@ cdef class ConnectStringParser(BaseParser):
636681 self .data_as_str[self .pos + 1 :instance_name_end_pos]
637682 self .pos = self .temp_pos
638683
639- cdef dict _set_connect_data(self , dict args):
684+ cdef dict _process_args_with_extras(self , dict args, set allowed_names,
685+ str extras_name):
640686 """
641- Sets the connect data value.
687+ Processes arguments which contain a set of known attributes and any
688+ number of unknown attributes. The known attributes are left untouched
689+ whereas the unknown ones are put in a separate dictionary with the
690+ given name.
642691 """
643692 cdef:
644693 dict extras, result = {}
645694 object value
646695 str key
647696 for key, value in args.items():
648- if key in CONNECT_DATA_PARAM_NAMES :
697+ if key in allowed_names :
649698 result[key] = value
650699 else :
651- extras = result.setdefault(" extra_connect_data_args " , {})
700+ extras = result.setdefault(extras_name , {})
652701 extras[key] = value
653702 return result
654703
@@ -663,6 +712,21 @@ cdef class ConnectStringParser(BaseParser):
663712 being added and addresses already exist, those addresses are first
664713 added to the address list before the new value is added.
665714 """
715+ # process unrecognized parameters, if applicable
716+ if name == " description" :
717+ value = self ._process_args_with_extras(
718+ value, DESCRIPTION_PARAM_NAMES, " extra_args"
719+ )
720+ elif name == " connect_data" :
721+ value = self ._process_args_with_extras(
722+ value, CONNECT_DATA_PARAM_NAMES, " extra_connect_data_args"
723+ )
724+ elif name == " security" :
725+ value = self ._process_args_with_extras(
726+ value, SECURITY_PARAM_NAMES, " extra_security_args"
727+ )
728+
729+ # add value to arguments, creating a list if encountered multiple times
666730 orig_value = args.get(name)
667731 if orig_value is None :
668732 if name == " address" and " address_list" in args:
@@ -673,8 +737,6 @@ cdef class ConnectStringParser(BaseParser):
673737 if not isinstance (addresses, list ):
674738 addresses = [addresses]
675739 value = [dict (address = a) for a in addresses] + [value]
676- elif name == " connect_data" :
677- value = self ._set_connect_data(value)
678740 args[name] = value
679741 elif isinstance (orig_value, list ):
680742 args[name].append(value)
0 commit comments