From 4ed562c20567bb904d9d283029178723b4a5e626 Mon Sep 17 00:00:00 2001
From: Anthony Tuininga
Date: Tue, 18 May 2021 16:53:31 -0600
Subject: [PATCH] Documentation updates, including changes for PEP 8
compliance, to take into account the fact that the default branch has changed
to main, etc.
---
README.md | 10 +-
doc/src/api_manual/connection.rst | 7 +-
doc/src/api_manual/cursor.rst | 2 +-
doc/src/api_manual/deprecations.rst | 2 +-
doc/src/api_manual/module.rst | 14 +-
doc/src/api_manual/session_pool.rst | 24 +-
doc/src/api_manual/soda.rst | 30 +-
doc/src/conf.py | 4 +-
doc/src/release_notes.rst | 52 ++--
doc/src/user_guide/aq.rst | 53 ++--
doc/src/user_guide/batch_statement.rst | 52 ++--
doc/src/user_guide/bind.rst | 112 +++----
doc/src/user_guide/connection_handling.rst | 289 +++++++++++-------
doc/src/user_guide/cqn.rst | 24 +-
doc/src/user_guide/exception_handling.rst | 6 +-
doc/src/user_guide/globalization.rst | 19 +-
doc/src/user_guide/ha.rst | 2 +-
doc/src/user_guide/initialization.rst | 9 +-
doc/src/user_guide/installation.rst | 175 ++++++-----
doc/src/user_guide/introduction.rst | 28 +-
doc/src/user_guide/lob_data.rst | 64 ++--
doc/src/user_guide/plsql_execution.rst | 63 ++--
doc/src/user_guide/soda.rst | 110 +++----
doc/src/user_guide/sql_execution.rst | 78 ++---
doc/src/user_guide/startup.rst | 11 +-
doc/src/user_guide/tracing_sql.rst | 15 +-
doc/src/user_guide/tuning.rst | 14 +-
doc/src/user_guide/txn_management.rst | 8 +-
doc/src/user_guide/xml_data_type.rst | 12 +-
samples/README.md | 10 +-
...cle-Database-Scripting-for-the-Future.html | 6 +-
setup.cfg | 2 +-
test/README.md | 10 +-
33 files changed, 742 insertions(+), 575 deletions(-)
diff --git a/README.md b/README.md
index d80b919..0685f94 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ See [/test][11].
## Contributing
-See [CONTRIBUTING](https://github.com/oracle/python-cx_Oracle/blob/master/CONTRIBUTING.md)
+See [CONTRIBUTING](https://github.com/oracle/python-cx_Oracle/blob/main/CONTRIBUTING.md)
## License
@@ -47,13 +47,13 @@ cx_Oracle is licensed under a BSD license which you can find [here][3].
[1]: https://www.python.org/dev/peps/pep-0249
[2]: http://cx-oracle.readthedocs.io
-[3]: https://github.com/oracle/python-cx_Oracle/blob/master/LICENSE.txt
+[3]: https://github.com/oracle/python-cx_Oracle/blob/main/LICENSE.txt
[5]: http://lists.sourceforge.net/lists/listinfo/cx-oracle-users
-[6]: https://github.com/oracle/python-cx_Oracle/tree/master/samples/tutorial
+[6]: https://github.com/oracle/python-cx_Oracle/tree/main/samples/tutorial
[7]: http://cx-oracletools.sourceforge.net
[8]: http://cx-pyoraclelib.sourceforge.net
[9]: https://github.com/oracle/python-cx_Oracle/issues
-[11]: https://github.com/oracle/python-cx_Oracle/tree/master/test
-[12]: https://github.com/oracle/python-cx_Oracle/tree/master/samples
+[11]: https://github.com/oracle/python-cx_Oracle/tree/main/test
+[12]: https://github.com/oracle/python-cx_Oracle/tree/main/samples
[14]: https://cx-oracle.readthedocs.io/en/latest/release_notes.html
[15]: https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html
diff --git a/doc/src/api_manual/connection.rst b/doc/src/api_manual/connection.rst
index 5c74dad..4694822 100644
--- a/doc/src/api_manual/connection.rst
+++ b/doc/src/api_manual/connection.rst
@@ -74,13 +74,18 @@ Connection Object
that a single round-trip to the database may take before a timeout will
occur. A value of 0 means that no timeout will take place.
+ If a timeout occurs, the error *DPI-1067* will be returned if the
+ connection is still usable. Alternatively the error *DPI-1080* will be
+ returned if the connection has become invalid and can no longer be used.
+
.. versionadded:: 7.0
.. versionchanged:: 8.2
For consistency and compliance with the PEP 8 naming style, the
attribute `callTimeout` was renamed to `call_timeout`. The old name
- will continue to work for a period of time.
+ will continue to work for a period of time. The error *DPI-1080* was
+ also introduced in this release.
.. note::
diff --git a/doc/src/api_manual/cursor.rst b/doc/src/api_manual/cursor.rst
index 31b2fef..b89b2f1 100644
--- a/doc/src/api_manual/cursor.rst
+++ b/doc/src/api_manual/cursor.rst
@@ -67,7 +67,7 @@ Cursor Object
Array variables can only be used for PL/SQL associative arrays with
contiguous keys. For PL/SQL associative arrays with sparsely populated keys
or for varrays and nested tables, the approach shown in this
- `example `__ needs to be used.
.. note::
diff --git a/doc/src/api_manual/deprecations.rst b/doc/src/api_manual/deprecations.rst
index 982a71a..e2b7a2f 100644
--- a/doc/src/api_manual/deprecations.rst
+++ b/doc/src/api_manual/deprecations.rst
@@ -35,7 +35,7 @@ if applicable. The most recent deprecations are listed first.
* - Positional parameters to :meth:`cx_Oracle.connect()`
- Replace with keyword parameters in order to comply with the Python
database API.
- * - positional parameters to :meth:`cx_Oracle.SessionPool()`
+ * - Positional parameters to :meth:`cx_Oracle.SessionPool()`
- Replace with keyword parameters in order to comply with the Python
database API.
* - `threaded` parameter to :meth:`cx_Oracle.SessionPool()`
diff --git a/doc/src/api_manual/module.rst b/doc/src/api_manual/module.rst
index cdfd5dc..daad2fa 100644
--- a/doc/src/api_manual/module.rst
+++ b/doc/src/api_manual/module.rst
@@ -97,7 +97,7 @@ Module Interface
See the :ref:`globalization ` section for details on the
encoding and nencoding parameters. Note the default encoding and nencoding
values changed to "UTF-8" in cx_Oracle 8, and any character set in NLS_LANG
- is ignored.
+ is ignored. In a future release of cx_Oracle, only UTF-8 will be supported.
The edition parameter is expected to be a string if specified and sets the
edition to use for the session. It is only relevant if both the client and
@@ -208,7 +208,7 @@ Module Interface
.. function:: SessionPool(user=None, password=None, dsn=None, min=1, max=2, \
- increment=1, connectiontype=cx_Oracle.Connection, threaded=False, \
+ increment=1, connectiontype=cx_Oracle.Connection, threaded=True, \
getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT, events=False, \
homogeneous=True, externalauth=False, encoding=None, nencoding=None, \
edition=None, timeout=0, wait_timeout=0, max_lifetime_session=0, \
@@ -275,7 +275,8 @@ Module Interface
values transferred between cx_Oracle and Oracle Database, see
:ref:`Character Sets and Globalization `. Note the default
encoding and nencoding values changed to "UTF-8" in cx_Oracle 8, and any
- character set in NLS_LANG is ignored.
+ character set in NLS_LANG is ignored. In a future release of cx_Oracle,
+ only UTF-8 will be supported.
The edition parameter is expected to be a string, if specified, and sets the
edition to use for the sessions in the pool. It is only relevant if both the
@@ -285,7 +286,9 @@ Module Interface
The timeout parameter is expected to be an integer, if specified, and sets
the length of time (in seconds) after which idle sessions in the pool are
terminated. Note that termination only occurs when the pool is accessed.
- The default value of 0 means that no idle sessions are terminated.
+ The default value of 0 means that no idle sessions are terminated. The
+ initial pool timeout must be non-zero if you subsequently want to change
+ the timeout with :meth:`SessionPool.reconfigure()`.
The wait_timeout parameter is expected to be an integer, if specified, and
sets the length of time (in milliseconds) that the caller should wait for
@@ -350,7 +353,8 @@ Module Interface
`session_callback` and the parameter `maxSessionsPerShard` was renamed
to `max_sessions_per_shard`. The old names will continue to work as
keyword parameters for a period of time. The `threaded` parameter value
- is ignored and threading is always enabled.
+ is ignored and threading is always enabled; in previous versions the
+ default was False.
.. function:: Time(hour, minute, second)
diff --git a/doc/src/api_manual/session_pool.rst b/doc/src/api_manual/session_pool.rst
index fc9cd92..83e2f3e 100644
--- a/doc/src/api_manual/session_pool.rst
+++ b/doc/src/api_manual/session_pool.rst
@@ -71,6 +71,20 @@ SessionPool Object
connection has been established.
+.. attribute:: SessionPool.getmode
+
+ This read-write attribute determines how connections are returned from the
+ pool. If :data:`~cx_Oracle.SPOOL_ATTRVAL_FORCEGET` is specified, a new
+ connection will be returned even if there are no free sessions in the pool.
+ :data:`~cx_Oracle.SPOOL_ATTRVAL_NOWAIT` will raise an exception if there
+ are no free sessions are available in the pool. If
+ :data:`~cx_Oracle.SPOOL_ATTRVAL_WAIT` is specified and there are no free
+ sessions in the pool, the caller will wait until a free session is
+ available. :data:`~cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT` uses the value of
+ :data:`~SessionPool.wait_timeout` to determine how long the caller should
+ wait for a session to become available before returning an error.
+
+
.. attribute:: SessionPool.homogeneous
This read-write boolean attribute indicates whether the pool is considered
@@ -128,11 +142,11 @@ SessionPool Object
This read-write integer attribute specifies the pool ping interval in
seconds. When a connection is acquired from the pool, a check is first made
to see how long it has been since the connection was put into the pool. If
- this idle time exceeds ``ping_interval``, then a :ref:`round-trip `
- ping to the database is performed. If the connection is unusable, it is
- discarded and a different connection is selected to be returned by
- :meth:`SessionPool.acquire()`. Setting ``ping_interval`` to a negative
- value disables pinging. Setting it to 0 forces a ping for every
+ this idle time exceeds ``ping_interval``, then a :ref:`round-trip
+ ` ping to the database is performed. If the connection is
+ unusable, it is discarded and a different connection is selected to be
+ returned by :meth:`SessionPool.acquire()`. Setting ``ping_interval`` to a
+ negative value disables pinging. Setting it to 0 forces a ping for every
``aquire()`` and is not recommended.
Prior to cx_Oracle 8.2, the ping interval was fixed at 60 seconds.
diff --git a/doc/src/api_manual/soda.rst b/doc/src/api_manual/soda.rst
index 19f21b7..f71d06f 100644
--- a/doc/src/api_manual/soda.rst
+++ b/doc/src/api_manual/soda.rst
@@ -256,9 +256,11 @@ SODA Collection Object
The hint parameter, if specified, supplies a hint to the database when
processing the SODA operation. This is expected to be a string in the same
- format as SQL hints but without the enclosing comment characters. Use of
- this parameter requires Oracle Client 21.3 or higher (or Oracle Client 19
- from 19.11).
+ format as SQL hints but without any comment characters, for example
+ ``hint="MONITOR"``. While you could use this to pass any SQL hint, the
+ hints ``MONITOR`` (turn on monitoring) and ``NO_MONITOR`` (turn off
+ monitoring) are the most useful. Use of the hint parameter requires Oracle
+ Client 21.3 or higher (or Oracle Client 19 from 19.11).
.. note::
@@ -288,9 +290,11 @@ SODA Collection Object
The hint parameter, if specified, supplies a hint to the database when
processing the SODA operation. This is expected to be a string in the same
- format as SQL hints but without the enclosing comment characters. Use of
- this parameter requires Oracle Client 21.3 or higher (or Oracle Client 19
- from 19.11).
+ format as SQL hints but without any comment characters, for example
+ ``hint="MONITOR"``. While you could use this to pass any SQL hint, the
+ hints ``MONITOR`` (turn on monitoring) and ``NO_MONITOR`` (turn off
+ monitoring) are the most useful. Use of the hint parameter requires Oracle
+ Client 21.3 or higher (or Oracle Client 19 from 19.11).
.. versionadded:: 7.0
@@ -339,9 +343,11 @@ SODA Collection Object
The hint parameter, if specified, supplies a hint to the database when
processing the SODA operation. This is expected to be a string in the same
- format as SQL hints but without the enclosing comment characters. Use of
- this parameter requires Oracle Client 21.3 or higher (or Oracle Client 19
- from 19.11).
+ format as SQL hints but without any comment characters, for example
+ ``hint="MONITOR"``. While you could use this to pass any SQL hint, the
+ hints ``MONITOR`` (turn on monitoring) and ``NO_MONITOR`` (turn off
+ monitoring) are the most useful. Use of the hint parameter requires Oracle
+ Client 21.3 or higher (or Oracle Client 19 from 19.11).
This method requires Oracle Client 19.9 or higher in addition to the usual
SODA requirements.
@@ -560,8 +566,10 @@ SODA Operation Object
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 hints
- but without the enclosing comment characters. Use of this method
- requires Oracle Client 21.3 or higher (or Oracle Client 19 from 19.11).
+ but without any comment characters. While you could use this to pass any SQL
+ hint, the hints ``MONITOR`` (turn on monitoring) and ``NO_MONITOR`` (turn
+ off monitoring) are the most useful. Use of this method requires Oracle
+ Client 21.3 or higher (or Oracle Client 19 from 19.11).
As a convenience, the SodaOperation object is returned so that further
criteria can be specified by chaining methods together.
diff --git a/doc/src/conf.py b/doc/src/conf.py
index 33c5676..dc8e6d2 100644
--- a/doc/src/conf.py
+++ b/doc/src/conf.py
@@ -28,8 +28,8 @@ templates_path = ['.templates']
# The suffix of source filenames.
source_suffix = '.rst'
-# The master toctree document.
-master_doc = 'index'
+# The main toctree document.
+main_doc = 'index'
# General substitutions.
project = 'cx_Oracle'
diff --git a/doc/src/release_notes.rst b/doc/src/release_notes.rst
index df69525..ecbf2ab 100644
--- a/doc/src/release_notes.rst
+++ b/doc/src/release_notes.rst
@@ -5,23 +5,16 @@
cx_Oracle Release Notes
=======================
+For any deprecations, see :ref:`Deprecations `.
+
Version 8.2 (TBD)
-----------------
#) Updated embedded ODPI-C to `version 4.2.0
`__.
-#) Added :ref:`SODA metadata cache ` support to connection
- pools. This significantly improves the performance of methods
- :meth:`SodaDatabase.createCollection()` (when not specifying a value for
- the metadata parameter) and :meth:`SodaDatabase.openCollection()`. Caching
- is available when using Oracle Client version 19.11 and higher.
-#) Added support for supplying hints to SODA operations. A new non-terminal
- method :meth:`~SodaOperation.hint()` was added and a `hint` parameter was
- added to the methods :meth:`SodaCollection.insertOneAndGet()`,
- :meth:`SodaCollection.insertManyAndGet()` and
- :meth:`SodaCollection.saveAndGet()`. All of these require Oracle Client
- 21.3 or higher (or Oracle Client 19 from 19.11).
+#) Threaded mode is now always enabled when creating connection pools with
+ :meth:`cx_Oracle.SessionPool()`. Any `threaded` parameter value is ignored.
#) Added parameter `stmtcachesize` to :meth:`cx_Oracle.connect()` and
:meth:`cx_Oracle.SessionPool()` in order to permit specifying the size of
the statement cache during the creation of pools and standalone
@@ -31,20 +24,39 @@ Version 8.2 (TBD)
attribute :data:`SessionPool.ping_interval` was added in order to permit
making adjustments after the pool has been created. In previous cx_Oracle
releases a fixed ping interval of 60 seconds was used.
+#) Added parameter `soda_metadata_cache` to :meth:`cx_Oracle.SessionPool()` for
+ :ref:`SODA metadata cache ` support. In addition, the
+ attribute :data:`SessionPool.soda_metadata_cache` was added in order to
+ permit making adjustments after the pool has been created. This feature
+ significantly improves the performance of methods
+ :meth:`SodaDatabase.createCollection()` (when not specifying a value for the
+ metadata parameter) and :meth:`SodaDatabase.openCollection()`. Caching is
+ available when using Oracle Client version 19.11 and higher.
+#) Added support for supplying hints to SODA operations. A new non-terminal
+ method :meth:`~SodaOperation.hint()` was added and a `hint` parameter was
+ added to the methods :meth:`SodaCollection.insertOneAndGet()`,
+ :meth:`SodaCollection.insertManyAndGet()` and
+ :meth:`SodaCollection.saveAndGet()`. All of these require Oracle Client
+ 21.3 or higher (or Oracle Client 19 from 19.11).
#) Added parameter `bypass_decode` to :meth:`Cursor.var()` in order to allow
the `decode` step to be bypassed when converting data from Oracle Database
into Python strings
(`issue 385 `__).
Initial work was done in `PR 549
`__.
-#) Threaded mode is now always enabled when creating connection pools with
- :meth:`cx_Oracle.SessionPool()`. Any `threaded` parameter value is ignored.
+#) Enhanced dead connection detection. If an Oracle Database error indicates
+ that a connection is no longer usable, the error `DPI-1080: connection was
+ closed by ORA-%d` is now returned. The `%d` will be the Oracle error
+ causing the connection to be closed. Using the connection after this will
+ give `DPI-1010: not connected`. This behavior also applies for
+ :data:`Connection.call_timeout` errors that result in an unusable
+ connection.
#) Eliminated a memory leak when calling :meth:`SodaOperation.filter()` with a
dictionary.
#) The distributed transaction handle assosciated with the connection is now
cleared on commit or rollback (`issue 530
`__).
-#) Added check to ensure that when setting variables or object attributes, the
+#) Added a check to ensure that when setting variables or object attributes, the
type of the temporary LOB must match the expected type.
#) A small number of parameter, method, and attribute names were updated to
follow the PEP 8 style guide. This brings better consistency to the
@@ -1020,10 +1032,10 @@ Version 6.0 beta 1 (April 2017)
tagging.
#) Added parameter edition to the :meth:`cx_Oracle.SessionPool` method.
#) Added support for
- `universal rowids `__.
#) Added support for `DML Returning of multiple rows
- `__.
#) Added attributes :attr:`Variable.actualElements` and
:attr:`Variable.values` to variables.
@@ -1053,19 +1065,19 @@ Version 6.0 beta 1 (April 2017)
#) Dropped deprecated parameters action, module and clientinfo from the
:meth:`cx_Oracle.connect` method. The appcontext parameter should be used
instead as shown in this `sample `__.
+ python-cx_Oracle/blob/main/samples/app_context.py>`__.
#) Dropped deprecated attribute numbersAsString from
:ref:`cursor objects `. Use an output type handler instead as
shown in this `sample `__.
+ main/samples/return_numbers_as_decimals.py>`__.
#) Dropped deprecated attributes cqqos and rowids from
:ref:`subscription objects `. Use the qos attribute instead as
shown in this `sample `__.
+ main/samples/cqn.py>`__.
#) Dropped deprecated parameters cqqos and rowids from the
:meth:`Connection.subscribe()` method. Use the qos parameter instead as
shown in this `sample `__.
+ main/samples/cqn.py>`__.
Version 5.3 (March 2017)
diff --git a/doc/src/user_guide/aq.rst b/doc/src/user_guide/aq.rst
index 3c237ed..2214e78 100644
--- a/doc/src/user_guide/aq.rst
+++ b/doc/src/user_guide/aq.rst
@@ -14,7 +14,7 @@ cx_Oracle 7.2 introduced an updated interface for Oracle Advanced
Queuing.
There are Advanced Queuing examples in the `GitHub examples
-`__ directory.
+`__ directory.
Creating a Queue
@@ -46,7 +46,7 @@ queue can be used for enqueuing, dequeuing, or both as needed.
queue = connection.queue("DEMO_RAW_QUEUE")
-Now messages can be queued using :meth:`Queue.enqOne()`. To send three
+Now messages can be queued using :meth:`~Queue.enqone()`. To send three
messages:
.. code-block:: python
@@ -57,7 +57,7 @@ messages:
"The third message"
]
for data in PAYLOAD_DATA:
- queue.enqOne(connection.msgproperties(payload=data))
+ queue.enqone(connection.msgproperties(payload=data))
connection.commit()
Since the queue sending the messages is a RAW queue, the strings in this
@@ -69,7 +69,7 @@ Dequeuing Messages
==================
Dequeuing is performed similarly. To dequeue a message call the method
-:meth:`Queue.deqOne()` as shown. Note that if the message is expected to be a
+:meth:`~Queue.deqone()` as shown. Note that if the message is expected to be a
string, the bytes must be decoded using :attr:`Connection.encoding`.
.. code-block:: python
@@ -110,25 +110,25 @@ You can queue messages:
.. code-block:: python
- booksType = connection.gettype("UDT_BOOK")
- queue = connection.queue("DEMO_BOOK_QUEUE", booksType)
+ book_type = connection.gettype("UDT_BOOK")
+ queue = connection.queue("DEMO_BOOK_QUEUE", book_type)
- book = booksType.newobject()
+ book = book_type.newobject()
book.TITLE = "Quick Brown Fox"
book.AUTHORS = "The Dog"
book.PRICE = 123
- queue.enqOne(connection.msgproperties(payload=book))
+ queue.enqone(connection.msgproperties(payload=book))
connection.commit()
Dequeuing is done like this:
.. code-block:: python
- booksType = connection.gettype("UDT_BOOK")
- queue = connection.queue("DEMO_BOOK_QUEUE", booksType)
+ book_type = connection.gettype("UDT_BOOK")
+ queue = connection.queue("DEMO_BOOK_QUEUE", book_type)
- msg = queue.deqOne()
+ msg = queue.deqone()
connection.commit()
print(msg.payload.TITLE) # will print Quick Brown Fox
@@ -148,7 +148,7 @@ messages:
.. code-block:: python
queue = connection.queue("DEMO_RAW_QUEUE")
- queue.enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
+ queue.enqoptions.visibility = cx_Oracle.ENQ_IMMEDIATE
Dequeue options can also be set. For example, to specify not to block on
dequeuing if no messages are available:
@@ -156,14 +156,14 @@ dequeuing if no messages are available:
.. code-block:: python
queue = connection.queue("DEMO_RAW_QUEUE")
- queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
+ queue.deqoptions.wait = cx_Oracle.DEQ_NO_WAIT
Message properties can be set when enqueuing. For example, to set an
expiration of 60 seconds on a message:
.. code-block:: python
- queue.enqOne(connection.msgproperties(payload="Message", expiration=60))
+ queue.enqone(connection.msgproperties(payload="Message", expiration=60))
This means that if no dequeue operation occurs within 60 seconds that the
message will be dropped from the queue.
@@ -172,10 +172,10 @@ message will be dropped from the queue.
Bulk Enqueue and Dequeue
========================
-The :meth:`Queue.enqMany()` and :meth:`Queue.deqMany()` methods can be used for
-efficient bulk message handling.
+The :meth:`~Queue.enqmany()` and :meth:`~Queue.deqmany()` methods can be used
+for efficient bulk message handling.
-:meth:`Queue.enqMany()` is similar to :meth:`Queue.enqOne()` but accepts an
+:meth:`~Queue.enqmany()` is similar to :meth:`~Queue.enqone()` but accepts an
array of messages:
.. code-block:: python
@@ -186,22 +186,25 @@ array of messages:
"The third message",
]
queue = connection.queue("DEMO_RAW_QUEUE")
- queue.enqMany(connection.msgproperties(payload=m) for m in messages)
+ queue.enqmany(connection.msgproperties(payload=m) for m in messages)
connection.commit()
-Warning: calling :meth:`Queue.enqMany()` in parallel on different connections
-acquired from the same pool may fail due to Oracle bug 29928074. Ensure that
-this function is not run in parallel, use standalone connections or connections
-from different pools, or make multiple calls to :meth:`Queue.enqOne()` instead.
-The function :meth:`Queue.deqMany()` call is not affected.
+.. warning::
-To dequeue multiple messages at one time, use :meth:`Queue.deqMany()`. This
+ Calling :meth:`~Queue.enqmany()` in parallel on different connections
+ acquired from the same pool may fail due to Oracle bug 29928074. Ensure
+ that this function is not run in parallel, use standalone connections or
+ connections from different pools, or make multiple calls to
+ :meth:`~Queue.enqone()` instead. The function :meth:`~Queue.deqmany()` call
+ is not affected.
+
+To dequeue multiple messages at one time, use :meth:`~Queue.deqmany()`. This
takes an argument specifying the maximum number of messages to dequeue at one
time:
.. code-block:: python
- for m in queue.deqMany(maxMessages=10):
+ for m in queue.deqmany(10):
print(m.payload.decode(connection.encoding))
Depending on the queue properties and the number of messages available to
diff --git a/doc/src/user_guide/batch_statement.rst b/doc/src/user_guide/batch_statement.rst
index 19dc472..efa1d15 100644
--- a/doc/src/user_guide/batch_statement.rst
+++ b/doc/src/user_guide/batch_statement.rst
@@ -12,7 +12,7 @@ The :meth:`~Cursor.executemany()` method can also be used to execute PL/SQL
statements multiple times at once.
There are examples in the `GitHub examples
-`__
+`__
directory.
The following tables will be used in the samples that follow:
@@ -42,14 +42,14 @@ The following example inserts five rows into the table ``ParentTable``:
.. code-block:: python
- dataToInsert = [
+ data = [
(10, 'Parent 10'),
(20, 'Parent 20'),
(30, 'Parent 30'),
(40, 'Parent 40'),
(50, 'Parent 50')
]
- cursor.executemany("insert into ParentTable values (:1, :2)", dataToInsert)
+ cursor.executemany("insert into ParentTable values (:1, :2)", data)
This code requires only one :ref:`round-trip ` from the client to
the database instead of the five round-trips that would be required for
@@ -70,14 +70,14 @@ example:
.. code-block:: python
- dataToInsert = [
+ data = [
(10, 'Parent 10'),
(20, 'Parent 20'),
(30, 'Parent 30'),
(40, 'Parent 40'),
(50, 'Parent 50')
]
- cursor.executemany("begin mypkg.create_parent(:1, :2); end;", dataToInsert)
+ cursor.executemany("begin mypkg.create_parent(:1, :2); end;", data)
Note that the ``batcherrors`` parameter (discussed below) cannot be used with
PL/SQL block execution.
@@ -104,7 +104,7 @@ This example shows how data errors can be identified:
.. code-block:: python
- dataToInsert = [
+ data = [
(60, 'Parent 60'),
(70, 'Parent 70'),
(70, 'Parent 70 (duplicate)'),
@@ -112,8 +112,8 @@ This example shows how data errors can be identified:
(80, 'Parent 80 (duplicate)'),
(90, 'Parent 90')
]
- cursor.executemany("insert into ParentTable values (:1, :2)", dataToInsert,
- batcherrors=True)
+ cursor.executemany("insert into ParentTable values (:1, :2)", data,
+ batcherrors=True)
for error in cursor.getbatcherrors():
print("Error", error.message, "at row offset", error.offset)
@@ -142,16 +142,16 @@ affected by each row of data that is bound you must set the parameter
.. code-block:: python
- parentIdsToDelete = [20, 30, 50]
+ parent_ids_to_delete = [20, 30, 50]
cursor.executemany("delete from ChildTable where ParentId = :1",
- [(i,) for i in parentIdsToDelete],
- arraydmlrowcounts=True)
- rowCounts = cursor.getarraydmlrowcounts()
- for parentId, count in zip(parentIdsToDelete, rowCounts):
- print("Parent ID:", parentId, "deleted", count, "rows.")
+ [(i,) for i in parent_ids_to_delete],
+ arraydmlrowcounts=True)
+ row_counts = cursor.getarraydmlrowcounts()
+ for parent_id, count in zip(parent_ids_to_delete, row_counts):
+ print("Parent ID:", parent_id, "deleted", count, "rows.")
Using the data found in the `GitHub samples
-`__ the output
+`__ the output
is as follows::
Parent ID: 20 deleted 3 rows.
@@ -172,17 +172,17 @@ you could use the following code:
.. code-block:: python
- parentIdsToDelete = [20, 30, 50]
- childIdVar = cursor.var(int, arraysize=len(parentIdsToDelete))
- cursor.setinputsizes(None, childIdVar)
+ parent_ids_to_delete = [20, 30, 50]
+ child_id_var = cursor.var(int, arraysize=len(parent_ids_to_delete))
+ cursor.setinputsizes(None, child_id_var)
cursor.executemany("""
delete from ChildTable
where ParentId = :1
returning ChildId into :2""",
- [(i,) for i in parentIdsToDelete])
- for ix, parentId in enumerate(parentIdsToDelete):
- print("Child IDs deleted for parent ID", parentId, "are",
- childIdVar.getvalue(ix))
+ [(i,) for i in parent_ids_to_delete])
+ for ix, parent_id in enumerate(parent_ids_to_delete):
+ print("Child IDs deleted for parent ID", parent_id, "are",
+ child_id_var.getvalue(ix))
The output would then be::
@@ -216,10 +216,10 @@ Consider the following code:
.. code-block:: python
data = [
- ( 110, "Parent 110"),
- ( 2000, "Parent 2000"),
- ( 30000, "Parent 30000"),
- ( 400000, "Parent 400000"),
+ (110, "Parent 110"),
+ (2000, "Parent 2000"),
+ (30000, "Parent 30000"),
+ (400000, "Parent 400000"),
(5000000, "Parent 5000000")
]
cursor.setinputsizes(None, 20)
diff --git a/doc/src/user_guide/bind.rst b/doc/src/user_guide/bind.rst
index 325abf8..27fbfc1 100644
--- a/doc/src/user_guide/bind.rst
+++ b/doc/src/user_guide/bind.rst
@@ -29,7 +29,7 @@ statements:
# !! Never do this !!
sql = f"""insert into departments (department_id, department_name)
- values ({did}, {dnm})"""
+ values ({did}, '{dnm}')"""
cursor.execute(sql)
Bind variables reduce parsing and execution costs when statements are executed
@@ -58,7 +58,7 @@ bind variables in a statement are associated with a name. For example:
# alternatively, the parameters can be passed as a dictionary instead of as
# keyword parameters
- data = { "dept_id": 280, "dept_name": "Facility" }
+ data = dict(dept_id=280, dept_name="Facility")
cursor.execute("""
insert into departments (department_id, department_name)
values (:dept_id, :dept_name)""", data)
@@ -105,12 +105,13 @@ integers 8 and 7 and stores the result in an OUT bind variable of type integer:
.. code-block:: python
- outVal = cursor.var(int)
+ out_val = cursor.var(int)
cursor.execute("""
begin
- :outVal := :inBindVar1 + :inBindVar2;
- end;""", outVal=outVal, inBindVar1=8, inBindVar2=7)
- print(outVal.getvalue()) # will print 15
+ :out_val := :in_bind_var1 + :in_bind_var2;
+ end;""",
+ out_val=out_val, in_bind_var1=8, in_bind_var2=7)
+ print(out_val.getvalue()) # will print 15
If instead of simply getting data back you wish to supply an initial value to
the database, you can set the variable's initial value. This example is the
@@ -118,13 +119,15 @@ same as the previous one but it sets the initial value first:
.. code-block:: python
- inOutVal = cursor.var(int)
- inOutVal.setvalue(0, 25)
+ in_out_var = cursor.var(int)
+ in_out_var.setvalue(0, 25)
cursor.execute("""
begin
- :inOutBindVar := :inOutBindVar + :inBindVar1 + :inBindVar2;
- end;""", inOutBindVar=inOutVal, inBindVar1=8, inBindVar2=7)
- print(inOutVal.getvalue()) # will print 40
+ :in_out_bind_var := :in_out_bind_var + :in_bind_var1 +
+ :in_bind_var2;
+ end;""",
+ in_out_bind_var=in_out_var, in_bind_var1=8, in_bind_var2=7)
+ print(in_out_var.getvalue()) # will print 40
When binding data to parameters of PL/SQL procedures that are declared as OUT
parameters, it is worth noting that any value that is set in the bind variable
@@ -257,9 +260,9 @@ cursor which had executed a SQL query:
.. code-block:: python
- refCursor = connection.cursor()
- cursor.callproc("find_employees", ['Smith', refCursor])
- for row in refCursor:
+ ref_cursor = connection.cursor()
+ cursor.callproc("find_employees", ['Smith', ref_cursor])
+ for row in ref_cursor:
print(row)
With Oracle's `sample HR schema
@@ -274,8 +277,9 @@ return type of :meth:`Cursor.callfunc()`:
.. code-block:: python
- refCursor = cursor.callfunc('example_package.f_get_cursor', cx_Oracle.DB_TYPE_CURSOR)
- for row in refCursor:
+ ref_cursor = cursor.callfunc('example_package.f_get_cursor',
+ cx_Oracle.DB_TYPE_CURSOR)
+ for row in ref_cursor:
print(row)
See :ref:`tuning` for information on how to tune REF CURSORS.
@@ -322,8 +326,8 @@ Then the Python code:
.. code-block:: python
values = ["String One", "String Two", "String Three"]
- returnVal = cursor.callfunc("mypkg.DemoCollectionIn", int, [values])
- print(returnVal) # will print 32
+ return_val = cursor.callfunc("mypkg.DemoCollectionIn", int, [values])
+ print(return_val) # will print 32
In order get values back from the database, a bind variable must be created
using :meth:`Cursor.arrayvar()`. The first parameter to this method is a Python
@@ -388,9 +392,9 @@ language array`` would be raised.
.. code-block:: python
- outArrayVar = cursor.arrayvar(str, 10, 100)
- cursor.callproc("mypkg.DemoCollectionOut", [5, outArrayVar])
- for val in outArrayVar.getvalue():
+ out_array_var = cursor.arrayvar(str, 10, 100)
+ cursor.callproc("mypkg.DemoCollectionOut", [5, out_array_var])
+ for val in out_array_var.getvalue():
print(val)
This would produce the following output::
@@ -408,10 +412,10 @@ initial value.
.. code-block:: python
- inValues = ["String One", "String Two", "String Three", "String Four"]
- inOutArrayVar = cursor.arrayvar(str, inValues)
- cursor.callproc("mypkg.DemoCollectionInOut", [inOutArrayVar])
- for val in inOutArrayVar.getvalue():
+ in_values = ["String One", "String Two", "String Three", "String Four"]
+ in_out_array_var = cursor.arrayvar(str, in_values)
+ cursor.callproc("mypkg.DemoCollectionInOut", [in_out_array_var])
+ for val in in_out_array_var.getvalue():
print(val)
This would produce the following output::
@@ -427,8 +431,8 @@ used instead:
.. code-block:: python
- inOutArrayVar = cursor.arrayvar(str, 10, 100)
- inOutArrayVar.setvalue(0, ["String One", "String Two"])
+ in_out_array_var = cursor.arrayvar(str, 10, 100)
+ in_out_array_var.setvalue(0, ["String One", "String Two"])
All of the collections that have been bound in preceding examples have used
contiguous array elements. If an associative array with sparse array elements
@@ -470,8 +474,8 @@ process this collection looks like this instead:
.. code-block:: python
- collectionType = connection.gettype("MYPKG.UDT_STRINGLIST")
- collection = collectionType.newobject()
+ collection_type = connection.gettype("MYPKG.UDT_STRINGLIST")
+ collection = collection_type.newobject()
cursor.callproc("mypkg.DemoCollectionOut", [collection])
print(collection.aslist())
@@ -570,8 +574,8 @@ update the record:
.. code-block:: python
# create and populate a record
- recordType = connection.gettype("MYPKG.UDT_DEMORECORD")
- record = recordType.newobject()
+ record_type = connection.gettype("MYPKG.UDT_DEMORECORD")
+ record = record_type.newobject()
record.NUMBERVALUE = 6
record.STRINGVALUE = "Test String"
record.DATEVALUE = datetime.datetime(2016, 5, 28)
@@ -639,36 +643,38 @@ objects seamlessly:
.. code-block:: python
# A standard Python object
- class Building(object):
- def __init__(self, buildingId, description, numFloors, dateBuilt):
- self.buildingId = buildingId
+ class Building:
+
+ def __init__(self, build_id, description, num_floors, date_built):
+ self.building_id = build_id
self.description = description
- self.numFloors = numFloors
- self.dateBuilt = dateBuilt
+ self.num_floors = num_floors
+ self.date_built = date_built
building = Building(1, "Skyscraper 1", 5, datetime.date(2001, 5, 24))
# Get Python representation of the Oracle user defined type UDT_BUILDING
- objType = con.gettype("UDT_BUILDING")
+ obj_type = con.gettype("UDT_BUILDING")
- # convert a Python Building object to the Oracle user defined type UDT_BUILDING
- def BuildingInConverter(value):
- obj = objType.newobject()
- obj.BUILDINGID = value.buildingId
+ # convert a Python Building object to the Oracle user defined type
+ # UDT_BUILDING
+ def building_in_converter(value):
+ obj = obj_type.newobject()
+ obj.BUILDINGID = value.building_id
obj.DESCRIPTION = value.description
- obj.NUMFLOORS = value.numFloors
- obj.DATEBUILT = value.dateBuilt
+ obj.NUMFLOORS = value.num_floors
+ obj.DATEBUILT = value.date_built
return obj
- def InputTypeHandler(cursor, value, numElements):
+ def input_type_handler(cursor, value, num_elements):
if isinstance(value, Building):
- return cursor.var(cx_Oracle.DB_TYPE_OBJECT, arraysize = numElements,
- inconverter = BuildingInConverter, typename = objType.name)
+ return cursor.var(obj_type, arraysize=num_elements,
+ inconverter=building_in_converter)
# With the input type handler, the bound Python object is converted
# to the required Oracle object before being inserted
- cur.inputtypehandler = InputTypeHandler
+ cur.inputtypehandler = input_type_handler
cur.execute("insert into myTable values (:1, :2)", (1, building))
@@ -746,11 +752,11 @@ means to validate the data in order to avoid SQL Injection security issues:
.. code-block:: python
- tableAllowList = ['employees', 'departments']
- tableName = getTableName() # get the table name from user input
- if tableName not in tableAllowList:
+ table_allow_list = ['employees', 'departments']
+ table_name = get_table_name() # get the table name from user input
+ if table_name.lower() not in table_allow_list:
raise Exception('Invalid table name')
- sql = 'select * from ' + tableName
+ sql = f'select * from {table_name}'
Binding column names can be done either by using the above method or by using a
CASE statement. The example below demonstrates binding a column name in an
@@ -766,8 +772,8 @@ ORDER BY clause:
ELSE MANAGER_ID
END"""
- columnName = getColumnName() # Obtain a column name from the user
- cursor.execute(sql, [colname])
+ col_name = get_column_name() # Obtain a column name from the user
+ cursor.execute(sql, [col_name])
Depending on the name provided by the user, the query results will be
ordered either by the column ``DEPARTMENT_ID`` or the column ``MANAGER_ID``.
diff --git a/doc/src/user_guide/connection_handling.rst b/doc/src/user_guide/connection_handling.rst
index b674b2c..0942ce1 100644
--- a/doc/src/user_guide/connection_handling.rst
+++ b/doc/src/user_guide/connection_handling.rst
@@ -44,7 +44,9 @@ enabling :ref:`network encryption `.
userpwd = ". . ." # Obtain password string from a user prompt or environment variable
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1", encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1",
+ encoding="UTF-8")
cx_Oracle also supports :ref:`external authentication ` so
passwords do not need to be in the application.
@@ -61,11 +63,12 @@ the use of a "with" block, for example:
.. code-block:: python
- with cx_Oracle.connect(userName, password, "dbhost.example.com/orclpdb1",
- encoding="UTF-8") as connection:
+ with cx_Oracle.connect(user=user, password=password,
+ dsn="dbhost.example.com/orclpdb1",
+ encoding="UTF-8") as connection:
cursor = connection.cursor()
cursor.execute("insert into SomeTable values (:1, :2)",
- (1, "Some string"))
+ (1, "Some string"))
connection.commit()
This code ensures that, once the block is completed, the connection is closed
@@ -103,15 +106,21 @@ such as ``tnsnames.ora``.
For example, to connect to the Oracle Database service ``orclpdb1`` that is
running on the host ``dbhost.example.com`` with the default Oracle
-Database port 1521, use::
+Database port 1521, use:
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
- encoding="UTF-8")
+.. code-block:: python
-If the database is using a non-default port, it must be specified::
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1",
+ encoding="UTF-8")
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com:1984/orclpdb1",
- encoding="UTF-8")
+If the database is using a non-default port, it must be specified:
+
+.. code-block:: python
+
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com:1984/orclpdb1",
+ encoding="UTF-8")
The Easy Connect syntax supports Oracle Database service names. It cannot be
used with the older System Identifiers (SID).
@@ -143,10 +152,13 @@ syntax.
For example, to connect to the Oracle Database service ``orclpdb1`` that is
running on the host ``dbhost.example.com`` with the default Oracle
-Database port 1521, use::
+Database port 1521, use:
+
+.. code-block:: python
dsn = cx_Oracle.makedsn("dbhost.example.com", 1521, service_name="orclpdb1")
- connection = cx_Oracle.connect("hr", userpwd, dsn, encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd, dsn=dsn,
+ encoding="UTF-8")
Note the use of the named argument ``service_name``. By default, the third
parameter of :meth:`~cx_Oracle.makedsn()` is a database System Identifier (SID),
@@ -158,7 +170,9 @@ The value of ``dsn`` in this example is the connect descriptor string::
You can manually create similar connect descriptor strings. This lets you
extend the syntax, for example to support failover. These strings can be
-embedded directly in the application::
+embedded directly in the application:
+
+.. code-block:: python
dsn = """(DESCRIPTION=
(FAILOVER=on)
@@ -167,7 +181,8 @@ embedded directly in the application::
(ADDRESS=(PROTOCOL=tcp)(HOST=sales2-svr)(PORT=1521)))
(CONNECT_DATA=(SERVICE_NAME=sales.example.com)))"""
- connection = cx_Oracle.connect("hr", userpwd, dsn, encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd, dsn=dsn,
+ encoding="UTF-8")
.. _netservice:
@@ -189,9 +204,12 @@ given a ``tnsnames.ora`` file with the following contents::
)
)
-then you could connect using the following code::
+then you could connect using the following code:
- connection = cx_Oracle.connect("hr", userpwd, "orclpdb1", encoding="UTF-8")
+.. code-block:: python
+
+ connection = cx_Oracle.connect(user="hr", password=userpwd, dsn="orclpdb1",
+ encoding="UTF-8")
For more information about Net Service Names, see
`Database Net Services Reference
@@ -210,9 +228,13 @@ for example::
jdbc:oracle:thin:@dbhost.example.com:1521/orclpdb1
-then use Oracle's Easy Connect syntax in cx_Oracle::
+then use Oracle's Easy Connect syntax in cx_Oracle:
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com:1521/orclpdb1", encoding="UTF-8")
+.. code-block:: python
+
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com:1521/orclpdb1",
+ encoding="UTF-8")
Alternatively, if a JDBC connection string uses an old-style Oracle SID "system
identifier", and the database does not have a service name::
@@ -224,10 +246,13 @@ for example::
jdbc:oracle:thin:@dbhost.example.com:1521:orcl
then a connect descriptor string from ``makedsn()`` can be used in the
-application::
+application:
+
+.. code-block:: python
dsn = cx_Oracle.makedsn("dbhost.example.com", 1521, sid="orcl")
- connection = cx_Oracle.connect("hr", userpwd, dsn, encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd, dsn=dsn,
+ encoding="UTF-8")
Alternatively, create a ``tnsnames.ora`` (see :ref:`optnetfiles`) entry, for
example::
@@ -240,9 +265,12 @@ example::
)
)
-This can be referenced in cx_Oracle::
+This can be referenced in cx_Oracle:
- connection = cx_Oracle.connect("hr", userpwd, "finance", encoding="UTF-8")
+.. code-block:: python
+
+ connection = cx_Oracle.connect(user="hr", password=userpwd, dsn="finance",
+ encoding="UTF-8")
.. _connpool:
@@ -289,8 +317,9 @@ connection pool:
.. code-block:: python
# Create the session pool
- pool = cx_Oracle.SessionPool("hr", userpwd,
- "dbhost.example.com/orclpdb1", min=2, max=5, increment=1, encoding="UTF-8")
+ pool = cx_Oracle.SessionPool(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1", min=2,
+ max=5, increment=1, encoding="UTF-8")
# Acquire a connection from the pool
connection = pool.acquire()
@@ -306,18 +335,22 @@ connection pool:
# Close the pool
pool.close()
-Other :meth:`cx_Oracle.SessionPool()` options can be used at pool creation. For
-example the ``getmode`` value can be set so that any ``aquire()`` call will wait
-for a connection to become available if all are currently in use, for example:
+Other :meth:`cx_Oracle.SessionPool()` options can be used at pool creation.
+For example the ``getmode`` value can be set so that any ``aquire()`` call will
+wait for a connection to become available if all are currently in use, for
+example:
.. code-block:: python
# Create the session pool
- pool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orclpdb1",
- min=2, max=5, increment=1, getmode=cx_Oracle.SPOOL_ATTRVAL_WAIT, encoding="UTF-8")
+ pool = cx_Oracle.SessionPool(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1", min=2,
+ max=5, increment=1,
+ getmode=cx_Oracle.SPOOL_ATTRVAL_WAIT,
+ encoding="UTF-8")
See `ConnectionPool.py
-`__
+`__
for an example.
Before :meth:`SessionPool.acquire()` returns, cx_Oracle does a lightweight check
@@ -386,7 +419,7 @@ However, because pools can grow, or connections in the pool can be recreated,
there is no guarantee a subsequent :meth:`~SessionPool.acquire()` call will
return a database connection that has any particular state.
-The :meth:`~cx_Oracle.SessionPool()` parameter ``sessionCallback``
+The :meth:`~cx_Oracle.SessionPool()` parameter ``session_callback``
enables efficient setting of session state so that connections have a
known session state, without requiring that state to be explicitly set
after each :meth:`~SessionPool.acquire()` call.
@@ -401,7 +434,7 @@ necessary changes.
The session callback can be a Python function or a PL/SQL procedure.
-There are three common scenarios for ``sessionCallback``:
+There are three common scenarios for ``session_callback``:
- When all connections in the pool should have the same state, use a
Python callback without tagging.
@@ -414,7 +447,7 @@ There are three common scenarios for ``sessionCallback``:
**Python Callback**
-If the ``sessionCallback`` parameter is a Python procedure, it will be called
+If the ``session_callback`` parameter is a Python procedure, it will be called
whenever :meth:`~SessionPool.acquire()` will return a newly created database
connection that has not been used before. It is also called when connection
tagging is being used and the requested tag is not identical to the tag in the
@@ -425,24 +458,25 @@ An example is:
.. code-block:: python
# Set the NLS_DATE_FORMAT for a session
- def initSession(connection, requestedTag):
+ def init_session(connection, requested_tag):
cursor = connection.cursor()
cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI'")
# Create the pool with session callback defined
- pool = cx_Oracle.SessionPool("hr", userpwd, "orclpdb1",
- sessionCallback=initSession, encoding="UTF-8")
+ pool = cx_Oracle.SessionPool(user="hr", password=userpwd, dsn="orclpdb1",
+ session_callback=init_session,
+ encoding="UTF-8")
# Acquire a connection from the pool (will always have the new date format)
connection = pool.acquire()
-If needed, the ``initSession()`` procedure is called internally before
+If needed, the ``init_session()`` procedure is called internally before
``acquire()`` returns. It will not be called when previously used connections
are returned from the pool. This means that the ALTER SESSION does not need to
be executed after every ``acquire()`` call. This improves performance and
scalability.
-In this example tagging was not being used, so the ``requestedTag`` parameter
+In this example tagging was not being used, so the ``requested_tag`` parameter
is ignored.
Note: if you need to execute multiple SQL statements in the callback, use an
@@ -483,25 +517,26 @@ The example below demonstrates connection tagging:
.. code-block:: python
- def initSession(connection, requestedTag):
- if requestedTag == "NLS_DATE_FORMAT=SIMPLE":
+ def init_session(connection, requested_tag):
+ if requested_tag == "NLS_DATE_FORMAT=SIMPLE":
sql = "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'"
- elif requestedTag == "NLS_DATE_FORMAT=FULL":
+ elif requested_tag == "NLS_DATE_FORMAT=FULL":
sql = "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI'"
cursor = connection.cursor()
cursor.execute(sql)
- connection.tag = requestedTag
+ connection.tag = requested_tag
- pool = cx_Oracle.SessionPool("hr", userpwd, "orclpdb1",
- sessionCallback=initSession, encoding="UTF-8")
+ pool = cx_Oracle.SessionPool(user="hr", password=userpwd, dsn="orclpdb1",
+ session_callback=init_session,
+ encoding="UTF-8")
# Two connections with different session state:
- connection1 = pool.acquire(tag = "NLS_DATE_FORMAT=SIMPLE")
- connection2 = pool.acquire(tag = "NLS_DATE_FORMAT=FULL")
+ connection1 = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE")
+ connection2 = pool.acquire(tag="NLS_DATE_FORMAT=FULL")
-See `SessionCallback.py
-`__ for an example.
+See `session_callback.py
+`__ for an example.
**PL/SQL Callback**
@@ -533,21 +568,24 @@ Oracle 'multi-property tags' must be used. The tag string must be of the form
of one or more "name=value" pairs separated by a semi-colon, for example
``"loc=uk;lang=cy"``.
-In cx_Oracle set ``sessionCallback`` to the name of the PL/SQL procedure. For
+In cx_Oracle set ``session_callback`` to the name of the PL/SQL procedure. For
example:
.. code-block:: python
- pool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orclpdb1:pooled",
- sessionCallback="myPlsqlCallback", encoding="UTF-8")
+ pool = cx_Oracle.SessionPool(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1:pooled",
+ session_callback="MyPlsqlCallback",
+ encoding="UTF-8")
connection = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE",
- # DRCP options, if you are using DRCP
- cclass='MYCLASS', purity=cx_Oracle.ATTR_PURITY_SELF)
+ # DRCP options, if you are using DRCP
+ cclass='MYCLASS',
+ purity=cx_Oracle.ATTR_PURITY_SELF)
-See `SessionCallbackPLSQL.py
-`__ for an example.
+See `session_callback_plsql.py
+`__ for an example.
.. _connpooltypes:
@@ -568,8 +606,8 @@ may be passed to :meth:`~SessionPool.acquire()` as shown in this example:
.. code-block:: python
- pool = cx_Oracle.SessionPool(dsn="dbhost.example.com/orclpdb1", homogeneous=False,
- encoding="UTF-8")
+ pool = cx_Oracle.SessionPool(dsn="dbhost.example.com/orclpdb1",
+ homogeneous=False, encoding="UTF-8")
connection = pool.acquire(user="hr", password=userpwd)
.. _drcp:
@@ -697,14 +735,16 @@ Using Oracle’s Easy Connect syntax, the connection would look like:
.. code-block:: python
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orcl:pooled",
- encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orcl:pooled",
+ encoding="UTF-8")
Or if you connect using a Net Service Name named ``customerpool``:
.. code-block:: python
- connection = cx_Oracle.connect("hr", userpwd, "customerpool", encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="customerpool", encoding="UTF-8")
Then only the Oracle Network configuration file ``tnsnames.ora`` needs
to be modified::
@@ -729,17 +769,22 @@ Resident Connection Pooling:
.. code-block:: python
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orcl:pooled",
- cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF, encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orcl:pooled",
+ cclass="MYCLASS",
+ purity=cx_Oracle.ATTR_PURITY_SELF,
+ encoding="UTF-8")
The example below shows connecting to Oracle Database using DRCP and
cx_Oracle's connection pooling:
.. code-block:: python
- mypool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orcl:pooled",
- encoding="UTF-8")
- connection = mypool.acquire(cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF)
+ mypool = cx_Oracle.SessionPool(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orcl:pooled",
+ encoding="UTF-8")
+ connection = mypool.acquire(cclass="MYCLASS",
+ purity=cx_Oracle.ATTR_PURITY_SELF)
For more information about DRCP see `Oracle Database Concepts Guide
`__
+`__
for a runnable CQN example.
diff --git a/doc/src/user_guide/exception_handling.rst b/doc/src/user_guide/exception_handling.rst
index f830cf1..e27075b 100644
--- a/doc/src/user_guide/exception_handling.rst
+++ b/doc/src/user_guide/exception_handling.rst
@@ -32,9 +32,9 @@ code can be used:
try:
cursor.execute("insert into customer values (101, 'Customer A')")
except cx_Oracle.IntegrityError as e:
- errorObj, = e.args
+ error_obj, = e.args
print("Customer ID already exists")
- print("Error Code:", errorObj.code)
- print("Error Message:", errorObj.message)
+ print("Error Code:", error_obj.code)
+ print("Error Message:", error_obj.message)
else:
print("Customer added")
diff --git a/doc/src/user_guide/globalization.rst b/doc/src/user_guide/globalization.rst
index 722589c..2d6f947 100644
--- a/doc/src/user_guide/globalization.rst
+++ b/doc/src/user_guide/globalization.rst
@@ -29,8 +29,12 @@ specify different Oracle Client character sets. For example:
.. code-block:: python
import cx_Oracle
- connection = cx_Oracle.connect(connectString, encoding="US-ASCII",
- nencoding="UTF-8")
+ connection = cx_Oracle.connect(dsn=connect_string, encoding="US-ASCII",
+ nencoding="UTF-8")
+
+.. note::
+
+ In a future release of cx_Oracle, only UTF-8 will be supported.
The ``encoding`` parameter affects character data such as VARCHAR2 and CLOB
columns. The ``nencoding`` parameter affects "National Character" data such as
@@ -66,8 +70,9 @@ database.
.. code-block:: python
- connection = cx_Oracle.connect(userName, password, "dbhost.example.com/orclpdb1",
- encoding="US-ASCII")
+ connection = cx_Oracle.connect(user=user, password=password,
+ dsn="dbhost.example.com/orclpdb1",
+ encoding="US-ASCII")
cursor = connection.cursor()
for row in cursor.execute("select nvarchar2_column from nchar_test"):
print(row)
@@ -77,11 +82,13 @@ Because the '€' symbol is not supported by the ``US-ASCII`` character set, all
('¿',)
-When the ``encoding`` parameter is removed (or set to "UTF-8") during connection:
+When the ``encoding`` parameter is removed (or set to "UTF-8") during
+connection:
.. code-block:: python
- connection = cx_Oracle.connect(userName, password, "dbhost.example.com/orclpdb1")
+ connection = cx_Oracle.connect(user=user, password=password,
+ dsn="dbhost.example.com/orclpdb1")
Then the output displays the Euro symbol as desired::
diff --git a/doc/src/user_guide/ha.rst b/doc/src/user_guide/ha.rst
index 93df970..70bc3e5 100644
--- a/doc/src/user_guide/ha.rst
+++ b/doc/src/user_guide/ha.rst
@@ -212,5 +212,5 @@ In the Python application code:
the last call was completed successfully or not.
See the `Transaction Guard Sample
-`__ for further details.
diff --git a/doc/src/user_guide/initialization.rst b/doc/src/user_guide/initialization.rst
index 5987b5c..5abd929 100644
--- a/doc/src/user_guide/initialization.rst
+++ b/doc/src/user_guide/initialization.rst
@@ -40,7 +40,7 @@ Support's `Doc ID 207303.1
you will need to have previously set your environment to use that
software installation, otherwise files such as message files will not be
located. On Windows when the path contains backslashes, use a 'raw'
- string like ``lib_dir = r"C:\instantclient_19_6"``. If the Oracle Client
+ string like ``lib_dir=r"C:\instantclient_19_6"``. If the Oracle Client
libraries cannot be loaded from ``lib_dir``, then an exception is raised.
- If ``lib_dir`` was not specified, then Oracle Client libraries are looked
@@ -164,7 +164,8 @@ example, if the Oracle Instant Client Libraries are in
"instantclient_19_8")
cx_Oracle.init_oracle_client(lib_dir=lib_dir)
elif sys.platform.startswith("win32"):
- cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_9")
+ lib_dir=r"C:\oracle\instantclient_19_9"
+ cx_Oracle.init_oracle_client(lib_dir=lib_dir)
except Exception as err:
print("Whoops!")
print(err);
@@ -388,8 +389,8 @@ parameters is:
import sys
try:
- cx_Oracle.init_oracle_client(driver_name = "My Great App : 3.1.4",
- error_url: "https://example.com/MyInstallInstructions.html")
+ cx_Oracle.init_oracle_client(driver_name="My Great App : 3.1.4",
+ error_url="https://example.com/MyInstallInstructions.html")
except Exception as err:
print("Whoops!")
print(err);
diff --git a/doc/src/user_guide/installation.rst b/doc/src/user_guide/installation.rst
index 20f5b91..62d9f84 100644
--- a/doc/src/user_guide/installation.rst
+++ b/doc/src/user_guide/installation.rst
@@ -12,15 +12,14 @@ To use cx_Oracle 8 with Python and Oracle Database you need:
- Python 3.5 and higher. Older versions of cx_Oracle may work with older
versions of Python.
-- Oracle Client libraries. These can be from the free `Oracle Instant
- Client
- `__,
- or those included in Oracle Database if Python is on the same
- machine as the database. Oracle client libraries versions 19, 18, 12,
- and 11.2 are supported on Linux, Windows and macOS (Intel x86). Users have
- also reported success with other platforms. Use the latest client possible:
- Oracle's standard client-server version interoperability allows connection to
- both older and newer databases.
+- Oracle Client libraries. These can be from the free `Oracle Instant Client
+ `__, from a
+ full Oracle Client installation, or from those included in Oracle Database if
+ Python is on the same machine as the database. Oracle client libraries
+ versions 21, 19, 18, 12, and 11.2 are supported where available on Linux,
+ Windows and macOS (Intel x86). Users have also reported success with other
+ platforms. Use the latest client possible: Oracle's standard client-server
+ version interoperability allows connection to both older and newer databases.
- An Oracle Database, either local or remote.
@@ -36,6 +35,14 @@ product: it is how the Oracle Client and Oracle Database communicate.
Quick Start cx_Oracle Installation
==================================
+The `Quick Start: Developing Python Applications for Oracle Database
+`__
+and `Quick Start: Developing Python Applications for Oracle Autonomous Database
+`__
+instructions have steps for Windows, Linux, and macOS.
+
+Alternatively you can:
+
- Install `Python `__ 3, if not already
available. On macOS you must always install your own Python.
@@ -63,7 +70,7 @@ Quick Start cx_Oracle Installation
If you are behind a proxy, add a proxy server to the command, for example add
``--proxy=http://proxy.example.com:80``
-- Add Oracle 19, 18, 12 or 11.2 client libraries to your operating system
+- Add Oracle 21, 19, 18, 12 or 11.2 client libraries to your operating system
library search path such as ``PATH`` on Windows or ``LD_LIBRARY_PATH`` on
Linux. On macOS use :meth:`~cx_Oracle.init_oracle_client()` in your
application to pass the Oracle Client directory name, see
@@ -88,6 +95,7 @@ Quick Start cx_Oracle Installation
`__
release.
+ Version 21 client libraries can connect to Oracle Database 12.1 or greater.
Version 19, 18 and 12.2 client libraries can connect to Oracle Database 11.2
or greater. Version 12.1 client libraries can connect to Oracle Database 10.2
or greater. Version 11.2 client libraries can connect to Oracle Database 9.2
@@ -102,7 +110,8 @@ Quick Start cx_Oracle Installation
import cx_Oracle
# Connect as user "hr" with password "welcome" to the "orclpdb1" service running on this computer.
- connection = cx_Oracle.connect("hr", "welcome", "localhost/orclpdb1")
+ connection = cx_Oracle.connect(user="hr", password="welcome",
+ dsn="localhost/orclpdb1")
cursor = connection.cursor()
cursor.execute("""
@@ -126,7 +135,7 @@ Quick Start cx_Oracle Installation
You can learn how to use cx_Oracle from the :ref:`API documentation `
and `samples
-`__.
+`__.
If you run into installation trouble, check out the section on `Troubleshooting`_.
@@ -150,12 +159,12 @@ connections between different versions of Oracle Client libraries and
Oracle Database. For certified configurations see Oracle Support's
`Doc ID 207303.1
`__.
-In summary, Oracle Client 19, 18 and 12.2 can connect to Oracle Database 11.2 or
+In summary, Oracle Client 21 can connect to Oracle Database 12.1 or greater.
+Oracle Client 19, 18 and 12.2 can connect to Oracle Database 11.2 or
greater. Oracle Client 12.1 can connect to Oracle Database 10.2 or
-greater. Oracle Client 11.2 can connect to Oracle Database 9.2 or
-greater. The technical restrictions on creating connections may be
-more flexible. For example Oracle Client 12.2 can successfully
-connect to Oracle Database 10.2.
+greater. Oracle Client 11.2 can connect to Oracle Database 9.2 or greater. The
+technical restrictions on creating connections may be more flexible. For
+example Oracle Client 12.2 can successfully connect to Oracle Database 10.2.
cx_Oracle uses the shared library loading mechanism available on each
supported platform to load the Oracle Client libraries at runtime. It
@@ -169,26 +178,12 @@ file available with 12.1 or later clients, session pool improvements,
improved high availability features, call timeouts, and `other enhancements
`__.
-The cx_Oracle function :func:`~cx_Oracle.clientversion()` can be used
-to determine which Oracle Client version is in use and the attribute
-:attr:`Connection.version` can be used to determine which Oracle
-Database version a connection is accessing. These can then be used to
-adjust application behavior accordingly. Attempts to use some Oracle
-features that are not supported by a particular client/server
-combination may result in runtime errors. These include:
-
- - when attempting to access attributes that are not supported by the
- current Oracle Client library you will get the error "ORA-24315: illegal
- attribute type"
-
- - when attempting to use implicit results with Oracle Client 11.2
- against Oracle Database 12c you will get the error "ORA-29481:
- Implicit results cannot be returned to client"
-
- - when attempting to get array DML row counts with Oracle Client
- 11.2 you will get the error "DPI-1050: Oracle Client library must be at
- version 12.1 or higher"
-
+The cx_Oracle function :func:`~cx_Oracle.clientversion()` can be used to
+determine which Oracle Client version is in use. The attribute
+:attr:`Connection.version` can be used to determine which Oracle Database
+version a connection is accessing. These can then be used to adjust application
+behavior accordingly. Attempts to use Oracle features that are not supported by
+a particular client/server library combination will result in runtime errors.
Installing cx_Oracle on Linux
=============================
@@ -251,14 +246,15 @@ Oracle Instant Client Zip Files
To use cx_Oracle with Oracle Instant Client zip files:
-1. Download an Oracle 19, 18, 12, or 11.2 "Basic" or "Basic Light" zip file: `64-bit
- `__
- or `32-bit
- `__, matching your
- Python architecture.
+1. Download an Oracle 21, 19, 18, 12, or 11.2 "Basic" or "Basic Light" zip file
+ matching your Python 64-bit or 32-bit architecture:
- The latest version is recommended. Oracle Instant Client 19 will
- connect to Oracle Database 11.2 or later.
+ - `x86-64 64-bit `__
+ - `x86 32-bit `__
+ - `ARM (aarch64) 64-bit `__
+
+ The latest version is recommended. Oracle Instant Client 21 will connect to
+ Oracle Database 12.1 or later.
2. Unzip the package into a single directory that is accessible to your
application. For example:
@@ -267,7 +263,7 @@ To use cx_Oracle with Oracle Instant Client zip files:
mkdir -p /opt/oracle
cd /opt/oracle
- unzip instantclient-basic-linux.x64-19.9.0.0.0dbru.zip
+ unzip instantclient-basic-linux.x64-21.1.0.0.0.zip
3. Install the ``libaio`` package with sudo or as the root user. For example::
@@ -275,8 +271,8 @@ To use cx_Oracle with Oracle Instant Client zip files:
On some Linux distributions this package is called ``libaio1`` instead.
- On recent Linux versions, such as Oracle Linux 8, you may also need to
- install the ``libnsl`` package.
+ On recent Linux versions such as Oracle Linux 8, you may also need to
+ install the ``libnsl`` package when using Oracle Instant Client 19.
4. If there is no other Oracle software on the machine that will be
impacted, permanently add Instant Client to the runtime link
@@ -284,14 +280,14 @@ To use cx_Oracle with Oracle Instant Client zip files:
.. code-block:: shell
- sudo sh -c "echo /opt/oracle/instantclient_19_9 > /etc/ld.so.conf.d/oracle-instantclient.conf"
+ sudo sh -c "echo /opt/oracle/instantclient_21_1 > /etc/ld.so.conf.d/oracle-instantclient.conf"
sudo ldconfig
Alternatively, set the environment variable ``LD_LIBRARY_PATH`` to
the appropriate directory for the Instant Client version. For
example::
- export LD_LIBRARY_PATH=/opt/oracle/instantclient_19_9:$LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH=/opt/oracle/instantclient_21_1:$LD_LIBRARY_PATH
5. If you use optional Oracle configuration files such as ``tnsnames.ora``,
``sqlnet.ora`` or ``oraaccess.xml`` with Instant Client, then put the files
@@ -306,7 +302,7 @@ To use cx_Oracle with Oracle Instant Client zip files:
Or set the environment variable ``TNS_ADMIN`` to that directory name.
Alternatively, put the files in the ``network/admin`` subdirectory of Instant
- Client, for example in ``/opt/oracle/instantclient_19_9/network/admin``.
+ Client, for example in ``/opt/oracle/instantclient_21_1/network/admin``.
This is the default Oracle configuration directory for executables linked
with this Instant Client.
@@ -315,35 +311,36 @@ Oracle Instant Client RPMs
To use cx_Oracle with Oracle Instant Client RPMs:
-1. Download an Oracle 19, 18, 12, or 11.2 "Basic" or "Basic Light" RPM: `64-bit
- `__
- or `32-bit
- `__, matching your
- Python architecture.
+1. Download an Oracle 21,19, 18, 12, or 11.2 "Basic" or "Basic Light" RPM
+ matching your Python architecture:
- Oracle's yum server has `Instant Client RPMs for Oracle Linux 8
- `__,
- `Instant Client RPMs for Oracle Linux 7
- `__
- and `Instant Client RPMs for Oracle Linux 6
- `__
- that can be downloaded without needing a click-through.
+ - `x86-64 64-bit `__
+ - `x86 32-bit `__
+ - `ARM (aarch64) 64-bit `__
- The latest version is recommended. Oracle Instant Client 19 will
- connect to Oracle Database 11.2 or later.
+ Oracle's yum server has convenient repositories:
+
+ - `Instant Client 21 RPMs for Oracle Linux x86-64 8 `__, `Older Instant Client RPMs for Oracle Linux x86-64 8 `__
+ - `Instant Client 21 RPMs for Oracle Linux x86-64 7 `__, `Older Instant Client RPMs for Oracle Linux x86-64 7 `__
+ - `Instant Client RPMs for Oracle Linux x86-64 6 `__
+ - `Instant Client RPMs for Oracle Linux ARM (aarch64) 8 `__
+ - `Instant Client RPMs for Oracle Linux ARM (aarch64) 7 `__
+
+ The latest version is recommended. Oracle Instant Client 21 will connect to
+ Oracle Database 12.1 or later.
2. Install the downloaded RPM with sudo or as the root user. For example:
.. code-block:: shell
- sudo yum install oracle-instantclient19.9-basic-19.9.0.0.0-1.x86_64.rpm
+ sudo yum install oracle-instantclient-basic-21.1.0.0.0-1.x86_64.rpm
Yum will automatically install required dependencies, such as ``libaio``.
On recent Linux versions, such as Oracle Linux 8, you may need to manually
- install the ``libnsl`` package.
+ install the ``libnsl`` package when using Oracle Instant Client 19.
-3. For Instant Client 19, the system library search path is
+3. For Instant Client 19, or later, the system library search path is
automatically configured during installation.
For older versions, if there is no other Oracle software on the machine that will be
@@ -352,7 +349,7 @@ To use cx_Oracle with Oracle Instant Client RPMs:
.. code-block:: shell
- sudo sh -c "echo /usr/lib/oracle/18.3/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf"
+ sudo sh -c "echo /usr/lib/oracle/18.5/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf"
sudo ldconfig
Alternatively, for version 18 and earlier, every shell running
@@ -360,7 +357,7 @@ To use cx_Oracle with Oracle Instant Client RPMs:
``LD_LIBRARY_PATH`` set to the appropriate directory for the
Instant Client version. For example::
- export LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib:$LD_LIBRARY_PATH
+ export LD_LIBRARY_PATH=/usr/lib/oracle/18.5/client64/lib:$LD_LIBRARY_PATH
4. If you use optional Oracle configuration files such as ``tnsnames.ora``,
``sqlnet.ora`` or ``oraaccess.xml`` with Instant Client, then put the files
@@ -375,14 +372,14 @@ To use cx_Oracle with Oracle Instant Client RPMs:
Or set the environment variable ``TNS_ADMIN`` to that directory name.
Alternatively, put the files in the ``network/admin`` subdirectory of Instant
- Client, for example in ``/usr/lib/oracle/19.9/client64/lib/network/admin``.
+ Client, for example in ``/usr/lib/oracle/21/client64/lib/network/admin``.
This is the default Oracle configuration directory for executables linked
with this Instant Client.
Local Database or Full Oracle Client
++++++++++++++++++++++++++++++++++++
-cx_Oracle applications can use Oracle Client 19, 18, 12, or 11.2 libraries
+cx_Oracle applications can use Oracle Client 21, 19, 18, 12, or 11.2 libraries
from a local Oracle Database or full Oracle Client installation.
The libraries must be either 32-bit or 64-bit, matching your
@@ -487,8 +484,8 @@ To use cx_Oracle with Oracle Instant Client zip files:
2. Unzip the package into a directory that is accessible to your
application. For example unzip
- ``instantclient-basic-windows.x64-19.9.0.0.0dbru.zip`` to
- ``C:\oracle\instantclient_19_9``.
+ ``instantclient-basic-windows.x64-19.11.0.0.0dbru.zip`` to
+ ``C:\oracle\instantclient_19_11``.
3. Oracle Instant Client libraries require a Visual Studio redistributable with
a 64-bit or 32-bit architecture to match Instant Client's architecture.
@@ -511,7 +508,7 @@ Configure Oracle Instant Client
.. code-block:: python
import cx_Oracle
- cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_9")
+ cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_11")
Note a 'raw' string is used because backslashes occur in the path.
@@ -536,14 +533,14 @@ Configure Oracle Instant Client
.. code-block:: python
import cx_Oracle
- cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_9",
+ cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_11",
config_dir=r"C:\oracle\your_config_dir")
Or set the environment variable ``TNS_ADMIN`` to that directory name.
Alternatively, put the files in a ``network\admin`` subdirectory of
Instant Client, for example in
- ``C:\oracle\instantclient_19_9\network\admin``. This is the default
+ ``C:\oracle\instantclient_19_11\network\admin``. This is the default
Oracle configuration directory for executables linked with this
Instant Client.
@@ -630,6 +627,8 @@ Manual Installation
/Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh
This copies the contents to ``$HOME/Downloads/instantclient_19_8``.
+ Applications may not have access to the ``Downloads`` directory, so you
+ should move Instant Client somewhere convenient.
* In Finder, eject the mounted Instant Client package.
@@ -651,6 +650,8 @@ Instant Client installation can alternatively be scripted, for example:
hdiutil unmount /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru
The Instant Client directory will be ``$HOME/Downloads/instantclient_19_8``.
+Applications may not have access to the ``Downloads`` directory, so you should
+move Instant Client somewhere convenient.
Configure Oracle Instant Client
@@ -682,6 +683,20 @@ Configure Oracle Instant Client
default Oracle configuration directory for executables linked with this
Instant Client.
+Linux Containers
+================
+
+Sample Dockerfiles are on `GitHub
+`__.
+
+Pre-built images for Python and cx_Oracle are in the `GitHub Container Registry
+`__. These are easily used. For
+example, to pull an Oracle Linux 8 image with Python 3.6 and cx_Oracle,
+execute::
+
+ docker pull ghcr.io/oracle/oraclelinux7-python:3.6-oracledb
+
+
Installing cx_Oracle without Internet Access
============================================
@@ -711,10 +726,10 @@ you will also need to download an `ODPI-C
`__ source zip file and extract it
inside the directory called "odpi".
-cx_Oracle source code is also available from oss.oracle.com. This can
+cx_Oracle source code is also available from opensource.oracle.com. This can
be cloned with::
- git clone git://oss.oracle.com/git/oracle/python-cx_Oracle.git cx_Oracle
+ git clone git://opensource.oracle.com/git/oracle/python-cx_Oracle.git cx_Oracle
cd cx_Oracle
git submodule init
git submodule update
@@ -734,8 +749,8 @@ which the following commands should be run::
Upgrading from Older Versions
=============================
-Review the :ref:`release notes ` for deprecations and modify any
-affected code.
+Review the :ref:`release notes ` and :ref:`Deprecations
+` for changes. Modify affected code.
If you are upgrading from cx_Oracle 7 note these changes:
diff --git a/doc/src/user_guide/introduction.rst b/doc/src/user_guide/introduction.rst
index 0f98e27..8a928da 100644
--- a/doc/src/user_guide/introduction.rst
+++ b/doc/src/user_guide/introduction.rst
@@ -23,12 +23,15 @@ the same machine as Python, or it can be remote.
cx_Oracle is typically installed from `PyPI
`__ using `pip
-`__. The Oracle Client
-libraries need to be installed separately. The libraries can be obtained from
-an installation of `Oracle Instant Client
+`__. The Oracle Client libraries
+need to be installed separately. The libraries can be from an installation of
+`Oracle Instant Client
`__, from a
full Oracle Client installation, or even from an Oracle Database installation
-(if Python is running on the same machine as the database).
+(if Python is running on the same machine as the database). Oracle’s standard
+client-server version interoperability allows connection to both older and
+newer databases from different Client library versions, see :ref:`cx_Oracle
+Installation `.
Some behaviors of the Oracle Client libraries can optionally be configured with
an ``oraaccess.xml`` file, for example to enable auto-tuning of a statement
@@ -74,20 +77,21 @@ Create a script ``query.py`` as shown below:
import cx_Oracle
# Establish the database connection
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1")
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1")
# Obtain a cursor
cursor = connection.cursor()
# Data for binding
- managerId = 145
- firstName = "Peter"
+ manager_id = 145
+ first_name = "Peter"
# Execute the query
sql = """SELECT first_name, last_name
FROM employees
WHERE manager_id = :mid AND first_name = :fn"""
- cursor.execute(sql, mid = managerId, fn = firstName)
+ cursor.execute(sql, mid=manager_id, fn=first_name)
# Loop over the result set
for row in cursor:
@@ -127,8 +131,14 @@ The output is::
Examples and Tutorials
----------------------
+The `Quick Start: Developing Python Applications for Oracle Database
+`__
+and `Quick Start: Developing Python Applications for Oracle Autonomous Database
+`__
+instructions have steps for Windows, Linux, and macOS.
+
Runnable examples are in the `GitHub samples directory
-`__. A `Python
+`__. A `Python
cx_Oracle tutorial
`__
is also available.
diff --git a/doc/src/user_guide/lob_data.rst b/doc/src/user_guide/lob_data.rst
index f1e60f9..39ae12b 100644
--- a/doc/src/user_guide/lob_data.rst
+++ b/doc/src/user_guide/lob_data.rst
@@ -29,7 +29,7 @@ cx_Oracle. This makes LOBs easy to work with, and has significant performance
benefits over streaming. However it requires the entire LOB data to be present
in Python memory, which may not be possible.
-See `GitHub `__ for LOB examples.
+See `GitHub `__ for LOB examples.
Simple Insertion of LOBs
@@ -51,15 +51,15 @@ bytes as needed:
.. code-block:: python
with open('example.txt', 'r') as f:
- textdata = f.read()
+ text_data = f.read()
with open('image.png', 'rb') as f:
- imgdata = f.read()
+ img_data = f.read()
cursor.execute("""
insert into lob_tbl (id, c, b)
values (:lobid, :clobdata, :blobdata)""",
- lobid=10, clobdata=textdata, blobdata=imgdata)
+ lobid=10, clobdata=text_data, blobdata=img_data)
Note that with this approach, LOB data is limited to 1 GB in size.
@@ -76,25 +76,25 @@ to be used as shown in this example:
.. code-block:: python
- def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
- if defaultType == cx_Oracle.DB_TYPE_CLOB:
+ def output_type_handler(cursor, name, default_type, size, precision, scale):
+ if default_type == cx_Oracle.DB_TYPE_CLOB:
return cursor.var(cx_Oracle.DB_TYPE_LONG, arraysize=cursor.arraysize)
- if defaultType == cx_Oracle.DB_TYPE_BLOB:
+ if default_type == cx_Oracle.DB_TYPE_BLOB:
return cursor.var(cx_Oracle.DB_TYPE_LONG_RAW, arraysize=cursor.arraysize)
- idVal = 1
- textData = "The quick brown fox jumps over the lazy dog"
- bytesData = b"Some binary data"
+ id_val = 1
+ text_data = "The quick brown fox jumps over the lazy dog"
+ binary_data = b"Some binary data"
cursor.execute("insert into lob_tbl (id, c, b) values (:1, :2, :3)",
- [idVal, textData, bytesData])
+ [id_val, text_data, binary_data])
- connection.outputtypehandler = OutputTypeHandler
- cursor.execute("select c, b from lob_tbl where id = :1", [idVal])
- clobData, blobData = cursor.fetchone()
- print("CLOB length:", len(clobData))
- print("CLOB data:", clobData)
- print("BLOB length:", len(blobData))
- print("BLOB data:", blobData)
+ connection.outputtypehandler = output_type_handler
+ cursor.execute("select c, b from lob_tbl where id = :1", [id_val])
+ clob_data, blob_data = cursor.fetchone()
+ print("CLOB length:", len(clob_data))
+ print("CLOB data:", clob_data)
+ print("BLOB length:", len(blob_data))
+ print("BLOB data:", blob_data)
This displays::
@@ -114,13 +114,13 @@ calling :meth:`LOB.size()` and the data can be read by calling
.. code-block:: python
- idVal = 1
- textData = "The quick brown fox jumps over the lazy dog"
- bytesData = b"Some binary data"
+ id_val = 1
+ text_data = "The quick brown fox jumps over the lazy dog"
+ binary_data = b"Some binary data"
cursor.execute("insert into lob_tbl (id, c, b) values (:1, :2, :3)",
- [idVal, textData, bytesData])
+ [id_val, text_data, binary_data])
- cursor.execute("select b, c from lob_tbl where id = :1", [idVal])
+ cursor.execute("select b, c from lob_tbl where id = :1", [id_val])
b, c = cursor.fetchone()
print("CLOB length:", c.size())
print("CLOB data:", c.read())
@@ -140,13 +140,13 @@ repeatedly until all of the data has been read, as shown below:
cursor.execute("select b from lob_tbl where id = :1", [10])
blob, = cursor.fetchone()
offset = 1
- numBytesInChunk = 65536
+ num_bytes_in_chunk = 65536
with open("image.png", "wb") as f:
while True:
- data = blob.read(offset, numBytesInChunk)
+ data = blob.read(offset, num_bytes_in_chunk)
if data:
f.write(data)
- if len(data) < numBytesInChunk:
+ if len(data) < num_bytes_in_chunk:
break
offset += len(data)
@@ -161,21 +161,21 @@ in the following code:
.. code-block:: python
- idVal = 9
- lobVar = cursor.var(cx_Oracle.DB_TYPE_BLOB)
+ id_val = 9
+ lob_var = cursor.var(cx_Oracle.DB_TYPE_BLOB)
cursor.execute("""
insert into lob_tbl (id, b)
values (:1, empty_blob())
- returning b into :2""", [idVal, lobVar])
+ returning b into :2""", [id_val, lob_var])
blob, = lobVar.getvalue()
offset = 1
- numBytesInChunk = 65536
+ num_bytes_in_chunk = 65536
with open("image.png", "rb") as f:
while True:
- data = f.read(numBytesInChunk)
+ data = f.read(num_bytes_in_chunk)
if data:
blob.write(data, offset)
- if len(data) < numBytesInChunk:
+ if len(data) < num_bytes_in_chunk:
break
offset += len(data)
connection.commit()
diff --git a/doc/src/user_guide/plsql_execution.rst b/doc/src/user_guide/plsql_execution.rst
index 9e9367c..7a1306a 100644
--- a/doc/src/user_guide/plsql_execution.rst
+++ b/doc/src/user_guide/plsql_execution.rst
@@ -30,16 +30,16 @@ then the following Python code can be used to call it:
.. code-block:: python
- outVal = cursor.var(int)
- cursor.callproc('myproc', [123, outVal])
- print(outVal.getvalue()) # will print 246
+ out_val = cursor.var(int)
+ cursor.callproc('myproc', [123, out_val])
+ print(out_val.getvalue()) # will print 246
Calling :meth:`Cursor.callproc()` actually generates an anonymous PL/SQL block
as shown below, which is then executed:
.. code-block:: python
- cursor.execute("begin myproc(:1,:2); end;", [123, outval])
+ cursor.execute("begin myproc(:1,:2); end;", [123, out_val])
See :ref:`bind` for information on binding.
@@ -71,8 +71,8 @@ then the following Python code can be used to call it:
.. code-block:: python
- returnVal = cursor.callfunc("myfunc", int, ["a string", 15])
- print(returnVal) # will print 38
+ return_val = cursor.callfunc("myfunc", int, ["a string", 15])
+ print(return_val) # will print 38
A more complex example that returns a spatial (SDO) object can be seen below.
First, the SQL statements necessary to set up the example:
@@ -104,10 +104,10 @@ The Python code that will call this procedure looks as follows:
.. code-block:: python
- objType = connection.gettype("SDO_POINT_TYPE")
+ obj_type = connection.gettype("SDO_POINT_TYPE")
cursor = connection.cursor()
- returnVal = cursor.callfunc("spatial_queryfn", objType, [1])
- print("(%d, %d, %d)" % (returnVal.X, returnVal.Y, returnVal.Z))
+ return_val = cursor.callfunc("spatial_queryfn", obj_type, [1])
+ print(f"({return_val.X}, {return_val.Y}, {return_val.Z})")
# will print (125, 375, 0)
See :ref:`bind` for information on binding.
@@ -123,8 +123,8 @@ An anonymous PL/SQL block can be called as shown:
var = cursor.var(int)
cursor.execute("""
begin
- :outVal := length(:inVal);
- end;""", inVal="A sample string", outVal=var)
+ :out_val := length(:in_val);
+ end;""", in_val="A sample string", out_val=var)
print(var.getvalue()) # will print 15
See :ref:`bind` for information on binding.
@@ -223,18 +223,18 @@ This will produce the following output::
This is the cx_Oracle manual
Demonstrating use of DBMS_OUTPUT
-An alternative is to call ``DBMS_OUTPUT.GET_LINE()`` once per output line, which
-may be much slower:
+An alternative is to call ``DBMS_OUTPUT.GET_LINE()`` once per output line,
+which may be much slower:
.. code-block:: python
- textVar = cursor.var(str)
- statusVar = cursor.var(int)
+ text_var = cursor.var(str)
+ status_var = cursor.var(int)
while True:
- cursor.callproc("dbms_output.get_line", (textVar, statusVar))
- if statusVar.getvalue() != 0:
+ cursor.callproc("dbms_output.get_line", (text_var, status_var))
+ if status_var.getvalue() != 0:
break
- print(textVar.getvalue())
+ print(text_var.getvalue())
Implicit results
----------------
@@ -260,8 +260,8 @@ An example using implicit results is as shown:
dbms_sql.return_result(sales_cur);
end;""")
- for implicitCursor in cursor.getimplicitresults():
- for row in implicitCursor:
+ for implicit_cursor in cursor.getimplicitresults():
+ for row in implicit_cursor:
print(row)
Data from both the result sets are returned::
@@ -289,8 +289,9 @@ The simplest way to set an edition is to pass the ``edition`` parameter to
.. code-block:: python
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
- edition="newsales", encoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1",
+ edition="newsales", encoding="UTF-8")
The edition could also be set by setting the environment variable
@@ -353,22 +354,24 @@ function as shown:
.. code-block:: python
- connection = cx_Oracle.connect(, , "dbhost.example.com/orclpdb1",
- encoding="UTF-8")
+ connection = cx_Oracle.connect(user=user, password=password,
+ dsn="dbhost.example.com/orclpdb1",
+ encoding="UTF-8")
print("Edition is:", repr(connection.edition))
cursor = connection.cursor()
- discountedPrice = cursor.callfunc("Discount", int, [100])
- print("Price after discount is:", discountedPrice)
+ discounted_price = cursor.callfunc("Discount", int, [100])
+ print("Price after discount is:", discounted_price)
# Use the edition parameter for the connection
- connection = cx_Oracle.connect(, , "dbhost.example.com/orclpdb1",
- edition = "demo", encoding="UTF-8")
+ connection = cx_Oracle.connect(user=user, password=password,
+ dsn="dbhost.example.com/orclpdb1",
+ edition="demo", encoding="UTF-8")
print("Edition is:", repr(connection.edition))
cursor = connection.cursor()
- discountedPrice = cursor.callfunc("Discount", int, [100])
- print("Price after discount is:", discountedPrice)
+ discounted_price = cursor.callfunc("Discount", int, [100])
+ print("Price after discount is:", discounted_price)
The output of the function call for the default and demo edition is as shown::
diff --git a/doc/src/user_guide/soda.rst b/doc/src/user_guide/soda.rst
index 6093da1..552aa6e 100644
--- a/doc/src/user_guide/soda.rst
+++ b/doc/src/user_guide/soda.rst
@@ -73,53 +73,6 @@ cx_Oracle uses the following objects for SODA:
then used by a terminal method to find, count, replace, or remove documents.
This is an internal object that should not be directly accessed.
-.. _sodametadatacache:
-
-Using the SODA Metadata Cache
-=============================
-
-SODA metadata can be cached to improve the performance of
-:meth:`SodaDatabase.createCollection()` and
-:meth:`SodaDatabase.openCollection()` by reducing :ref:`round-trips
-` to the database. Caching is available with Oracle Client 21.3 (or
-later). The feature is also available in Oracle Client 19 from 19.11 onwards.
-Note: if collection metadata changes are made externally, the cache can become
-invalid.
-
-Caching can be enabled for pooled connections but not standalone connections.
-Each pool has its own cache. Applications using standalone connections should
-retain and reuse the :ref:`collection ` returned from
-``createCollection()`` or ``openCollection()`` wherever possible, instead of
-making repeated calls to those methods.
-
-The metadata cache can be turned on when creating a connection pool
-with :meth:`cx_Oracle.SessionPool()`:
-
-.. code-block:: python
-
- # Create the session pool
- pool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orclpdb1",
- soda_metadata_cache=True)
-
-Note the cache is not used by ``createCollection()`` when explicitly passing
-metadata. In this case, instead of using only ``createCollection()`` and
-relying on its behavior of opening an existing collection like:
-
-.. code-block:: python
-
- mymetadata = { . . . }
- collection = soda.createCollection("mycollection", mymetadata) # open existing or create new collection
- collection.insertOne(mycontent)
-
-you may find it more efficient to use logic similar to:
-
-.. code-block:: python
-
- collection = soda.openCollection("mycollection")
- if (collection is None):
- mymetadata = { . . . }
- collection = soda.createCollection("mycollection", mymetadata)
- collection.insertOne(mycontent)
SODA Examples
=============
@@ -138,8 +91,8 @@ Creating and adding documents to a collection can be done as follows:
# document, the content can be a simple Python dictionary which will
# internally be converted to a JSON document
content = {'name': 'Matilda', 'address': {'city': 'Melbourne'}}
- returnedDoc = collection.insertOneAndGet(content)
- key = returnedDoc.key
+ returned_doc = collection.insertOneAndGet(content)
+ key = returned_doc.key
print('The key of the new SODA document is: ', key)
By default, a system generated key is created when documents are inserted.
@@ -163,12 +116,65 @@ You can also search for documents using query-by-example syntax:
print(content["name"])
See the `samples directory
-`__
+`__
for runnable SODA examples.
---------------------
+
+.. _sodametadatacache:
+
+Using the SODA Metadata Cache
+=============================
+
+SODA metadata can be cached to improve the performance of
+:meth:`SodaDatabase.createCollection()` and
+:meth:`SodaDatabase.openCollection()` by reducing :ref:`round-trips
+` to the database. Caching is available with Oracle Client 21.3 (or
+later). The feature is also available in Oracle Client 19 from 19.11 onwards.
+Note: if collection metadata changes are made externally, the cache can become
+invalid. If this happens, the cache can be cleared by calling
+:meth:`SessionPool.reconfigure()` with ``soda_metadata_cache`` set to `False`,
+or by setting the attribute :attr:`SessionPool.soda_metadata_cache` to `False`.
+A second call to ``reconfigure()`` or a direct setting of the
+``soda_metadata_cache`` attribute can then be performed to re-enable the cache.
+
+Caching can be enabled for pooled connections but not standalone
+connections. Applications using standalone connections should retain and reuse
+the :ref:`collection ` returned from ``createCollection()`` or
+``openCollection()`` wherever possible, instead of making repeated calls to
+those methods.
+
+The metadata cache can be turned on when creating a connection pool with
+:meth:`cx_Oracle.SessionPool()`. Each pool has its own cache:
+
+.. code-block:: python
+
+ # Create the session pool
+ pool = cx_Oracle.SessionPool(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1",
+ soda_metadata_cache=True)
+
+Note the cache is not used by ``createCollection()`` when explicitly passing
+metadata. In this case, instead of using only ``createCollection()`` and
+relying on its behavior of opening an existing collection like:
+
+.. code-block:: python
+
+ mymetadata = { . . . }
+ collection = soda.createCollection("mycollection", mymetadata) # open existing or create new collection
+ collection.insertOne(mycontent)
+
+you will find it more efficient to use logic similar to:
+
+.. code-block:: python
+
+ collection = soda.openCollection("mycollection")
+ if collection is None:
+ mymetadata = { . . . }
+ collection = soda.createCollection("mycollection", mymetadata)
+ collection.insertOne(mycontent)
+
Committing SODA Work
---------------------
+====================
The general recommendation for SODA applications is to turn on
:attr:`~Connection.autocommit` globally:
diff --git a/doc/src/user_guide/sql_execution.rst b/doc/src/user_guide/sql_execution.rst
index 12c7e3d..dca4179 100644
--- a/doc/src/user_guide/sql_execution.rst
+++ b/doc/src/user_guide/sql_execution.rst
@@ -19,7 +19,7 @@ contain information on specific data types and features. See :ref:`batchstmnt`,
cx_Oracle can be used to execute individual statements, one at a time. It does
not read SQL*Plus ".sql" files. To read SQL files, use a technique like the one
in ``run_sql_script()`` in `samples/sample_env.py
-`__
+`__
SQL statements should not contain a trailing semicolon (";") or forward slash
("/"). This will fail:
@@ -87,9 +87,9 @@ which defaults to the value of :attr:`Cursor.arraysize`.
cur = connection.cursor()
cur.execute("select * from MyTable")
- numRows = 10
+ num_rows = 10
while True:
- rows = cur.fetchmany(numRows)
+ rows = cur.fetchmany(num_rows)
if not rows:
break
for row in rows:
@@ -289,7 +289,7 @@ should be used.
Examples of output handlers are shown in :ref:`numberprecision`,
:ref:`directlobs` and :ref:`fetching-raw-data`. Also see samples such as `samples/type_handlers.py
-`__
+`__
.. _numberprecision:
@@ -324,12 +324,12 @@ Using Python decimal objects, however, there is no loss of precision:
import decimal
- def NumberToDecimal(cursor, name, defaultType, size, precision, scale):
- if defaultType == cx_Oracle.DB_TYPE_NUMBER:
+ def number_to_decimal(cursor, name, default_type, size, precision, scale):
+ if default_type == cx_Oracle.DB_TYPE_NUMBER:
return cursor.var(decimal.Decimal, arraysize=cursor.arraysize)
cur = connection.cursor()
- cur.outputtypehandler = NumberToDecimal
+ cur.outputtypehandler = number_to_decimal
cur.execute("select * from test_float")
val, = cur.fetchone()
print(val, "* 3 =", val * 3)
@@ -341,7 +341,7 @@ representation of the Oracle number. The output from ``decimal.Decimal`` is
returned in the output tuple.
See `samples/return_numbers_as_decimals.py
-`__
+`__
.. _outconverters:
@@ -356,16 +356,17 @@ For example, to make queries return empty strings instead of NULLs:
.. code-block:: python
- def OutConverter(value):
+ def out_converter(value):
if value is None:
return ''
return value
- def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
- if defaultType in (cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.DB_TYPE_CHAR):
- return cursor.var(str, size, cur.arraysize, outconverter=OutConverter)
+ def output_type_handler(cursor, name, default_type, size, precision, scale):
+ if default_type in (cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.DB_TYPE_CHAR):
+ return cursor.var(str, size, arraysize=cur.arraysize,
+ outconverter=out_converter)
- connection.outputtypehandler = OutputTypeHandler
+ connection.outputtypehandler = output_type_handler
.. _rowfactories:
@@ -673,15 +674,15 @@ The following sample demonstrates how to use this feature:
# define output type handler
def return_strings_as_bytes(cursor, name, default_type, size,
precision, scale):
- if default_type == cx_Oracle.DB_TYPE_VARCHAR:
- return cursor.var(str, arraysize=cursor.arraysize,
+ if default_type == cx_Oracle.DB_TYPE_VARCHAR:
+ return cursor.var(str, arraysize=cursor.arraysize,
bypass_decode=True)
- # set output type handler on cursor before fetching data
- with connection.cursor() as cursor:
- cursor.outputtypehandler = return_strings_as_bytes
- cursor.execute("select content, charset from SomeTable")
- data = cursor.fetchall()
+ # set output type handler on cursor before fetching data
+ with connection.cursor() as cursor:
+ cursor.outputtypehandler = return_strings_as_bytes
+ cursor.execute("select content, charset from SomeTable")
+ data = cursor.fetchall()
This will produce output as::
@@ -708,13 +709,13 @@ using a Python string, you will need to create a variable using
with cx_Oracle.connect(user="hr", password=userpwd,
dsn="dbhost.example.com/orclpdb1") as conn:
with conn.cursor() cursor:
- var = cursor.var(cx_Oracle.DB_TYPE_VARCHAR)
- var.setvalue(0, b"Fianc\xc4\x9b")
- cursor.execute("""
- update SomeTable set
- SomeColumn = :param
- where id = 1""",
- param=var)
+ var = cursor.var(cx_Oracle.DB_TYPE_VARCHAR)
+ var.setvalue(0, b"Fianc\xc4\x9b")
+ cursor.execute("""
+ update SomeTable set
+ SomeColumn = :param
+ where id = 1""",
+ param=var)
.. warning::
@@ -737,8 +738,9 @@ then:
.. code-block:: python
- connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
- encoding="UTF-8", nencoding="UTF-8")
+ connection = cx_Oracle.connect(user="hr", password=userpwd,
+ dsn="dbhost.example.com/orclpdb1",
+ encoding="UTF-8", nencoding="UTF-8")
* Check for corrupt data in the database.
@@ -746,21 +748,21 @@ If data really is corrupt, you can pass options to the internal `decode()
`__ used by
cx_Oracle to allow it to be selected and prevent the whole query failing. Do
this by creating an :ref:`outputtypehandler ` and setting
-``encodingErrors``. For example to replace corrupt characters in character
+``encoding_errors``. For example to replace corrupt characters in character
columns:
.. code-block:: python
- def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
- if defaultType == cx_Oracle.STRING:
- return cursor.var(defaultType, size, arraysize=cursor.arraysize,
- encodingErrors="replace")
+ def output_type_handler(cursor, name, default_type, size, precision, scale):
+ if default_type == cx_Oracle.DB_TYPE_VARCHAR:
+ return cursor.var(default_type, size, arraysize=cursor.arraysize,
+ encoding_errors="replace")
- cursor.outputtypehandler = OutputTypeHandler
+ cursor.outputtypehandler = output_type_handler
cursor.execute("select column1, column2 from SomeTableWithBadData")
-Other codec behaviors can be chosen for ``encodingErrors``, see `Error Handlers
+Other codec behaviors can be chosen for ``encoding_errors``, see `Error Handlers
`__.
.. _dml:
@@ -797,7 +799,7 @@ SDO_GEOMETRY ` object:
.. code-block:: python
- typeObj = connection.gettype("SDO_GEOMETRY")
+ type_obj = connection.gettype("SDO_GEOMETRY")
cur = connection.cursor()
- cur.setinputsizes(typeObj)
+ cur.setinputsizes(type_obj)
cur.execute("insert into sometable values (:1)", [None])
diff --git a/doc/src/user_guide/startup.rst b/doc/src/user_guide/startup.rst
index a48f2d4..527a877 100644
--- a/doc/src/user_guide/startup.rst
+++ b/doc/src/user_guide/startup.rst
@@ -20,12 +20,11 @@ of the database that should be started:
.. code-block:: python
# the connection must be in PRELIM_AUTH mode to perform startup
- connection = cx_Oracle.connect("/",
- mode = cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH)
+ connection = cx_Oracle.connect(mode=cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH)
connection.startup()
# the following statements must be issued in normal SYSDBA mode
- connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA, encoding="UTF-8")
+ connection = cx_Oracle.connect(mode=cx_Oracle.SYSDBA, encoding="UTF-8")
cursor = connection.cursor()
cursor.execute("alter database mount")
cursor.execute("alter database open")
@@ -48,11 +47,11 @@ connection. This example also assumes that the environment variable
.. code-block:: python
# need to connect as SYSDBA or SYSOPER
- connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA)
+ connection = cx_Oracle.connect(mode=cx_Oracle.SYSDBA)
# first shutdown() call must specify the mode, if DBSHUTDOWN_ABORT is used,
# there is no need for any of the other steps
- connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_IMMEDIATE)
+ connection.shutdown(mode=cx_Oracle.DBSHUTDOWN_IMMEDIATE)
# now close and dismount the database
cursor = connection.cursor()
@@ -60,4 +59,4 @@ connection. This example also assumes that the environment variable
cursor.execute("alter database dismount")
# perform the final shutdown call
- connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_FINAL)
+ connection.shutdown(mode=cx_Oracle.DBSHUTDOWN_FINAL)
diff --git a/doc/src/user_guide/tracing_sql.rst b/doc/src/user_guide/tracing_sql.rst
index 0ef716e..a1e1d3e 100644
--- a/doc/src/user_guide/tracing_sql.rst
+++ b/doc/src/user_guide/tracing_sql.rst
@@ -18,15 +18,15 @@ in the custom subclass, so application code does not need to supply them.
.. code-block:: python
class Connection(cx_Oracle.Connection):
- logFileName = "log.txt"
+ log_file_name = "log.txt"
def __init__(self):
- connectString = "hr/hr_password@dbhost.example.com/orclpdb1"
+ connect_string = "hr/hr_password@dbhost.example.com/orclpdb1"
self._log("Connect to the database")
- return super(Connection, self).__init__(connectString)
+ return super(Connection, self).__init__(connect_string)
def _log(self, message):
- with open(self.logFileName, "a") as f:
+ with open(self.log_file_name, "a") as f:
print(message, file=f)
def execute(self, sql, parameters):
@@ -35,8 +35,9 @@ in the custom subclass, so application code does not need to supply them.
try:
return cursor.execute(sql, parameters)
except cx_Oracle.Error as e:
- errorObj, = e.args
- self._log(errorObj.message)
+ error_obj, = e.args
+ self._log(error_obj.message)
+ raise
connection = Connection()
connection.execute("""
@@ -65,7 +66,7 @@ instead::
In production applications be careful not to log sensitive information.
See `Subclassing.py
-`__ for an example.
diff --git a/doc/src/user_guide/tuning.rst b/doc/src/user_guide/tuning.rst
index 80253a0..ba3bea8 100644
--- a/doc/src/user_guide/tuning.rst
+++ b/doc/src/user_guide/tuning.rst
@@ -200,18 +200,18 @@ data from one database to another:
.. code-block:: python
# setup cursors
- sourceCursor = sourceConnection.cursor()
- sourceCursor.arraysize = 1000
- targetCursor = targetConnection.cursor()
+ source_cursor = source_connection.cursor()
+ source_cursor.arraysize = 1000
+ target_cursor = target_connection.cursor()
# perform fetch and bulk insertion
- sourceCursor.execute("select * from MyTable")
+ source_cursor.execute("select * from MyTable")
while True:
- rows = sourceCursor.fetchmany()
+ rows = source_cursor.fetchmany()
if not rows:
break
- targetCursor.executemany("insert into MyTable values (:1, :2)", rows)
- targetConnection.commit()
+ target_cursor.executemany("insert into MyTable values (:1, :2)", rows)
+ target_connection.commit()
Tuning REF CURSORS
++++++++++++++++++
diff --git a/doc/src/user_guide/txn_management.rst b/doc/src/user_guide/txn_management.rst
index 4679621..9e8985a 100644
--- a/doc/src/user_guide/txn_management.rst
+++ b/doc/src/user_guide/txn_management.rst
@@ -49,17 +49,17 @@ records:
.. code-block:: python
# Add a new customer
- idVar = cursor.var(int)
+ id_var = cursor.var(int)
connection.autocommit = False # make sure any previous value is off
cursor.execute("""
INSERT INTO cust_table (name) VALUES ('John')
- RETURNING id INTO :bvid""", bvid=idVar)
+ RETURNING id INTO :bvid""", bvid=id_var)
# Add sales data for the new customer and commit all new values
- idVal = idVar.getvalue()[0]
+ id_val = id_var.getvalue()[0]
connection.autocommit = True
cursor.execute("INSERT INTO sales_table VALUES (:bvid, 'pens', 3000)",
- bvid=idVal)
+ bvid=id_val)
Explicit Transactions
diff --git a/doc/src/user_guide/xml_data_type.rst b/doc/src/user_guide/xml_data_type.rst
index 4fa79d2..e0e0a06 100644
--- a/doc/src/user_guide/xml_data_type.rst
+++ b/doc/src/user_guide/xml_data_type.rst
@@ -22,7 +22,7 @@ Inserting into the table can be done by simply binding a string as shown:
.. code-block:: python
- xmlData = """
+ xml_data = """
John Smith
43
@@ -30,7 +30,7 @@ Inserting into the table can be done by simply binding a string as shown:
Mathematics
"""
cursor.execute("insert into xml_table values (:id, :xml)",
- id=1, xml=xmlData)
+ id=1, xml=xml_data)
This approach works with XML strings up to 1 GB in size. For longer strings, a
temporary CLOB must be created using :meth:`Connection.createlob()` and bound
@@ -39,9 +39,9 @@ as shown:
.. code-block:: python
clob = connection.createlob(cx_Oracle.DB_TYPE_CLOB)
- clob.write(xmlData)
+ clob.write(xml_data)
cursor.execute("insert into xml_table values (:id, sys.xmltype(:xml))",
- id=2, xml=clob)
+ id=2, xml=clob)
Fetching XML data can be done simply for values that are shorter than the
length of a VARCHAR2 column, as shown:
@@ -49,8 +49,8 @@ length of a VARCHAR2 column, as shown:
.. code-block:: python
cursor.execute("select xml_data from xml_table where id = :id", id=1)
- xmlData, = cursor.fetchone()
- print(xmlData) # will print the string that was originally stored
+ xml_data, = cursor.fetchone()
+ print(xml_data) # will print the string that was originally stored
For values that exceed the length of a VARCHAR2 column, a CLOB must be returned
instead by using the function ``XMLTYPE.GETCLOBVAL()`` as shown:
diff --git a/samples/README.md b/samples/README.md
index 3970078..d2493e2 100644
--- a/samples/README.md
+++ b/samples/README.md
@@ -36,10 +36,10 @@ This directory contains samples for [cx_Oracle][6]. Documentation is [here][7].
sqlplus sys/syspassword@hostname/servicename @sql/drop_samples.sql
-[1]: https://github.com/oracle/python-cx_Oracle/blob/master/samples/setup_samples.py
-[2]: https://github.com/oracle/python-cx_Oracle/blob/master/samples/sample_env.py
-[3]: https://github.com/oracle/python-cx_Oracle/blob/master/samples/sql/setup_samples.sql
-[4]: https://github.com/oracle/python-cx_Oracle/blob/master/samples/drop_samples.py
-[5]: https://github.com/oracle/python-cx_Oracle/blob/master/samples/sql/drop_samples.sql
+[1]: https://github.com/oracle/python-cx_Oracle/blob/main/samples/setup_samples.py
+[2]: https://github.com/oracle/python-cx_Oracle/blob/main/samples/sample_env.py
+[3]: https://github.com/oracle/python-cx_Oracle/blob/main/samples/sql/setup_samples.sql
+[4]: https://github.com/oracle/python-cx_Oracle/blob/main/samples/drop_samples.py
+[5]: https://github.com/oracle/python-cx_Oracle/blob/main/samples/sql/drop_samples.sql
[6]: https://oracle.github.io/python-cx_Oracle/
[7]: http://cx-oracle.readthedocs.org/en/latest/index.html
diff --git a/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html b/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html
index 596c8f6..ded7787 100644
--- a/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html
+++ b/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html
@@ -117,7 +117,7 @@
href="http://cx-oracle.readthedocs.org/en/latest/index.html" >cx_Oracle
documention.
- The master copy of these instructions that you are reading is The original copy of these instructions that you are reading is here.
@@ -165,9 +165,9 @@
Download the tutorial scripts
- The Python scripts used in this example are in the cx_Oracle GitHub repository.
+ The Python scripts used in this example are in the cx_Oracle GitHub repository.
- Download a zip file of the repository from here and unzip it. Alternatively you can use 'git' to clone the repository with git clone https://github.com/oracle/python-cx_Oracle.git
+ Download a zip file of the repository from here and unzip it. Alternatively you can use 'git' to clone the repository with git clone https://github.com/oracle/python-cx_Oracle.git
The samples/tutorial directory has scripts to run and
modify. The samples/tutorial/solutions directory has scripts
diff --git a/setup.cfg b/setup.cfg
index 5ec4590..4260087 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -10,7 +10,7 @@ license = BSD License
url = https://oracle.github.io/python-cx_Oracle
project_urls =
Installation = https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html
- Samples = https://github.com/oracle/python-cx_Oracle/tree/master/samples
+ Samples = https://github.com/oracle/python-cx_Oracle/tree/main/samples
Documentation = http://cx-oracle.readthedocs.io
Release Notes = https://cx-oracle.readthedocs.io/en/latest/release_notes.html#releasenotes
Issues = https://github.com/oracle/python-cx_Oracle/issues
diff --git a/test/README.md b/test/README.md
index bda6800..6f88126 100644
--- a/test/README.md
+++ b/test/README.md
@@ -46,8 +46,8 @@ This directory contains the test suite for cx_Oracle.
sqlplus system/systempassword@hostname/servicename @sql/drop_test.sql
-[1]: https://github.com/oracle/python-cx_Oracle/blob/master/test/setup_test.py
-[2]: https://github.com/oracle/python-cx_Oracle/blob/master/test/test_env.py
-[3]: https://github.com/oracle/python-cx_Oracle/blob/master/test/sql/setup_test.sql
-[4]: https://github.com/oracle/python-cx_Oracle/blob/master/test/drop_test.py
-[5]: https://github.com/oracle/python-cx_Oracle/blob/master/test/sql/drop_test.sql
+[1]: https://github.com/oracle/python-cx_Oracle/blob/main/test/setup_test.py
+[2]: https://github.com/oracle/python-cx_Oracle/blob/main/test/test_env.py
+[3]: https://github.com/oracle/python-cx_Oracle/blob/main/test/sql/setup_test.sql
+[4]: https://github.com/oracle/python-cx_Oracle/blob/main/test/drop_test.py
+[5]: https://github.com/oracle/python-cx_Oracle/blob/main/test/sql/drop_test.sql