Skip to content

Commit 2587740

Browse files
Added new method enable_thin_mode() as requested (#408).
1 parent 50d9c36 commit 2587740

File tree

7 files changed

+114
-10
lines changed

7 files changed

+114
-10
lines changed

doc/src/api_manual/module.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,26 @@ Oracledb Methods
18911891
(number of seconds since the epoch; see the documentation of the standard
18921892
Python time module for details).
18931893

1894+
1895+
.. function:: enable_thin_mode()
1896+
1897+
Makes python-oracledb be in Thin mode. After this method is called, Thick
1898+
mode cannot be enabled. If python-oracledb is already in Thick mode, then
1899+
calling ``enable_thin_mode()`` will fail. If connections have already been
1900+
opened, or a connection pool created, in Thin mode, then calling
1901+
``enable_thin_mode()`` is a no-op.
1902+
1903+
Since python-oracledb defaults to Thin mode, almost all applications do not
1904+
need to call this method. However, because it bypasses python-oracledb's
1905+
internal mode-determination heuristic, it may be useful for applications
1906+
that are using :ref:`standalone connections <standaloneconnection>` in
1907+
multiple threads to concurrently create connections when the application
1908+
starts.
1909+
1910+
See :ref:`enablingthin` for more information.
1911+
1912+
.. versionadded:: 2.5.0
1913+
18941914
.. function:: init_oracle_client(lib_dir=None, config_dir=None, \
18951915
error_url=None, driver_name=None)
18961916

doc/src/release_notes.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ Thin Mode Changes
3434
#) Added :meth:`oracledb.register_protocol()` to allow users to register a
3535
function that will be called when a particular protocol is detected in a
3636
connection string.
37+
#) Added :meth:`oracledb.enable_thin_mode()` as a means of enabling
38+
python-oracledb Thin mode without waiting for an initial connection to be
39+
succesfully established. Since python-oracledb defaults to Thin mode, this
40+
method is mostly useful for applications with multiple threads concurrently
41+
creating connections to different databases when the application starts
42+
(`issue 408 <https://github.com/oracle/python-oracledb/issues/408>`__).
3743
#) Fixed bug when calling :meth:`Connection.gettype()` for a type that exists
3844
but on which the user has insufficient privileges to view
3945
(`issue 397 <https://github.com/oracle/python-oracledb/issues/397>`__).

doc/src/user_guide/initialization.rst

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,59 @@ On Linux and macOS, you might use::
307307
When your python-oracledb application is run, logging output is shown on the
308308
terminal.
309309

310+
.. _enablingthin:
311+
312+
Explicitly Enabling python-oracledb Thin Mode
313+
=============================================
314+
315+
Python-oracledb defaults to Thin mode after determining that Thick mode is not
316+
going to be used. In one special case, you may wish to explicitly enable Thin
317+
mode to prevent Thick mode from being enabled later.
318+
319+
To allow application portability, the driver's internal logic allows
320+
applications to initally attempt
321+
:ref:`standalone connection <standaloneconnection>` creation in Thin mode, but
322+
then lets them :ref:`enable Thick mode <enablingthick>` if that connection is
323+
unsuccessful. An example is when trying to connect to an Oracle Database that
324+
turns out to be an old version that requires Thick mode. This heuristic means
325+
Thin mode is not enforced until the initial connection is successful. Since
326+
all connections must be the same mode, any second and subsequent concurrent
327+
Thin mode connection attempts will wait for the initial standalone connection
328+
to succeed, meaning the driver mode is no longer potentially changeable to
329+
Thick mode.
330+
331+
This heuristic delay does not impact:
332+
333+
- Single-threaded applications using standalone connections.
334+
- Single or multi-threaded applications using
335+
:ref:`connection pools <connpooling>` (even with ``min`` of 0).
336+
- Applications that have already called :func:`oracledb.init_oracle_client()`.
337+
338+
In the case that you want to open multiple standalone Thin mode connections in
339+
multiple threads, you may wish to force Thin mode by calling
340+
:meth:`oracledb.enable_thin_mode()` as part of your application initialization.
341+
This avoids the mode heuristic delay. For example:
342+
343+
.. code-block:: python
344+
345+
import oracledb
346+
347+
oracledb.enable_thin_mode()
348+
349+
Once this method is called, then python-oracledb Thick mode cannot be enabled.
350+
If you call :func:`oracledb.init_oracle_client()`, you will get the following
351+
error::
352+
353+
DPY-2019: python-oracledb thick mode cannot be used because thin mode has
354+
already been enabled or a thin mode connection has already been created
355+
356+
If you have already enabled Thick mode by calling
357+
:func:`oracledb.init_oracle_client()` and then call
358+
:meth:`oracledb.enable_thin_mode()`, you will get the following error::
359+
360+
DPY-2053: python-oracledb thin mode cannot be used because thick mode has
361+
already been enabled
362+
310363
.. _optconfigfiles:
311364

312365
Optional Oracle Configuration Files

src/oracledb/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,10 @@
284284

285285
from .driver_mode import is_thin_mode as is_thin_mode
286286

287-
from .utils import register_protocol as register_protocol
287+
from .utils import (
288+
enable_thin_mode as enable_thin_mode,
289+
register_protocol as register_protocol,
290+
)
288291

289292
from .thick_impl import (
290293
clientversion as clientversion,

src/oracledb/driver_mode.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,6 @@ def get_manager(requested_thin_mode=None):
9696
"""
9797
Returns the manager, but only after ensuring that no other threads are
9898
attempting to initialize the mode.
99-
100-
NOTE: the current implementation of the driver only requires
101-
requested_thin_mode to be set when initializing the thick mode; for this
102-
reason the error raised is specified about a thin mode connection already
103-
being created. If this assumption changes, a new error message will be
104-
required.
10599
"""
106100
with manager.condition:
107101
if manager.thin_mode is None:
@@ -116,7 +110,10 @@ def get_manager(requested_thin_mode=None):
116110
requested_thin_mode is not None
117111
and requested_thin_mode != manager.thin_mode
118112
):
119-
errors._raise_err(errors.ERR_THIN_CONNECTION_ALREADY_CREATED)
113+
if requested_thin_mode:
114+
errors._raise_err(errors.ERR_THICK_MODE_ENABLED)
115+
else:
116+
errors._raise_err(errors.ERR_THIN_CONNECTION_ALREADY_CREATED)
120117
return manager
121118

122119

src/oracledb/errors.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ def _raise_not_supported(feature: str) -> None:
272272
ERR_INVALID_TPC_BEGIN_FLAGS = 2050
273273
ERR_INVALID_TPC_END_FLAGS = 2051
274274
ERR_MISMATCHED_TOKEN = 2052
275+
ERR_THICK_MODE_ENABLED = 2053
275276

276277
# error numbers that result in NotSupportedError
277278
ERR_TIME_NOT_SUPPORTED = 3000
@@ -709,9 +710,14 @@ def _raise_not_supported(feature: str) -> None:
709710
"by python-oracledb in thin mode"
710711
),
711712
ERR_TDS_TYPE_NOT_SUPPORTED: "Oracle TDS data type {num} is not supported",
713+
ERR_THICK_MODE_ENABLED: (
714+
"python-oracledb thin mode cannot be used because thick mode has "
715+
"already been enabled"
716+
),
712717
ERR_THIN_CONNECTION_ALREADY_CREATED: (
713-
"python-oracledb thick mode cannot be used because a thin mode "
714-
"connection has already been created"
718+
"python-oracledb thick mode cannot be used because thin mode has "
719+
"already been enabled or a thin mode connection has already been "
720+
"created"
715721
),
716722
ERR_TIME_NOT_SUPPORTED: (
717723
"Oracle Database does not support time only variables"

src/oracledb/utils.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,28 @@
3131
from typing import Callable, Union
3232

3333
from . import base_impl
34+
from . import driver_mode
3435
from . import errors
3536

3637

38+
def enable_thin_mode():
39+
"""
40+
Makes python-oracledb be in Thin mode. After this method is called, Thick
41+
mode cannot be enabled. If python-oracledb is already in Thick mode, then
42+
calling ``enable_thin_mode()`` will fail. If connections have already been
43+
opened, or a connection pool created, in Thin mode, then calling
44+
``enable_thin_mode()`` is a no-op.
45+
46+
Since python-oracledb defaults to Thin mode, almost all applications do not
47+
need to call this method. However, because it bypasses python-oracledb's
48+
internal mode-determination heuristic, it may be useful for applications
49+
that are using standalone connections in multiple threads to concurrently
50+
create connections when the application starts.
51+
"""
52+
with driver_mode.get_manager(requested_thin_mode=True):
53+
pass
54+
55+
3756
def params_initer(f):
3857
"""
3958
Decorator function which is used on the ConnectParams and PoolParams

0 commit comments

Comments
 (0)