Compare commits
12 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
f2f2ed9fd5 | |
![]() |
065d8ba81a | |
![]() |
790ee29d3c | |
![]() |
1674d8ce8f | |
![]() |
6dda5b597c | |
![]() |
0a59085f64 | |
![]() |
512826e028 | |
![]() |
d3e14f6b87 | |
![]() |
aa9b1daa65 | |
![]() |
b0f0c671b2 | |
![]() |
6f37dec1d9 | |
![]() |
25fb52b6b2 |
|
@ -1,4 +1,4 @@
|
||||||
# python-oracledb 1.0
|
# python-oracledb 1.1
|
||||||
|
|
||||||
python-oracledb is a [Python programming language][python] extension module
|
python-oracledb is a [Python programming language][python] extension module
|
||||||
allowing Python programs to connect to [Oracle Database][oracledb]. It is the
|
allowing Python programs to connect to [Oracle Database][oracledb]. It is the
|
||||||
|
|
|
@ -2066,9 +2066,9 @@ DB API Types
|
||||||
.. data:: ROWID
|
.. data:: ROWID
|
||||||
|
|
||||||
This type object is used to describe the pseudo column "rowid". The
|
This type object is used to describe the pseudo column "rowid". The
|
||||||
database type :data:`DB_TYPE_ROWID` will compare equal to this value. If a
|
database types :data:`DB_TYPE_ROWID` and :data:`DB_TYPE_UROWID` will
|
||||||
variable is created with this type, the database type
|
compare equal to this value. If a variable is created with this type, the
|
||||||
:data:`DB_TYPE_VARCHAR` will be used.
|
database type :data:`DB_TYPE_VARCHAR` will be used.
|
||||||
|
|
||||||
|
|
||||||
.. data:: STRING
|
.. data:: STRING
|
||||||
|
@ -2281,6 +2281,17 @@ when binding data.
|
||||||
:data:`DATETIME`.
|
:data:`DATETIME`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_UROWID
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type UROWID. It will compare equal to the DB API type :data:`ROWID`.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This type is not supported in python-oracledb Thick mode.
|
||||||
|
See :ref:`querymetadatadiff`.
|
||||||
|
|
||||||
|
|
||||||
.. data:: DB_TYPE_VARCHAR
|
.. data:: DB_TYPE_VARCHAR
|
||||||
|
|
||||||
Describes columns, attributes or array elements in a database that are of
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
|
|
@ -7,6 +7,40 @@ python-oracledb Release Notes
|
||||||
|
|
||||||
For deprecations, see :ref:`Deprecations <deprecations>`.
|
For deprecations, see :ref:`Deprecations <deprecations>`.
|
||||||
|
|
||||||
|
oracledb 1.1.1 (September 2022)
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Thin Mode Changes
|
||||||
|
+++++++++++++++++
|
||||||
|
|
||||||
|
#) Fixed bug that prevented binding data of types
|
||||||
|
:data:`~oracledb.DB_TYPE_ROWID` and :data:`~oracledb.DB_TYPE_UROWID`.
|
||||||
|
#) Fixed bug that caused :meth:`Connection.is_healthy()` to return `True`
|
||||||
|
after a connection has been killed.
|
||||||
|
#) Internally, before a connection is returned from a pool, perform additional
|
||||||
|
checks in order to avoid returning a dead connection from the pool.
|
||||||
|
|
||||||
|
Thick Mode Changes
|
||||||
|
++++++++++++++++++
|
||||||
|
|
||||||
|
#) Fixed bug returning metadata of SODA documents inserted into a collection
|
||||||
|
using :meth:`SodaCollection.saveAndGet()`.
|
||||||
|
|
||||||
|
Common Changes
|
||||||
|
++++++++++++++
|
||||||
|
|
||||||
|
#) Fixed type checking errors
|
||||||
|
(`issue 52 <https://github.com/oracle/python-oracledb/issues/52>`__).
|
||||||
|
#) Enhanced type checking
|
||||||
|
(`issue 54 <https://github.com/oracle/python-oracledb/issues/54>`__),
|
||||||
|
(`issue 60 <https://github.com/oracle/python-oracledb/issues/60>`__).
|
||||||
|
#) The mode of python-oracledb is now fixed only after a call to
|
||||||
|
:meth:`oracledb.init_oracle_client()`, :meth:`oracledb.connect()` or
|
||||||
|
:meth:`oracledb.create_pool()` has completed successfully
|
||||||
|
(`issue 44 <https://github.com/oracle/python-oracledb/issues/44>`__).
|
||||||
|
#) Improved test suite and documentation.
|
||||||
|
|
||||||
|
|
||||||
oracledb 1.1.0 (September 2022)
|
oracledb 1.1.0 (September 2022)
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
|
|
@ -463,11 +463,11 @@ values.
|
||||||
* - ROWID
|
* - ROWID
|
||||||
- DB_TYPE_ROWID
|
- DB_TYPE_ROWID
|
||||||
- Yes
|
- Yes
|
||||||
- cannot be set
|
- bytes, str
|
||||||
* - UROWID
|
* - UROWID
|
||||||
- DB_TYPE_ROWID
|
- DB_TYPE_ROWID, DB_TYPE_UROWID (only supported in python-oracledb Thin mode)
|
||||||
- Yes. May show DB_TYPE_UROWID in metadata. See :ref:`Query Metadata Differences <querymetadatadiff>`.
|
- Yes. May show DB_TYPE_UROWID in metadata. See :ref:`Query Metadata Differences <querymetadatadiff>`.
|
||||||
- cannot be set
|
- bytes, str
|
||||||
* - CHAR
|
* - CHAR
|
||||||
- DB_TYPE_CHAR
|
- DB_TYPE_CHAR
|
||||||
- Yes
|
- Yes
|
||||||
|
@ -578,7 +578,7 @@ these arrays.
|
||||||
* - DB_TYPE_RAW
|
* - DB_TYPE_RAW
|
||||||
- bytes, str
|
- bytes, str
|
||||||
* - DB_TYPE_ROWID
|
* - DB_TYPE_ROWID
|
||||||
- cannot be set
|
- bytes, str
|
||||||
* - DB_TYPE_TIMESTAMP
|
* - DB_TYPE_TIMESTAMP
|
||||||
- datetime.date, datetime.datetime
|
- datetime.date, datetime.datetime
|
||||||
* - DB_TYPE_TIMESTAMP_LTZ
|
* - DB_TYPE_TIMESTAMP_LTZ
|
||||||
|
@ -586,6 +586,6 @@ these arrays.
|
||||||
* - DB_TYPE_TIMESTAMP_TZ
|
* - DB_TYPE_TIMESTAMP_TZ
|
||||||
- datetime.date, datetime.datetime
|
- datetime.date, datetime.datetime
|
||||||
* - DB_TYPE_UROWID
|
* - DB_TYPE_UROWID
|
||||||
- cannot be set
|
- bytes, str
|
||||||
* - DB_TYPE_VARCHAR
|
* - DB_TYPE_VARCHAR
|
||||||
- bytes, str
|
- bytes, str
|
||||||
|
|
|
@ -183,6 +183,48 @@ fetching a row and then updating that row by binding its rowid:
|
||||||
where rowid = :rid""", manager_id=205, rid=rowid)
|
where rowid = :rid""", manager_id=205, rid=rowid)
|
||||||
|
|
||||||
|
|
||||||
|
Binding UROWID Values
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Universal rowids (UROWID) are used to uniquely identify rows in index
|
||||||
|
organized tables. In python-oracledb, UROWID values are represented as strings.
|
||||||
|
The example below shows fetching a row from index organized table
|
||||||
|
``universal_rowids`` and then updating that row by binding its urowid:
|
||||||
|
|
||||||
|
.. code-block:: sql
|
||||||
|
|
||||||
|
CREATE TABLE universal_rowids (
|
||||||
|
int_col number(9) not null,
|
||||||
|
str_col varchar2(250) not null,
|
||||||
|
date_col date not null,
|
||||||
|
CONSTRAINT universal_rowids_pk PRIMARY KEY(int_col, str_col, date_col)
|
||||||
|
) ORGANIZATION INDEX
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
ridvar = cursor.var(oracledb.DB_TYPE_UROWID)
|
||||||
|
|
||||||
|
# fetch the row
|
||||||
|
cursor.execute("""
|
||||||
|
begin
|
||||||
|
select rowid into :rid from universal_rowids
|
||||||
|
where int_col = 3;
|
||||||
|
end;""", rid=ridvar)
|
||||||
|
|
||||||
|
# update the row by binding UROWID
|
||||||
|
cursor.execute("""
|
||||||
|
update universal_rowids set
|
||||||
|
str_col = :str_val
|
||||||
|
where rowid = :rowid_val""",
|
||||||
|
str_val="String #33", rowid_val=ridvar)
|
||||||
|
|
||||||
|
Note that the type :attr:`oracledb.DB_TYPE_UROWID` is only supported in
|
||||||
|
python-oracledb Thin mode. For python-oracledb Thick mode, the database type
|
||||||
|
UROWID can be bound with type :attr:`oracledb.DB_TYPE_ROWID`.
|
||||||
|
See :ref:`querymetadatadiff`.
|
||||||
|
|
||||||
|
|
||||||
DML RETURNING Bind Variables
|
DML RETURNING Bind Variables
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
|
|
@ -795,13 +795,13 @@ In order to install using the source on GitHub, use the following commands::
|
||||||
|
|
||||||
Note that if you download a source zip file directly from GitHub then you will
|
Note that if you download a source zip file directly from GitHub then you will
|
||||||
also need to download an `ODPI-C <https://github.com/oracle/odpi>`__ source zip
|
also need to download an `ODPI-C <https://github.com/oracle/odpi>`__ source zip
|
||||||
file and put the extracted contents inside the subdirectory
|
file and put the extracted contents inside the "odpi" subdirectory, for example
|
||||||
"python-oracledb-*/src/oracledb/impl/thick/odpi".
|
in "python-oracledb-main/src/oracledb/impl/thick/odpi".
|
||||||
|
|
||||||
Python-oracledb source code is also available from opensource.oracle.com. This
|
Python-oracledb source code is also available from opensource.oracle.com. This
|
||||||
can be installed with::
|
can be installed with::
|
||||||
|
|
||||||
git clone --recurse-submodules git://opensource.oracle.com/git/oracle/python-oracledb.git
|
git clone --recurse-submodules https://opensource.oracle.com/git/oracle/python-oracledb.git
|
||||||
cd python-oracledb
|
cd python-oracledb
|
||||||
python setup.py build
|
python setup.py build
|
||||||
python setup.py install
|
python setup.py install
|
||||||
|
|
|
@ -239,7 +239,7 @@ Python object that is returned by default. Python types can be changed with
|
||||||
- :attr:`oracledb.DB_TYPE_TIMESTAMP_TZ`
|
- :attr:`oracledb.DB_TYPE_TIMESTAMP_TZ`
|
||||||
- datetime.datetime [2]_
|
- datetime.datetime [2]_
|
||||||
* - UROWID
|
* - UROWID
|
||||||
- :attr:`oracledb.DB_TYPE_ROWID`
|
- :attr:`oracledb.DB_TYPE_ROWID`, :attr:`oracledb.DB_TYPE_UROWID`
|
||||||
- str
|
- str
|
||||||
* - VARCHAR2
|
* - VARCHAR2
|
||||||
- :attr:`oracledb.DB_TYPE_VARCHAR`
|
- :attr:`oracledb.DB_TYPE_VARCHAR`
|
||||||
|
@ -744,15 +744,10 @@ Querying Corrupt Data
|
||||||
If queries fail with the error "codec can't decode byte" when you select data,
|
If queries fail with the error "codec can't decode byte" when you select data,
|
||||||
then:
|
then:
|
||||||
|
|
||||||
* Check your :ref:`character set <globalization>` is correct. Review the
|
* Check if your :ref:`character set <globalization>` is correct. Review the
|
||||||
:ref:`database character sets <findingcharset>`. Check with
|
:ref:`database character sets <findingcharset>`. Check with
|
||||||
:ref:`fetching-raw-data`. Consider using UTF-8, if this is appropriate:
|
:ref:`fetching-raw-data`. Note that the encoding used for all character
|
||||||
|
data in python-oracledb is "UTF-8".
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
connection = oracledb.connect(user="hr", password=userpwd,
|
|
||||||
dsn="dbhost.example.com/orclpdb",
|
|
||||||
encoding="UTF-8", nencoding="UTF-8")
|
|
||||||
|
|
||||||
* Check for corrupt data in the database.
|
* Check for corrupt data in the database.
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ classifiers =
|
||||||
zip_safe = false
|
zip_safe = false
|
||||||
python_requires = >=3.6
|
python_requires = >=3.6
|
||||||
setup_requires = cython
|
setup_requires = cython
|
||||||
install_requires = cryptography>=3.4
|
install_requires = cryptography>=3.2.1
|
||||||
test_suite = tests
|
test_suite = tests
|
||||||
packages = find:
|
packages = find:
|
||||||
package_dir =
|
package_dir =
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from . import connection as connection_module
|
from . import connection as connection_module
|
||||||
from typing import Type, Union
|
from typing import Union, List
|
||||||
from . import errors, exceptions
|
from . import errors, exceptions
|
||||||
from .dbobject import DbObject, DbObjectType
|
from .dbobject import DbObject, DbObjectType
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class Queue:
|
||||||
queue._impl = impl
|
queue._impl = impl
|
||||||
return queue
|
return queue
|
||||||
|
|
||||||
def _verify_message(self, message: Type["MessageProperties"]) -> None:
|
def _verify_message(self, message: "MessageProperties") -> None:
|
||||||
"""
|
"""
|
||||||
Internal method used for verifying a message.
|
Internal method used for verifying a message.
|
||||||
"""
|
"""
|
||||||
|
@ -58,7 +58,7 @@ class Queue:
|
||||||
errors._raise_err(errors.ERR_MESSAGE_HAS_NO_PAYLOAD)
|
errors._raise_err(errors.ERR_MESSAGE_HAS_NO_PAYLOAD)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def connection(self) -> Type["connection_module.Connection"]:
|
def connection(self) -> "connection_module.Connection":
|
||||||
"""
|
"""
|
||||||
Returns the connection on which the queue was created.
|
Returns the connection on which the queue was created.
|
||||||
"""
|
"""
|
||||||
|
@ -72,13 +72,13 @@ class Queue:
|
||||||
message_impls = self._impl.deq_many(max_num_messages)
|
message_impls = self._impl.deq_many(max_num_messages)
|
||||||
return [MessageProperties._from_impl(impl) for impl in message_impls]
|
return [MessageProperties._from_impl(impl) for impl in message_impls]
|
||||||
|
|
||||||
def deqMany(self, max_num_messages: int) -> list:
|
def deqMany(self, max_num_messages: int) -> List["MessageProperties"]:
|
||||||
"""
|
"""
|
||||||
Deprecated: use deqmany() instead.
|
Deprecated: use deqmany() instead.
|
||||||
"""
|
"""
|
||||||
return self.deqmany(max_num_messages)
|
return self.deqmany(max_num_messages)
|
||||||
|
|
||||||
def deqone(self) -> Union[Type["MessageProperties"], None]:
|
def deqone(self) -> Union["MessageProperties", None]:
|
||||||
"""
|
"""
|
||||||
Dequeues at most one message from the queue and returns it. If no
|
Dequeues at most one message from the queue and returns it. If no
|
||||||
message is dequeued, None is returned.
|
message is dequeued, None is returned.
|
||||||
|
@ -87,14 +87,14 @@ class Queue:
|
||||||
if message_impl is not None:
|
if message_impl is not None:
|
||||||
return MessageProperties._from_impl(message_impl)
|
return MessageProperties._from_impl(message_impl)
|
||||||
|
|
||||||
def deqOne(self) -> Union[Type["MessageProperties"], None]:
|
def deqOne(self) -> Union["MessageProperties", None]:
|
||||||
"""
|
"""
|
||||||
Deprecated: use deqone() instead.
|
Deprecated: use deqone() instead.
|
||||||
"""
|
"""
|
||||||
return self.deqone()
|
return self.deqone()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def deqoptions(self) -> Type["DeqOptions"]:
|
def deqoptions(self) -> "DeqOptions":
|
||||||
"""
|
"""
|
||||||
Returns the options that will be used when dequeuing messages from the
|
Returns the options that will be used when dequeuing messages from the
|
||||||
queue.
|
queue.
|
||||||
|
@ -102,7 +102,7 @@ class Queue:
|
||||||
return self._deq_options
|
return self._deq_options
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def deqOptions(self) -> Type["DeqOptions"]:
|
def deqOptions(self) -> "DeqOptions":
|
||||||
"""
|
"""
|
||||||
Deprecated: use deqoptions instead.
|
Deprecated: use deqoptions instead.
|
||||||
"""
|
"""
|
||||||
|
@ -131,7 +131,7 @@ class Queue:
|
||||||
"""
|
"""
|
||||||
return self.enqmany(messages)
|
return self.enqmany(messages)
|
||||||
|
|
||||||
def enqone(self, message: Type["MessageProperties"]) -> None:
|
def enqone(self, message: "MessageProperties") -> None:
|
||||||
"""
|
"""
|
||||||
Enqueues a single message into the queue. The message must be a message
|
Enqueues a single message into the queue. The message must be a message
|
||||||
property object which has had its payload attribute set to a value that
|
property object which has had its payload attribute set to a value that
|
||||||
|
@ -140,14 +140,14 @@ class Queue:
|
||||||
self._verify_message(message)
|
self._verify_message(message)
|
||||||
self._impl.enq_one(message._impl)
|
self._impl.enq_one(message._impl)
|
||||||
|
|
||||||
def enqOne(self, message: Type["MessageProperties"]) -> None:
|
def enqOne(self, message: "MessageProperties") -> None:
|
||||||
"""
|
"""
|
||||||
Deprecated: use enqone() instead.
|
Deprecated: use enqone() instead.
|
||||||
"""
|
"""
|
||||||
return self.enqone(message)
|
return self.enqone(message)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def enqoptions(self) -> Type["EnqOptions"]:
|
def enqoptions(self) -> "EnqOptions":
|
||||||
"""
|
"""
|
||||||
Returns the options that will be used when enqueuing messages into the
|
Returns the options that will be used when enqueuing messages into the
|
||||||
queue.
|
queue.
|
||||||
|
@ -155,7 +155,7 @@ class Queue:
|
||||||
return self._enq_options
|
return self._enq_options
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def enqOptions(self) -> Type["EnqOptions"]:
|
def enqOptions(self) -> "EnqOptions":
|
||||||
"""
|
"""
|
||||||
Deprecated: use enqoptions() instead.
|
Deprecated: use enqoptions() instead.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
from typing import Type, Union, Callable
|
from typing import Union, Callable
|
||||||
|
|
||||||
import oracledb
|
import oracledb
|
||||||
|
|
||||||
|
@ -575,7 +575,7 @@ class ConnectParams:
|
||||||
"""
|
"""
|
||||||
return self._impl.wallet_location
|
return self._impl.wallet_location
|
||||||
|
|
||||||
def copy(self) -> Type["ConnectParams"]:
|
def copy(self) -> "ConnectParams":
|
||||||
"""
|
"""
|
||||||
Creates a copy of the parameters and returns it.
|
Creates a copy of the parameters and returns it.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Connection:
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
dsn: str=None, *,
|
dsn: str=None, *,
|
||||||
pool: Type["pool_module.ConnectionPool"]=None,
|
pool: "pool_module.ConnectionPool"=None,
|
||||||
params: ConnectParams=None,
|
params: ConnectParams=None,
|
||||||
**kwargs) -> None:
|
**kwargs) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -99,51 +99,52 @@ class Connection:
|
||||||
self._impl = None
|
self._impl = None
|
||||||
|
|
||||||
# determine if thin mode is being used
|
# determine if thin mode is being used
|
||||||
thin = driver_mode.check_and_return_mode()
|
with driver_mode.get_manager() as mode_mgr:
|
||||||
|
thin = mode_mgr.thin
|
||||||
|
|
||||||
# determine which connection parameters to use
|
# determine which connection parameters to use
|
||||||
if params is None:
|
if params is None:
|
||||||
params_impl = base_impl.ConnectParamsImpl()
|
params_impl = base_impl.ConnectParamsImpl()
|
||||||
elif not isinstance(params, ConnectParams):
|
elif not isinstance(params, ConnectParams):
|
||||||
errors._raise_err(errors.ERR_INVALID_CONNECT_PARAMS)
|
errors._raise_err(errors.ERR_INVALID_CONNECT_PARAMS)
|
||||||
else:
|
|
||||||
params_impl = params._impl.copy()
|
|
||||||
if kwargs:
|
|
||||||
params_impl.set(kwargs)
|
|
||||||
if dsn is not None:
|
|
||||||
dsn = params_impl.parse_dsn(dsn, thin)
|
|
||||||
if dsn is None:
|
|
||||||
dsn = params_impl.get_connect_string()
|
|
||||||
|
|
||||||
# see if connection is being acquired from a pool
|
|
||||||
if pool is None:
|
|
||||||
pool_impl = None
|
|
||||||
elif not isinstance(pool, pool_module.ConnectionPool):
|
|
||||||
message = "pool must be an instance of oracledb.ConnectionPool"
|
|
||||||
raise TypeError(message)
|
|
||||||
else:
|
|
||||||
pool._verify_open()
|
|
||||||
pool_impl = pool._impl
|
|
||||||
|
|
||||||
# create thin or thick implementation object
|
|
||||||
if thin:
|
|
||||||
if pool is not None:
|
|
||||||
impl = pool_impl.acquire(params_impl)
|
|
||||||
else:
|
else:
|
||||||
impl = thin_impl.ThinConnImpl(dsn, params_impl)
|
params_impl = params._impl.copy()
|
||||||
impl.connect(params_impl)
|
if kwargs:
|
||||||
else:
|
params_impl.set(kwargs)
|
||||||
impl = thick_impl.ThickConnImpl(dsn, params_impl)
|
if dsn is not None:
|
||||||
impl.connect(params_impl, pool_impl)
|
dsn = params_impl.parse_dsn(dsn, thin)
|
||||||
self._impl = impl
|
if dsn is None:
|
||||||
self._version = None
|
dsn = params_impl.get_connect_string()
|
||||||
|
|
||||||
# invoke callback, if applicable
|
# see if connection is being acquired from a pool
|
||||||
if impl.invoke_session_callback and pool is not None \
|
if pool is None:
|
||||||
and pool.session_callback is not None \
|
pool_impl = None
|
||||||
and callable(pool.session_callback):
|
elif not isinstance(pool, pool_module.ConnectionPool):
|
||||||
pool.session_callback(self, params_impl.tag)
|
message = "pool must be an instance of oracledb.ConnectionPool"
|
||||||
impl.invoke_session_callback = False
|
raise TypeError(message)
|
||||||
|
else:
|
||||||
|
pool._verify_open()
|
||||||
|
pool_impl = pool._impl
|
||||||
|
|
||||||
|
# create thin or thick implementation object
|
||||||
|
if thin:
|
||||||
|
if pool is not None:
|
||||||
|
impl = pool_impl.acquire(params_impl)
|
||||||
|
else:
|
||||||
|
impl = thin_impl.ThinConnImpl(dsn, params_impl)
|
||||||
|
impl.connect(params_impl)
|
||||||
|
else:
|
||||||
|
impl = thick_impl.ThickConnImpl(dsn, params_impl)
|
||||||
|
impl.connect(params_impl, pool_impl)
|
||||||
|
self._impl = impl
|
||||||
|
self._version = None
|
||||||
|
|
||||||
|
# invoke callback, if applicable
|
||||||
|
if impl.invoke_session_callback and pool is not None \
|
||||||
|
and pool.session_callback is not None \
|
||||||
|
and callable(pool.session_callback):
|
||||||
|
pool.session_callback(self, params_impl.tag)
|
||||||
|
impl.invoke_session_callback = False
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self._impl is not None:
|
if self._impl is not None:
|
||||||
|
@ -502,7 +503,7 @@ class Connection:
|
||||||
This function performs a local check. To fully check a connection's
|
This function performs a local check. To fully check a connection's
|
||||||
health, use ping() which performs a round-trip to the database.
|
health, use ping() which performs a round-trip to the database.
|
||||||
"""
|
"""
|
||||||
return self._impl.get_is_healthy()
|
return self._impl is not None and self._impl.get_is_healthy()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ltxid(self) -> bytes:
|
def ltxid(self) -> bytes:
|
||||||
|
@ -603,7 +604,7 @@ class Connection:
|
||||||
"""
|
"""
|
||||||
return self.tpc_prepare()
|
return self.tpc_prepare()
|
||||||
|
|
||||||
def queue(self, name: str, payload_type: [DbObjectType, str]=None, *,
|
def queue(self, name: str, payload_type: Union[DbObjectType, str]=None, *,
|
||||||
payloadType: DbObjectType=None) -> Queue:
|
payloadType: DbObjectType=None) -> Queue:
|
||||||
"""
|
"""
|
||||||
Creates and returns a queue which is used to enqueue and dequeue
|
Creates and returns a queue which is used to enqueue and dequeue
|
||||||
|
@ -1001,7 +1002,7 @@ def _connection_factory(f):
|
||||||
"""
|
"""
|
||||||
@functools.wraps(f)
|
@functools.wraps(f)
|
||||||
def connect(dsn: str=None, *,
|
def connect(dsn: str=None, *,
|
||||||
pool: Type["pool_module.ConnectionPool"]=None,
|
pool: "pool_module.ConnectionPool"=None,
|
||||||
conn_class: Type[Connection]=Connection,
|
conn_class: Type[Connection]=Connection,
|
||||||
params: ConnectParams=None,
|
params: ConnectParams=None,
|
||||||
**kwargs) -> Connection:
|
**kwargs) -> Connection:
|
||||||
|
@ -1014,7 +1015,7 @@ def _connection_factory(f):
|
||||||
|
|
||||||
@_connection_factory
|
@_connection_factory
|
||||||
def connect(dsn: str=None, *,
|
def connect(dsn: str=None, *,
|
||||||
pool: Type["pool_module.ConnectionPool"]=None,
|
pool: "pool_module.ConnectionPool"=None,
|
||||||
conn_class: Type[Connection]=Connection,
|
conn_class: Type[Connection]=Connection,
|
||||||
params: ConnectParams=None,
|
params: ConnectParams=None,
|
||||||
user: str=None,
|
user: str=None,
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
# fetching results from queries.
|
# fetching results from queries.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
from typing import Any, Type, Union, Callable
|
from typing import Any, Union, Callable
|
||||||
|
|
||||||
from . import __name__ as MODULE_NAME
|
from . import __name__ as MODULE_NAME
|
||||||
from . import errors, exceptions
|
from . import errors, exceptions
|
||||||
|
@ -42,7 +42,7 @@ from .dbobject import DbObjectType
|
||||||
class Cursor:
|
class Cursor:
|
||||||
__module__ = MODULE_NAME
|
__module__ = MODULE_NAME
|
||||||
|
|
||||||
def __init__(self, connection: Type["connection_module.Connection"],
|
def __init__(self, connection: "connection_module.Connection",
|
||||||
scrollable: bool = False) -> None:
|
scrollable: bool = False) -> None:
|
||||||
self._impl = None
|
self._impl = None
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
|
@ -309,7 +309,7 @@ class Cursor:
|
||||||
|
|
||||||
def execute(self, statement: Union[str, None],
|
def execute(self, statement: Union[str, None],
|
||||||
parameters: Union[list, tuple, dict]=None,
|
parameters: Union[list, tuple, dict]=None,
|
||||||
**keyword_parameters: dict) -> Union[Type["Cursor"], None]:
|
**keyword_parameters: dict) -> Union["Cursor", None]:
|
||||||
"""
|
"""
|
||||||
Execute a statement against the database.
|
Execute a statement against the database.
|
||||||
|
|
||||||
|
@ -739,7 +739,7 @@ class Cursor:
|
||||||
encoding_errors: str=None,
|
encoding_errors: str=None,
|
||||||
bypass_decode: bool=False,
|
bypass_decode: bool=False,
|
||||||
*,
|
*,
|
||||||
encodingErrors: str=None) -> Type["Var"]:
|
encodingErrors: str=None) -> "Var":
|
||||||
"""
|
"""
|
||||||
Create a variable with the specified characteristics. This method was
|
Create a variable with the specified characteristics. This method was
|
||||||
designed for use with PL/SQL in/out variables where the length or type
|
designed for use with PL/SQL in/out variables where the length or type
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
# object type metadata: DbObject, DbObjectType and DbObjectAttr.
|
# object type metadata: DbObject, DbObjectType and DbObjectAttr.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
from typing import Sequence, Type, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from . import __name__ as MODULE_NAME
|
from . import __name__ as MODULE_NAME
|
||||||
from .base_impl import DbType
|
from .base_impl import DbType
|
||||||
|
@ -91,7 +91,7 @@ class DbObject:
|
||||||
ix = self._impl.get_next_index(ix)
|
ix = self._impl.get_next_index(ix)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def copy(self) -> Type["DbObject"]:
|
def copy(self) -> "DbObject":
|
||||||
"""
|
"""
|
||||||
Create a copy of the object and return it.
|
Create a copy of the object and return it.
|
||||||
"""
|
"""
|
||||||
|
@ -181,7 +181,7 @@ class DbObject:
|
||||||
self._impl.trim(num)
|
self._impl.trim(num)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self) -> Type["DbObjectType"]:
|
def type(self) -> "DbObjectType":
|
||||||
"""
|
"""
|
||||||
Returns an ObjectType corresponding to the type of the object.
|
Returns an ObjectType corresponding to the type of the object.
|
||||||
"""
|
"""
|
||||||
|
@ -211,7 +211,7 @@ class DbObjectAttr:
|
||||||
return self._impl.name
|
return self._impl.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self) -> Union[Type["DbObjectType"], DbType]:
|
def type(self) -> Union["DbObjectType", DbType]:
|
||||||
"""
|
"""
|
||||||
This read-only attribute returns the type of the attribute. This will
|
This read-only attribute returns the type of the attribute. This will
|
||||||
be an Oracle Object Type if the variable binds Oracle objects;
|
be an Oracle Object Type if the variable binds Oracle objects;
|
||||||
|
@ -274,7 +274,7 @@ class DbObjectType:
|
||||||
return self._impl.name
|
return self._impl.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def element_type(self) -> Union[Type["DbObjectType"], DbType]:
|
def element_type(self) -> Union["DbObjectType", DbType]:
|
||||||
"""
|
"""
|
||||||
This read-only attribute returns the type of elements found in
|
This read-only attribute returns the type of elements found in
|
||||||
collections of this type, if iscollection is True; otherwise, it
|
collections of this type, if iscollection is True; otherwise, it
|
||||||
|
|
|
@ -31,27 +31,63 @@
|
||||||
# simultaneously.
|
# simultaneously.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import threading
|
||||||
|
|
||||||
from . import errors
|
from . import errors
|
||||||
|
|
||||||
# this flag is used to indicate which mode is currently being used:
|
# The DriverModeHandler class is used to manage which mode the driver is using.
|
||||||
# None: neither thick nor thin implementation has been used yet
|
#
|
||||||
# False: thick implementation is being used
|
# The "thin_mode" flag contains the current state:
|
||||||
# True: thin implementation is being used
|
# None: neither thick nor thin implementation has been used yet
|
||||||
thin_mode = None
|
# False: thick implementation is being used
|
||||||
|
# True: thin implementation is being used
|
||||||
def check_and_return_mode(requested_thin_mode=None):
|
#
|
||||||
|
# The "requested_thin_mode" flag is set to the mode that is being requested:
|
||||||
|
# False: thick implementation is being initialized
|
||||||
|
# True: thin implementation is being initialized
|
||||||
|
class DriverModeManager:
|
||||||
"""
|
"""
|
||||||
Internal function to return the current mode of python-oracledb.
|
Manages the mode the driver is using. The "thin_mode" flag contains the
|
||||||
|
current state:
|
||||||
|
None: neither thick nor thin implementation has been used yet
|
||||||
|
False: thick implementation is being used
|
||||||
|
True: thin implementation is being used
|
||||||
|
The "requested_thin_mode" is set to the mode that is being requested, but
|
||||||
|
only while initialization is taking place (otherwise, it contains the value
|
||||||
|
None):
|
||||||
|
False: thick implementation is being initialized
|
||||||
|
True: thin implementation is being initialized
|
||||||
|
The condition is used to ensure that only one thread is performing
|
||||||
|
initialization.
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self.thin_mode = None
|
||||||
|
self.requested_thin_mode = None
|
||||||
|
self.condition = threading.Condition()
|
||||||
|
|
||||||
If neither the thick nor the thin implementation have been used yet (the
|
def __enter__(self):
|
||||||
value of thin_mode is None), then:
|
return self
|
||||||
|
|
||||||
- the mode is set to the requested mode, or
|
def __exit__(self, exc_type, exc_value, exc_tb):
|
||||||
|
with self.condition:
|
||||||
|
if exc_type is None and exc_value is None and exc_tb is None \
|
||||||
|
and self.requested_thin_mode is not None:
|
||||||
|
self.thin_mode = self.requested_thin_mode
|
||||||
|
self.requested_thin_mode = None
|
||||||
|
self.condition.notify()
|
||||||
|
|
||||||
- the mode is set to thin, if no mode is requested.
|
@property
|
||||||
|
def thin(self):
|
||||||
|
if self.requested_thin_mode is not None:
|
||||||
|
return self.requested_thin_mode
|
||||||
|
return self.thin_mode
|
||||||
|
|
||||||
Otherwise, if requested_thin_mode is used and the mode requested
|
manager = DriverModeManager()
|
||||||
does not match the current mode, an error is raised.
|
|
||||||
|
def get_manager(requested_thin_mode=None):
|
||||||
|
"""
|
||||||
|
Returns the manager, but only after ensuring that no other threads are
|
||||||
|
attempting to initialize the mode.
|
||||||
|
|
||||||
NOTE: the current implementation of the driver only requires
|
NOTE: the current implementation of the driver only requires
|
||||||
requested_thin_mode to be set when initializing the thick mode; for this
|
requested_thin_mode to be set when initializing the thick mode; for this
|
||||||
|
@ -59,15 +95,19 @@ def check_and_return_mode(requested_thin_mode=None):
|
||||||
being created. If this assumption changes, a new error message will be
|
being created. If this assumption changes, a new error message will be
|
||||||
required.
|
required.
|
||||||
"""
|
"""
|
||||||
global thin_mode
|
with manager.condition:
|
||||||
if thin_mode is None:
|
if manager.thin_mode is None:
|
||||||
if requested_thin_mode is None:
|
if manager.requested_thin_mode is not None:
|
||||||
thin_mode = True
|
manager.condition.wait()
|
||||||
else:
|
if manager.thin_mode is None:
|
||||||
thin_mode = requested_thin_mode
|
if requested_thin_mode is None:
|
||||||
elif requested_thin_mode is not None and requested_thin_mode != thin_mode:
|
manager.requested_thin_mode = True
|
||||||
errors._raise_err(errors.ERR_THIN_CONNECTION_ALREADY_CREATED)
|
else:
|
||||||
return thin_mode
|
manager.requested_thin_mode = requested_thin_mode
|
||||||
|
elif requested_thin_mode is not None \
|
||||||
|
and requested_thin_mode != manager.thin_mode:
|
||||||
|
errors._raise_err(errors.ERR_THIN_CONNECTION_ALREADY_CREATED)
|
||||||
|
return manager
|
||||||
|
|
||||||
|
|
||||||
def is_thin_mode() -> bool:
|
def is_thin_mode() -> bool:
|
||||||
|
@ -77,14 +117,14 @@ def is_thin_mode() -> bool:
|
||||||
|
|
||||||
Immediately after python-oracledb is imported, this function will return
|
Immediately after python-oracledb is imported, this function will return
|
||||||
True indicating that python-oracledb defaults to Thin mode. If
|
True indicating that python-oracledb defaults to Thin mode. If
|
||||||
oracledb.init_oracle_client() is called, then a subsequent call to
|
oracledb.init_oracle_client() is called successfully, then a subsequent
|
||||||
is_thin_mode() will return False indicating that Thick mode is enabled.
|
call to is_thin_mode() will return False indicating that Thick mode is
|
||||||
Once the first standalone connection or connection pool is created, or a
|
enabled. Once the first standalone connection or connection pool is
|
||||||
call to oracledb.init_oracle_client() is made, then python-oracledb's mode
|
created succesfully, or a call to oracledb.init_oracle_client() is made
|
||||||
is fixed and the value returned by is_thin_mode() will never change for the
|
successfully, then python-oracledb's mode is fixed and the value returned
|
||||||
lifetime of the process.
|
by is_thin_mode() will never change for the lifetime of the process.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if thin_mode is not None:
|
if manager.thin_mode is not None:
|
||||||
return thin_mode
|
return manager.thin_mode
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -452,31 +452,32 @@ def init_oracle_client(lib_dir=None, config_dir=None, error_url=None,
|
||||||
if params_tuple != driver_context_params:
|
if params_tuple != driver_context_params:
|
||||||
errors._raise_err(errors.ERR_LIBRARY_ALREADY_INITIALIZED)
|
errors._raise_err(errors.ERR_LIBRARY_ALREADY_INITIALIZED)
|
||||||
return
|
return
|
||||||
driver_mode.check_and_return_mode(requested_thin_mode=False)
|
with driver_mode.get_manager(requested_thin_mode=False) as mode_mgr:
|
||||||
memset(¶ms, 0, sizeof(dpiContextCreateParams))
|
memset(¶ms, 0, sizeof(dpiContextCreateParams))
|
||||||
encoding_bytes = constants.ENCODING.encode()
|
encoding_bytes = constants.ENCODING.encode()
|
||||||
params.defaultEncoding = encoding_bytes
|
params.defaultEncoding = encoding_bytes
|
||||||
if config_dir is None:
|
if config_dir is None:
|
||||||
config_dir = defaults.config_dir
|
config_dir = defaults.config_dir
|
||||||
if lib_dir is not None:
|
if lib_dir is not None:
|
||||||
lib_dir_bytes = lib_dir.encode()
|
lib_dir_bytes = lib_dir.encode()
|
||||||
params.oracleClientLibDir = lib_dir_bytes
|
params.oracleClientLibDir = lib_dir_bytes
|
||||||
if config_dir is not None:
|
if config_dir is not None:
|
||||||
config_dir_bytes = config_dir.encode()
|
config_dir_bytes = config_dir.encode()
|
||||||
params.oracleClientConfigDir = config_dir_bytes
|
params.oracleClientConfigDir = config_dir_bytes
|
||||||
if driver_name is None:
|
if driver_name is None:
|
||||||
driver_name = f"{constants.DRIVER_NAME} thk : {VERSION}"
|
driver_name = f"{constants.DRIVER_NAME} thk : {VERSION}"
|
||||||
driver_name_bytes = driver_name.encode()
|
driver_name_bytes = driver_name.encode()
|
||||||
params.defaultDriverName = driver_name_bytes
|
params.defaultDriverName = driver_name_bytes
|
||||||
if error_url is not None:
|
if error_url is not None:
|
||||||
error_url_bytes = error_url.encode()
|
error_url_bytes = error_url.encode()
|
||||||
else:
|
else:
|
||||||
error_url_bytes = constants.INSTALLATION_URL.encode()
|
error_url_bytes = constants.INSTALLATION_URL.encode()
|
||||||
params.loadErrorUrl = error_url_bytes
|
params.loadErrorUrl = error_url_bytes
|
||||||
if dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
|
if dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
|
||||||
¶ms, &driver_context, &error_info) < 0:
|
¶ms, &driver_context,
|
||||||
_raise_from_info(&error_info)
|
&error_info) < 0:
|
||||||
driver_context_params = params_tuple
|
_raise_from_info(&error_info)
|
||||||
|
driver_context_params = params_tuple
|
||||||
|
|
||||||
|
|
||||||
def init_thick_impl(package):
|
def init_thick_impl(package):
|
||||||
|
|
|
@ -1016,15 +1016,22 @@ cdef class ReadBuffer:
|
||||||
const char_type *input_ptr
|
const char_type *input_ptr
|
||||||
bytearray output_value
|
bytearray output_value
|
||||||
uint32_t num_bytes
|
uint32_t num_bytes
|
||||||
|
uint8_t length
|
||||||
Rowid rowid
|
Rowid rowid
|
||||||
|
|
||||||
# check for null
|
# check for null
|
||||||
self.read_ub4(&num_bytes)
|
self.read_ub1(&length)
|
||||||
if num_bytes == 0:
|
if _is_null_length(length):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# handle physical rowid
|
if length == 1:
|
||||||
|
self.skip_ub1()
|
||||||
|
else:
|
||||||
|
self.read_ub4(&num_bytes)
|
||||||
|
|
||||||
self.read_raw_bytes_chunked(&input_ptr, &input_len)
|
self.read_raw_bytes_chunked(&input_ptr, &input_len)
|
||||||
|
|
||||||
|
# handle physical rowid
|
||||||
if input_ptr[0] == 1:
|
if input_ptr[0] == 1:
|
||||||
rowid.rba = unpack_uint32(&input_ptr[1], BYTE_ORDER_MSB)
|
rowid.rba = unpack_uint32(&input_ptr[1], BYTE_ORDER_MSB)
|
||||||
rowid.partition_id = unpack_uint16(&input_ptr[5], BYTE_ORDER_MSB)
|
rowid.partition_id = unpack_uint16(&input_ptr[5], BYTE_ORDER_MSB)
|
||||||
|
|
|
@ -325,7 +325,8 @@ cdef class ThinConnImpl(BaseConnImpl):
|
||||||
return self._internal_name
|
return self._internal_name
|
||||||
|
|
||||||
def get_is_healthy(self):
|
def get_is_healthy(self):
|
||||||
return not self._protocol._read_buf._session_needs_to_be_closed
|
return self._protocol._socket is not None \
|
||||||
|
and not self._protocol._read_buf._session_needs_to_be_closed
|
||||||
|
|
||||||
def get_ltxid(self):
|
def get_ltxid(self):
|
||||||
return self._ltxid or b''
|
return self._ltxid or b''
|
||||||
|
|
|
@ -621,6 +621,7 @@ DEF TNS_MAX_CURSORS_TO_CLOSE = 500
|
||||||
DEF TNS_TXN_IN_PROGRESS = 0x00000002
|
DEF TNS_TXN_IN_PROGRESS = 0x00000002
|
||||||
DEF TNS_MAX_CONNECT_DATA = 230
|
DEF TNS_MAX_CONNECT_DATA = 230
|
||||||
DEF TNS_CHUNK_SIZE = 32767
|
DEF TNS_CHUNK_SIZE = 32767
|
||||||
|
DEF TNS_MAX_UROWID_LENGTH = 3950
|
||||||
|
|
||||||
# base 64 encoding alphabet
|
# base 64 encoding alphabet
|
||||||
DEF TNS_BASE64_ALPHABET = \
|
DEF TNS_BASE64_ALPHABET = \
|
||||||
|
|
|
@ -537,7 +537,8 @@ cdef class MessageWithData(Message):
|
||||||
if var_impl.bypass_decode:
|
if var_impl.bypass_decode:
|
||||||
ora_type_num = TNS_DATA_TYPE_RAW
|
ora_type_num = TNS_DATA_TYPE_RAW
|
||||||
if buffer_size == 0 and ora_type_num != TNS_DATA_TYPE_LONG \
|
if buffer_size == 0 and ora_type_num != TNS_DATA_TYPE_LONG \
|
||||||
and ora_type_num != TNS_DATA_TYPE_LONG_RAW:
|
and ora_type_num != TNS_DATA_TYPE_LONG_RAW \
|
||||||
|
and ora_type_num != TNS_DATA_TYPE_UROWID:
|
||||||
column_value = None # column is null by describe
|
column_value = None # column is null by describe
|
||||||
elif ora_type_num == TNS_DATA_TYPE_VARCHAR \
|
elif ora_type_num == TNS_DATA_TYPE_VARCHAR \
|
||||||
or ora_type_num == TNS_DATA_TYPE_CHAR \
|
or ora_type_num == TNS_DATA_TYPE_CHAR \
|
||||||
|
@ -557,7 +558,7 @@ cdef class MessageWithData(Message):
|
||||||
column_value = buf.read_date()
|
column_value = buf.read_date()
|
||||||
elif ora_type_num == TNS_DATA_TYPE_ROWID:
|
elif ora_type_num == TNS_DATA_TYPE_ROWID:
|
||||||
if not self.in_fetch:
|
if not self.in_fetch:
|
||||||
column_value = buf.read_urowid()
|
column_value = buf.read_str(TNS_CS_IMPLICIT)
|
||||||
else:
|
else:
|
||||||
buf.read_ub1(&num_bytes)
|
buf.read_ub1(&num_bytes)
|
||||||
if _is_null_length(num_bytes):
|
if _is_null_length(num_bytes):
|
||||||
|
@ -566,7 +567,10 @@ cdef class MessageWithData(Message):
|
||||||
buf.read_rowid(&rowid)
|
buf.read_rowid(&rowid)
|
||||||
column_value = _encode_rowid(&rowid)
|
column_value = _encode_rowid(&rowid)
|
||||||
elif ora_type_num == TNS_DATA_TYPE_UROWID:
|
elif ora_type_num == TNS_DATA_TYPE_UROWID:
|
||||||
column_value = buf.read_urowid()
|
if not self.in_fetch:
|
||||||
|
column_value = buf.read_str(TNS_CS_IMPLICIT)
|
||||||
|
else:
|
||||||
|
column_value = buf.read_urowid()
|
||||||
elif ora_type_num == TNS_DATA_TYPE_BINARY_DOUBLE:
|
elif ora_type_num == TNS_DATA_TYPE_BINARY_DOUBLE:
|
||||||
column_value = buf.read_binary_double()
|
column_value = buf.read_binary_double()
|
||||||
elif ora_type_num == TNS_DATA_TYPE_BINARY_FLOAT:
|
elif ora_type_num == TNS_DATA_TYPE_BINARY_FLOAT:
|
||||||
|
@ -895,11 +899,14 @@ cdef class MessageWithData(Message):
|
||||||
list bind_var_impls) except -1:
|
list bind_var_impls) except -1:
|
||||||
cdef:
|
cdef:
|
||||||
uint8_t ora_type_num, flag
|
uint8_t ora_type_num, flag
|
||||||
|
uint32_t buffer_size
|
||||||
ThinVarImpl var_impl
|
ThinVarImpl var_impl
|
||||||
for var_impl in bind_var_impls:
|
for var_impl in bind_var_impls:
|
||||||
ora_type_num = var_impl.dbtype._ora_type_num
|
ora_type_num = var_impl.dbtype._ora_type_num
|
||||||
if ora_type_num == TNS_DATA_TYPE_ROWID:
|
buffer_size = var_impl.buffer_size
|
||||||
ora_type_num = TNS_DATA_TYPE_UROWID
|
if ora_type_num in (TNS_DATA_TYPE_ROWID, TNS_DATA_TYPE_UROWID):
|
||||||
|
ora_type_num = TNS_DATA_TYPE_VARCHAR
|
||||||
|
buffer_size = TNS_MAX_UROWID_LENGTH
|
||||||
flag = TNS_BIND_USE_INDICATORS
|
flag = TNS_BIND_USE_INDICATORS
|
||||||
if var_impl.is_array:
|
if var_impl.is_array:
|
||||||
flag |= TNS_BIND_ARRAY
|
flag |= TNS_BIND_ARRAY
|
||||||
|
@ -909,10 +916,10 @@ cdef class MessageWithData(Message):
|
||||||
# expects that and complains if any other value is sent!
|
# expects that and complains if any other value is sent!
|
||||||
buf.write_uint8(0)
|
buf.write_uint8(0)
|
||||||
buf.write_uint8(0)
|
buf.write_uint8(0)
|
||||||
if var_impl.buffer_size >= TNS_MIN_LONG_LENGTH:
|
if buffer_size >= TNS_MIN_LONG_LENGTH:
|
||||||
buf.write_ub4(TNS_MAX_LONG_LENGTH)
|
buf.write_ub4(TNS_MAX_LONG_LENGTH)
|
||||||
else:
|
else:
|
||||||
buf.write_ub4(var_impl.buffer_size)
|
buf.write_ub4(buffer_size)
|
||||||
if var_impl.is_array:
|
if var_impl.is_array:
|
||||||
buf.write_ub4(var_impl.num_elements)
|
buf.write_ub4(var_impl.num_elements)
|
||||||
else:
|
else:
|
||||||
|
@ -996,6 +1003,9 @@ cdef class MessageWithData(Message):
|
||||||
num_bytes = <uint32_t> len(lob_impl._locator)
|
num_bytes = <uint32_t> len(lob_impl._locator)
|
||||||
buf.write_ub4(num_bytes)
|
buf.write_ub4(num_bytes)
|
||||||
buf.write_bytes_chunked(lob_impl._locator)
|
buf.write_bytes_chunked(lob_impl._locator)
|
||||||
|
elif ora_type_num in (TNS_DATA_TYPE_ROWID, TNS_DATA_TYPE_UROWID):
|
||||||
|
temp_bytes = (<str> value).encode()
|
||||||
|
buf.write_bytes_chunked(temp_bytes)
|
||||||
else:
|
else:
|
||||||
errors._raise_err(errors.ERR_DB_TYPE_NOT_SUPPORTED,
|
errors._raise_err(errors.ERR_DB_TYPE_NOT_SUPPORTED,
|
||||||
name=var_impl.dbtype.name)
|
name=var_impl.dbtype.name)
|
||||||
|
|
|
@ -331,8 +331,10 @@ cdef class ThinPoolImpl(BasePoolImpl):
|
||||||
read_buf = conn_impl._protocol._read_buf
|
read_buf = conn_impl._protocol._read_buf
|
||||||
if not read_buf._session_needs_to_be_closed:
|
if not read_buf._session_needs_to_be_closed:
|
||||||
socket_list = [conn_impl._protocol._socket]
|
socket_list = [conn_impl._protocol._socket]
|
||||||
read_socks, _, _ = select.select(socket_list, [], [], 0)
|
while not read_buf._session_needs_to_be_closed:
|
||||||
if read_socks:
|
read_socks, _, _ = select.select(socket_list, [], [], 0)
|
||||||
|
if not read_socks:
|
||||||
|
break
|
||||||
read_buf.check_control_packet()
|
read_buf.check_control_packet()
|
||||||
if read_buf._session_needs_to_be_closed:
|
if read_buf._session_needs_to_be_closed:
|
||||||
with self._condition:
|
with self._condition:
|
||||||
|
|
|
@ -88,17 +88,18 @@ class ConnectionPool:
|
||||||
params_impl.set(kwargs)
|
params_impl.set(kwargs)
|
||||||
self._connection_type = \
|
self._connection_type = \
|
||||||
params_impl.connectiontype or connection_module.Connection
|
params_impl.connectiontype or connection_module.Connection
|
||||||
thin = driver_mode.check_and_return_mode()
|
with driver_mode.get_manager() as mode_mgr:
|
||||||
if dsn is not None:
|
thin = mode_mgr.thin
|
||||||
dsn = params_impl.parse_dsn(dsn, thin)
|
if dsn is not None:
|
||||||
if dsn is None:
|
dsn = params_impl.parse_dsn(dsn, thin)
|
||||||
dsn = params_impl.get_connect_string()
|
if dsn is None:
|
||||||
if thin:
|
dsn = params_impl.get_connect_string()
|
||||||
impl = thin_impl.ThinPoolImpl(dsn, params_impl)
|
if thin:
|
||||||
else:
|
impl = thin_impl.ThinPoolImpl(dsn, params_impl)
|
||||||
impl = thick_impl.ThickPoolImpl(dsn, params_impl)
|
else:
|
||||||
self._impl = impl
|
impl = thick_impl.ThickPoolImpl(dsn, params_impl)
|
||||||
self.session_callback = params_impl.session_callback
|
self._impl = impl
|
||||||
|
self.session_callback = params_impl.session_callback
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self._impl is not None:
|
if self._impl is not None:
|
||||||
|
@ -120,7 +121,7 @@ class ConnectionPool:
|
||||||
tag: str=None,
|
tag: str=None,
|
||||||
matchanytag: bool=False,
|
matchanytag: bool=False,
|
||||||
shardingkey: list=None,
|
shardingkey: list=None,
|
||||||
supershardingkey: list=None) -> Type["connection_module.Connection"]:
|
supershardingkey: list=None) -> "connection_module.Connection":
|
||||||
"""
|
"""
|
||||||
Acquire a connection from the pool and return it.
|
Acquire a connection from the pool and return it.
|
||||||
|
|
||||||
|
@ -177,7 +178,7 @@ class ConnectionPool:
|
||||||
self._impl.close(force)
|
self._impl.close(force)
|
||||||
self._impl = None
|
self._impl = None
|
||||||
|
|
||||||
def drop(self, connection: Type["connection_module.Connection"]) -> None:
|
def drop(self, connection: "connection_module.Connection") -> None:
|
||||||
"""
|
"""
|
||||||
Drop the connection from the pool, which is useful if the connection is
|
Drop the connection from the pool, which is useful if the connection is
|
||||||
no longer usable (such as when the database session is killed).
|
no longer usable (such as when the database session is killed).
|
||||||
|
@ -322,7 +323,7 @@ class ConnectionPool:
|
||||||
def ping_interval(self, value: int) -> None:
|
def ping_interval(self, value: int) -> None:
|
||||||
self._impl.set_ping_interval(value)
|
self._impl.set_ping_interval(value)
|
||||||
|
|
||||||
def release(self, connection: Type["connection_module.Connection"],
|
def release(self, connection: "connection_module.Connection",
|
||||||
tag: str=None) -> None:
|
tag: str=None) -> None:
|
||||||
"""
|
"""
|
||||||
Release the connection back to the pool now, rather than whenever
|
Release the connection back to the pool now, rather than whenever
|
||||||
|
|
|
@ -468,7 +468,7 @@ class PoolParams(ConnectParams):
|
||||||
"""
|
"""
|
||||||
return self._impl.wait_timeout
|
return self._impl.wait_timeout
|
||||||
|
|
||||||
def copy(self) -> Type["PoolParams"]:
|
def copy(self) -> "PoolParams":
|
||||||
"""
|
"""
|
||||||
Creates a copy of the parameters and returns it.
|
Creates a copy of the parameters and returns it.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
# SodaDatabase, SodaCollection, SodaDocument, SodaDocCursor and SodaOperation.
|
# SodaDatabase, SodaCollection, SodaDocument, SodaDocCursor and SodaOperation.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
from typing import Type, Union
|
from typing import Union, List
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from . import connection
|
from . import connection
|
||||||
|
@ -58,7 +58,7 @@ class SodaDatabase:
|
||||||
return json.dumps(content).encode()
|
return json.dumps(content).encode()
|
||||||
|
|
||||||
def createCollection(self, name: str, metadata: Union[str, dict]=None,
|
def createCollection(self, name: str, metadata: Union[str, dict]=None,
|
||||||
mapMode: bool=False) -> Type["SodaCollection"]:
|
mapMode: bool=False) -> "SodaCollection":
|
||||||
"""
|
"""
|
||||||
Creates a SODA collection with the given name and returns a new SODA
|
Creates a SODA collection with the given name and returns a new SODA
|
||||||
collection object. If you try to create a collection, and a collection
|
collection object. If you try to create a collection, and a collection
|
||||||
|
@ -85,7 +85,7 @@ class SodaDatabase:
|
||||||
return SodaCollection._from_impl(self, collection_impl)
|
return SodaCollection._from_impl(self, collection_impl)
|
||||||
|
|
||||||
def createDocument(self, content: object, key: str=None,
|
def createDocument(self, content: object, key: str=None,
|
||||||
mediaType: str="application/json") -> Type["SodaDocument"]:
|
mediaType: str="application/json") -> "SodaDocument":
|
||||||
"""
|
"""
|
||||||
Creates a SODA document usable for SODA write operations. You only need
|
Creates a SODA document usable for SODA write operations. You only need
|
||||||
to use this method if your collection requires client-assigned keys or
|
to use this method if your collection requires client-assigned keys or
|
||||||
|
@ -112,7 +112,8 @@ class SodaDatabase:
|
||||||
doc_impl = self._impl.create_document(content_bytes, key, mediaType)
|
doc_impl = self._impl.create_document(content_bytes, key, mediaType)
|
||||||
return SodaDocument._from_impl(doc_impl)
|
return SodaDocument._from_impl(doc_impl)
|
||||||
|
|
||||||
def getCollectionNames(self, startName: str=None, limit: int=0) -> list:
|
def getCollectionNames(self, startName: str=None,
|
||||||
|
limit: int=0) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Returns a list of the names of collections in the database that match
|
Returns a list of the names of collections in the database that match
|
||||||
the criteria, in alphabetical order.
|
the criteria, in alphabetical order.
|
||||||
|
@ -126,7 +127,7 @@ class SodaDatabase:
|
||||||
"""
|
"""
|
||||||
return self._impl.get_collection_names(startName, limit)
|
return self._impl.get_collection_names(startName, limit)
|
||||||
|
|
||||||
def openCollection(self, name: str) -> Type["SodaCollection"]:
|
def openCollection(self, name: str) -> "SodaCollection":
|
||||||
"""
|
"""
|
||||||
Opens an existing collection with the given name and returns a new SODA
|
Opens an existing collection with the given name and returns a new SODA
|
||||||
collection object. If a collection with that name does not exist, None
|
collection object. If a collection with that name does not exist, None
|
||||||
|
@ -191,7 +192,7 @@ class SodaCollection:
|
||||||
"""
|
"""
|
||||||
return self._impl.drop_index(name, force)
|
return self._impl.drop_index(name, force)
|
||||||
|
|
||||||
def find(self) -> Type["SodaOperation"]:
|
def find(self) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
This method is used to begin an operation that will act upon documents
|
This method is used to begin an operation that will act upon documents
|
||||||
in the collection. It creates and returns a SodaOperation object which
|
in the collection. It creates and returns a SodaOperation object which
|
||||||
|
@ -200,7 +201,7 @@ class SodaCollection:
|
||||||
"""
|
"""
|
||||||
return SodaOperation(self)
|
return SodaOperation(self)
|
||||||
|
|
||||||
def getDataGuide(self) -> Type["SodaDocument"]:
|
def getDataGuide(self) -> "SodaDocument":
|
||||||
"""
|
"""
|
||||||
Returns a SODA document object containing property names, data types
|
Returns a SODA document object containing property names, data types
|
||||||
and lengths inferred from the JSON documents in the collection. It can
|
and lengths inferred from the JSON documents in the collection. It can
|
||||||
|
@ -253,7 +254,7 @@ class SodaCollection:
|
||||||
self._impl.insert_one(doc_impl, hint=None, return_doc=False)
|
self._impl.insert_one(doc_impl, hint=None, return_doc=False)
|
||||||
|
|
||||||
def insertOneAndGet(self, doc: object,
|
def insertOneAndGet(self, doc: object,
|
||||||
hint: str=None) -> Type["SodaDocument"]:
|
hint: str=None) -> "SodaDocument":
|
||||||
"""
|
"""
|
||||||
Similarly to insertOne() this method inserts a given document into the
|
Similarly to insertOne() this method inserts a given document into the
|
||||||
collection. The only difference is that it returns a SODA Document
|
collection. The only difference is that it returns a SODA Document
|
||||||
|
@ -300,7 +301,7 @@ class SodaCollection:
|
||||||
doc_impl = self._process_doc_arg(doc)
|
doc_impl = self._process_doc_arg(doc)
|
||||||
self._impl.save(doc_impl, hint=None, return_doc=False)
|
self._impl.save(doc_impl, hint=None, return_doc=False)
|
||||||
|
|
||||||
def saveAndGet(self, doc: object, hint: str=None) -> Type["SodaDocument"]:
|
def saveAndGet(self, doc: object, hint: str=None) -> "SodaDocument":
|
||||||
"""
|
"""
|
||||||
Saves a document into the collection. This method is equivalent to
|
Saves a document into the collection. This method is equivalent to
|
||||||
insertOneAndGet() except that if client-assigned keys are used, and the
|
insertOneAndGet() except that if client-assigned keys are used, and the
|
||||||
|
@ -318,7 +319,7 @@ class SodaCollection:
|
||||||
doc_impl = self._process_doc_arg(doc)
|
doc_impl = self._process_doc_arg(doc)
|
||||||
if hint is not None and not isinstance(hint, str):
|
if hint is not None and not isinstance(hint, str):
|
||||||
raise TypeError("expecting a string")
|
raise TypeError("expecting a string")
|
||||||
return_doc_impl = self._impl.save(doc_impl, hint, return_doc=False)
|
return_doc_impl = self._impl.save(doc_impl, hint, return_doc=True)
|
||||||
return SodaDocument._from_impl(return_doc_impl)
|
return SodaDocument._from_impl(return_doc_impl)
|
||||||
|
|
||||||
def truncate(self) -> None:
|
def truncate(self) -> None:
|
||||||
|
@ -461,7 +462,7 @@ class SodaOperation:
|
||||||
"""
|
"""
|
||||||
return self._collection._impl.get_count(self)
|
return self._collection._impl.get_count(self)
|
||||||
|
|
||||||
def fetchArraySize(self, value: int) -> Type["SodaOperation"]:
|
def fetchArraySize(self, value: int) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
This is a tuning method to specify the number of documents that are
|
This is a tuning method to specify the number of documents that are
|
||||||
internally fetched in batches by calls to getCursor() and
|
internally fetched in batches by calls to getCursor() and
|
||||||
|
@ -480,7 +481,7 @@ class SodaOperation:
|
||||||
self._fetch_array_size = value
|
self._fetch_array_size = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def filter(self, value: Union[dict, str]) -> Type["SodaOperation"]:
|
def filter(self, value: Union[dict, str]) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
Sets a filter specification for complex document queries and ordering
|
Sets a filter specification for complex document queries and ordering
|
||||||
of JSON documents. Filter specifications must be provided as a
|
of JSON documents. Filter specifications must be provided as a
|
||||||
|
@ -499,7 +500,7 @@ class SodaOperation:
|
||||||
raise TypeError("expecting string or dictionary")
|
raise TypeError("expecting string or dictionary")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def getCursor(self) -> Type["SodaDocCursor"]:
|
def getCursor(self) -> "SodaDocCursor":
|
||||||
"""
|
"""
|
||||||
Returns a SodaDocCursor object that can be used to iterate over the
|
Returns a SodaDocCursor object that can be used to iterate over the
|
||||||
documents that match the criteria.
|
documents that match the criteria.
|
||||||
|
@ -513,7 +514,7 @@ class SodaOperation:
|
||||||
"""
|
"""
|
||||||
return [d for d in self.getCursor()]
|
return [d for d in self.getCursor()]
|
||||||
|
|
||||||
def getOne(self) -> Union[Type["SodaDocument"], None]:
|
def getOne(self) -> Union["SodaDocument", None]:
|
||||||
"""
|
"""
|
||||||
Returns a single SodaDocument object that matches the criteria. Note
|
Returns a single SodaDocument object that matches the criteria. Note
|
||||||
that if multiple documents match the criteria only the first one is
|
that if multiple documents match the criteria only the first one is
|
||||||
|
@ -523,7 +524,7 @@ class SodaOperation:
|
||||||
if doc_impl is not None:
|
if doc_impl is not None:
|
||||||
return SodaDocument._from_impl(doc_impl)
|
return SodaDocument._from_impl(doc_impl)
|
||||||
|
|
||||||
def hint(self, value: str) -> Type["SodaOperation"]:
|
def hint(self, value: str) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
Specifies a hint that will be provided to the SODA operation when it is
|
Specifies a hint that will be provided to the SODA operation when it is
|
||||||
performed. This is expected to be a string in the same format as SQL
|
performed. This is expected to be a string in the same format as SQL
|
||||||
|
@ -541,7 +542,7 @@ class SodaOperation:
|
||||||
self._hint = value
|
self._hint = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def key(self, value: str) -> Type["SodaOperation"]:
|
def key(self, value: str) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
Specifies that the document with the specified key should be returned.
|
Specifies that the document with the specified key should be returned.
|
||||||
This causes any previous calls made to this method and keys() to be
|
This causes any previous calls made to this method and keys() to be
|
||||||
|
@ -556,7 +557,7 @@ class SodaOperation:
|
||||||
self._keys = None
|
self._keys = None
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def keys(self, value: list) -> Type["SodaOperation"]:
|
def keys(self, value: list) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
Specifies that documents that match the keys found in the supplied
|
Specifies that documents that match the keys found in the supplied
|
||||||
sequence should be returned. This causes any previous calls made to
|
sequence should be returned. This causes any previous calls made to
|
||||||
|
@ -573,7 +574,7 @@ class SodaOperation:
|
||||||
self._key = None
|
self._key = None
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def limit(self, value: int) -> Type["SodaOperation"]:
|
def limit(self, value: int) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
Specifies that only the specified number of documents should be
|
Specifies that only the specified number of documents should be
|
||||||
returned. This method is only usable for read operations such as
|
returned. This method is only usable for read operations such as
|
||||||
|
@ -609,7 +610,7 @@ class SodaOperation:
|
||||||
return self._collection._impl.replace_one(self, doc_impl,
|
return self._collection._impl.replace_one(self, doc_impl,
|
||||||
return_doc=False)
|
return_doc=False)
|
||||||
|
|
||||||
def replaceOneAndGet(self, doc: object) -> Type["SodaDocument"]:
|
def replaceOneAndGet(self, doc: object) -> "SodaDocument":
|
||||||
"""
|
"""
|
||||||
Similarly to replaceOne(), this method replaces a single document in
|
Similarly to replaceOne(), this method replaces a single document in
|
||||||
the collection with the specified document. The only difference is that
|
the collection with the specified document. The only difference is that
|
||||||
|
@ -621,7 +622,7 @@ class SodaOperation:
|
||||||
return_doc=True)
|
return_doc=True)
|
||||||
return SodaDocument._from_impl(return_doc_impl)
|
return SodaDocument._from_impl(return_doc_impl)
|
||||||
|
|
||||||
def skip(self, value: int) -> Type["SodaOperation"]:
|
def skip(self, value: int) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
Specifies the number of documents that match the other criteria that
|
Specifies the number of documents that match the other criteria that
|
||||||
will be skipped. This method is only usable for read operations such as
|
will be skipped. This method is only usable for read operations such as
|
||||||
|
@ -636,7 +637,7 @@ class SodaOperation:
|
||||||
self._skip = value
|
self._skip = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def version(self, value: str) -> Type["SodaOperation"]:
|
def version(self, value: str) -> "SodaOperation":
|
||||||
"""
|
"""
|
||||||
Specifies that documents with the specified version should be returned.
|
Specifies that documents with the specified version should be returned.
|
||||||
Typically this is used with key() to implement optimistic locking, so
|
Typically this is used with key() to implement optimistic locking, so
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
# events are detected.
|
# events are detected.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
from typing import Callable, Type, Union
|
from typing import Callable, Union, List
|
||||||
from . import connection
|
from . import connection
|
||||||
|
|
||||||
class Subscription:
|
class Subscription:
|
||||||
|
@ -53,7 +53,7 @@ class Subscription:
|
||||||
return self._impl.callback
|
return self._impl.callback
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def connection(self) -> Type["connection.Connection"]:
|
def connection(self) -> "connection.Connection":
|
||||||
"""
|
"""
|
||||||
Returns the connection that was used to register the subscription when
|
Returns the connection that was used to register the subscription when
|
||||||
it was created.
|
it was created.
|
||||||
|
@ -172,7 +172,7 @@ class Message:
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def consumer_name(self) -> str:
|
def consumer_name(self) -> Union[str, None]:
|
||||||
"""
|
"""
|
||||||
Returns the name of the consumer which generated the notification. It
|
Returns the name of the consumer which generated the notification. It
|
||||||
will be populated if the subscription was created with the namespace
|
will be populated if the subscription was created with the namespace
|
||||||
|
@ -181,28 +181,29 @@ class Message:
|
||||||
return self._consumer_name
|
return self._consumer_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def consumerName(self) -> str:
|
def consumerName(self) -> Union[str, None]:
|
||||||
"""
|
"""
|
||||||
Deprecated. Use property consumer_name instead.
|
Deprecated. Use property consumer_name instead.
|
||||||
"""
|
"""
|
||||||
return self.consumer_name
|
return self.consumer_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dbname(self) -> str:
|
def dbname(self) -> Union[str, None]:
|
||||||
"""
|
"""
|
||||||
Returns the name of the database that generated the notification.
|
Returns the name of the database that generated the notification.
|
||||||
"""
|
"""
|
||||||
return self._db_name
|
return self._db_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def msgid(self) -> bytes:
|
def msgid(self) -> Union[bytes, None]:
|
||||||
"""
|
"""
|
||||||
Returns the message id of the AQ message that generated the notification.
|
Returns the message id of the AQ message that generated the
|
||||||
|
notification.
|
||||||
"""
|
"""
|
||||||
return self._msgid
|
return self._msgid
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def queries(self) -> list:
|
def queries(self) -> List["MessageQuery"]:
|
||||||
"""
|
"""
|
||||||
Returns a list of message query objects that give information about
|
Returns a list of message query objects that give information about
|
||||||
query result sets changed for this notification. This attribute will be
|
query result sets changed for this notification. This attribute will be
|
||||||
|
@ -212,7 +213,7 @@ class Message:
|
||||||
return self._queries
|
return self._queries
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def queue_name(self) -> str:
|
def queue_name(self) -> Union[str, None]:
|
||||||
"""
|
"""
|
||||||
Returns the name of the queue which generated the notification. It will
|
Returns the name of the queue which generated the notification. It will
|
||||||
only be populated if the subscription was created with the namespace
|
only be populated if the subscription was created with the namespace
|
||||||
|
@ -221,7 +222,7 @@ class Message:
|
||||||
return self._queue_name
|
return self._queue_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def queueName(self) -> str:
|
def queueName(self) -> Union[str, None]:
|
||||||
"""
|
"""
|
||||||
Deprecated. Use property queue_name instead.
|
Deprecated. Use property queue_name instead.
|
||||||
"""
|
"""
|
||||||
|
@ -247,7 +248,7 @@ class Message:
|
||||||
return self._subscription
|
return self._subscription
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tables(self) -> list:
|
def tables(self) -> List["MessageTable"]:
|
||||||
"""
|
"""
|
||||||
Returns a list of message table objects that give information about the
|
Returns a list of message table objects that give information about the
|
||||||
tables changed for this notification. This attribute will be an empty
|
tables changed for this notification. This attribute will be an empty
|
||||||
|
@ -257,14 +258,14 @@ class Message:
|
||||||
return self._tables
|
return self._tables
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def txid(self) -> bytes:
|
def txid(self) -> Union[bytes, None]:
|
||||||
"""
|
"""
|
||||||
Returns the id of the transaction that generated the notification.
|
Returns the id of the transaction that generated the notification.
|
||||||
"""
|
"""
|
||||||
return self._txid
|
return self._txid
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self) -> str:
|
def type(self) -> int:
|
||||||
"""
|
"""
|
||||||
Returns the type of message that has been sent.
|
Returns the type of message that has been sent.
|
||||||
"""
|
"""
|
||||||
|
@ -297,7 +298,7 @@ class MessageQuery:
|
||||||
return self._operation
|
return self._operation
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tables(self) -> list:
|
def tables(self) -> List["MessageTable"]:
|
||||||
"""
|
"""
|
||||||
Returns a list of message table objects that give information about the
|
Returns a list of message table objects that give information about the
|
||||||
table changes that caused the query result set to change for this
|
table changes that caused the query result set to change for this
|
||||||
|
@ -320,7 +321,7 @@ class MessageRow:
|
||||||
return self._operation
|
return self._operation
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rowid(self) -> str:
|
def rowid(self) -> Union[str, None]:
|
||||||
"""
|
"""
|
||||||
Returns the rowid of the row that was changed.
|
Returns the rowid of the row that was changed.
|
||||||
"""
|
"""
|
||||||
|
@ -335,7 +336,7 @@ class MessageTable:
|
||||||
self._rows = []
|
self._rows = []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> Union[str, None]:
|
||||||
"""
|
"""
|
||||||
Returns the name of the table that was changed.
|
Returns the name of the table that was changed.
|
||||||
"""
|
"""
|
||||||
|
@ -349,7 +350,7 @@ class MessageTable:
|
||||||
return self._operation
|
return self._operation
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rows(self) -> list:
|
def rows(self) -> List["MessageRow"]:
|
||||||
"""
|
"""
|
||||||
Returns a list of message row objects that give information about the
|
Returns a list of message row objects that give information about the
|
||||||
rows changed on the table. This value is only filled in if the qos
|
rows changed on the table. This value is only filled in if the qos
|
||||||
|
|
|
@ -30,4 +30,4 @@
|
||||||
# file doc/src/conf.py both reference this file directly.
|
# file doc/src/conf.py both reference this file directly.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
__version__ = "1.1.0"
|
__version__ = "1.1.1"
|
||||||
|
|
|
@ -194,5 +194,10 @@ class TestCase(test_env.BaseTestCase):
|
||||||
"1528 - test oracledb.ROWID pickling"
|
"1528 - test oracledb.ROWID pickling"
|
||||||
self.__test_pickle(oracledb.ROWID)
|
self.__test_pickle(oracledb.ROWID)
|
||||||
|
|
||||||
|
def test_1529_DB_TYPE_UROWID(self):
|
||||||
|
"1529 - test oracledb.DB_TYPE_UROWID comparisons and pickling"
|
||||||
|
self.__test_compare(oracledb.DB_TYPE_UROWID, oracledb.ROWID)
|
||||||
|
self.__test_pickle(oracledb.DB_TYPE_UROWID)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_env.run_test_cases()
|
test_env.run_test_cases()
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import unittest
|
||||||
|
|
||||||
import oracledb
|
import oracledb
|
||||||
import test_env
|
import test_env
|
||||||
|
@ -84,5 +85,90 @@ class TestCase(test_env.BaseTestCase):
|
||||||
val=rowid)
|
val=rowid)
|
||||||
self.assertEqual(self.cursor.fetchall(), [(int_val,)])
|
self.assertEqual(self.cursor.fetchall(), [(int_val,)])
|
||||||
|
|
||||||
|
def test_2904_select_rowids_as_rowids(self):
|
||||||
|
"2904 - test selecting regular rowids stored in a rowid column"
|
||||||
|
self.cursor.execute("truncate table TestRowids")
|
||||||
|
self.cursor.execute("""
|
||||||
|
insert into TestRowids (IntCol, RowidCol)
|
||||||
|
select IntCol, rowid from TestNumbers""")
|
||||||
|
self.connection.commit()
|
||||||
|
self.cursor.execute("select IntCol, RowidCol from TestRowids")
|
||||||
|
for int_val, rowid in self.cursor.fetchall():
|
||||||
|
self.cursor.execute("""
|
||||||
|
select IntCol
|
||||||
|
from TestNumbers
|
||||||
|
where rowid = :val""",
|
||||||
|
val=rowid)
|
||||||
|
self.assertEqual(self.cursor.fetchall(), [(int_val,)])
|
||||||
|
|
||||||
|
def test_2905_test_bind_and_insert_rowid(self):
|
||||||
|
"2905 - binding and inserting a rowid"
|
||||||
|
self.cursor.execute("truncate table TestRowids")
|
||||||
|
insert_data = [
|
||||||
|
(1, "String #1"), (2, "String #2"),
|
||||||
|
(3, "String #3"),(4, "String #4")
|
||||||
|
]
|
||||||
|
self.cursor.execute("truncate table TestTempTable")
|
||||||
|
sql = "insert into TestTempTable (IntCol, StringCol1) values (:1, :2)"
|
||||||
|
self.cursor.executemany(sql, insert_data)
|
||||||
|
self.connection.commit()
|
||||||
|
ridvar = self.cursor.var(oracledb.ROWID)
|
||||||
|
self.cursor.execute("""
|
||||||
|
begin
|
||||||
|
select rowid into :rid from TestTempTable
|
||||||
|
where IntCol = 3;
|
||||||
|
end;""",
|
||||||
|
rid=ridvar)
|
||||||
|
self.cursor.setinputsizes(r1=oracledb.ROWID)
|
||||||
|
self.cursor.execute("""
|
||||||
|
insert into TestRowids (IntCol, RowidCol)
|
||||||
|
values(1, :r1)""",
|
||||||
|
r1=ridvar)
|
||||||
|
self.connection.commit()
|
||||||
|
self.cursor.execute("select IntCol, RowidCol from TestRowids")
|
||||||
|
int_val, rowid = self.cursor.fetchone()
|
||||||
|
self.cursor.execute("""
|
||||||
|
select IntCol, StringCol1 from TestTempTable
|
||||||
|
where rowid = :val""",
|
||||||
|
val=rowid)
|
||||||
|
self.assertEqual(self.cursor.fetchone(), (3, "String #3"))
|
||||||
|
|
||||||
|
@unittest.skipIf(not test_env.get_is_thin(),
|
||||||
|
"thick mode doesn't support DB_TYPE_UROWID")
|
||||||
|
def test_2906_test_bind_and_insert_rowid_as_urowid(self):
|
||||||
|
"2906 - binding and inserting a rowid as urowid"
|
||||||
|
self.cursor.execute("truncate table TestRowids")
|
||||||
|
insert_data = [
|
||||||
|
(1, "String #1", datetime.datetime(2017, 4, 4)),
|
||||||
|
(2, "String #2", datetime.datetime(2017, 4, 5)),
|
||||||
|
(3, "String #3", datetime.datetime(2017, 4, 6)),
|
||||||
|
(4, "A" * 250, datetime.datetime(2017, 4, 7))
|
||||||
|
]
|
||||||
|
self.cursor.execute("truncate table TestUniversalRowids")
|
||||||
|
sql = "insert into TestUniversalRowids values (:1, :2, :3)"
|
||||||
|
self.cursor.executemany(sql, insert_data)
|
||||||
|
self.connection.commit()
|
||||||
|
ridvar = self.cursor.var(oracledb.DB_TYPE_UROWID)
|
||||||
|
self.cursor.execute("""
|
||||||
|
begin
|
||||||
|
select rowid into :rid from TestUniversalRowids
|
||||||
|
where IntCol = 3;
|
||||||
|
end;""",
|
||||||
|
rid=ridvar)
|
||||||
|
self.cursor.setinputsizes(r1=oracledb.DB_TYPE_UROWID)
|
||||||
|
self.cursor.execute("""
|
||||||
|
insert into TestRowids (IntCol, UrowidCol)
|
||||||
|
values(1, :r1)""",
|
||||||
|
r1=ridvar)
|
||||||
|
self.connection.commit()
|
||||||
|
self.cursor.execute("select IntCol, UrowidCol from TestRowids")
|
||||||
|
int_val, rowid = self.cursor.fetchone()
|
||||||
|
self.cursor.execute("""
|
||||||
|
select IntCol, StringCol, DateCol from TestUniversalRowids
|
||||||
|
where rowid = :val""",
|
||||||
|
val=rowid)
|
||||||
|
self.assertEqual(self.cursor.fetchone(),
|
||||||
|
(3, "String #3", datetime.datetime(2017, 4, 6)))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_env.run_test_cases()
|
test_env.run_test_cases()
|
||||||
|
|
|
@ -446,5 +446,46 @@ class TestCase(test_env.BaseTestCase):
|
||||||
result, = cursor.fetchone()
|
result, = cursor.fetchone()
|
||||||
self.assertTrue(hint in result.read())
|
self.assertTrue(hint in result.read())
|
||||||
|
|
||||||
|
def test_3420_save_and_get(self):
|
||||||
|
"3420 - test saveAndGet"
|
||||||
|
soda_db = self.get_soda_database(minclient=(19, 9))
|
||||||
|
coll = soda_db.createCollection("TestSodaSaveAndGet")
|
||||||
|
coll.find().remove()
|
||||||
|
values_to_save = [
|
||||||
|
dict(name="John", age=50),
|
||||||
|
soda_db.createDocument(dict(name="Mark", age=45)),
|
||||||
|
soda_db.createDocument(dict(name="Jill", age=32))
|
||||||
|
]
|
||||||
|
inserted_keys = []
|
||||||
|
for value in values_to_save:
|
||||||
|
doc = coll.saveAndGet(value)
|
||||||
|
inserted_keys.append(doc.key)
|
||||||
|
fetched_docs = coll.find().getDocuments()
|
||||||
|
self.connection.commit()
|
||||||
|
self.assertEqual(coll.find().count(), len(values_to_save))
|
||||||
|
for key, fetched_doc in zip(inserted_keys, fetched_docs):
|
||||||
|
doc = coll.find().key(key).getOne()
|
||||||
|
self.assertEqual(doc.getContent(), fetched_doc.getContent())
|
||||||
|
coll.drop()
|
||||||
|
|
||||||
|
def test_3421_insert_many_and_get(self):
|
||||||
|
"3421 - test insert many and get"
|
||||||
|
soda_db = self.get_soda_database(minclient=(18, 5))
|
||||||
|
coll = soda_db.createCollection("TestInsertManyAndGet")
|
||||||
|
values_to_insert = [
|
||||||
|
dict(name="George", age=25),
|
||||||
|
soda_db.createDocument(dict(name="Lucas", age=47))
|
||||||
|
]
|
||||||
|
docs = coll.insertManyAndGet(values_to_insert)
|
||||||
|
inserted_keys = [i.key for i in docs]
|
||||||
|
self.connection.commit()
|
||||||
|
self.assertEqual(coll.find().count(), len(values_to_insert))
|
||||||
|
for key, expected_doc in zip(inserted_keys, values_to_insert):
|
||||||
|
if isinstance(expected_doc, dict):
|
||||||
|
expected_doc = soda_db.createDocument(expected_doc)
|
||||||
|
doc = coll.find().key(key).getOne()
|
||||||
|
self.assertEqual(doc.getContent(), expected_doc.getContent())
|
||||||
|
coll.drop()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_env.run_test_cases()
|
test_env.run_test_cases()
|
||||||
|
|
|
@ -395,5 +395,12 @@ class TestCase(test_env.BaseTestCase):
|
||||||
results = self.cursor.fetchall()
|
results = self.cursor.fetchall()
|
||||||
self.assertEqual(results, [(None, None, None, None, None, None, None)])
|
self.assertEqual(results, [(None, None, None, None, None, None, None)])
|
||||||
|
|
||||||
|
@unittest.skipIf(not test_env.get_is_thin(),
|
||||||
|
"thick mode doesn't support DB_TYPE_UROWID")
|
||||||
|
def test_3725_DB_TYPE_UROWID(self):
|
||||||
|
"3725 - setting values on variables of type DB_TYPE_UROWID"
|
||||||
|
self._test_negative_set_and_get(oracledb.DB_TYPE_UROWID, 12345)
|
||||||
|
self._test_negative_set_and_get(oracledb.DB_TYPE_UROWID, "523lkhlf")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_env.run_test_cases()
|
test_env.run_test_cases()
|
||||||
|
|
|
@ -739,6 +739,7 @@ class TestCase(test_env.BaseTestCase):
|
||||||
admin_cursor.execute(sql)
|
admin_cursor.execute(sql)
|
||||||
self.assertRaisesRegex(oracledb.DatabaseError, "^DPY-4011:",
|
self.assertRaisesRegex(oracledb.DatabaseError, "^DPY-4011:",
|
||||||
cursor.execute, "select user from dual")
|
cursor.execute, "select user from dual")
|
||||||
|
self.assertFalse(conn.is_healthy())
|
||||||
|
|
||||||
def test_4359_kill_conn_in_context_manager(self):
|
def test_4359_kill_conn_in_context_manager(self):
|
||||||
"4359 - kill connection in cursor context manager"
|
"4359 - kill connection in cursor context manager"
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
from typing import Type, Union, Callable
|
from typing import Union, Callable
|
||||||
|
|
||||||
import oracledb
|
import oracledb
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class ConnectParams:
|
||||||
|
|
||||||
#{{ params_properties }}
|
#{{ params_properties }}
|
||||||
|
|
||||||
def copy(self) -> Type["ConnectParams"]:
|
def copy(self) -> "ConnectParams":
|
||||||
"""
|
"""
|
||||||
Creates a copy of the parameters and returns it.
|
Creates a copy of the parameters and returns it.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -62,7 +62,7 @@ class Connection:
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
dsn: str=None, *,
|
dsn: str=None, *,
|
||||||
pool: Type["pool_module.ConnectionPool"]=None,
|
pool: "pool_module.ConnectionPool"=None,
|
||||||
params: ConnectParams=None,
|
params: ConnectParams=None,
|
||||||
**kwargs) -> None:
|
**kwargs) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -97,51 +97,52 @@ class Connection:
|
||||||
self._impl = None
|
self._impl = None
|
||||||
|
|
||||||
# determine if thin mode is being used
|
# determine if thin mode is being used
|
||||||
thin = driver_mode.check_and_return_mode()
|
with driver_mode.get_manager() as mode_mgr:
|
||||||
|
thin = mode_mgr.thin
|
||||||
|
|
||||||
# determine which connection parameters to use
|
# determine which connection parameters to use
|
||||||
if params is None:
|
if params is None:
|
||||||
params_impl = base_impl.ConnectParamsImpl()
|
params_impl = base_impl.ConnectParamsImpl()
|
||||||
elif not isinstance(params, ConnectParams):
|
elif not isinstance(params, ConnectParams):
|
||||||
errors._raise_err(errors.ERR_INVALID_CONNECT_PARAMS)
|
errors._raise_err(errors.ERR_INVALID_CONNECT_PARAMS)
|
||||||
else:
|
|
||||||
params_impl = params._impl.copy()
|
|
||||||
if kwargs:
|
|
||||||
params_impl.set(kwargs)
|
|
||||||
if dsn is not None:
|
|
||||||
dsn = params_impl.parse_dsn(dsn, thin)
|
|
||||||
if dsn is None:
|
|
||||||
dsn = params_impl.get_connect_string()
|
|
||||||
|
|
||||||
# see if connection is being acquired from a pool
|
|
||||||
if pool is None:
|
|
||||||
pool_impl = None
|
|
||||||
elif not isinstance(pool, pool_module.ConnectionPool):
|
|
||||||
message = "pool must be an instance of oracledb.ConnectionPool"
|
|
||||||
raise TypeError(message)
|
|
||||||
else:
|
|
||||||
pool._verify_open()
|
|
||||||
pool_impl = pool._impl
|
|
||||||
|
|
||||||
# create thin or thick implementation object
|
|
||||||
if thin:
|
|
||||||
if pool is not None:
|
|
||||||
impl = pool_impl.acquire(params_impl)
|
|
||||||
else:
|
else:
|
||||||
impl = thin_impl.ThinConnImpl(dsn, params_impl)
|
params_impl = params._impl.copy()
|
||||||
impl.connect(params_impl)
|
if kwargs:
|
||||||
else:
|
params_impl.set(kwargs)
|
||||||
impl = thick_impl.ThickConnImpl(dsn, params_impl)
|
if dsn is not None:
|
||||||
impl.connect(params_impl, pool_impl)
|
dsn = params_impl.parse_dsn(dsn, thin)
|
||||||
self._impl = impl
|
if dsn is None:
|
||||||
self._version = None
|
dsn = params_impl.get_connect_string()
|
||||||
|
|
||||||
# invoke callback, if applicable
|
# see if connection is being acquired from a pool
|
||||||
if impl.invoke_session_callback and pool is not None \
|
if pool is None:
|
||||||
and pool.session_callback is not None \
|
pool_impl = None
|
||||||
and callable(pool.session_callback):
|
elif not isinstance(pool, pool_module.ConnectionPool):
|
||||||
pool.session_callback(self, params_impl.tag)
|
message = "pool must be an instance of oracledb.ConnectionPool"
|
||||||
impl.invoke_session_callback = False
|
raise TypeError(message)
|
||||||
|
else:
|
||||||
|
pool._verify_open()
|
||||||
|
pool_impl = pool._impl
|
||||||
|
|
||||||
|
# create thin or thick implementation object
|
||||||
|
if thin:
|
||||||
|
if pool is not None:
|
||||||
|
impl = pool_impl.acquire(params_impl)
|
||||||
|
else:
|
||||||
|
impl = thin_impl.ThinConnImpl(dsn, params_impl)
|
||||||
|
impl.connect(params_impl)
|
||||||
|
else:
|
||||||
|
impl = thick_impl.ThickConnImpl(dsn, params_impl)
|
||||||
|
impl.connect(params_impl, pool_impl)
|
||||||
|
self._impl = impl
|
||||||
|
self._version = None
|
||||||
|
|
||||||
|
# invoke callback, if applicable
|
||||||
|
if impl.invoke_session_callback and pool is not None \
|
||||||
|
and pool.session_callback is not None \
|
||||||
|
and callable(pool.session_callback):
|
||||||
|
pool.session_callback(self, params_impl.tag)
|
||||||
|
impl.invoke_session_callback = False
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self._impl is not None:
|
if self._impl is not None:
|
||||||
|
@ -500,7 +501,7 @@ class Connection:
|
||||||
This function performs a local check. To fully check a connection's
|
This function performs a local check. To fully check a connection's
|
||||||
health, use ping() which performs a round-trip to the database.
|
health, use ping() which performs a round-trip to the database.
|
||||||
"""
|
"""
|
||||||
return self._impl.get_is_healthy()
|
return self._impl is not None and self._impl.get_is_healthy()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ltxid(self) -> bytes:
|
def ltxid(self) -> bytes:
|
||||||
|
@ -601,7 +602,7 @@ class Connection:
|
||||||
"""
|
"""
|
||||||
return self.tpc_prepare()
|
return self.tpc_prepare()
|
||||||
|
|
||||||
def queue(self, name: str, payload_type: [DbObjectType, str]=None, *,
|
def queue(self, name: str, payload_type: Union[DbObjectType, str]=None, *,
|
||||||
payloadType: DbObjectType=None) -> Queue:
|
payloadType: DbObjectType=None) -> Queue:
|
||||||
"""
|
"""
|
||||||
Creates and returns a queue which is used to enqueue and dequeue
|
Creates and returns a queue which is used to enqueue and dequeue
|
||||||
|
@ -999,7 +1000,7 @@ def _connection_factory(f):
|
||||||
"""
|
"""
|
||||||
@functools.wraps(f)
|
@functools.wraps(f)
|
||||||
def connect(dsn: str=None, *,
|
def connect(dsn: str=None, *,
|
||||||
pool: Type["pool_module.ConnectionPool"]=None,
|
pool: "pool_module.ConnectionPool"=None,
|
||||||
conn_class: Type[Connection]=Connection,
|
conn_class: Type[Connection]=Connection,
|
||||||
params: ConnectParams=None,
|
params: ConnectParams=None,
|
||||||
**kwargs) -> Connection:
|
**kwargs) -> Connection:
|
||||||
|
@ -1012,7 +1013,7 @@ def _connection_factory(f):
|
||||||
|
|
||||||
@_connection_factory
|
@_connection_factory
|
||||||
def connect(dsn: str=None, *,
|
def connect(dsn: str=None, *,
|
||||||
pool: Type["pool_module.ConnectionPool"]=None,
|
pool: "pool_module.ConnectionPool"=None,
|
||||||
conn_class: Type[Connection]=Connection,
|
conn_class: Type[Connection]=Connection,
|
||||||
params: ConnectParams=None,
|
params: ConnectParams=None,
|
||||||
#{{ args_with_defaults }}
|
#{{ args_with_defaults }}
|
||||||
|
|
|
@ -86,17 +86,18 @@ class ConnectionPool:
|
||||||
params_impl.set(kwargs)
|
params_impl.set(kwargs)
|
||||||
self._connection_type = \
|
self._connection_type = \
|
||||||
params_impl.connectiontype or connection_module.Connection
|
params_impl.connectiontype or connection_module.Connection
|
||||||
thin = driver_mode.check_and_return_mode()
|
with driver_mode.get_manager() as mode_mgr:
|
||||||
if dsn is not None:
|
thin = mode_mgr.thin
|
||||||
dsn = params_impl.parse_dsn(dsn, thin)
|
if dsn is not None:
|
||||||
if dsn is None:
|
dsn = params_impl.parse_dsn(dsn, thin)
|
||||||
dsn = params_impl.get_connect_string()
|
if dsn is None:
|
||||||
if thin:
|
dsn = params_impl.get_connect_string()
|
||||||
impl = thin_impl.ThinPoolImpl(dsn, params_impl)
|
if thin:
|
||||||
else:
|
impl = thin_impl.ThinPoolImpl(dsn, params_impl)
|
||||||
impl = thick_impl.ThickPoolImpl(dsn, params_impl)
|
else:
|
||||||
self._impl = impl
|
impl = thick_impl.ThickPoolImpl(dsn, params_impl)
|
||||||
self.session_callback = params_impl.session_callback
|
self._impl = impl
|
||||||
|
self.session_callback = params_impl.session_callback
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self._impl is not None:
|
if self._impl is not None:
|
||||||
|
@ -118,7 +119,7 @@ class ConnectionPool:
|
||||||
tag: str=None,
|
tag: str=None,
|
||||||
matchanytag: bool=False,
|
matchanytag: bool=False,
|
||||||
shardingkey: list=None,
|
shardingkey: list=None,
|
||||||
supershardingkey: list=None) -> Type["connection_module.Connection"]:
|
supershardingkey: list=None) -> "connection_module.Connection":
|
||||||
"""
|
"""
|
||||||
Acquire a connection from the pool and return it.
|
Acquire a connection from the pool and return it.
|
||||||
|
|
||||||
|
@ -175,7 +176,7 @@ class ConnectionPool:
|
||||||
self._impl.close(force)
|
self._impl.close(force)
|
||||||
self._impl = None
|
self._impl = None
|
||||||
|
|
||||||
def drop(self, connection: Type["connection_module.Connection"]) -> None:
|
def drop(self, connection: "connection_module.Connection") -> None:
|
||||||
"""
|
"""
|
||||||
Drop the connection from the pool, which is useful if the connection is
|
Drop the connection from the pool, which is useful if the connection is
|
||||||
no longer usable (such as when the database session is killed).
|
no longer usable (such as when the database session is killed).
|
||||||
|
@ -320,7 +321,7 @@ class ConnectionPool:
|
||||||
def ping_interval(self, value: int) -> None:
|
def ping_interval(self, value: int) -> None:
|
||||||
self._impl.set_ping_interval(value)
|
self._impl.set_ping_interval(value)
|
||||||
|
|
||||||
def release(self, connection: Type["connection_module.Connection"],
|
def release(self, connection: "connection_module.Connection",
|
||||||
tag: str=None) -> None:
|
tag: str=None) -> None:
|
||||||
"""
|
"""
|
||||||
Release the connection back to the pool now, rather than whenever
|
Release the connection back to the pool now, rather than whenever
|
||||||
|
|
|
@ -66,7 +66,7 @@ class PoolParams(ConnectParams):
|
||||||
|
|
||||||
#{{ params_properties }}
|
#{{ params_properties }}
|
||||||
|
|
||||||
def copy(self) -> Type["PoolParams"]:
|
def copy(self) -> "PoolParams":
|
||||||
"""
|
"""
|
||||||
Creates a copy of the parameters and returns it.
|
Creates a copy of the parameters and returns it.
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue