Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c9a44d4

Browse files
committedDec 20, 2024
Support added for extended connection strings.
1 parent eb1daa4 commit c9a44d4

File tree

10 files changed

+557
-49
lines changed

10 files changed

+557
-49
lines changed
 

‎doc/src/release_notes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Thin Mode Changes
3535
expected value: "{expected_name}"`` is now raised when neither the common
3636
name (CN) nor any of the subject alternative names (SANs) found on the
3737
server certificate match the host name used to connect to the database.
38+
#) The text of error ``DPY-4022: invalid value for DRCP purity {purity}``
39+
changed to ``DPY-4022: invalid value for enumeration {name}: {value}``.
3840
#) Internal change: improve low-level encoding and decoding routines.
3941
#) Internal change: send buffer length for bind variables without unneeded
4042
adjustment.

‎doc/src/user_guide/connection_handling.rst

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,198 @@ internal extraction is done automatically when a value is passed to the ``dsn``
626626
parameter of :meth:`oracledb.connect()` or :meth:`oracledb.create_pool()` but
627627
no value is passed to the ``user`` password.
628628

629+
.. _defineconnparams:
630+
631+
Defining ConnectParams Parameters in a Connection String
632+
--------------------------------------------------------
633+
634+
You can specify certain common parameters of the :ref:`ConnectParams object
635+
<connparam>` directly in an :ref:`Easy Connect string <easyconnect>`. This can
636+
be done by using the question mark symbol (?) to indicate the start of the
637+
parameter-value pairs and the ampersand symbol (&) to delimit each
638+
parameter-value pair. For example:
639+
640+
.. code-block:: python
641+
642+
cp = oracledb.ConnectParams()
643+
cp.parse_connect_string("host.example.com:1522/orclpdb?transport_connect_timeout=15&retry_count=5&retry_delay=5")
644+
645+
The common ConnectParams parameters that can be set in a connection string are
646+
listed in the table below:
647+
648+
.. list-table-with-summary:: Common ConnectParams Parameters
649+
:header-rows: 1
650+
:class: wy-table-responsive
651+
:align: center
652+
:widths: 10 10 10
653+
:name: _common_parameters
654+
:summary: The first column displays the name of the connect string parameter name. The second column displays the Python parameter name. The third column displays the type of the parameter.
655+
656+
* - Connect String Parameter Name
657+
- Python Parameter Name
658+
- Type
659+
* - EXPIRE_TIME
660+
- :attr:`~ConnectParams.expire_time`
661+
- integer
662+
* - HTTPS_PROXY
663+
- :attr:`~ConnectParams.https_proxy`
664+
- string
665+
* - HTTPS_PROXY_PORT
666+
- :attr:`~ConnectParams.https_proxy_port`
667+
- integer
668+
* - POOL_BOUNDARY
669+
- :attr:`~ConnectParams.pool_boundary`
670+
- string
671+
* - POOL_CONNECTION_CLASS
672+
- :attr:`~ConnectParams.cclass`
673+
- string
674+
* - POOL_PURITY
675+
- :attr:`~ConnectParams.purity`
676+
- oracledb.Purity
677+
* - RETRY_COUNT
678+
- :attr:`~ConnectParams.retry_count`
679+
- integer
680+
* - RETRY_DELAY
681+
- :attr:`~ConnectParams.retry_delay`
682+
- integer
683+
* - SDU
684+
- :attr:`~ConnectParams.sdu`
685+
- integer
686+
* - SSL_SERVER_DN_MATCH
687+
- :attr:`~ConnectParams.ssl_server_dn_match`
688+
- boolean
689+
* - SSL_SERVER_CERT_DN
690+
- :attr:`~ConnectParams.ssl_server_cert_dn`
691+
- string
692+
* - TRANSPORT_CONNECT_TIMEOUT
693+
- :attr:`~ConnectParams.tcp_connect_timeout`
694+
- integer
695+
* - WALLET_LOCATION
696+
- :attr:`~ConnectParams.wallet_location`
697+
- string
698+
699+
Also, you can specify additional parameters of the :ref:`ConnectParams object
700+
<connparam>` directly in an :ref:`Easy Connect string <easyconnect>`. This can
701+
be done by using the question mark symbol (?) to indicate the start of the
702+
parameter-value pairs and the ampersand symbol (&) to delimit each
703+
parameter-value pair. Addiitionally, you must define each parameter name with
704+
the prefix "pyo.". For example:
705+
706+
.. code-block:: python
707+
708+
cp = oracledb.ConnectParams()
709+
cp.parse_connect_string("host.example.com:1522/orclpdb?pyo.stmtcachesize=30&pyo.mode=SYSDBA")
710+
711+
Note that these parameters can only be added in Easy Connect strings and not
712+
in :ref:`Connect Descriptors <conndescriptor>`.
713+
714+
The ConnectParams parameters that can be set in a connection string with the
715+
prefix "pyo."" are listed in the table below:
716+
717+
.. list-table-with-summary:: Additional ConnectParams Parameters
718+
:header-rows: 1
719+
:class: wy-table-responsive
720+
:align: center
721+
:widths: 10 10 10
722+
:name: _additional_connectparams_parameters
723+
:summary: The first column displays the name of the connect string parameter name. The second column displays the Python parameter name. The third column displays the type of the parameter.
724+
725+
* - Connect String Parameter Name
726+
- Python Parameter Name
727+
- Type
728+
* - PYO.CCLASS
729+
- :attr:`ConnectParams.cclass`
730+
- string
731+
* - PYO.CONNECTION_ID_PREFIX
732+
- :attr:`ConnectParams.connection_id_prefix`
733+
- string
734+
* - PYO.DISABLE_OOB
735+
- :attr:`ConnectParams.disable_oob`
736+
- boolean
737+
* - PYO.DRIVER_NAME
738+
- :attr:`~ConnectParams.driver_name`
739+
- string
740+
* - PYO.EDITION
741+
- :attr:`~ConnectParams.edition`
742+
- string
743+
* - PYO.EVENTS
744+
- :attr:`~ConnectParams.events`
745+
- boolean
746+
* - PYO.EXPIRE_TIME
747+
- :attr:`~ConnectParams.expire_time`
748+
- integer
749+
* - PYO.EXTERNALAUTH
750+
- :attr:`~ConnectParams.externalauth`
751+
- boolean
752+
* - PYO.HTTPS_PROXY
753+
- :attr:`~ConnectParams.https_proxy`
754+
- string
755+
* - PYO.HTTPS_PROXY_PORT
756+
- :attr:`~ConnectParams.https_proxy_port`
757+
- integer
758+
* - PYO.MACHINE
759+
- :attr:`~ConnectParams.machine`
760+
- string
761+
* - PYO.MODE
762+
- :attr:`~ConnectParams.mode`
763+
- oracledb.AuthMode
764+
* - PYO.OSUSER
765+
- :attr:`~ConnectParams.osuser`
766+
- string
767+
* - PYO.POOL_BOUNDARY
768+
- :attr:`~ConnectParams.pool_boundary`
769+
- string
770+
* - PYO.PROGRAM
771+
- :attr:`~ConnectParams.program`
772+
- string
773+
* - PYO.PURITY
774+
- :attr:`~ConnectParams.purity`
775+
- oracledb.Purity
776+
* - PYO.RETRY_COUNT
777+
- :attr:`~ConnectParams.retry_count`
778+
- integer
779+
* - PYO.RETRY_DELAY
780+
- :attr:`~ConnectParams.retry_delay`
781+
- integer
782+
* - PYO.SDU
783+
- :attr:`~ConnectParams.sdu`
784+
- integer
785+
* - PYO.SSL_SERVER_CERT_DN
786+
- :attr:`~ConnectParams.ssl_server_cert_dn`
787+
- string
788+
* - PYO.SSL_SERVER_DN_MATCH
789+
- :attr:`~ConnectParams.ssl_server_dn_match`
790+
- boolean
791+
* - PYO.STMTCACHESIZE
792+
- :attr:`~ConnectParams.stmtcachesize`
793+
- integer
794+
* - PYO.TCP_CONNECT_TIMEOUT
795+
- :attr:`~ConnectParams.tcp_connect_timeout`
796+
- integer
797+
* - PYO.TERMINAL
798+
- :attr:`~ConnectParams.terminal`
799+
- string
800+
* - PYO.USE_TCP_FAST_OPEN
801+
- :attr:`~ConnectParams.use_tcp_fast_open`
802+
- boolean
803+
* - PYO.WALLET_LOCATION
804+
- :attr:`~ConnectParams.wallet_location`
805+
- string
806+
807+
If a common or additional parameter is specified multiple times in a connect
808+
string, then the last value of that parameter is considered as the value. For
809+
example, if the ``sdu`` parameter is specified multiple times in the connect
810+
string like this "sdu=5&sdu=10&pyo.sdu=15&sdu=20", then the value 20 is
811+
considered as the value of the this parameter.
812+
813+
Note that the Connect String parameter names for the common and additional
814+
parameters are not case-sensitive. The boolean values may use one of the
815+
strings "on" or "off", "true" or "false", or "yes" or "no". The enumerated
816+
values use the enumerated name and are converted to uppercase before they are
817+
looked up in the enumeration. For example,
818+
:data:`oracledb.AuthMode.SYSDBA <oracledb.AUTH_MODE_SYSDBA>` would be
819+
specified as SYSDBA.
820+
629821
.. _connectionhook:
630822

631823
Connection Hook Functions
@@ -1594,6 +1786,175 @@ Thin mode is that values in any ``dsn`` parameter override values passed as
15941786
individual parameters, which themselves override values set in the ``params``
15951787
object. Similar precedence rules also apply to other values.
15961788

1789+
.. _definepoolparams:
1790+
1791+
Defining PoolParams Parameters in a Connection String
1792+
-----------------------------------------------------
1793+
1794+
You can specify certain common parameters of the :ref:`PoolParams object
1795+
<poolparam>` directly in an :ref:`Easy Connect string <easyconnect>`. This can
1796+
be done by using the question mark symbol (?) to indicate the start of the
1797+
parameter-value pairs and the ampersand symbol (&) to delimit each
1798+
parameter-value pair. See :ref:`_common_parameters` for the list of common
1799+
parameters.
1800+
1801+
Also, you can specify additional parameters of the :ref:`PoolParams object
1802+
<poolparam>` directly in an :ref:`Easy Connect string <easyconnect>`. This can
1803+
be done by using the question mark symbol (?) to indicate the start of the
1804+
parameter-value pairs and the ampersand symbol (&) to delimit each
1805+
parameter-value pair. Additionally, you must define each parameter name with
1806+
the prefix "pyo.". For example:
1807+
1808+
.. code-block:: python
1809+
1810+
pp = oracledb.PoolParams()
1811+
pp.parse_connect_string("host.example.com:1522/orclpdb?pyo.max=10&pyo.increment=2")
1812+
1813+
Note that these parameters can only be added in Easy Connect strings and not in
1814+
:ref:`Connect Descriptors <conndescriptor>`.
1815+
1816+
The PoolParams parameters that can be set in a connection string with the
1817+
prefix "pyo."" are listed in the table below:
1818+
1819+
.. list-table-with-summary::
1820+
:header-rows: 1
1821+
:class: wy-table-responsive
1822+
:align: center
1823+
:widths: 10 10 10
1824+
:summary: The first column displays the connect string parameter name. The second column displays the Python parameter name. The third column displays the type of the parameter.
1825+
1826+
* - Connect String Parameter Name
1827+
- Python Parameter Name
1828+
- Type
1829+
* - PYO.CCLASS
1830+
- :attr:`ConnectParams.cclass`
1831+
- string
1832+
* - PYO.CONNECTION_ID_PREFIX
1833+
- :attr:`ConnectParams.connection_id_prefix`
1834+
- string
1835+
* - PYO.DISABLE_OOB
1836+
- :attr:`ConnectParams.disable_oob`
1837+
- boolean
1838+
* - PYO.DRIVER_NAME
1839+
- :attr:`ConnectParams.driver_name`
1840+
- string
1841+
* - PYO.EDITION
1842+
- :attr:`ConnectParams.edition`
1843+
- string
1844+
* - PYO.EVENTS
1845+
- :attr:`ConnectParams.events`
1846+
- boolean
1847+
* - PYO.EXPIRE_TIME
1848+
- :attr:`ConnectParams.expire_time`
1849+
- integer
1850+
* - PYO.EXTERNALAUTH
1851+
- :attr:`ConnectParams.externalauth`
1852+
- boolean
1853+
* - PYO.GETMODE
1854+
- :attr:`PoolParams.getmode`
1855+
- oracledb.PoolGetMode
1856+
* - PYO.HOMOGENEOUS
1857+
- :attr:`PoolParams.homogeneous`
1858+
- boolean
1859+
* - PYO.HTTPS_PROXY
1860+
- :attr:`ConnectParams.https_proxy`
1861+
- string
1862+
* - PYO.HTTPS_PROXY_PORT
1863+
- :attr:`ConnectParams.https_proxy_port`
1864+
- integer
1865+
* - PYO.INCREMENT
1866+
- :attr:`PoolParams.increment`
1867+
- integer
1868+
* - PYO.MACHINE
1869+
- :attr:`ConnectParams.machine`
1870+
- string
1871+
* - PYO.MAX
1872+
- :attr:`PoolParams.max`
1873+
- integer
1874+
* - PYO.MAX_LIFETIME_SESSION
1875+
- :attr:`PoolParams.max_lifetime_session`
1876+
- integer
1877+
* - PYO.MAX_SESSIONS_PER_SHARD
1878+
- :attr:`PoolParams.max_sessions_per_shard`
1879+
- integer
1880+
* - PYO.MIN
1881+
- :attr:`PoolParams.min`
1882+
- integer
1883+
* - PYO.MODE
1884+
- :attr:`ConnectParams.mode`
1885+
- oracledb.AuthMode
1886+
* - PYO.OSUSER
1887+
- :attr:`ConnectParams.osuser`
1888+
- string
1889+
* - PYO_PING_INTERVAL
1890+
- :attr:`PoolParams.ping_interval`
1891+
- integer
1892+
* - PYO.PING_TIMEOUT
1893+
- :attr:`PoolParams.ping_timeout`
1894+
- integer
1895+
* - PYO.POOL_BOUNDARY
1896+
- :attr:`ConnectParams.pool_boundary`
1897+
- string
1898+
* - PYO.PROGRAM
1899+
- :attr:`ConnectParams.program`
1900+
- string
1901+
* - PYO.PURITY
1902+
- :attr:`ConnectParams.purity`
1903+
- oracledb.Purity
1904+
* - PYO.RETRY_COUNT
1905+
- :attr:`ConnectParams.retry_count`
1906+
- integer
1907+
* - PYO.RETRY_DELAY
1908+
- :attr:`ConnectParams.retry_delay`
1909+
- integer
1910+
* - PYO.SDU
1911+
- :attr:`ConnectParams.sdu`
1912+
- integer
1913+
* - PYO.SODA_METADATA_CACHE
1914+
- :attr:`PoolParams.soda_metadata_cache`
1915+
- boolean
1916+
* - PYO.SSL_SERVER_CERT_DN
1917+
- :attr:`ConnectParams.ssl_server_cert_dn`
1918+
- string
1919+
* - PYO.SSL_SERVER_DN_MATCH
1920+
- :attr:`ConnectParams.ssl_server_dn_match`
1921+
- boolean
1922+
* - PYO.STMTCACHESIZE
1923+
- :attr:`ConnectParams.stmtcachesize`
1924+
- integer
1925+
* - PYO.TCP_CONNECT_TIMEOUT
1926+
- :attr:`ConnectParams.tcp_connect_timeout`
1927+
- integer
1928+
* - PYO.TERMINAL
1929+
- :attr:`ConnectParams.terminal`
1930+
- string
1931+
* - PYO.TIMEOUT
1932+
- :attr:`PoolParams.timeout`
1933+
- integer
1934+
* - PYO.USE_TCP_FAST_OPEN
1935+
- :attr:`ConnectParams.use_tcp_fast_open`
1936+
- boolean
1937+
* - PYO.WAIT_TIMEOUT
1938+
- :attr:`PoolParams.wait_timeout`
1939+
- integer
1940+
* - PYO.WALLET_LOCATION
1941+
- :attr:`ConnectParams.wallet_location`
1942+
- string
1943+
1944+
If a common or additional parameter is specified multiple times in a connect
1945+
string, then the last value of that parameter is considered as the value. For
1946+
example, if the ``sdu`` parameter is specified multiple times in the connect
1947+
string like this "sdu=5&sdu=10&pyo.sdu=15&sdu=20", then the value 20 is
1948+
considered as the value of the this parameter.
1949+
1950+
Note that the Connect String parameter names for the common and additional
1951+
parameters are not case-sensitive. The boolean values may use one of the
1952+
strings "on" or "off", "true" or "false", or "yes" or "no". The enumerated
1953+
values use the enumerated name and are converted to uppercase before they are
1954+
looked up in the enumeration. For example,
1955+
:data:`oracledb.AuthMode.SYSDBA <oracledb.AUTH_MODE_SYSDBA>` would be
1956+
specified as SYSDBA.
1957+
15971958
.. _drcp:
15981959

15991960
Database Resident Connection Pooling (DRCP)

‎src/oracledb/base_impl.pyx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ cdef type PY_TYPE_TIMEDELTA = datetime.timedelta
8080
cdef type PY_TYPE_VAR
8181
cdef type PY_TYPE_FETCHINFO
8282

83+
# enumerations used by the driver in connect parameters
84+
cdef object ENUM_AUTH_MODE
85+
cdef object ENUM_POOL_GET_MODE
86+
cdef object ENUM_PURITY
87+
8388
cdef const char* DRIVER_NAME = "python-oracledb"
8489
cdef const char* DRIVER_VERSION
8590
cdef const char* DRIVER_INSTALLATION_URL = \

‎src/oracledb/errors.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ def _raise_not_supported(feature: str) -> None:
329329
ERR_CANNOT_PARSE_CONNECT_STRING = 4018
330330
ERR_INVALID_REDIRECT_DATA = 4019
331331
ERR_INVALID_PROTOCOL = 4021
332-
ERR_INVALID_POOL_PURITY = 4022
332+
ERR_INVALID_ENUM_VALUE = 4022
333333
ERR_CALL_TIMEOUT_EXCEEDED = 4024
334334
ERR_INVALID_REF_CURSOR = 4025
335335
ERR_MISSING_FILE = 4026
@@ -581,6 +581,7 @@ def _raise_not_supported(feature: str) -> None:
581581
"given index {index} must be in the range of {min_index} to "
582582
"{max_index}"
583583
),
584+
ERR_INVALID_ENUM_VALUE: "invalid value for enumeration {name}: {value}",
584585
ERR_INVALID_LOB_AMOUNT: "LOB amount must be greater than zero",
585586
ERR_INVALID_LOB_OFFSET: "LOB offset must be greater than zero",
586587
ERR_INVALID_MAKEDSN_ARG: '"{name}" argument contains invalid values',
@@ -589,7 +590,6 @@ def _raise_not_supported(feature: str) -> None:
589590
ERR_INVALID_OCI_ATTR_TYPE: "invalid OCI attribute type {attr_type}",
590591
ERR_INVALID_POOL_CLASS: "invalid connection pool class",
591592
ERR_INVALID_POOL_PARAMS: "invalid pool params",
592-
ERR_INVALID_POOL_PURITY: "invalid DRCP purity {purity}",
593593
ERR_INVALID_PROTOCOL: 'invalid protocol "{protocol}"',
594594
ERR_INVALID_REDIRECT_DATA: "invalid redirect data {data}",
595595
ERR_INVALID_REF_CURSOR: "invalid REF CURSOR: never opened in PL/SQL",

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ cdef class ConnectParamsImpl:
8484
self._set_new_password(args.get("newpassword"))
8585
self._set_wallet_password(args.get("wallet_password"))
8686
_set_bool_param(args, "events", &self.events)
87-
_set_uint_param(args, "mode", &self.mode)
87+
_set_enum_param(args, "mode", ENUM_AUTH_MODE, &self.mode)
8888
_set_str_param(args, "edition", self)
8989
_set_str_param(args, "tag", self)
9090
_set_bool_param(args, "matchanytag", &self.matchanytag)
@@ -284,6 +284,8 @@ cdef class ConnectParamsImpl:
284284
errors._raise_err(errors.ERR_CANNOT_PARSE_CONNECT_STRING,
285285
data=connect_string)
286286
self.description_list = parser.description_list
287+
if parser.parameters is not None:
288+
self.set(parser.parameters)
287289

288290
cdef int _set_access_token(self, object val, int error_num) except -1:
289291
"""
@@ -850,7 +852,7 @@ cdef class Description(ConnectParamsNode):
850852
if server_type is not None:
851853
self.set_server_type(server_type)
852854
_set_str_param(args, "cclass", self)
853-
_set_purity_param(args, "purity", &self.purity)
855+
_set_enum_param(args, "purity", ENUM_PURITY, &self.purity)
854856
_set_str_param(args, "pool_boundary", self)
855857
_set_str_param(args, "connection_id_prefix", self)
856858
_set_bool_param(args, "use_tcp_fast_open", &self.use_tcp_fast_open)

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

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ ALTERNATIVE_PARAM_NAMES = {
4040
"my_wallet_directory": "wallet_location"
4141
}
4242

43+
# a set of parameter names used as containers for storing additional parameters
4344
CONTAINER_PARAM_NAMES = set([
4445
"address",
4546
"address_list",
@@ -49,6 +50,68 @@ CONTAINER_PARAM_NAMES = set([
4950
"security",
5051
])
5152

53+
# a set of parameter names supported in EasyConnect strings that are common
54+
# to all drivers
55+
COMMON_PARAM_NAMES = set([
56+
"expire_time",
57+
"https_proxy",
58+
"https_proxy_port",
59+
"pool_boundary",
60+
"pool_connection_class",
61+
"pool_purity",
62+
"retry_count",
63+
"retry_delay",
64+
"sdu",
65+
"ssl_server_cert_dn",
66+
"ssl_server_dn_match",
67+
"transport_connect_timeout",
68+
"wallet_location",
69+
])
70+
71+
# extended parameter prefix
72+
EXTENDED_PARAM_PREFIX = "pyo."
73+
74+
# a set of parameter names that can be specified in EasyConnect strings using
75+
# the extended parameter prefix; these are specific to python-oracledb
76+
EXTENDED_PARAM_NAMES = set([
77+
78+
# ConnectParams
79+
"connection_id_prefix",
80+
"disable_oob",
81+
"driver_name",
82+
"edition",
83+
"events",
84+
"externalauth",
85+
"machine",
86+
"mode",
87+
"osuser",
88+
"program",
89+
"stmtcachesize",
90+
"terminal",
91+
"use_tcp_fast_open",
92+
93+
# PoolParams
94+
"getmode",
95+
"homogeneous",
96+
"increment",
97+
"max",
98+
"max_lifetime_session",
99+
"max_sessions_per_shard",
100+
"min",
101+
"ping_interval",
102+
"ping_timeout",
103+
"soda_metadata_cache",
104+
"timeout",
105+
"wait_timeout",
106+
107+
])
108+
109+
# add all of the common parameters to the extended parameters using the
110+
# python-oracledb specific name
111+
for name in COMMON_PARAM_NAMES:
112+
EXTENDED_PARAM_NAMES.add(ALTERNATIVE_PARAM_NAMES.get(name, name))
113+
114+
52115
cdef class BaseParser:
53116

54117
cdef Py_UCS4 get_current_char(self):
@@ -76,7 +139,7 @@ cdef class BaseParser:
76139
cdef Py_UCS4 ch
77140
while self.temp_pos < self.num_chars:
78141
ch = self.get_current_char()
79-
if not cpython.Py_UNICODE_ISALPHA(ch) and ch != '_':
142+
if not cpython.Py_UNICODE_ISALPHA(ch) and ch != '_' and ch != '.':
80143
break
81144
self.temp_pos += 1
82145

@@ -117,6 +180,7 @@ cdef class ConnectStringParser(BaseParser):
117180
ConnectParamsImpl params_impl
118181
Address template_address
119182
Description description
183+
dict parameters
120184

121185
cdef bint _is_host_or_service_name_char(self, Py_UCS4 ch):
122186
"""
@@ -351,7 +415,7 @@ cdef class ConnectStringParser(BaseParser):
351415
break
352416
self.temp_pos += 1
353417

354-
cdef int _parse_easy_connect_parameter(self, dict parameters) except -1:
418+
cdef int _parse_easy_connect_parameter(self) except -1:
355419
"""
356420
Parses a single parameter from the easy connect string. This is
357421
expected to be a keyword followed by a value seprated by an equals
@@ -360,6 +424,7 @@ cdef class ConnectStringParser(BaseParser):
360424
cdef:
361425
ssize_t start_pos, end_pos = 0
362426
Py_UCS4 ch = 0
427+
bint keep
363428
str name
364429

365430
# get parameter name
@@ -369,7 +434,12 @@ cdef class ConnectStringParser(BaseParser):
369434
if self.temp_pos == start_pos or self.temp_pos >= self.num_chars:
370435
return 0
371436
name = self.data_as_str[start_pos:self.temp_pos].lower()
372-
name = ALTERNATIVE_PARAM_NAMES.get(name, name)
437+
if name.startswith(EXTENDED_PARAM_PREFIX):
438+
name = name[len(EXTENDED_PARAM_PREFIX):]
439+
keep = name in EXTENDED_PARAM_NAMES
440+
else:
441+
keep = name in COMMON_PARAM_NAMES
442+
name = ALTERNATIVE_PARAM_NAMES.get(name, name)
373443

374444
# look for the equals sign
375445
self.skip_spaces()
@@ -401,8 +471,10 @@ cdef class ConnectStringParser(BaseParser):
401471
break
402472
self.temp_pos += 1
403473
end_pos = self.temp_pos
404-
if end_pos > start_pos:
405-
parameters[name] = self.data_as_str[start_pos:end_pos]
474+
if end_pos > start_pos and keep:
475+
if self.parameters is None:
476+
self.parameters = {}
477+
self.parameters[name] = self.data_as_str[start_pos:end_pos]
406478
self.skip_spaces()
407479
self.pos = self.temp_pos
408480

@@ -414,7 +486,6 @@ cdef class ConnectStringParser(BaseParser):
414486
"""
415487
cdef:
416488
Py_UCS4 ch, expected_sep
417-
dict parameters = {}
418489
Address address
419490
expected_sep = '?'
420491
self.temp_pos = self.pos
@@ -424,11 +495,7 @@ cdef class ConnectStringParser(BaseParser):
424495
break
425496
expected_sep = '&'
426497
self.temp_pos += 1
427-
self._parse_easy_connect_parameter(parameters)
428-
if parameters:
429-
for address in self.description_list.get_addresses():
430-
address.set_from_args(parameters)
431-
self.description.set_from_args(parameters)
498+
self._parse_easy_connect_parameter()
432499

433500
cdef int _parse_easy_connect_port(self, Address address) except -1:
434501
"""

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ cdef class PoolParamsImpl(ConnectParamsImpl):
8181
_set_uint_param(args, "max", &self.max)
8282
_set_uint_param(args, "increment", &self.increment)
8383
_set_obj_param(args, "connectiontype", self)
84-
_set_uint_param(args, "getmode", &self.getmode)
84+
_set_enum_param(args, "getmode", ENUM_POOL_GET_MODE, &self.getmode)
8585
_set_bool_param(args, "homogeneous", &self.homogeneous)
8686
_set_uint_param(args, "timeout", &self.timeout)
8787
_set_uint_param(args, "wait_timeout", &self.wait_timeout)

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

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,28 @@ cdef int _set_duration_param(dict args, str name, double *out_val) except -1:
9090
out_val[0] = float(in_val)
9191

9292

93+
cdef int _set_enum_param(dict args, str name, object enum_obj,
94+
uint32_t* out_val) except -1:
95+
"""
96+
Sets an unsigned integer parameter to the value provided in the dictionary.
97+
If digits are not provided, the value is looked up in the provided
98+
enumeration.
99+
"""
100+
in_val = args.get(name)
101+
if in_val is not None:
102+
if not isinstance(in_val, str) or in_val.isdigit():
103+
out_val[0] = int(in_val)
104+
if out_val[0] in enum_obj:
105+
return 0
106+
else:
107+
enum_val = getattr(enum_obj, in_val.upper(), None)
108+
if enum_val is not None:
109+
out_val[0] = enum_val.value
110+
return 0
111+
errors._raise_err(errors.ERR_INVALID_ENUM_VALUE,
112+
name=enum_obj.__name__, value=in_val)
113+
114+
93115
cdef int _set_int_param(dict args, str name, int* out_val) except -1:
94116
"""
95117
Sets an integer parameter to the value provided in the dictionary. This
@@ -124,39 +146,6 @@ cdef int _set_obj_param(dict args, str name, object target) except -1:
124146
setattr(target, name, in_val)
125147

126148

127-
cdef int _set_purity_param(dict args, str name, uint32_t* out_val) except -1:
128-
"""
129-
Sets a purity parameter to the value provided in the dictionary. This
130-
must be one of "new" or "self" currently (or the equivalent constants, if
131-
specified directly). If it is not one of these values an error is raised.
132-
"""
133-
cdef bint ok = True
134-
in_val = args.get(name)
135-
if in_val is not None:
136-
if isinstance(in_val, str):
137-
in_val = in_val.lower()
138-
if in_val == "new":
139-
out_val[0] = PURITY_NEW
140-
elif in_val == "self":
141-
out_val[0] = PURITY_SELF
142-
else:
143-
ok = False
144-
elif isinstance(in_val, int):
145-
if in_val == PURITY_NEW:
146-
out_val[0] = PURITY_NEW
147-
elif in_val == PURITY_SELF:
148-
out_val[0] = PURITY_SELF
149-
elif in_val == PURITY_DEFAULT:
150-
out_val[0] = PURITY_DEFAULT
151-
else:
152-
ok = False
153-
else:
154-
ok = False
155-
if not ok:
156-
errors._raise_err(errors.ERR_INVALID_POOL_PURITY,
157-
purity=in_val)
158-
159-
160149
cdef int _set_ssl_version_param(dict args, str name, object target) except -1:
161150
"""
162151
Sets a SSL version parameter to the value specified. This must be one of
@@ -205,6 +194,9 @@ def init_base_impl(package):
205194
exceptions, \
206195
utils, \
207196
DRIVER_VERSION, \
197+
ENUM_AUTH_MODE, \
198+
ENUM_POOL_GET_MODE, \
199+
ENUM_PURITY, \
208200
PY_TYPE_ASYNC_CURSOR, \
209201
PY_TYPE_ASYNC_LOB, \
210202
PY_TYPE_CONNECT_PARAMS, \
@@ -226,6 +218,9 @@ def init_base_impl(package):
226218
exceptions = package.exceptions
227219
utils = package.utils
228220
DRIVER_VERSION = package.__version__
221+
ENUM_AUTH_MODE = package.AuthMode
222+
ENUM_PURITY = package.Purity
223+
ENUM_POOL_GET_MODE = package.PoolGetMode
229224
PY_TYPE_ASYNC_CURSOR = package.AsyncCursor
230225
PY_TYPE_ASYNC_LOB = package.AsyncLOB
231226
PY_TYPE_CONNECT_PARAMS = package.ConnectParams

‎tests/test_4500_connect_params.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,53 @@ def hook(passed_protocol, passed_protocol_arg, passed_params):
10631063
self.assertEqual(params.port, port)
10641064
self.assertEqual(params.service_name, service_name)
10651065

1066+
def test_4564(self):
1067+
"4564 - test extended connect strings for ConnectParams"
1068+
test_scenarios = [
1069+
("cclass", "test_cclass", "test_cclass"),
1070+
("connection_id_prefix", "cid_prefix", "cid_prefix"),
1071+
("disable_oob", "true", True),
1072+
("disable_oob", "off", False),
1073+
("driver_name", "test_driver_name", "test_driver_name"),
1074+
("edition", "test_edition", "test_edition"),
1075+
("events", "on", True),
1076+
("events", "false", False),
1077+
("expire_time", "10", 10),
1078+
("externalauth", "yes", True),
1079+
("externalauth", "no", False),
1080+
("https_proxy", "test_proxy", "test_proxy"),
1081+
("https_proxy_port", "80", 80),
1082+
("machine", "test_machine", "test_machine"),
1083+
("machine", "test_machine", "test_machine"),
1084+
("mode", "SYSDBA", oracledb.AUTH_MODE_SYSDBA),
1085+
("osuser", "test_osuser", "test_osuser"),
1086+
("pool_boundary", "statement", "statement"),
1087+
("program", "test_program", "test_program"),
1088+
("purity", "NEW", oracledb.PURITY_NEW),
1089+
("retry_count", "5", 5),
1090+
("retry_delay", "3", 3),
1091+
("sdu", "16384", 16384),
1092+
("ssl_server_cert_dn", "test_dn", "test_dn"),
1093+
("ssl_server_dn_match", "on", True),
1094+
("ssl_server_dn_match", "false", False),
1095+
("stmtcachesize", "25", 25),
1096+
("tcp_connect_timeout", "15", 15),
1097+
("terminal", "test_terminal", "test_terminal"),
1098+
("use_tcp_fast_open", "true", True),
1099+
("use_tcp_fast_open", "off", False),
1100+
("wallet_location", "test_location", "test_location"),
1101+
]
1102+
host = "host_4564"
1103+
service_name = "service_4564"
1104+
for name, str_value, actual_value in test_scenarios:
1105+
conn_string = f"{host}/{service_name}?pyo.{name}={str_value}"
1106+
with self.subTest(name=name, value=str_value):
1107+
params = oracledb.ConnectParams()
1108+
params.parse_connect_string(conn_string)
1109+
self.assertEqual(params.host, host)
1110+
self.assertEqual(params.service_name, service_name)
1111+
self.assertEqual(getattr(params, name), actual_value)
1112+
10661113

10671114
if __name__ == "__main__":
10681115
test_env.run_test_cases()

‎tests/test_4700_pool_params.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,35 @@ def test_4701(self):
136136
self.assertEqual(repr(params), expected_value)
137137
self.assertIs(params.getmode, oracledb.PoolGetMode.WAIT)
138138

139+
def test_4702(self):
140+
"4702 - test extended connect strings for ConnectParams"
141+
test_scenarios = [
142+
("getmode", "NOWAIT", oracledb.POOL_GETMODE_NOWAIT),
143+
("homogeneous", "true", True),
144+
("homogeneous", "false", False),
145+
("increment", "2", 2),
146+
("max", "50", 50),
147+
("max_lifetime_session", "6000", 6000),
148+
("max_sessions_per_shard", "5", 5),
149+
("min", "3", 3),
150+
("ping_interval", "-1", -1),
151+
("ping_timeout", "2500", 2500),
152+
("homogeneous", "on", True),
153+
("homogeneous", "off", False),
154+
("timeout", "3000", 3000),
155+
("wait_timeout", "300", 300),
156+
]
157+
host = "host_4702"
158+
service_name = "service_4702"
159+
for name, str_value, actual_value in test_scenarios:
160+
conn_string = f"{host}/{service_name}?pyo.{name}={str_value}"
161+
with self.subTest(name=name, value=str_value):
162+
params = oracledb.PoolParams()
163+
params.parse_connect_string(conn_string)
164+
self.assertEqual(params.host, host)
165+
self.assertEqual(params.service_name, service_name)
166+
self.assertEqual(getattr(params, name), actual_value)
167+
139168

140169
if __name__ == "__main__":
141170
test_env.run_test_cases()

0 commit comments

Comments
 (0)
Please sign in to comment.