Codebase list python-cx-oracle / e278c43
Import upstream version 8.0.1 Kali Janitor 3 years ago
212 changed file(s) with 18800 addition(s) and 9678 deletion(s). Raw diff Collapse all Expand all
0 ---
1 name: Announcements
2 about: Use this if you are sharing something interesting
3 title: ''
4 labels: announcement
5 assignees: ''
6
7 ---
8
9 Let us know if you are speaking at a conference on cx_Oracle, or have a new package or app that uses cx_Oracle, or something similarly exciting.
0 ---
1 name: Bug report
2 about: Create a report to help us improve
3 title: ''
4 labels: bug
5 assignees: ''
6
7 ---
8
9 **See https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html for how to report security issues**.
10
11 For other issues:
12
13 1. Is it an error or a hang or a crash?
14
15 2. What error(s) you are seeing?
16 **Cut and paste text showing the command you ran. No screenshots. Use a gist for long screen output and logs: see https://gist.github.com/**.
17
18 3. Include a runnable Python script that shows the problem.
19 Include all SQL needed to create the database schema.
20
21 4. Show the output of:
22
23 ```
24 import sys
25 import platform
26
27 print("platform.platform:", platform.platform())
28 print("sys.maxsize > 2**32:", sys.maxsize > 2**32)
29 print("platform.python_version:", platform.python_version())
30 ```
31
32 And:
33
34 ```
35 import cx_Oracle
36 print("cx_Oracle.version:", cx_Oracle.version)
37 print("cx_Oracle.clientversion:", cx_Oracle.clientversion())
38 ```
39
40 5. What is your Oracle Database version?
0 ---
1 name: Documentation and Example Improvements
2 about: Use this to suggest changes to documentation and examples
3 title: ''
4 labels: enhancement
5 assignees: ''
6
7 ---
8
9 - Include a link to the documentation section or the example
10
11 - Describe the confusion
12
13 - Suggest changes that would help
0 ---
1 name: Enhancement Requests
2 about: Use this for enhancement requests
3 title: ''
4 labels: enhancement
5 assignees: ''
6
7 ---
8
9 1. Review existing [enhancement requests](https://github.com/oracle/python-cx_Oracle/labels/enhancement)
10
11 2. Describe your new request in detail
12
13 3. Give supporting information about tools and operating systems. Give relevant product version numbers
0 ---
1 name: General Questions and Runtime Problems
2 about: For general cx_Oracle questions
3 title: ''
4 labels: question
5 assignees: ''
6
7 ---
8
9 1. Review the [cx_Oracle Documentation](https://cx-oracle.readthedocs.io/en/latest/index.html). Review your output and logs. **Google any errors**
10
11 2. Describe the problem
12 **Cut and paste text showing the command you ran. No screenshots. Use a gist for long screen output and logs: see https://gist.github.com/**.
13
14 3. Include a runnable Python script that shows the problem. Include all SQL needed to create the database schema. Use Markdown syntax, see https://help.github.com/github/writing-on-github/basic-writing-and-formatting-syntax
15
16 The more details you give, the more we can help.
17
18 4. Show the output of:
19
20 ```
21 import sys
22 import platform
23
24 print("platform.platform:", platform.platform())
25 print("sys.maxsize > 2**32:", sys.maxsize > 2**32)
26 print("platform.python_version:", platform.python_version())
27 ```
28
29 And:
30
31 ```
32 import cx_Oracle
33 print("cx_Oracle.version:", cx_Oracle.version)
34 print("cx_Oracle.clientversion:", cx_Oracle.clientversion())
35 ```
36
37 5. What is your Oracle Database version?
0 ---
1 name: Installation Questions
2 about: Use this for cx_Oracle installation questions
3 title: ''
4 labels: install & configuration
5 assignees: ''
6
7 ---
8
9 # Do these first
10
11 - Review and follow the [installation instructions](https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html)
12
13 - Review the [troubleshooting tips](https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html#troubleshooting)
14
15 - If you have a `DPI-1047`, `DPI-1050` or `DPI-1072` error, review both the above again before opening an issue.
16
17 - **Google any errors**
18
19 # Answer the following questions
20
21 1. Describe the problem and show the error you have.
22 **Cut and paste text showing the command you ran. No screenshots. Use a gist for long screen output and logs: see https://gist.github.com/**.
23
24 2. Show the output of:
25
26 ```
27 import sys
28 import platform
29
30 print("platform.platform:", platform.platform())
31 print("sys.maxsize > 2**32:", sys.maxsize > 2**32)
32 print("platform.python_version:", platform.python_version())
33 ```
34
35 3. Show the directory listing where your Oracle client libraries are installed (e.g. the Instant Client directory). Is it 64-bit or 32-bit?
36
37 4. Show what the `PATH` environment variable (on Windows) or `LD_LIBRARY_PATH` (on Linux) is set to? On macOS, show what is in `~/lib`.
38
39 5. Show any Oracle environment variables set (e.g. ORACLE_HOME, ORACLE_BASE).
+0
-45
.github/issue_template.md less more
0 *Delete unnecessary parts of this template.*
1
2 ### For security issues:
3
4 See https://www.oracle.com/support/assurance/vulnerability-remediation/reporting-security-vulnerabilities.html for how to report security issues.
5
6 ### For general questions:
7
8 Describe exactly what you did and what you want to happen.
9 Use the questions at the bottom of this template as a guide.
10
11 Use Markdown syntax, particularly for code blocks: see https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code
12
13 ### For installation issues:
14
15 Use a gist for screen output and logs: see https://gist.github.com/
16 **Do not paste long output into this issue**
17
18 Review your output and logs. **Google any errors**
19 Try to install in a different way. Try some potential solutions.
20
21 Review the install instructions at
22 http://cx-oracle.readthedocs.io/en/latest/installation.html
23
24 #### Answer the following questions:
25
26 1. What is your version of Python? Is it 32-bit or 64-bit?
27
28 2. What is your cx_Oracle version?
29
30 3. What *exact* command caused the problem (e.g. what command did you try to install with)? Who were you logged in as?
31
32 4. What error(s) you are seeing?
33
34 5. What OS (and version) is Python executing on?
35
36 6. What is your version of the Oracle client (e.g. Instant Client)? How was it installed? Where is it installed?
37
38 7. What is your Oracle Database version?
39
40 8. What is the `PATH` environment variable (on Windows) or `LD_LIBRARY_PATH` (on Linux) set to? On macOS, what is in `~/lib`?
41
42 9. What Oracle environment variables did you set? How *exactly* did you set them?
43
44 10. Do you have a small, single Python script that immediately runs to show us the problem?
00 [submodule "odpi"]
11 path = odpi
22 url = ../odpi.git
3 branch = v3.1.x
0 # cx_Oracle version 7.1
0 # cx_Oracle version 8.0
11
22 cx_Oracle is a Python extension module that enables access to Oracle
33 Database. It conforms to the [Python database API 2.0
66 [homepage](https://oracle.github.io/python-cx_Oracle/index.html) for a
77 feature list.
88
9 cx_Oracle 7 has been tested with Python version 2.7, and with versions
10 3.5 and higher. You can use cx_Oracle with Oracle 11.2 and higher client
11 libraries (including Oracle 18.3). Oracle's standard client-server version
12 interoperability allows connection to both older and newer databases,
13 for example Oracle 18.3 client libraries can connect to Oracle
14 Database 11.2.
9 cx_Oracle 8 has been tested with Python versions 3.5 through 3.8. You can use
10 cx_Oracle with Oracle 11.2, 12c, 18c and 19c client libraries. Oracle's
11 standard client-server version interoperability allows connection to both older
12 and newer databases. For example Oracle 19c client libraries can connect to
13 Oracle Database 11.2. Older versions of cx_Oracle may work with older
14 versions of Python.
1515
1616 ## Installation
1717
5454 [9]: https://github.com/oracle/python-cx_Oracle/issues
5555 [11]: https://github.com/oracle/python-cx_Oracle/tree/master/test
5656 [12]: https://github.com/oracle/python-cx_Oracle/tree/master/samples
57 [14]: http://cx-oracle.readthedocs.io/en/latest/releasenotes.html
58 [15]: http://cx-oracle.readthedocs.io/en/latest/installation.html
57 [14]: https://cx-oracle.readthedocs.io/en/latest/release_notes.html
58 [15]: https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html
0 .. _aq:
1
2 *********************
3 Advanced Queuing (AQ)
4 *********************
5
6 See :ref:`aqusermanual` for more information about using AQ in cx_Oracle.
7
8 .. note::
9
10 All of these objects are extensions to the DB API.
11
12 .. _queue:
13
14 ------
15 Queues
16 ------
17
18 These objects are created using the :meth:`Connection.queue()` method and are
19 used to enqueue and dequeue messages.
20
21 .. attribute:: Queue.connection
22
23 This read-only attribute returns a reference to the connection object on
24 which the queue was created.
25
26
27 .. method:: Queue.deqMany(maxMessages)
28
29 Dequeues up to the specified number of messages from the queue and returns
30 a list of these messages. Each element of the returned list is a
31 :ref:`message property<msgproperties>` object.
32
33
34 .. method:: Queue.deqOne()
35
36 Dequeues at most one message from the queue. If a message is dequeued, it
37 will be a :ref:`message property<msgproperties>` object; otherwise, it will
38 be the value None.
39
40 .. attribute:: Queue.deqOptions
41
42 This read-only attribute returns a reference to the :ref:`options
43 <deqoptions>` that will be used when dequeuing messages from the queue.
44
45
46 .. method:: Queue.enqOne(message)
47
48 Enqueues a single message into the queue. The message must be a
49 :ref:`message property<msgproperties>` object which has had its payload
50 attribute set to a value that the queue supports.
51
52
53 .. method:: Queue.enqMany(messages)
54
55 Enqueues multiple messages into the queue. The messages parameter must be a
56 sequence containing :ref:`message property <msgproperties>` objects which
57 have all had their payload attribute set to a value that the queue
58 supports.
59
60 Warning: calling this function in parallel on different connections
61 acquired from the same pool may fail due to Oracle bug 29928074. Ensure
62 that this function is not run in parallel, use standalone connections or
63 connections from different pools, or make multiple calls to
64 :meth:`Queue.enqOne()` instead. The function :meth:`Queue.deqMany()`
65 call is not affected.
66
67
68 .. attribute:: Queue.enqOptions
69
70 This read-only attribute returns a reference to the :ref:`options
71 <enqoptions>` that will be used when enqueuing messages into the queue.
72
73
74 .. attribute:: Queue.name
75
76 This read-only attribute returns the name of the queue.
77
78
79 .. attribute:: Queue.payloadType
80
81 This read-only attribute returns the object type for payloads that can be
82 enqueued and dequeued. If using a raw queue, this returns the value None.
83
84
85 .. _deqoptions:
86
87 ---------------
88 Dequeue Options
89 ---------------
90
91 .. note::
92
93 These objects are used to configure how messages are dequeued from queues.
94 An instance of this object is found in the attribute
95 :attr:`Queue.deqOptions`.
96
97
98 .. attribute:: DeqOptions.condition
99
100 This attribute specifies a boolean expression similar to the where clause
101 of a SQL query. The boolean expression can include conditions on message
102 properties, user data properties and PL/SQL or SQL functions. The default
103 is to have no condition specified.
104
105
106 .. attribute:: DeqOptions.consumername
107
108 This attribute specifies the name of the consumer. Only messages matching
109 the consumer name will be accessed. If the queue is not set up for multiple
110 consumers this attribute should not be set. The default is to have no
111 consumer name specified.
112
113
114 .. attribute:: DeqOptions.correlation
115
116 This attribute specifies the correlation identifier of the message to be
117 dequeued. Special pattern-matching characters, such as the percent sign (%)
118 and the underscore (_), can be used. If multiple messages satisfy the
119 pattern, the order of dequeuing is indeterminate. The default is to have no
120 correlation specified.
121
122
123 .. attribute:: DeqOptions.deliverymode
124
125 This write-only attribute specifies what types of messages should be
126 dequeued. It should be one of the values :data:`~cx_Oracle.MSG_PERSISTENT`
127 (default), :data:`~cx_Oracle.MSG_BUFFERED` or
128 :data:`~cx_Oracle.MSG_PERSISTENT_OR_BUFFERED`.
129
130
131 .. attribute:: DeqOptions.mode
132
133 This attribute specifies the locking behaviour associated with the dequeue
134 operation. It should be one of the values :data:`~cx_Oracle.DEQ_BROWSE`,
135 :data:`~cx_Oracle.DEQ_LOCKED`,
136 :data:`~cx_Oracle.DEQ_REMOVE` (default), or
137 :data:`~cx_Oracle.DEQ_REMOVE_NODATA`.
138
139
140 .. attribute:: DeqOptions.msgid
141
142 This attribute specifies the identifier of the message to be dequeued. The
143 default is to have no message identifier specified.
144
145
146 .. attribute:: DeqOptions.navigation
147
148 This attribute specifies the position of the message that is retrieved. It
149 should be one of the values :data:`~cx_Oracle.DEQ_FIRST_MSG`,
150 :data:`~cx_Oracle.DEQ_NEXT_MSG` (default), or
151 :data:`~cx_Oracle.DEQ_NEXT_TRANSACTION`.
152
153
154 .. attribute:: DeqOptions.transformation
155
156 This attribute specifies the name of the transformation that must be
157 applied after the message is dequeued from the database but before it is
158 returned to the calling application. The transformation must be created
159 using dbms_transform. The default is to have no transformation specified.
160
161
162 .. attribute:: DeqOptions.visibility
163
164 This attribute specifies the transactional behavior of the dequeue request.
165 It should be one of the values :data:`~cx_Oracle.DEQ_ON_COMMIT` (default)
166 or :data:`~cx_Oracle.DEQ_IMMEDIATE`. This attribute is ignored when using
167 the :data:`~cx_Oracle.DEQ_BROWSE` mode. Note the value of
168 :attr:`~Connection.autocommit` is always ignored.
169
170
171 .. attribute:: DeqOptions.wait
172
173 This attribute specifies the time to wait, in seconds, for a message
174 matching the search criteria to become available for dequeuing. One of the
175 values :data:`~cx_Oracle.DEQ_NO_WAIT` or
176 :data:`~cx_Oracle.DEQ_WAIT_FOREVER` can also be used. The default is
177 :data:`~cx_Oracle.DEQ_WAIT_FOREVER`.
178
179
180 .. _enqoptions:
181
182 ---------------
183 Enqueue Options
184 ---------------
185
186 .. note::
187
188 These objects are used to configure how messages are enqueued into queues.
189 An instance of this object is found in the attribute
190 :attr:`Queue.enqOptions`.
191
192
193 .. attribute:: EnqOptions.deliverymode
194
195 This write-only attribute specifies what type of messages should be
196 enqueued. It should be one of the values :data:`~cx_Oracle.MSG_PERSISTENT`
197 (default) or :data:`~cx_Oracle.MSG_BUFFERED`.
198
199
200 .. attribute:: EnqOptions.transformation
201
202 This attribute specifies the name of the transformation that must be
203 applied before the message is enqueued into the database. The
204 transformation must be created using dbms_transform. The default is to have
205 no transformation specified.
206
207
208 .. attribute:: EnqOptions.visibility
209
210 This attribute specifies the transactional behavior of the enqueue request.
211 It should be one of the values :data:`~cx_Oracle.ENQ_ON_COMMIT` (default)
212 or :data:`~cx_Oracle.ENQ_IMMEDIATE`. Note the value of
213 :attr:`~Connection.autocommit` is ignored.
214
215
216 .. _msgproperties:
217
218 ------------------
219 Message Properties
220 ------------------
221
222 .. note::
223
224 These objects are used to identify the properties of messages that are
225 enqueued and dequeued in queues. They are created by the method
226 :meth:`Connection.msgproperties()`. They are used by the methods
227 :meth:`Queue.enqOne()` and :meth:`Queue.enqMany()` and
228 returned by the methods :meth:`Queue.deqOne()` and :meth:`Queue.deqMany()`.
229
230
231 .. attribute:: MessageProperties.attempts
232
233 This read-only attribute specifies the number of attempts that have been
234 made to dequeue the message.
235
236
237 .. attribute:: MessageProperties.correlation
238
239 This attribute specifies the correlation used when the message was
240 enqueued.
241
242
243 .. attribute:: MessageProperties.delay
244
245 This attribute specifies the number of seconds to delay an enqueued
246 message. Any integer is acceptable but the constant
247 :data:`~cx_Oracle.MSG_NO_DELAY` can also be used indicating that the
248 message is available for immediate dequeuing.
249
250
251 .. attribute:: MessageProperties.deliverymode
252
253 This read-only attribute specifies the type of message that was dequeued.
254 It will be one of the values :data:`~cx_Oracle.MSG_PERSISTENT` or
255 :data:`~cx_Oracle.MSG_BUFFERED`.
256
257
258 .. attribute:: MessageProperties.enqtime
259
260 This read-only attribute specifies the time that the message was enqueued.
261
262
263 .. attribute:: MessageProperties.exceptionq
264
265 This attribute specifies the name of the queue to which the message is
266 moved if it cannot be processed successfully. Messages are moved if the
267 number of unsuccessful dequeue attempts has exceeded the maximum number of
268 retries or if the message has expired. All messages in the exception queue
269 are in the :data:`~cx_Oracle.MSG_EXPIRED` state. The default value is the
270 name of the exception queue associated with the queue table.
271
272
273 .. attribute:: MessageProperties.expiration
274
275 This attribute specifies, in seconds, how long the message is available for
276 dequeuing. This attribute is an offset from the delay attribute. Expiration
277 processing requires the queue monitor to be running. Any integer is
278 accepted but the constant :data:`~cx_Oracle.MSG_NO_EXPIRATION` can also be
279 used indicating that the message never expires.
280
281
282 .. attribute:: MessageProperties.msgid
283
284 This attribute specifies the id of the message in the last queue that
285 generated this message.
286
287
288 .. attribute:: MessageProperties.payload
289
290 This attribute identifies the payload that will be enqueued or the payload
291 that was dequeued when using a :ref:`queue <queue>`. When enqueuing, the
292 value is checked to ensure that it conforms to the type expected by that
293 queue. For RAW queues, the value can be a bytes object or a string. If the
294 value is a string it will first be converted to bytes by encoding in the
295 encoding identified by the attribute :attr:`Connection.encoding`.
296
297
298 .. attribute:: MessageProperties.priority
299
300 This attribute specifies the priority of the message. A smaller number
301 indicates a higher priority. The priority can be any integer, including
302 negative numbers. The default value is zero.
303
304
305 .. attribute:: MessageProperties.state
306
307 This read-only attribute specifies the state of the message at the time of
308 the dequeue. It will be one of the values :data:`~cx_Oracle.MSG_WAITING`,
309 :data:`~cx_Oracle.MSG_READY`, :data:`~cx_Oracle.MSG_PROCESSED` or
310 :data:`~cx_Oracle.MSG_EXPIRED`.
0 .. _connobj:
1
2 *****************
3 Connection Object
4 *****************
5
6 .. note::
7
8 Any outstanding changes will be rolled back when the connection object
9 is destroyed or closed.
10
11
12
13 .. method:: Connection.__enter__()
14
15 The entry point for the connection as a context manager. It returns itself.
16
17 .. note::
18
19 This method is an extension to the DB API definition.
20
21
22 .. method:: Connection.__exit__()
23
24 The exit point for the connection as a context manager. This will close
25 the connection and roll back any uncommitted transaction.
26
27 .. note::
28
29 This method is an extension to the DB API definition.
30
31
32 .. attribute:: Connection.action
33
34 This write-only attribute sets the action column in the v$session table. It
35 is a string attribute and cannot be set to None -- use the empty string
36 instead.
37
38 .. note::
39
40 This attribute is an extension to the DB API definition.
41
42
43 .. attribute:: Connection.autocommit
44
45 This read-write attribute determines whether autocommit mode is on or off.
46 When autocommit mode is on, all statements are committed as soon as they
47 have completed executing.
48
49 .. note::
50
51 This attribute is an extension to the DB API definition.
52
53
54 .. method:: Connection.begin([formatId, transactionId, branchId])
55
56 Explicitly begin a new transaction. Without parameters, this explicitly
57 begins a local transaction; otherwise, this explicitly begins a distributed
58 (global) transaction with the given parameters. See the Oracle
59 documentation for more details.
60
61 Note that in order to make use of global (distributed) transactions, the
62 :attr:`~Connection.internal_name` and :attr:`~Connection.external_name`
63 attributes must be set.
64
65 .. note::
66
67 This method is an extension to the DB API definition.
68
69
70 .. attribute:: Connection.callTimeout
71
72 This read-write attribute specifies the amount of time (in milliseconds)
73 that a single round-trip to the database may take before a timeout will
74 occur. A value of 0 means that no timeout will take place.
75
76 .. versionadded:: 7.0
77
78 .. note::
79
80 This attribute is an extension to the DB API definition and is only
81 available in Oracle Client 18c and higher.
82
83
84 .. method:: Connection.cancel()
85
86 Cancel a long-running transaction.
87
88 .. note::
89
90 This method is an extension to the DB API definition.
91
92
93 .. method:: Connection.changepassword(oldpassword, newpassword)
94
95 Change the password of the logon.
96
97 .. note::
98
99 This method is an extension to the DB API definition.
100
101
102 .. attribute:: Connection.client_identifier
103
104 This write-only attribute sets the client_identifier column in the
105 v$session table.
106
107 .. note::
108
109 This attribute is an extension to the DB API definition.
110
111
112 .. attribute:: Connection.clientinfo
113
114 This write-only attribute sets the client_info column in the v$session
115 table.
116
117 .. note::
118
119 This attribute is an extension to the DB API definition.
120
121
122 .. method:: Connection.close()
123
124 Close the connection now, rather than whenever __del__ is called. The
125 connection will be unusable from this point forward; an Error exception
126 will be raised if any operation is attempted with the connection.
127
128 All open cursors and LOBs created by the connection will be closed and will
129 also no longer be usable.
130
131 Internally, references to the connection are held by cursor objects,
132 LOB objects, subscription objects, etc. Once all of these references are
133 released, the connection itself will be closed automatically. Either
134 control references to these related objects carefully or explicitly close
135 connections in order to ensure sufficient resources are available.
136
137
138 .. method:: Connection.commit()
139
140 Commit any pending transactions to the database.
141
142
143 .. method:: Connection.createlob(lobType)
144
145 Create and return a new temporary :ref:`LOB object <lobobj>` of the
146 specified type. The lobType parameter should be one of
147 :data:`cx_Oracle.CLOB`, :data:`cx_Oracle.BLOB` or :data:`cx_Oracle.NCLOB`.
148
149 .. versionadded:: 6.2
150
151 .. note::
152
153 This method is an extension to the DB API definition.
154
155
156 .. attribute:: Connection.current_schema
157
158 This read-write attribute sets the current schema attribute for the
159 session. Setting this value is the same as executing the SQL statement
160 "ALTER SESSION SET CURRENT_SCHEMA". The attribute is set (and verified) on
161 the next call that does a round trip to the server. The value is placed
162 before unqualified database objects in SQL statements you then execute.
163
164 .. note::
165
166 This attribute is an extension to the DB API definition.
167
168
169 .. method:: Connection.cursor()
170
171 Return a new :ref:`cursor object <cursorobj>` using the connection.
172
173
174 .. attribute:: Connection.dbop
175
176 This write-only attribute sets the database operation that is to be
177 monitored. This can be viewed in the DBOP_NAME column of the V$SQL_MONITOR
178 table.
179
180 .. note::
181
182 This attribute is an extension to the DB API definition.
183
184
185 .. method:: Connection.deq(name, options, msgproperties, payload)
186
187 Returns a message id after successfully dequeuing a message. The options
188 object can be created using :meth:`~Connection.deqoptions()` and the
189 msgproperties object can be created using
190 :meth:`~Connection.msgproperties()`. The payload must be an object created
191 using :meth:`ObjectType.newobject()`.
192
193 .. versionadded:: 5.3
194
195 .. deprecated:: 7.2
196
197 Use the methods :meth:`Queue.deqOne()` or :meth:`Queue.deqMany()`
198 instead.
199
200 .. note::
201
202 This method is an extension to the DB API definition.
203
204
205 .. method:: Connection.deqoptions()
206
207 Returns an object specifying the options to use when dequeuing messages.
208 See :ref:`deqoptions` for more information.
209
210 .. versionadded:: 5.3
211
212 .. deprecated:: 7.2
213
214 Use the attribute :attr:`Queue.deqOptions` instead.
215
216 .. note::
217
218 This method is an extension to the DB API definition.
219
220
221 .. attribute:: Connection.dsn
222
223 This read-only attribute returns the TNS entry of the database to which a
224 connection has been established.
225
226 .. note::
227
228 This attribute is an extension to the DB API definition.
229
230
231 .. attribute:: Connection.edition
232
233 This read-only attribute gets the session edition and is only available in
234 Oracle Database 11.2 (both client and server must be at this level or
235 higher for this to work).
236
237 .. versionadded:: 5.3
238
239 .. note::
240
241 This attribute is an extension to the DB API definition.
242
243
244 .. attribute:: Connection.encoding
245
246 This read-only attribute returns the IANA character set name of the
247 character set in use by the Oracle client for regular strings.
248
249 .. note::
250
251 This attribute is an extension to the DB API definition.
252
253
254 .. method:: Connection.enq(name, options, msgproperties, payload)
255
256 Returns a message id after successfully enqueuing a message. The options
257 object can be created using :meth:`~Connection.enqoptions()` and the
258 msgproperties object can be created using
259 :meth:`~Connection.msgproperties()`. The payload must be an object created
260 using :meth:`ObjectType.newobject()`.
261
262 .. versionadded:: 5.3
263
264 .. deprecated:: 7.2
265
266 Use the methods :meth:`Queue.enqOne()` or :meth:`Queue.enqMany()`
267 instead.
268
269 .. note::
270
271 This method is an extension to the DB API definition.
272
273
274 .. method:: Connection.enqoptions()
275
276 Returns an object specifying the options to use when enqueuing messages.
277 See :ref:`enqoptions` for more information.
278
279 .. versionadded:: 5.3
280
281 .. deprecated:: 7.2
282
283 Use the attribute :attr:`Queue.enqOptions` instead.
284
285 .. note::
286
287 This method is an extension to the DB API definition.
288
289
290 .. attribute:: Connection.external_name
291
292 This read-write attribute specifies the external name that is used by the
293 connection when logging distributed transactions.
294
295 .. versionadded:: 5.3
296
297 .. note::
298
299 This attribute is an extension to the DB API definition.
300
301
302 .. method:: Connection.getSodaDatabase()
303
304 Return a :ref:`SodaDatabase <sodadb>` object for Simple Oracle Document
305 Access (SODA). All SODA operations are performed either on the returned
306 SodaDatabase object or from objects created by the returned SodaDatabase
307 object. See `here <http://www.oracle.com/pls/topic/lookup?
308 ctx=dblatest&id=GUID-BE42F8D3-B86B-43B4-B2A3-5760A4DF79FB>`__ for
309 additional information on SODA.
310
311 .. versionadded:: 7.0
312
313 .. note::
314
315 This method is an extension to the DB API definition.
316
317
318 .. method:: Connection.gettype(name)
319
320 Return a :ref:`type object <objecttype>` given its name. This can then be
321 used to create objects which can be bound to cursors created by this
322 connection.
323
324 .. versionadded:: 5.3
325
326 .. note::
327
328 This method is an extension to the DB API definition.
329
330
331 .. attribute:: Connection.handle
332
333 This read-only attribute returns the OCI service context handle for the
334 connection. It is primarily provided to facilitate testing the creation of
335 a connection using the OCI service context handle.
336
337 .. note::
338
339 This attribute is an extension to the DB API definition.
340
341
342 .. attribute:: Connection.inputtypehandler
343
344 This read-write attribute specifies a method called for each value that is
345 bound to a statement executed on any cursor associated with this
346 connection. The method signature is handler(cursor, value, arraysize) and
347 the return value is expected to be a variable object or None in which case
348 a default variable object will be created. If this attribute is None, the
349 default behavior will take place for all values bound to statements.
350
351 .. note::
352
353 This attribute is an extension to the DB API definition.
354
355
356 .. attribute:: Connection.internal_name
357
358 This read-write attribute specifies the internal name that is used by the
359 connection when logging distributed transactions.
360
361 .. versionadded:: 5.3
362
363 .. note::
364
365 This attribute is an extension to the DB API definition.
366
367
368 .. attribute:: Connection.ltxid
369
370 This read-only attribute returns the logical transaction id for the
371 connection. It is used within Oracle Transaction Guard as a means of
372 ensuring that transactions are not duplicated. See the Oracle documentation
373 and the provided sample for more information.
374
375 .. versionadded:: 5.3
376
377 .. note:
378
379 This attribute is an extension to the DB API definition. It is only
380 available when Oracle Database 12.1 or higher is in use on both the
381 server and the client.
382
383
384 .. attribute:: Connection.maxBytesPerCharacter
385
386 This read-only attribute returns the maximum number of bytes each character
387 can use for the client character set.
388
389 .. note::
390
391 This attribute is an extension to the DB API definition.
392
393
394 .. attribute:: Connection.module
395
396 This write-only attribute sets the module column in the v$session table.
397 The maximum length for this string is 48 and if you exceed this length you
398 will get ORA-24960.
399
400 .. note:
401
402 This attribute is an extension to the DB API definition.
403
404
405 .. method:: Connection.msgproperties(payload, correlation, delay, exceptionq, \
406 expiration, priority)
407
408 Returns an object specifying the properties of messages used in advanced
409 queuing. See :ref:`msgproperties` for more information.
410
411 Each of the parameters are optional. If specified, they act as a shortcut
412 for setting each of the equivalently named properties.
413
414 .. versionadded:: 5.3
415
416 .. versionchanged:: 7.2 Added parameters
417
418 .. note::
419
420 This method is an extension to the DB API definition.
421
422
423 .. attribute:: Connection.nencoding
424
425 This read-only attribute returns the IANA character set name of the
426 national character set in use by the Oracle client.
427
428 .. note::
429
430 This attribute is an extension to the DB API definition.
431
432
433 .. attribute:: Connection.outputtypehandler
434
435 This read-write attribute specifies a method called for each column that is
436 going to be fetched from any cursor associated with this connection. The
437 method signature is handler(cursor, name, defaultType, length, precision,
438 scale) and the return value is expected to be a variable object or None in
439 which case a default variable object will be created. If this attribute is
440 None, the default behavior will take place for all columns fetched from
441 cursors.
442
443 See :ref:`outputtypehandlers`.
444
445 .. note::
446
447 This attribute is an extension to the DB API definition.
448
449
450 .. method:: Connection.ping()
451
452 Ping the server which can be used to test if the connection is still
453 active.
454
455 .. note::
456
457 This method is an extension to the DB API definition.
458
459
460 .. method:: Connection.prepare()
461
462 Prepare the distributed (global) transaction for commit. Return a boolean
463 indicating if a transaction was actually prepared in order to avoid the
464 error ORA-24756 (transaction does not exist).
465
466 .. note::
467
468 This method is an extension to the DB API definition.
469
470
471 .. method:: Connection.queue(name, payloadType=None)
472
473 Creates a :ref:`queue <queue>` which is used to enqueue and dequeue
474 messages in Advanced Queueing.
475
476 The name parameter is expected to be a string identifying the queue in
477 which messages are to be enqueued or dequeued.
478
479 The payloadType parameter, if specified, is expected to be an
480 :ref:`object type <objecttype>` that identifies the type of payload the
481 queue expects. If not specified, RAW data is enqueued and dequeued.
482
483 .. versionadded:: 7.2
484
485 .. note::
486
487 This method is an extension to the DB API definition.
488
489
490 .. method:: Connection.rollback()
491
492 Rollback any pending transactions.
493
494
495 .. method:: Connection.shutdown([mode])
496
497 Shutdown the database. In order to do this the connection must be connected
498 as :data:`~cx_Oracle.SYSDBA` or :data:`~cx_Oracle.SYSOPER`. Two calls must
499 be made unless the mode specified is :data:`~cx_Oracle.DBSHUTDOWN_ABORT`.
500 An example is shown below:
501
502 ::
503
504 import cx_Oracle
505
506 connection = cx_Oracle.connect(mode = cx_Oracle.SYSDBA)
507 connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_IMMEDIATE)
508 cursor = connection.cursor()
509 cursor.execute("alter database close normal")
510 cursor.execute("alter database dismount")
511 connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_FINAL)
512
513 .. note::
514
515 This method is an extension to the DB API definition.
516
517
518 .. method:: Connection.startup(force=False, restrict=False, pfile=None)
519
520 Startup the database. This is equivalent to the SQL\*Plus command "startup
521 nomount". The connection must be connected as :data:`~cx_Oracle.SYSDBA` or
522 :data:`~cx_Oracle.SYSOPER` with the :data:`~cx_Oracle.PRELIM_AUTH` option
523 specified for this to work.
524
525 The pfile parameter, if specified, is expected to be a string identifying
526 the location of the parameter file (PFILE) which will be used instead of
527 the stored parameter file (SPFILE).
528
529 An example is shown below:
530
531 ::
532
533 import cx_Oracle
534
535 connection = cx_Oracle.connect(
536 mode=cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH)
537 connection.startup()
538 connection = cx_Oracle.connect(mode=cx_Oracle.SYSDBA)
539 cursor = connection.cursor()
540 cursor.execute("alter database mount")
541 cursor.execute("alter database open")
542
543 .. note::
544
545 This method is an extension to the DB API definition.
546
547
548 .. attribute:: Connection.stmtcachesize
549
550 This read-write attribute specifies the size of the statement cache. This
551 value can make a significant difference in performance (up to 100x) if you
552 have a small number of statements that you execute repeatedly.
553
554 The default value is 20.
555
556 See :ref:`Statement Caching <stmtcache>` for more information.
557
558 .. note::
559
560 This attribute is an extension to the DB API definition.
561
562
563 .. method:: Connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE, protocol=cx_Oracle.SUBSCR_PROTO_OCI, callback=None, timeout=0, operations=OPCODE_ALLOPS, port=0, qos=0, ipAddress=None, groupingClass=0, groupingValue=0, groupingType=cx_Oracle.SUBSCR_GROUPING_TYPE_SUMMARY, name=None, clientInitiated=False)
564
565 Return a new :ref:`subscription object <subscrobj>` that receives
566 notifications for events that take place in the database that match the
567 given parameters.
568
569 The namespace parameter specifies the namespace the subscription uses. It
570 can be one of :data:`cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE` or
571 :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ`.
572
573 The protocol parameter specifies the protocol to use when notifications are
574 sent. Currently the only valid value is :data:`cx_Oracle.SUBSCR_PROTO_OCI`.
575
576 The callback is expected to be a callable that accepts a single parameter.
577 A :ref:`message object <msgobjects>` is passed to this callback whenever a
578 notification is received.
579
580 The timeout value specifies that the subscription expires after the given
581 time in seconds. The default value of 0 indicates that the subscription
582 never expires.
583
584 The operations parameter enables filtering of the messages that are sent
585 (insert, update, delete). The default value will send notifications for all
586 operations. This parameter is only used when the namespace is set to
587 :data:`cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE`.
588
589 The port parameter specifies the listening port for callback notifications
590 from the database server. If not specified, an unused port will be selected
591 by the Oracle Client libraries.
592
593 The qos parameter specifies quality of service options. It should be one or
594 more of the following flags, OR'ed together:
595 :data:`cx_Oracle.SUBSCR_QOS_RELIABLE`,
596 :data:`cx_Oracle.SUBSCR_QOS_DEREG_NFY`,
597 :data:`cx_Oracle.SUBSCR_QOS_ROWIDS`,
598 :data:`cx_Oracle.SUBSCR_QOS_QUERY`,
599 :data:`cx_Oracle.SUBSCR_QOS_BEST_EFFORT`.
600
601 The ipAddress parameter specifies the IP address (IPv4 or IPv6) in standard
602 string notation to bind for callback notifications from the database
603 server. If not specified, the client IP address will be determined by the
604 Oracle Client libraries.
605
606 The groupingClass parameter specifies what type of grouping of
607 notifications should take place. Currently, if set, this value can only be
608 set to the value :data:`cx_Oracle.SUBSCR_GROUPING_CLASS_TIME`, which
609 will group notifications by the number of seconds specified in the
610 groupingValue parameter. The groupingType parameter should be one of the
611 values :data:`cx_Oracle.SUBSCR_GROUPING_TYPE_SUMMARY` (the default) or
612 :data:`cx_Oracle.SUBSCR_GROUPING_TYPE_LAST`.
613
614 The name parameter is used to identify the subscription and is specific to
615 the selected namespace. If the namespace parameter is
616 :data:`cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE` then the name is optional and
617 can be any value. If the namespace parameter is
618 :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ`, however, the name must be in the
619 format '<QUEUE_NAME>' for single consumer queues and
620 '<QUEUE_NAME>:<CONSUMER_NAME>' for multiple consumer queues, and identifies
621 the queue that will be monitored for messages. The queue name may include
622 the schema, if needed.
623
624 The clientInitiated parameter is used to determine if client initiated
625 connections or server initiated connections (the default) will be
626 established. Client initiated connections are only available in Oracle
627 Client 19.4 and Oracle Database 19.4 and higher.
628
629 .. versionadded:: 6.4
630
631 The parameters ipAddress, groupingClass, groupingValue, groupingType
632 and name were added.
633
634 .. versionadded:: 7.3
635
636 The parameter clientInitiated was added.
637
638 .. note::
639
640 This method is an extension to the DB API definition.
641
642 .. note::
643
644 The subscription can be deregistered in the database by calling the
645 function :meth:`~Connection.unsubscribe()`. If this method is not
646 called and the connection that was used to create the subscription is
647 explicitly closed using the function :meth:`~Connection.close()`, the
648 subscription will not be deregistered in the database.
649
650
651 .. attribute:: Connection.tag
652
653 This read-write attribute initially contains the actual tag of the session
654 that was acquired from a pool by :meth:`SessionPool.acquire()`. If the
655 connection was not acquired from a pool or no tagging parameters were
656 specified (tag and matchanytag) when the connection was acquired from the
657 pool, this value will be None. If the value is changed, it must be a string
658 containing name=value pairs like "k1=v1;k2=v2".
659
660 If this value is not None when the connection is released back to the pool
661 it will be used to retag the session. This value can be overridden in the
662 call to :meth:`SessionPool.release()`.
663
664 .. note::
665
666 This attribute is an extension to the DB API definition.
667
668 .. versionadded:: 7.1
669
670
671 .. attribute:: Connection.tnsentry
672
673 This read-only attribute returns the TNS entry of the database to which a
674 connection has been established.
675
676 .. note::
677
678 This attribute is an extension to the DB API definition.
679
680
681 .. method:: Connection.unsubscribe(subscr)
682
683 Unsubscribe from events in the database that were originally subscribed to
684 using :meth:`~Connection.subscribe()`. The connection used to unsubscribe
685 should be the same one used to create the subscription, or should access
686 the same database and be connected as the same user name.
687
688 .. versionadded:: 6.4
689
690
691 .. attribute:: Connection.username
692
693 This read-only attribute returns the name of the user which established the
694 connection to the database.
695
696 .. note::
697
698 This attribute is an extension to the DB API definition.
699
700
701 .. attribute:: Connection.version
702
703 This read-only attribute returns the version of the database to which a
704 connection has been established.
705
706 .. note::
707
708 This attribute is an extension to the DB API definition.
709
710 .. note::
711
712 If you connect to Oracle Database 18 or higher with client libraries
713 12.2 or lower that you will only receive the base version (such as
714 18.0.0.0.0) instead of the full version (18.3.0.0.0).
0 .. _cursorobj:
1
2 *************
3 Cursor Object
4 *************
5
6
7 .. method:: Cursor.__enter__()
8
9 The entry point for the cursor as a context manager. It returns itself.
10
11 .. note::
12
13 This method is an extension to the DB API definition.
14
15
16 .. method:: Cursor.__exit__()
17
18 The exit point for the cursor as a context manager. It closes the cursor.
19
20 .. note::
21
22 This method is an extension to the DB API definition.
23
24
25 .. attribute:: Cursor.arraysize
26
27 This read-write attribute can be used to tune the number of rows internally
28 fetched and buffered by internal calls to the database. The value can
29 drastically affect the performance of a query since it directly affects the
30 number of network round trips between Python and the database. For methods
31 like :meth:`~Cursor.fetchone()` and :meth:`~Cursor.fetchall()` it does not
32 change how many rows are returned to the application. For
33 :meth:`~Cursor.fetchmany()` it is the default number of rows to fetch.
34
35 Due to the performance benefits, the default ``Cursor.arraysize`` is 100
36 instead of the 1 that the DB API recommends. This value means that 100 rows
37 are fetched by each internal call to the database.
38
39 See :ref:`Tuning Fetch Performance <tuningfetch>` for more information.
40
41 .. attribute:: Cursor.bindarraysize
42
43 This read-write attribute specifies the number of rows to bind at a time
44 and is used when creating variables via :meth:`~Cursor.setinputsizes()` or
45 :meth:`~Cursor.var()`. It defaults to 1 meaning to bind a single row at a
46 time.
47
48 .. note::
49
50 The DB API definition does not define this attribute.
51
52
53 .. method:: Cursor.arrayvar(dataType, value, [size])
54
55 Create an array variable associated with the cursor of the given type and
56 size and return a :ref:`variable object <varobj>`. The value is either an
57 integer specifying the number of elements to allocate or it is a list and
58 the number of elements allocated is drawn from the size of the list. If the
59 value is a list, the variable is also set with the contents of the list. If
60 the size is not specified and the type is a string or binary, 4000 bytes
61 is allocated. This is needed for passing arrays to PL/SQL (in cases where
62 the list might be empty and the type cannot be determined automatically) or
63 returning arrays from PL/SQL.
64
65 Array variables can only be used for PL/SQL associative arrays with
66 contiguous keys. For PL/SQL associative arrays with sparsely populated keys
67 or for varrays and nested tables, the approach shown in this
68 `example <https://github.com/oracle/python-cx_Oracle/blob/master/
69 samples/PLSQLCollection.py>`__ needs to be used.
70
71 .. note::
72
73 The DB API definition does not define this method.
74
75
76 .. method:: Cursor.bindnames()
77
78 Return the list of bind variable names bound to the statement. Note that a
79 statement must have been prepared first.
80
81 .. note::
82
83 The DB API definition does not define this method.
84
85
86 .. attribute:: Cursor.bindvars
87
88 This read-only attribute provides the bind variables used for the last
89 execute. The value will be either a list or a dictionary depending on
90 whether binding was done by position or name. Care should be taken when
91 referencing this attribute. In particular, elements should not be removed
92 or replaced.
93
94 .. note::
95
96 The DB API definition does not define this attribute.
97
98
99 .. method:: Cursor.callfunc(name, returnType, parameters=[], \
100 keywordParameters={})
101
102 Call a function with the given name. The return type is specified in the
103 same notation as is required by :meth:`~Cursor.setinputsizes()`. The
104 sequence of parameters must contain one entry for each parameter that the
105 function expects. Any keyword parameters will be included after the
106 positional parameters. The result of the call is the return value of the
107 function.
108
109 See :ref:`plsqlfunc` for an example.
110
111 .. note::
112
113 The DB API definition does not define this method.
114
115 .. note::
116
117 If you intend to call :meth:`Cursor.setinputsizes()` on the cursor
118 prior to making this call, then note that the first item in the
119 parameter list refers to the return value of the function.
120
121
122 .. method:: Cursor.callproc(name, parameters=[], keywordParameters={})
123
124 Call a procedure with the given name. The sequence of parameters must
125 contain one entry for each parameter that the procedure expects. The result
126 of the call is a modified copy of the input sequence. Input parameters are
127 left untouched; output and input/output parameters are replaced with
128 possibly new values. Keyword parameters will be included after the
129 positional parameters and are not returned as part of the output sequence.
130
131 See :ref:`plsqlproc` for an example.
132
133 .. note::
134
135 The DB API definition does not allow for keyword parameters.
136
137
138 .. method:: Cursor.close()
139
140 Close the cursor now, rather than whenever __del__ is called. The cursor
141 will be unusable from this point forward; an Error exception will be raised
142 if any operation is attempted with the cursor.
143
144
145 .. attribute:: Cursor.connection
146
147 This read-only attribute returns a reference to the connection object on
148 which the cursor was created.
149
150 .. note::
151
152 This attribute is an extension to the DB API definition but it is
153 mentioned in PEP 249 as an optional extension.
154
155
156 .. data:: Cursor.description
157
158 This read-only attribute is a sequence of 7-item sequences. Each of these
159 sequences contains information describing one result column: (name, type,
160 display_size, internal_size, precision, scale, null_ok). This attribute
161 will be None for operations that do not return rows or if the cursor has
162 not had an operation invoked via the :meth:`~Cursor.execute()` method yet.
163
164 The type will be one of the :ref:`database type constants <dbtypes>`
165 defined at the module level.
166
167
168 .. method:: Cursor.execute(statement, [parameters], \*\*keywordParameters)
169
170 Execute a statement against the database. See :ref:`sqlexecution`.
171
172 Parameters may be passed as a dictionary or sequence or as keyword
173 parameters. If the parameters are a dictionary, the values will be bound by
174 name and if the parameters are a sequence the values will be bound by
175 position. Note that if the values are bound by position, the order of the
176 variables is from left to right as they are encountered in the statement
177 and SQL statements are processed differently than PL/SQL statements. For
178 this reason, it is generally recommended to bind parameters by name instead
179 of by position.
180
181 Parameters passed as a dictionary are name and value pairs. The name maps
182 to the bind variable name used by the statement and the value maps to the
183 Python value you wish bound to that bind variable.
184
185 A reference to the statement will be retained by the cursor. If None or the
186 same string object is passed in again, the cursor will execute that
187 statement again without performing a prepare or rebinding and redefining.
188 This is most effective for algorithms where the same statement is used, but
189 different parameters are bound to it (many times). Note that parameters
190 that are not passed in during subsequent executions will retain the value
191 passed in during the last execution that contained them.
192
193 For maximum efficiency when reusing an statement, it is best to use the
194 :meth:`~Cursor.setinputsizes()` method to specify the parameter types and
195 sizes ahead of time; in particular, None is assumed to be a string of
196 length 1 so any values that are later bound as numbers or dates will raise
197 a TypeError exception.
198
199 If the statement is a query, the cursor is returned as a convenience to the
200 caller (so it can be used directly as an iterator over the rows in the
201 cursor); otherwise, ``None`` is returned.
202
203 .. note::
204
205 The DB API definition does not define the return value of this method.
206
207
208 .. method:: Cursor.executemany(statement, parameters, batcherrors=False, \
209 arraydmlrowcounts=False)
210
211 Prepare a statement for execution against a database and then execute it
212 against all parameter mappings or sequences found in the sequence
213 parameters. See :ref:`batchstmnt`.
214
215 The statement is managed in the same way as the :meth:`~Cursor.execute()`
216 method manages it. If the size of the buffers allocated for any of the
217 parameters exceeds 2 GB, you will receive the error "DPI-1015: array size
218 of <n> is too large", where <n> varies with the size of each element being
219 allocated in the buffer. If you receive this error, decrease the number of
220 elements in the sequence parameters.
221
222 If there are no parameters, or parameters have previously been bound, the
223 number of iterations can be specified as an integer instead of needing to
224 provide a list of empty mappings or sequences.
225
226 When true, the batcherrors parameter enables batch error support within
227 Oracle and ensures that the call succeeds even if an exception takes place
228 in one or more of the sequence of parameters. The errors can then be
229 retrieved using :meth:`~Cursor.getbatcherrors()`.
230
231 When true, the arraydmlrowcounts parameter enables DML row counts to be
232 retrieved from Oracle after the method has completed. The row counts can
233 then be retrieved using :meth:`~Cursor.getarraydmlrowcounts()`.
234
235 Both the batcherrors parameter and the arraydmlrowcounts parameter can only
236 be true when executing an insert, update, delete or merge statement; in all
237 other cases an error will be raised.
238
239 For maximum efficiency, it is best to use the
240 :meth:`~Cursor.setinputsizes()` method to specify the parameter types and
241 sizes ahead of time; in particular, None is assumed to be a string of
242 length 1 so any values that are later bound as numbers or dates will raise
243 a TypeError exception.
244
245
246 .. method:: Cursor.executemanyprepared(numIters)
247
248 Execute the previously prepared and bound statement the given number of
249 times. The variables that are bound must have already been set to their
250 desired value before this call is made. This method was designed for the
251 case where optimal performance is required as it comes at the expense of
252 compatibility with the DB API.
253
254 .. note::
255
256 The DB API definition does not define this method.
257
258 .. deprecated:: 6.4
259 Use :meth:`~Cursor.executemany()` instead with None for the statement
260 argument and an integer for the parameters argument.
261
262
263 .. method:: Cursor.fetchall()
264
265 Fetch all (remaining) rows of a query result, returning them as a list of
266 tuples. An empty list is returned if no more rows are available. Note that
267 the cursor's arraysize attribute can affect the performance of this
268 operation, as internally reads from the database are done in batches
269 corresponding to the arraysize.
270
271 An exception is raised if the previous call to :meth:`~Cursor.execute()`
272 did not produce any result set or no call was issued yet.
273
274 See :ref:`fetching` for an example.
275
276
277 .. method:: Cursor.fetchmany([numRows=cursor.arraysize])
278
279 Fetch the next set of rows of a query result, returning a list of tuples.
280 An empty list is returned if no more rows are available. Note that the
281 cursor's arraysize attribute can affect the performance of this operation.
282
283 The number of rows to fetch is specified by the parameter. If it is not
284 given, the cursor's arraysize attribute determines the number of rows to be
285 fetched. If the number of rows available to be fetched is fewer than the
286 amount requested, fewer rows will be returned.
287
288 An exception is raised if the previous call to :meth:`~Cursor.execute()`
289 did not produce any result set or no call was issued yet.
290
291 See :ref:`fetching` for an example.
292
293 .. method:: Cursor.fetchone()
294
295 Fetch the next row of a query result set, returning a single tuple or None
296 when no more data is available.
297
298 An exception is raised if the previous call to :meth:`~Cursor.execute()`
299 did not produce any result set or no call was issued yet.
300
301 See :ref:`fetching` for an example.
302
303 .. method:: Cursor.fetchraw([numRows=cursor.arraysize])
304
305 Fetch the next set of rows of a query result into the internal buffers of
306 the defined variables for the cursor. The number of rows actually fetched
307 is returned. This method was designed for the case where optimal
308 performance is required as it comes at the expense of compatibility with
309 the DB API.
310
311 An exception is raised if the previous call to :meth:`~Cursor.execute()`
312 did not produce any result set or no call was issued yet.
313
314 .. note::
315
316 The DB API definition does not define this method.
317
318
319 .. attribute:: Cursor.fetchvars
320
321 This read-only attribute specifies the list of variables created for the
322 last query that was executed on the cursor. Care should be taken when
323 referencing this attribute. In particular, elements should not be removed
324 or replaced.
325
326 .. note::
327
328 The DB API definition does not define this attribute.
329
330
331 .. method:: Cursor.getarraydmlrowcounts()
332
333 Retrieve the DML row counts after a call to :meth:`~Cursor.executemany()`
334 with arraydmlrowcounts enabled. This will return a list of integers
335 corresponding to the number of rows affected by the DML statement for each
336 element of the array passed to :meth:`~Cursor.executemany()`.
337
338 .. note::
339
340 The DB API definition does not define this method and it is only
341 available for Oracle 12.1 and higher.
342
343
344 .. method:: Cursor.getbatcherrors()
345
346 Retrieve the exceptions that took place after a call to
347 :meth:`~Cursor.executemany()` with batcherrors enabled. This will return a
348 list of Error objects, one error for each iteration that failed. The offset
349 can be determined by looking at the offset attribute of the error object.
350
351 .. note::
352
353 The DB API definition does not define this method.
354
355
356 .. method:: Cursor.getimplicitresults()
357
358 Return a list of cursors which correspond to implicit results made
359 available from a PL/SQL block or procedure without the use of OUT ref
360 cursor parameters. The PL/SQL block or procedure opens the cursors and
361 marks them for return to the client using the procedure
362 dbms_sql.return_result. Cursors returned in this fashion should not be
363 closed. They will be closed automatically by the parent cursor when it is
364 closed. Closing the parent cursor will invalidate the cursors returned by
365 this method.
366
367 .. versionadded:: 5.3
368
369 .. note::
370
371 The DB API definition does not define this method and it is only
372 available for Oracle Database 12.1 (both client and server must be at
373 this level or higher). It is most like the DB API method nextset(), but
374 unlike that method (which requires that the next result set overwrite
375 the current result set), this method returns cursors which can be
376 fetched independently of each other.
377
378
379 .. attribute:: Cursor.inputtypehandler
380
381 This read-write attribute specifies a method called for each value that is
382 bound to a statement executed on the cursor and overrides the attribute
383 with the same name on the connection if specified. The method signature is
384 handler(cursor, value, arraysize) and the return value is expected to be a
385 variable object or None in which case a default variable object will be
386 created. If this attribute is None, the value of the attribute with the
387 same name on the connection is used.
388
389 .. note::
390
391 This attribute is an extension to the DB API definition.
392
393
394 .. method:: Cursor.__iter__()
395
396 Returns the cursor itself to be used as an iterator.
397
398 .. note::
399
400 This method is an extension to the DB API definition but it is
401 mentioned in PEP 249 as an optional extension.
402
403
404 .. data:: Cursor.lastrowid
405
406 This read-only attribute returns the rowid of the last row modified by the
407 cursor. If no row was modified by the last operation performed on the
408 cursor, the value None is returned.
409
410 .. versionadded:: 7.3
411
412
413 .. attribute:: Cursor.outputtypehandler
414
415 This read-write attribute specifies a method called for each column that is
416 to be fetched from this cursor. The method signature is
417 handler(cursor, name, defaultType, length, precision, scale) and the return
418 value is expected to be a variable object or None in which case a default
419 variable object will be created. If this attribute is None, the value of
420 the attribute with the same name on the connection is used instead.
421
422 See :ref:`outputtypehandlers`.
423
424 .. note::
425
426 This attribute is an extension to the DB API definition.
427
428
429 .. method:: Cursor.parse(statement)
430
431 This can be used to parse a statement without actually executing it (this
432 step is done automatically by Oracle when a statement is executed).
433
434 .. note::
435
436 The DB API definition does not define this method.
437
438 .. note::
439
440 You can parse any DML or DDL statement. DDL statements are executed
441 immediately and an implied commit takes place.
442
443
444 .. attribute:: Cursor.prefetchrows
445
446 This read-write attribute can be used to tune the number of rows that the
447 Oracle Client library fetches when a query is executed. This value can
448 reduce the number of round-trips to the database that are required to
449 fetch rows but at the cost of additional memory. Setting this value to 0
450 can be useful when the timing of fetches must be explicitly controlled.
451
452 See :ref:`Tuning Fetch Performance <tuningfetch>` for more information.
453
454 .. note::
455
456 The DB API definition does not define this method.
457
458
459 .. method:: Cursor.prepare(statement, [tag])
460
461 This can be used before a call to :meth:`~Cursor.execute()` to define the
462 statement that will be executed. When this is done, the prepare phase will
463 not be performed when the call to :meth:`~Cursor.execute()` is made with
464 None or the same string object as the statement. If specified the
465 statement will be returned to the statement cache with the given tag. See
466 the Oracle documentation for more information about the statement cache.
467
468 See :ref:`Statement Caching <stmtcache>` for more information.
469
470 .. note::
471
472 The DB API definition does not define this method.
473
474
475 .. attribute:: Cursor.rowcount
476
477 This read-only attribute specifies the number of rows that have currently
478 been fetched from the cursor (for select statements), that have been
479 affected by the operation (for insert, update, delete and merge
480 statements), or the number of successful executions of the statement
481 (for PL/SQL statements).
482
483
484 .. attribute:: Cursor.rowfactory
485
486 This read-write attribute specifies a method to call for each row that is
487 retrieved from the database. Ordinarily a tuple is returned for each row
488 but if this attribute is set, the method is called with the tuple that
489 would normally be returned, and the result of the method is returned
490 instead.
491
492 See :ref:`rowfactories`.
493
494 .. note::
495
496 The DB API definition does not define this attribute.
497
498
499 .. method:: Cursor.scroll(value=0, mode="relative")
500
501 Scroll the cursor in the result set to a new position according to the
502 mode.
503
504 If mode is "relative" (the default value), the value is taken as an offset
505 to the current position in the result set. If set to "absolute", value
506 states an absolute target position. If set to "first", the cursor is
507 positioned at the first row and if set to "last", the cursor is set to the
508 last row in the result set.
509
510 An error is raised if the mode is "relative" or "absolute" and the scroll
511 operation would position the cursor outside of the result set.
512
513 .. versionadded:: 5.3
514
515 .. note::
516
517 This method is an extension to the DB API definition but it is
518 mentioned in PEP 249 as an optional extension.
519
520
521 .. attribute:: Cursor.scrollable
522
523 This read-write boolean attribute specifies whether the cursor can be
524 scrolled or not. By default, cursors are not scrollable, as the server
525 resources and response times are greater than nonscrollable cursors. This
526 attribute is checked and the corresponding mode set in Oracle when calling
527 the method :meth:`~Cursor.execute()`.
528
529 .. versionadded:: 5.3
530
531 .. note::
532
533 The DB API definition does not define this attribute.
534
535
536 .. method:: Cursor.setinputsizes(\*args, \*\*keywordArgs)
537
538 This can be used before a call to :meth:`~Cursor.execute()`,
539 :meth:`~Cursor.callfunc()` or :meth:`~Cursor.callproc()` to predefine
540 memory areas for the operation's parameters. Each parameter should be a
541 type object corresponding to the input that will be used or it should be an
542 integer specifying the maximum length of a string parameter. Use keyword
543 parameters when binding by name and positional parameters when binding by
544 position. The singleton None can be used as a parameter when using
545 positional parameters to indicate that no space should be reserved for that
546 position.
547
548 .. note::
549
550 If you plan to use :meth:`~Cursor.callfunc()` then be aware that the
551 first parameter in the list refers to the return value of the function.
552
553
554 .. method:: Cursor.setoutputsize(size, [column])
555
556 This method does nothing and is retained solely for compatibility with the
557 DB API. The module automatically allocates as much space as needed to fetch
558 LONG and LONG RAW columns (or CLOB as string and BLOB as bytes).
559
560
561 .. attribute:: Cursor.statement
562
563 This read-only attribute provides the string object that was previously
564 prepared with :meth:`~Cursor.prepare()` or executed with
565 :meth:`~Cursor.execute()`.
566
567 .. note::
568
569 The DB API definition does not define this attribute.
570
571
572 .. method:: Cursor.var(dataType, [size, arraysize, inconverter, outconverter, \
573 typename, encodingErrors])
574
575 Create a variable with the specified characteristics. This method was
576 designed for use with PL/SQL in/out variables where the length or type
577 cannot be determined automatically from the Python object passed in or for
578 use in input and output type handlers defined on cursors or connections.
579
580 The dataType parameter specifies the type of data that should be stored in
581 the variable. This should be one of the
582 :ref:`database type constants <dbtypes>`, :ref:`DB API constants <types>`,
583 an object type returned from the method :meth:`Connection.gettype()` or one
584 of the following Python types:
585
586 .. list-table::
587 :header-rows: 1
588
589 * - Python Type
590 - Database Type
591 * - bool
592 - :attr:`cx_Oracle.DB_TYPE_BOOLEAN`
593 * - bytes
594 - :attr:`cx_Oracle.DB_TYPE_RAW`
595 * - datetime.date
596 - :attr:`cx_Oracle.DB_TYPE_DATE`
597 * - datetime.datetime
598 - :attr:`cx_Oracle.DB_TYPE_DATE`
599 * - datetime.timedelta
600 - :attr:`cx_Oracle.DB_TYPE_INTERVAL_DS`
601 * - decimal.Decimal
602 - :attr:`cx_Oracle.DB_TYPE_NUMBER`
603 * - float
604 - :attr:`cx_Oracle.DB_TYPE_NUMBER`
605 * - int
606 - :attr:`cx_Oracle.DB_TYPE_NUMBER`
607 * - str
608 - :attr:`cx_Oracle.DB_TYPE_VARCHAR`
609
610 The size parameter specifies the length of string and raw variables and is
611 ignored in all other cases. If not specified for string and raw variables,
612 the value 4000 is used.
613
614 The arraysize parameter specifies the number of elements the variable will
615 have. If not specified the bind array size (usually 1) is used. When a
616 variable is created in an output type handler this parameter should be set
617 to the cursor's array size.
618
619 The inconverter and outconverter parameters specify methods used for
620 converting values to/from the database. More information can be found in
621 the section on :ref:`variable objects<varobj>`.
622
623 The typename parameter specifies the name of a SQL object type and must be
624 specified when using type :data:`cx_Oracle.OBJECT` unless the type object
625 was passed directly as the first parameter.
626
627 The encodingErrors parameter specifies what should happen when decoding
628 byte strings fetched from the database into strings. It should be one of
629 the values noted in the builtin
630 `decode <https://docs.python.org/3/library/stdtypes.html#bytes.decode>`__
631 function.
632
633 .. note::
634
635 The DB API definition does not define this method.
0 .. _lobobj:
1
2 ***********
3 LOB Objects
4 ***********
5
6 See :ref:`lobdata` for more information about using LOBs.
7
8 .. note::
9
10 This object is an extension the DB API. It is returned whenever Oracle
11 :data:`CLOB`, :data:`BLOB` and :data:`BFILE` columns are fetched.
12
13
14 .. method:: LOB.close()
15
16 Close the LOB. Call this when writing is completed so that the indexes
17 associated with the LOB can be updated -- but only if :meth:`~LOB.open()`
18 was called first.
19
20
21 .. method:: LOB.fileexists()
22
23 Return a boolean indicating if the file referenced by the BFILE type LOB
24 exists.
25
26
27 .. method:: LOB.getchunksize()
28
29 Return the chunk size for the internal LOB. Reading and writing to the LOB
30 in chunks of multiples of this size will improve performance.
31
32
33 .. method:: LOB.getfilename()
34
35 Return a two-tuple consisting of the directory alias and file name for a
36 BFILE type LOB.
37
38
39 .. method:: LOB.isopen()
40
41 Return a boolean indicating if the LOB has been opened using the method
42 :meth:`~LOB.open()`.
43
44
45 .. method:: LOB.open()
46
47 Open the LOB for writing. This will improve performance when writing to a
48 LOB in chunks and there are functional or extensible indexes associated
49 with the LOB. If this method is not called, each write will perform an open
50 internally followed by a close after the write has been completed.
51
52
53 .. method:: LOB.read([offset=1, [amount]])
54
55 Return a portion (or all) of the data in the LOB object. Note that the
56 amount and offset are in bytes for BLOB and BFILE type LOBs and in UCS-2
57 code points for CLOB and NCLOB type LOBs. UCS-2 code points are equivalent
58 to characters for all but supplemental characters. If supplemental
59 characters are in the LOB, the offset and amount will have to be chosen
60 carefully to avoid splitting a character.
61
62
63 .. method:: LOB.setfilename(dirAlias, name)
64
65 Set the directory alias and name of the BFILE type LOB.
66
67
68 .. method:: LOB.size()
69
70 Returns the size of the data in the LOB object. For BLOB and BFILE type
71 LOBs this is the number of bytes. For CLOB and NCLOB type LOBs this is the
72 number of UCS-2 code points. UCS-2 code points are equivalent to characters
73 for all but supplemental characters.
74
75
76 .. method:: LOB.trim([newSize=0])
77
78 Trim the LOB to the new size.
79
80
81 .. attribute:: LOB.type
82
83 This read-only attribute returns the type of the LOB as one of the
84 :ref:`database type constants <dbtypes>`.
85
86 .. versionadded:: 8.0
87
88
89 .. method:: LOB.write(data, [offset=1])
90
91 Write the data to the LOB object at the given offset. The offset is in
92 bytes for BLOB type LOBs and in UCS-2 code points for CLOB and NCLOB type
93 LOBs. UCS-2 code points are equivalent to characters for all but
94 supplemental characters. If supplemental characters are in the LOB, the
95 offset will have to be chosen carefully to avoid splitting a character.
96 Note that if you want to make the LOB value smaller, you must use the
97 :meth:`~LOB.trim()` function.
0 .. module:: cx_Oracle
1
2 .. _module:
3
4 ****************
5 Module Interface
6 ****************
7
8 .. data:: __future__
9
10 Special object which contains attributes which control the behavior of
11 cx_Oracle, allowing for opting in for new features. No attributes are
12 currently supported so all attributes will silently ignore being set and
13 will always appear to have the value None.
14
15 .. note::
16
17 This method is an extension to the DB API definition.
18
19 .. versionadded:: 6.2
20
21
22 .. function:: Binary(string)
23
24 Construct an object holding a binary (long) string value.
25
26
27 .. function:: clientversion()
28
29 Return the version of the client library being used as a 5-tuple. The five
30 values are the major version, minor version, update number, patch number
31 and port update number.
32
33 .. note::
34
35 This method is an extension to the DB API definition.
36
37
38 .. function:: connect(user=None, password=None, dsn=None, \
39 mode=cx_Oracle.DEFAULT_AUTH, handle=0, pool=None, threaded=False, \
40 events=False, cclass=None, purity=cx_Oracle.ATTR_PURITY_DEFAULT, \
41 newpassword=None, encoding=None, nencoding=None, edition=None, \
42 appcontext=[], tag=None, matchanytag=None, shardingkey=[], \
43 supershardingkey=[])
44 Connection(user=None, password=None, dsn=None, \
45 mode=cx_Oracle.DEFAULT_AUTH, handle=0, pool=None, threaded=False, \
46 events=False, cclass=None, purity=cx_Oracle.ATTR_PURITY_DEFAULT, \
47 newpassword=None, encoding=None, nencoding=None, edition=None, \
48 appcontext=[], tag=None, matchanytag=False, shardingkey=[], \
49 supershardingkey=[])
50
51 Constructor for creating a connection to the database. Return a
52 :ref:`connection object <connobj>`. All parameters are optional and can be
53 specified as keyword parameters. See :ref:`connhandling` information about
54 connections.
55
56 The dsn (data source name) is the TNS entry (from the Oracle names server
57 or tnsnames.ora file) or is a string like the one returned from
58 :meth:`~cx_Oracle.makedsn()`. If the user parameter is passed and the
59 password and dsn parameters are not passed, the user parameter is assumed
60 to be a connect string in the format ``user/password@dsn``, the same format
61 accepted by Oracle applications such as SQL\*Plus. See :ref:`connstr` for
62 more information.
63
64 If the mode is specified, it must be one of the
65 :ref:`connection authorization modes<connection-authorization-modes>`
66 which are defined at the module level.
67
68 If the handle is specified, it must be of type OCISvcCtx\* and is only of
69 use when embedding Python in an application (like PowerBuilder) which has
70 already made the connection.
71
72 The pool parameter is expected to be a
73 :ref:`session pool object <sesspool>` and the use of this parameter is the
74 equivalent of calling :meth:`SessionPool.acquire()`. Parameters not
75 accepted by that method are ignored.
76
77 The threaded parameter is expected to be a boolean expression which
78 indicates whether or not Oracle should wrap accesses to connections with a
79 mutex. Doing so in single threaded applications imposes a performance
80 penalty of about 10-15% which is why the default is False.
81
82 The events parameter is expected to be a boolean expression which indicates
83 whether or not to initialize Oracle in events mode. This is required for
84 continuous query notification and high availability event notifications.
85
86 The cclass parameter is expected to be a string and defines the connection
87 class for database resident connection pooling (DRCP).
88
89 The purity parameter is expected to be one of
90 :data:`~cx_Oracle.ATTR_PURITY_NEW`, :data:`~cx_Oracle.ATTR_PURITY_SELF`, or
91 :data:`~cx_Oracle.ATTR_PURITY_DEFAULT`.
92
93 The newpassword parameter is expected to be a string if specified and sets
94 the password for the logon during the connection process.
95
96 See the :ref:`globalization <globalization>` section for details on the
97 encoding and nencoding parameters. Note the default encoding and nencoding
98 values changed to "UTF-8" in cx_Oracle 8, and any character set in NLS_LANG
99 is ignored.
100
101 The edition parameter is expected to be a string if specified and sets the
102 edition to use for the session. It is only relevant if both the client and
103 the database are at least Oracle Database 11.2. If this parameter is used
104 with the cclass parameter the exception "DPI-1058: edition not supported
105 with connection class" will be raised.
106
107 The appcontext parameter is expected to be a list of 3-tuples, if specified,
108 and sets the application context for the connection. Application context
109 is available in the database by using the sys_context() PL/SQL method and
110 can be used within a logon trigger as well as any other PL/SQL procedures.
111 Each entry in the list is expected to contain three strings: the namespace,
112 the name and the value.
113
114 The tag parameter, if specified, is expected to be a string and will limit
115 the sessions that can be returned from a session pool unless the
116 matchanytag parameter is set to True. In that case sessions with the
117 specified tag will be preferred over others, but if no such sessions are
118 available a session with a different tag may be returned instead. In any
119 case, untagged sessions will always be returned if no sessions with the
120 specified tag are available. Sessions are tagged when they are
121 :meth:`released <SessionPool.release>` back to the pool.
122
123 The shardingkey and supershardingkey parameters, if specified, are expected
124 to be a sequence of values which will be used to identify the database
125 shard to connect to. The key values can be strings, numbers, bytes or dates.
126
127
128 .. function:: Cursor(connection)
129
130 Constructor for creating a cursor. Return a new
131 :ref:`cursor object <cursorobj>` using the connection.
132
133 .. note::
134
135 This method is an extension to the DB API definition.
136
137
138 .. function:: Date(year, month, day)
139
140 Construct an object holding a date value.
141
142
143 .. function:: DateFromTicks(ticks)
144
145 Construct an object holding a date value from the given ticks value (number
146 of seconds since the epoch; see the documentation of the standard Python
147 time module for details).
148
149
150 .. function:: init_oracle_client(lib_dir=None, config_dir=None, \
151 error_url=None, driver_name=None)
152
153 Initialize the Oracle client library now, rather than when
154 :func:`cx_Oracle.clientversion()`, :func:`cx_Oracle.connect()` or
155 :func:`cx_Oracle.SessionPool()` is called for the first time. If
156 initialization has already taken place, an exception is raised.
157
158 If the parameter `lib_dir` is not `None` or the empty string,
159 the specified directory is the only one searched for the Oracle Client
160 libraries; otherwise, the standard way of locating the Oracle Client
161 library is used.
162
163 If the parameter `config_dir` is not `None` or the empty string, the
164 specified directory is used to find Oracle Client library configuration
165 files. This is equivalent to setting the environment variable `TNS_ADMIN`
166 and overrides any value already set in `TNS_ADMIN`. If this parameter is not
167 set, the standard way of locating Oracle Client library configuration files
168 is used.
169
170 If the parameter `error_url` is not `None` or the empty string, the
171 specified value is included in the message of the exception raised when the
172 Oracle Client library cannot be loaded; otherwise, the :ref:`installation`
173 URL is included.
174
175 If the parameter `driver_name` is not `None` or the empty string, the
176 specified value can be found in database views that give information about
177 connections. For example, it is in the ``CLIENT_DRIVER`` column of
178 ``V$SESSION_CONNECT_INFO``. The standard is to set this value to
179 ``"<name> : version>"``, where <name> is the name of the driver and
180 <version> is its version. Theere should be a single space character before
181 and after the colon. If this value is not specified, then the default
182 value of "cx_Oracle : <version>" is used.
183
184 See :ref:`initialization` for more discussion.
185
186 .. note::
187
188 This method is an extension to the DB API definition.
189
190
191 .. function:: makedsn(host, port, sid=None, service_name=None, region=None, \
192 sharding_key=None, super_sharding_key=None)
193
194 Return a string suitable for use as the dsn parameter for
195 :meth:`~cx_Oracle.connect()`. This string is identical to the strings that
196 are defined by the Oracle names server or defined in the tnsnames.ora file.
197
198 .. note::
199
200 This method is an extension to the DB API definition.
201
202
203 .. function:: SessionPool(user=None, password=None, dsn=None, min=1, max=2, \
204 increment=1, connectiontype=cx_Oracle.Connection, threaded=False, \
205 getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT, events=False, \
206 homogeneous=True, externalauth=False, encoding=None, nencoding=None, \
207 edition=None, timeout=0, waitTimeout=0, maxLifetimeSession=0, \
208 sessionCallback=None, maxSessionsPerShard=0)
209
210 Create and return a :ref:`session pool object <sesspool>`. Session pooling
211 (also known as connection pooling) creates a pool of available connections
212 to the database, allowing applications to acquire a connection very quickly.
213 It is of primary use in a server where connections are requested in rapid
214 succession and used for a short period of time, for example in a web server.
215 See :ref:`connpool` for more information.
216
217 Connection pooling in cx_Oracle is handled by Oracle's
218 `Session pooling <https://www.oracle.com/pls/topic/lookup?
219 ctx=dblatest&id=GUID-F9662FFB-EAEF-495C-96FC-49C6D1D9625C>`__
220 technology. This allows cx_Oracle applications to support features
221 like `Application Continuity <https://www.oracle.com/pls/topic/lookup?
222 ctx=dblatest&id=GUID-A8DD9422-2F82-42A9-9555-134296416E8F>`__.
223
224 The user, password and dsn parameters are the same as for
225 :meth:`cx_Oracle.connect()`
226
227 The min, max and increment parameters control pool growth behavior. A fixed
228 pool size where min equals max is recommended to help prevent connection
229 storms and to help overall system stability. The min parameter is the
230 number of connections opened when the pool is created. The increment is the
231 number of connections that are opened whenever a connection request exceeds
232 the number of currently open connections. The max parameter is the maximum
233 number of connections that can be open in the connection pool.
234
235 Note that when using :ref:`external authentication <extauth>`,
236 :ref:`heterogeneous pools <connpooltypes>`, or :ref:`drcp`, then the pool
237 growth behavior is different. In these cases the number of connections
238 created at pool startup is always zero, and the increment is always one.
239
240 If the connectiontype parameter is specified, all calls to
241 :meth:`~SessionPool.acquire()` will create connection objects of that type,
242 rather than the base type defined at the module level.
243
244 The threaded parameter is expected to be a boolean expression which
245 indicates whether Oracle should wrap accesses to connections with a mutex.
246 Doing so in single threaded applications imposes a performance penalty of
247 about 10-15% which is why the default is False.
248
249 The getmode parameter indicates whether or not future
250 :func:`SessionPool.acquire()` calls will wait for available connections. It
251 can be one of the :ref:`Session Pool Get Modes <sesspoolmodes>` values.
252
253 The events parameter is expected to be a boolean expression which indicates
254 whether or not to initialize Oracle in events mode. This is required for
255 continuous query notification and high availability event notifications.
256
257 The homogeneous parameter is expected to be a boolean expression which
258 indicates whether or not to create a homogeneous pool. A homogeneous pool
259 requires that all connections in the pool use the same credentials. As such
260 proxy authentication and external authentication is not possible with a
261 homogeneous pool. See :ref:`Heterogeneous and Homogeneous Connection Pools
262 <connpooltypes>`.
263
264 The externalauth parameter is expected to be a boolean expression which
265 indicates whether or not external authentication should be used. External
266 authentication implies that something other than the database is
267 authenticating the user to the database. This includes the use of operating
268 system authentication and Oracle wallets. See :ref:`Connecting Using
269 External Authentication <extauth>`.
270
271 The encoding and nencoding parameters set the encodings used for string
272 values transferred between cx_Oracle and Oracle Database, see
273 :ref:`Character Sets and Globalization <globalization>`. Note the default
274 encoding and nencoding values changed to "UTF-8" in cx_Oracle 8, and any
275 character set in NLS_LANG is ignored.
276
277 The edition parameter is expected to be a string, if specified, and sets the
278 edition to use for the sessions in the pool. It is only relevant if both the
279 client and the server are at least Oracle Database 11.2. See
280 :ref:`Edition-Based Redefinition (EBR) <ebr>`.
281
282 The timeout parameter is expected to be an integer, if specified, and sets
283 the length of time (in seconds) after which idle sessions in the pool are
284 terminated. Note that termination only occurs when the pool is accessed.
285 The default value of 0 means that no idle sessions are terminated.
286
287 The waitTimeout parameter is expected to be an integer, if specified, and
288 sets the length of time (in milliseconds) that the caller should wait for
289 a session to become available in the pool before returning with an error.
290 This value is only used if the getmode parameter is set to the value
291 :data:`cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT`.
292
293 The maxLifetimeSession parameter is expected to be an integer, if
294 specified, and sets the maximum length of time (in seconds) a pooled
295 session may exist. Sessions that are in use will not be closed. They become
296 candidates for termination only when they are released back to the pool and
297 have existed for longer than maxLifetimeSession seconds. Note that
298 termination only occurs when the pool is accessed. The default value is 0
299 which means that there is no maximum length of time that a pooled session
300 may exist.
301
302 The sessionCallback parameter is expected to be either a string or a
303 callable. If the sessionCallback parameter is a callable, it will be called
304 when a newly created connection is returned from the pool, or when a tag is
305 requested and that tag does not match the connection's actual tag. The
306 callable will be invoked with the connection and the requested tag as its
307 only parameters. If the parameter is a string, it should be the name of a
308 PL/SQL procedure that will be called when :func:`SessionPool.acquire()`
309 requests a tag and that tag does not match the connection's actual tag. See
310 :ref:`Session CallBacks for Setting Pooled Connection State
311 <sessioncallback>`. Support for the PL/SQL procedure requires Oracle Client
312 libraries 12.2 or later. See the `OCI documentation
313 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
314 id=GUID-B853A020-752F-494A-8D88-D0396EF57177>`__ for more information.
315
316 The maxSessionsPerShard parameter is expected to be an integer, if
317 specified, and sets the maximum number of sessions in the pool that can be
318 used for any given shard in a sharded database. This value is ignored if
319 the Oracle client library version is less than 18.3.
320
321 .. note::
322
323 This method is an extension to the DB API definition.
324
325
326 .. function:: Time(hour, minute, second)
327
328 Construct an object holding a time value.
329
330 .. note::
331
332 The time only data type is not supported by Oracle. Calling this
333 function will raise a NotSupportedError exception.
334
335
336
337 .. function:: TimeFromTicks(ticks)
338
339 Construct an object holding a time value from the given ticks value (number
340 of seconds since the epoch; see the documentation of the standard Python
341 time module for details).
342
343 .. note::
344
345 The time only data type is not supported by Oracle. Calling this
346 function will raise a NotSupportedError exception.
347
348
349 .. function:: Timestamp(year, month, day, hour, minute, second)
350
351 Construct an object holding a time stamp value.
352
353
354 .. function:: TimestampFromTicks(ticks)
355
356 Construct an object holding a time stamp value from the given ticks value
357 (number of seconds since the epoch; see the documentation of the standard
358 Python time module for details).
359
360
361
362 .. _constants:
363
364 Constants
365 =========
366
367 General
368 -------
369
370 .. data:: apilevel
371
372 String constant stating the supported DB API level. Currently '2.0'.
373
374
375 .. data:: buildtime
376
377 String constant stating the time when the binary was built.
378
379 .. note::
380
381 This constant is an extension to the DB API definition.
382
383
384 .. data:: paramstyle
385
386 String constant stating the type of parameter marker formatting expected by
387 the interface. Currently 'named' as in 'where name = :name'.
388
389
390 .. data:: threadsafety
391
392 Integer constant stating the level of thread safety that the interface
393 supports. Currently 2, which means that threads may share the module and
394 connections, but not cursors. Sharing means that a thread may use a
395 resource without wrapping it using a mutex semaphore to implement resource
396 locking.
397
398 Note that in order to make use of multiple threads in a program which
399 intends to connect and disconnect in different threads, the threaded
400 parameter to :meth:`connect()` or :meth:`SessionPool()` must be true.
401
402
403 .. data:: version
404 .. data:: __version__
405
406 String constant stating the version of the module. Currently '|release|'.
407
408 .. note::
409
410 This attribute is an extension to the DB API definition.
411
412
413 Advanced Queuing: Delivery Modes
414 --------------------------------
415
416 These constants are extensions to the DB API definition. They are possible
417 values for the :attr:`~DeqOptions.deliverymode` attribute of the
418 :ref:`dequeue options object <deqoptions>` passed as the options parameter to
419 the :meth:`Connection.deq()` method as well as the
420 :attr:`~EnqOptions.deliverymode` attribute of the
421 :ref:`enqueue options object <enqoptions>` passed as the options parameter to
422 the :meth:`Connection.enq()` method. They are also possible values for the
423 :attr:`~MessageProperties.deliverymode` attribute of the
424 :ref:`message properties object <msgproperties>` passed as the msgproperties
425 parameter to the :meth:`Connection.deq()` and :meth:`Connection.enq()` methods.
426
427
428 .. data:: MSG_BUFFERED
429
430 This constant is used to specify that enqueue/dequeue operations should
431 enqueue or dequeue buffered messages.
432
433
434 .. data:: MSG_PERSISTENT
435
436 This constant is used to specify that enqueue/dequeue operations should
437 enqueue or dequeue persistent messages. This is the default value.
438
439
440 .. data:: MSG_PERSISTENT_OR_BUFFERED
441
442 This constant is used to specify that dequeue operations should dequeue
443 either persistent or buffered messages.
444
445
446 Advanced Queuing: Dequeue Modes
447 -------------------------------
448
449 These constants are extensions to the DB API definition. They are possible
450 values for the :attr:`~DeqOptions.mode` attribute of the
451 :ref:`dequeue options object <deqoptions>`. This object is the options
452 parameter for the :meth:`Connection.deq()` method.
453
454
455 .. data:: DEQ_BROWSE
456
457 This constant is used to specify that dequeue should read the message
458 without acquiring any lock on the message (equivalent to a select
459 statement).
460
461
462 .. data:: DEQ_LOCKED
463
464 This constant is used to specify that dequeue should read and obtain a
465 write lock on the message for the duration of the transaction (equivalent
466 to a select for update statement).
467
468
469 .. data:: DEQ_REMOVE
470
471 This constant is used to specify that dequeue should read the message and
472 update or delete it. This is the default value.
473
474
475 .. data:: DEQ_REMOVE_NODATA
476
477 This constant is used to specify that dequeue should confirm receipt of the
478 message but not deliver the actual message content.
479
480
481 Advanced Queuing: Dequeue Navigation Modes
482 ------------------------------------------
483
484 These constants are extensions to the DB API definition. They are possible
485 values for the :attr:`~DeqOptions.navigation` attribute of the
486 :ref:`dequeue options object <deqoptions>`. This object is the options
487 parameter for the :meth:`Connection.deq()` method.
488
489
490 .. data:: DEQ_FIRST_MSG
491
492 This constant is used to specify that dequeue should retrieve the first
493 available message that matches the search criteria. This resets the
494 position to the beginning of the queue.
495
496
497 .. data:: DEQ_NEXT_MSG
498
499 This constant is used to specify that dequeue should retrieve the next
500 available message that matches the search criteria. If the previous message
501 belongs to a message group, AQ retrieves the next available message that
502 matches the search criteria and belongs to the message group. This is the
503 default.
504
505
506 .. data:: DEQ_NEXT_TRANSACTION
507
508 This constant is used to specify that dequeue should skip the remainder of
509 the transaction group and retrieve the first message of the next
510 transaction group. This option can only be used if message grouping is
511 enabled for the current queue.
512
513
514 Advanced Queuing: Dequeue Visibility Modes
515 ------------------------------------------
516
517 These constants are extensions to the DB API definition. They are possible
518 values for the :attr:`~DeqOptions.visibility` attribute of the
519 :ref:`dequeue options object <deqoptions>`. This object is the options
520 parameter for the :meth:`Connection.deq()` method.
521
522
523 .. data:: DEQ_IMMEDIATE
524
525 This constant is used to specify that dequeue should perform its work as
526 part of an independent transaction.
527
528
529 .. data:: DEQ_ON_COMMIT
530
531 This constant is used to specify that dequeue should be part of the current
532 transaction. This is the default value.
533
534
535 Advanced Queuing: Dequeue Wait Modes
536 ------------------------------------
537
538 These constants are extensions to the DB API definition. They are possible
539 values for the :attr:`~DeqOptions.wait` attribute of the
540 :ref:`dequeue options object <deqoptions>`. This object is the options
541 parameter for the :meth:`Connection.deq()` method.
542
543
544 .. data:: DEQ_NO_WAIT
545
546 This constant is used to specify that dequeue not wait for messages to be
547 available for dequeuing.
548
549
550 .. data:: DEQ_WAIT_FOREVER
551
552 This constant is used to specify that dequeue should wait forever for
553 messages to be available for dequeuing. This is the default value.
554
555
556 Advanced Queuing: Enqueue Visibility Modes
557 ------------------------------------------
558
559 These constants are extensions to the DB API definition. They are possible
560 values for the :attr:`~EnqOptions.visibility` attribute of the
561 :ref:`enqueue options object <enqoptions>`. This object is the options
562 parameter for the :meth:`Connection.enq()` method.
563
564
565 .. data:: ENQ_IMMEDIATE
566
567 This constant is used to specify that enqueue should perform its work as
568 part of an independent transaction.
569
570
571 .. data:: ENQ_ON_COMMIT
572
573 This constant is used to specify that enqueue should be part of the current
574 transaction. This is the default value.
575
576
577 Advanced Queuing: Message States
578 --------------------------------
579
580 These constants are extensions to the DB API definition. They are possible
581 values for the :attr:`~MessageProperties.state` attribute of the
582 :ref:`message properties object <msgproperties>`. This object is the
583 msgproperties parameter for the :meth:`Connection.deq()` and
584 :meth:`Connection.enq()` methods.
585
586
587 .. data:: MSG_EXPIRED
588
589 This constant is used to specify that the message has been moved to the
590 exception queue.
591
592
593 .. data:: MSG_PROCESSED
594
595 This constant is used to specify that the message has been processed and
596 has been retained.
597
598
599 .. data:: MSG_READY
600
601 This constant is used to specify that the message is ready to be processed.
602
603
604 .. data:: MSG_WAITING
605
606 This constant is used to specify that the message delay has not yet been
607 reached.
608
609
610 Advanced Queuing: Other
611 -----------------------
612
613 These constants are extensions to the DB API definition. They are special
614 constants used in advanced queuing.
615
616
617 .. data:: MSG_NO_DELAY
618
619 This constant is a possible value for the :attr:`~MessageProperties.delay`
620 attribute of the :ref:`message properties object <msgproperties>` passed
621 as the msgproperties parameter to the :meth:`Connection.deq()` and
622 :meth:`Connection.enq()` methods. It specifies that no delay should be
623 imposed and the message should be immediately available for dequeuing. This
624 is also the default value.
625
626
627 .. data:: MSG_NO_EXPIRATION
628
629 This constant is a possible value for the
630 :attr:`~MessageProperties.expiration` attribute of the
631 :ref:`message properties object <msgproperties>` passed as the msgproperties
632 parameter to the :meth:`Connection.deq()` and :meth:`Connection.enq()`
633 methods. It specifies that the message never expires. This is also the
634 default value.
635
636
637 .. _connection-authorization-modes:
638
639 Connection Authorization Modes
640 ------------------------------
641
642 These constants are extensions to the DB API definition. They are possible
643 values for the mode parameter of the :meth:`connect()` method.
644
645
646 .. data:: DEFAULT_AUTH
647
648 This constant is used to specify that default authentication is to take
649 place. This is the default value if no mode is passed at all.
650
651 .. versionadded:: 7.2
652
653 .. data:: PRELIM_AUTH
654
655 This constant is used to specify that preliminary authentication is to be
656 used. This is needed for performing database startup and shutdown.
657
658
659 .. data:: SYSASM
660
661 This constant is used to specify that SYSASM access is to be acquired.
662
663
664 .. data:: SYSBKP
665
666 This constant is used to specify that SYSBACKUP access is to be acquired.
667
668
669 .. data:: SYSDBA
670
671 This constant is used to specify that SYSDBA access is to be acquired.
672
673
674 .. data:: SYSDGD
675
676 This constant is used to specify that SYSDG access is to be acquired.
677
678
679 .. data:: SYSKMT
680
681 This constant is used to specify that SYSKM access is to be acquired.
682
683
684 .. data:: SYSOPER
685
686 This constant is used to specify that SYSOPER access is to be acquired.
687
688
689 .. data:: SYSRAC
690
691 This constant is used to specify that SYSRAC access is to be acquired.
692
693
694 Database Shutdown Modes
695 -----------------------
696
697 These constants are extensions to the DB API definition. They are possible
698 values for the mode parameter of the :meth:`Connection.shutdown()` method.
699
700
701 .. data:: DBSHUTDOWN_ABORT
702
703 This constant is used to specify that the caller should not wait for
704 current processing to complete or for users to disconnect from the
705 database. This should only be used in unusual circumstances since database
706 recovery may be necessary upon next startup.
707
708
709 .. data:: DBSHUTDOWN_FINAL
710
711 This constant is used to specify that the instance can be truly halted.
712 This should only be done after the database has been shutdown with one of
713 the other modes (except abort) and the database has been closed and
714 dismounted using the appropriate SQL commands.
715
716
717 .. data:: DBSHUTDOWN_IMMEDIATE
718
719 This constant is used to specify that all uncommitted transactions should
720 be rolled back and any connected users should be disconnected.
721
722
723 .. data:: DBSHUTDOWN_TRANSACTIONAL
724
725 This constant is used to specify that further connections to the database
726 should be prohibited and no new transactions should be allowed. It then
727 waits for all active transactions to complete.
728
729
730 .. data:: DBSHUTDOWN_TRANSACTIONAL_LOCAL
731
732 This constant is used to specify that further connections to the database
733 should be prohibited and no new transactions should be allowed. It then
734 waits for only local active transactions to complete.
735
736
737 Event Types
738 -----------
739
740 These constants are extensions to the DB API definition. They are possible
741 values for the :attr:`Message.type` attribute of the messages that are sent
742 for subscriptions created by the :meth:`Connection.subscribe()` method.
743
744
745 .. data:: EVENT_AQ
746
747 This constant is used to specify that one or more messages are available
748 for dequeuing on the queue specified when the subscription was created.
749
750
751 .. data:: EVENT_DEREG
752
753 This constant is used to specify that the subscription has been
754 deregistered and no further notifications will be sent.
755
756
757 .. data:: EVENT_NONE
758
759 This constant is used to specify no information is available about the
760 event.
761
762
763 .. data:: EVENT_OBJCHANGE
764
765 This constant is used to specify that a database change has taken place on
766 a table registered with the :meth:`Subscription.registerquery()` method.
767
768
769 .. data:: EVENT_QUERYCHANGE
770
771 This constant is used to specify that the result set of a query registered
772 with the :meth:`Subscription.registerquery()` method has been changed.
773
774
775 .. data:: EVENT_SHUTDOWN
776
777 This constant is used to specify that the instance is in the process of
778 being shut down.
779
780
781 .. data:: EVENT_SHUTDOWN_ANY
782
783 This constant is used to specify that any instance (when running RAC) is in
784 the process of being shut down.
785
786
787 .. data:: EVENT_STARTUP
788
789 This constant is used to specify that the instance is in the process of
790 being started up.
791
792
793 .. _cqn-operation-codes:
794
795 Operation Codes
796 ---------------
797
798 These constants are extensions to the DB API definition. They are possible
799 values for the operations parameter for the :meth:`Connection.subscribe()`
800 method. One or more of these values can be OR'ed together. These values are
801 also used by the :attr:`MessageTable.operation` or
802 :attr:`MessageQuery.operation` attributes of the messages that are sent.
803
804
805 .. data:: OPCODE_ALLOPS
806
807 This constant is used to specify that messages should be sent for all
808 operations.
809
810
811 .. data:: OPCODE_ALLROWS
812
813 This constant is used to specify that the table or query has been
814 completely invalidated.
815
816
817 .. data:: OPCODE_ALTER
818
819 This constant is used to specify that messages should be sent when a
820 registered table has been altered in some fashion by DDL, or that the
821 message identifies a table that has been altered.
822
823
824 .. data:: OPCODE_DELETE
825
826 This constant is used to specify that messages should be sent when data is
827 deleted, or that the message identifies a row that has been deleted.
828
829
830 .. data:: OPCODE_DROP
831
832 This constant is used to specify that messages should be sent when a
833 registered table has been dropped, or that the message identifies a table
834 that has been dropped.
835
836
837 .. data:: OPCODE_INSERT
838
839 This constant is used to specify that messages should be sent when data is
840 inserted, or that the message identifies a row that has been inserted.
841
842
843 .. data:: OPCODE_UPDATE
844
845 This constant is used to specify that messages should be sent when data is
846 updated, or that the message identifies a row that has been updated.
847
848 .. _sesspoolmodes:
849
850 Session Pool Get Modes
851 ----------------------
852
853 These constants are extensions to the DB API definition. They are possible
854 values for the getmode parameter of the :meth:`SessionPool()` method.
855
856
857 .. data:: SPOOL_ATTRVAL_FORCEGET
858
859 This constant is used to specify that a new connection will be returned if
860 there are no free sessions available in the pool.
861
862
863 .. data:: SPOOL_ATTRVAL_NOWAIT
864
865 This constant is used to specify that an exception should be raised if
866 there are no free sessions available in the pool. This is the default
867 value.
868
869
870 .. data:: SPOOL_ATTRVAL_WAIT
871
872 This constant is used to specify that the caller should wait until a
873 session is available if there are no free sessions available in the pool.
874
875
876 .. data:: SPOOL_ATTRVAL_TIMEDWAIT
877
878 This constant is used to specify that the caller should wait for a period
879 of time (defined by the waitTimeout parameter) for a session to become
880 available before returning with an error.
881
882
883 Session Pool Purity
884 -------------------
885
886 These constants are extensions to the DB API definition. They are possible
887 values for the purity parameter of the :meth:`connect()` method, which is used
888 in database resident connection pooling (DRCP).
889
890
891 .. data:: ATTR_PURITY_DEFAULT
892
893 This constant is used to specify that the purity of the session is the
894 default value identified by Oracle (see Oracle's documentation for more
895 information). This is the default value.
896
897
898 .. data:: ATTR_PURITY_NEW
899
900 This constant is used to specify that the session acquired from the pool
901 should be new and not have any prior session state.
902
903
904 .. data:: ATTR_PURITY_SELF
905
906 This constant is used to specify that the session acquired from the pool
907 need not be new and may have prior session state.
908
909
910 Subscription Grouping Classes
911 -----------------------------
912
913 These constants are extensions to the DB API definition. They are possible
914 values for the groupingClass parameter of the :meth:`Connection.subscribe()`
915 method.
916
917 .. data:: SUBSCR_GROUPING_CLASS_TIME
918
919 This constant is used to specify that events are to be grouped by the
920 period of time in which they are received.
921
922
923 Subscription Grouping Types
924 ---------------------------
925
926 These constants are extensions to the DB API definition. They are possible
927 values for the groupingType parameter of the :meth:`Connection.subscribe()`
928 method.
929
930 .. data:: SUBSCR_GROUPING_TYPE_SUMMARY
931
932 This constant is used to specify that when events are grouped a summary of
933 the events should be sent instead of the individual events. This is the
934 default value.
935
936 .. data:: SUBSCR_GROUPING_TYPE_LAST
937
938 This constant is used to specify that when events are grouped the last
939 event that makes up the group should be sent instead of the individual
940 events.
941
942
943 .. _subscr-namespaces:
944
945 Subscription Namespaces
946 -----------------------
947
948 These constants are extensions to the DB API definition. They are possible
949 values for the namespace parameter of the :meth:`Connection.subscribe()`
950 method.
951
952 .. data:: SUBSCR_NAMESPACE_AQ
953
954 This constant is used to specify that notifications should be sent when a
955 queue has messages available to dequeue.
956
957 .. data:: SUBSCR_NAMESPACE_DBCHANGE
958
959 This constant is used to specify that database change notification or query
960 change notification messages are to be sent. This is the default value.
961
962
963 .. _subscr-protocols:
964
965 Subscription Protocols
966 ----------------------
967
968 These constants are extensions to the DB API definition. They are possible
969 values for the protocol parameter of the :meth:`Connection.subscribe()` method.
970
971
972 .. data:: SUBSCR_PROTO_HTTP
973
974 This constant is used to specify that notifications will be sent to an
975 HTTP URL when a message is generated. This value is currently not
976 supported.
977
978
979 .. data:: SUBSCR_PROTO_MAIL
980
981 This constant is used to specify that notifications will be sent to an
982 e-mail address when a message is generated. This value is currently not
983 supported.
984
985
986 .. data:: SUBSCR_PROTO_OCI
987
988 This constant is used to specify that notifications will be sent to the
989 callback routine identified when the subscription was created. It is the
990 default value and the only value currently supported.
991
992
993 .. data:: SUBSCR_PROTO_SERVER
994
995 This constant is used to specify that notifications will be sent to a
996 PL/SQL procedure when a message is generated. This value is currently not
997 supported.
998
999
1000 .. _subscr-qos:
1001
1002 Subscription Quality of Service
1003 -------------------------------
1004
1005 These constants are extensions to the DB API definition. They are possible
1006 values for the qos parameter of the :meth:`Connection.subscribe()` method. One
1007 or more of these values can be OR'ed together.
1008
1009 .. data:: SUBSCR_QOS_BEST_EFFORT
1010
1011 This constant is used to specify that best effort filtering for query
1012 result set changes is acceptable. False positive notifications may be
1013 received. This behaviour may be suitable for caching applications.
1014
1015
1016 .. data:: SUBSCR_QOS_DEREG_NFY
1017
1018 This constant is used to specify that the subscription should be
1019 automatically unregistered after the first notification is received.
1020
1021
1022 .. data:: SUBSCR_QOS_QUERY
1023
1024 This constant is used to specify that notifications should be sent if the
1025 result set of the registered query changes. By default no false positive
1026 notifications will be generated.
1027
1028
1029 .. data:: SUBSCR_QOS_RELIABLE
1030
1031 This constant is used to specify that notifications should not be lost in
1032 the event of database failure.
1033
1034
1035 .. data:: SUBSCR_QOS_ROWIDS
1036
1037 This constant is used to specify that the rowids of the inserted, updated
1038 or deleted rows should be included in the message objects that are sent.
1039
1040
1041 .. _types:
1042
1043 DB API Types
1044 ------------
1045
1046 .. data:: BINARY
1047
1048 This type object is used to describe columns in a database that contain
1049 binary data. The database types :data:`DB_TYPE_RAW` and
1050 :data:`DB_TYPE_LONG_RAW` will compare equal to this value. If a variable is
1051 created with this type, the database type :data:`DB_TYPE_RAW` will be used.
1052
1053
1054 .. data:: DATETIME
1055
1056 This type object is used to describe columns in a database that are dates.
1057 The database types :data:`DB_TYPE_DATE`, :data:`DB_TYPE_TIMESTAMP`,
1058 :data:`DB_TYPE_TIMESTAMP_LTZ` and :data:`DB_TYPE_TIMESTAMP_TZ` will all
1059 compare equal to this value. If a variable is created with this
1060 type, the database type :data:`DB_TYPE_DATE` will be used.
1061
1062
1063 .. data:: NUMBER
1064
1065 This type object is used to describe columns in a database that are
1066 numbers. The database types :data:`DB_TYPE_BINARY_DOUBLE`,
1067 :data:`DB_TYPE_BINARY_FLOAT`, :data:`DB_TYPE_BINARY_INTEGER` and
1068 :data:`DB_TYPE_NUMBER` will all compare equal to this value. If a variable
1069 is created with this type, the database type :data:`DB_TYPE_NUMBER` will be
1070 used.
1071
1072
1073 .. data:: ROWID
1074
1075 This type object is used to describe the pseudo column "rowid". The
1076 database type :data:`DB_TYPE_ROWID` will compare equal to this value. If a
1077 variable is created with this type, the database type
1078 :data:`DB_TYPE_VARCHAR` will be used.
1079
1080
1081 .. data:: STRING
1082
1083 This type object is used to describe columns in a database that are
1084 strings. The database types :data:`DB_TYPE_CHAR`, :data:`DB_TYPE_LONG`,
1085 :data:`DB_TYPE_NCHAR`, :data:`DB_TYPE_NVARCHAR` and :data:`DB_TYPE_VARCHAR`
1086 will all compare equal to this value. If a variable is created with this
1087 type, the database type :data:`DB_TYPE_VARCHAR` will be used.
1088
1089
1090 .. _dbtypes:
1091
1092 Database Types
1093 --------------
1094
1095 All of these types are extensions to the DB API definition. They are found in
1096 query and object metadata. They can also be used to specify the database type
1097 when binding data.
1098
1099 .. data:: DB_TYPE_BFILE
1100
1101 Describes columns, attributes or array elements in a database that are of
1102 type BFILE. It will compare equal to the DB API type :data:`BINARY`.
1103
1104
1105 .. data:: DB_TYPE_BINARY_DOUBLE
1106
1107 Describes columns, attributes or array elements in a database that are of
1108 type BINARY_DOUBLE. It will compare equal to the DB API type
1109 :data:`NUMBER`.
1110
1111
1112 .. data:: DB_TYPE_BINARY_FLOAT
1113
1114 Describes columns, attributes or array elements in a database that are
1115 of type BINARY_FLOAT. It will compare equal to the DB API type
1116 :data:`NUMBER`.
1117
1118
1119 .. data:: DB_TYPE_BINARY_INTEGER
1120
1121 Describes attributes or array elements in a database that are of type
1122 BINARY_INTEGER. It will compare equal to the DB API type :data:`NUMBER`.
1123
1124
1125 .. data:: DB_TYPE_BLOB
1126
1127 Describes columns, attributes or array elements in a database that are of
1128 type BLOB. It will compare equal to the DB API type :data:`BINARY`.
1129
1130
1131 .. data:: DB_TYPE_BOOLEAN
1132
1133 Describes attributes or array elements in a database that are of type
1134 BOOLEAN. It is only available in Oracle 12.1 and higher and only within
1135 PL/SQL.
1136
1137
1138 .. data:: DB_TYPE_CHAR
1139
1140 Describes columns, attributes or array elements in a database that are of
1141 type CHAR. It will compare equal to the DB API type :data:`STRING`.
1142
1143 Note that these are fixed length string values and behave differently from
1144 VARCHAR2.
1145
1146
1147 .. data:: DB_TYPE_CLOB
1148
1149 Describes columns, attributes or array elements in a database that are of
1150 type CLOB. It will compare equal to the DB API type :data:`STRING`.
1151
1152
1153 .. data:: DB_TYPE_CURSOR
1154
1155 Describes columns in a database that are of type CURSOR. In PL/SQL these
1156 are knoown as REF CURSOR.
1157
1158
1159 .. data:: DB_TYPE_DATE
1160
1161 Describes columns, attributes or array elements in a database that are of
1162 type DATE. It will compare equal to the DB API type :data:`DATETIME`.
1163
1164
1165 .. data:: DB_TYPE_INTERVAL_DS
1166
1167 Describes columns, attributes or array elements in a database that are of
1168 type INTERVAL DAY TO SECOND.
1169
1170
1171 .. data:: DB_TYPE_INTERVAL_YM
1172
1173 Describes columns, attributes or array elements in a database that are of
1174 type INTERVAL YEAR TO MONTH. This database type is not currently supported
1175 by cx_Oracle.
1176
1177
1178 .. data:: DB_TYPE_LONG
1179
1180 Describes columns, attributes or array elements in a database that are of
1181 type LONG. It will compare equal to the DB API type :data:`STRING`.
1182
1183
1184 .. data:: DB_TYPE_LONG_RAW
1185
1186 Describes columns, attributes or array elements in a database that are of
1187 type LONG RAW. It will compare equal to the DB API type :data:`BINARY`.
1188
1189
1190 .. data:: DB_TYPE_NCHAR
1191
1192 Describes columns, attributes or array elements in a database that are of
1193 type NCHAR. It will compare equal to the DB API type :data:`STRING`.
1194
1195 Note that these are fixed length string values and behave differently from
1196 NVARCHAR2.
1197
1198
1199 .. data:: DB_TYPE_NCLOB
1200
1201 Describes columns, attributes or array elements in a database that are of
1202 type NCLOB. It will compare equal to the DB API type :data:`STRING`.
1203
1204
1205 .. data:: DB_TYPE_NUMBER
1206
1207 Describes columns, attributes or array elements in a database that are of
1208 type NUMBER. It will compare equal to the DB API type :data:`NUMBER`.
1209
1210
1211 .. data:: DB_TYPE_NVARCHAR
1212
1213 Describes columns, attributes or array elements in a database that are of
1214 type NVARCHAR2. It will compare equal to the DB API type :data:`STRING`.
1215
1216
1217 .. data:: DB_TYPE_OBJECT
1218
1219 Describes columns, attributes or array elements in a database that are an
1220 instance of a named SQL or PL/SQL type.
1221
1222
1223 .. data:: DB_TYPE_RAW
1224
1225 Describes columns, attributes or array elements in a database that are of
1226 type RAW. It will compare equal to the DB API type :data:`BINARY`.
1227
1228
1229 .. data:: DB_TYPE_ROWID
1230
1231 Describes columns, attributes or array elements in a database that are of
1232 type ROWID or UROWID. It will compare equal to the DB API type
1233 :data:`ROWID`.
1234
1235
1236 .. data:: DB_TYPE_TIMESTAMP
1237
1238 Describes columns, attributes or array elements in a database that are of
1239 type TIMESTAMP. It will compare equal to the DB API type :data:`DATETIME`.
1240
1241
1242 .. data:: DB_TYPE_TIMESTAMP_LTZ
1243
1244 Describes columns, attributes or array elements in a database that are of
1245 type TIMESTAMP WITH LOCAL TIME ZONE. It will compare equal to the DB API
1246 type :data:`DATETIME`.
1247
1248
1249 .. data:: DB_TYPE_TIMESTAMP_TZ
1250
1251 Describes columns, attributes or array elements in a database that are of
1252 type TIMESTAMP WITH TIME ZONE. It will compare equal to the DB API type
1253 :data:`DATETIME`.
1254
1255
1256 .. data:: DB_TYPE_VARCHAR
1257
1258 Describes columns, attributes or array elements in a database that are of
1259 type VARCHAR2. It will compare equal to the DB API type :data:`STRING`.
1260
1261
1262 .. _dbtypesynonyms:
1263
1264 Database Type Synonyms
1265 ----------------------
1266
1267 All of the following constants are deprecated and will be removed in a future
1268 version of cx_Oracle.
1269
1270 .. data:: BFILE
1271
1272 A synonym for :data:`DB_TYPE_BFILE`.
1273
1274 .. deprecated:: 8.0
1275
1276
1277 .. data:: BLOB
1278
1279 A synonym for :data:`DB_TYPE_BLOB`.
1280
1281 .. deprecated:: 8.0
1282
1283
1284 .. data:: BOOLEAN
1285
1286 A synonym for :data:`DB_TYPE_BOOLEAN`.
1287
1288 .. deprecated:: 8.0
1289
1290
1291 .. data:: CLOB
1292
1293 A synonym for :data:`DB_TYPE_CLOB`.
1294
1295 .. deprecated:: 8.0
1296
1297 .. data:: CURSOR
1298
1299 A synonym for :data:`DB_TYPE_CURSOR`.
1300
1301 .. deprecated:: 8.0
1302
1303
1304 .. data:: FIXED_CHAR
1305
1306 A synonym for :data:`DB_TYPE_CHAR`.
1307
1308 .. deprecated:: 8.0
1309
1310
1311 .. data:: FIXED_NCHAR
1312
1313 A synonym for :data:`DB_TYPE_NCHAR`.
1314
1315 .. deprecated:: 8.0
1316
1317
1318 .. data:: INTERVAL
1319
1320 A synonym for :data:`DB_TYPE_INTERVAL_DS`.
1321
1322 .. deprecated:: 8.0
1323
1324
1325 .. data:: LONG_BINARY
1326
1327 A synonym for :data:`DB_TYPE_LONG_RAW`.
1328
1329 .. deprecated:: 8.0
1330
1331
1332 .. data:: LONG_STRING
1333
1334 A synonym for :data:`DB_TYPE_LONG`.
1335
1336 .. deprecated:: 8.0
1337
1338
1339 .. data:: NATIVE_FLOAT
1340
1341 A synonym for :data:`DB_TYPE_BINARY_DOUBLE`.
1342
1343 .. deprecated:: 8.0
1344
1345
1346 .. data:: NATIVE_INT
1347
1348 A synonym for :data:`DB_TYPE_BINARY_INTEGER`.
1349
1350 .. deprecated:: 8.0
1351
1352
1353 .. data:: NCHAR
1354
1355 A synonym for :data:`DB_TYPE_NVARCHAR`.
1356
1357 .. deprecated:: 8.0
1358
1359
1360 .. data:: NCLOB
1361
1362 A synonym for :data:`DB_TYPE_NCLOB`.
1363
1364 .. deprecated:: 8.0
1365
1366
1367 .. data:: OBJECT
1368
1369 A synonym for :data:`DB_TYPE_OBJECT`.
1370
1371 .. deprecated:: 8.0
1372
1373
1374 .. data:: TIMESTAMP
1375
1376 A synonym for :data:`DB_TYPE_TIMESTAMP`.
1377
1378 .. deprecated:: 8.0
1379
1380
1381 Other Types
1382 -----------
1383
1384 All of these types are extensions to the DB API definition.
1385
1386 .. data:: ApiType
1387
1388 This type object is the Python type of the database API type constants
1389 :data:`BINARY`, :data:`DATETIME`, :data:`NUMBER`, :data:`ROWID` and
1390 :data:`STRING`.
1391
1392
1393 .. data:: DbType
1394
1395 This type object is the Python type of the
1396 :ref:`database type constants <dbtypes>`.
1397
1398
1399 .. data:: LOB
1400
1401 This type object is the Python type of :data:`DB_TYPE_BLOB`,
1402 :data:`DB_TYPE_BFILE`, :data:`DB_TYPE_CLOB` and :data:`DB_TYPE_NCLOB` data
1403 that is returned from cursors.
1404
1405
1406 .. _exceptions:
1407
1408 Exceptions
1409 ==========
1410
1411 .. exception:: Warning
1412
1413 Exception raised for important warnings and defined by the DB API but not
1414 actually used by cx_Oracle.
1415
1416
1417 .. exception:: Error
1418
1419 Exception that is the base class of all other exceptions defined by
1420 cx_Oracle and is a subclass of the Python StandardError exception (defined
1421 in the module exceptions).
1422
1423
1424 .. exception:: InterfaceError
1425
1426 Exception raised for errors that are related to the database interface
1427 rather than the database itself. It is a subclass of Error.
1428
1429
1430 .. exception:: DatabaseError
1431
1432 Exception raised for errors that are related to the database. It is a
1433 subclass of Error.
1434
1435
1436 .. exception:: DataError
1437
1438 Exception raised for errors that are due to problems with the processed
1439 data. It is a subclass of DatabaseError.
1440
1441
1442 .. exception:: OperationalError
1443
1444 Exception raised for errors that are related to the operation of the
1445 database but are not necessarily under the control of the programmer. It is
1446 a subclass of DatabaseError.
1447
1448
1449 .. exception:: IntegrityError
1450
1451 Exception raised when the relational integrity of the database is affected.
1452 It is a subclass of DatabaseError.
1453
1454
1455 .. exception:: InternalError
1456
1457 Exception raised when the database encounters an internal error. It is a
1458 subclass of DatabaseError.
1459
1460
1461 .. exception:: ProgrammingError
1462
1463 Exception raised for programming errors. It is a subclass of DatabaseError.
1464
1465
1466 .. exception:: NotSupportedError
1467
1468 Exception raised when a method or database API was used which is not
1469 supported by the database. It is a subclass of DatabaseError.
1470
1471
1472 .. _exchandling:
1473
1474 Exception handling
1475 ==================
1476
1477 .. note::
1478
1479 PEP 249 (Python Database API Specification v2.0) says the following about
1480 exception values:
1481
1482 [...] The values of these exceptions are not defined. They should
1483 give the user a fairly good idea of what went wrong, though. [...]
1484
1485 With cx_Oracle every exception object has exactly one argument in the
1486 ``args`` tuple. This argument is a ``cx_Oracle._Error`` object which has
1487 the following five read-only attributes.
1488
1489 .. attribute:: _Error.code
1490
1491 Integer attribute representing the Oracle error number (ORA-XXXXX).
1492
1493 .. attribute:: _Error.offset
1494
1495 Integer attribute representing the error offset when applicable.
1496
1497 .. attribute:: _Error.message
1498
1499 String attribute representing the Oracle message of the error. This
1500 message is localized by the environment of the Oracle connection.
1501
1502 .. attribute:: _Error.context
1503
1504 String attribute representing the context in which the exception was
1505 raised.
1506
1507 .. attribute:: _Error.isrecoverable
1508
1509 Boolean attribute representing whether the error is recoverable or not.
1510 This is False in all cases unless both Oracle Database 12.1 (or later) and
1511 Oracle Client 12.1 (or later) are being used.
1512
1513 .. versionadded:: 5.3
1514
1515
1516 This allows you to use the exceptions for example in the following way:
1517
1518 ::
1519
1520 import cx_Oracle
1521
1522 connection = cx_Oracle.connect("cx_Oracle/dev@localhost/orclpdb1")
1523 cursor = connection.cursor()
1524
1525 try:
1526 cursor.execute("select 1 / 0 from dual")
1527 except cx_Oracle.DatabaseError as exc:
1528 error, = exc.args
1529 print("Oracle-Error-Code:", error.code)
1530 print("Oracle-Error-Message:", error.message)
0 .. _objecttype:
1
2 *******************
3 Object Type Objects
4 *******************
5
6 .. note::
7
8 This object is an extension to the DB API. It is returned by the
9 :meth:`Connection.gettype()` call and is available as the
10 :data:`Variable.type` for variables containing Oracle objects.
11
12
13 .. method:: ObjectType([sequence])
14
15 The object type may be called directly and serves as an alternative way of
16 calling :meth:`~ObjectType.newobject()`.
17
18
19 .. attribute:: ObjectType.attributes
20
21 This read-only attribute returns a list of the :ref:`attributes
22 <objectattr>` that make up the object type.
23
24
25 .. attribute:: ObjectType.iscollection
26
27 This read-only attribute returns a boolean indicating if the object type
28 refers to a collection or not.
29
30
31 .. attribute:: ObjectType.name
32
33 This read-only attribute returns the name of the type.
34
35
36 .. attribute:: ObjectType.element_type
37
38 This read-only attribute returns the type of elements found in collections
39 of this type, if :attr:`~ObjectType.iscollection` is ``True``; otherwise,
40 it returns ``None``. If the collection contains objects, this will be
41 another object type; otherwise, it will be one of the
42 :ref:`database type constants <dbtypes>`.
43
44 .. versionadded:: 8.0
45
46
47 .. method:: ObjectType.newobject([sequence])
48
49 Return a new Oracle object of the given type. This object can then be
50 modified by setting its attributes and then bound to a cursor for
51 interaction with Oracle. If the object type refers to a collection, a
52 sequence may be passed and the collection will be initialized with the
53 items in that sequence.
54
55
56 .. attribute:: ObjectType.schema
57
58 This read-only attribute returns the name of the schema that owns the type.
59
60
61 Object Objects
62 --------------
63
64 .. note::
65
66 This object is an extension to the DB API. It is returned by the
67 :meth:`ObjectType.newobject()` call and can be bound to variables of
68 type :data:`~cx_Oracle.OBJECT`. Attributes can be retrieved and set
69 directly.
70
71 .. method:: Object.append(element)
72
73 Append an element to the collection object. If no elements exist in the
74 collection, this creates an element at index 0; otherwise, it creates an
75 element immediately following the highest index available in the
76 collection.
77
78
79 .. method:: Object.asdict()
80
81 Return a dictionary where the collection's indexes are the keys and the
82 elements are its values.
83
84 .. versionadded:: 7.0
85
86
87 .. method:: Object.aslist()
88
89 Return a list of each of the collection's elements in index order.
90
91
92 .. method:: Object.copy()
93
94 Create a copy of the object and return it.
95
96
97 .. method:: Object.delete(index)
98
99 Delete the element at the specified index of the collection. If the
100 element does not exist or is otherwise invalid, an error is raised. Note
101 that the indices of the remaining elements in the collection are not
102 changed. In other words, the delete operation creates holes in the
103 collection.
104
105
106 .. method:: Object.exists(index)
107
108 Return True or False indicating if an element exists in the collection at
109 the specified index.
110
111
112 .. method:: Object.extend(sequence)
113
114 Append all of the elements in the sequence to the collection. This is
115 the equivalent of performing :meth:`~Object.append()` for each element
116 found in the sequence.
117
118
119 .. method:: Object.first()
120
121 Return the index of the first element in the collection. If the collection
122 is empty, None is returned.
123
124
125 .. method:: Object.getelement(index)
126
127 Return the element at the specified index of the collection. If no element
128 exists at that index, an exception is raised.
129
130
131 .. method:: Object.last()
132
133 Return the index of the last element in the collection. If the collection
134 is empty, None is returned.
135
136
137 .. method:: Object.next(index)
138
139 Return the index of the next element in the collection following the
140 specified index. If there are no elements in the collection following the
141 specified index, None is returned.
142
143
144 .. method:: Object.prev(index)
145
146 Return the index of the element in the collection preceding the specified
147 index. If there are no elements in the collection preceding the
148 specified index, None is returned.
149
150
151 .. method:: Object.setelement(index, value)
152
153 Set the value in the collection at the specified index to the given value.
154
155
156 .. method:: Object.size()
157
158 Return the number of elements in the collection.
159
160
161 .. method:: Object.trim(num)
162
163 Remove the specified number of elements from the end of the collection.
164
165
166 .. _objectattr:
167
168 Object Attribute Objects
169 ------------------------
170
171 .. note::
172
173 This object is an extension to the DB API. The elements of
174 :attr:`ObjectType.attributes` are instances of this type.
175
176
177 .. attribute:: ObjectAttribute.name
178
179 This read-only attribute returns the name of the attribute.
180
181
182 .. attribute:: ObjectAttribute.type
183
184 This read-only attribute returns the type of the attribute. This will be an
185 :ref:`Oracle Object Type <objecttype>` if the variable binds
186 Oracle objects; otherwise, it will be one of the
187 :ref:`database type constants <dbtypes>`.
188
189 .. versionadded:: 8.0
0 .. _sesspool:
1
2 ******************
3 SessionPool Object
4 ******************
5
6 .. note::
7
8 This object is an extension to the DB API.
9
10 Connection pooling in cx_Oracle is handled by SessionPool objects.
11
12 See :ref:`connpool` for information on connection pooling.
13
14
15 .. method:: SessionPool.acquire(user=None, password=None, cclass=None, \
16 purity=cx_Oracle.ATTR_PURITY_DEFAULT, tag=None, matchanytag=False, \
17 shardingkey=[], supershardingkey=[])
18
19 Acquire a connection from the session pool and return a
20 :ref:`connection object <connobj>`.
21
22 If the pool is homogeneous, the user and password parameters cannot be
23 specified. If they are, an exception will be raised.
24
25 The cclass parameter, if specified, should be a string corresponding to the
26 connection class for database resident connection pooling (DRCP).
27
28 The purity parameter is expected to be one of
29 :data:`~cx_Oracle.ATTR_PURITY_NEW`, :data:`~cx_Oracle.ATTR_PURITY_SELF`, or
30 :data:`~cx_Oracle.ATTR_PURITY_DEFAULT`.
31
32 The tag parameter, if specified, is expected to be a string with name=value
33 pairs like "k1=v1;k2=v2" and will limit the sessions that can be returned
34 from a session pool unless the matchanytag parameter is set to True. In
35 that case sessions with the specified tag will be preferred over others,
36 but if no such sessions are available a session with a different tag may be
37 returned instead. In any case, untagged sessions will always be returned if
38 no sessions with the specified tag are available. Sessions are tagged when
39 they are :meth:`released <SessionPool.release>` back to the pool.
40
41 The shardingkey and supershardingkey parameters, if specified, are expected
42 to be a sequence of values which will be used to identify the database
43 shard to connect to. The key values can be strings, numbers, bytes or dates.
44
45 .. attribute:: SessionPool.busy
46
47 This read-only attribute returns the number of sessions currently acquired.
48
49
50 .. method:: SessionPool.close(force=False)
51
52 Close the session pool now, rather than when the last reference to it is
53 released, which makes it unusable for further work.
54
55 If any connections have been acquired and not released back to the pool
56 this method will fail unless the force parameter is set to True.
57
58
59 .. method:: SessionPool.drop(connection)
60
61 Drop the connection from the pool which is useful if the connection is no
62 longer usable (such as when the session is killed).
63
64
65 .. attribute:: SessionPool.dsn
66
67 This read-only attribute returns the TNS entry of the database to which a
68 connection has been established.
69
70
71 .. attribute:: SessionPool.homogeneous
72
73 This read-write boolean attribute indicates whether the pool is considered
74 homogeneous or not. If the pool is not homogeneous different authentication
75 can be used for each connection acquired from the pool.
76
77
78 .. attribute:: SessionPool.increment
79
80 This read-only attribute returns the number of sessions that will be
81 established when additional sessions need to be created.
82
83
84 .. attribute:: SessionPool.max
85
86 This read-only attribute returns the maximum number of sessions that the
87 session pool can control.
88
89
90 .. attribute:: SessionPool.max_lifetime_session
91
92 This read-write attribute returns the maximum length of time (in seconds)
93 that a pooled session may exist. Sessions that are in use will not be
94 closed. They become candidates for termination only when they are released
95 back to the pool and have existed for longer than max_lifetime_session
96 seconds. Note that termination only occurs when the pool is accessed. A
97 value of 0 means that there is no maximum length of time that a pooled
98 session may exist. This attribute is only available in Oracle Database
99 12.1.
100
101
102
103 .. versionadded:: 5.3
104
105
106 .. attribute:: SessionPool.min
107
108 This read-only attribute returns the number of sessions with which the
109 session pool was created and the minimum number of sessions that will be
110 controlled by the session pool.
111
112
113 .. attribute:: SessionPool.name
114
115 This read-only attribute returns the name assigned to the session pool by
116 Oracle.
117
118
119 .. attribute:: SessionPool.opened
120
121 This read-only attribute returns the number of sessions currently opened by
122 the session pool.
123
124
125 .. method:: SessionPool.release(connection, tag=None)
126
127 Release the connection back to the pool now, rather than whenever __del__
128 is called. The connection will be unusable from this point forward; an
129 Error exception will be raised if any operation is attempted with the
130 connection. Any cursors or LOBs created by the connection will also be
131 marked unusable and an Error exception will be raised if any operation is
132 attempted with them.
133
134 Internally, references to the connection are held by cursor objects,
135 LOB objects, etc. Once all of these references are released, the connection
136 itself will be released back to the pool automatically. Either control
137 references to these related objects carefully or explicitly release
138 connections back to the pool in order to ensure sufficient resources are
139 available.
140
141 If the tag is not None, it is expected to be a string with name=value pairs
142 like "k1=v1;k2=v2" and will override the value in the property
143 :attr:`Connection.tag`. If either :attr:`Connection.tag` or the tag
144 parameter are not None, the connection will be retagged when it is released
145 back to the pool.
146
147
148 .. attribute:: SessionPool.stmtcachesize
149
150 This read-write attribute specifies the size of the statement cache that
151 will be used as the starting point for any connections that are created by
152 the session pool. Once a connection is created, that connection's statement
153 cache size can only be changed by setting the
154 :attr:`Connection.stmtcachesize` attribute on the connection itself.
155
156 See :ref:`Statement Caching <stmtcache>` for more information.
157
158 .. versionadded:: 6.0
159
160
161 .. attribute:: SessionPool.timeout
162
163 This read-write attribute specifies the time (in seconds) after which idle
164 sessions will be terminated in order to maintain an optimum number of open
165 sessions. Note that termination only occurs when the pool is accessed. A
166 value of 0 means that no idle sessions are terminated.
167
168
169 .. attribute:: SessionPool.tnsentry
170
171 This read-only attribute returns the TNS entry of the database to which a
172 connection has been established.
173
174
175 .. attribute:: SessionPool.username
176
177 This read-only attribute returns the name of the user which established the
178 connection to the database.
179
180
181 .. attribute:: SessionPool.wait_timeout
182
183 This read-write attribute specifies the time (in milliseconds) that the
184 caller should wait for a session to become available in the pool before
185 returning with an error. This value is only used if the getmode parameter
186 to :meth:`cx_Oracle.SessionPool()` was the value
187 :data:`cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT`.
188
189 .. versionadded:: 6.4
0 .. _soda:
1
2 ****
3 SODA
4 ****
5
6 `Oracle Database Simple Oracle Document Access (SODA)
7 <https://docs.oracle.com/en/database/oracle/simple-oracle-document-access>`__
8 allows documents to be inserted, queried, and retrieved from Oracle Database
9 using a set of NoSQL-style cx_Oracle methods.
10
11 See :ref:`sodausermanual` for a cx_Oracle example.
12
13 SODA requires Oracle Client 18.3 or higher and Oracle Database 18.1 and higher.
14 The role SODA_APP must be granted to the user.
15
16 See
17 `this tracking issue <https://github.com/oracle/python-cx_Oracle/issues/309>`__ for known issues with SODA.
18
19 .. _sodadb:
20
21 --------------------
22 SODA Database Object
23 --------------------
24
25 .. note::
26
27 This object is an extension the DB API. It is returned by the method
28 :meth:`Connection.getSodaDatabase()`.
29
30
31 .. method:: SodaDatabase.createCollection(name, metadata=None, mapMode=False)
32
33 Creates a SODA collection with the given name and returns a new
34 :ref:`SODA collection object <sodacoll>`. If you try to create a
35 collection, and a collection with the same name and metadata already
36 exists, then that existing collection is opened without error.
37
38 If metadata is specified, it is expected to be a string containing valid
39 JSON or a dictionary that will be transformed into a JSON string. This JSON
40 permits you to specify the configuration of the collection including
41 storage options; specifying the presence or absence of columns for creation
42 timestamp, last modified timestamp and version; whether the collection can
43 store only JSON documents; and methods of key and version generation. The
44 default metadata creates a collection that only supports JSON documents and
45 uses system generated keys. See this `collection metadata reference
46 <https://www.oracle.com/pls/topic/
47 lookup?ctx=dblatest&id=GUID-49EFF3D3-9FAB-4DA6-BDE2-2650383566A3>`__
48 for more information.
49
50 If the mapMode parameter is set to True, the new collection is mapped to an
51 existing table instead of creating a table. If a collection is created in
52 this way, dropping the collection will not drop the existing table either.
53
54 .. versionadded:: 7.0
55
56
57 .. method:: SodaDatabase.createDocument(content, key=None, mediaType="application/json")
58
59 Creates a :ref:`SODA document <sodadoc>` usable for SODA write operations.
60 You only need to use this method if your collection requires
61 client-assigned keys or has non-JSON content; otherwise, you can pass your
62 content directly to SODA write operations. SodaDocument attributes
63 'createdOn', 'lastModified' and 'version' will be None.
64
65 The content parameter can be a dictionary or list which will be transformed
66 into a JSON string and then UTF-8 encoded. It can also be a string which
67 will be UTF-8 encoded or it can be a bytes object which will be stored
68 unchanged. If a bytes object is provided and the content is expected to be
69 JSON, note that SODA only supports UTF-8, UTF-16LE and UTF-16BE encodings.
70
71 The key parameter should only be supplied if the collection in which the
72 document is to be placed requires client-assigned keys.
73
74 The mediaType parameter should only be supplied if the collection in which
75 the document is to be placed supports non-JSON documents and the content
76 for this document is non-JSON. Using a standard MIME type for this value is
77 recommended but any string will be accepted.
78
79 .. versionadded:: 7.0
80
81
82 .. method:: SodaDatabase.getCollectionNames(startName=None, limit=0)
83
84 Returns a list of the names of collections in the database that match the
85 criteria, in alphabetical order.
86
87 If the startName parameter is specified, the list of names returned will
88 start with this value and also contain any names that fall after this value
89 in alphabetical order.
90
91 If the limit parameter is specified and is non-zero, the number of
92 collection names returned will be limited to this value.
93
94 .. versionadded:: 7.0
95
96
97 .. method:: SodaDatabase.openCollection(name)
98
99 Opens an existing collection with the given name and returns a new
100 :ref:`SODA collection object <sodacoll>`. If a collection with that name
101 does not exist, None is returned.
102
103 .. versionadded:: 7.0
104
105
106 .. _sodacoll:
107
108 ----------------------
109 SODA Collection Object
110 ----------------------
111
112 .. note::
113
114 This object is an extension the DB API. It is used to represent SODA
115 collections and is created by methods
116 :meth:`SodaDatabase.createCollection()` and
117 :meth:`SodaDatabase.openCollection()`.
118
119
120 .. method:: SodaCollection.createIndex(spec)
121
122 Creates an index on a SODA collection. The spec is expected to be a
123 dictionary or a JSON-encoded string. See this `overview
124 <https://www.oracle.com/pls/topic/
125 lookup?ctx=dblatest&id=GUID-4848E6A0-58A7-44FD-8D6D-A033D0CCF9CB>`__
126 for information on indexes in SODA.
127
128 Note that a commit should be performed before attempting to create an
129 index.
130
131 .. versionadded:: 7.0
132
133
134 .. method:: SodaCollection.drop()
135
136 Drops the collection from the database, if it exists. Note that if the
137 collection was created with mapMode set to True the underlying table will
138 not be dropped.
139
140 A boolean value is returned indicating if the collection was actually
141 dropped.
142
143 .. versionadded:: 7.0
144
145
146 .. method:: SodaCollection.dropIndex(name, force=False)
147
148 Drops the index with the specified name, if it exists.
149
150 The force parameter, if set to True, can be used to force the dropping of
151 an index that the underlying Oracle Database domain index doesn't normally
152 permit. This is only applicable to spatial and JSON search indexes.
153 See `here <https://www.oracle.com/pls/topic/
154 lookup?ctx=dblatest&id=GUID-F60F75DF-2866-4F93-BB7F-8FCE64BF67B6>`__
155 for more information.
156
157 A boolean value is returned indicating if the index was actually dropped.
158
159 .. versionadded:: 7.0
160
161
162 .. method:: SodaCollection.find()
163
164 This method is used to begin an operation that will act upon documents in
165 the collection. It creates and returns a
166 :ref:`SodaOperation object <sodaop>` which is used to specify the criteria
167 and the operation that will be performed on the documents that match that
168 criteria.
169
170 .. versionadded:: 7.0
171
172
173 .. method:: SodaCollection.getDataGuide()
174
175 Returns a :ref:`SODA document object <sodadoc>` containing property names,
176 data types and lengths inferred from the JSON documents in the collection.
177 It can be useful for exploring the schema of a collection. Note that this
178 method is only supported for JSON-only collections where a JSON search
179 index has been created with the 'dataguide' option enabled. If there are
180 no documents in the collection, None is returned.
181
182 .. versionadded:: 7.0
183
184
185 .. method:: SodaCollection.insertMany(docs)
186
187 Inserts a list of documents into the collection at one time. Each of the
188 input documents can be a dictionary or list or an existing :ref:`SODA
189 document object <sodadoc>`.
190
191 .. note::
192
193 This method requires Oracle Client 18.5 and higher and is available
194 only as a preview.
195
196 .. versionadded:: 7.2
197
198
199 .. method:: SodaCollection.insertManyAndGet(docs)
200
201 Similarly to :meth:`~SodaCollection.insertMany()` this method inserts a
202 list of documents into the collection at one time. The only difference is
203 that it returns a list of :ref:`SODA Document objects <sodadoc>`. Note that
204 for performance reasons the returned documents do not contain the content.
205
206 .. note::
207
208 This method requires Oracle Client 18.5 and higher.
209
210 .. versionadded:: 7.2
211
212
213 .. method:: SodaCollection.insertOne(doc)
214
215 Inserts a given document into the collection. The input document can be a
216 dictionary or list or an existing :ref:`SODA document object <sodadoc>`.
217
218 .. versionadded:: 7.0
219
220
221 .. method:: SodaCollection.insertOneAndGet(doc)
222
223 Similarly to :meth:`~SodaCollection.insertOne()` this method inserts a
224 given document into the collection. The only difference is that it
225 returns a :ref:`SODA Document object <sodadoc>`. Note that for performance
226 reasons the returned document does not contain the content.
227
228 .. versionadded:: 7.0
229
230
231 .. attribute:: SodaCollection.metadata
232
233 This read-only attribute returns a dictionary containing the metadata that
234 was used to create the collection. See this `collection metadata reference
235 <https://www.oracle.com/pls/topic/
236 lookup?ctx=dblatest&id=GUID-49EFF3D3-9FAB-4DA6-BDE2-2650383566A3>`__
237 for more information.
238
239 .. versionadded:: 7.0
240
241
242 .. attribute:: SodaCollection.name
243
244 This read-only attribute returns the name of the collection.
245
246 .. versionadded:: 7.0
247
248
249 .. method:: SodaCollection.save(doc)
250
251 Saves a document into the collection. This method is equivalent to
252 :meth:`~SodaCollection.insertOne()` except that if client-assigned keys are
253 used, and the document with the specified key already exists in the
254 collection, it will be replaced with the input document.
255
256 .. versionadded:: 8.0
257
258
259 .. method:: SodaCollection.saveAndGet(doc)
260
261 Saves a document into the collection. This method is equivalent to
262 :meth:`~SodaCollection.insertOneAndGet()` except that if client-assigned
263 keys are used, and the document with the specified key already exists in
264 the collection, it will be replaced with the input document.
265
266 .. versionadded:: 8.0
267
268
269 .. method:: SodaCollection.truncate()
270
271 Removes all of the documents in the collection, similarly to what is done
272 for rows in a table by the TRUNCATE TABLE statement.
273
274 .. versionadded:: 8.0
275
276
277 .. _sodadoc:
278
279 --------------------
280 SODA Document Object
281 --------------------
282
283 .. note::
284
285 This object is an extension the DB API. It is returned by the methods
286 :meth:`SodaDatabase.createDocument()`,
287 :meth:`SodaOperation.getDocuments()` and
288 :meth:`SodaOperation.getOne()` as well as by iterating over
289 :ref:`SODA document cursors <sodadoccur>`.
290
291
292 .. attribute:: SodaDoc.createdOn
293
294 This read-only attribute returns the creation time of the document in
295 `ISO 8601 <https://www.iso.org/iso-8601-date-and-time-format.html>`__
296 format. Documents created by :meth:`SodaDatabase.createDocument()` or
297 fetched from collections where this attribute is not stored will return
298 None.
299
300 .. versionadded:: 7.0
301
302
303 .. method:: SodaDoc.getContent()
304
305 Returns the content of the document as a dictionary or list. This method
306 assumes that the content is application/json and will raise an exception if
307 this is not the case. If there is no content, however, None will be
308 returned.
309
310 .. versionadded:: 7.0
311
312
313 .. method:: SodaDoc.getContentAsBytes()
314
315 Returns the content of the document as a bytes object. If there is no
316 content, however, None will be returned.
317
318 .. versionadded:: 7.0
319
320
321 .. method:: SodaDoc.getContentAsString()
322
323 Returns the content of the document as a string. If the document encoding
324 is not known, UTF-8 will be used. If there is no content, however, None
325 will be returned.
326
327 .. versionadded:: 7.0
328
329
330 .. attribute:: SodaDoc.key
331
332 This read-only attribute returns the unique key assigned to this document.
333 Documents created by :meth:`SodaDatabase.createDocument()` may not have a
334 value assigned to them and return None.
335
336 .. versionadded:: 7.0
337
338
339 .. attribute:: SodaDoc.lastModified
340
341 This read-only attribute returns the last modified time of the document in
342 `ISO 8601 <https://www.iso.org/iso-8601-date-and-time-format.html>`__
343 format. Documents created by :meth:`SodaDatabase.createDocument()` or
344 fetched from collections where this attribute is not stored will return
345 None.
346
347 .. versionadded:: 7.0
348
349
350 .. attribute:: SodaDoc.mediaType
351
352 This read-only attribute returns the media type assigned to the document.
353 By convention this is expected to be a MIME type but no checks are
354 performed on this value. If a value is not specified when calling
355 :meth:`SodaDatabase.createDocument()` or the document is fetched from a
356 collection where this component is not stored, the string
357 "application/json" is returned.
358
359 .. versionadded:: 7.0
360
361
362 .. attribute:: SodaDoc.version
363
364 This read-only attribute returns the version assigned to this document.
365 Documents created by :meth:`SodaDatabase.createDocument()` or fetched
366 from collections where this attribute is not stored will return None.
367
368 .. versionadded:: 7.0
369
370
371 .. _sodadoccur:
372
373 ---------------------------
374 SODA Document Cursor Object
375 ---------------------------
376
377 .. note::
378
379 This object is an extension the DB API. It is returned by the method
380 :meth:`SodaOperation.getCursor()` and implements the iterator protocol.
381 Each iteration will return a :ref:`SODA document object <sodadoc>`.
382
383
384 .. method:: SodaDocCursor.close()
385
386 Close the cursor now, rather than whenever __del__ is called. The cursor
387 will be unusable from this point forward; an Error exception will be raised
388 if any operation is attempted with the cursor.
389
390 .. versionadded:: 7.0
391
392
393 .. _sodaop:
394
395 ---------------------
396 SODA Operation Object
397 ---------------------
398
399 .. note::
400
401 This object is an extension to the DB API. It represents an operation that
402 will be performed on all or some of the documents in a SODA collection. It
403 is created by the method :meth:`SodaCollection.find()`.
404
405
406 .. method:: SodaOperation.count()
407
408 Returns a count of the number of documents in the collection that match
409 the criteria. If :meth:`~SodaOperation.skip()` or
410 :meth:`~SodaOperation.limit()` were called on this object, an exception is
411 raised.
412
413 .. versionadded:: 7.0
414
415
416 .. method:: SodaOperation.fetchArraySize(value)
417
418 This is a tuning method to specify the number of documents that are
419 internally fetched in batches by calls to :meth:`~SodaOperation.getCursor()`
420 and :meth:`~SodaOperation.getDocuments()`. It does not affect how many
421 documents are returned to the application. A value of 0 will use the default
422 value (100). This method is only available in Oracle Client 19.5 and higher.
423
424 As a convenience, the SodaOperation object is returned so that further
425 criteria can be specified by chaining methods together.
426
427 .. versionadded:: 8.0
428
429
430 .. method:: SodaOperation.filter(value)
431
432 Sets a filter specification for complex document queries and ordering of
433 JSON documents. Filter specifications must be provided as a dictionary or
434 JSON-encoded string and can include comparisons, regular expressions,
435 logical and spatial operators, among others. See the
436 `overview of SODA filter specifications
437 <https://www.oracle.com/pls/topic/
438 lookup?ctx=dblatest&id=GUID-CB09C4E3-BBB1-40DC-88A8-8417821B0FBE>`__
439 for more information.
440
441 As a convenience, the SodaOperation object is returned so that further
442 criteria can be specified by chaining methods together.
443
444 .. versionadded:: 7.0
445
446
447 .. method:: SodaOperation.getCursor()
448
449 Returns a :ref:`SODA Document Cursor object <sodadoccur>` that can be used
450 to iterate over the documents that match the criteria.
451
452 .. versionadded:: 7.0
453
454
455 .. method:: SodaOperation.getDocuments()
456
457 Returns a list of :ref:`SODA Document objects <sodadoc>` that match the
458 criteria.
459
460 .. versionadded:: 7.0
461
462
463 .. method:: SodaOperation.getOne()
464
465 Returns a single :ref:`SODA Document object <sodadoc>` that matches the
466 criteria. Note that if multiple documents match the criteria only the first
467 one is returned.
468
469 .. versionadded:: 7.0
470
471
472 .. method:: SodaOperation.key(value)
473
474 Specifies that the document with the specified key should be returned.
475 This causes any previous calls made to this method and
476 :meth:`~SodaOperation.keys()` to be ignored.
477
478 As a convenience, the SodaOperation object is returned so that further
479 criteria can be specified by chaining methods together.
480
481 .. versionadded:: 7.0
482
483
484 .. method:: SodaOperation.keys(seq)
485
486 Specifies that documents that match the keys found in the supplied sequence
487 should be returned. This causes any previous calls made to this method and
488 :meth:`~SodaOperation.key()` to be ignored.
489
490 As a convenience, the SodaOperation object is returned so that further
491 criteria can be specified by chaining methods together.
492
493 .. versionadded:: 7.0
494
495
496 .. method:: SodaOperation.limit(value)
497
498 Specifies that only the specified number of documents should be returned.
499 This method is only usable for read operations such as
500 :meth:`~SodaOperation.getCursor()` and
501 :meth:`~SodaOperation.getDocuments()`. For write operations, any value set
502 using this method is ignored.
503
504 As a convenience, the SodaOperation object is returned so that further
505 criteria can be specified by chaining methods together.
506
507 .. versionadded:: 7.0
508
509
510 .. method:: SodaOperation.remove()
511
512 Removes all of the documents in the collection that match the criteria. The
513 number of documents that have been removed is returned.
514
515 .. versionadded:: 7.0
516
517
518 .. method:: SodaOperation.replaceOne(doc)
519
520 Replaces a single document in the collection with the specified document.
521 The input document can be a dictionary or list or an existing
522 :ref:`SODA document object <sodadoc>`. A boolean indicating if a document
523 was replaced or not is returned.
524
525 Currently the method :meth:`~SodaOperation.key()` must be called before
526 this method can be called.
527
528 .. versionadded:: 7.0
529
530
531 .. method:: SodaOperation.replaceOneAndGet(doc)
532
533 Similarly to :meth:`~SodaOperation.replaceOne()`, this method replaces a
534 single document in the collection with the specified document. The only
535 difference is that it returns a :ref:`SODA document object <sodadoc>`.
536 Note that for performance reasons the returned document does not contain
537 the content.
538
539 .. versionadded:: 7.0
540
541
542 .. method:: SodaOperation.skip(value)
543
544 Specifies the number of documents that match the other criteria that will
545 be skipped. This method is only usable for read operations such as
546 :meth:`~SodaOperation.getCursor()` and
547 :meth:`~SodaOperation.getDocuments()`. For write operations, any value set
548 using this method is ignored.
549
550 As a convenience, the SodaOperation object is returned so that further
551 criteria can be specified by chaining methods together.
552
553 .. versionadded:: 7.0
554
555
556 .. method:: SodaOperation.version(value)
557
558 Specifies that documents with the specified version should be returned.
559 Typically this is used with :meth:`~SodaOperation.key()` to implement
560 optimistic locking, so that the write operation called later does not
561 affect a document that someone else has modified.
562
563 As a convenience, the SodaOperation object is returned so that further
564 criteria can be specified by chaining methods together.
565
566 .. versionadded:: 7.0
0 .. _subscrobj:
1
2 *******************
3 Subscription Object
4 *******************
5
6 .. note::
7
8 This object is an extension the DB API.
9
10
11 .. attribute:: Subscription.callback
12
13 This read-only attribute returns the callback that was registered when the
14 subscription was created.
15
16
17 .. attribute:: Subscription.connection
18
19 This read-only attribute returns the connection that was used to register
20 the subscription when it was created.
21
22
23 .. attribute:: Subscription.id
24
25 This read-only attribute returns the value of ``REGID`` found in the
26 database view ``USER_CHANGE_NOTIFICATION_REGS`` or the value of ``REG_ID``
27 found in the database view ``USER_SUBSCR_REGISTRATIONS``. For AQ
28 subscriptions, the value is 0.
29
30
31 .. attribute:: Subscription.ipAddress
32
33 This read-only attribute returns the IP address used for callback
34 notifications from the database server. If not set during construction,
35 this value is None.
36
37 .. versionadded:: 6.4
38
39
40 .. attribute:: Subscription.name
41
42 This read-only attribute returns the name used to register the subscription
43 when it was created.
44
45 .. versionadded:: 6.4
46
47
48 .. attribute:: Subscription.namespace
49
50 This read-only attribute returns the namespace used to register the
51 subscription when it was created.
52
53
54 .. attribute:: Subscription.operations
55
56 This read-only attribute returns the operations that will send
57 notifications for each table or query that is registered using this
58 subscription.
59
60
61 .. attribute:: Subscription.port
62
63 This read-only attribute returns the port used for callback notifications
64 from the database server. If not set during construction, this value is
65 zero.
66
67
68 .. attribute:: Subscription.protocol
69
70 This read-only attribute returns the protocol used to register the
71 subscription when it was created.
72
73
74 .. attribute:: Subscription.qos
75
76 This read-only attribute returns the quality of service flags used to
77 register the subscription when it was created.
78
79
80 .. method:: Subscription.registerquery(statement, [args])
81
82 Register the query for subsequent notification when tables referenced by
83 the query are changed. This behaves similarly to cursor.execute() but only
84 queries are permitted and the args parameter must be a sequence or
85 dictionary. If the qos parameter included the flag
86 cx_Oracle.SUBSCR_QOS_QUERY when the subscription was created, then the ID
87 for the registered query is returned; otherwise, None is returned.
88
89
90 .. attribute:: Subscription.timeout
91
92 This read-only attribute returns the timeout (in seconds) that was
93 specified when the subscription was created. A value of 0 indicates that
94 there is no timeout.
95
96
97 .. _msgobjects:
98
99 Message Objects
100 ---------------
101
102 .. note::
103
104 This object is created internally when notification is received and passed
105 to the callback procedure specified when a subscription is created.
106
107
108 .. attribute:: Message.consumerName
109
110 This read-only attribute returns the name of the consumer which generated
111 the notification. It will be populated if the subscription was created with
112 the namespace :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ` and the queue is a
113 multiple consumer queue.
114
115 .. versionadded:: 6.4
116
117
118 .. attribute:: Message.dbname
119
120 This read-only attribute returns the name of the database that generated
121 the notification.
122
123
124 .. attribute:: Message.queries
125
126 This read-only attribute returns a list of message query objects that give
127 information about query result sets changed for this notification. This
128 attribute will be None if the qos parameter did not include the flag
129 :data:`~cx_Oracle.SUBSCR_QOS_QUERY` when the subscription was created.
130
131
132 .. attribute:: Message.queueName
133
134 This read-only attribute returns the name of the queue which generated the
135 notification. It will only be populated if the subscription was created
136 with the namespace :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ`.
137
138 .. versionadded:: 6.4
139
140
141 .. attribute:: Message.registered
142
143 This read-only attribute returns whether the subscription which generated
144 this notification is still registered with the database. The subscription
145 is automatically deregistered with the database when the subscription
146 timeout value is reached or when the first notification is sent (when the
147 quality of service flag :data:`cx_Oracle.SUBSCR_QOS_DEREG_NFY` is used).
148
149 .. versionadded:: 6.4
150
151
152 .. attribute:: Message.subscription
153
154 This read-only attribute returns the subscription object for which this
155 notification was generated.
156
157
158 .. attribute:: Message.tables
159
160 This read-only attribute returns a list of message table objects that give
161 information about the tables changed for this notification. This
162 attribute will be None if the qos parameter included the flag
163 :data:`~cx_Oracle.SUBSCR_QOS_QUERY` when the subscription was created.
164
165
166 .. attribute:: Message.txid
167
168 This read-only attribute returns the id of the transaction that generated
169 the notification.
170
171
172 .. attribute:: Message.type
173
174 This read-only attribute returns the type of message that has been sent.
175 See the constants section on event types for additional information.
176
177
178 Message Table Objects
179 ---------------------
180
181 .. note::
182
183 This object is created internally for each table changed when notification
184 is received and is found in the tables attribute of message objects, and
185 the tables attribute of message query objects.
186
187
188 .. attribute:: MessageTable.name
189
190 This read-only attribute returns the name of the table that was changed.
191
192
193 .. attribute:: MessageTable.operation
194
195 This read-only attribute returns the operation that took place on the table
196 that was changed.
197
198
199 .. attribute:: MessageTable.rows
200
201 This read-only attribute returns a list of message row objects that give
202 information about the rows changed on the table. This value is only filled
203 in if the qos parameter to the :meth:`Connection.subscribe()` method
204 included the flag :data:`~cx_Oracle.SUBSCR_QOS_ROWIDS`.
205
206
207 Message Row Objects
208 -------------------
209
210 .. note::
211
212 This object is created internally for each row changed on a table when
213 notification is received and is found in the rows attribute of message
214 table objects.
215
216
217 .. attribute:: MessageRow.operation
218
219 This read-only attribute returns the operation that took place on the row
220 that was changed.
221
222
223 .. attribute:: MessageRow.rowid
224
225 This read-only attribute returns the rowid of the row that was changed.
226
227
228 Message Query Objects
229 ---------------------
230
231 .. note::
232
233 This object is created internally for each query result set changed when
234 notification is received and is found in the queries attribute of message
235 objects.
236
237
238 .. attribute:: MessageQuery.id
239
240 This read-only attribute returns the query id of the query for which the
241 result set changed. The value will match the value returned by
242 Subscription.registerquery when the related query was registered.
243
244
245 .. attribute:: MessageQuery.operation
246
247 This read-only attribute returns the operation that took place on the query
248 result set that was changed. Valid values for this attribute are
249 :data:`~cx_Oracle.EVENT_DEREG` and :data:`~cx_Oracle.EVENT_QUERYCHANGE`.
250
251
252 .. attribute:: MessageQuery.tables
253
254 This read-only attribute returns a list of message table objects that give
255 information about the table changes that caused the query result set to
256 change for this notification.
0 .. _varobj:
1
2 ****************
3 Variable Objects
4 ****************
5
6 .. note::
7
8 The DB API definition does not define this object.
9
10
11 .. attribute:: Variable.actualElements
12
13 This read-only attribute returns the actual number of elements in the
14 variable. This corresponds to the number of elements in a PL/SQL index-by
15 table for variables that are created using the method
16 :func:`Cursor.arrayvar()`. For all other variables this value will be
17 identical to the attribute :attr:`~Variable.numElements`.
18
19 .. attribute:: Variable.bufferSize
20
21 This read-only attribute returns the size of the buffer allocated for each
22 element in bytes.
23
24
25 .. method:: Variable.getvalue([pos=0])
26
27 Return the value at the given position in the variable. For variables
28 created using the method :func:`Cursor.arrayvar()` the value returned will
29 be a list of each of the values in the PL/SQL index-by table. For variables
30 bound to DML returning statements, the value returned will also be a list
31 corresponding to the returned data for the given execution of the statement
32 (as identified by the pos parameter).
33
34
35 .. attribute:: Variable.inconverter
36
37 This read-write attribute specifies the method used to convert data from
38 Python to the Oracle database. The method signature is converter(value)
39 and the expected return value is the value to bind to the database. If this
40 attribute is None, the value is bound directly without any conversion.
41
42
43 .. attribute:: Variable.numElements
44
45 This read-only attribute returns the number of elements allocated in an
46 array, or the number of scalar items that can be fetched into the variable
47 or bound to the variable.
48
49
50 .. attribute:: Variable.outconverter
51
52 This read-write attribute specifies the method used to convert data from
53 the Oracle database to Python. The method signature is converter(value)
54 and the expected return value is the value to return to Python. If this
55 attribute is None, the value is returned directly without any conversion.
56
57
58 .. method:: Variable.setvalue(pos, value)
59
60 Set the value at the given position in the variable.
61
62
63 .. attribute:: Variable.size
64
65 This read-only attribute returns the size of the variable. For strings this
66 value is the size in characters. For all others, this is same value as the
67 attribute bufferSize.
68
69
70 .. attribute:: Variable.type
71
72 This read-only attribute returns the type of the variable. This will be an
73 :ref:`Oracle Object Type <objecttype>` if the variable binds
74 Oracle objects; otherwise, it will be one of the
75 :ref:`database type constants <dbtypes>`.
76
77 .. versionchanged:: 8.0
78 Database type constants are now used when the variable is not used for
79 binding Oracle objects.
80
81
82 .. attribute:: Variable.values
83
84 This read-only attribute returns a copy of the value of all actual
85 positions in the variable as a list. This is the equivalent of calling
86 :meth:`~Variable.getvalue()` for each valid position and the length will
87 correspond to the value of the :attr:`~Variable.actualElements` attribute.
+0
-221
doc/src/aq.rst less more
0 .. _aq:
1
2 ****************
3 Advanced Queuing
4 ****************
5
6 .. _deqoptions:
7
8 ---------------
9 Dequeue Options
10 ---------------
11
12 .. note::
13
14 This object is an extension to the DB API. It is returned by the
15 :meth:`Connection.deqoptions()` call and is used in calls to
16 :meth:`Connection.deq()`.
17
18
19 .. attribute:: DeqOptions.condition
20
21 This attribute specifies a boolean expression similar to the where clause
22 of a SQL query. The boolean expression can include conditions on message
23 properties, user data properties and PL/SQL or SQL functions. The default
24 is to have no condition specified.
25
26
27 .. attribute:: DeqOptions.consumername
28
29 This attribute specifies the name of the consumer. Only messages matching
30 the consumer name will be accessed. If the queue is not set up for multiple
31 consumers this attribute should not be set. The default is to have no
32 consumer name specified.
33
34
35 .. attribute:: DeqOptions.correlation
36
37 This attribute specifies the correlation identifier of the message to be
38 dequeued. Special pattern-matching characters, such as the percent sign (%)
39 and the underscore (_), can be used. If multiple messages satisfy the
40 pattern, the order of dequeuing is indeterminate. The default is to have no
41 correlation specified.
42
43
44 .. attribute:: DeqOptions.deliverymode
45
46 This write-only attribute specifies what types of messages should be
47 dequeued. It should be one of the values :data:`~cx_Oracle.MSG_PERSISTENT`
48 (default), :data:`~cx_Oracle.MSG_BUFFERED` or
49 :data:`~cx_Oracle.MSG_PERSISTENT_OR_BUFFERED`.
50
51
52 .. attribute:: DeqOptions.mode
53
54 This attribute specifies the locking behaviour associated with the dequeue
55 operation. It should be one of the values :data:`~cx_Oracle.DEQ_BROWSE`,
56 :data:`~cx_Oracle.DEQ_LOCKED`,
57 :data:`~cx_Oracle.DEQ_REMOVE` (default), or
58 :data:`~cx_Oracle.DEQ_REMOVE_NODATA`.
59
60
61 .. attribute:: DeqOptions.msgid
62
63 This attribute specifies the identifier of the message to be dequeued. The
64 default is to have no message identifier specified.
65
66
67 .. attribute:: DeqOptions.navigation
68
69 This attribute specifies the position of the message that is retrieved. It
70 should be one of the values :data:`~cx_Oracle.DEQ_FIRST_MSG`,
71 :data:`~cx_Oracle.DEQ_NEXT_MSG` (default), or
72 :data:`~cx_Oracle.DEQ_NEXT_TRANSACTION`.
73
74
75 .. attribute:: DeqOptions.transformation
76
77 This attribute specifies the name of the transformation that must be
78 applied after the message is dequeued from the database but before it is
79 returned to the calling application. The transformation must be created
80 using dbms_transform. The default is to have no transformation specified.
81
82
83 .. attribute:: DeqOptions.visibility
84
85 This attribute specifies the transactional behavior of the dequeue request.
86 It should be one of the values :data:`~cx_Oracle.DEQ_ON_COMMIT` (default)
87 or :data:`~cx_Oracle.DEQ_IMMEDIATE`. This attribute is ignored when using
88 the :data:`~cx_Oracle.DEQ_BROWSE` mode. Note the value of
89 :attr:`~Connection.autocommit` is always ignored.
90
91
92 .. attribute:: DeqOptions.wait
93
94 This attribute specifies the time to wait, in seconds, for a message
95 matching the search criteria to become available for dequeuing. One of the
96 values :data:`~cx_Oracle.DEQ_NO_WAIT` or
97 :data:`~cx_Oracle.DEQ_WAIT_FOREVER` can also be used. The default is
98 :data:`~cx_Oracle.DEQ_WAIT_FOREVER`.
99
100
101 .. _enqoptions:
102
103 ---------------
104 Enqueue Options
105 ---------------
106
107 .. note::
108
109 This object is an extension to the DB API. It is returned by the
110 :meth:`Connection.enqoptions()` call and is used in calls to
111 :meth:`Connection.enq()`.
112
113
114 .. attribute:: EnqOptions.deliverymode
115
116 This write-only attribute specifies what type of messages should be
117 enqueued. It should be one of the values :data:`~cx_Oracle.MSG_PERSISTENT`
118 (default) or :data:`~cx_Oracle.MSG_BUFFERED`.
119
120
121 .. attribute:: EnqOptions.transformation
122
123 This attribute specifies the name of the transformation that must be
124 applied before the message is enqueued into the database. The
125 transformation must be created using dbms_transform. The default is to have
126 no transformation specified.
127
128
129 .. attribute:: EnqOptions.visibility
130
131 This attribute specifies the transactional behavior of the enqueue request.
132 It should be one of the values :data:`~cx_Oracle.ENQ_ON_COMMIT` (default)
133 or :data:`~cx_Oracle.ENQ_IMMEDIATE`. Note the value of
134 :attr:`~Connection.autocommit` is ignored.
135
136
137 .. _msgproperties:
138
139 ------------------
140 Message Properties
141 ------------------
142
143 .. note::
144
145 This object is an extension to the DB API. It is returned by the
146 :meth:`Connection.msgproperties()` call and is used in calls to
147 :meth:`Connection.deq()` and :meth:`Connection.enq()`.
148
149
150 .. attribute:: MessageProperties.attempts
151
152 This read-only attribute specifies the number of attempts that have been
153 made to dequeue the message.
154
155
156 .. attribute:: MessageProperties.correlation
157
158 This attribute specifies the correlation used when the message was
159 enqueued.
160
161
162 .. attribute:: MessageProperties.delay
163
164 This attribute specifies the number of seconds to delay an enqueued
165 message. Any integer is acceptable but the constant
166 :data:`~cx_Oracle.MSG_NO_DELAY` can also be used indicating that the
167 message is available for immediate dequeuing.
168
169
170 .. attribute:: MessageProperties.deliverymode
171
172 This read-only attribute specifies the type of message that was dequeued.
173 It will be one of the values :data:`~cx_Oracle.MSG_PERSISTENT` or
174 :data:`~cx_Oracle.MSG_BUFFERED`.
175
176
177 .. attribute:: MessageProperties.enqtime
178
179 This read-only attribute specifies the time that the message was enqueued.
180
181
182 .. attribute:: MessageProperties.exceptionq
183
184 This attribute specifies the name of the queue to which the message is
185 moved if it cannot be processed successfully. Messages are moved if the
186 number of unsuccessful dequeue attempts has exceeded the maximum number of
187 retries or if the message has expired. All messages in the exception queue
188 are in the :data:`~cx_Oracle.MSG_EXPIRED` state. The default value is the
189 name of the exception queue associated with the queue table.
190
191
192 .. attribute:: MessageProperties.expiration
193
194 This attribute specifies, in seconds, how long the message is available for
195 dequeuing. This attribute is an offset from the delay attribute. Expiration
196 processing requires the queue monitor to be running. Any integer is
197 accepted but the constant :data:`~cx_Oracle.MSG_NO_EXPIRATION` can also be
198 used indicating that the message never expires.
199
200
201 .. attribute:: MessageProperties.msgid
202
203 This attribute specifies the id of the message in the last queue that
204 generated this message.
205
206
207 .. attribute:: MessageProperties.priority
208
209 This attribute specifies the priority of the message. A smaller number
210 indicates a higher priority. The priority can be any integer, including
211 negative numbers. The default value is zero.
212
213
214 .. attribute:: MessageProperties.state
215
216 This read-only attribute specifies the state of the message at the time of
217 the dequeue. It will be one of the values :data:`~cx_Oracle.MSG_WAITING`,
218 :data:`~cx_Oracle.MSG_READY`, :data:`~cx_Oracle.MSG_PROCESSED` or
219 :data:`~cx_Oracle.MSG_EXPIRED`.
220
3232
3333 # General substitutions.
3434 project = 'cx_Oracle'
35 copyright = u'2016, 2019, Oracle and/or its affiliates. All rights reserved. Portions Copyright © 2007-2015, Anthony Tuininga. All rights reserved. Portions Copyright © 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta, Canada. All rights reserved'
35 copyright = u'2016, 2020, Oracle and/or its affiliates. All rights reserved. Portions Copyright © 2007-2015, Anthony Tuininga. All rights reserved. Portions Copyright © 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta, Canada. All rights reserved'
3636 author = 'Oracle'
3737
3838 # The default replacements for |version| and |release|, also used in various
3939 # other places throughout the built documents.
4040 #
4141 # The short X.Y version.
42 version = '7.1'
42 version = '8.0'
4343 # The full version, including alpha/beta/rc tags.
44 release = '7.1.0'
44 release = '8.0.1'
4545
4646 # There are two options for replacing |today|: either, you set today to some
4747 # non-false value, then it is used:
107107 # Output file base name for HTML help builder.
108108 htmlhelp_basename = 'cx_Oracledoc'
109109
110 numfig = True
110111
111112 # Options for LaTeX output
112113 # ------------------------
+0
-652
doc/src/connection.rst less more
0 .. _connobj:
1
2 *****************
3 Connection Object
4 *****************
5
6 .. note::
7
8 Any outstanding changes will be rolled back when the connection object
9 is destroyed or closed.
10
11
12
13 .. method:: Connection.__enter__()
14
15 The entry point for the connection as a context manager. It returns itself.
16
17 .. note::
18
19 This method is an extension to the DB API definition.
20
21
22 .. method:: Connection.__exit__()
23
24 The exit point for the connection as a context manager. This will close
25 the connection and roll back any uncomitted transaction.
26
27 .. note::
28
29 This method is an extension to the DB API definition.
30
31
32 .. attribute:: Connection.action
33
34 This write-only attribute sets the action column in the v$session table. It
35 is a string attribute and cannot be set to None -- use the empty string
36 instead.
37
38 .. note::
39
40 This attribute is an extension to the DB API definition.
41
42
43 .. attribute:: Connection.autocommit
44
45 This read-write attribute determines whether autocommit mode is on or off.
46 When autocommit mode is on, all statements are committed as soon as they
47 have completed executing.
48
49 .. note::
50
51 This attribute is an extension to the DB API definition.
52
53
54 .. method:: Connection.begin([formatId, transactionId, branchId])
55
56 Explicitly begin a new transaction. Without parameters, this explicitly
57 begins a local transaction; otherwise, this explicitly begins a distributed
58 (global) transaction with the given parameters. See the Oracle
59 documentation for more details.
60
61 Note that in order to make use of global (distributed) transactions, the
62 :attr:`~Connection.internal_name` and :attr:`~Connection.external_name`
63 attributes must be set.
64
65 .. note::
66
67 This method is an extension to the DB API definition.
68
69
70 .. attribute:: Connection.callTimeout
71
72 This read-write attribute specifies the amount of time (in milliseconds)
73 that a single round-trip to the database may take before a timeout will
74 occur. A value of 0 means that no timeout will take place.
75
76 .. note::
77
78 This attribute is an extension to the DB API definition and is only
79 available in Oracle Client 18c and higher.
80
81
82 .. method:: Connection.cancel()
83
84 Cancel a long-running transaction.
85
86 .. note::
87
88 This method is an extension to the DB API definition.
89
90
91 .. method:: Connection.changepassword(oldpassword, newpassword)
92
93 Change the password of the logon.
94
95 .. note::
96
97 This method is an extension to the DB API definition.
98
99
100 .. attribute:: Connection.client_identifier
101
102 This write-only attribute sets the client_identifier column in the
103 v$session table.
104
105 .. note::
106
107 This attribute is an extension to the DB API definition.
108
109
110 .. attribute:: Connection.clientinfo
111
112 This write-only attribute sets the client_info column in the v$session
113 table.
114
115 .. note::
116
117 This attribute is an extension to the DB API definition.
118
119
120 .. method:: Connection.close()
121
122 Close the connection now, rather than whenever __del__ is called. The
123 connection will be unusable from this point forward; an Error exception
124 will be raised if any operation is attempted with the connection.
125
126 All open cursors and LOBs created by the connection will be closed and will
127 also no longer be usable.
128
129 Internally, references to the connection are held by cursor objects,
130 LOB objects, subscription objects, etc. Once all of these references are
131 released, the connection itself will be closed automatically. Either
132 control references to these related objects carefully or explicitly close
133 connections in order to ensure sufficient resources are available.
134
135
136 .. method:: Connection.commit()
137
138 Commit any pending transactions to the database.
139
140
141 .. method:: Connection.createlob(lobType)
142
143 Create and return a new temporary :ref:`LOB object <lobobj>` of the
144 specified type. The lobType parameter should be one of
145 :data:`cx_Oracle.CLOB`, :data:`cx_Oracle.BLOB` or :data:`cx_Oracle.NCLOB`.
146
147 .. versionadded:: 6.2
148
149 .. note::
150
151 This method is an extension to the DB API definition.
152
153
154 .. attribute:: Connection.current_schema
155
156 This read-write attribute sets the current schema attribute for the
157 session. Setting this value is the same as executing the SQL statement
158 "ALTER SESSION SET CURRENT_SCHEMA". The attribute is set (and verified) on
159 the next call that does a round trip to the server. The value is placed
160 before unqualified database objects in SQL statements you then execute.
161
162 .. note::
163
164 This attribute is an extension to the DB API definition.
165
166
167 .. method:: Connection.cursor()
168
169 Return a new :ref:`cursor object <cursorobj>` using the connection.
170
171
172 .. attribute:: Connection.dbop
173
174 This write-only attribute sets the database operation that is to be
175 monitored. This can be viewed in the DBOP_NAME column of the V$SQL_MONITOR
176 table.
177
178 .. note::
179
180 This attribute is an extension to the DB API definition.
181
182
183 .. method:: Connection.deq(name, options, msgproperties, payload)
184
185 Returns a message id after successfully dequeuing a message. The options
186 object can be created using :meth:`~Connection.deqoptions()` and the
187 msgproperties object can be created using
188 :meth:`~Connection.msgproperties()`. The payload must be an object created
189 using :meth:`ObjectType.newobject()`.
190
191 .. versionadded:: 5.3
192
193 .. note::
194
195 This method is an extension to the DB API definition.
196
197
198 .. method:: Connection.deqoptions()
199
200 Returns an object specifying the options to use when dequeuing messages.
201 See :ref:`deqoptions` for more information.
202
203 .. versionadded:: 5.3
204
205 .. note::
206
207 This method is an extension to the DB API definition.
208
209
210 .. attribute:: Connection.dsn
211
212 This read-only attribute returns the TNS entry of the database to which a
213 connection has been established.
214
215 .. note::
216
217 This attribute is an extension to the DB API definition.
218
219
220 .. attribute:: Connection.edition
221
222 This read-only attribute gets the session edition and is only available in
223 Oracle Database 11.2 (both client and server must be at this level or
224 higher for this to work).
225
226 .. versionadded:: 5.3
227
228 .. note::
229
230 This attribute is an extension to the DB API definition.
231
232
233 .. attribute:: Connection.encoding
234
235 This read-only attribute returns the IANA character set name of the
236 character set in use by the Oracle client for regular strings.
237
238 .. note::
239
240 This attribute is an extension to the DB API definition.
241
242
243 .. method:: Connection.enq(name, options, msgproperties, payload)
244
245 Returns a message id after successfully enqueuing a message. The options
246 object can be created using :meth:`~Connection.enqoptions()` and the
247 msgproperties object can be created using
248 :meth:`~Connection.msgproperties()`. The payload must be an object created
249 using :meth:`ObjectType.newobject()`.
250
251 .. versionadded:: 5.3
252
253 .. note::
254
255 This method is an extension to the DB API definition.
256
257
258 .. method:: Connection.enqoptions()
259
260 Returns an object specifying the options to use when enqueuing messages.
261 See :ref:`enqoptions` for more information.
262
263 .. versionadded:: 5.3
264
265 .. note::
266
267 This method is an extension to the DB API definition.
268
269
270 .. attribute:: Connection.external_name
271
272 This read-write attribute specifies the external name that is used by the
273 connection when logging distributed transactions.
274
275 .. versionadded:: 5.3
276
277 .. note::
278
279 This attribute is an extension to the DB API definition.
280
281
282 .. method:: Connection.getSodaDatabase()
283
284 Return a :ref:`SodaDatabase <sodadb>` object for Simple Oracle Document
285 Access (SODA). All SODA operations are performed either on the returned
286 SodaDatabase object or from objects created by the returned SodaDatabase
287 object. See `here <http://www.oracle.com/pls/topic/lookup?
288 ctx=dblatest&id=GUID-BE42F8D3-B86B-43B4-B2A3-5760A4DF79FB>`__ for
289 additional information on SODA.
290
291 SODA support in cx_Oracle is in Preview status and should not be used in
292 production. It will be supported with a future version of Oracle Client
293 libraries.
294
295 .. versionadded:: 7.0
296
297 .. note::
298
299 This method is an extension to the DB API definition.
300
301
302 .. method:: Connection.gettype(name)
303
304 Return a :ref:`type object <objecttype>` given its name. This can then be
305 used to create objects which can be bound to cursors created by this
306 connection.
307
308 .. versionadded:: 5.3
309
310 .. note::
311
312 This method is an extension to the DB API definition.
313
314
315 .. attribute:: Connection.handle
316
317 This read-only attribute returns the OCI service context handle for the
318 connection. It is primarily provided to facilitate testing the creation of
319 a connection using the OCI service context handle.
320
321 .. note::
322
323 This attribute is an extension to the DB API definition.
324
325
326 .. attribute:: Connection.inputtypehandler
327
328 This read-write attribute specifies a method called for each value that is
329 bound to a statement executed on any cursor associated with this
330 connection. The method signature is handler(cursor, value, arraysize) and
331 the return value is expected to be a variable object or None in which case
332 a default variable object will be created. If this attribute is None, the
333 default behavior will take place for all values bound to statements.
334
335 .. note::
336
337 This attribute is an extension to the DB API definition.
338
339
340 .. attribute:: Connection.internal_name
341
342 This read-write attribute specifies the internal name that is used by the
343 connection when logging distributed transactions.
344
345 .. versionadded:: 5.3
346
347 .. note::
348
349 This attribute is an extension to the DB API definition.
350
351
352 .. attribute:: Connection.ltxid
353
354 This read-only attribute returns the logical transaction id for the
355 connection. It is used within Oracle Transaction Guard as a means of
356 ensuring that transactions are not duplicated. See the Oracle documentation
357 and the provided sample for more information.
358
359 .. versionadded:: 5.3
360
361 .. note:
362
363 This attribute is an extension to the DB API definition. It is only
364 available when Oracle Database 12.1 or higher is in use on both the
365 server and the client.
366
367
368 .. attribute:: Connection.maxBytesPerCharacter
369
370 This read-only attribute returns the maximum number of bytes each character
371 can use for the client character set.
372
373 .. note::
374
375 This attribute is an extension to the DB API definition.
376
377
378 .. attribute:: Connection.module
379
380 This write-only attribute sets the module column in the v$session table.
381 The maximum length for this string is 48 and if you exceed this length you
382 will get ORA-24960.
383
384 .. note:
385
386 This attribute is an extension to the DB API definition.
387
388
389 .. method:: Connection.msgproperties()
390
391 Returns an object specifying the properties of messages used in advanced
392 queuing. See :ref:`msgproperties` for more information.
393
394 .. versionadded:: 5.3
395
396 .. note::
397
398 This method is an extension to the DB API definition.
399
400
401 .. attribute:: Connection.nencoding
402
403 This read-only attribute returns the IANA character set name of the
404 national character set in use by the Oracle client.
405
406 .. note::
407
408 This attribute is an extension to the DB API definition.
409
410
411 .. attribute:: Connection.outputtypehandler
412
413 This read-write attribute specifies a method called for each column that is
414 going to be fetched from any cursor associated with this connection. The
415 method signature is handler(cursor, name, defaultType, length, precision,
416 scale) and the return value is expected to be a variable object or None in
417 which case a default variable object will be created. If this attribute is
418 None, the default behavior will take place for all columns fetched from
419 cursors.
420
421 .. note::
422
423 This attribute is an extension to the DB API definition.
424
425
426 .. method:: Connection.ping()
427
428 Ping the server which can be used to test if the connection is still
429 active.
430
431 .. note::
432
433 This method is an extension to the DB API definition.
434
435
436 .. method:: Connection.prepare()
437
438 Prepare the distributed (global) transaction for commit. Return a boolean
439 indicating if a transaction was actually prepared in order to avoid the
440 error ORA-24756 (transaction does not exist).
441
442 .. note::
443
444 This method is an extension to the DB API definition.
445
446
447 .. method:: Connection.rollback()
448
449 Rollback any pending transactions.
450
451
452 .. method:: Connection.shutdown([mode])
453
454 Shutdown the database. In order to do this the connection must be connected
455 as :data:`~cx_Oracle.SYSDBA` or :data:`~cx_Oracle.SYSOPER`. Two calls must
456 be made unless the mode specified is :data:`~cx_Oracle.DBSHUTDOWN_ABORT`.
457 An example is shown below:
458
459 ::
460
461 import cx_Oracle
462
463 connection = cx_Oracle.connect(mode = cx_Oracle.SYSDBA)
464 connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_IMMEDIATE)
465 cursor = connection.cursor()
466 cursor.execute("alter database close normal")
467 cursor.execute("alter database dismount")
468 connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_FINAL)
469
470 .. note::
471
472 This method is an extension to the DB API definition.
473
474
475 .. method:: Connection.startup(force=False, restrict=False)
476
477 Startup the database. This is equivalent to the SQL\*Plus command "startup
478 nomount". The connection must be connected as :data:`~cx_Oracle.SYSDBA` or
479 :data:`~cx_Oracle.SYSOPER` with the :data:`~cx_Oracle.PRELIM_AUTH` option
480 specified for this to work. An example is shown below:
481
482 ::
483
484 import cx_Oracle
485
486 connection = cx_Oracle.connect(
487 mode=cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH)
488 connection.startup()
489 connection = cx_Oracle.connect(mode=cx_Oracle.SYSDBA)
490 cursor = connection.cursor()
491 cursor.execute("alter database mount")
492 cursor.execute("alter database open")
493
494 .. note::
495
496 This method is an extension to the DB API definition.
497
498
499 .. attribute:: Connection.stmtcachesize
500
501 This read-write attribute specifies the size of the statement cache. This
502 value can make a significant difference in performance (up to 100x) if you
503 have a small number of statements that you execute repeatedly.
504
505 .. note::
506
507 This attribute is an extension to the DB API definition.
508
509
510 .. method:: Connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE, protocol=cx_Oracle.SUBSCR_PROTO_OCI, callback=None, timeout=0, operations=OPCODE_ALLOPS, port=0, qos=0, ipAddress=None, groupingClass=0, groupingValue=0, groupingType=cx_Oracle.SUBSCR_GROUPING_TYPE_SUMMARY, name=None)
511
512 Return a new :ref:`subscription object <subscrobj>` that receives
513 notifications for events that take place in the database that match the
514 given parameters.
515
516 The namespace parameter specifies the namespace the subscription uses. It
517 can be one of :data:`cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE` or
518 :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ`.
519
520 The protocol parameter specifies the protocol to use when notifications are
521 sent. Currently the only valid value is :data:`cx_Oracle.SUBSCR_PROTO_OCI`.
522
523 The callback is expected to be a callable that accepts a single parameter.
524 A :ref:`message object <msgobjects>` is passed to this callback whenever a
525 notification is received.
526
527 The timeout value specifies that the subscription expires after the given
528 time in seconds. The default value of 0 indicates that the subscription
529 never expires.
530
531 The operations parameter enables filtering of the messages that are sent
532 (insert, update, delete). The default value will send notifications for all
533 operations. This parameter is only used when the namespace is set to
534 :data:`cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE`.
535
536 The port parameter specifies the listening port for callback notifications
537 from the database server. If not specified, an unused port will be selected
538 by the Oracle Client libraries.
539
540 The qos parameter specifies quality of service options. It should be one or
541 more of the following flags, OR'ed together:
542 :data:`cx_Oracle.SUBSCR_QOS_RELIABLE`,
543 :data:`cx_Oracle.SUBSCR_QOS_DEREG_NFY`,
544 :data:`cx_Oracle.SUBSCR_QOS_ROWIDS`,
545 :data:`cx_Oracle.SUBSCR_QOS_QUERY`,
546 :data:`cx_Oracle.SUBSCR_QOS_BEST_EFFORT`.
547
548 The ipAddress parameter specifies the IP address (IPv4 or IPv6) in standard
549 string notation to bind for callback notifications from the database
550 server. If not specified, the client IP address will be determined by the
551 Oracle Client libraries.
552
553 The groupingClass parameter specifies what type of grouping of
554 notifications should take place. Currently, if set, this value can only be
555 set to the value :data:`cx_Oracle.SUBSCR_GROUPING_CLASS_TIME`, which
556 will group notifications by the number of seconds specified in the
557 groupingValue parameter. The groupingType parameter should be one of the
558 values :data:`cx_Oracle.SUBSCR_GROUPING_TYPE_SUMMARY` (the default) or
559 :data:`cx_Oracle.SUBSCR_GROUPING_TYPE_LAST`.
560
561 The name parameter is used to identify the subscription and is specific to
562 the selected namespace. If the namespace parameter is
563 :data:`cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE` then the name is optional and
564 can be any value. If the namespace parameter is
565 :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ`, however, the name must be in the
566 format '<QUEUE_NAME>' for single consumer queues and
567 '<QUEUE_NAME>:<CONSUMER_NAME>' for multiple consumer queues, and identifies
568 the queue that will be monitored for messages. The queue name may include
569 the schema, if needed.
570
571 *New in version 6.4:* The parameters ipAddress, groupingClass,
572 groupingValue, groupingType and name were added.
573
574 .. note::
575
576 This method is an extension to the DB API definition.
577
578 .. note::
579
580 The subscription can be deregistered in the database by calling the
581 function :meth:`~Connection.unsubscribe()`. If this method is not
582 called and the connection that was used to create the subscription is
583 explictly closed using the function :meth:`~Connection.close()`, the
584 subscription will not be deregistered in the database.
585
586
587 .. attribute:: Connection.tag
588
589 This read-write attribute initially contains the actual tag of the session
590 that was acquired from a pool by :meth:`SessionPool.acquire()`. If the
591 connection was not acquired from a pool or no tagging parameters were
592 specified (tag and matchanytag) when the connection was acquired from the
593 pool, this value will be None. If the value is changed, it must be a string
594 containing name=value pairs like "k1=v1;k2=v2".
595
596 If this value is not None when the connection is released back to the pool
597 it will be used to retag the session. This value can be overridden in the
598 call to :meth:`SessionPool.release()`.
599
600 .. note::
601
602 This attribute is an extension to the DB API definition.
603
604 .. versionadded:: 7.1
605
606
607 .. attribute:: Connection.tnsentry
608
609 This read-only attribute returns the TNS entry of the database to which a
610 connection has been established.
611
612 .. note::
613
614 This attribute is an extension to the DB API definition.
615
616
617 .. method:: Connection.unsubscribe(subscr)
618
619 Unsubscribe from events in the database that were originally subscribed to
620 using :meth:`~Connection.subscribe()`. The connection used to unsubscribe
621 should be the same one used to create the subscription, or should access
622 the same database and be connected as the same user name.
623
624 .. versionadded:: 6.4
625
626
627 .. attribute:: Connection.username
628
629 This read-only attribute returns the name of the user which established the
630 connection to the database.
631
632 .. note::
633
634 This attribute is an extension to the DB API definition.
635
636
637 .. attribute:: Connection.version
638
639 This read-only attribute returns the version of the database to which a
640 connection has been established.
641
642 .. note::
643
644 This attribute is an extension to the DB API definition.
645
646 .. note::
647
648 If you connect to Oracle Database 18 or higher with client libraries
649 12.2 or lower that you will only receive the base version (such as
650 18.0.0.0.0) instead of the full version (18.3.0.0.0).
651
+0
-557
doc/src/cursor.rst less more
0 .. _cursorobj:
1
2 *************
3 Cursor Object
4 *************
5
6
7 .. method:: Cursor.__enter__()
8
9 The entry point for the cursor as a context manager. It returns itself.
10
11 .. note::
12
13 This method is an extension to the DB API definition.
14
15
16 .. method:: Cursor.__exit__()
17
18 The exit point for the cursor as a context manager. It closes the cursor.
19
20 .. note::
21
22 This method is an extension to the DB API definition.
23
24
25 .. attribute:: Cursor.arraysize
26
27 This read-write attribute specifies the number of rows to fetch at a time
28 internally and is the default number of rows to fetch with the
29 :meth:`~Cursor.fetchmany()` call. It defaults to 100 meaning to fetch 100
30 rows at a time. Note that this attribute can drastically affect the
31 performance of a query since it directly affects the number of network
32 round trips that need to be performed. This is the reason for setting it to
33 100 instead of the 1 that the DB API recommends.
34
35
36 .. attribute:: Cursor.bindarraysize
37
38 This read-write attribute specifies the number of rows to bind at a time
39 and is used when creating variables via :meth:`~Cursor.setinputsizes()` or
40 :meth:`~Cursor.var()`. It defaults to 1 meaning to bind a single row at a
41 time.
42
43 .. note::
44
45 The DB API definition does not define this attribute.
46
47
48 .. method:: Cursor.arrayvar(dataType, value, [size])
49
50 Create an array variable associated with the cursor of the given type and
51 size and return a :ref:`variable object <varobj>`. The value is either an
52 integer specifying the number of elements to allocate or it is a list and
53 the number of elements allocated is drawn from the size of the list. If the
54 value is a list, the variable is also set with the contents of the list. If
55 the size is not specified and the type is a string or binary, 4000 bytes
56 is allocated. This is needed for passing arrays to PL/SQL (in cases where
57 the list might be empty and the type cannot be determined automatically) or
58 returning arrays from PL/SQL.
59
60 .. note::
61
62 The DB API definition does not define this method.
63
64
65 .. method:: Cursor.bindnames()
66
67 Return the list of bind variable names bound to the statement. Note that a
68 statement must have been prepared first.
69
70 .. note::
71
72 The DB API definition does not define this method.
73
74
75 .. attribute:: Cursor.bindvars
76
77 This read-only attribute provides the bind variables used for the last
78 execute. The value will be either a list or a dictionary depending on
79 whether binding was done by position or name. Care should be taken when
80 referencing this attribute. In particular, elements should not be removed
81 or replaced.
82
83 .. note::
84
85 The DB API definition does not define this attribute.
86
87
88 .. method:: Cursor.callfunc(name, returnType, parameters=[], \
89 keywordParameters={})
90
91 Call a function with the given name. The return type is specified in the
92 same notation as is required by :meth:`~Cursor.setinputsizes()`. The
93 sequence of parameters must contain one entry for each parameter that the
94 function expects. Any keyword parameters will be included after the
95 positional parameters. The result of the call is the return value of the
96 function.
97
98 .. note::
99
100 The DB API definition does not define this method.
101
102 .. note::
103
104 If you intend to call :meth:`Cursor.setinputsizes()` on the cursor
105 prior to making this call, then note that the first item in the
106 parameter list refers to the return value of the function.
107
108
109 .. method:: Cursor.callproc(name, parameters=[], keywordParameters={})
110
111 Call a procedure with the given name. The sequence of parameters must
112 contain one entry for each parameter that the procedure expects. The result
113 of the call is a modified copy of the input sequence. Input parameters are
114 left untouched; output and input/output parameters are replaced with
115 possibly new values. Keyword parameters will be included after the
116 positional parameters and are not returned as part of the output sequence.
117
118 .. note::
119
120 The DB API definition does not allow for keyword parameters.
121
122
123 .. method:: Cursor.close()
124
125 Close the cursor now, rather than whenever __del__ is called. The cursor
126 will be unusable from this point forward; an Error exception will be raised
127 if any operation is attempted with the cursor.
128
129
130 .. attribute:: Cursor.connection
131
132 This read-only attribute returns a reference to the connection object on
133 which the cursor was created.
134
135 .. note::
136
137 This attribute is an extension to the DB API definition but it is
138 mentioned in PEP 249 as an optional extension.
139
140
141 .. data:: Cursor.description
142
143 This read-only attribute is a sequence of 7-item sequences. Each of these
144 sequences contains information describing one result column: (name, type,
145 display_size, internal_size, precision, scale, null_ok). This attribute
146 will be None for operations that do not return rows or if the cursor has
147 not had an operation invoked via the :meth:`~Cursor.execute()` method yet.
148
149 The type will be one of the type objects defined at the module level.
150
151
152 .. method:: Cursor.execute(statement, [parameters], \*\*keywordParameters)
153
154 Execute a statement against the database. Parameters may be passed as a
155 dictionary or sequence or as keyword parameters. If the parameters are a
156 dictionary, the values will be bound by name and if the parameters are a
157 sequence the values will be bound by position. Note that if the values are
158 bound by position, the order of the variables is from left to right as they
159 are encountered in the statement and SQL statements are processed
160 differently than PL/SQL statements. For this reason, it is generally
161 recommended to bind parameters by name instead of by position.
162
163 Parameters passed as a dictionary are name and value pairs. The name maps
164 to the bind variable name used by the statement and the value maps to the
165 Python value you wish bound to that bind variable.
166
167 A reference to the statement will be retained by the cursor. If None or the
168 same string object is passed in again, the cursor will execute that
169 statement again without performing a prepare or rebinding and redefining.
170 This is most effective for algorithms where the same statement is used, but
171 different parameters are bound to it (many times). Note that parameters
172 that are not passed in during subsequent executions will retain the value
173 passed in during the last execution that contained them.
174
175 For maximum efficiency when reusing an statement, it is best to use the
176 :meth:`~Cursor.setinputsizes()` method to specify the parameter types and
177 sizes ahead of time; in particular, None is assumed to be a string of
178 length 1 so any values that are later bound as numbers or dates will raise
179 a TypeError exception.
180
181 If the statement is a query, the cursor is returned as a convenience to the
182 caller (so it can be used directly as an iterator over the rows in the
183 cursor); otherwise, ``None`` is returned.
184
185 .. note::
186
187 The DB API definition does not define the return value of this method.
188
189
190 .. method:: Cursor.executemany(statement, parameters, batcherrors=False, \
191 arraydmlrowcounts=False)
192
193 Prepare a statement for execution against a database and then execute it
194 against all parameter mappings or sequences found in the sequence
195 parameters. The statement is managed in the same way as the
196 :meth:`~Cursor.execute()` method manages it. If the size of the buffers
197 allocated for any of the parameters exceeds 2 GB, you will receive the
198 error "DPI-1015: array size of <n> is too large", where <n> varies with the
199 size of each element being allocated in the buffer. If you receive this
200 error, decrease the number of elements in the sequence parameters.
201
202 If there are no parameters, or parameters have previously been bound, the
203 number of iterations can be specified as an integer instead of needing to
204 provide a list of empty mappings or sequences.
205
206 When true, the batcherrors parameter enables batch error support within
207 Oracle and ensures that the call succeeds even if an exception takes place
208 in one or more of the sequence of parameters. The errors can then be
209 retrieved using :meth:`~Cursor.getbatcherrors()`.
210
211 When true, the arraydmlrowcounts parameter enables DML row counts to be
212 retrieved from Oracle after the method has completed. The row counts can
213 then be retrieved using :meth:`~Cursor.getarraydmlrowcounts()`.
214
215 Both the batcherrors parameter and the arraydmlrowcounts parameter can only
216 be true when executing an insert, update, delete or merge statement; in all
217 other cases an error will be raised.
218
219 For maximum efficiency, it is best to use the
220 :meth:`~Cursor.setinputsizes()` method to specify the parameter types and
221 sizes ahead of time; in particular, None is assumed to be a string of
222 length 1 so any values that are later bound as numbers or dates will raise
223 a TypeError exception.
224
225
226 .. method:: Cursor.executemanyprepared(numIters)
227
228 Execute the previously prepared and bound statement the given number of
229 times. The variables that are bound must have already been set to their
230 desired value before this call is made. This method was designed for the
231 case where optimal performance is required as it comes at the expense of
232 compatibility with the DB API.
233
234 .. note::
235
236 The DB API definition does not define this method.
237
238 .. deprecated:: 6.4
239 Use :meth:`~Cursor.executemany()` instead with None for the statement
240 argument and an integer for the parameters argument.
241
242
243 .. method:: Cursor.fetchall()
244
245 Fetch all (remaining) rows of a query result, returning them as a list of
246 tuples. An empty list is returned if no more rows are available. Note that
247 the cursor's arraysize attribute can affect the performance of this
248 operation, as internally reads from the database are done in batches
249 corresponding to the arraysize.
250
251 An exception is raised if the previous call to :meth:`~Cursor.execute()`
252 did not produce any result set or no call was issued yet.
253
254
255 .. method:: Cursor.fetchmany([numRows=cursor.arraysize])
256
257 Fetch the next set of rows of a query result, returning a list of tuples.
258 An empty list is returned if no more rows are available. Note that the
259 cursor's arraysize attribute can affect the performance of this operation.
260
261 The number of rows to fetch is specified by the parameter. If it is not
262 given, the cursor's arrysize attribute determines the number of rows to be
263 fetched. If the number of rows available to be fetched is fewer than the
264 amount requested, fewer rows will be returned.
265
266 An exception is raised if the previous call to :meth:`~Cursor.execute()`
267 did not produce any result set or no call was issued yet.
268
269
270 .. method:: Cursor.fetchone()
271
272 Fetch the next row of a query result set, returning a single tuple or None
273 when no more data is available.
274
275 An exception is raised if the previous call to :meth:`~Cursor.execute()`
276 did not produce any result set or no call was issued yet.
277
278
279 .. method:: Cursor.fetchraw([numRows=cursor.arraysize])
280
281 Fetch the next set of rows of a query result into the internal buffers of
282 the defined variables for the cursor. The number of rows actually fetched
283 is returned. This method was designed for the case where optimal
284 performance is required as it comes at the expense of compatibility with
285 the DB API.
286
287 An exception is raised if the previous call to :meth:`~Cursor.execute()`
288 did not produce any result set or no call was issued yet.
289
290 .. note::
291
292 The DB API definition does not define this method.
293
294
295 .. attribute:: Cursor.fetchvars
296
297 This read-only attribute specifies the list of variables created for the
298 last query that was executed on the cursor. Care should be taken when
299 referencing this attribute. In particular, elements should not be removed
300 or replaced.
301
302 .. note::
303
304 The DB API definition does not define this attribute.
305
306
307 .. method:: Cursor.getarraydmlrowcounts()
308
309 Retrieve the DML row counts after a call to :meth:`~Cursor.executemany()`
310 with arraydmlrowcounts enabled. This will return a list of integers
311 corresponding to the number of rows affected by the DML statement for each
312 element of the array passed to :meth:`~Cursor.executemany()`.
313
314 .. note::
315
316 The DB API definition does not define this method and it is only
317 available for Oracle 12.1 and higher.
318
319
320 .. method:: Cursor.getbatcherrors()
321
322 Retrieve the exceptions that took place after a call to
323 :meth:`~Cursor.executemany()` with batcherors enabled. This will return a
324 list of Error objects, one error for each iteration that failed. The offset
325 can be determined by looking at the offset attribute of the error object.
326
327 .. note::
328
329 The DB API definition does not define this method.
330
331
332 .. method:: Cursor.getimplicitresults()
333
334 Return a list of cursors which correspond to implicit results made
335 available from a PL/SQL block or procedure without the use of OUT ref
336 cursor parameters. The PL/SQL block or procedure opens the cursors and
337 marks them for return to the client using the procedure
338 dbms_sql.return_result. Cursors returned in this fashion should not be
339 closed. They will be closed automatically by the parent cursor when it is
340 closed. Closing the parent cursor will invalidate the cursors returned by
341 this method.
342
343 .. versionadded:: 5.3
344
345 .. note::
346
347 The DB API definition does not define this method and it is only
348 available for Oracle Database 12.1 (both client and server must be at
349 this level or higher). It is most like the DB API method nextset(), but
350 unlike that method (which requires that the next result set overwrite
351 the current result set), this method returns cursors which can be
352 fetched independently of each other.
353
354
355 .. attribute:: Cursor.inputtypehandler
356
357 This read-write attribute specifies a method called for each value that is
358 bound to a statement executed on the cursor and overrides the attribute
359 with the same name on the connection if specified. The method signature is
360 handler(cursor, value, arraysize) and the return value is expected to be a
361 variable object or None in which case a default variable object will be
362 created. If this attribute is None, the value of the attribute with the
363 same name on the connection is used.
364
365 .. note::
366
367 This attribute is an extension to the DB API definition.
368
369
370 .. method:: Cursor.__iter__()
371
372 Returns the cursor itself to be used as an iterator.
373
374 .. note::
375
376 This method is an extension to the DB API definition but it is
377 mentioned in PEP 249 as an optional extension.
378
379
380 .. attribute:: Cursor.outputtypehandler
381
382 This read-write attribute specifies a method called for each column that is
383 to be fetched from this cursor. The method signature is
384 handler(cursor, name, defaultType, length, precision, scale) and the return
385 value is expected to be a variable object or None in which case a default
386 variable object will be created. If this attribute is None, the value of
387 the attribute with the same name on the connection is used instead.
388
389 .. note::
390
391 This attribute is an extension to the DB API definition.
392
393
394 .. method:: Cursor.parse(statement)
395
396 This can be used to parse a statement without actually executing it (this
397 step is done automatically by Oracle when a statement is executed).
398
399 .. note::
400
401 The DB API definition does not define this method.
402
403 .. note::
404
405 You can parse any DML or DDL statement. DDL statements are executed
406 immediately and an implied commit takes place.
407
408
409 .. method:: Cursor.prepare(statement, [tag])
410
411 This can be used before a call to :meth:`~Cursor.execute()` to define the
412 statement that will be executed. When this is done, the prepare phase will
413 not be performed when the call to :meth:`~Cursor.execute()` is made with
414 None or the same string object as the statement. If specified the
415 statement will be returned to the statement cache with the given tag. See
416 the Oracle documentation for more information about the statement cache.
417
418 .. note::
419
420 The DB API definition does not define this method.
421
422
423 .. attribute:: Cursor.rowcount
424
425 This read-only attribute specifies the number of rows that have currently
426 been fetched from the cursor (for select statements) or that have been
427 affected by the operation (for insert, update and delete statements).
428
429
430 .. attribute:: Cursor.rowfactory
431
432 This read-write attribute specifies a method to call for each row that is
433 retrieved from the database. Ordinarily a tuple is returned for each row
434 but if this attribute is set, the method is called with the tuple that
435 would normally be returned, and the result of the method is returned
436 instead.
437
438 .. note::
439
440 The DB API definition does not define this attribute.
441
442
443 .. method:: Cursor.scroll(value=0, mode="relative")
444
445 Scroll the cursor in the result set to a new position according to the
446 mode.
447
448 If mode is "relative" (the default value), the value is taken as an offset
449 to the current position in the result set. If set to "absolute", value
450 states an absolute target position. If set to "first", the cursor is
451 positioned at the first row and if set to "last", the cursor is set to the
452 last row in the result set.
453
454 An error is raised if the mode is "relative" or "absolute" and the scroll
455 operation would position the cursor outside of the result set.
456
457 .. versionadded:: 5.3
458
459 .. note::
460
461 This method is an extension to the DB API definition but it is
462 mentioned in PEP 249 as an optional extension.
463
464
465 .. attribute:: Cursor.scrollable
466
467 This read-write boolean attribute specifies whether the cursor can be
468 scrolled or not. By default, cursors are not scrollable, as the server
469 resources and response times are greater than nonscrollable cursors. This
470 attribute is checked and the corresponding mode set in Oracle when calling
471 the method :meth:`~Cursor.execute()`.
472
473 .. versionadded:: 5.3
474
475 .. note::
476
477 The DB API definition does not define this attribute.
478
479
480 .. method:: Cursor.setinputsizes(\*args, \*\*keywordArgs)
481
482 This can be used before a call to :meth:`~Cursor.execute()`,
483 :meth:`~Cursor.callfunc()` or :meth:`~Cursor.callproc()` to predefine
484 memory areas for the operation's parameters. Each parameter should be a
485 type object corresponding to the input that will be used or it should be an
486 integer specifying the maximum length of a string parameter. Use keyword
487 parameters when binding by name and positional parameters when binding by
488 position. The singleton None can be used as a parameter when using
489 positional parameters to indicate that no space should be reserved for that
490 position.
491
492 .. note::
493
494 If you plan to use :meth:`~Cursor.callfunc()` then be aware that the
495 first parameter in the list refers to the return value of the function.
496
497
498 .. method:: Cursor.setoutputsize(size, [column])
499
500 This method does nothing and is retained solely for compatibility with the
501 DB API. The module automatically allocates as much space as needed to fetch
502 LONG and LONG RAW columns (or CLOB as string and BLOB as bytes).
503
504
505 .. attribute:: Cursor.statement
506
507 This read-only attribute provides the string object that was previously
508 prepared with :meth:`~Cursor.prepare()` or executed with
509 :meth:`~Cursor.execute()`.
510
511 .. note::
512
513 The DB API definition does not define this attribute.
514
515
516 .. method:: Cursor.var(dataType, [size, arraysize, inconverter, outconverter, \
517 typename, encodingErrors])
518
519 Create a variable with the specified charactistics. This method was
520 designed for use with PL/SQL in/out variables where the length or type
521 cannot be determined automatically from the Python object passed in or for
522 use in input and output type handlers defined on cursors or connections.
523
524 The dataType parameter specifies the type of data that should be stored in
525 the variable. This should be one of the types defined at the module level
526 (such as :data:`cx_Oracle.STRING`) or a Python type that cx_Oracle knows
527 how to process (such as str) or an object type returned from the method
528 :meth:`Connection.gettype()`.
529
530 The size parameter specifies the length of string and raw variables and is
531 ignored in all other cases. If not specified for string and raw variables,
532 the value 4000 is used.
533
534 The arraysize parameter specifies the number of elements the variable will
535 have. If not specified the bind array size (usually 1) is used. When a
536 variable is created in an output type handler this parameter should be set
537 to the cursor's array size.
538
539 The inconverter and outconverter parameters specify methods used for
540 converting values to/from the database. More information can be found in
541 the section on :ref:`variable objects<varobj>`.
542
543 The typename parameter specifies the name of a SQL object type and must be
544 specified when using type :data:`cx_Oracle.OBJECT` unless the type object
545 was passed directly as the first parameter.
546
547 The encodingErrors parameter specifies what should happen when decoding
548 byte strings fetched from the database into strings (Python 3) or unicode
549 objects (Python 2). It should be one of the values noted in the builtin
550 `decode <https://docs.python.org/3/library/stdtypes.html#bytes.decode>`__
551 function.
552
553 .. note::
554
555 The DB API definition does not define this method.
556
33
44 **cx_Oracle** is a module that enables access to Oracle Database and conforms
55 to the Python database API specification. This module is currently tested
6 against Oracle Client 11.2, 12.1, 12.2 and 18.3 and Python 2.7, 3.5, 3.6 and
7 3.7.
6 against Oracle Client 19c, 18c, 12c, and 11.2, and Python 3.5, 3.6, 3.7 and
7 3.8. Older versions of cx_Oracle may be used with previous Python releases.
88
99 **cx_Oracle** is distributed under an open-source :ref:`license <license>`
10 (the BSD license).
10 (the BSD license). A detailed description of cx_Oracle changes can be found in
11 the :ref:`release notes <releasenotes>`.
1112
1213 Contents:
1314
15 User Guide
16 ==========
17
1418 .. toctree::
15 :maxdepth: 2
19 :maxdepth: 3
1620
17 installation.rst
18 module.rst
19 connection.rst
20 cursor.rst
21 variable.rst
22 session_pool.rst
23 subscription.rst
24 lob.rst
25 objecttype.rst
26 aq.rst
27 soda.rst
28 whatsnew.rst
29 releasenotes.rst
30 license.rst
21 user_guide/introduction.rst
22 user_guide/installation.rst
23 user_guide/initialization.rst
24 user_guide/connection_handling.rst
25 user_guide/sql_execution.rst
26 user_guide/plsql_execution.rst
27 user_guide/bind.rst
28 user_guide/lob_data.rst
29 user_guide/json_data_type.rst
30 user_guide/soda.rst
31 user_guide/xml_data_type.rst
32 user_guide/batch_statement.rst
33 user_guide/exception_handling.rst
34 user_guide/aq.rst
35 user_guide/cqn.rst
36 user_guide/txn_management.rst
37 user_guide/tuning.rst
38 user_guide/globalization.rst
39 user_guide/startup.rst
40 user_guide/ha.rst
41 user_guide/tracing_sql.rst
42
43 API Manual
44 ==========
45
46 .. toctree::
47 :maxdepth: 3
48
49 api_manual/module.rst
50 api_manual/connection.rst
51 api_manual/cursor.rst
52 api_manual/variable.rst
53 api_manual/session_pool.rst
54 api_manual/subscription.rst
55 api_manual/lob.rst
56 api_manual/object_type.rst
57 api_manual/aq.rst
58 Soda Document Class <api_manual/soda.rst>
3159
3260
3361 Indices and tables
+0
-667
doc/src/installation.rst less more
0 .. _installation:
1
2 ************************
3 cx_Oracle 7 Installation
4 ************************
5
6 .. contents:: :local:
7
8 Overview
9 ========
10
11 To use cx_Oracle 7 with Python and Oracle Database you need:
12
13 - Python 2.7 or 3.5 and higher. Older versions of cx_Oracle may work
14 with older versions of Python.
15
16 - Oracle client libraries. These can be from the free `Oracle Instant
17 Client
18 <http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html>`__,
19 or those included in Oracle Database if Python is on the same
20 machine as the database. Oracle client libraries versions 18, 12,
21 and 11.2 are supported on Linux, Windows and macOS. Users have
22 also reported success with other platforms.
23
24 - An Oracle Database. Oracle's standard client-server version
25 interoperability allows cx_Oracle to connect to both older and newer
26 databases.
27
28
29 Quick Start cx_Oracle Installation
30 ==================================
31
32 - An installation of `Python <https://www.python.org/downloads>`__ is
33 needed. Python 2.7 and Python 3.5 and higher are supported by cx_Oracle 7.
34
35 - Install cx_Oracle from `PyPI
36 <https://pypi.python.org/pypi/cx_Oracle>`__ with::
37
38 python -m pip install cx_Oracle --upgrade
39
40 Note: if a binary wheel package is not available for your platform,
41 the source package will be downloaded instead. This will be compiled
42 and the resulting binary installed.
43
44 - Add Oracle 18, 12 or 11.2 client libraries to your operating
45 system library search path such as ``PATH`` on Windows or
46 ``LD_LIBRARY_PATH`` on Linux. On macOS move the files to ``~/lib``
47 or ``/usr/local/lib``.
48
49 - If your database is on a remote computer, then download and unzip the client
50 libraries from the free `Oracle Instant Client
51 <http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html>`__
52 "Basic" or "Basic Light" package for your operating system
53 architecture.
54
55 Instant Client on Windows requires an appropriate `Microsoft
56 Windows Redistributables
57 <https://oracle.github.io/odpi/doc/installation.html#windows>`__.
58 On Linux, the ``libaio`` (sometimes called ``libaio1``) package
59 is needed.
60
61 - Alternatively use the client libraries already available in a
62 locally installed database such as the free `Oracle XE
63 <https://www.oracle.com/database/technologies/appdev/xe.html>`__
64 release.
65
66 Version 18 and 12.2 client libraries can connect to Oracle Database 11.2 or
67 greater. Version 12.1 client libraries can connect to Oracle Database
68 10.2 or greater. Version 11.2 client libraries can connect to Oracle
69 Database 9.2 or greater.
70
71 The database abstraction layer in cx_Oracle is `ODPI-C
72 <https://github.com/oracle/odpi>`__, which means that the `ODPI-C
73 installation instructions
74 <https://oracle.github.io/odpi/doc/installation.html>`__ can be useful
75 to review.
76
77 - Create a script like the one below::
78
79 # myscript.py
80
81 from __future__ import print_function
82
83 import cx_Oracle
84
85 # Connect as user "hr" with password "welcome" to the "oraclepdb" service running on this computer.
86 connection = cx_Oracle.connect("hr", "welcome", "localhost/orclpdb")
87
88 cursor = connection.cursor()
89 cursor.execute("""
90 SELECT first_name, last_name
91 FROM employees
92 WHERE department_id = :did AND employee_id > :eid""",
93 did = 50,
94 eid = 190)
95 for fname, lname in cursor:
96 print("Values:", fname, lname)
97
98 Locate your Oracle Database username and password, and the database
99 connection string. The connection string is commonly of the format
100 ``hostname/servicename``, using the hostname where the database is
101 running, and the service name of the Oracle Database instance.
102
103 Substitute your username, password and connection string in the
104 code. Run the Python script, for example::
105
106 python myscript.py
107
108 You can learn how to use cx_Oracle from the :ref:`API documentation <module>`
109 and `samples
110 <https://github.com/oracle/python-cx_Oracle/blob/master/samples>`__.
111
112 If you run into installation trouble, check out the section on `Troubleshooting`_.
113
114
115 Oracle Client and Oracle Database Interoperability
116 ==================================================
117
118 cx_Oracle requires Oracle Client libraries. The libraries provide the
119 necessary network connectivity to access an Oracle Database instance.
120 They also provide basic and advanced connection management and data
121 features to cx_Oracle.
122
123 The simplest way to get Oracle Client libraries is to install the free
124 `Oracle Instant Client
125 <http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html>`__
126 "Basic" or "Basic Light" package. The libraries are also available in
127 any Oracle Database installation or full Oracle Client installation.
128
129 Oracle's standard client-server network interoperability allows
130 connections between different versions of Oracle Client libraries and
131 Oracle Database. For certified configurations see Oracle Support's
132 `Doc ID 207303.1
133 <https://support.oracle.com/epmos/faces/DocumentDisplay?id=207303.1>`__.
134 In summary, Oracle Client 18 and 12.2 can connect to Oracle Database 11.2 or
135 greater. Oracle Client 12.1 can connect to Oracle Database 10.2 or
136 greater. Oracle Client 11.2 can connect to Oracle Database 9.2 or
137 greater. The technical restrictions on creating connections may be
138 more flexible. For example Oracle Client 12.2 can successfully
139 connect to Oracle Database 10.2.
140
141 cx_Oracle uses the shared library loading mechanism available on each
142 supported platform to load the Oracle Client libraries at runtime. It
143 does not need to be rebuilt for different versions of the libraries.
144 Since a single cx_Oracle binary can use different client versions and
145 also access multiple database versions, it is important your
146 application is tested in your intended release environments. Newer
147 Oracle clients support new features, such as the `oraaccess.xml
148 <http://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-9D12F489-EC02-46BE-8CD4-5AECED0E2BA2>`__ external configuration
149 file available with 12.1 or later clients, session pool improvements,
150 call timeouts with 18 or later clients, and `other enhancements
151 <http://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-D60519C3-406F-4588-8DA1-D475D5A3E1F6>`__.
152
153 The cx_Oracle function :func:`~cx_Oracle.clientversion()` can be used
154 to determine which Oracle Client version is in use and the attribute
155 :attr:`Connection.version` can be used to determine which Oracle
156 Database version a connection is accessing. These can then be used to
157 adjust application behavior accordingly. Attempts to use some Oracle
158 features that are not supported by a particular client/server
159 combination may result in runtime errors. These include:
160
161 - when attempting to access attributes that are not supported by the
162 current Oracle Client library you will get the error "ORA-24315: illegal
163 attribute type"
164
165 - when attempting to use implicit results with Oracle Client 11.2
166 against Oracle Database 12c you will get the error "ORA-29481:
167 Implicit results cannot be returned to client"
168
169 - when attempting to get array DML row counts with Oracle Client
170 11.2 you will get the error "DPI-1050: Oracle Client library must be at
171 version 12.1 or higher"
172
173
174 Installing cx_Oracle on Linux
175 =============================
176
177 This section discusses the generic installation method on Linux.
178 Using Python and cx_Oracle RPM packages on Oracle Linux is discussed
179 in :ref:`oraclelinux`.
180
181 Install cx_Oracle
182 -----------------
183
184 The generic way to install cx_Oracle on Linux is to use Python's `Pip
185 <http://pip.readthedocs.io/en/latest/installing/>`__ package to
186 install cx_Oracle from `PyPI
187 <https://pypi.python.org/pypi/cx_Oracle>`__::
188
189 python -m pip install cx_Oracle --upgrade
190
191 This will download and install a pre-compiled binary `if one is
192 available <https://pypi.python.org/pypi/cx_Oracle>`__ for your
193 architecture. If a pre-compiled binary is not available, the source
194 will be downloaded, compiled, and the resulting binary installed.
195 Compiling cx_Oracle requires the `Python.h` header file. If you are
196 using the default python package, this file is in the ``python-devel``
197 package or equivalent.
198
199 Install Oracle Client
200 ---------------------
201
202 Using cx_Oracle requires Oracle Client libraries to be installed.
203 These provide the necessary network connectivity allowing cx_Oracle
204 to access an Oracle Database instance. Oracle Client versions 18,
205 12 and 11.2 are supported.
206
207 - If your database is on a remote computer, then download the free `Oracle
208 Instant Client
209 <http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html>`__
210 "Basic" or "Basic Light" package for your operating system
211 architecture. Use the RPM or ZIP packages, based on your
212 preferences.
213
214 - Alternatively use the client libraries already available in a
215 locally installed database such as the free `Oracle XE
216 <https://www.oracle.com/database/technologies/appdev/xe.html>`__
217 release.
218
219 Oracle Instant Client Zip Files
220 +++++++++++++++++++++++++++++++
221
222 To use cx_Oracle with Oracle Instant Client zip files:
223
224 1. Download an Oracle 18, 12, or 11.2 "Basic" or "Basic Light" zip file: `64-bit
225 <http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html>`__
226 or `32-bit
227 <http://www.oracle.com/technetwork/topics/linuxsoft-082809.html>`__, matching your
228 Python architecture.
229
230 2. Unzip the package into a single directory that is accessible to your
231 application. For example::
232
233 mkdir -p /opt/oracle
234 cd /opt/oracle
235 unzip instantclient-basic-linux.x64-18.3.0.0.0dbru.zip
236
237 3. Install the ``libaio`` package with sudo or as the root user. For example::
238
239 sudo yum install libaio
240
241 On some Linux distributions this package is called ``libaio1`` instead.
242
243 4. If there is no other Oracle software on the machine that will be
244 impacted, permanently add Instant Client to the runtime link
245 path. For example, with sudo or as the root user::
246
247 sudo sh -c "echo /opt/oracle/instantclient_18_3 > /etc/ld.so.conf.d/oracle-instantclient.conf"
248 sudo ldconfig
249
250 Alternatively, set the environment variable ``LD_LIBRARY_PATH`` to
251 the appropriate directory for the Instant Client version. For
252 example::
253
254 export LD_LIBRARY_PATH=/opt/oracle/instantclient_18_3:$LD_LIBRARY_PATH
255
256 5. If you intend to co-locate optional Oracle configuration files such
257 as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml`` with
258 Instant Client, then put them in the ``network/admin``
259 subdirectory. With Instant Client 12.2 or earlier, create this
260 manually. For example::
261
262 mkdir -p /opt/oracle/instantclient_12_2/network/admin
263
264 This is the default Oracle configuration directory for executables
265 linked with this Instant Client.
266
267 Alternatively, Oracle configuration files can be put in another,
268 accessible directory. Then set the environment variable
269 ``TNS_ADMIN`` to that directory name.
270
271 Oracle Instant Client RPMs
272 ++++++++++++++++++++++++++
273
274 To use cx_Oracle with Oracle Instant Client RPMs:
275
276 1. Download an Oracle 18, 12, or 11.2 "Basic" or "Basic Light" RPM: `64-bit
277 <http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html>`__
278 or `32-bit
279 <http://www.oracle.com/technetwork/topics/linuxsoft-082809.html>`__, matching your
280 Python architecture.
281
282 Oracle's yum server has `Instant Client RPMs for Oracle Linux 7
283 <http://yum.oracle.com/repo/OracleLinux/OL7/oracle/instantclient/x86_64/index.html>`__
284 and `Instant Client RPMs for Oracle Linux 6
285 <http://yum.oracle.com/repo/OracleLinux/OL6/oracle/instantclient/x86_64/index.html>`__
286 that can be downloaded without needing a click-through.
287
288 2. Install the downloaded RPM with sudo or as the root user. For example::
289
290 sudo yum install oracle-instantclient18.3-basic-18.3.0.0.0-1.x86_64.rpm
291
292 Yum will automatically install required dependencies, such as ``libaio``.
293
294 3. If there is no other Oracle software on the machine that will be
295 impacted, permanently add Instant Client to the runtime link
296 path. For example, with sudo or as the root user::
297
298 sudo sh -c "echo /usr/lib/oracle/18.3/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf"
299 sudo ldconfig
300
301 Alternatively, set the environment variable ``LD_LIBRARY_PATH`` to
302 the appropriate directory for the Instant Client version. For
303 example::
304
305 export LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib:$LD_LIBRARY_PATH
306
307 4. If you intend to co-locate optional Oracle configuration files such
308 as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml`` with
309 Instant Client, then put them in the ``network/admin`` subdirectory
310 under ``lib/``. With Instant Client 12.2 or earlier, create this
311 manually. For example::
312
313 sudo mkdir -p /usr/lib/oracle/12.2/client64/lib/network/admin
314
315 This is the default Oracle configuration directory for executables
316 linked with this Instant Client.
317
318 Alternatively, Oracle configuration files can be put in another,
319 accessible directory. Then set the environment variable
320 ``TNS_ADMIN`` to that directory name.
321
322 Local Database or Full Oracle Client
323 ++++++++++++++++++++++++++++++++++++
324
325 cx_Oracle applications can use Oracle Client 18, 12, or 11.2 libraries
326 from a local Oracle Database or full Oracle Client installation.
327
328 The libraries must be either 32-bit or 64-bit, matching your
329 Python architecture.
330
331 1. Set required Oracle environment variables by running the Oracle environment
332 script. For example::
333
334 source /usr/local/bin/oraenv
335
336 For Oracle Database XE, run::
337
338 source /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh
339
340 2. Optional Oracle configuration files such as ``tnsnames.ora``,
341 ``sqlnet.ora`` or ``oraaccess.xml`` can be placed in
342 ``$ORACLE_HOME/network/admin``.
343
344 Alternatively, Oracle configuration files can be put in another,
345 accessible directory. Then set the environment variable
346 ``TNS_ADMIN`` to that directory name.
347
348
349 .. _oraclelinux:
350
351 Installing cx_Oracle RPMs on Oracle Linux
352 =========================================
353
354 Python and cx_Oracle RPM packages are available from the `Oracle Linux yum server
355 <http://yum.oracle.com/>`__. Various versions of Python are easily installed.
356 Using the yum server makes it easy to keep up to date.
357
358 Installation instructions are at `Oracle Linux for Python
359 Developers <https://yum.oracle.com/oracle-linux-python.html>`__.
360
361 Installing cx_Oracle on Windows
362 ===============================
363
364 Install cx_Oracle
365 -----------------
366
367 Use Python's `Pip <http://pip.readthedocs.io/en/latest/installing/>`__
368 package to install cx_Oracle from `PyPI
369 <https://pypi.python.org/pypi/cx_Oracle>`__::
370
371 python -m pip install cx_Oracle --upgrade
372
373 This will download and install a pre-compiled binary `if one is
374 available <https://pypi.python.org/pypi/cx_Oracle>`__ for your
375 architecture. If a pre-compiled binary is not available, the source
376 will be downloaded, compiled, and the resulting binary installed.
377
378 Install Oracle Client
379 ---------------------
380
381 Using cx_Oracle requires Oracle Client libraries to be installed.
382 These provide the necessary network connectivity allowing cx_Oracle
383 to access an Oracle Database instance. Oracle Client versions 18,
384 12 and 11.2 are supported.
385
386 - If your database is on a remote computer, then download the free `Oracle
387 Instant Client
388 <http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html>`__
389 "Basic" or "Basic Light" package for your operating system
390 architecture.
391
392 - Alternatively use the client libraries already available in a
393 locally installed database such as the free `Oracle XE
394 <https://www.oracle.com/database/technologies/appdev/xe.html>`__
395 release.
396
397
398 Oracle Instant Client Zip Files
399 +++++++++++++++++++++++++++++++
400
401 To use cx_Oracle with Oracle Instant Client zip files:
402
403 1. Download an Oracle 18, 12, or 11.2 "Basic" or "Basic Light" zip
404 file: `64-bit
405 <http://www.oracle.com/technetwork/topics/winx64soft-089540.html>`__
406 or `32-bit
407 <http://www.oracle.com/technetwork/topics/winsoft-085727.html>`__, matching your
408 Python architecture.
409
410 2. Unzip the package into a single directory that is accessible to your
411 application, for example ``C:\oracle\instantclient_18_3``.
412
413 3. Set the environment variable ``PATH`` to include the path that you
414 created in step 2. For example, on Windows 7, update ``PATH`` in
415 Control Panel -> System -> Advanced System Settings -> Advanced ->
416 Environment Variables -> System Variables -> PATH. Alternatively
417 use ``SET`` to change your ``PATH`` in each command prompt window
418 before you run python.
419
420 If you have other Oracle software installed, then when you use
421 Python you will need to make sure that the Instant Client
422 directory, e.g. ``C:\oracle\instantclient_18_3``, occurs in
423 ``PATH`` before any other Oracle directories.
424
425 Restart any open command prompt windows.
426
427 4. Oracle Instant Client libraries require a Visual Studio redistributable with a 64-bit or 32-bit architecture to match Instant Client's architecture. Each Instant Client version requires a different redistributable version:
428
429 - For Instant Client 18 or 12.2 install `VS 2013 <https://support.microsoft.com/en-us/kb/2977003#bookmark-vs2013>`__
430 - For Instant Client 12.1 install `VS 2010 <https://support.microsoft.com/en-us/kb/2977003#bookmark-vs2010>`__
431 - For Instant Client 11.2 install `VS 2005 64-bit <https://www.microsoft.com/en-us/download/details.aspx?id=18471>`__ or `VS 2005 32-bit <https://www.microsoft.com/en-ca/download/details.aspx?id=3387>`__
432
433 5. If you intend to co-locate optional Oracle configuration files such
434 as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml`` with
435 Instant Client, then create a ``network\admin`` subdirectory, for example
436 ``C:\oracle\instantclient_18_3\network\admin``.
437
438 This is the default Oracle configuration directory for executables
439 linked with this Instant Client.
440
441 Alternatively, Oracle configuration files can be put in another,
442 accessible directory. Then set the environment variable
443 ``TNS_ADMIN`` to that directory name.
444
445
446 Local Database or Full Oracle Client
447 ++++++++++++++++++++++++++++++++++++
448
449 cx_Oracle applications can use Oracle Client 18, 12, or 11.2
450 libraries libraries from a local Oracle Database or full Oracle
451 Client.
452
453 The Oracle libraries must be either 32-bit or 64-bit, matching your
454 Python architecture.
455
456 1. Set the environment variable ``PATH`` to include the path that
457 contains OCI.dll, if it is not already set. For example, on Windows
458 7, update ``PATH`` in Control Panel -> System -> Advanced System
459 Settings -> Advanced -> Environment Variables -> System Variables
460 -> PATH.
461
462 Restart any open command prompt windows.
463
464 2. Optional Oracle configuration files such as ``tnsnames.ora``,
465 ``sqlnet.ora`` or ``oraaccess.xml`` can be placed in the
466 ``network/admin`` subdirectory of the Oracle Database software
467 installation.
468
469 Alternatively, Oracle configuration files can be put in another,
470 accessible directory. Then set the environment variable
471 ``TNS_ADMIN`` to that directory name.
472
473
474 Installing cx_Oracle on macOS
475 =============================
476
477 Install Python
478 --------------
479
480 Make sure you are not using the bundled Python. This has restricted
481 entitlements and will fail to load Oracle client libraries. Instead
482 use `Homebrew <https://brew.sh>`__ or `Python.org
483 <https://www.python.org/downloads>`__.
484
485 Install cx_Oracle
486 -----------------
487
488 Use Python's `Pip <http://pip.readthedocs.io/en/latest/installing/>`__
489 package to install cx_Oracle from `PyPI
490 <https://pypi.python.org/pypi/cx_Oracle>`__::
491
492 python -m pip install cx_Oracle --upgrade
493
494 The source will be downloaded, compiled, and the resulting binary
495 installed.
496
497
498 Install Oracle Instant Client
499 -----------------------------
500
501 cx_Oracle requires Oracle Client libraries, which are found in Oracle
502 Instant Client for macOS. These provide the necessary network
503 connectivity allowing cx_Oracle to access an Oracle Database
504 instance. Oracle Client versions 18, 12 and 11.2 are supported.
505
506 To use cx_Oracle with Oracle Instant Client zip files:
507
508 1. Download the Oracle 12 or 11.2 "Basic" or "Basic Light" zip file from `here
509 <http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html>`__.
510 Choose either a 64-bit or 32-bit package, matching your
511 Python architecture.
512
513 2. Unzip the package into a single directory that is accessible to your
514 application. For example::
515
516 mkdir -p /opt/oracle
517 unzip instantclient-basic-macos.x64-12.2.0.1.0.zip
518
519 3. Add links to ``$HOME/lib`` or ``/usr/local/lib`` to enable
520 applications to find the library. For example::
521
522 mkdir ~/lib
523 ln -s /opt/oracle/instantclient_12_2/libclntsh.dylib ~/lib/
524
525 Alternatively, copy the required OCI libraries. For example::
526
527 mkdir ~/lib
528 cp /opt/oracle/instantclient_12_2/{libclntsh.dylib.12.1,libclntshcore.dylib.12.1,libons.dylib,libnnz12.dylib,libociei.dylib} ~/lib/
529
530 For Instant Client 11.2, the OCI libraries must be copied. For example::
531
532 mkdir ~/lib
533 cp /opt/oracle/instantclient_11_2/{libclntsh.dylib.11.1,libnnz11.dylib,libociei.dylib} ~/lib/
534
535 4. If you intend to co-locate optional Oracle configuration files such
536 as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml`` with
537 Instant Client, then create a ``network/admin`` subdirectory. For
538 example::
539
540 mkdir -p /opt/oracle/instantclient_12_2/network/admin
541
542 This is the default Oracle configuration directory for executables
543 linked with this Instant Client.
544
545 Alternatively, Oracle configuration files can be put in another,
546 accessible directory. Then set the environment variable
547 ``TNS_ADMIN`` to that directory name.
548
549
550 Install Using GitHub
551 ====================
552
553 In order to install using the source on GitHub, use the following commands::
554
555 git clone https://github.com/oracle/python-cx_Oracle.git cx_Oracle
556 cd cx_Oracle
557 git submodule init
558 git submodule update
559 python setup.py install
560
561 Note that if you download a source zip file directly from GitHub then
562 you will also need to download an `ODPI-C
563 <https://github.com/oracle/odpi>`__ source zip file and extract it
564 inside the directory called "odpi".
565
566 cx_Oracle source code is also available from oss.oracle.com. This can
567 be cloned with::
568
569 git clone git://oss.oracle.com/git/oracle/python-cx_Oracle.git cx_Oracle
570 cd cx_Oracle
571 git submodule init
572 git submodule update
573
574
575 Install Using Source from PyPI
576 ==============================
577
578 The source package can be downloaded manually from
579 `PyPI <https://pypi.python.org/pypi/cx_Oracle>`__ and extracted, after
580 which the following commands should be run::
581
582 python setup.py build
583 python setup.py install
584
585 Upgrading from cx_Oracle 6
586 ==========================
587
588 Review the `release notes
589 <http://cx-oracle.readthedocs.io/en/latest/releasenotes.html>`__ for
590 deprecations and modify any affected code.
591
592 Upgrading from cx_Oracle 5
593 ==========================
594
595 If you are upgrading from cx_Oracle 5 note these installation changes:
596
597 - When using Oracle Instant Client, you should not set ``ORACLE_HOME``.
598
599 - On Linux, cx_Oracle 6 no longer uses Instant Client RPMs automatically.
600 You must set ``LD_LIBRARY_PATH`` or use ``ldconfig`` to locate the Oracle
601 client library.
602
603 - PyPI no longer allows Windows installers or Linux RPMs to be
604 hosted. Use the supplied cx_Oracle Wheels instead, or use RPMs
605 from Oracle, see :ref:`oraclelinux`.
606
607 Installing cx_Oracle 5.3
608 ========================
609
610 If you require cx_Oracle 5.3, download a Windows installer from `PyPI
611 <https://pypi.python.org/pypi/cx_Oracle>`__ or use ``python -m pip
612 install cx-oracle==5.3`` to install from source.
613
614 Very old versions of cx_Oracle can be found in the files section at
615 `SourceForce <https://sourceforge.net/projects/cx-oracle/files/>`__.
616
617
618 Troubleshooting
619 ===============
620
621 If installation fails:
622
623 - Use option ``-v`` with pip. Review your output and logs. Try to install
624 using a different method. **Google anything that looks like an error.**
625 Try some potential solutions.
626
627 - Was there a network connection error? Do you need to see the environment
628 variables ``http_proxy`` and/or ``https_proxy``?
629
630 - Do you get the error "``No module named pip``"? The pip module is builtin
631 to Python from version 2.7.9 but is sometimes removed by the OS. Use the
632 venv module (builtin to Python 3.x) or virtualenv module (Python 2.x)
633 instead.
634
635 - Do you get the error "``fatal error: dpi.h: No such file or directory``"
636 when building from source code? Ensure that your source installation has a
637 subdirectory called "odpi" containing files. If missing, review the
638 section on `Install Using GitHub`_.
639
640 If using cx_Oracle fails:
641
642 - Do you get the error "``DPI-1047: Oracle Client library cannot be
643 loaded``"?
644
645 - Check that Python, cx_Oracle and your Oracle Client libraries
646 are all 64-bit or all 32-bit. The ``DPI-1047`` message will
647 tell you whether the 64-bit or 32-bit Oracle Client is needed
648 for your Python.
649 - On Windows, restart your command prompt and use ``set PATH``
650 to check the environment variable has the correct Oracle
651 Client listed before any other Oracle directories.
652 - On Windows, use the ``DIR`` command on the directory set in
653 ``PATH``. Verify that ``OCI.DLL`` exists there.
654 - On Windows, check that the correct `Windows Redistributables
655 <https://oracle.github.io/odpi/doc/installation.html#windows>`__ have
656 been installed.
657 - On Linux, check the ``LD_LIBRARY_PATH`` environment variable
658 contains the Oracle Client library directory.
659 - On macOS, make sure Oracle Instant Client is in ``~/lib`` or
660 ``/usr/local/lib`` and that you are not using the bundled Python (use
661 `Homebrew <https://brew.sh>`__ or `Python.org
662 <https://www.python.org/downloads>`__ instead).
663
664 - If you have both Python 2 and 3 installed, make sure you are
665 using the correct python and pip (or python3 and pip3)
666 executables.
0 :orphan:
1
02 .. _license:
13
24 *******
79
810 .. centered:: **LICENSE AGREEMENT FOR CX_ORACLE**
911
10 Copyright |copy| 2016, 2018, Oracle and/or its affiliates. All rights reserved.
12 Copyright |copy| 2016, 2020, Oracle and/or its affiliates. All rights reserved.
1113
1214 Copyright |copy| 2007-2015, Anthony Tuininga. All rights reserved.
1315
+0
-89
doc/src/lob.rst less more
0 .. _lobobj:
1
2 ***********
3 LOB Objects
4 ***********
5
6 .. note::
7
8 This object is an extension the DB API. It is returned whenever Oracle
9 :data:`CLOB`, :data:`BLOB` and :data:`BFILE` columns are fetched.
10
11
12 .. method:: LOB.close()
13
14 Close the LOB. Call this when writing is completed so that the indexes
15 associated with the LOB can be updated -- but only if :meth:`~LOB.open()`
16 was called first.
17
18
19 .. method:: LOB.fileexists()
20
21 Return a boolean indicating if the file referenced by the BFILE type LOB
22 exists.
23
24
25 .. method:: LOB.getchunksize()
26
27 Return the chunk size for the internal LOB. Reading and writing to the LOB
28 in chunks of multiples of this size will improve performance.
29
30
31 .. method:: LOB.getfilename()
32
33 Return a two-tuple consisting of the directory alias and file name for a
34 BFILE type LOB.
35
36
37 .. method:: LOB.isopen()
38
39 Return a boolean indicating if the LOB has been opened using the method
40 :meth:`~LOB.open()`.
41
42
43 .. method:: LOB.open()
44
45 Open the LOB for writing. This will improve performance when writing to a
46 LOB in chunks and there are functional or extensible indexes associated
47 with the LOB. If this method is not called, each write will perform an open
48 internally followed by a close after the write has been completed.
49
50
51 .. method:: LOB.read([offset=1, [amount]])
52
53 Return a portion (or all) of the data in the LOB object. Note that the
54 amount and offset are in bytes for BLOB and BFILE type LOBs and in UCS-2
55 code points for CLOB and NCLOB type LOBs. UCS-2 code points are equivalent
56 to characters for all but supplemental characters. If supplemental
57 characters are in the LOB, the offset and amount will have to be chosen
58 carefully to avoid splitting a character.
59
60
61 .. method:: LOB.setfilename(dirAlias, name)
62
63 Set the directory alias and name of the BFILE type LOB.
64
65
66 .. method:: LOB.size()
67
68 Returns the size of the data in the LOB object. For BLOB and BFILE type
69 LOBs this is the number of bytes. For CLOB and NCLOB type LOBs this is the
70 number of UCS-2 code points. UCS-2 code points are equivalent to characters
71 for all but supplemental characters.
72
73
74 .. method:: LOB.trim([newSize=0])
75
76 Trim the LOB to the new size.
77
78
79 .. method:: LOB.write(data, [offset=1])
80
81 Write the data to the LOB object at the given offset. The offset is in
82 bytes for BLOB type LOBs and in UCS-2 code points for CLOB and NCLOB type
83 LOBs. UCS-2 code points are equivalent to characters for all but
84 supplemental characters. If supplemental characters are in the LOB, the
85 offset will have to be chosen carefully to avoid splitting a character.
86 Note that if you want to make the LOB value smaller, you must use the
87 :meth:`~LOB.trim()` function.
88
+0
-1288
doc/src/module.rst less more
0 .. module:: cx_Oracle
1
2 .. _module:
3
4 ****************
5 Module Interface
6 ****************
7
8 .. data:: __future__
9
10 Special object which contains attributes which control the behavior of
11 cx_Oracle, allowing for opting in for new features. No attributes are
12 currently supported so all attributes will silently ignore being set and
13 will always appear to have the value None.
14
15 .. note::
16
17 This method is an extension to the DB API definition.
18
19 .. versionadded:: 6.2
20
21
22 .. function:: Binary(string)
23
24 Construct an object holding a binary (long) string value.
25
26
27 .. function:: clientversion()
28
29 Return the version of the client library being used as a 5-tuple. The five
30 values are the major version, minor version, update number, patch number
31 and port update number.
32
33 .. note::
34
35 This method is an extension to the DB API definition.
36
37
38 .. function:: Connection(user=None, password=None, dsn=None, mode=None, \
39 handle=None, pool=None, threaded=False, events=False, cclass=None, \
40 purity=None, newpassword=None, encoding=None, nencoding=None, \
41 edition=None, appcontext=[], tag=None, matchanytag=False, \
42 shardingkey=[], supershardingkey=[])
43 connect(user=None, password=None, dsn=None, mode=None, handle=None, \
44 pool=None, threaded=False, events=False, cclass=None, purity=None, \
45 newpassword=None, encoding=None, nencoding=None, edition=None, \
46 appcontext=[], tag=None, matchanytag=None, shardingkey=[], \
47 supershardingkey=[])
48
49 Constructor for creating a connection to the database. Return a
50 :ref:`connection object <connobj>`. All parameters are optional and can be
51 specified as keyword parameters.
52
53 The dsn (data source name) is the TNS entry (from the Oracle names server
54 or tnsnames.ora file) or is a string like the one returned from
55 :meth:`~cx_Oracle.makedsn()`. If only one parameter is passed, a connect
56 string is assumed which is to be of the format ``user/password@dsn``, the
57 same format accepted by Oracle applications such as SQL\*Plus.
58
59 If the mode is specified, it must be one of :data:`~cx_Oracle.SYSDBA`,
60 :data:`~cx_Oracle.SYSASM`, :data:`~cx_Oracle.SYSOPER`,
61 :data:`~cx_Oracle.SYSBKP`, :data:`~cx_Oracle.SYSDGD`,
62 :data:`~cx_Oracle.SYSKMT` or :data:`~cx_Oracle.SYSRAC` which are defined
63 at the module level; otherwise, it defaults to the normal mode of
64 connecting.
65
66 If the handle is specified, it must be of type OCISvcCtx\* and is only of
67 use when embedding Python in an application (like PowerBuilder) which has
68 already made the connection.
69
70 The pool parameter is expected to be a
71 :ref:`session pool object <sesspool>` and the use of this parameter is the
72 equivalent of calling :meth:`SessionPool.acquire()`. Parameters not
73 acecpted by that method are ignored.
74
75 The threaded parameter is expected to be a boolean expression which
76 indicates whether or not Oracle should wrap accesses to connections with a
77 mutex. Doing so in single threaded applications imposes a performance
78 penalty of about 10-15% which is why the default is False.
79
80 The events parameter is expected to be a boolean expression which indicates
81 whether or not to initialize Oracle in events mode. This is required for
82 continuous query notification and high availablity event notifications.
83
84 The cclass parameter is expected to be a string and defines the connection
85 class for database resident connection pooling (DRCP).
86
87 The purity parameter is expected to be one of
88 :data:`~cx_Oracle.ATTR_PURITY_NEW`, :data:`~cx_Oracle.ATTR_PURITY_SELF`, or
89 :data:`~cx_Oracle.ATTR_PURITY_DEFAULT`.
90
91 The newpassword parameter is expected to be a string if specified and sets
92 the password for the logon during the connection process.
93
94 The encoding parameter is expected to be a string if specified and sets the
95 encoding to use for regular database strings. If not specified, the
96 environment variable NLS_LANG is used. If the environment variable NLS_LANG
97 is not set, ASCII is used.
98
99 The nencoding parameter is expected to be a string if specified and sets
100 the encoding to use for national character set database strings. If not
101 specified, the environment variable NLS_NCHAR is used. If the environment
102 variable NLS_NCHAR is not used, the environment variable NLS_LANG is used
103 instead, and if the environment variable NLS_LANG is not set, ASCII is
104 used.
105
106 The edition parameter is expected to be a string if specified and sets the
107 edition to use for the session. It is only relevant if both the client and
108 the database are at least Oracle Database 11.2. If this parameter is used
109 with the cclass parameter the exception "DPI-1058: edition not supported
110 with connection class" will be raised.
111
112 The appcontext parameter is expected to be a list of 3-tuples, if specified,
113 and sets the application context for the connection. Application context
114 is available in the database by using the sys_context() PL/SQL method and
115 can be used within a logon trigger as well as any other PL/SQL procedures.
116 Each entry in the list is expected to contain three strings: the namespace,
117 the name and the value.
118
119 The tag parameter, if specified, is expected to be a string and will limit
120 the sessions that can be returned from a session pool unless the
121 matchanytag parameter is set to True. In that case sessions with the
122 specified tag will be preferred over others, but if no such sessions are
123 available a session with a different tag may be returned instead. In any
124 case, untagged sessions will always be returned if no sessions with the
125 specified tag are available. Sessions are tagged when they are
126 :meth:`released <SessionPool.release>` back to the pool.
127
128 The shardingkey and supershardingkey parameters, if specified, are expected
129 to be a sequence of values which will be used to identify the database
130 shard to connect to. Currently only strings are supported for the key
131 values.
132
133
134 .. function:: Cursor(connection)
135
136 Constructor for creating a cursor. Return a new
137 :ref:`cursor object <cursorobj>` using the connection.
138
139 .. note::
140
141 This method is an extension to the DB API definition.
142
143
144 .. function:: Date(year, month, day)
145
146 Construct an object holding a date value.
147
148
149 .. function:: DateFromTicks(ticks)
150
151 Construct an object holding a date value from the given ticks value (number
152 of seconds since the epoch; see the documentation of the standard Python
153 time module for details).
154
155
156 .. function:: makedsn(host, port, sid=None, service_name=None, region=None, \
157 sharding_key=None, super_sharding_key=None)
158
159 Return a string suitable for use as the dsn parameter for
160 :meth:`~cx_Oracle.connect()`. This string is identical to the strings that
161 are defined by the Oracle names server or defined in the tnsnames.ora file.
162
163 .. note::
164
165 This method is an extension to the DB API definition.
166
167
168 .. function:: SessionPool(user=None, password=None, dsn=None, min=1, max=2, \
169 increment=1, connectiontype=cx_Oracle.Connection, threaded=False, \
170 getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT, events=False, \
171 homogeneous=True, externalauth=False, encoding=None, nencoding=None, \
172 edition=None, timeout=0, waitTimeout=0, maxLifetimeSession=0, \
173 sessionCallback=None)
174
175 Create and return a :ref:`session pool object <sesspool>`. This
176 allows for very fast connections to the database and is of primary use in a
177 server where the same connection is being made multiple times in rapid
178 succession (a web server, for example).
179
180 If the connection type is specified, all calls to
181 :meth:`~SessionPool.acquire()` will create connection objects of that type,
182 rather than the base type defined at the module level.
183
184 The threaded parameter is expected to be a boolean expression which
185 indicates whether Oracle should wrap accesses to connections with a mutex.
186 Doing so in single threaded applications imposes a performance penalty of
187 about 10-15% which is why the default is False.
188
189 The events parameter is expected to be a boolean expression which indicates
190 whether or not to initialize Oracle in events mode. This is required for
191 continuous query notification and high availability event notifications.
192
193 The homogeneous parameter is expected to be a boolean expression which
194 indicates whether or not to create a homogeneous pool. A homogeneous pool
195 requires that all connections in the pool use the same credentials. As such
196 proxy authentication and external authentication is not possible with a
197 homogeneous pool.
198
199 The externalauth parameter is expected to be a boolean expression which
200 indicates whether or not external authentication should be used. External
201 authentication implies that something other than the database is
202 authenticating the user to the database. This includes the use of operating
203 system authentication and Oracle wallets.
204
205 The encoding parameter is expected to be a string, if specified, and sets
206 the encoding to use for regular database strings. If not specified, the
207 environment variable NLS_LANG is used. If the environment variable NLS_LANG
208 is not set, ASCII is used.
209
210 The nencoding parameter is expected to be a string, if specified, and sets
211 the encoding to use for national character set database strings. If not
212 specified, the environment variable NLS_NCHAR is used. If the environment
213 variable NLS_NCHAR is not used, the environment variable NLS_LANG is used
214 instead, and if the environment variable NLS_LANG is not set, ASCII is
215 used.
216
217 The edition parameter is expected to be a string, if specified, and sets
218 the edition to use for the sessions in the pool. It is only relevant if
219 both the client and the server are at least Oracle Database 11.2.
220
221 The timeout parameter is expected to be an integer, if specified, and sets
222 the length of time (in seconds) after which idle sessions in the pool are
223 terminated. Note that termination only occurs when the pool is accessed.
224 The default value of 0 means that no idle sessions are terminated.
225
226 The waitTimeout parameter is expected to be an integer, if specified, and
227 sets the length of time (in milliseconds) that the caller should wait for
228 a session to become available in the pool before returning with an error.
229 This value is only used if the getmode parameter is set to the value
230 :data:`cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT`.
231
232 The maxLifetimeSession parameter is expected to be an integer, if
233 specified, and sets the maximum length of time (in seconds) a pooled
234 session may exist. Sessions that are in use will not be closed. They become
235 candidates for termination only when they are released back to the pool and
236 have existed for longer than maxLifetimeSession seconds. Note that
237 termination only occurs when the pool is accessed. The default value is 0
238 which means that there is no maximum length of time that a pooled session
239 may exist.
240
241 The sessionCallback parameter is expected to be either a string or a
242 callable. If the parameter is a string, this refers to a PL/SQL procedure
243 that will be called when :func:`SessionPool.acquire()` requests a tag and
244 that tag does not match the connection's actual tag. Support for the PL/SQL
245 procedure requires Oracle Client libraries 12.2 or later. See the
246 `OCI documentation <https://www.oracle.com/pls/topic/lookup?
247 ctx=dblatest&id=GUID-B853A020-752F-494A-8D88-D0396EF57177>`__ for more
248 information. If the sessionCallback parameter is a callable, however, it
249 will be called when a newly created connection is returned from the pool
250 or when a tag is requested and that tag does not match the connection's
251 actual tag. The callable will be invoked with the connection and the
252 requested tag as its only parameters.
253
254 .. note::
255
256 This method is an extension to the DB API definition.
257
258
259 .. function:: Time(hour, minute, second)
260
261 Construct an object holding a time value.
262
263 .. note::
264
265 The time only data type is not supported by Oracle. Calling this
266 function will raise a NotSupportedError exception.
267
268
269
270 .. function:: TimeFromTicks(ticks)
271
272 Construct an object holding a time value from the given ticks value (number
273 of seconds since the epoch; see the documentation of the standard Python
274 time module for details).
275
276 .. note::
277
278 The time only data type is not supported by Oracle. Calling this
279 function will raise a NotSupportedError exception.
280
281
282 .. function:: Timestamp(year, month, day, hour, minute, second)
283
284 Construct an object holding a time stamp value.
285
286
287 .. function:: TimestampFromTicks(ticks)
288
289 Construct an object holding a time stamp value from the given ticks value
290 (number of seconds since the epoch; see the documentation of the standard
291 Python time module for details).
292
293
294
295 .. _constants:
296
297 Constants
298 =========
299
300 General
301 -------
302
303 .. data:: apilevel
304
305 String constant stating the supported DB API level. Currently '2.0'.
306
307
308 .. data:: buildtime
309
310 String constant stating the time when the binary was built.
311
312 .. note::
313
314 This constant is an extension to the DB API definition.
315
316
317 .. data:: paramstyle
318
319 String constant stating the type of parameter marker formatting expected by
320 the interface. Currently 'named' as in 'where name = :name'.
321
322
323 .. data:: threadsafety
324
325 Integer constant stating the level of thread safety that the interface
326 supports. Currently 2, which means that threads may share the module and
327 connections, but not cursors. Sharing means that a thread may use a
328 resource without wrapping it using a mutex semaphore to implement resource
329 locking.
330
331 Note that in order to make use of multiple threads in a program which
332 intends to connect and disconnect in different threads, the threaded
333 parameter to :meth:`connect()` or :meth:`SessionPool()` must be true.
334
335
336 .. data:: version
337 .. data:: __version__
338
339 String constant stating the version of the module. Currently '|release|'.
340
341 .. note::
342
343 This attribute is an extension to the DB API definition.
344
345
346 Advanced Queuing: Delivery Modes
347 --------------------------------
348
349 These constants are extensions to the DB API definition. They are possible
350 values for the :attr:`~DeqOptions.deliverymode` attribute of the
351 :ref:`dequeue options object <deqoptions>` passed as the options parameter to
352 the :meth:`Connection.deq()` method as well as the
353 :attr:`~EnqOptions.deliverymode` attribute of the
354 :ref:`enqueue options object <enqoptions>` passed as the options parameter to
355 the :meth:`Connection.enq()` method. They are also possible values for the
356 :attr:`~MessageProperties.deliverymode` attribute of the
357 :ref:`message properties object <msgproperties>` passed as the msgproperties
358 parameter to the :meth:`Connection.deq()` and :meth:`Connection.enq()` methods.
359
360
361 .. data:: MSG_BUFFERED
362
363 This constant is used to specify that enqueue/dequeue operations should
364 enqueue or dequeue buffered messages.
365
366
367 .. data:: MSG_PERSISTENT
368
369 This constant is used to specify that enqueue/dequeue operations should
370 enqueue or dequeue persistent messages. This is the default value.
371
372
373 .. data:: MSG_PERSISTENT_OR_BUFFERED
374
375 This constant is used to specify that dequeue operations should dequeue
376 either persistent or buffered messages.
377
378
379 Advanced Queuing: Dequeue Modes
380 -------------------------------
381
382 These constants are extensions to the DB API definition. They are possible
383 values for the :attr:`~DeqOptions.mode` attribute of the
384 :ref:`dequeue options object <deqoptions>`. This object is the options
385 parameter for the :meth:`Connection.deq()` method.
386
387
388 .. data:: DEQ_BROWSE
389
390 This constant is used to specify that dequeue should read the message
391 without acquiring any lock on the message (eqivalent to a select
392 statement).
393
394
395 .. data:: DEQ_LOCKED
396
397 This constant is used to specify that dequeue should read and obtain a
398 write lock on the message for the duration of the transaction (equivalent
399 to a select for update statement).
400
401
402 .. data:: DEQ_REMOVE
403
404 This constant is used to specify that dequeue should read the message and
405 update or delete it. This is the default value.
406
407
408 .. data:: DEQ_REMOVE_NODATA
409
410 This constant is used to specify that dequeue should confirm receipt of the
411 message but not deliver the actual message content.
412
413
414 Advanced Queuing: Dequeue Navigation Modes
415 ------------------------------------------
416
417 These constants are extensions to the DB API definition. They are possible
418 values for the :attr:`~DeqOptions.navigation` attribute of the
419 :ref:`dequeue options object <deqoptions>`. This object is the options
420 parameter for the :meth:`Connection.deq()` method.
421
422
423 .. data:: DEQ_FIRST_MSG
424
425 This constant is used to specify that dequeue should retrieve the first
426 available message that matches the search criteria. This resets the
427 position to the beginning of the queue.
428
429
430 .. data:: DEQ_NEXT_MSG
431
432 This constant is used to specify that dequeue should retrieve the next
433 available message that matches the search criteria. If the previous message
434 belongs to a message group, AQ retrieves the next available message that
435 matches the search criteria and belongs to the message group. This is the
436 default.
437
438
439 .. data:: DEQ_NEXT_TRANSACTION
440
441 This constant is used to specify that dequeue should skip the remainder of
442 the transaction group and retrieve the first message of the next
443 transaction group. This option can only be used if message grouping is
444 enabled for the current queue.
445
446
447 Advanced Queuing: Dequeue Visibility Modes
448 ------------------------------------------
449
450 These constants are extensions to the DB API definition. They are possible
451 values for the :attr:`~DeqOptions.visibility` attribute of the
452 :ref:`dequeue options object <deqoptions>`. This object is the options
453 parameter for the :meth:`Connection.deq()` method.
454
455
456 .. data:: DEQ_IMMEDIATE
457
458 This constant is used to specify that dequeue should perform its work as
459 part of an independent transaction.
460
461
462 .. data:: DEQ_ON_COMMIT
463
464 This constant is used to specify that dequeue should be part of the current
465 transaction. This is the default value.
466
467
468 Advanced Queuing: Dequeue Wait Modes
469 ------------------------------------
470
471 These constants are extensions to the DB API definition. They are possible
472 values for the :attr:`~DeqOptions.wait` attribute of the
473 :ref:`dequeue options object <deqoptions>`. This object is the options
474 parameter for the :meth:`Connection.deq()` method.
475
476
477 .. data:: DEQ_NO_WAIT
478
479 This constant is used to specify that dequeue not wait for messages to be
480 available for dequeuing.
481
482
483 .. data:: DEQ_WAIT_FOREVER
484
485 This constant is used to specify that dequeue should wait forever for
486 messages to be available for dequeuing. This is the default value.
487
488
489 Advanced Queuing: Enqueue Visibility Modes
490 ------------------------------------------
491
492 These constants are extensions to the DB API definition. They are possible
493 values for the :attr:`~EnqOptions.visibility` attribute of the
494 :ref:`enqueue options object <enqoptions>`. This object is the options
495 parameter for the :meth:`Connection.enq()` method.
496
497
498 .. data:: ENQ_IMMEDIATE
499
500 This constant is used to specify that enqueue should perform its work as
501 part of an independent transaction.
502
503
504 .. data:: ENQ_ON_COMMIT
505
506 This constant is used to specify that enqueue should be part of the current
507 transaction. This is the default value.
508
509
510 Advanced Queuing: Message States
511 --------------------------------
512
513 These constants are extensions to the DB API definition. They are possible
514 values for the :attr:`~MessageProperties.state` attribute of the
515 :ref:`message properties object <msgproperties>`. This object is the
516 msgproperties parameter for the :meth:`Connection.deq()` and
517 :meth:`Connection.enq()` methods.
518
519
520 .. data:: MSG_EXPIRED
521
522 This constant is used to specify that the message has been moved to the
523 exception queue.
524
525
526 .. data:: MSG_PROCESSED
527
528 This constant is used to specify that the message has been processed and
529 has been retained.
530
531
532 .. data:: MSG_READY
533
534 This constant is used to specify that the message is ready to be processed.
535
536
537 .. data:: MSG_WAITING
538
539 This constant is used to specify that the message delay has not yet been
540 reached.
541
542
543 Advanced Queuing: Other
544 -----------------------
545
546 These constants are extensions to the DB API definition. They are special
547 constants used in advanced queuing.
548
549
550 .. data:: MSG_NO_DELAY
551
552 This constant is a possible value for the :attr:`~MessageProperties.delay`
553 attribute of the :ref:`message properties object <msgproperties>` passed
554 as the msgproperties parameter to the :meth:`Connection.deq()` and
555 :meth:`Connection.enq()` methods. It specifies that no delay should be
556 imposed and the message should be immediately available for dequeuing. This
557 is also the default value.
558
559
560 .. data:: MSG_NO_EXPIRATION
561
562 This constant is a possible value for the
563 :attr:`~MessageProperties.expiration` attribute of the
564 :ref:`message properties object <msgproperties>` passed as the msgproperties
565 parameter to the :meth:`Connection.deq()` and :meth:`Connection.enq()`
566 methods. It specifies that the message never expires. This is also the
567 default value.
568
569
570 Connection Authorization Modes
571 ------------------------------
572
573 These constants are extensions to the DB API definition. They are possible
574 values for the mode parameter of the :meth:`connect()` method.
575
576
577 .. data:: PRELIM_AUTH
578
579 This constant is used to specify that preliminary authentication is to be
580 used. This is needed for performing database startup and shutdown.
581
582
583 .. data:: SYSASM
584
585 This constant is used to specify that SYSASM access is to be acquired.
586
587
588 .. data:: SYSBKP
589
590 This constant is used to specify that SYSBACKUP access is to be acquired.
591
592
593 .. data:: SYSDBA
594
595 This constant is used to specify that SYSDBA access is to be acquired.
596
597
598 .. data:: SYSDGD
599
600 This constant is used to specify that SYSDG access is to be acquired.
601
602
603 .. data:: SYSKMT
604
605 This constant is used to specify that SYSKM access is to be acquired.
606
607
608 .. data:: SYSOPER
609
610 This constant is used to specify that SYSOPER access is to be acquired.
611
612
613 .. data:: SYSRAC
614
615 This constant is used to specify that SYSRAC access is to be acquired.
616
617
618 Database Shutdown Modes
619 -----------------------
620
621 These constants are extensions to the DB API definition. They are possible
622 values for the mode parameter of the :meth:`Connection.shutdown()` method.
623
624
625 .. data:: DBSHUTDOWN_ABORT
626
627 This constant is used to specify that the caller should not wait for
628 current processing to complete or for users to disconnect from the
629 database. This should only be used in unusual circumstances since database
630 recovery may be necessary upon next startup.
631
632
633 .. data:: DBSHUTDOWN_FINAL
634
635 This constant is used to specify that the instance can be truly halted.
636 This should only be done after the database has been shutdown with one of
637 the other modes (except abort) and the database has been closed and
638 dismounted using the appropriate SQL commands.
639
640
641 .. data:: DBSHUTDOWN_IMMEDIATE
642
643 This constant is used to specify that all uncommitted transactions should
644 be rolled back and any connected users should be disconnected.
645
646
647 .. data:: DBSHUTDOWN_TRANSACTIONAL
648
649 This constant is used to specify that further connections to the database
650 should be prohibited and no new transactions should be allowed. It then
651 waits for all active transactions to complete.
652
653
654 .. data:: DBSHUTDOWN_TRANSACTIONAL_LOCAL
655
656 This constant is used to specify that further connections to the database
657 should be prohibited and no new transactions should be allowed. It then
658 waits for only local active transactions to complete.
659
660
661 Event Types
662 -----------
663
664 These constants are extensions to the DB API definition. They are possible
665 values for the :attr:`Message.type` attribute of the messages that are sent
666 for subscriptions created by the :meth:`Connection.subscribe()` method.
667
668
669 .. data:: EVENT_AQ
670
671 This constant is used to specify that one or more messages are available
672 for dequeuing on the queue specified when the subscription was created.
673
674
675 .. data:: EVENT_DEREG
676
677 This constant is used to specify that the subscription has been
678 deregistered and no further notifications will be sent.
679
680
681 .. data:: EVENT_NONE
682
683 This constant is used to specify no information is available about the
684 event.
685
686
687 .. data:: EVENT_OBJCHANGE
688
689 This constant is used to specify that a database change has taken place on
690 a table registered with the :meth:`Subscription.registerquery()` method.
691
692
693 .. data:: EVENT_QUERYCHANGE
694
695 This constant is used to specify that the result set of a query registered
696 with the :meth:`Subscription.registerquery()` method has been changed.
697
698
699 .. data:: EVENT_SHUTDOWN
700
701 This constant is used to specify that the instance is in the process of
702 being shut down.
703
704
705 .. data:: EVENT_SHUTDOWN_ANY
706
707 This constant is used to specify that any instance (when running RAC) is in
708 the process of being shut down.
709
710
711 .. data:: EVENT_STARTUP
712
713 This constant is used to specify that the instance is in the process of
714 being started up.
715
716
717 Operation Codes
718 ---------------
719
720 These constants are extensions to the DB API definition. They are possible
721 values for the operations parameter for the :meth:`Connection.subscribe()`
722 method. One or more of these values can be OR'ed together. These values are
723 also used by the :attr:`MessageTable.operation` or
724 :attr:`MessageQuery.operation` attributes of the messages that are sent.
725
726
727 .. data:: OPCODE_ALLOPS
728
729 This constant is used to specify that messages should be sent for all
730 operations.
731
732
733 .. data:: OPCODE_ALLROWS
734
735 This constant is used to specify that the table or query has been
736 completely invalidated.
737
738
739 .. data:: OPCODE_ALTER
740
741 This constant is used to specify that messages should be sent when a
742 registered table has been altered in some fashion by DDL, or that the
743 message identifies a table that has been altered.
744
745
746 .. data:: OPCODE_DELETE
747
748 This constant is used to specify that messages should be sent when data is
749 deleted, or that the message identifies a row that has been deleted.
750
751
752 .. data:: OPCODE_DROP
753
754 This constant is used to specify that messages should be sent when a
755 registered table has been dropped, or that the message identifies a table
756 that has been dropped.
757
758
759 .. data:: OPCODE_INSERT
760
761 This constant is used to specify that messages should be sent when data is
762 inserted, or that the message identifies a row that has been inserted.
763
764
765 .. data:: OPCODE_UPDATE
766
767 This constant is used to specify that messages should be sent when data is
768 updated, or that the message identifies a row that has been updated.
769
770
771 Session Pool Get Modes
772 ----------------------
773
774 These constants are extensions to the DB API definition. They are possible
775 values for the getmode parameter of the :meth:`SessionPool()` method.
776
777
778 .. data:: SPOOL_ATTRVAL_FORCEGET
779
780 This constant is used to specify that a new connection will be returned if
781 there are no free sessions available in the pool.
782
783
784 .. data:: SPOOL_ATTRVAL_NOWAIT
785
786 This constant is used to specify that an exception should be raised if
787 there are no free sessions available in the pool. This is the default
788 value.
789
790
791 .. data:: SPOOL_ATTRVAL_WAIT
792
793 This constant is used to specify that the caller should wait until a
794 session is available if there are no free sessions available in the pool.
795
796
797 .. data:: SPOOL_ATTRVAL_TIMEDWAIT
798
799 This constant is used to specify that the caller should wait for a period
800 of time (defined by the waitTimeout parameter) for a session to become
801 available before returning with an error.
802
803
804 Session Pool Purity
805 -------------------
806
807 These constants are extensions to the DB API definition. They are possible
808 values for the purity parameter of the :meth:`connect()` method, which is used
809 in database resident connection pooling (DRCP).
810
811
812 .. data:: ATTR_PURITY_DEFAULT
813
814 This constant is used to specify that the purity of the session is the
815 default value identified by Oracle (see Oracle's documentation for more
816 information). This is the default value.
817
818
819 .. data:: ATTR_PURITY_NEW
820
821 This constant is used to specify that the session acquired from the pool
822 should be new and not have any prior session state.
823
824
825 .. data:: ATTR_PURITY_SELF
826
827 This constant is used to specify that the session acquired from the pool
828 need not be new and may have prior session state.
829
830
831 Subscription Grouping Classes
832 -----------------------------
833
834 These constants are extensions to the DB API definition. They are possible
835 values for the groupingClass parameter of the :meth:`Connection.subscribe()`
836 method.
837
838 .. data:: SUBSCR_GROUPING_CLASS_TIME
839
840 This constant is used to specify that events are to be grouped by the
841 period of time in which they are received.
842
843
844 Subscription Grouping Types
845 ---------------------------
846
847 These constants are extensions to the DB API definition. They are possible
848 values for the groupingType parameter of the :meth:`Connection.subscribe()`
849 method.
850
851 .. data:: SUBSCR_GROUPING_TYPE_SUMMARY
852
853 This constant is used to specify that when events are grouped a summary of
854 the events should be sent instead of the individual events. This is the
855 default value.
856
857 .. data:: SUBSCR_GROUPING_TYPE_LAST
858
859 This constant is used to specify that when events are grouped the last
860 event that makes up the group should be sent instead of the individual
861 events.
862
863
864 Subscription Namespaces
865 -----------------------
866
867 These constants are extensions to the DB API definition. They are possible
868 values for the namespace parameter of the :meth:`Connection.subscribe()`
869 method.
870
871 .. data:: SUBSCR_NAMESPACE_AQ
872
873 This constant is used to specify that notifications should be sent when a
874 queue has messages available to dequeue.
875
876 .. data:: SUBSCR_NAMESPACE_DBCHANGE
877
878 This constant is used to specify that database change notification or query
879 change notification messages are to be sent. This is the default value.
880
881
882 Subscription Protocols
883 ----------------------
884
885 These constants are extensions to the DB API definition. They are possible
886 values for the protocol parameter of the :meth:`Connection.subscribe()` method.
887
888
889 .. data:: SUBSCR_PROTO_HTTP
890
891 This constant is used to specify that notifications will be sent to an
892 HTTP URL when a message is generated. This value is currently not
893 supported.
894
895
896 .. data:: SUBSCR_PROTO_MAIL
897
898 This constant is used to specify that notifications will be sent to an
899 e-mail address when a message is generated. This value is currently not
900 supported.
901
902
903 .. data:: SUBSCR_PROTO_OCI
904
905 This constant is used to specify that notifications will be sent to the
906 callback routine identified when the subscription was created. It is the
907 default value and the only value currently supported.
908
909
910 .. data:: SUBSCR_PROTO_SERVER
911
912 This constant is used to specify that notifications will be sent to a
913 PL/SQL procedure when a message is generated. This value is currently not
914 supported.
915
916
917 Subscription Quality of Service
918 -------------------------------
919
920 These constants are extensions to the DB API definition. They are possible
921 values for the qos parameter of the :meth:`Connection.subscribe()` method. One
922 or more of these values can be OR'ed together.
923
924 .. data:: SUBSCR_QOS_BEST_EFFORT
925
926 This constant is used to specify that best effort filtering for query
927 result set changes is acceptable. False positive notifications may be
928 received. This behaviour may be suitable for caching applications.
929
930
931 .. data:: SUBSCR_QOS_DEREG_NFY
932
933 This constant is used to specify that the subscription should be
934 automatically unregistered after the first notification is received.
935
936
937 .. data:: SUBSCR_QOS_QUERY
938
939 This constant is used to specify that notifications should be sent if the
940 result set of the registered query changes. By default no false positive
941 notifications will be generated.
942
943
944 .. data:: SUBSCR_QOS_RELIABLE
945
946 This constant is used to specify that notifications should not be lost in
947 the event of database failure.
948
949
950 .. data:: SUBSCR_QOS_ROWIDS
951
952 This constant is used to specify that the rowids of the inserted, updated
953 or deleted rows should be included in the message objects that are sent.
954
955
956 Types
957 =====
958
959 .. data:: BINARY
960
961 This type object is used to describe columns in a database that contain
962 binary data. In Oracle this is RAW columns.
963
964
965 .. data:: BFILE
966
967 This type object is used to describe columns in a database that are BFILEs.
968
969 .. note::
970
971 This type is an extension to the DB API definition.
972
973
974 .. data:: BLOB
975
976 This type object is used to describe columns in a database that are BLOBs.
977
978 .. note::
979
980 This type is an extension to the DB API definition.
981
982
983 .. data:: BOOLEAN
984
985 This type object is used to represent PL/SQL booleans.
986
987 .. versionadded:: 5.2.1
988
989 .. note::
990
991 This type is an extension to the DB API definition. It is only
992 available in Oracle 12.1 and higher and only within PL/SQL. It cannot
993 be used in columns.
994
995
996 .. data:: CLOB
997
998 This type object is used to describe columns in a database that are CLOBs.
999
1000 .. note::
1001
1002 This type is an extension to the DB API definition.
1003
1004
1005 .. data:: CURSOR
1006
1007 This type object is used to describe columns in a database that are cursors
1008 (in PL/SQL these are known as ref cursors).
1009
1010 .. note::
1011
1012 This type is an extension to the DB API definition.
1013
1014
1015 .. data:: DATETIME
1016
1017 This type object is used to describe columns in a database that are dates.
1018
1019
1020 .. data:: FIXED_CHAR
1021
1022 This type object is used to describe columns in a database that are fixed
1023 length strings (in Oracle these is CHAR columns); these behave differently
1024 in Oracle than varchar2 so they are differentiated here even though the DB
1025 API does not differentiate them.
1026
1027 .. note::
1028
1029 This attribute is an extension to the DB API definition.
1030
1031
1032 .. data:: FIXED_NCHAR
1033
1034 This type object is used to describe columns in a database that are NCHAR
1035 columns in Oracle; these behave differently in Oracle than nvarchar2 so
1036 they are differentiated here even though the DB API does not differentiate
1037 them.
1038
1039 .. note::
1040
1041 This type is an extension to the DB API definition.
1042
1043
1044 .. data:: INTERVAL
1045
1046 This type object is used to describe columns in a database that are of type
1047 interval day to second.
1048
1049 .. note::
1050
1051 This type is an extension to the DB API definition.
1052
1053
1054 .. data:: LOB
1055
1056 This type object is the Python type of :data:`BLOB` and :data:`CLOB` data
1057 that is returned from cursors.
1058
1059 .. note::
1060
1061 This type is an extension to the DB API definition.
1062
1063
1064 .. data:: LONG_BINARY
1065
1066 This type object is used to describe columns in a database that are long
1067 binary (in Oracle these are LONG RAW columns).
1068
1069 .. note::
1070
1071 This type is an extension to the DB API definition.
1072
1073
1074 .. data:: LONG_STRING
1075
1076 This type object is used to describe columns in a database that are long
1077 strings (in Oracle these are LONG columns).
1078
1079 .. note::
1080
1081 This type is an extension to the DB API definition.
1082
1083
1084 .. data:: NATIVE_FLOAT
1085
1086 This type object is used to describe columns in a database that are of type
1087 binary_double or binary_float.
1088
1089 .. note::
1090
1091 This type is an extension to the DB API definition.
1092
1093
1094 .. data:: NATIVE_INT
1095
1096 This type object is used to bind integers using Oracle's native integer
1097 support, rather than the standard number support.
1098
1099 .. versionadded:: 5.3
1100
1101 .. note::
1102
1103 This type is an extension to the DB API definition.
1104
1105
1106 .. data:: NCHAR
1107
1108 This type object is used to describe national character strings (NVARCHAR2)
1109 in Oracle.
1110
1111 .. note::
1112
1113 This type is an extension to the DB API definition.
1114
1115
1116 .. data:: NCLOB
1117
1118 This type object is used to describe columns in a database that are NCLOBs.
1119
1120 .. note::
1121
1122 This type is an extension to the DB API definition.
1123
1124
1125 .. data:: NUMBER
1126
1127 This type object is used to describe columns in a database that are
1128 numbers.
1129
1130
1131 .. data:: OBJECT
1132
1133 This type object is used to describe columns in a database that are
1134 objects.
1135
1136 .. note::
1137
1138 This type is an extension to the DB API definition.
1139
1140
1141 .. data:: ROWID
1142
1143 This type object is used to describe the pseudo column "rowid".
1144
1145
1146 .. data:: STRING
1147
1148 This type object is used to describe columns in a database that are strings
1149 (in Oracle this is VARCHAR2 columns).
1150
1151
1152 .. data:: TIMESTAMP
1153
1154 This type object is used to describe columns in a database that are
1155 timestamps.
1156
1157 .. note::
1158
1159 This attribute is an extension to the DB API definition.
1160
1161
1162 .. _exceptions:
1163
1164 Exceptions
1165 ==========
1166
1167 .. exception:: Warning
1168
1169 Exception raised for important warnings and defined by the DB API but not
1170 actually used by cx_Oracle.
1171
1172
1173 .. exception:: Error
1174
1175 Exception that is the base class of all other exceptions defined by
1176 cx_Oracle and is a subclass of the Python StandardError exception (defined
1177 in the module exceptions).
1178
1179
1180 .. exception:: InterfaceError
1181
1182 Exception raised for errors that are related to the database interface
1183 rather than the database itself. It is a subclass of Error.
1184
1185
1186 .. exception:: DatabaseError
1187
1188 Exception raised for errors that are related to the database. It is a
1189 subclass of Error.
1190
1191
1192 .. exception:: DataError
1193
1194 Exception raised for errors that are due to problems with the processed
1195 data. It is a subclass of DatabaseError.
1196
1197
1198 .. exception:: OperationalError
1199
1200 Exception raised for errors that are related to the operation of the
1201 database but are not necessarily under the control of the progammer. It is
1202 a subclass of DatabaseError.
1203
1204
1205 .. exception:: IntegrityError
1206
1207 Exception raised when the relational integrity of the database is affected.
1208 It is a subclass of DatabaseError.
1209
1210
1211 .. exception:: InternalError
1212
1213 Exception raised when the database encounters an internal error. It is a
1214 subclass of DatabaseError.
1215
1216
1217 .. exception:: ProgrammingError
1218
1219 Exception raised for programming errors. It is a subclass of DatabaseError.
1220
1221
1222 .. exception:: NotSupportedError
1223
1224 Exception raised when a method or database API was used which is not
1225 supported by the database. It is a subclass of DatabaseError.
1226
1227
1228 Exception handling
1229 ==================
1230
1231 .. note::
1232
1233 PEP 249 (Python Database API Specification v2.0) says the following about
1234 exception values:
1235
1236 [...] The values of these exceptions are not defined. They should
1237 give the user a fairly good idea of what went wrong, though. [...]
1238
1239 With cx_Oracle every exception object has exactly one argument in the
1240 ``args`` tuple. This argument is a ``cx_Oracle._Error`` object which has
1241 the following five read-only attributes.
1242
1243 .. attribute:: _Error.code
1244
1245 Integer attribute representing the Oracle error number (ORA-XXXXX).
1246
1247 .. attribute:: _Error.offset
1248
1249 Integer attribute representing the error offset when applicable.
1250
1251 .. attribute:: _Error.message
1252
1253 String attribute representing the Oracle message of the error. This
1254 message is localized by the environment of the Oracle connection.
1255
1256 .. attribute:: _Error.context
1257
1258 String attribute representing the context in which the exception was
1259 raised.
1260
1261 .. attribute:: _Error.isrecoverable
1262
1263 Boolean attribute representing whether the error is recoverable or not.
1264 This is False in all cases unless Oracle Database 12.1 is being used on
1265 both the server and the client.
1266
1267 .. versionadded:: 5.3
1268
1269
1270 This allows you to use the exceptions for example in the following way:
1271
1272 ::
1273
1274 from __future__ import print_function
1275
1276 import cx_Oracle
1277
1278 connection = cx_Oracle.connect("cx_Oracle/dev@localhost/orclpdb")
1279 cursor = connection.cursor()
1280
1281 try:
1282 cursor.execute("select 1 / 0 from dual")
1283 except cx_Oracle.DatabaseError as exc:
1284 error, = exc.args
1285 print("Oracle-Error-Code:", error.code)
1286 print("Oracle-Error-Message:", error.message)
1287
+0
-152
doc/src/objecttype.rst less more
0 .. _objecttype:
1
2 *******************
3 Object Type Objects
4 *******************
5
6 .. note::
7
8 This object is an extension to the DB API. It is returned by the
9 :meth:`Connection.gettype()` call and is available as the
10 :data:`Variable.type` for variables containing Oracle objects.
11
12
13 .. method:: ObjectType([sequence])
14
15 The object type may be called directly and serves as an alternative way of
16 calling :meth:`~ObjectType.newobject()`.
17
18
19 .. attribute:: ObjectType.attributes
20
21 This read-only attribute returns a list of the attributes that make up the
22 object type. Each attribute has a name attribute on it.
23
24
25 .. attribute:: ObjectType.iscollection
26
27 This read-only attribute returns a boolean indicating if the object type
28 refers to a collection or not.
29
30
31 .. attribute:: ObjectType.name
32
33 This read-only attribute returns the name of the type.
34
35
36 .. method:: ObjectType.newobject([sequence])
37
38 Return a new Oracle object of the given type. This object can then be
39 modified by setting its attributes and then bound to a cursor for
40 interaction with Oracle. If the object type refers to a collection, a
41 sequence may be passed and the collection will be initialized with the
42 items in that sequence.
43
44
45 .. attribute:: ObjectType.schema
46
47 This read-only attribute returns the name of the schema that owns the type.
48
49
50 Object Objects
51 ==============
52
53 .. note::
54
55 This object is an extension to the DB API. It is returned by the
56 :meth:`ObjectType.newobject()` call and can be bound to variables of
57 type :data:`~cx_Oracle.OBJECT`. Attributes can be retrieved and set
58 directly.
59
60 .. method:: Object.append(element)
61
62 Append an element to the collection object. If no elements exist in the
63 collection, this creates an element at index 0; otherwise, it creates an
64 element immediately following the highest index available in the
65 collection.
66
67
68 .. method:: Object.asdict()
69
70 Return a dictionary where the collection's indexes are the keys and the
71 elements are its values.
72
73
74 .. method:: Object.aslist()
75
76 Return a list of each of the collection's elements in index order.
77
78
79 .. method:: Object.copy()
80
81 Create a copy of the object and return it.
82
83
84 .. method:: Object.delete(index)
85
86 Delete the element at the specified index of the collection. If the
87 element does not exist or is otherwise invalid, an error is raised. Note
88 that the indices of the remaining elements in the collection are not
89 changed. In other words, the delete operation creates holes in the
90 collection.
91
92
93 .. method:: Object.exists(index)
94
95 Return True or False indicating if an element exists in the collection at
96 the specified index.
97
98
99 .. method:: Object.extend(sequence)
100
101 Append all of the elements in the sequence to the collection. This is
102 the equivalent of performing :meth:`~Object.append()` for each element
103 found in the sequence.
104
105
106 .. method:: Object.first()
107
108 Return the index of the first element in the collection. If the collection
109 is empty, None is returned.
110
111
112 .. method:: Object.getelement(index)
113
114 Return the element at the specified index of the collection. If no element
115 exists at that index, an exception is raised.
116
117
118 .. method:: Object.last()
119
120 Return the index of the last element in the collection. If the collection
121 is empty, None is returned.
122
123
124 .. method:: Object.next(index)
125
126 Return the index of the next element in the collection following the
127 specified index. If there are no elements in the collection following the
128 specified index, None is returned.
129
130
131 .. method:: Object.prev(index)
132
133 Return the index of the element in the collection preceding the specified
134 index. If there are no elements in the collection preceding the
135 specified index, None is returned.
136
137
138 .. method:: Object.setelement(index, value)
139
140 Set the value in the collection at the specified index to the given value.
141
142
143 .. method:: Object.size()
144
145 Return the number of elements in the collection.
146
147
148 .. method:: Object.trim(num)
149
150 Remove the specified number of elements from the end of the collection.
151
0 :orphan:
1
2 .. _releasenotes:
3
4 cx_Oracle Release Notes
5 =======================
6
7 Version 8.0.1 (August 2020)
8 ---------------------------
9
10 #) Updated embedded ODPI-C to `version 4.0.2
11 <https://oracle.github.io/odpi/doc/releasenotes.html#
12 version-4-0-2-august-31-2020>`__. This includes the fix for binding and
13 fetching numbers with 39 or 40 decimal digits
14 (`issue 459 <https://github.com/oracle/python-cx_Oracle/issues/459>`__).
15 #) Added build metadata specifying that Python 3.5 and higher is required in
16 order to avoid downloading and failing to install with Python 2. The
17 exception message when running ``setup.py`` directly was updated to inform
18 those using Python 2 to use version 7.3 instead.
19 #) Documentation improvements.
20
21
22 Version 8.0 (June 2020)
23 -----------------------
24
25 #) Dropped support for Python 2. For those still requiring Python 2, see
26 :ref:`python2`.
27 #) Updated embedded ODPI-C to `version 4.0.1
28 <https://oracle.github.io/odpi/doc/releasenotes.html#
29 version-4-0-1-june-26-2020>`__.
30 #) Reworked type management to clarify and simplify code
31
32 - Added :ref:`constants <dbtypes>` for all database types. The database
33 types :data:`cx_Oracle.DB_TYPE_BINARY_FLOAT`,
34 :data:`cx_Oracle.DB_TYPE_INTERVAL_YM`,
35 :data:`cx_Oracle.DB_TYPE_TIMESTAMP_LTZ` and
36 :data:`cx_Oracle.DB_TYPE_TIMESTAMP_TZ` are completely new. The other
37 types were found in earlier releases under a different name. These types
38 will be found in :data:`Cursor.description` and passed as the defaultType
39 parameter to the :data:`Connection.outputtypehandler` and
40 :data:`Cursor.outputtypehandler` functions.
41 - Added :ref:`synonyms <dbtypesynonyms>` from the old type names to the new
42 type names for backwards compatibility. They are deprecated and will be
43 removed in a future version of cx_Oracle.
44 - The DB API :ref:`constants <types>` are now a specialized constant that
45 matches to the corresponding database types, as recommended by the DB
46 API.
47 - The variable attribute :data:`~Variable.type` now refers to one of the
48 new database type constants if the variable does not contain objects
49 (previously it was None in that case).
50 - The attribute :data:`~LOB.type` was added to LOB values.
51 - The attribute :data:`~ObjectAttribute.type` was added to attributes of
52 object types.
53 - The attribute :data:`~ObjectType.element_type` was added to object types.
54 - :ref:`Object types <objecttype>` now compare equal if they were created
55 by the same connection or session pool and their schemas and names match.
56 - All variables are now instances of the same class (previously each type
57 was an instance of a separate variable type). The attribute
58 :data:`~Variable.type` can be examined to determine the database type it
59 is associated with.
60 - The string representation of variables has changed to include the type
61 in addition to the value.
62
63 #) Added function :meth:`cx_Oracle.init_oracle_client()` in order to enable
64 programmatic control of the initialization of the Oracle Client library.
65 #) The default encoding for all character data is now UTF-8 and any character
66 set specified in the environment variable ``NLS_LANG`` is ignored.
67 #) Added functions :meth:`SodaCollection.save()`,
68 :meth:`SodaCollection.saveAndGet()` and :meth:`SodaCollection.truncate()`
69 available in Oracle Client 20 and higher.
70 #) Added function :meth:`SodaOperation.fetchArraySize()` available in Oracle
71 Client 19.5 and higher.
72 #) Added attribute :attr:`Cursor.prefetchrows` to control the number of rows
73 that the Oracle Client library fetches into internal buffers when a query
74 is executed.
75 #) Internally make use of new mode available in Oracle Client 20 and higher in
76 order to avoid a round-trip when accessing :attr:`Connection.version` for
77 the first time.
78 #) Added support for starting up a database using a parameter file (PFILE),
79 as requested
80 (`issue 295 <https://github.com/oracle/python-cx_Oracle/issues/295>`__).
81 #) Fixed overflow issue when calling :meth:`Cursor.getbatcherrors()` with
82 row offsets exceeding 65536.
83 #) Eliminated spurious error when accessing :attr:`Cursor.lastrowid` after
84 executing an INSERT ALL statement.
85 #) Miscellaneous improvements supplied by Alex Henrie (pull requests
86 `419 <https://github.com/oracle/python-cx_Oracle/pull/419>`__,
87 `420 <https://github.com/oracle/python-cx_Oracle/pull/420>`__,
88 `421 <https://github.com/oracle/python-cx_Oracle/pull/421>`__,
89 `422 <https://github.com/oracle/python-cx_Oracle/pull/422>`__,
90 `423 <https://github.com/oracle/python-cx_Oracle/pull/423>`__,
91 `437 <https://github.com/oracle/python-cx_Oracle/pull/437>`__ and
92 `438 <https://github.com/oracle/python-cx_Oracle/pull/438>`__).
93 #) Python objects bound to boolean variables are now converted to True or
94 False based on whether they would be considered True or False in a Python
95 if statement. Previously, only True was treated as True and all other
96 Python values (including 1, 1.0, and "foo") were treated as False
97 (pull request
98 `435 <https://github.com/oracle/python-cx_Oracle/pull/435>`__).
99 #) Documentation, samples and test suite improvements.
100
101
102 Version 7.3 (December 2019)
103 ---------------------------
104
105 #) Added support for Python 3.8.
106 #) Updated embedded ODPI-C to `version 3.3
107 <https://oracle.github.io/odpi/doc/releasenotes.html#
108 version-3-3-december-2-2019>`__.
109 #) Added support for CQN and other subscription client initiated connections
110 to the database (as opposed to the default server initiated connections)
111 created by calling :meth:`Connection.subscribe()`.
112 #) Added :attr:`support <Cursor.lastrowid>` for returning the rowid of the
113 last row modified by an operation on a cursor (or None if no row was
114 modified).
115 #) Added support for setting the maxSessionsPerShard attribute when
116 :meth:`creating session pools <cx_Oracle.SessionPool>`.
117 #) Added check to ensure sharding key is specified when a super sharding key
118 is specified.
119 #) Improved error message when the Oracle Client library is loaded
120 successfully but the attempt to detect the version of that library fails,
121 either due to the fact that the library is too old or the method could not
122 be called for some reason (`node-oracledb issue 1168
123 <https://github.com/oracle/node-oracledb/issues/1168>`__).
124 #) Adjusted support for creating a connection using an existing OCI service
125 context handle. In order to avoid potential memory corruption and
126 unsupported behaviors, the connection will now use the same encoding as the
127 existing OCI service context handle when it was created.
128 #) Added ``ORA-3156: OCI call timed out`` to the list of error messages that
129 result in error DPI-1067.
130 #) Adjusted samples and the test suite so that they can be run against Oracle
131 Cloud databases.
132 #) Fixed bug when attempting to create a scrollable cursor on big endian
133 platforms like AIX on PPC.
134 #) Eliminated reference leak and ensure that memory is properly initialized in
135 case of error when using sharding keys.
136 #) Eliminated reference leak when splitting the password and DSN components
137 out of a full connect string.
138 #) Corrected processing of DATE sharding keys (sharding requires a slightly
139 different format to be passed to the server).
140 #) Eliminated reference leak when
141 :meth:`creating message property objects <Connection.msgproperties()>`.
142 #) Attempting to use proxy authentication with a homogeneous pool will now
143 raise a ``DatabaseError`` exception with the message
144 ``DPI-1012: proxy authentication is not possible with homogeneous pools``
145 instead of a ``ProgrammingError`` exception with the message
146 ``pool is homogeneous. Proxy authentication is not possible.`` since this
147 check is done by ODPI-C. An empty string (or None) for the user name will
148 no longer generate an exception.
149 #) Exception ``InterfaceError: not connected`` is now always raised when an
150 operation is attempted with a closed connection. Previously, a number of
151 different exceptions were raised depending on the operation.
152 #) Added ``ORA-40479: internal JSON serializer error`` to the list of
153 exceptions that result in ``cx_Oracle.IntegrityError``.
154 #) Improved documentation.
155
156
157 Version 7.2.3 (October 2019)
158 ----------------------------
159
160 #) Updated embedded ODPI-C to `version 3.2.2
161 <https://oracle.github.io/odpi/doc/releasenotes.html#
162 version-3-2-2-october-1-2019>`__.
163 #) Restored support for setting numeric bind variables with boolean values.
164 #) Ensured that sharding keys are dedicated to the connection that is acquired
165 using them in order to avoid possible hangs, crashes or unusual errors.
166 #) Corrected support for PLS_INTEGER and BINARY_INTEGER types when used in
167 PL/SQL records
168 (`ODPI-C issue 112 <https://github.com/oracle/odpi/issues/112>`__).
169 #) Improved documentation.
170
171
172 Version 7.2.2 (August 2019)
173 ---------------------------
174
175 #) Updated embedded ODPI-C to `version 3.2.1
176 <https://oracle.github.io/odpi/doc/releasenotes.html#
177 version-3-2-1-august-12-2019>`__.
178 #) A more meaningful error is now returned when calling
179 :meth:`SodaCollection.insertMany()` with an empty list.
180 #) A more meaningful error is now returned when calling
181 :meth:`Subscription.registerquery()` with SQL that is not a SELECT
182 statement.
183 #) Eliminated segfault when a connection is closed after being created by a
184 call to :meth:`cx_Oracle.connect()` with the parameter ``cclass`` set to
185 a non-empty string.
186 #) Added user guide documentation.
187 #) Updated default connect strings to use 19c and XE 18c defaults.
188
189
190 Version 7.2.1 (July 2019)
191 -------------------------
192
193 #) Resolved ``MemoryError`` exception on Windows when using an output type
194 handler
195 (`issue 330 <https://github.com/oracle/python-cx_Oracle/issues/330>`__).
196 #) Improved test suite and samples.
197 #) Improved documentation.
198
199
200 Version 7.2 (July 2019)
201 -----------------------
202
203 #) Updated embedded ODPI-C to `version 3.2
204 <https://oracle.github.io/odpi/doc/releasenotes.html#
205 version-3-2-july-1-2019>`__.
206 #) Improved AQ support
207
208 - added support for enqueue and dequeue of RAW payloads
209 - added support for bulk enqueue and dequeue of messages
210 - added new method :meth:`Connection.queue()` which creates a new
211 :ref:`queue object <queue>` in order to simplify AQ usage
212 - enhanced method :meth:`Connection.msgproperties()` to allow the writable
213 properties of the newly created object to be initialized.
214 - the original methods for enqueueing and dequeuing (Connection.deq(),
215 Connection.deqoptions(), Connection.enq() and Connection.enqoptions())
216 are now deprecated and will be removed in a future version.
217
218 #) Removed preview status from existing SODA functionality. See
219 `this tracking issue
220 <https://github.com/oracle/python-cx_Oracle/issues/309>`__ for known issues
221 with SODA.
222 #) Added support for a preview of SODA bulk insert, available in Oracle Client
223 18.5 and higher.
224 #) Added support for setting LOB object attributes, as requested
225 (`issue 299 <https://github.com/oracle/python-cx_Oracle/issues/299>`__).
226 #) Added mode :data:`cx_Oracle.DEFAULT_AUTH` as requested
227 (`issue 293 <https://github.com/oracle/python-cx_Oracle/issues/293>`__).
228 #) Added support for setting the LOB prefetch length indicator in order to
229 reduce the number of round trips when fetching LOBs and then subsequently
230 calling :meth:`LOB.size()`, :meth:`LOB.getchunksize()` or
231 :meth:`LOB.read()`.
232 #) Added support for types BINARY_INTEGER, PLS_INTEGER, ROWID, LONG and LONG
233 RAW when used in PL/SQL.
234 #) Eliminated deprecation of attribute :attr:`Subscription.id`. It is now
235 populated with the value of ``REGID`` found in the database view
236 ``USER_CHANGE_NOTIFICATION_REGS`` or the value of ``REG_ID`` found in the
237 database view ``USER_SUBSCR_REGISTRATIONS``. For AQ subscriptions, the
238 value is 0.
239 #) Enabled PY_SSIZE_T_CLEAN, as required by Python 3.8
240 (`issue 317 <https://github.com/oracle/python-cx_Oracle/issues/317>`__).
241 #) Eliminated memory leak when fetching objects that are atomically null
242 (`issue 298 <https://github.com/oracle/python-cx_Oracle/issues/298>`__).
243 #) Eliminated bug when processing the string representation of numbers like
244 1e-08 and 1e-09 (`issue 300
245 <https://github.com/oracle/python-cx_Oracle/issues/300>`__).
246 #) Improved error message when the parent cursor is closed before a fetch is
247 attempted from an implicit result cursor.
248 #) Improved test suite and samples.
249 #) Improved documentation.
250
251
252 Version 7.1.3 (April 2019)
253 --------------------------
254
255 #) Updated to `ODPI-C 3.1.4
256 <https://oracle.github.io/odpi/doc/releasenotes.html#
257 version-3-1-4-april-24-2019>`__.
258 #) Added support for getting the row count for PL/SQL statements
259 (`issue 285 <https://github.com/oracle/python-cx_Oracle/issues/285>`__).
260 #) Corrected parsing of connect string so that the last @ symbol is searched
261 for instead of the first @ symbol; otherwise, passwords containing an @
262 symbol will result in the incorrect DSN being extracted
263 (`issue 290 <https://github.com/oracle/python-cx_Oracle/issues/290>`__).
264 #) Adjusted return value of cursor.callproc() to follow documentation (only
265 positional arguments are returned since the order of keyword parameters
266 cannot be guaranteed in any case)
267 (`PR 287 <https://github.com/oracle/python-cx_Oracle/pull/287>`__).
268 #) Corrected code getting sample and test parameters by user input when using
269 Python 2.7.
270
271
272 Version 7.1.2 (March 2019)
273 --------------------------
274
275 #) Updated to `ODPI-C 3.1.3
276 <https://oracle.github.io/odpi/doc/releasenotes.html#
277 version-3-1-3-march-12-2019>`__.
278 #) Ensured that the strings "-0" and "-0.0" are correctly handled as zero
279 values
280 (`issue 274 <https://github.com/oracle/python-cx_Oracle/issues/274>`__).
281 #) Eliminated error when startup and shutdown events are generated
282 (`ODPI-C issue 102 <https://github.com/oracle/odpi/issues/102>`__).
283 #) Enabled the types specified in :meth:`Cursor.setinputsizes()` and
284 :meth:`Cursor.callfunc()` to be an object type in addition to a Python
285 type, just like in :meth:`Cursor.var()`.
286 #) Reverted changes to return decimal numbers when the numeric precision was
287 too great to be returned accurately as a floating point number. This change
288 had too great an impact on existing functionality and an output type
289 handler can be used to return decimal numbers where that is desirable
290 (`issue 279 <https://github.com/oracle/python-cx_Oracle/issues/279>`__).
291 #) Eliminated discrepancies in character sets between an external connection
292 handle and the newly created connection handle that references the external
293 connection handle
294 (`issue 273 <https://github.com/oracle/python-cx_Oracle/issues/273>`__).
295 #) Eliminated memory leak when receiving messages received from subscriptions.
296 #) Improved test suite and documentation.
297
298
299 Version 7.1.1 (February 2019)
300 -----------------------------
301
302 #) Updated to `ODPI-C 3.1.2
303 <https://oracle.github.io/odpi/doc/releasenotes.html#
304 version-3-1-2-february-19-2019>`__.
305 #) Corrected code for freeing CQN message objects when multiple queries are
306 registered
307 (`ODPI-C issue 96 <https://github.com/oracle/odpi/issues/96>`__).
308 #) Improved error messages and installation documentation.
309
310
311 Version 7.1 (February 2019)
312 ---------------------------
313
314 #) Updated to `ODPI-C 3.1
315 <https://oracle.github.io/odpi/doc/releasenotes.html#
316 version-3-1-january-21-2019>`__.
317 #) Improved support for session tagging in session pools by allowing a
318 session callback to be specified when creating a pool via
319 :meth:`cx_Oracle.SessionPool()`. Callbacks can be written in Python or in
320 PL/SQL and can be used to improve performance by decreasing round trips to
321 the database needed to set session state. Callbacks written in Python will
322 be invoked for brand new connections (that have never been acquired from
323 the pool before) or when the tag assigned to the connection doesn't match
324 the one that was requested. Callbacks written in PL/SQL will only be
325 invoked when the tag assigned to the connection doesn't match the one that
326 was requested.
327 #) Added attribute :attr:`Connection.tag` to provide access to the actual tag
328 assigned to the connection. Setting this attribute will cause the
329 connection to be retagged when it is released back to the pool.
330 #) Added support for fetching SYS.XMLTYPE values as strings, as requested
331 (`issue 14 <https://github.com/oracle/python-cx_Oracle/issues/14>`__).
332 Note that this support is limited to the size of VARCHAR2 columns in the
333 database (either 4000 or 32767 bytes).
334 #) Added support for allowing the typename parameter in method
335 :meth:`Cursor.var()` to be None or a valid object type created by the
336 method :meth:`Connection.gettype()`, as requested
337 (`issue 231 <https://github.com/oracle/python-cx_Oracle/issues/231>`__).
338 #) Added support for getting and setting attributes of type RAW on Oracle
339 objects, as requested
340 (`ODPI-C issue 72 <https://github.com/oracle/odpi/issues/72>`__).
341 #) Added support for performing external authentication with proxy for
342 standalone connections.
343 #) Added support for mixing integers, floating point and decimal values in
344 data passed to :meth:`Cursor.executemany()`
345 (`issue 241 <https://github.com/oracle/python-cx_Oracle/issues/241>`__).
346 The error message raised when a value cannot be converted to an Oracle
347 number was also improved.
348 #) Adjusted fetching of numeric values so that no precision is lost. If an
349 Oracle number cannot be represented by a Python floating point number a
350 decimal value is automatically returned instead.
351 #) Corrected handling of multiple calls to method
352 :meth:`Cursor.executemany()` where all of the values in one of the columns
353 passed to the first call are all None and a subsequent call has a value
354 other than None in the same column
355 (`issue 236 <https://github.com/oracle/python-cx_Oracle/issues/236>`__).
356 #) Added additional check for calling :meth:`Cursor.setinputsizes()` with an
357 empty dictionary in order to avoid the error "cx_Oracle.ProgrammingError:
358 positional and named binds cannot be intermixed"
359 (`issue 199 <https://github.com/oracle/python-cx_Oracle/issues/199>`__).
360 #) Corrected handling of values that exceed the maximum value of a plain
361 integer object on Python 2 on Windows
362 (`issue 257 <https://github.com/oracle/python-cx_Oracle/issues/257>`__).
363 #) Added error message when attempting external authentication with proxy
364 without placing the user name in [] (proxy authentication was previously
365 silently ignored).
366 #) Exempted additional error messages from forcing a statement to be dropped
367 from the cache
368 (`ODPI-C issue 76 <https://github.com/oracle/odpi/issues/76>`__).
369 #) Improved dead session detection when using session pools for Oracle Client
370 12.2 and higher.
371 #) Ensured that the connection returned from a pool after a failed ping (such
372 as due to a killed session) is not itself marked as needing to be dropped
373 from the pool.
374 #) Eliminated memory leak under certain circumstances when pooled connections
375 are released back to the pool.
376 #) Eliminated memory leak when connections are dropped from the pool.
377 #) Eliminated memory leak when calling :meth:`Connection.close()` after
378 fetching collections from the database.
379 #) Adjusted order in which memory is freed when the last references to SODA
380 collections, documents, document cursors and collection cursors are
381 released, in order to prevent a segfault under certain circumstances.
382 #) Improved code preventing a statement from binding itself, in order to avoid
383 a potential segfault under certain circumstances.
384 #) Worked around OCI bug when attempting to free objects that are PL/SQL
385 records, in order to avoid a potential segfault.
386 #) Improved test suite and samples. Note that default passwords are no longer
387 supplied. New environment variables can be set to specify passwords if
388 desired, or the tests and samples will prompt for the passwords when
389 needed. In addition, a Python script is now available to create and drop
390 the schemas used for the tests and samples.
391 #) Improved documentation.
392
393
394 Version 7.0 (September 2018)
395 ----------------------------
396
397 #) Update to `ODPI-C 3.0
398 <https://oracle.github.io/odpi/doc/releasenotes.html#
399 version-3-0-0-september-13-2018>`__.
400 #) Added support for Oracle Client 18 libraries.
401 #) Added support for SODA (as preview). See :ref:`SODA Database <sodadb>`,
402 :ref:`SODA Collection <sodacoll>` and :ref:`SODA Document <sodadoc>` for
403 more information.
404 #) Added support for call timeouts available in Oracle Client 18.1 and
405 higher. See :attr:`Connection.callTimeout`.
406 #) Added support for getting the contents of a SQL collection object as a
407 dictionary, where the keys are the indices of the collection and the values
408 are the elements of the collection. See function :meth:`Object.asdict()`.
409 #) Added support for closing a session pool via the function
410 :meth:`SessionPool.close()`. Once closed, further attempts to use any
411 connection that was acquired from the pool will result in the error
412 "DPI-1010: not connected".
413 #) Added support for setting a LOB attribute of an object with a string or
414 bytes (instead of requiring a temporary LOB to be created).
415 #) Added support for the packed decimal type used by object attributes with
416 historical types DECIMAL and NUMERIC
417 (`issue 212 <https://github.com/oracle/python-cx_Oracle/issues/212>`__).
418 #) On Windows, first attempt to load oci.dll from the same directory as
419 the cx_Oracle module.
420 #) SQL objects that are created or fetched from the database are now tracked
421 and marked unusable when a connection is closed. This was done in order
422 to avoid a segfault under certain circumstances.
423 #) Re-enabled dead session detection functionality when using pools for Oracle
424 Client 12.2 and higher in order to handle classes of connection errors such
425 as resource profile limits.
426 #) Improved error messages when the Oracle Client or Oracle Database need to
427 be at a minimum version in order to support a particular feature.
428 #) When a connection is used as a context manager, the connection is now
429 closed when the block ends. Attempts to set
430 ``cx_Oracle.__future__.ctx_mgr_close`` are now ignored.
431 #) When a DML returning statement is executed, variables bound to it will
432 return an array when calling :meth:`Variable.getvalue()`. Attempts to set
433 ``cx_Oracle.__future__.dml_ret_array_val`` are now ignored.
434 #) Support for Python 3.4 has been dropped.
435 #) Added additional test cases.
436 #) Improved documentation.
437
438
439 Version 6.4.1 (July 2018)
440 -------------------------
441
442 #) Update to `ODPI-C 2.4.2
443 <https://oracle.github.io/odpi/doc/releasenotes.html#
444 version-2-4-2-july-9-2018>`__.
445
446 - Avoid buffer overrun due to improper calculation of length byte when
447 converting some negative 39 digit numbers from string to the internal
448 Oracle number format
449 (`ODPI-C issue 67 <https://github.com/oracle/odpi/issues/67>`__).
450
451 #) Prevent error "cx_Oracle.ProgrammingError: positional and named binds
452 cannot be intermixed" when calling cursor.setinputsizes() without any
453 parameters and then calling cursor.execute() with named bind parameters
454 (`issue 199 <https://github.com/oracle/python-cx_Oracle/issues/199>`__).
455
456
457 Version 6.4 (July 2018)
458 -----------------------
459
460 #) Update to `ODPI-C 2.4.1
461 <https://oracle.github.io/odpi/doc/releasenotes.html#
462 version-2-4-1-july-2-2018>`__.
463
464 - Added support for grouping subscriptions. See parameters groupingClass,
465 groupingValue and groupingType to function
466 :meth:`Connection.subscribe()`.
467 - Added support for specifying the IP address a subscription should use
468 instead of having the Oracle Client library determine the IP address on
469 its own. See parameter ipAddress to function
470 :meth:`Connection.subscribe()`.
471 - Added support for subscribing to notifications when messages are
472 available to dequeue in an AQ queue. The new constant
473 :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ` should be passed to the namespace
474 parameter of function :meth:`Connection.subscribe()` in order to get this
475 functionality. Attributes :attr:`Message.queueName` and
476 :attr:`Message.consumerName` will be populated in notification messages
477 that are received when this namespace is used.
478 - Added attribute :attr:`Message.registered` to let the notification
479 callback know when the subscription that generated the notification is no
480 longer registered with the database.
481 - Added support for timed waits when acquiring a session from a session
482 pool. Use the new constant :data:`cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT` in
483 the parameter getmode to function :meth:`cx_Oracle.SessionPool` along
484 with the new parameter waitTimeout.
485 - Added support for specifying the timeout and maximum lifetime session for
486 session pools when they are created using function
487 :meth:`cx_Oracle.SessionPool`. Previously the pool had to be created
488 before these values could be changed.
489 - Avoid memory leak when dequeuing from an empty queue.
490 - Ensure that the row count for queries is reset to zero when the statement
491 is executed
492 (`issue 193 <https://github.com/oracle/python-cx_Oracle/issues/193>`__).
493 - If the statement should be deleted from the statement cache, first check
494 to see that there is a statement cache currently being used; otherwise,
495 the error "ORA-24300: bad value for mode" will be raised under certain
496 conditions.
497
498 #) Added support for using the cursor as a context manager
499 (`issue 190 <https://github.com/oracle/python-cx_Oracle/issues/190>`__).
500 #) Added parameter "encodingErrors" to function :meth:`Cursor.var()` in order
501 to add support for specifying the "errors" parameter to the decode() that
502 takes place internally when fetching strings from the database
503 (`issue 162 <https://github.com/oracle/python-cx_Oracle/issues/162>`__).
504 #) Added support for specifying an integer for the parameters argument to
505 :meth:`Cursor.executemany()`. This allows for batch execution when no
506 parameters are required or when parameters have previously been bound. This
507 replaces Cursor.executemanyprepared() (which is now deprecated and will be
508 removed in cx_Oracle 7).
509 #) Adjusted the binding of booleans so that outside of PL/SQL they are bound
510 as integers
511 (`issue 181 <https://github.com/oracle/python-cx_Oracle/issues/181>`__).
512 #) Added support for binding decimal.Decimal values to cx_Oracle.NATIVE_FLOAT
513 as requested
514 (`issue 184 <https://github.com/oracle/python-cx_Oracle/issues/184>`__).
515 #) Added checks on passing invalid type parameters to methods
516 :meth:`Cursor.arrayvar()`, :meth:`Cursor.callfunc()` and
517 :meth:`Cursor.setinputsizes()`.
518 #) Corrected handling of cursors and rowids in DML Returning statements.
519 #) Added sample from David Lapp demonstrating the use of GeoPandas with
520 SDO_GEOMETRY and a sample for demonstrating the use of REF cursors.
521 #) Adjusted samples and documentation for clarity.
522 #) Added additional test cases.
523
524
525 Version 6.3.1 (May 2018)
526 ------------------------
527
528 #) Update to `ODPI-C 2.3.2
529 <https://oracle.github.io/odpi/doc/releasenotes.html#
530 version-2-3-2-may-7-2018>`__.
531
532 - Ensure that a call to unregister a subscription only occurs if the
533 subscription is still registered.
534 - Ensure that before a statement is executed any buffers used for DML
535 returning statements are reset.
536
537 #) Ensure that behavior with cx_Oracle.__future__.dml_ret_array_val not
538 set or False is the same as the behavior in cx_Oracle 6.2
539 (`issue 176 <https://github.com/oracle/python-cx_Oracle/issues/176>`__).
540
541
542 Version 6.3 (April 2018)
543 ------------------------
544
545 #) Update to `ODPI-C 2.3.1
546 <https://oracle.github.io/odpi/doc/releasenotes.html#
547 version-2-3-1-april-25-2018>`__.
548
549 - Fixed binding of LONG data (values exceeding 32KB) when using the
550 function :meth:`Cursor.executemany()`.
551 - Added code to verify that a CQN subscription is open before permitting it
552 to be used. Error "DPI-1060: subscription was already closed" will now be
553 raised if an attempt is made to use a subscription that was closed
554 earlier.
555 - Stopped attempting to unregister a CQN subscription before it was
556 completely registered. This prevents errors encountered during
557 registration from being masked by an error stating that the subscription
558 has not been registered!
559 - Added error "DPI-1061: edition is not supported when a new password is
560 specified" to clarify the fact that specifying an edition and a new
561 password at the same time is not supported when creating a connection.
562 Previously the edition value was simply ignored.
563 - Improved error message when older OCI client libraries are being used
564 that don't have the method OCIClientVersion().
565 - Fixed the handling of ANSI types REAL and DOUBLE PRECISION as
566 implemented by Oracle. These types are just subtypes of NUMBER and are
567 different from BINARY_FLOAT and BINARY_DOUBLE
568 (`issue 163 <https://github.com/oracle/python-cx_Oracle/issues/163>`__).
569 - Fixed support for true heterogeneous session pools that use different
570 user/password combinations for each session acquired from the pool.
571 - Added error message indicating that setting either of the parameters
572 arraydmlrowcounts and batcherrors to True in :meth:`Cursor.executemany()`
573 is only supported with insert, update, delete and merge statements.
574
575 #) Fixed support for getting the OUT values of bind variables bound to a DML
576 Returning statement when calling the function :meth:`Cursor.executemany()`.
577 Note that the attribute dml_ret_array_val in :attr:`cx_Oracle.__future__`
578 must be set to True first.
579 #) Added support for binding integers and floats as cx_Oracle.NATIVE_FLOAT.
580 #) A :attr:`cx_Oracle._Error` object is now the value of all cx_Oracle
581 exceptions raised by cx_Oracle.
582 (`issue 51 <https://github.com/oracle/python-cx_Oracle/issues/51>`__).
583 #) Added support for building cx_Oracle with a pre-compiled version of ODPI-C,
584 as requested
585 (`issue 103 <https://github.com/oracle/python-cx_Oracle/issues/103>`__).
586 #) Default values are now provided for all parameters to
587 :meth:`cx_Oracle.SessionPool`.
588 #) Improved error message when an unsupported Oracle type is encountered.
589 #) The Python GIL is now prevented from being held while performing a round
590 trip for the call to get the attribute :attr:`Connection.version`
591 (`issue 158 <https://github.com/oracle/python-cx_Oracle/issues/158>`__).
592 #) Added check for the validity of the year for Python 2.x since it doesn't do
593 that itself like Python 3.x does
594 (`issue 166 <https://github.com/oracle/python-cx_Oracle/issues/166>`__).
595 #) Adjusted documentation to provide additional information on the use of
596 :meth:`Cursor.executemany()` as requested
597 (`issue 153 <https://github.com/oracle/python-cx_Oracle/issues/153>`__).
598 #) Adjusted documentation to state that batch errors and array DML row counts
599 can only be used with insert, update, delete and merge statements
600 (`issue 31 <https://github.com/oracle/python-cx_Oracle/issues/31>`__).
601 #) Updated tutorial to import common connection information from files in
602 order to make setup a bit more generic.
603
604
605 Version 6.2.1 (March 2018)
606 --------------------------
607
608 #) Make sure cxoModule.h is included in the source archive
609 (`issue 155 <https://github.com/oracle/python-cx_Oracle/issues/155>`__).
610
611
612 Version 6.2 (March 2018)
613 ------------------------
614
615 #) Update to `ODPI-C 2.2.1
616 <https://oracle.github.io/odpi/doc/releasenotes.html#
617 version-2-2-1-march-5-2018>`__.
618
619 - eliminate error "DPI-1054: connection cannot be closed when open
620 statements or LOBs exist" (`issue 138
621 <https://github.com/oracle/python-cx_Oracle/issues/138>`__).
622 - avoid a round trip to the database when a connection is released back to
623 the pool by preventing a rollback from being called when no transaction
624 is in progress.
625 - improve error message when the use of bind variables is attempted with
626 DLL statements, which is not supported by Oracle.
627 - if an Oracle object is retrieved from an attribute of another Oracle
628 object or a collection, prevent the "owner" from being destroyed until
629 the object that was retrieved has itself been destroyed.
630 - correct handling of boundary numbers 1e126 and -1e126
631 - eliminate memory leak when calling :meth:`Connection.enq()` and
632 :meth:`Connection.deq()`
633 - eliminate memory leak when setting NCHAR and NVARCHAR attributes of
634 objects.
635 - eliminate memory leak when fetching collection objects from the database.
636
637 #) Added support for creating a temporary CLOB, BLOB or NCLOB via the method
638 :meth:`Connection.createlob()`.
639 #) Added support for binding a LOB value directly to a cursor.
640 #) Added support for closing the connection when reaching the end of a
641 ``with`` code block controlled by the connection as a context manager, but
642 in a backwards compatible way
643 (`issue 113 <https://github.com/oracle/python-cx_Oracle/issues/113>`__).
644 See :data:`cx_Oracle.__future__` for more information.
645 #) Reorganized code to simplify continued maintenance and consolidate
646 transformations to/from Python objects.
647 #) Ensure that the number of elements in the array is not lost when the
648 buffer size is increased to accommodate larger strings.
649 #) Corrected support in Python 3.x for cursor.parse() by permitting a string
650 to be passed, instead of incorrectly requiring a bytes object.
651 #) Eliminate reference leak with LOBs acquired from attributes of objects or
652 elements of collections.
653 #) Eliminate reference leak when extending an Oracle collection.
654 #) Documentation improvements.
655 #) Added test cases to the test suite.
656
657
658 Version 6.1 (December 2017)
659 ---------------------------
660
661 #) Update to `ODPI-C 2.1
662 <https://oracle.github.io/odpi/doc/releasenotes.html#
663 version-2-1-december-12-2017>`__.
664
665 - Support was added for accessing sharded databases via sharding keys (new
666 in Oracle 12.2). NOTE: the underlying OCI library has a bug when using
667 standalone connections. There is a small memory leak proportional to the
668 number of connections created/dropped. There is no memory leak when using
669 session pools, which is recommended.
670 - Added options for authentication with SYSBACKUP, SYSDG, SYSKM and SYSRAC,
671 as requested (`issue 101
672 <https://github.com/oracle/python-cx_Oracle/issues/101>`__).
673 - Attempts to release statements or free LOBs after the connection has been
674 closed (by, for example, killing the session) are now prevented.
675 - An error message was added when specifying an edition and a connection
676 class since this combination is not supported.
677 - Attempts to close the session for connections created with an external
678 handle are now prevented.
679 - Attempting to ping a database earlier than 10g results in ORA-1010:
680 invalid OCI operation, but that implies a response from the database and
681 therefore a successful ping, so treat it that way!
682 (see `<https://github.com/rana/ora/issues/224>`__ for more information).
683 - Support was added for converting numeric values in an object type
684 attribute to integer and text, as requested (`ODPI-C issue 35
685 <https://github.com/oracle/odpi/issues/35>`__).
686 - Setting attributes :attr:`DeqOptions.msgId` and
687 :attr:`MessageProperties.msgId` now works as expected.
688 - The overflow check when using double values (Python floats) as input
689 to float attributes of objects or elements of collections was removed as
690 it didn't work anyway and is a well-known issue that cannot be prevented
691 without removing desired functionality. The developer should ensure that
692 the source value falls within the limits of floats, understand the
693 consequent precision loss or use a different data type.
694 - Variables of string/raw types are restricted to 2 bytes less than 1 GB
695 (1,073,741,822 bytes), since OCI cannot handle more than that currently.
696 - Support was added for identifying the id of the transaction which spawned
697 a CQN subscription message, as requested
698 (`ODPI-C issue 32 <https://github.com/oracle/odpi/issues/32>`__).
699 - Corrected use of subscription port number (`issue 115
700 <https://github.com/oracle/python-cx_Oracle/issues/115>`__).
701 - Problems reported with the usage of FormatMessage() on Windows were
702 addressed (`ODPI-C issue 47
703 <https://github.com/oracle/odpi/issues/47>`__).
704 - On Windows, if oci.dll cannot be loaded because it is the wrong
705 architecture (32-bit vs 64-bit), attempt to find the offending DLL and
706 include the full path of the DLL in the message, as suggested.
707 (`ODPI-C issue 49 <https://github.com/oracle/odpi/issues/49>`__).
708 - Force OCI prefetch to always use the value 2; the OCI default is 1 but
709 setting the ODPI-C default to 2 ensures that single row fetches don't
710 require an extra round trip to determine if there are more rows to fetch;
711 this change also reduces the potential memory consumption when
712 fetchArraySize was set to a large value and also avoids performance
713 issues discovered with larger values of prefetch.
714
715 #) Fix build with PyPy 5.9.0-alpha0 in libpython mode
716 (`PR 54 <https://github.com/oracle/python-cx_Oracle/pull/54>`__).
717 #) Ensure that the edition is passed through to the database when a session
718 pool is created.
719 #) Corrected handling of Python object references when an invalid keyword
720 parameter is passed to :meth:`cx_Oracle.SessionPool`.
721 #) Corrected handling of :attr:`Connection.handle` and the handle parameter
722 to :meth:`cx_Oracle.connect` on Windows.
723 #) Documentation improvements.
724 #) Added test cases to the test suite.
725
726
727 Version 6.0.3 (November 2017)
728 -----------------------------
729
730 #) Update to `ODPI-C 2.0.3
731 <https://oracle.github.io/odpi/doc/releasenotes.html#
732 version-2-0-3-november-6-2017>`__.
733
734 - Prevent use of uninitialized data in certain cases (`issue 77
735 <https://github.com/oracle/python-cx_Oracle/issues/77>`__).
736 - Attempting to ping a database earlier than 10g results in error
737 "ORA-1010: invalid OCI operation", but that implies a response from the
738 database and therefore a successful ping, so treat it that way!
739 - Correct handling of conversion of some numbers to NATIVE_FLOAT.
740 - Prevent use of NaN with Oracle numbers since it produces corrupt data
741 (`issue 91 <https://github.com/oracle/python-cx_Oracle/issues/91>`__).
742 - Verify that Oracle objects bound to cursors, fetched from cursors, set in
743 object attributes or appended to collection objects are of the correct
744 type.
745 - Correct handling of NVARCHAR2 when used as attributes of Oracle objects
746 or as elements of collections.
747
748 #) Ensure that a call to setinputsizes() with an invalid type prior to a call
749 to executemany() does not result in a type error, but instead gracefully
750 ignores the call to setinputsizes() as required by the DB API
751 (`issue 75 <https://github.com/oracle/python-cx_Oracle/issues/75>`__).
752 #) Check variable array size when setting variable values and raise
753 IndexError, as is already done for getting variable values.
754
755
756 Version 6.0.2 (August 2017)
757 ---------------------------
758
759 #) Update to `ODPI-C 2.0.2
760 <https://oracle.github.io/odpi/doc/releasenotes.html
761 #version-2-0-2-august-30-2017>`__.
762
763 - Don't prevent connection from being explicitly closed when a fatal error
764 has taken place (`issue 67
765 <https://github.com/oracle/python-cx_Oracle/issues/67>`__).
766 - Correct handling of objects when dynamic binding is performed.
767 - Process deregistration events without an error.
768 - Eliminate memory leak when creating objects.
769
770 #) Added missing type check to prevent coercion of decimal to float
771 (`issue 68 <https://github.com/oracle/python-cx_Oracle/issues/68>`__).
772 #) On Windows, sizeof(long) = 4, not 8, which meant that integers between 10
773 and 18 digits were not converted to Python correctly
774 (`issue 70 <https://github.com/oracle/python-cx_Oracle/issues/70>`__).
775 #) Eliminate memory leak when repeatedly executing the same query.
776 #) Eliminate segfault when attempting to reuse a REF cursor that has been
777 closed.
778 #) Updated documentation.
779
780
781 Version 6.0.1 (August 2017)
782 ---------------------------
783
784 #) Update to `ODPI-C 2.0.1
785 <https://oracle.github.io/odpi/doc/releasenotes.html
786 #version-2-0-1-august-18-2017>`__.
787
788 - Ensure that queries registered via :meth:`Subscription.registerquery()`
789 do not prevent the associated connection from being closed
790 (`ODPI-C issue 27 <https://github.com/oracle/odpi/issues/27>`__).
791 - Deprecated attribute :attr:`Subscription.id` as it was never intended to
792 be exposed (`ODPI-C issue 28
793 <https://github.com/oracle/odpi/issues/28>`__). It will be dropped in
794 version 6.1.
795 - Add support for DML Returning statements that require dynamically
796 allocated variable data (such as CLOBs being returned as strings).
797
798 #) Correct packaging of Python 2.7 UCS4 wheels on Linux
799 (`issue 64 <https://github.com/oracle/python-cx_Oracle/issues/64>`__).
800 #) Updated documentation.
801
802
803 Version 6.0 (August 2017)
804 -------------------------
805
806 #) Update to `ODPI-C 2.0 <https://oracle.github.io/odpi/doc/releasenotes.html
807 #version-2-0-august-14-2017>`__.
808
809 - Prevent closing the connection when there are any open statements or
810 LOBs and add new error "DPI-1054: connection cannot be closed when open
811 statements or LOBs exist" when this situation is detected; this is
812 needed to prevent crashes under certain conditions when statements or
813 LOBs are being acted upon while at the same time (in another thread) a
814 connection is being closed; it also prevents leaks of statements and
815 LOBs when a connection is returned to a session pool.
816 - On platforms other than Windows, if the regular method for loading the
817 Oracle Client libraries fails, try using $ORACLE_HOME/lib/libclntsh.so
818 (`ODPI-C issue 20 <https://github.com/oracle/odpi/issues/20>`__).
819 - Use the environment variable DPI_DEBUG_LEVEL at runtime, not compile
820 time.
821 - Added support for DPI_DEBUG_LEVEL_ERRORS (reports errors and has the
822 value 8) and DPI_DEBUG_LEVEL_SQL (reports prepared SQL statement text
823 and has the value 16) in order to further improve the ability to debug
824 issues.
825 - Correct processing of :meth:`Cursor.scroll()` in some circumstances.
826
827 #) Delay initialization of the ODPI-C library until the first standalone
828 connection or session pool is created so that manipulation of the
829 environment variable NLS_LANG can be performed after the module has been
830 imported; this also has the added benefit of reducing the number of errors
831 that can take place when the module is imported.
832 #) Prevent binding of null values from generating the exception "ORA-24816:
833 Expanded non LONG bind data supplied after actual LONG or LOB column" in
834 certain circumstances
835 (`issue 50 <https://github.com/oracle/python-cx_Oracle/issues/50>`__).
836 #) Added information on how to run the test suite
837 (`issue 33 <https://github.com/oracle/python-cx_Oracle/issues/33>`__).
838 #) Documentation improvements.
839
840
841 Version 6.0 rc 2 (July 2017)
842 ----------------------------
843
844 #) Update to `ODPI-C rc 2 <https://oracle.github.io/odpi/doc/releasenotes.html
845 #version-2-0-0-rc-2-july-20-2017>`__.
846
847 - Provide improved error message when OCI environment cannot be created,
848 such as when the oraaccess.xml file cannot be processed properly.
849 - On Windows, convert system message to Unicode first, then to UTF-8;
850 otherwise, the error message returned could be in a mix of encodings
851 (`issue 40 <https://github.com/oracle/python-cx_Oracle/issues/40>`__).
852 - Corrected support for binding decimal values in object attribute values
853 and collection element values.
854 - Corrected support for binding PL/SQL boolean values to PL/SQL
855 procedures with Oracle client 11.2.
856
857 #) Define exception classes on the connection object in addition to at module
858 scope in order to simplify error handling in multi-connection environments,
859 as specified in the Python DB API.
860 #) Ensure the correct encoding is used for setting variable values.
861 #) Corrected handling of CLOB/NCLOB when using different encodings.
862 #) Corrected handling of TIMESTAMP WITH TIME ZONE attributes on objects.
863 #) Ensure that the array position passed to var.getvalue() does not exceed the
864 number of elements allocated in the array.
865 #) Reworked test suite and samples so that they are independent of each other
866 and so that the SQL scripts used to create/drop schemas are easily adjusted
867 to use different schema names, if desired.
868 #) Updated DB API test suite stub to support Python 3.
869 #) Added additional test cases and samples.
870 #) Documentation improvements.
871
872
873 Version 6.0 rc 1 (June 2017)
874 ----------------------------
875
876 #) Update to `ODPI-C rc 1 <https://oracle.github.io/odpi/doc/releasenotes.html
877 #version-2-0-0-rc-1-june-16-2017>`__.
878 #) The method :meth:`Cursor.setoutputsize` no longer needs to do anything,
879 since ODPI-C automatically manages buffer sizes of LONG and LONG RAW
880 columns.
881 #) Handle case when both precision and scale are zero, as occurs when
882 retrieving numeric expressions (`issue 34
883 <https://github.com/oracle/python-cx_Oracle/issues/34>`__).
884 #) OCI requires that both encoding and nencoding have values or that both
885 encoding and encoding do not have values. These parameters are used in
886 functions :meth:`cx_Oracle.connect` and :meth:`cx_Oracle.SessionPool`. The
887 missing value is set to its default value if one of the values is set and
888 the other is not (`issue 36
889 <https://github.com/oracle/python-cx_Oracle/issues/36>`__).
890 #) Permit use of both string and unicode for Python 2.7 for creating session
891 pools and for changing passwords (`issue 23
892 <https://github.com/oracle/python-cx_Oracle/issues/23>`__).
893 #) Corrected handling of BFILE LOBs.
894 #) Add script for dropping test schemas.
895 #) Documentation improvements.
896
897
898 Version 6.0 beta 2 (May 2017)
899 -----------------------------
900
901 #) Added support for getting/setting attributes of objects or element values
902 in collections that contain LOBs, BINARY_FLOAT values, BINARY_DOUBLE values
903 and NCHAR and NVARCHAR2 values. The error message for any types that are
904 not supported has been improved as well.
905 #) Enable temporary LOB caching in order to avoid disk I/O as
906 `suggested <https://github.com/oracle/odpi/issues/10>`__.
907 #) Added support for setting the debug level in ODPI-C, if desirable, by
908 setting environment variable DPI_DEBUG_LEVEL prior to building cx_Oracle.
909 #) Correct processing of strings in :meth:`Cursor.executemany` when a
910 larger string is found after a shorter string in the list of data bound to
911 the statement.
912 #) Correct handling of long Python integers that cannot fit inside a 64-bit C
913 integer (`issue 18
914 <https://github.com/oracle/python-cx_Oracle/issues/18>`__).
915 #) Correct creation of pool using external authentication.
916 #) Handle edge case when an odd number of zeroes trail the decimal point in a
917 value that is effectively zero (`issue 22
918 <https://github.com/oracle/python-cx_Oracle/issues/22>`__).
919 #) Prevent segfault under load when the attempt to create an error fails.
920 #) Eliminate resource leak when a standalone connection or pool is freed.
921 #) Correct `typo <https://github.com/oracle/python-cx_Oracle/issues/24>`__.
922 #) Correct handling of REF cursors when the array size is manipulated.
923 #) Prevent attempts from binding the cursor being executed to itself.
924 #) Correct reference count handling of parameters when creating a cursor.
925 #) Correct determination of the names of the bind variables in prepared SQL
926 statements (which behaves a little differently from PL/SQL statements).
927
928
929 Version 6.0 beta 1 (April 2017)
930 -------------------------------
931
932 #) Simplify building cx_Oracle considerably by use of
933 `ODPI-C <https://oracle.github.io/odpi>`__. This means that cx_Oracle can
934 now be built without Oracle Client header files or libraries and that at
935 runtime cx_Oracle can adapt to Oracle Client 11.2, 12.1 or 12.2 libraries
936 without needing to be rebuilt. This also means that wheels can now be
937 produced and installed via pip.
938 #) Added attribute :attr:`SessionPool.stmtcachesize` to support getting and
939 setting the default statement cache size for connections in the pool.
940 #) Added attribute :attr:`Connection.dbop` to support setting the database
941 operation that is to be monitored.
942 #) Added attribute :attr:`Connection.handle` to facilitate testing the
943 creation of a connection using a OCI service context handle.
944 #) Added parameters tag and matchanytag to the :meth:`cx_Oracle.connect`
945 and :meth:`SessionPool.acquire` methods and added parameters tag and retag
946 to the :meth:`SessionPool.release` method in order to support session
947 tagging.
948 #) Added parameter edition to the :meth:`cx_Oracle.SessionPool` method.
949 #) Added support for
950 `universal rowids <https://github.com/oracle/python-cx_Oracle/blob/master/
951 samples/UniversalRowids.py>`__.
952 #) Added support for `DML Returning of multiple rows
953 <https://github.com/oracle/python-cx_Oracle/blob/master/samples/
954 DMLReturningMultipleRows.py>`__.
955 #) Added attributes :attr:`Variable.actualElements` and
956 :attr:`Variable.values` to variables.
957 #) Added parameters region, sharding_key and super_sharding_key to the
958 :meth:`cx_Oracle.makedsn()` method to support connecting to a sharded
959 database (new in Oracle Database 12.2).
960 #) Added support for smallint and float data types in Oracle objects, as
961 `requested <https://github.com/oracle/python-cx_Oracle/issues/4>`__.
962 #) An exception is no longer raised when a collection is empty for methods
963 :meth:`Object.first()` and :meth:`Object.last()`. Instead, the value None
964 is returned to be consistent with the methods :meth:`Object.next()` and
965 :meth:`Object.prev()`.
966 #) If the environment variables NLS_LANG and NLS_NCHAR are being used, they
967 must be set before the module is imported. Using the encoding and nencoding
968 parameters to the :meth:`cx_Oracle.connect` and
969 :meth:`cx_Oracle.SessionPool` methods is a simpler alternative to setting
970 these environment variables.
971 #) Removed restriction on fetching LOBs across round trips to the database
972 (eliminates error "LOB variable no longer valid after subsequent fetch").
973 #) Removed requirement for specifying a maximum size when fetching LONG or
974 LONG raw columns. This also allows CLOB, NCLOB, BLOB and BFILE columns to
975 be fetched as strings or bytes without needing to specify a maximum size.
976 #) Dropped deprecated parameter twophase from the :meth:`cx_Oracle.connect`
977 method. Applications should set the :attr:`Connection.internal_name` and
978 :attr:`Connection.external_name` attributes instead to a value appropriate
979 to the application.
980 #) Dropped deprecated parameters action, module and clientinfo from the
981 :meth:`cx_Oracle.connect` method. The appcontext parameter should be used
982 instead as shown in this `sample <https://github.com/oracle/
983 python-cx_Oracle/blob/master/samples/AppContext.py>`__.
984 #) Dropped deprecated attribute numbersAsString from
985 :ref:`cursor objects <cursorobj>`. Use an output type handler instead as
986 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
987 master/samples/ReturnNumbersAsDecimals.py>`__.
988 #) Dropped deprecated attributes cqqos and rowids from
989 :ref:`subscription objects <subscrobj>`. Use the qos attribute instead as
990 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
991 master/samples/CQN.py>`__.
992 #) Dropped deprecated parameters cqqos and rowids from the
993 :meth:`Connection.subscribe()` method. Use the qos parameter instead as
994 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
995 master/samples/CQN.py>`__.
996
997
998 Version 5.3 (March 2017)
999 ------------------------
1000
1001 #) Added support for Python 3.6.
1002 #) Dropped support for Python versions earlier than 2.6.
1003 #) Dropped support for Oracle clients earlier than 11.2.
1004 #) Added support for
1005 :meth:`fetching implicit results<Cursor.getimplicitresults()>`
1006 (available in Oracle 12.1)
1007 #) Added support for :attr:`Transaction Guard <Connection.ltxid>` (available
1008 in Oracle 12.1).
1009 #) Added support for setting the
1010 :attr:`maximum lifetime <SessionPool.max_lifetime_session>` of pool
1011 connections (available in Oracle 12.1).
1012 #) Added support for large row counts (larger than 2 ** 32, available in
1013 Oracle 12.1)
1014 #) Added support for :meth:`advanced queuing <Connection.deq()>`.
1015 #) Added support for :meth:`scrollable cursors <Cursor.scroll()>`.
1016 #) Added support for :attr:`edition based redefinition <Connection.edition>`.
1017 #) Added support for :meth:`creating <ObjectType.newobject()>`, modifying and
1018 binding user defined types and collections.
1019 #) Added support for creating, modifying and binding PL/SQL records and
1020 collections (available in Oracle 12.1).
1021 #) Added support for binding :data:`native integers <cx_Oracle.NATIVE_INT>`.
1022 #) Enabled statement caching.
1023 #) Removed deprecated variable attributes maxlength and allocelems.
1024 #) Corrected support for setting the encoding and nencoding parameters when
1025 :meth:`creating a connection <cx_Oracle.Connection>` and added support for
1026 setting these when creating a session pool. These can now be used instead
1027 of setting the environment variables NLS_LANG and NLS_NCHAR.
1028 #) Use None instead of 0 for items in the :attr:`Cursor.description` attribute
1029 that do not have any validity.
1030 #) Changed driver name to match informal driver name standard used by Oracle
1031 for other drivers.
1032 #) Add check for maximum of 10,000 parameters when calling a stored procedure
1033 or function in order to prevent a possible improper memory access from
1034 taking place.
1035 #) Removed -mno-cygwin compile flag since it is no longer used in newer
1036 versions of the gcc compiler for Cygwin.
1037 #) Simplified test suite by combining Python 2 and 3 scripts into one script
1038 and separated out 12.1 features into a single script.
1039 #) Updated samples to use code that works on both Python 2 and 3
1040 #) Added support for pickling/unpickling error objects
1041 (`Issue #23 <https://bitbucket.org/anthony_tuininga/cx_oracle/issues/23>`__)
1042 #) Dropped support for callbacks on OCI functions.
1043 #) Removed deprecated types UNICODE, FIXED_UNICODE and LONG_UNICODE (use
1044 NCHAR, FIXED_NCHAR and LONG_NCHAR instead).
1045 #) Increased default array size to 100 (from 50) to match other drivers.
1046 #) Added support for setting the :attr:`~Connection.internal_name` and
1047 :attr:`~Connection.external_name` on the connection directly. The use of
1048 the twophase parameter is now deprecated. Applications should set the
1049 internal_name and external_name attributes directly to a value appropriate
1050 to the application.
1051 #) Added support for using application context when
1052 :meth:`creating a connection <cx_Oracle.Connection>`. This should be used
1053 in preference to the module, action and clientinfo parameters which are now
1054 deprecated.
1055 #) Reworked database change notification and continuous query notification to
1056 more closely align with the PL/SQL implementation and prepare for sending
1057 notifications for AQ messages. The following changes were made:
1058
1059 - added constant :data:`~cx_Oracle.SUBSCR_QOS_BEST_EFFORT` to replace
1060 deprecated constant SUBSCR_CQ_QOS_BEST_EFFORT
1061 - added constant :data:`~cx_Oracle.SUBSCR_QOS_QUERY` to replace
1062 deprecated constant SUBSCR_CQ_QOS_QUERY
1063 - added constant :data:`~cx_Oracle.SUBSCR_QOS_DEREG_NFY` to replace
1064 deprecated constant SUBSCR_QOS_PURGE_ON_NTFN
1065 - added constant :data:`~cx_Oracle.SUBSCR_QOS_ROWIDS` to replace parameter
1066 rowids for method :meth:`Connection.subscribe()`
1067 - deprecated parameter cqqos for method :meth:`Connection.subscribe()`. The
1068 qos parameter should be used instead.
1069 - dropped constants SUBSCR_CQ_QOS_CLQRYCACHE, SUBSCR_QOS_HAREG,
1070 SUBSCR_QOS_MULTICBK, SUBSCR_QOS_PAYLOAD, SUBSCR_QOS_REPLICATE, and
1071 SUBSCR_QOS_SECURE since they were never actually used
1072 #) Deprecated use of the numbersAsStrings attribute on cursors. An output type
1073 handler should be used instead.
1074
1075
1076 Version 5.2.1 (January 2016)
1077 ----------------------------
1078
1079 #) Added support for Python 3.5.
1080 #) Removed password attribute from connection and session pool objects in
1081 order to promote best security practices (if stored in RAM in cleartext it
1082 can be read in process dumps, for example). For those who would like to
1083 retain this feature, a subclass of Connection could be used to store the
1084 password.
1085 #) Added optional parameter externalauth to SessionPool() which enables wallet
1086 based or other external authentication mechanisms to be used.
1087 #) Use the national character set encoding when required (when char set form
1088 is SQLCS_NCHAR); otherwise, the wrong encoding would be used if the
1089 environment variable NLS_NCHAR is set.
1090 #) Added support for binding boolean values to PL/SQL blocks and stored
1091 procedures (available in Oracle 12.1).
1092
1093
1094 Version 5.2 (June 2015)
1095 -----------------------
1096
1097 #) Added support for strings up to 32k characters (new in Oracle 12c).
1098 #) Added support for getting array DML row counts (new in Oracle 12c).
1099 #) Added support for fetching batch errors.
1100 #) Added support for LOB values larger than 4 GB.
1101 #) Added support for connections as SYSASM.
1102 #) Added support for building without any configuration changes to the machine
1103 when using instant client RPMs on Linux.
1104 #) Added types NCHAR, FIXED_NCHAR and LONG_NCHAR to replace the types UNICODE,
1105 FIXED_UNICODE and LONG_UNICODE (which are now deprecated). These types are
1106 available in Python 3 as well so they can be used to specify the use of
1107 NCHAR type fields when binding or using setinputsizes().
1108 #) Fixed binding of booleans in Python 3.x.
1109 #) Test suite now sets NLS_LANG if not already set.
1110 #) Enhanced documentation for connection.action attribute and added note
1111 on cursor.parse() method to make clear that DDL statements are executed
1112 when parsed.
1113 #) Removed remaining remnants of support Oracle 9i.
1114 #) Added __version__ attribute to conform with PEP 396.
1115 #) Ensure that sessions are released to the pool when calling
1116 connection.close()
1117 (`Issue #2 <https://bitbucket.org/anthony_tuininga/cx_oracle/issue/2>`__)
1118 #) Fixed handling of datetime intervals
1119 (`Issue #7 <https://bitbucket.org/anthony_tuininga/cx_oracle/issue/7>`__)
1120
1121
1122 Version 5.1.3 (May 2014)
1123 ------------------------
1124
1125 #) Added support for Oracle 12c.
1126 #) Added support for Python 3.4.
1127 #) Added support for query result set change notification. Thanks to Glen
1128 Walker for the patch.
1129 #) Ensure that in Python 3.x that NCHAR and NVARCHAR2 and NCLOB columns are
1130 retrieved properly without conversion issues. Thanks to Joakim Andersson
1131 for pointing out the issue and the possible solution.
1132 #) Fix bug when an exception is caught and then another exception is raised
1133 while handling that exception in Python 3.x. Thanks to Boris Dzuba for
1134 pointing out the issue and providing a test case.
1135 #) Enhance performance returning integers between 10 and 18 digits on 64-bit
1136 platforms that support it. Thanks for Shai Berger for the initial patch.
1137 #) Fixed two memory leaks.
1138 #) Fix to stop current_schema from throwing a MemoryError on 64-bit platforms
1139 on occasion. Thanks to Andrew Horton for the fix.
1140 #) Class name of cursors changed to real name cx_Oracle.Cursor.
1141
1142
1143 Version 5.1.2 (July 2012)
1144 -------------------------
1145
1146 #) Added support for LONG_UNICODE which is a type used to handle long unicode
1147 strings. These are not explicitly supported in Oracle but can be used to
1148 bind to NCLOB, for example, without getting the error "unimplemented or
1149 unreasonable conversion requested".
1150 #) Set the row number in a cursor when executing PL/SQL blocks as requested
1151 by Robert Ritchie.
1152 #) Added support for setting the module, action and client_info attributes
1153 during connection so that logon triggers will see the supplied values, as
1154 requested by Rodney Barnett.
1155
1156
1157 Version 5.1.1 (October 2011)
1158 ----------------------------
1159
1160 #) Simplify management of threads for callbacks performed by database change
1161 notification and eliminate a crash that occurred under high load in
1162 certain situations. Thanks to Calvin S. for noting the issue and suggesting
1163 a solution and testing the patch.
1164 #) Force server detach on close so that the connection is completely closed
1165 and not just the session as before.
1166 #) Force use of OCI_UTF16ID for NCLOBs as using the default character set
1167 would result in ORA-03127 with Oracle 11.2.0.2 and UTF8 character set.
1168 #) Avoid attempting to clear temporary LOBs a second time when destroying the
1169 variable as in certain situations this results in spurious errors.
1170 #) Added additional parameter service_name to makedsn() which can be used to
1171 use the service_name rather than the SID in the DSN string that is
1172 generated.
1173 #) Fix cursor description in test suite to take into account the number of
1174 bytes per character.
1175 #) Added tests for NCLOBS to the test suite.
1176 #) Removed redundant code in setup.py for calculating the library path.
1177
1178
1179 Version 5.1 (March 2011)
1180 ------------------------
1181
1182 #) Remove support for UNICODE mode and permit Unicode to be passed through in
1183 everywhere a string may be passed in. This means that strings will be
1184 passed through to Oracle using the value of the NLS_LANG environment
1185 variable in Python 3.x as well. Doing this eliminated a bunch of problems
1186 that were discovered by using UNICODE mode and also removed an unnecessary
1187 restriction in Python 2.x that Unicode could not be used in connect strings
1188 or SQL statements, for example.
1189 #) Added support for creating an empty object variable via a named type, the
1190 first step to adding full object support.
1191 #) Added support for Python 3.2.
1192 #) Account for lib64 used on x86_64 systems. Thanks to Alex Wood for supplying
1193 the patch.
1194 #) Clear up potential problems when calling cursor.close() ahead of the
1195 cursor being freed by going out of scope.
1196 #) Avoid compilation difficulties on AIX5 as OCIPing does not appear to be
1197 available on that platform under Oracle 10g Release 2. Thanks to
1198 Pierre-Yves Fontaniere for the patch.
1199 #) Free temporary LOBs prior to each fetch in order to avoid leaking them.
1200 Thanks to Uwe Hoffmann for the initial patch.
1201
1202
1203 Version 5.0.4 (July 2010)
1204 -------------------------
1205
1206 #) Added support for Python 2.7.
1207 #) Added support for new parameter (port) for subscription() call which allows
1208 the client to specify the listening port for callback notifications from
1209 the database server. Thanks to Geoffrey Weber for the initial patch.
1210 #) Fixed compilation under Oracle 9i.
1211 #) Fixed a few error messages.
1212
1213
1214 Version 5.0.3 (February 2010)
1215 -----------------------------
1216
1217 #) Added support for 64-bit Windows.
1218 #) Added support for Python 3.1 and dropped support for Python 3.0.
1219 #) Added support for keyword parameters in cursor.callproc() and
1220 cursor.callfunc().
1221 #) Added documentation for the UNICODE and FIXED_UNICODE variable types.
1222 #) Added extra link arguments required for Mac OS X as suggested by Jason
1223 Woodward.
1224 #) Added additional error codes to the list of error codes that raise
1225 OperationalError rather than DatabaseError.
1226 #) Fixed calculation of display size for strings with national database
1227 character sets that are not the default AL16UTF16.
1228 #) Moved the resetting of the setinputsizes flag before the binding takes
1229 place so that if an error takes place and a new statement is prepared
1230 subsequently, spurious errors will not occur.
1231 #) Fixed compilation with Oracle 10g Release 1.
1232 #) Tweaked documentation based on feedback from a number of people.
1233 #) Added support for running the test suite using "python setup.py test"
1234 #) Added support for setting the CLIENT_IDENTIFIER value in the v$session
1235 table for connections.
1236 #) Added exception when attempting to call executemany() with arrays which is
1237 not supported by the OCI.
1238 #) Fixed bug when converting from decimal would result in OCI-22062 because
1239 the locale decimal point was not a period. Thanks to Amaury Forgeot d'Arc
1240 for the solution to this problem.
1241
1242
1243 Version 5.0.2 (May 2009)
1244 ------------------------
1245
1246 #) Fix creation of temporary NCLOB values and the writing of NCLOB values in
1247 non Unicode mode.
1248 #) Re-enabled parsing of non select statements as requested by Roy Terrill.
1249 #) Implemented a parse error offset as requested by Catherine Devlin.
1250 #) Removed lib subdirectory when forcing RPATH now that the library directory
1251 is being calculated exactly in setup.py.
1252 #) Added an additional cast in order to support compiling by Microsoft
1253 Visual C++ 2008 as requested by Marco de Paoli.
1254 #) Added additional include directory to setup.py in order to support
1255 compiling by Microsoft Visual Studio was requested by Jason Coombs.
1256 #) Fixed a few documentation issues.
1257
1258
1259 Version 5.0.1 (February 2009)
1260 -----------------------------
1261
1262 #) Added support for database change notification available in Oracle 10g
1263 Release 2 and higher.
1264 #) Fix bug where NCLOB data would be corrupted upon retrieval (non Unicode
1265 mode) or would generate exception ORA-24806 (LOB form mismatch). Oracle
1266 insists upon differentiating between CLOB and NCLOB no matter which
1267 character set is being used for retrieval.
1268 #) Add new attributes size, bufferSize and numElements to variable objects,
1269 deprecating allocelems (replaced by numElements) and maxlength (replaced
1270 by bufferSize)
1271 #) Avoid increasing memory allocation for strings when using variable width
1272 character sets and increasing the number of elements in a variable during
1273 executemany().
1274 #) Tweaked code in order to ensure that cx_Oracle can compile with Python
1275 3.0.1.
1276
1277
1278 Version 5.0 (December 2008)
1279 ---------------------------
1280
1281 #) Added support for Python 3.0 with much help from Amaury Forgeot d'Arc.
1282 #) Removed support for Python 2.3 and Oracle 8i.
1283 #) Added support for full unicode mode in Python 2.x where all strings are
1284 passed in and returned as unicode (module must be built in this mode)
1285 rather than encoded strings
1286 #) nchar and nvarchar columns now return unicode instead of encoded strings
1287 #) Added support for an output type handler and/or an input type handler to be
1288 specified at the connection and cursor levels.
1289 #) Added support for specifying both input and output converters for variables
1290 #) Added support for specifying the array size of variables that are created
1291 using the cursor.var() method
1292 #) Added support for events mode and database resident connection pooling
1293 (DRCP) in Oracle 11g.
1294 #) Added support for changing the password during construction of a new
1295 connection object as well as after the connection object has been created
1296 #) Added support for the interval day to second data type in Oracle,
1297 represented as datetime.timedelta objects in Python.
1298 #) Added support for getting and setting the current_schema attribute for a
1299 session
1300 #) Added support for proxy authentication in session pools as requested by
1301 Michael Wegrzynek (and thanks for the initial patch as well).
1302 #) Modified connection.prepare() to return a boolean indicating if a
1303 transaction was actually prepared in order to avoid the error ORA-24756
1304 (transaction does not exist).
1305 #) Raise a cx_Oracle.Error instance rather than a string for column
1306 truncation errors as requested by Helge Tesdal.
1307 #) Fixed handling of environment handles in session pools in order to allow
1308 session pools to fetch objects without exceptions taking place.
1309
1310
1311 Version 4.4.1 (October 2008)
1312 ----------------------------
1313
1314 #) Make the bind variables and fetch variables accessible although they need
1315 to be treated carefully since they are used internally; support added for
1316 forward compatibility with version 5.x.
1317 #) Include the "cannot insert null value" in the list of errors that are
1318 treated as integrity errors as requested by Matt Boersma.
1319 #) Use a cx_Oracle.Error instance rather than a string to hold the error when
1320 truncation (ORA-1406) takes place as requested by Helge Tesdal.
1321 #) Added support for fixed char, old style varchar and timestamp attribute
1322 values in objects.
1323 #) Tweaked setup.py to check for the Oracle version up front rather than
1324 during the build in order to produce more meaningful errors and simplify
1325 the code.
1326 #) In setup.py added proper detection for the instant client on Mac OS X as
1327 recommended by Martijn Pieters.
1328 #) In setup.py, avoided resetting the extraLinkArgs on Mac OS X as doing so
1329 prevents simple modification where desired as expressed by Christian
1330 Zagrodnick.
1331 #) Added documentation on exception handling as requested by Andreas Mock, who
1332 also graciously provided an initial patch.
1333 #) Modified documentation indicating that the password attribute on connection
1334 objects can be written.
1335 #) Added documentation warning that parameters not passed in during subsequent
1336 executions of a statement will retain their original values as requested by
1337 Harald Armin Massa.
1338 #) Added comments indicating that an Oracle client is required since so many
1339 people find this surprising.
1340 #) Removed all references to Oracle 8i from the documentation and version 5.x
1341 will eliminate all vestiges of support for this version of the Oracle
1342 client.
1343 #) Added additional link arguments for Cygwin as requested by Rob Gillen.
1344
1345
1346 Version 4.4 (June 2008)
1347 -----------------------
1348
1349 #) Fix setup.py to handle the Oracle instant client and Oracle XE on both
1350 Linux and Windows as pointed out by many. Thanks also to the many people
1351 who also provided patches.
1352 #) Set the default array size to 50 instead of 1 as the DB API suggests
1353 because the performance difference is so drastic and many people have
1354 recommended that the default be changed.
1355 #) Added Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS around each blocking
1356 call for LOBs as requested by Jason Conroy who also provided an initial
1357 patch and performed a number of tests that demonstrate the new code is much
1358 more responsive.
1359 #) Add support for acquiring cursor.description after a parse.
1360 #) Defer type assignment when performing executemany() until the last possible
1361 moment if the value being bound in is null as suggested by Dragos Dociu.
1362 #) When dropping a connection from the pool, ignore any errors that occur
1363 during the rollback; unfortunately, Oracle decides to commit data even when
1364 dropping a connection from the pool instead of rolling it back so the
1365 attempt still has to be made.
1366 #) Added support for setting CLIENT_DRIVER in V$SESSION_CONNECT_INFO in Oracle
1367 11g and higher.
1368 #) Use cx_Oracle.InterfaceError rather than the builtin RuntimeError when
1369 unable to create the Oracle environment object as requested by Luke Mewburn
1370 since the error is specific to Oracle and someone attempting to catch any
1371 exception cannot simply use cx_Oracle.Error.
1372 #) Translated some error codes to OperationalError as requested by Matthew
1373 Harriger; translated if/elseif/else logic to switch statement to make it
1374 more readable and to allow for additional translation if desired.
1375 #) Transformed documentation to new format using restructured text. Thanks to
1376 Waldemar Osuch for contributing the initial draft of the new documentation.
1377 #) Allow the password to be overwritten by a new value as requested by Alex
1378 VanderWoude; this value is retained as a convenience to the user and not
1379 used by anything in the module; if changed externally it may be convenient
1380 to keep this copy up to date.
1381 #) Cygwin is on Windows so should be treated in the same way as noted by
1382 Matthew Cahn.
1383 #) Add support for using setuptools if so desired as requested by Shreya
1384 Bhatt.
1385 #) Specify that the version of Oracle 10 that is now primarily used is 10.2,
1386 not 10.1.
1387
1388
1389 Version 4.3.3 (October 2007)
1390 ----------------------------
1391
1392 #) Added method ping() on connections which can be used to test whether or not
1393 a connection is still active (available in Oracle 10g R2).
1394 #) Added method cx_Oracle.clientversion() which returns a 5-tuple giving the
1395 version of the client that is in use (available in Oracle 10g R2).
1396 #) Added methods startup() and shutdown() on connections which can be used to
1397 startup and shutdown databases (available in Oracle 10g R2).
1398 #) Added support for Oracle 11g.
1399 #) Added samples directory which contains a handful of scripts containing
1400 sample code for more advanced techniques. More will follow in future
1401 releases.
1402 #) Prevent error "ORA-24333: zero iteration count" when calling executemany()
1403 with zero rows as requested by Andreas Mock.
1404 #) Added methods __enter__() and __exit__() on connections to support using
1405 connections as context managers in Python 2.5 and higher. The context
1406 managed is the transaction state. Upon exit the transaction is either
1407 rolled back or committed depending on whether an exception took place or
1408 not.
1409 #) Make the search for the lib32 and lib64 directories automatic for all
1410 platforms.
1411 #) Tweak the setup configuration script to include all of the metadata and
1412 allow for building the module within another setup configuration script
1413 #) Include the Oracle version in addition to the Python version in the build
1414 directories that are created and in the names of the binary packages that
1415 are created.
1416 #) Remove unnecessary dependency on win32api to build module on Windows.
1417
1418
1419 Version 4.3.2 (August 2007)
1420 ---------------------------
1421
1422 #) Added methods open(), close(), isopen() and getchunksize() in order to
1423 improve performance of reading/writing LOB values in chunks.
1424 #) Fixed support for native doubles and floats in Oracle 10g; added new type
1425 NATIVE_FLOAT to allow specification of a variable of that specific type
1426 where desired. Thanks to D.R. Boxhoorn for pointing out the fact that this
1427 was not working properly when the arraysize was anything other than 1.
1428 #) When calling connection.begin(), only create a new transaction handle if
1429 one is not already associated with the connection. Thanks to Andreas Mock
1430 for discovering this and for Amaury Forgeot d'Arc for diagnosing the
1431 problem and pointing the way to a solution.
1432 #) Added attribute cursor.rowfactory which allows a method to be called for
1433 each row that is returned; this is about 20% faster than calling the method
1434 in Python using the idiom [method(\*r) for r in cursor].
1435 #) Attempt to locate an Oracle installation by looking at the PATH if the
1436 environment variable ORACLE_HOME is not set; this is of primary use on
1437 Windows where this variable should not normally be set.
1438 #) Added support for autocommit mode as requested by Ian Kelly.
1439 #) Added support for connection.stmtcachesize which allows for both reading
1440 and writing the size of the statement cache size. This parameter can make a
1441 huge difference with the length of time taken to prepare statements. Added
1442 support for setting the statement tag when preparing a statement. Both of
1443 these were requested by Bjorn Sandberg who also provided an initial patch.
1444 #) When copying the value of a variable, copy the return code as well.
1445
1446
1447 Version 4.3.1 (April 2007)
1448 --------------------------
1449
1450 #) Ensure that if the client buffer size exceeds 4000 bytes that the server
1451 buffer size does not as strings may only contain 4000 bytes; this allows
1452 handling of multibyte character sets on the server as well as the client.
1453 #) Added support for using buffer objects to populate binary data and made the
1454 Binary() constructor the buffer type as requested by Ken Mason.
1455 #) Fix potential crash when using full optimization with some compilers.
1456 Thanks to Aris Motas for noticing this and providing the initial patch and
1457 to Amaury Forgeot d'Arc for providing an even simpler solution.
1458 #) Pass the correct charset form in to the write call in order to support
1459 writing to national character set LOB values properly. Thanks to Ian Kelly
1460 for noticing this discrepancy.
1461
1462
1463 Version 4.3 (March 2007)
1464 ------------------------
1465
1466 #) Added preliminary support for fetching Oracle objects (SQL types) as
1467 requested by Kristof Beyls (who kindly provided an initial patch).
1468 Additional work needs to be done to support binding and updating objects
1469 but the basic structure is now in place.
1470 #) Added connection.maxBytesPerCharacter which indicates the maximum number of
1471 bytes each character can use; use this value to also determine the size of
1472 local buffers in order to handle discrepancies between the client character
1473 set and the server character set. Thanks to Andreas Mock for providing the
1474 initial patch and working with me to resolve this issue.
1475 #) Added support for querying native floats in Oracle 10g as requested by
1476 Danny Boxhoorn.
1477 #) Add support for temporary LOB variables created via PL/SQL instead of only
1478 directly by cx_Oracle; thanks to Henning von Bargen for discovering this
1479 problem.
1480 #) Added support for specifying variable types using the builtin types int,
1481 float, str and datetime.date which allows for finer control of what type of
1482 Python object is returned from cursor.callfunc() for example.
1483 #) Added support for passing booleans to callproc() and callfunc() as
1484 requested by Anana Aiyer.
1485 #) Fixed support for 64-bit environments in Python 2.5.
1486 #) Thanks to Filip Ballegeer and a number of his co-workers, an intermittent
1487 crash was tracked down; specifically, if a connection is closed, then the
1488 call to OCIStmtRelease() will free memory twice. Preventing the call when
1489 the connection is closed solves the problem.
1490
1491
1492 Version 4.2.1 (September 2006)
1493 ------------------------------
1494
1495 #) Added additional type (NCLOB) to handle CLOBs that use the national
1496 character set as requested by Chris Dunscombe.
1497 #) Added support for returning cursors from functions as requested by Daniel
1498 Steinmann.
1499 #) Added support for getting/setting the "get" mode on session pools as
1500 requested by Anand Aiyer.
1501 #) Added support for binding subclassed cursors.
1502 #) Fixed binding of decimal objects with absolute values less than 0.1.
1503
1504
1505 Version 4.2 (July 2006)
1506 -----------------------
1507
1508 #) Added support for parsing an Oracle statement as requested by Patrick
1509 Blackwill.
1510 #) Added support for BFILEs at the request of Matthew Cahn.
1511 #) Added support for binding decimal.Decimal objects to cursors.
1512 #) Added support for reading from NCLOBs as requested by Chris Dunscombe.
1513 #) Added connection attributes encoding and nencoding which return the IANA
1514 character set name for the character set and national character set in use
1515 by the client.
1516 #) Rework module initialization to use the techniques recommended by the
1517 Python documentation as one user was experiencing random segfaults due
1518 to the use of the module dictionary after the initialization was complete.
1519 #) Removed support for the OPT_Threading attribute. Use the threaded keyword
1520 when creating connections and session pools instead.
1521 #) Removed support for the OPT_NumbersAsStrings attribute. Use the
1522 numbersAsStrings attribute on cursors instead.
1523 #) Use type long rather than type int in order to support long integers on
1524 64-bit machines as reported by Uwe Hoffmann.
1525 #) Add cursor attribute "bindarraysize" which is defaulted to 1 and is used
1526 to determine the size of the arrays created for bind variables.
1527 #) Added repr() methods to provide something a little more useful than the
1528 standard type name and memory address.
1529 #) Added keyword parameter support to the functions that imply such in the
1530 documentation as requested by Harald Armin Massa.
1531 #) Treat an empty dictionary passed through to cursor.execute() as keyword
1532 parameters the same as if no keyword parameters were specified at all, as
1533 requested by Fabien Grumelard.
1534 #) Fixed memory leak when a LOB read would fail.
1535 #) Set the LDFLAGS value in the environment rather than directly in the
1536 setup.py file in order to satisfy those who wish to enable the use of
1537 debugging symbols.
1538 #) Use __DATE__ and __TIME__ to determine the date and time of the build
1539 rather than passing it through directly.
1540 #) Use Oracle types and add casts to reduce warnings as requested by Amaury
1541 Forgeot d'Arc.
1542 #) Fixed typo in error message.
1543
1544
1545 Version 4.1.2 (December 2005)
1546 -----------------------------
1547
1548 #) Restore support of Oracle 9i features when using the Oracle 10g client.
1549
1550
1551 Version 4.1.1 (December 2005)
1552 -----------------------------
1553
1554 #) Add support for dropping a connection from a session pool.
1555 #) Add support for write only attributes "module", "action" and "clientinfo"
1556 which work only in Oracle 10g as requested by Egor Starostin.
1557 #) Add support for pickling database errors.
1558 #) Use the previously created bind variable as a template if available when
1559 creating a new variable of a larger size. Thanks to Ted Skolnick for the
1560 initial patch.
1561 #) Fixed tests to work properly in the Python 2.4 environment where dates and
1562 timestamps are different Python types. Thanks to Henning von Bargen for
1563 pointing this out.
1564 #) Added additional directories to search for include files and libraries in
1565 order to better support the Oracle 10g instant client.
1566 #) Set the internal fetch number to 0 in order to satisfy very picky source
1567 analysis tools as requested by Amaury Fogeot d'Arc.
1568 #) Improve the documentation for building and installing the module from
1569 source as some people are unaware of the standard methods for building
1570 Python modules using distutils.
1571 #) Added note in the documentation indicating that the arraysize attribute
1572 can drastically affect performance of queries since this seems to be a
1573 common misunderstanding of first time users of cx_Oracle.
1574 #) Add a comment indicating that on HP-UX Itanium with Oracle 10g the library
1575 ttsh10 must also be linked against. Thanks to Bernard Delmee for the
1576 information.
1577
1578
1579 Version 4.1 (January 2005)
1580 --------------------------
1581
1582 #) Fixed bug where subclasses of Cursor do not pass the connection in the
1583 constructor causing a segfault.
1584 #) DDL statements must be reparsed before execution as noted by Mihai
1585 Ibanescu.
1586 #) Add support for setting input sizes by position.
1587 #) Fixed problem with catching an exception during execute and then still
1588 attempting to perform a fetch afterwards as noted by Leith Parkin.
1589 #) Rename the types so that they can be pickled and unpickled. Thanks to Harri
1590 Pasanen for pointing out the problem.
1591 #) Handle invalid NLS_LANG setting properly (Oracle seems to like to provide a
1592 handle back even though it is invalid) and determine the number of bytes
1593 per character in order to allow for proper support in the future of
1594 multibyte and variable width character sets.
1595 #) Remove date checking from the native case since Python already checks that
1596 dates are valid; enhance error message when invalid dates are encountered
1597 so that additional processing can be done.
1598 #) Fix bug executing SQL using numeric parameter names with predefined
1599 variables (such as what takes place when calling stored procedures with out
1600 parameters).
1601 #) Add support for reading CLOB values using multibyte or variable length
1602 character sets.
1603
1604
1605 Version 4.1 beta 1 (September 2004)
1606 -----------------------------------
1607
1608 #) Added support for Python 2.4. In Python 2.4, the datetime module is used
1609 for both binding and fetching of date and timestamp data. In Python 2.3,
1610 objects from the datetime module can be bound but the internal datetime
1611 objects will be returned from queries.
1612 #) Added pickling support for LOB and datetime data.
1613 #) Fully qualified the table name that was missing in an alter table
1614 statement in the setup test script as noted by Marc Gehling.
1615 #) Added a section allowing for the setting of the RPATH linker directive in
1616 setup.py as requested by Iustin Pop.
1617 #) Added code to raise a programming error exception when an attempt is made
1618 to access a LOB locator variable in a subsequent fetch.
1619 #) The username, password and dsn (tnsentry) are stored on the connection
1620 object when specified, regardless of whether or not a standard connection
1621 takes place.
1622 #) Added additional module level constant called "LOB" as requested by Joseph
1623 Canedo.
1624 #) Changed exception type to IntegrityError for constraint violations as
1625 requested by Joseph Canedo.
1626 #) If scale and precision are not specified, an attempt is made to return a
1627 long integer as requested by Joseph Canedo.
1628 #) Added workaround for Oracle bug which returns an invalid handle when the
1629 prepare call fails. Thanks to [email protected] for providing the code that
1630 demonstrated the problem.
1631 #) The cursor method arrayvar() will now accept the actual list so that it is
1632 not necessary to call cursor.arrayvar() followed immediately by
1633 var.setvalue().
1634 #) Fixed bug where attempts to execute the statement "None" with bind
1635 variables would cause a segmentation fault.
1636 #) Added support for binding by position (paramstyle = "numeric").
1637 #) Removed memory leak created by calls to OCIParamGet() which were not
1638 mirrored by calls to OCIDescriptorFree(). Thanks to Mihai Ibanescu for
1639 pointing this out and providing a patch.
1640 #) Added support for calling cursor.executemany() with statement None
1641 implying that the previously prepared statement ought to be executed.
1642 Thanks to Mihai Ibanescu for providing a patch.
1643 #) Added support for rebinding variables when a subsequent call to
1644 cursor.executemany() uses a different number of rows. Thanks to Mihai
1645 Ibanescu for supplying a patch.
1646 #) The microseconds are now displayed in datetime variables when nonzero
1647 similar to method used in the datetime module.
1648 #) Added support for binary_float and binary_double columns in Oracle 10g.
1649
1650
1651 Version 4.0.1 (February 2004)
1652 -----------------------------
1653
1654 #) Fixed bugs on 64-bit platforms that caused segmentation faults and bus
1655 errors in session pooling and determining the bind variables associated
1656 with a statement.
1657 #) Modified test suite so that 64-bit platforms are tested properly.
1658 #) Added missing commit statements in the test setup scripts. Thanks to Keith
1659 Lyon for pointing this out.
1660 #) Fix setup.py for Cygwin environments. Thanks to Doug Henderson for
1661 providing the necessary fix.
1662 #) Added support for compiling cx_Oracle without thread support. Thanks to
1663 Andre Reitz for pointing this out.
1664 #) Added support for a new keyword parameter called threaded on connections
1665 and session pools. This parameter defaults to False and indicates whether
1666 threaded mode ought to be used. It replaces the module level attribute
1667 OPT_Threading although examining the attribute will be retained until the
1668 next release at least.
1669 #) Added support for a new keyword parameter called twophase on connections.
1670 This parameter defaults to False and indicates whether support for two
1671 phase (distributed or global) transactions ought to be present. Note that
1672 support for distributed transactions is buggy when crossing major version
1673 boundaries (Oracle 8i to Oracle 9i for example).
1674 #) Ensure that the rowcount attribute is set properly when an exception is
1675 raised during execution. Thanks to Gary Aviv for pointing out this problem
1676 and its solution.
1677
1678
1679 Version 4.0 (December 2003)
1680 ---------------------------
1681
1682 #) Added support for subclassing connections, cursors and session pools. The
1683 changes involved made it necessary to drop support for Python 2.1 and
1684 earlier although a branch exists in CVS to allow for support of Python 2.1
1685 and earlier if needed.
1686 #) Connections and session pools can now be created with keyword parameters,
1687 not just sequential parameters.
1688 #) Queries now return integers whenever possible and long integers if the
1689 number will overflow a simple integer. Floats are only returned when it is
1690 known that the number is a floating point number or the integer conversion
1691 fails.
1692 #) Added initial support for user callbacks on OCI functions. See the
1693 documentation for more details.
1694 #) Add support for retrieving the bind variable names associated with a
1695 cursor with a new method bindnames().
1696 #) Add support for temporary LOB variables. This means that setinputsizes()
1697 can be used with the values CLOB and BLOB to create these temporary LOB
1698 variables and allow for the equivalent of empty_clob() and empty_blob()
1699 since otherwise Oracle will treat empty strings as NULL values.
1700 #) Automatically switch to long strings when the data size exceeds the
1701 maximum string size that Oracle allows (4000 characters) and raise an
1702 error if an attempt is made to set a string variable to a size that it
1703 does not support. This avoids truncation errors as reported by Jon Franz.
1704 #) Add support for global (distributed) transactions and two phase commit.
1705 #) Force the NLS settings for the session so that test tables are populated
1706 correctly in all circumstances; problems were noted by Ralf Braun and
1707 Allan Poulsen.
1708 #) Display error messages using the environment handle when the error handle
1709 has not yet been created; this provides better error messages during this
1710 rather rare situation.
1711 #) Removed memory leak in callproc() that was reported by Todd Whiteman.
1712 #) Make consistent the calls to manipulate memory; otherwise segfaults can
1713 occur when the pymalloc option is used, as reported by Matt Hoskins.
1714 #) Force a rollback when a session is released back to the session pool.
1715 Apparently the connections are not as stateless as Oracle's documentation
1716 suggests and this makes the logic consistent with normal connections.
1717 #) Removed module method attach(). This can be replaced with a call to
1718 Connection(handle=) if needed.
1719
1720
1721 Version 3.1 (August 2003)
1722 -------------------------
1723
1724 #) Added support for connecting with SYSDBA and SYSOPER access which is
1725 needed for connecting as sys in Oracle 9i.
1726 #) Only check the dictionary size if the variable is not NULL; otherwise, an
1727 error takes place which is not caught or cleared; this eliminates a
1728 spurious "Objects/dictobject.c:1258: bad argument to internal function" in
1729 Python 2.3.
1730 #) Add support for session pooling. This is only support for Oracle 9i but
1731 is amazingly fast -- about 100 times faster than connecting.
1732 #) Add support for statement caching when pooling sessions, this reduces the
1733 parse time considerably. Unfortunately, the Oracle OCI does not allow this
1734 to be easily turned on for normal sessions.
1735 #) Add method trim() on CLOB and BLOB variables for trimming the size.
1736 #) Add support for externally identified users; to use this feature leave the
1737 username and password fields empty when connecting.
1738 #) Add method cancel() on connection objects to cancel long running queries.
1739 Note that this only works on non-Windows platforms.
1740 #) Add method callfunc() on cursor objects to allow calling a function
1741 without using an anonymous PL/SQL block.
1742 #) Added documentation on objects that were not documented. At this point all
1743 objects, methods and constants in cx_Oracle have been documented.
1744 #) Added support for timestamp columns in Oracle 9i.
1745 #) Added module level method makedsn() which creates a data source name given
1746 the host, port and SID.
1747 #) Added constant "buildtime" which is the time when the module was built as
1748 an additional means of identifying the build that is in use.
1749 #) Binding a value that is incompatible to the previous value that was bound
1750 (data types do not match or array size is larger) will now result in a
1751 new bind taking place. This is more consistent with the DB API although
1752 it does imply a performance penalty when used.
1753
1754
1755 Version 3.0a (June 2003)
1756 ------------------------
1757
1758 #) Fixed bug where zero length PL/SQL arrays were being mishandled
1759 #) Fixed support for the data type "float" in Oracle; added one to the
1760 display size to allow for the sign of the number, if necessary; changed
1761 the display size of unconstrained numbers to 127, which is the largest
1762 number that Oracle can handle
1763 #) Added support for retrieving the description of a bound cursor before
1764 fetching it
1765 #) Fixed a couple of build issues on Mac OS X, AIX and Solaris (64-bit)
1766 #) Modified documentation slightly based on comments from several people
1767 #) Included files in MANIFEST that are needed to generate the binaries
1768 #) Modified test suite to work within the test environment at Computronix
1769 as well as within the packages that are distributed
1770
1771
1772 Version 3.0 (March 2003)
1773 ------------------------
1774
1775 #) Removed support for connection to Oracle7 databases; it is entirely
1776 possible that it will still work but I no longer have any way of testing
1777 and Oracle has dropped any meaningful support for Oracle7 anyway
1778 #) Fetching of strings is now done with predefined memory areas rather than
1779 dynamic memory areas; dynamic fetching of strings was causing problems
1780 with Oracle 9i in some instances and databases using a different character
1781 set other than US ASCII
1782 #) Fixed bug where segfault would occur if the '/' character preceded the '@'
1783 character in a connect string
1784 #) Added two new cursor methods var() and arrayvar() in order to eliminate
1785 the need for setinputsizes() when defining PL/SQL arrays and as a generic
1786 method of acquiring bind variables directly when needed
1787 #) Fixed support for binding cursors and added support for fetching cursors
1788 (these are known as ref cursors in PL/SQL).
1789 #) Eliminated discrepancy between the array size used internally and the
1790 array size specified by the interface user; this was done earlier to avoid
1791 bus errors on 64-bit platforms but another way has been found to get
1792 around that issue and a number of people were getting confused because of
1793 the discrepancy
1794 #) Added support for the attribute "connection" on cursors, an optional
1795 DB API extension
1796 #) Added support for passing a dictionary as the second parameter for the
1797 cursor.execute() method in order to comply with the DB API more closely;
1798 the method of passing parameters with keyword parameters is still supported
1799 and is in fact preferred
1800 #) Added support for the attribute "statement" on cursors which is a
1801 reference to the last SQL statement prepared or executed
1802 #) Added support for passing any sequence to callproc() rather than just
1803 lists as before
1804 #) Fixed bug where segfault would occur if the array size was changed after
1805 the cursor was executed but before it was fetched
1806 #) Ignore array size when performing executemany() and use the length of the
1807 list of parameters instead
1808 #) Rollback when connection is closed or destroyed to follow DB API rather
1809 than use the Oracle default (which is commit)
1810 #) Added check for array size too large causing an integer overflow
1811 #) Added support for iterators for Python 2.2 and above
1812 #) Added test suite based on PyUnitTest
1813 #) Added documentation in HTML format similar to the documentation for the
1814 core Python library
1815
1816
1817 Version 2.5a (August 2002)
1818 --------------------------
1819
1820 #) Fix problem with Oracle 9i and retrieving strings; it seems that Oracle 9i
1821 uses the correct method for dynamic callback but Oracle 8i will not work
1822 with that method so an #ifdef was added to check for the existence of an
1823 Oracle 9i feature; thanks to Paul Denize for discovering this problem
1824
1825
1826 Version 2.5 (July 2002)
1827 -----------------------
1828
1829 #) Added flag OPT_NoOracle7 which, if set, assumes that connections are being
1830 made to Oracle8 or higher databases; this allows for eliminating the
1831 overhead in performing this check at connect time
1832 #) Added flag OPT_NumbersAsStrings which, if set, returns all numbers as
1833 strings rather than integers or floats; this flag is used when defined
1834 variables are created (during select statements only)
1835 #) Added flag OPT_Threading which, if set, uses OCI threading mode; there is a
1836 significant performance degradation in this mode (about 15-20%) but it does
1837 allow threads to share connections (threadsafety level 2 according to the
1838 Python Database API 2.0); note that in order to support this, Oracle 8i or
1839 higher is now required
1840 #) Added Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS pairs where
1841 applicable to support threading during blocking OCI calls
1842 #) Added global method attach() to cx_Oracle to support attaching to an
1843 existing database handle (as provided by PowerBuilder, for example)
1844 #) Eliminated the cursor method fetchbinds() which was used for returning the
1845 list of bind variables after execution to get the values of out variables;
1846 the cursor method setinputsizes() was modified to return the list of bind
1847 variables and the cursor method execute() was modified to return the list
1848 of defined variables in the case of a select statement being executed;
1849 these variables have three methods available to them: getvalue([<pos>]) to
1850 get the value of a variable, setvalue(<pos>, <value>) to set its value and
1851 copy(<var>, <src_pos>, <targ_pos>) to copy the value from a variable in a
1852 more efficient manner than setvalue(getvalue())
1853 #) Implemented cursor method executemany() which expects a list of
1854 dictionaries for the parameters
1855 #) Implemented cursor method callproc()
1856 #) Added cursor method prepare() which parses (prepares) the statement for
1857 execution; subsequent execute() or executemany() calls can pass None as the
1858 statement which will imply use of the previously prepared statement; used
1859 for high performance only
1860 #) Added cursor method fetchraw() which will perform a raw fetch of the cursor
1861 returning the number of rows thus fetched; this is used to avoid the
1862 overhead of generating result sets; used for high performance only
1863 #) Added cursor method executemanyprepared() which is identical to the method
1864 executemany() except that it takes a single parameter which is the number
1865 of times to execute a previously prepared statement and it assumes that the
1866 bind variables already have their values set; used for high performance
1867 only
1868 #) Added support for rowid being returned in a select statement
1869 #) Added support for comparing dates returned by cx_Oracle
1870 #) Integrated patch from Andre Reitz to set the null ok flag in the
1871 description attribute of the cursor
1872 #) Integrated patch from Andre Reitz to setup.py to support compilation with
1873 Python 1.5
1874 #) Integrated patch from Benjamin Kearns to setup.py to support compilation
1875 on Cygwin
1876
1877
1878 Version 2.4 (January 2002)
1879 --------------------------
1880
1881 #) String variables can now be made any length (previously restricted to the
1882 64K limit imposed by Oracle for default binding); use the type
1883 cx_Oracle.LONG_STRING as the parameter to setinputsizes() for binding in
1884 string values larger than 4000 bytes.
1885 #) Raw and long raw columns are now supported; use the types cx_Oracle.BINARY
1886 and cx_Oracle.LONG_BINARY as the parameter to setinputsizes() for binding
1887 in values of these types.
1888 #) Functions DateFromTicks(), TimeFromTicks() and TimestampFromTicks()
1889 are now implemented.
1890 #) Function cursor.setoutputsize() implemented
1891 #) Added the ability to bind arrays as out parameters to procedures; use the
1892 format [cx_Oracle.<DataType>, <NumElems>] as the input to the function
1893 setinputsizes() for binding arrays
1894 #) Discovered from the Oracle 8.1.6 version of the documentation of the OCI
1895 libraries, that the size of the memory location required for the precision
1896 variable is larger than the printed documentation says; this was causing a
1897 problem with the code on the Sun platform.
1898 #) Now support building RPMs for Linux.
1899
1900
1901 Version 2.3 (October 2001)
1902 --------------------------
1903
1904 #) Incremental performance enhancements (dealing with reusing cursors and
1905 bind handles)
1906 #) Ensured that arrays of integers with a single float in them are all
1907 treated as floats, as suggested by Martin Koch.
1908 #) Fixed code dealing with scale and precision for both defining a numeric
1909 variable and for providing the cursor description; this eliminates the
1910 problem of an underflow error (OCI-22054) when retrieving data with
1911 non-zero scale.
1912
1913
1914 Version 2.2 (July 2001)
1915 -----------------------
1916
1917 #) Upgraded thread safety to level 1 (according to the Python DB API 2.0) as
1918 an internal project required the ability to share the module between
1919 threads.
1920 #) Added ability to bind ref cursors to PL/SQL blocks as requested by
1921 Brad Powell.
1922 #) Added function write(Value, [Offset]) to LOB variables as requested by
1923 Matthias Kirst.
1924 #) Procedure execute() on Cursor objects now permits a value None for the
1925 statement which means that the previously prepared statement will be
1926 executed and any input sizes set earlier will be retained. This was done to
1927 improve the performance of scripts that execute one statement many times.
1928 #) Modified module global constants BINARY and DATETIME to point to the
1929 external representations of those types so that the expression
1930 type(var) == cx_Oracle.DATETIME will work as expected.
1931 #) Added global constant version to provide means of determining the current
1932 version of the module.
1933 #) Modified error checking routine to distinguish between an Oracle error and
1934 invalid handles.
1935 #) Added error checking to avoid setting the value of a bind variable to a
1936 value that it cannot support and raised an exception to indicate this fact.
1937 #) Added extra compile arguments for the AIX platform as suggested by Jehwan
1938 Ryu.
1939 #) Added section to the README to indicate the method for a binary
1940 installation as suggested by Steve Holden.
1941 #) Added simple usage example as requested by many people.
1942 #) Added HISTORY file to the distribution.
+0
-1658
doc/src/releasenotes.rst less more
0 .. _releasenotes:
1
2 cx_Oracle Release Notes
3 =======================
4
5 7.x releases
6 ############
7
8 .. _releasenotes70:
9
10 Version 7.1 (February 2019)
11 ---------------------------
12
13 #) Updated to `ODPI-C 3.1
14 <https://oracle.github.io/odpi/doc/releasenotes.html#
15 version-3-1-january-21-2019>`__.
16 #) Improved support for session tagging in session pools by allowing a
17 session callback to be specified when creating a pool via
18 :meth:`cx_Oracle.SessionPool()`. Callbacks can be written in Python or in
19 PL/SQL and can be used to improve performance by decreasing round trips to
20 the database needed to set session state. Callbacks written in Python will
21 be invoked for brand new connections (that have never been acquired from
22 the pool before) or when the tag assigned to the connection doesn't match
23 the one that was requested. Callbacks written in PL/SQL will only be
24 invoked when the tag assigned to the connection doesn't match the one that
25 was requested.
26 #) Added attribute :attr:`Connection.tag` to provide access to the actual tag
27 assigned to the connection. Setting this attribute will cause the
28 connection to be retagged when it is released back to the pool.
29 #) Added support for fetching SYS.XMLTYPE values as strings, as requested
30 (`issue 14 <https://github.com/oracle/python-cx_Oracle/issues/14>`__).
31 Note that this support is limited to the size of VARCHAR2 columns in the
32 database (either 4000 or 32767 bytes).
33 #) Added support for allowing the typename parameter in method
34 :meth:`Cursor.var()` to be None or a valid object type created by the
35 method :meth:`Connection.gettype()`, as requested
36 (`issue 231 <https://github.com/oracle/python-cx_Oracle/issues/231>`__).
37 #) Added support for getting and setting attributes of type RAW on Oracle
38 objects, as requested
39 (`ODPI-C issue 72 <https://github.com/oracle/odpi/issues/72>`__).
40 #) Added support for performing external authentication with proxy for
41 standalone connections.
42 #) Added support for mixing integers, floating point and decimal values in
43 data passed to :meth:`Cursor.executemany()`
44 (`issue 241 <https://github.com/oracle/python-cx_Oracle/issues/241>`__).
45 The error message raised when a value cannot be converted to an Oracle
46 number was also improved.
47 #) Adjusted fetching of numeric values so that no precision is lost. If an
48 Oracle number cannot be represented by a Python floating point number a
49 decimal value is automatically returned instead.
50 #) Corrected handling of multiple calls to method
51 :meth:`Cursor.executemany()` where all of the values in one of the columns
52 passed to the first call are all None and a subsequent call has a value
53 other than None in the same column
54 (`issue 236 <https://github.com/oracle/python-cx_Oracle/issues/236>`__).
55 #) Added additional check for calling :meth:`Cursor.setinputsizes()` with an
56 empty dictionary in order to avoid the error "cx_Oracle.ProgrammingError:
57 positional and named binds cannot be intermixed"
58 (`issue 199 <https://github.com/oracle/python-cx_Oracle/issues/199>`__).
59 #) Corrected handling of values that exceed the maximum value of a plain
60 integer object on Python 2 on Windows
61 (`issue 257 <https://github.com/oracle/python-cx_Oracle/issues/257>`__).
62 #) Added error message when attempting external authentication with proxy
63 without placing the user name in [] (proxy authentication was previously
64 silently ignored).
65 #) Exempted additional error messages from forcing a statement to be dropped
66 from the cache
67 (`ODPI-C issue 76 <https://github.com/oracle/odpi/issues/76>`__).
68 #) Improved dead session detection when using session pools for Oracle Client
69 12.2 and higher.
70 #) Ensured that the connection returned from a pool after a failed ping (such
71 as due to a killed session) is not itself marked as needing to be dropped
72 from the pool.
73 #) Eliminated memory leak under certain circumstances when pooled connections
74 are released back to the pool.
75 #) Eliminated memory leak when connections are dropped from the pool.
76 #) Eliminated memory leak when calling :meth:`Connection.close()` after
77 fetching collections from the database.
78 #) Adjusted order in which memory is freed when the last references to SODA
79 collections, documents, document cursors and collection cursors are
80 released, in order to prevent a segfault under certain circumstances.
81 #) Improved code preventing a statement from binding itself, in order to avoid
82 a potential segfault under certain circumstances.
83 #) Worked around OCI bug when attempting to free objects that are PL/SQL
84 records, in order to avoid a potential segfault.
85 #) Improved test suite and samples. Note that default passwords are no longer
86 supplied. New environment variables can be set to specify passwords if
87 desired, or the tests and samples will prompt for the passwords when
88 needed. In addition, a Python script is now available to create and drop
89 the schemas used for the tests and samples.
90 #) Improved documentation.
91
92
93 Version 7.0 (September 2018)
94 ----------------------------
95
96 #) Update to `ODPI-C 3.0
97 <https://oracle.github.io/odpi/doc/releasenotes.html#
98 version-3-0-0-september-13-2018>`__.
99 #) Added support for Oracle Client 18 libraries.
100 #) Added support for SODA (as preview). See :ref:`SODA Database <sodadb>`,
101 :ref:`SODA Collection <sodacoll>` and :ref:`SODA Document <sodadoc>` for
102 more information.
103 #) Added support for call timeouts available in Oracle Client 18.1 and
104 higher. See :attr:`Connection.callTimeout`.
105 #) Added support for getting the contents of a SQL collection object as a
106 dictionary, where the keys are the indices of the collection and the values
107 are the elements of the collection. See function :meth:`Object.asdict()`.
108 #) Added support for closing a session pool via the function
109 :meth:`SessionPool.close()`. Once closed, further attempts to use any
110 connection that was acquired from the pool will result in the error
111 "DPI-1010: not connected".
112 #) Added support for setting a LOB attribute of an object with a string or
113 bytes (instead of requiring a temporary LOB to be created).
114 #) Added support for the packed decimal type used by object attributes with
115 historical types DECIMAL and NUMERIC
116 (`issue 212 <https://github.com/oracle/python-cx_Oracle/issues/212>`__).
117 #) On Windows, first attempt to load oci.dll from the same directory as
118 the cx_Oracle module.
119 #) SQL objects that are created or fetched from the database are now tracked
120 and marked unusable when a connection is closed. This was done in order
121 to avoid a segfault under certain circumstances.
122 #) Re-enabled dead session detection functionality when using pools for Oracle
123 Client 12.2 and higher in order to handle classes of connection errors such
124 as resource profile limits.
125 #) Improved error messages when the Oracle Client or Oracle Database need to
126 be at a minimum version in order to support a particular feature.
127 #) When a connection is used as a context manager, the connection is now
128 closed when the block ends. Attempts to set
129 ``cx_Oracle.__future__.ctx_mgr_close`` are now ignored.
130 #) When a DML returning statement is executed, variables bound to it will
131 return an array when calling :meth:`Variable.getvalue()`. Attempts to set
132 ``cx_Oracle.__future__.dml_ret_array_val`` are now ignored.
133 #) Support for Python 3.4 has been dropped.
134 #) Added additional test cases.
135 #) Improved documentation.
136
137
138
139 6.x releases
140 ############
141
142 .. _releasenotes60:
143
144 Version 6.4.1 (July 2018)
145 -------------------------
146
147 #) Update to `ODPI-C 2.4.2
148 <https://oracle.github.io/odpi/doc/releasenotes.html#
149 version-2-4-2-july-9-2018>`__.
150
151 - Avoid buffer overrun due to improper calculation of length byte when
152 converting some negative 39 digit numbers from string to the internal
153 Oracle number format
154 (`ODPI-C issue 67 <https://github.com/oracle/odpi/issues/67>`__).
155
156 #) Prevent error "cx_Oracle.ProgrammingError: positional and named binds
157 cannot be intermixed" when calling cursor.setinputsizes() without any
158 parameters and then calling cursor.execute() with named bind parameters
159 (`issue 199 <https://github.com/oracle/python-cx_Oracle/issues/199>`__).
160
161
162 Version 6.4 (July 2018)
163 -----------------------
164
165 #) Update to `ODPI-C 2.4.1
166 <https://oracle.github.io/odpi/doc/releasenotes.html#
167 version-2-4-1-july-2-2018>`__.
168
169 - Added support for grouping subscriptions. See parameters groupingClass,
170 groupingValue and groupingType to function
171 :meth:`Connection.subscribe()`.
172 - Added support for specifying the IP address a subscription should use
173 instead of having the Oracle Client library determine the IP address on
174 its own. See parameter ipAddress to function
175 :meth:`Connection.subscribe()`.
176 - Added support for subscribing to notifications when messages are
177 available to dequeue in an AQ queue. The new constant
178 :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ` should be passed to the namespace
179 parameter of function :meth:`Connection.subscribe()` in order to get this
180 functionality. Attributes :attr:`Message.queueName` and
181 :attr:`Message.consumerName` will be populated in notification messages
182 that are received when this namespace is used.
183 - Added attribute :attr:`Message.registered` to let the notification
184 callback know when the subscription that generated the notification is no
185 longer registered with the database.
186 - Added support for timed waits when acquiring a session from a session
187 pool. Use the new constant :data:`cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT` in
188 the parameter getmode to function :meth:`cx_Oracle.SessionPool` along
189 with the new parameter waitTimeout.
190 - Added support for specifying the timeout and maximum lifetime session for
191 session pools when they are created using function
192 :meth:`cx_Oracle.SessionPool`. Previously the pool had to be created
193 before these values could be changed.
194 - Avoid memory leak when dequeuing from an empty queue.
195 - Ensure that the row count for queries is reset to zero when the statement
196 is executed
197 (`issue 193 <https://github.com/oracle/python-cx_Oracle/issues/193>`__).
198 - If the statement should be deleted from the statement cache, first check
199 to see that there is a statement cache currently being used; otherwise,
200 the error "ORA-24300: bad value for mode" will be raised under certain
201 conditions.
202
203 #) Added support for using the cursor as a context manager
204 (`issue 190 <https://github.com/oracle/python-cx_Oracle/issues/190>`__).
205 #) Added support for specifying the "errors" parameter to the decode() that
206 takes place internally when fetching strings from the database
207 (`issue 162 <https://github.com/oracle/python-cx_Oracle/issues/162>`__).
208 #) Added support for specifying an integer for the parameters argument to
209 :meth:`Cursor.executemany()`. This allows for batch execution when no
210 parameters are required or when parameters have previously been bound. This
211 replaces Cursor.executemanyprepared() (which is now deprecated and will be
212 removed in cx_Oracle 7).
213 #) Adjusted the binding of booleans so that outside of PL/SQL they are bound
214 as integers
215 (`issue 181 <https://github.com/oracle/python-cx_Oracle/issues/181>`__).
216 #) Added support for binding decimal.Decimal values to cx_Oracle.NATIVE_FLOAT
217 as requested
218 (`issue 184 <https://github.com/oracle/python-cx_Oracle/issues/184>`__).
219 #) Added checks on passing invalid type parameters to methods
220 :meth:`Cursor.arrayvar()`, :meth:`Cursor.callfunc()` and
221 :meth:`Cursor.setinputsizes()`.
222 #) Corrected handling of cursors and rowids in DML Returning statements.
223 #) Added sample from David Lapp demonstrating the use of GeoPandas with
224 SDO_GEOMETRY and a sample for demonstrating the use of REF cursors.
225 #) Adjusted samples and documentation for clarity.
226 #) Added additional test cases.
227
228
229 Version 6.3.1 (May 2018)
230 ------------------------
231
232 #) Update to `ODPI-C 2.3.2
233 <https://oracle.github.io/odpi/doc/releasenotes.html#
234 version-2-3-2-may-7-2018>`__.
235
236 - Ensure that a call to unregister a subscription only occurs if the
237 subscription is still registered.
238 - Ensure that before a statement is executed any buffers used for DML
239 returning statments are reset.
240
241 #) Ensure that behavior with cx_Oracle.__future__.dml_ret_array_val not
242 set or False is the same as the behavior in cx_Oracle 6.2
243 (`issue 176 <https://github.com/oracle/python-cx_Oracle/issues/176>`__).
244
245
246 Version 6.3 (April 2018)
247 ------------------------
248
249 #) Update to `ODPI-C 2.3.1
250 <https://oracle.github.io/odpi/doc/releasenotes.html#
251 version-2-3-1-april-25-2018>`__.
252
253 - Fixed binding of LONG data (values exceeding 32KB) when using the
254 function :meth:`Cursor.executemany()`.
255 - Added code to verify that a CQN subscription is open before permitting it
256 to be used. Error "DPI-1060: subscription was already closed" will now be
257 raised if an attempt is made to use a subscription that was closed
258 earlier.
259 - Stopped attempting to unregister a CQN subscription before it was
260 completely registered. This prevents errors encountered during
261 registration from being masked by an error stating that the subscription
262 has not been registered!
263 - Added error "DPI-1061: edition is not supported when a new password is
264 specified" to clarify the fact that specifying an edition and a new
265 password at the same time is not supported when creating a connection.
266 Previously the edition value was simply ignored.
267 - Improved error message when older OCI client libraries are being used
268 that don't have the method OCIClientVersion().
269 - Fixed the handling of ANSI types REAL and DOUBLE PRECISION as
270 implemented by Oracle. These types are just subtypes of NUMBER and are
271 different from BINARY_FLOAT and BINARY_DOUBLE
272 (`issue 163 <https://github.com/oracle/python-cx_Oracle/issues/163>`__).
273 - Fixed support for true heterogeneous session pools that use different
274 user/password combinations for each session acquired from the pool.
275 - Added error message indicating that setting either of the parameters
276 arraydmlrowcounts and batcherrors to True in :meth:`Cursor.executemany()`
277 is only supported with insert, update, delete and merge statements.
278
279 #) Fixed support for getting the OUT values of bind variables bound to a DML
280 Returning statement when calling the function :meth:`Cursor.executemany()`.
281 Note that the attribute dml_ret_array_val in :attr:`cx_Oracle.__future__`
282 must be set to True first.
283 #) Added support for binding integers and floats as cx_Oracle.NATIVE_FLOAT.
284 #) A :attr:`cx_Oracle._Error` object is now the value of all cx_Oracle
285 exceptions raised by cx_Oracle.
286 (`issue 51 <https://github.com/oracle/python-cx_Oracle/issues/51>`__).
287 #) Added support for building cx_Oracle with a pre-compiled version of ODPI-C,
288 as requested
289 (`issue 103 <https://github.com/oracle/python-cx_Oracle/issues/103>`__).
290 #) Default values are now provided for all parameters to
291 :meth:`cx_Oracle.SessionPool`.
292 #) Improved error message when an unsupported Oracle type is encountered.
293 #) The Python GIL is now prevented from being held while performing a round
294 trip for the call to get the attribute :attr:`Connection.version`
295 (`issue 158 <https://github.com/oracle/python-cx_Oracle/issues/158>`__).
296 #) Added check for the validity of the year for Python 2.x since it doesn't do
297 that itself like Python 3.x does
298 (`issue 166 <https://github.com/oracle/python-cx_Oracle/issues/166>`__).
299 #) Adjusted documentation to provide additional information on the use of
300 :meth:`Cursor.executemany()` as requested
301 (`issue 153 <https://github.com/oracle/python-cx_Oracle/issues/153>`__).
302 #) Adjusted documentation to state that batch errors and array DML row counts
303 can only be used with insert, update, delete and merge statements
304 (`issue 31 <https://github.com/oracle/python-cx_Oracle/issues/31>`__).
305 #) Updated tutorial to import common connection information from files in
306 order to make setup a bit more generic.
307
308
309 Version 6.2.1 (March 2018)
310 --------------------------
311
312 #) Make sure cxoModule.h is included in the source archive
313 (`issue 155 <https://github.com/oracle/python-cx_Oracle/issues/155>`__).
314
315
316 Version 6.2 (March 2018)
317 ------------------------
318
319 #) Update to `ODPI-C 2.2.1
320 <https://oracle.github.io/odpi/doc/releasenotes.html#
321 version-2-2-1-march-5-2018>`__.
322
323 - eliminate error "DPI-1054: connection cannot be closed when open
324 statements or LOBs exist" (`issue 138
325 <https://github.com/oracle/python-cx_Oracle/issues/138>`__).
326 - avoid a round trip to the database when a connection is released back to
327 the pool by preventing a rollback from being called when no transaction
328 is in progress.
329 - improve error message when the use of bind variables is attempted with
330 DLL statements, which is not supported by Oracle.
331 - if an Oracle object is retrieved from an attribute of another Oracle
332 object or a collection, prevent the "owner" from being destroyed until
333 the object that was retrieved has itself been destroyed.
334 - correct handling of boundary numbers 1e126 and -1e126
335 - eliminate memory leak when calling :meth:`Connection.enq()` and
336 :meth:`Connection.deq()`
337 - eliminate memory leak when setting NCHAR and NVARCHAR attributes of
338 objects.
339 - eliminate memory leak when fetching collection objects from the database.
340
341 #) Added support for creating a temporary CLOB, BLOB or NCLOB via the method
342 :meth:`Connection.createlob()`.
343 #) Added support for binding a LOB value directly to a cursor.
344 #) Added support for closing the connection when reaching the end of a
345 ``with`` code block controlled by the connection as a context manager, but
346 in a backwards compatible way
347 (`issue 113 <https://github.com/oracle/python-cx_Oracle/issues/113>`__).
348 See :data:`cx_Oracle.__future__` for more information.
349 #) Reorganized code to simplify continued maintenance and consolidate
350 transformations to/from Python objects.
351 #) Ensure that the number of elements in the array is not lost when the
352 buffer size is increased to accommodate larger strings.
353 #) Corrected support in Python 3.x for cursor.parse() by permitting a string
354 to be passed, instead of incorrectly requiring a bytes object.
355 #) Eliminate reference leak with LOBs acquired from attributes of objects or
356 elements of collections.
357 #) Eliminate reference leak when extending an Oracle collection.
358 #) Documentation improvements.
359 #) Added test cases to the test suite.
360
361
362 Version 6.1 (December 2017)
363 ---------------------------
364
365 #) Update to `ODPI-C 2.1
366 <https://oracle.github.io/odpi/doc/releasenotes.html#
367 version-2-1-december-12-2017>`__.
368
369 - Support was added for accessing sharded databases via sharding keys (new
370 in Oracle 12.2). NOTE: the underlying OCI library has a bug when using
371 standalone connections. There is a small memory leak proportional to the
372 number of connections created/dropped. There is no memory leak when using
373 session pools, which is recommended.
374 - Added options for authentication with SYSBACKUP, SYSDG, SYSKM and SYSRAC,
375 as requested (`issue 101
376 <https://github.com/oracle/python-cx_Oracle/issues/101>`__).
377 - Attempts to release statements or free LOBs after the connection has been
378 closed (by, for example, killing the session) are now prevented.
379 - An error message was added when specifying an edition and a connection
380 class since this combination is not supported.
381 - Attempts to close the session for connections created with an external
382 handle are now prevented.
383 - Attempting to ping a database earlier than 10g results in ORA-1010:
384 invalid OCI operation, but that implies a response from the database and
385 therefore a successful ping, so treat it that way!
386 (see `<https://github.com/rana/ora/issues/224>`__ for more information).
387 - Support was added for converting numeric values in an object type
388 attribute to integer and text, as requested (`ODPI-C issue 35
389 <https://github.com/oracle/odpi/issues/35>`__).
390 - Setting attributes :attr:`DeqOptions.msgId` and
391 :attr:`MessageProperties.msgId` now works as expected.
392 - The overflow check when using double values (Python floats) as input
393 to float attributes of objects or elements of collections was removed as
394 it didn't work anyway and is a well-known issue that cannot be prevented
395 without removing desired functionality. The developer should ensure that
396 the source value falls within the limits of floats, understand the
397 consequent precision loss or use a different data type.
398 - Variables of string/raw types are restricted to 2 bytes less than 1 GB
399 (1,073,741,822 bytes), since OCI cannot handle more than that currently.
400 - Support was added for identifying the id of the transaction which spawned
401 a CQN subscription message, as requested
402 (`ODPI-C issue 32 <https://github.com/oracle/odpi/issues/32>`__).
403 - Corrected use of subscription port number (`issue 115
404 <https://github.com/oracle/python-cx_Oracle/issues/115>`__).
405 - Problems reported with the usage of FormatMessage() on Windows were
406 addressed (`ODPI-C issue 47
407 <https://github.com/oracle/odpi/issues/47>`__).
408 - On Windows, if oci.dll cannot be loaded because it is the wrong
409 architecture (32-bit vs 64-bit), attempt to find the offending DLL and
410 include the full path of the DLL in the message, as suggested.
411 (`ODPI-C issue 49 <https://github.com/oracle/odpi/issues/49>`__).
412 - Force OCI prefetch to always use the value 2; the OCI default is 1 but
413 setting the ODPI-C default to 2 ensures that single row fetches don't
414 require an extra round trip to determine if there are more rows to fetch;
415 this change also reduces the potential memory consumption when
416 fetchArraySize was set to a large value and also avoids performance
417 issues discovered with larger values of prefetch.
418
419 #) Fix build with PyPy 5.9.0-alpha0 in libpython mode
420 (`PR 54 <https://github.com/oracle/python-cx_Oracle/pull/54>`__).
421 #) Ensure that the edition is passed through to the database when a session
422 pool is created.
423 #) Corrected handling of Python object references when an invalid keyword
424 parameter is passed to :meth:`cx_Oracle.SessionPool`.
425 #) Corrected handling of :attr:`Connection.handle` and the handle parameter
426 to :meth:`cx_Oracle.connect` on Windows.
427 #) Documentation improvements.
428 #) Added test cases to the test suite.
429
430
431 Version 6.0.3 (November 2017)
432 -----------------------------
433
434 #) Update to `ODPI-C 2.0.3
435 <https://oracle.github.io/odpi/doc/releasenotes.html#
436 version-2-0-3-november-6-2017>`__.
437
438 - Prevent use of unitialized data in certain cases (`issue 77
439 <https://github.com/oracle/python-cx_Oracle/issues/77>`__).
440 - Attempting to ping a database earlier than 10g results in error
441 "ORA-1010: invalid OCI operation", but that implies a response from the
442 database and therefore a successful ping, so treat it that way!
443 - Correct handling of conversion of some numbers to NATIVE_FLOAT.
444 - Prevent use of NaN with Oracle numbers since it produces corrupt data
445 (`issue 91 <https://github.com/oracle/python-cx_Oracle/issues/91>`__).
446 - Verify that Oracle objects bound to cursors, fetched from cursors, set in
447 object attributes or appended to collection objects are of the correct
448 type.
449 - Correct handling of NVARCHAR2 when used as attributes of Oracle objects
450 or as elements of collections.
451
452 #) Ensure that a call to setinputsizes() with an invalid type prior to a call
453 to executemany() does not result in a type error, but instead gracefully
454 ignores the call to setinputsizes() as required by the DB API
455 (`issue 75 <https://github.com/oracle/python-cx_Oracle/issues/75>`__).
456 #) Check variable array size when setting variable values and raise
457 IndexError, as is already done for getting variable values.
458
459
460 Version 6.0.2 (August 2017)
461 ---------------------------
462
463 #) Update to `ODPI-C 2.0.2
464 <https://oracle.github.io/odpi/doc/releasenotes.html
465 #version-2-0-2-august-30-2017>`__.
466
467 - Don't prevent connection from being explicitly closed when a fatal error
468 has taken place (`issue 67
469 <https://github.com/oracle/python-cx_Oracle/issues/67>`__).
470 - Correct handling of objects when dynamic binding is performed.
471 - Process deregistration events without an error.
472 - Eliminate memory leak when creating objects.
473
474 #) Added missing type check to prevent coercion of decimal to float
475 (`issue 68 <https://github.com/oracle/python-cx_Oracle/issues/68>`__).
476 #) On Windows, sizeof(long) = 4, not 8, which meant that integers between 10
477 and 18 digits were not converted to Python correctly
478 (`issue 70 <https://github.com/oracle/python-cx_Oracle/issues/70>`__).
479 #) Eliminate memory leak when repeatedly executing the same query.
480 #) Eliminate segfault when attempting to reuse a REF cursor that has been
481 closed.
482 #) Updated documentation.
483
484
485 Version 6.0.1 (August 2017)
486 ---------------------------
487
488 #) Update to `ODPI-C 2.0.1
489 <https://oracle.github.io/odpi/doc/releasenotes.html
490 #version-2-0-1-august-18-2017>`__.
491
492 - Ensure that queries registered via :meth:`Subscription.registerquery()`
493 do not prevent the associated connection from being closed
494 (`ODPI-C issue 27 <https://github.com/oracle/odpi/issues/27>`__).
495 - Deprecated attribute :attr:`Subscription.id` as it was never intended to
496 be exposed (`ODPI-C issue 28
497 <https://github.com/oracle/odpi/issues/28>`__). It will be dropped in
498 version 6.1.
499 - Add support for DML Returning statements that require dynamically
500 allocated variable data (such as CLOBs being returned as strings).
501
502 #) Correct packaging of Python 2.7 UCS4 wheels on Linux
503 (`issue 64 <https://github.com/oracle/python-cx_Oracle/issues/64>`__).
504 #) Updated documentation.
505
506
507 Version 6.0 (August 2017)
508 -------------------------
509
510 See :ref:`What's New <whatsnew60>` for a summary of the changes between
511 cx_Oracle 5.3 and cx_Oracle 6.0.
512
513 #) Update to `ODPI-C 2.0 <https://oracle.github.io/odpi/doc/releasenotes.html
514 #version-2-0-august-14-2017>`__.
515
516 - Prevent closing the connection when there are any open statements or
517 LOBs and add new error "DPI-1054: connection cannot be closed when open
518 statements or LOBs exist" when this situation is detected; this is
519 needed to prevent crashes under certain conditions when statements or
520 LOBs are being acted upon while at the same time (in another thread) a
521 connection is being closed; it also prevents leaks of statements and
522 LOBs when a connection is returned to a session pool.
523 - On platforms other than Windows, if the regular method for loading the
524 Oracle Client libraries fails, try using $ORACLE_HOME/lib/libclntsh.so
525 (`ODPI-C issue 20 <https://github.com/oracle/odpi/issues/20>`__).
526 - Use the environment variable DPI_DEBUG_LEVEL at runtime, not compile
527 time.
528 - Added support for DPI_DEBUG_LEVEL_ERRORS (reports errors and has the
529 value 8) and DPI_DEBUG_LEVEL_SQL (reports prepared SQL statement text
530 and has the value 16) in order to further improve the ability to debug
531 issues.
532 - Correct processing of :meth:`Cursor.scroll()` in some circumstances.
533
534 #) Delay initialization of the ODPI-C library until the first standalone
535 connection or session pool is created so that manipulation of the
536 environment variable NLS_LANG can be performed after the module has been
537 imported; this also has the added benefit of reducing the number of errors
538 that can take place when the module is imported.
539 #) Prevent binding of null values from generating the exception "ORA-24816:
540 Expanded non LONG bind data supplied after actual LONG or LOB column" in
541 certain circumstances
542 (`issue 50 <https://github.com/oracle/python-cx_Oracle/issues/50>`__).
543 #) Added information on how to run the test suite
544 (`issue 33 <https://github.com/oracle/python-cx_Oracle/issues/33>`__).
545 #) Documentation improvements.
546
547
548 Version 6.0 rc 2 (July 2017)
549 ----------------------------
550
551 #) Update to `ODPI-C rc 2 <https://oracle.github.io/odpi/doc/releasenotes.html
552 #version-2-0-0-rc-2-july-20-2017>`__.
553
554 - Provide improved error message when OCI environment cannot be created,
555 such as when the oraaccess.xml file cannot be processed properly.
556 - On Windows, convert system message to Unicode first, then to UTF-8;
557 otherwise, the error message returned could be in a mix of encodings
558 (`issue 40 <https://github.com/oracle/python-cx_Oracle/issues/40>`__).
559 - Corrected support for binding decimal values in object attribute values
560 and collection element values.
561 - Corrected support for binding PL/SQL boolean values to PL/SQL
562 procedures with Oracle client 11.2.
563
564 #) Define exception classes on the connection object in addition to at module
565 scope in order to simplify error handling in multi-connection environments,
566 as specified in the Python DB API.
567 #) Ensure the correct encoding is used for setting variable values.
568 #) Corrected handling of CLOB/NCLOB when using different encodings.
569 #) Corrected handling of TIMESTAMP WITH TIME ZONE attributes on objects.
570 #) Ensure that the array position passed to var.getvalue() does not exceed the
571 number of elements allocated in the array.
572 #) Reworked test suite and samples so that they are independent of each other
573 and so that the SQL scripts used to create/drop schemas are easily adjusted
574 to use different schema names, if desired.
575 #) Updated DB API test suite stub to support Python 3.
576 #) Added additional test cases and samples.
577 #) Documentation improvements.
578
579
580 Version 6.0 rc 1 (June 2017)
581 ----------------------------
582
583 #) Update to `ODPI-C rc 1 <https://oracle.github.io/odpi/doc/releasenotes.html
584 #version-2-0-0-rc-1-june-16-2017>`__.
585 #) The method :meth:`Cursor.setoutputsize` no longer needs to do anything,
586 since ODPI-C automatically manages buffer sizes of LONG and LONG RAW
587 columns.
588 #) Handle case when both precision and scale are zero, as occurs when
589 retrieving numeric expressions (`issue 34
590 <https://github.com/oracle/python-cx_Oracle/issues/34>`__).
591 #) OCI requires that both encoding and nencoding have values or that both
592 encoding and encoding do not have values. These parameters are used in
593 functions :meth:`cx_Oracle.connect` and :meth:`cx_Oracle.SessionPool`. The
594 missing value is set to its default value if one of the values is set and
595 the other is not (`issue 36
596 <https://github.com/oracle/python-cx_Oracle/issues/36>`__).
597 #) Permit use of both string and unicode for Python 2.7 for creating session
598 pools and for changing passwords (`issue 23
599 <https://github.com/oracle/python-cx_Oracle/issues/23>`__).
600 #) Corrected handling of BFILE LOBs.
601 #) Add script for dropping test schemas.
602 #) Documentation improvements.
603
604
605 Version 6.0 beta 2 (May 2017)
606 -----------------------------
607
608 #) Added support for getting/setting attributes of objects or element values
609 in collections that contain LOBs, BINARY_FLOAT values, BINARY_DOUBLE values
610 and NCHAR and NVARCHAR2 values. The error message for any types that are
611 not supported has been improved as well.
612 #) Enable temporary LOB caching in order to avoid disk I/O as
613 `suggested <https://github.com/oracle/odpi/issues/10>`__.
614 #) Added support for setting the debug level in ODPI-C, if desirable, by
615 setting environment variable DPI_DEBUG_LEVEL prior to building cx_Oracle.
616 #) Correct processing of strings in :meth:`Cursor.executemany` when a
617 larger string is found after a shorter string in the list of data bound to
618 the statement.
619 #) Correct handling of long Python integers that cannot fit inside a 64-bit C
620 integer (`issue 18
621 <https://github.com/oracle/python-cx_Oracle/issues/18>`__).
622 #) Correct creation of pool using external authentication.
623 #) Handle edge case when an odd number of zeroes trail the decimal point in a
624 value that is effectively zero (`issue 22
625 <https://github.com/oracle/python-cx_Oracle/issues/22>`__).
626 #) Prevent segfault under load when the attempt to create an error fails.
627 #) Eliminate resource leak when a standalone connection or pool is freed.
628 #) Correct `typo <https://github.com/oracle/python-cx_Oracle/issues/24>`__.
629 #) Correct handling of REF cursors when the array size is manipulated.
630 #) Prevent attempts from binding the cursor being executed to itself.
631 #) Correct reference count handling of parameters when creating a cursor.
632 #) Correct determination of the names of the bind variables in prepared SQL
633 statements (which behaves a little differently from PL/SQL statements).
634
635
636 Version 6.0 beta 1 (April 2017)
637 -------------------------------
638
639 #) Simplify building cx_Oracle considerably by use of
640 `ODPI-C <https://oracle.github.io/odpi>`__. This means that cx_Oracle can
641 now be built without Oracle Client header files or libraries and that at
642 runtime cx_Oracle can adapt to Oracle Client 11.2, 12.1 or 12.2 libraries
643 without needing to be rebuilt. This also means that wheels can now be
644 produced and installed via pip.
645 #) Added attribute :attr:`SessionPool.stmtcachesize` to support getting and
646 setting the default statement cache size for connections in the pool.
647 #) Added attribute :attr:`Connection.dbop` to support setting the database
648 operation that is to be monitored.
649 #) Added attribute :attr:`Connection.handle` to facilitate testing the
650 creation of a connection using a OCI service context handle.
651 #) Added parameters tag and matchanytag to the :meth:`cx_Oracle.connect`
652 and :meth:`SessionPool.acquire` methods and added parameters tag and retag
653 to the :meth:`SessionPool.release` method in order to support session
654 tagging.
655 #) Added parameter edition to the :meth:`cx_Oracle.SessionPool` method.
656 #) Added support for
657 `universal rowids <https://github.com/oracle/python-cx_Oracle/blob/master/
658 samples/UniversalRowids.py>`__.
659 #) Added support for `DML Returning of multiple rows
660 <https://github.com/oracle/python-cx_Oracle/blob/master/samples/
661 DMLReturningMultipleRows.py>`__.
662 #) Added attributes :attr:`Variable.actualElements` and
663 :attr:`Variable.values` to variables.
664 #) Added parameters region, sharding_key and super_sharding_key to the
665 :meth:`cx_Oracle.makedsn()` method to support connecting to a sharded
666 database (new in Oracle Database 12.2).
667 #) Added support for smallint and float data types in Oracle objects, as
668 `requested <https://github.com/oracle/python-cx_Oracle/issues/4>`__.
669 #) An exception is no longer raised when a collection is empty for methods
670 :meth:`Object.first()` and :meth:`Object.last()`. Instead, the value None
671 is returned to be consistent with the methods :meth:`Object.next()` and
672 :meth:`Object.prev()`.
673 #) If the environment variables NLS_LANG and NLS_NCHAR are being used, they
674 must be set before the module is imported. Using the encoding and nencoding
675 parameters to the :meth:`cx_Oracle.connect` and
676 :meth:`cx_Oracle.SessionPool` methods is a simpler alternative to setting
677 these environment variables.
678 #) Removed restriction on fetching LOBs across round trips to the database
679 (eliminates error "LOB variable no longer valid after subsequent fetch").
680 #) Removed requirement for specifying a maximum size when fetching LONG or
681 LONG raw columns. This also allows CLOB, NCLOB, BLOB and BFILE columns to
682 be fetched as strings or bytes without needing to specify a maximum size.
683 #) Dropped deprecated parameter twophase from the :meth:`cx_Oracle.connect`
684 method. Applications should set the :attr:`Connection.internal_name` and
685 :attr:`Connection.external_name` attributes instead to a value appropriate
686 to the application.
687 #) Dropped deprecated parameters action, module and clientinfo from the
688 :meth:`cx_Oracle.connect` method. The appcontext parameter should be used
689 instead as shown in this `sample <https://github.com/oracle/
690 python-cx_Oracle/blob/master/samples/AppContext.py>`__.
691 #) Dropped deprecated attribute numbersAsString from
692 :ref:`cursor objects <cursorobj>`. Use an output type handler instead as
693 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
694 master/samples/ReturnNumbersAsDecimals.py>`__.
695 #) Dropped deprecated attributes cqqos and rowids from
696 :ref:`subscription objects <subscrobj>`. Use the qos attribute instead as
697 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
698 master/samples/CQN.py>`__.
699 #) Dropped deprecated parameters cqqos and rowids from the
700 :meth:`Connection.subscribe()` method. Use the qos parameter instead as
701 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
702 master/samples/CQN.py>`__.
703
704
705 5.x releases
706 ############
707
708
709 Version 5.3 (March 2017)
710 ------------------------
711
712 #) Added support for Python 3.6.
713 #) Dropped support for Python versions earlier than 2.6.
714 #) Dropped support for Oracle clients earlier than 11.2.
715 #) Added support for
716 :meth:`fetching implicit results<Cursor.getimplicitresults()>`
717 (available in Oracle 12.1)
718 #) Added support for :attr:`Transaction Guard <Connection.ltxid>` (available
719 in Oracle 12.1).
720 #) Added support for setting the
721 :attr:`maximum lifetime <SessionPool.max_lifetime_session>` of pool
722 connections (available in Oracle 12.1).
723 #) Added support for large row counts (larger than 2 ** 32, available in
724 Oracle 12.1)
725 #) Added support for :meth:`advanced queuing <Connection.deq()>`.
726 #) Added support for :meth:`scrollable cursors <Cursor.scroll()>`.
727 #) Added support for :attr:`edition based redefinition <Connection.edition>`.
728 #) Added support for :meth:`creating <ObjectType.newobject()>`, modifying and
729 binding user defined types and collections.
730 #) Added support for creating, modifying and binding PL/SQL records and
731 collections (available in Oracle 12.1).
732 #) Added support for binding :data:`native integers <cx_Oracle.NATIVE_INT>`.
733 #) Enabled statement caching.
734 #) Removed deprecated variable attributes maxlength and allocelems.
735 #) Corrected support for setting the encoding and nencoding parameters when
736 :meth:`creating a connection <cx_Oracle.Connection>` and added support for
737 setting these when creating a session pool. These can now be used instead
738 of setting the environment variables NLS_LANG and NLS_NCHAR.
739 #) Use None instead of 0 for items in the :attr:`Cursor.description` attribute
740 that do not have any validity.
741 #) Changed driver name to match informal driver name standard used by Oracle
742 for other drivers.
743 #) Add check for maximum of 10,000 parameters when calling a stored procedure
744 or function in order to prevent a possible improper memory access from
745 taking place.
746 #) Removed -mno-cygwin compile flag since it is no longer used in newer
747 versions of the gcc compiler for Cygwin.
748 #) Simplified test suite by combining Python 2 and 3 scripts into one script
749 and separated out 12.1 features into a single script.
750 #) Updated samples to use code that works on both Python 2 and 3
751 #) Added support for pickling/unpickling error objects
752 (`Issue #23 <https://bitbucket.org/anthony_tuininga/cx_oracle/issues/23>`__)
753 #) Dropped support for callbacks on OCI functions.
754 #) Removed deprecated types UNICODE, FIXED_UNICODE and LONG_UNICODE (use
755 NCHAR, FIXED_NCHAR and LONG_NCHAR instead).
756 #) Increased default array size to 100 (from 50) to match other drivers.
757 #) Added support for setting the :attr:`~Connection.internal_name` and
758 :attr:`~Connection.external_name` on the connection directly. The use of
759 the twophase parameter is now deprecated. Applications should set the
760 internal_name and external_name attributes directly to a value appropriate
761 to the application.
762 #) Added support for using application context when
763 :meth:`creating a connection <cx_Oracle.Connection>`. This should be used
764 in preference to the module, action and clientinfo parameters which are now
765 deprecated.
766 #) Reworked database change notification and continuous query notification to
767 more closely align with the PL/SQL implementation and prepare for sending
768 notifications for AQ messages. The following changes were made:
769
770 - added constant :data:`~cx_Oracle.SUBSCR_QOS_BEST_EFFORT` to replace
771 deprecated constant SUBSCR_CQ_QOS_BEST_EFFORT
772 - added constant :data:`~cx_Oracle.SUBSCR_QOS_QUERY` to replace
773 deprecated constant SUBSCR_CQ_QOS_QUERY
774 - added constant :data:`~cx_Oracle.SUBSCR_QOS_DEREG_NFY` to replace
775 deprecated constant SUBSCR_QOS_PURGE_ON_NTFN
776 - added constant :data:`~cx_Oracle.SUBSCR_QOS_ROWIDS` to replace parameter
777 rowids for method :meth:`Connection.subscribe()`
778 - deprecated parameter cqqos for method :meth:`Connection.subscribe()`. The
779 qos parameter should be used instead.
780 - dropped constants SUBSCR_CQ_QOS_CLQRYCACHE, SUBSCR_QOS_HAREG,
781 SUBSCR_QOS_MULTICBK, SUBSCR_QOS_PAYLOAD, SUBSCR_QOS_REPLICATE, and
782 SUBSCR_QOS_SECURE since they were never actually used
783 #) Deprecated use of the numbersAsStrings attribute on cursors. An output type
784 handler should be used instead.
785
786
787 Version 5.2.1 (January 2016)
788 ----------------------------
789
790 #) Added support for Python 3.5.
791 #) Removed password attribute from connection and session pool objects in
792 order to promote best security practices (if stored in RAM in cleartext it
793 can be read in process dumps, for example). For those who would like to
794 retain this feature, a subclass of Connection could be used to store the
795 password.
796 #) Added optional parameter externalauth to SessionPool() which enables wallet
797 based or other external authentication mechanisms to be used.
798 #) Use the national character set encoding when required (when char set form
799 is SQLCS_NCHAR); otherwise, the wrong encoding would be used if the
800 environment variable NLS_NCHAR is set.
801 #) Added support for binding boolean values to PL/SQL blocks and stored
802 procedures (available in Oracle 12.1).
803
804
805 Version 5.2 (June 2015)
806 -----------------------
807
808 #) Added support for strings up to 32k characters (new in Oracle 12c).
809 #) Added support for getting array DML row counts (new in Oracle 12c).
810 #) Added support for fetching batch errors.
811 #) Added support for LOB values larger than 4 GB.
812 #) Added support for connections as SYSASM.
813 #) Added support for building without any configuration changes to the machine
814 when using instant client RPMs on Linux.
815 #) Added types NCHAR, FIXED_NCHAR and LONG_NCHAR to replace the types UNICODE,
816 FIXED_UNICODE and LONG_UNICODE (which are now deprecated). These types are
817 available in Python 3 as well so they can be used to specify the use of
818 NCHAR type fields when binding or using setinputsizes().
819 #) Fixed binding of booleans in Python 3.x.
820 #) Test suite now sets NLS_LANG if not already set.
821 #) Enhanced documentation for connection.action attribute and added note
822 on cursor.parse() method to make clear that DDL statements are executed
823 when parsed.
824 #) Removed remaining remnants of support Oracle 9i.
825 #) Added __version__ attribute to conform with PEP 396.
826 #) Ensure that sessions are released to the pool when calling
827 connection.close()
828 (`Issue #2 <https://bitbucket.org/anthony_tuininga/cx_oracle/issue/2>`__)
829 #) Fixed handling of datetime intervals
830 (`Issue #7 <https://bitbucket.org/anthony_tuininga/cx_oracle/issue/7>`__)
831
832
833 Version 5.1.3 (May 2014)
834 ------------------------
835
836 #) Added support for Oracle 12c.
837 #) Added support for Python 3.4.
838 #) Added support for query result set change notification. Thanks to Glen
839 Walker for the patch.
840 #) Ensure that in Python 3.x that NCHAR and NVARCHAR2 and NCLOB columns are
841 retrieved properly without conversion issues. Thanks to Joakim Andersson
842 for pointing out the issue and the possible solution.
843 #) Fix bug when an exception is caught and then another exception is raised
844 while handling that exception in Python 3.x. Thanks to Boris Dzuba for
845 pointing out the issue and providing a test case.
846 #) Enhance performance returning integers between 10 and 18 digits on 64-bit
847 platforms that support it. Thanks for Shai Berger for the initial patch.
848 #) Fixed two memory leaks.
849 #) Fix to stop current_schema from throwing a MemoryError on 64-bit platforms
850 on occasion. Thanks to Andrew Horton for the fix.
851 #) Class name of cursors changed to real name cx_Oracle.Cursor.
852
853
854 Version 5.1.2 (July 2012)
855 -------------------------
856
857 #) Added support for LONG_UNICODE which is a type used to handle long unicode
858 strings. These are not explicitly supported in Oracle but can be used to
859 bind to NCLOB, for example, without getting the error "unimplemented or
860 unreasonable conversion requested".
861 #) Set the row number in a cursor when executing PL/SQL blocks as requested
862 by Robert Ritchie.
863 #) Added support for setting the module, action and client_info attributes
864 during connection so that logon triggers will see the supplied values, as
865 requested by Rodney Barnett.
866
867
868 Version 5.1.1 (October 2011)
869 ----------------------------
870
871 #) Simplify management of threads for callbacks performed by database change
872 notification and eliminate a crash that occurred under high load in
873 certain situations. Thanks to Calvin S. for noting the issue and suggesting
874 a solution and testing the patch.
875 #) Force server detach on close so that the connection is completely closed
876 and not just the session as before.
877 #) Force use of OCI_UTF16ID for NCLOBs as using the default character set
878 would result in ORA-03127 with Oracle 11.2.0.2 and UTF8 character set.
879 #) Avoid attempting to clear temporary LOBs a second time when destroying the
880 variable as in certain situations this results in spurious errors.
881 #) Added additional parameter service_name to makedsn() which can be used to
882 use the service_name rather than the SID in the DSN string that is
883 generated.
884 #) Fix cursor description in test suite to take into account the number of
885 bytes per character.
886 #) Added tests for NCLOBS to the test suite.
887 #) Removed redundant code in setup.py for calculating the library path.
888
889
890 Version 5.1 (March 2011)
891 ------------------------
892
893 #) Remove support for UNICODE mode and permit Unicode to be passed through in
894 everywhere a string may be passed in. This means that strings will be
895 passed through to Oracle using the value of the NLS_LANG environment
896 variable in Python 3.x as well. Doing this eliminated a bunch of problems
897 that were discovered by using UNICODE mode and also removed an unnecessary
898 restriction in Python 2.x that Unicode could not be used in connect strings
899 or SQL statements, for example.
900 #) Added support for creating an empty object variable via a named type, the
901 first step to adding full object support.
902 #) Added support for Python 3.2.
903 #) Account for lib64 used on x86_64 systems. Thanks to Alex Wood for supplying
904 the patch.
905 #) Clear up potential problems when calling cursor.close() ahead of the
906 cursor being freed by going out of scope.
907 #) Avoid compilation difficulties on AIX5 as OCIPing does not appear to be
908 available on that platform under Oracle 10g Release 2. Thanks to
909 Pierre-Yves Fontaniere for the patch.
910 #) Free temporary LOBs prior to each fetch in order to avoid leaking them.
911 Thanks to Uwe Hoffmann for the initial patch.
912
913
914 Version 5.0.4 (July 2010)
915 -------------------------
916
917 #) Added support for Python 2.7.
918 #) Added support for new parameter (port) for subscription() call which allows
919 the client to specify the listening port for callback notifications from
920 the database server. Thanks to Geoffrey Weber for the initial patch.
921 #) Fixed compilation under Oracle 9i.
922 #) Fixed a few error messages.
923
924
925 Version 5.0.3 (February 2010)
926 -----------------------------
927
928 #) Added support for 64-bit Windows.
929 #) Added support for Python 3.1 and dropped support for Python 3.0.
930 #) Added support for keyword parameters in cursor.callproc() and
931 cursor.callfunc().
932 #) Added documentation for the UNICODE and FIXED_UNICODE variable types.
933 #) Added extra link arguments required for Mac OS X as suggested by Jason
934 Woodward.
935 #) Added additional error codes to the list of error codes that raise
936 OperationalError rather than DatabaseError.
937 #) Fixed calculation of display size for strings with national database
938 character sets that are not the default AL16UTF16.
939 #) Moved the resetting of the setinputsizes flag before the binding takes
940 place so that if an error takes place and a new statement is prepared
941 subsequently, spurious errors will not occur.
942 #) Fixed compilation with Oracle 10g Release 1.
943 #) Tweaked documentation based on feedback from a number of people.
944 #) Added support for running the test suite using "python setup.py test"
945 #) Added support for setting the CLIENT_IDENTIFIER value in the v$session
946 table for connections.
947 #) Added exception when attempting to call executemany() with arrays which is
948 not supported by the OCI.
949 #) Fixed bug when converting from decimal would result in OCI-22062 because
950 the locale decimal point was not a period. Thanks to Amaury Forgeot d'Arc
951 for the solution to this problem.
952
953
954 Version 5.0.2 (May 2009)
955 ------------------------
956
957 #) Fix creation of temporary NCLOB values and the writing of NCLOB values in
958 non Unicode mode.
959 #) Re-enabled parsing of non select statements as requested by Roy Terrill.
960 #) Implemented a parse error offset as requested by Catherine Devlin.
961 #) Removed lib subdirectory when forcing RPATH now that the library directory
962 is being calculated exactly in setup.py.
963 #) Added an additional cast in order to support compiling by Microsoft
964 Visual C++ 2008 as requested by Marco de Paoli.
965 #) Added additional include directory to setup.py in order to support
966 compiling by Microsoft Visual Studio was requested by Jason Coombs.
967 #) Fixed a few documentation issues.
968
969
970 Version 5.0.1 (February 2009)
971 -----------------------------
972
973 #) Added support for database change notification available in Oracle 10g
974 Release 2 and higher.
975 #) Fix bug where NCLOB data would be corrupted upon retrieval (non Unicode
976 mode) or would generate exception ORA-24806 (LOB form mismatch). Oracle
977 insists upon differentiating between CLOB and NCLOB no matter which
978 character set is being used for retrieval.
979 #) Add new attributes size, bufferSize and numElements to variable objects,
980 deprecating allocelems (replaced by numElements) and maxlength (replaced
981 by bufferSize)
982 #) Avoid increasing memory allocation for strings when using variable width
983 character sets and increasing the number of elements in a variable during
984 executemany().
985 #) Tweaked code in order to ensure that cx_Oracle can compile with Python
986 3.0.1.
987
988
989 Version 5.0 (December 2008)
990 ---------------------------
991
992 #) Added support for Python 3.0 with much help from Amaury Forgeot d'Arc.
993 #) Removed support for Python 2.3 and Oracle 8i.
994 #) Added support for full unicode mode in Python 2.x where all strings are
995 passed in and returned as unicode (module must be built in this mode)
996 rather than encoded strings
997 #) nchar and nvarchar columns now return unicode instead of encoded strings
998 #) Added support for an output type handler and/or an input type handler to be
999 specified at the connection and cursor levels.
1000 #) Added support for specifying both input and output converters for variables
1001 #) Added support for specifying the array size of variables that are created
1002 using the cursor.var() method
1003 #) Added support for events mode and database resident connection pooling
1004 (DRCP) in Oracle 11g.
1005 #) Added support for changing the password during construction of a new
1006 connection object as well as after the connection object has been created
1007 #) Added support for the interval day to second data type in Oracle,
1008 represented as datetime.timedelta objects in Python.
1009 #) Added support for getting and setting the current_schema attribute for a
1010 session
1011 #) Added support for proxy authentication in session pools as requested by
1012 Michael Wegrzynek (and thanks for the initial patch as well).
1013 #) Modified connection.prepare() to return a boolean indicating if a
1014 transaction was actually prepared in order to avoid the error ORA-24756
1015 (transaction does not exist).
1016 #) Raise a cx_Oracle.Error instance rather than a string for column
1017 truncation errors as requested by Helge Tesdal.
1018 #) Fixed handling of environment handles in session pools in order to allow
1019 session pools to fetch objects without exceptions taking place.
1020
1021
1022 Older releases
1023 ##############
1024
1025 Version 4.4.1 (October 2008)
1026 ----------------------------
1027
1028 #) Make the bind variables and fetch variables accessible although they need
1029 to be treated carefully since they are used internally; support added for
1030 forward compatibility with version 5.x.
1031 #) Include the "cannot insert null value" in the list of errors that are
1032 treated as integrity errors as requested by Matt Boersma.
1033 #) Use a cx_Oracle.Error instance rather than a string to hold the error when
1034 truncation (ORA-1406) takes place as requested by Helge Tesdal.
1035 #) Added support for fixed char, old style varchar and timestamp attribute
1036 values in objects.
1037 #) Tweaked setup.py to check for the Oracle version up front rather than
1038 during the build in order to produce more meaningful errors and simplify
1039 the code.
1040 #) In setup.py added proper detection for the instant client on Mac OS X as
1041 recommended by Martijn Pieters.
1042 #) In setup.py, avoided resetting the extraLinkArgs on Mac OS X as doing so
1043 prevents simple modification where desired as expressed by Christian
1044 Zagrodnick.
1045 #) Added documentation on exception handling as requested by Andreas Mock, who
1046 also graciously provided an initial patch.
1047 #) Modified documentation indicating that the password attribute on connection
1048 objects can be written.
1049 #) Added documentation warning that parameters not passed in during subsequent
1050 executions of a statement will retain their original values as requested by
1051 Harald Armin Massa.
1052 #) Added comments indicating that an Oracle client is required since so many
1053 people find this surprising.
1054 #) Removed all references to Oracle 8i from the documentation and version 5.x
1055 will eliminate all vestiges of support for this version of the Oracle
1056 client.
1057 #) Added additional link arguments for Cygwin as requested by Rob Gillen.
1058
1059
1060 Version 4.4 (June 2008)
1061 -----------------------
1062
1063 #) Fix setup.py to handle the Oracle instant client and Oracle XE on both
1064 Linux and Windows as pointed out by many. Thanks also to the many people
1065 who also provided patches.
1066 #) Set the default array size to 50 instead of 1 as the DB API suggests
1067 because the performance difference is so drastic and many people have
1068 recommended that the default be changed.
1069 #) Added Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS around each blocking
1070 call for LOBs as requested by Jason Conroy who also provided an initial
1071 patch and performed a number of tests that demonstrate the new code is much
1072 more responsive.
1073 #) Add support for acquiring cursor.description after a parse.
1074 #) Defer type assignment when performing executemany() until the last possible
1075 moment if the value being bound in is null as suggested by Dragos Dociu.
1076 #) When dropping a connection from the pool, ignore any errors that occur
1077 during the rollback; unfortunately, Oracle decides to commit data even when
1078 dropping a connection from the pool instead of rolling it back so the
1079 attempt still has to be made.
1080 #) Added support for setting CLIENT_DRIVER in V$SESSION_CONNECT_INFO in Oracle
1081 11g and higher.
1082 #) Use cx_Oracle.InterfaceError rather than the builtin RuntimeError when
1083 unable to create the Oracle environment object as requested by Luke Mewburn
1084 since the error is specific to Oracle and someone attempting to catch any
1085 exception cannot simply use cx_Oracle.Error.
1086 #) Translated some error codes to OperationalError as requested by Matthew
1087 Harriger; translated if/elseif/else logic to switch statement to make it
1088 more readable and to allow for additional translation if desired.
1089 #) Transformed documentation to new format using restructured text. Thanks to
1090 Waldemar Osuch for contributing the initial draft of the new documentation.
1091 #) Allow the password to be overwritten by a new value as requested by Alex
1092 VanderWoude; this value is retained as a convenience to the user and not
1093 used by anything in the module; if changed externally it may be convenient
1094 to keep this copy up to date.
1095 #) Cygwin is on Windows so should be treated in the same way as noted by
1096 Matthew Cahn.
1097 #) Add support for using setuptools if so desired as requested by Shreya
1098 Bhatt.
1099 #) Specify that the version of Oracle 10 that is now primarily used is 10.2,
1100 not 10.1.
1101
1102
1103 Version 4.3.3 (October 2007)
1104 ----------------------------
1105
1106 #) Added method ping() on connections which can be used to test whether or not
1107 a connection is still active (available in Oracle 10g R2).
1108 #) Added method cx_Oracle.clientversion() which returns a 5-tuple giving the
1109 version of the client that is in use (available in Oracle 10g R2).
1110 #) Added methods startup() and shutdown() on connections which can be used to
1111 startup and shutdown databases (available in Oracle 10g R2).
1112 #) Added support for Oracle 11g.
1113 #) Added samples directory which contains a handful of scripts containing
1114 sample code for more advanced techniques. More will follow in future
1115 releases.
1116 #) Prevent error "ORA-24333: zero iteration count" when calling executemany()
1117 with zero rows as requested by Andreas Mock.
1118 #) Added methods __enter__() and __exit__() on connections to support using
1119 connections as context managers in Python 2.5 and higher. The context
1120 managed is the transaction state. Upon exit the transaction is either
1121 rolled back or committed depending on whether an exception took place or
1122 not.
1123 #) Make the search for the lib32 and lib64 directories automatic for all
1124 platforms.
1125 #) Tweak the setup configuration script to include all of the metadata and
1126 allow for building the module within another setup configuration script
1127 #) Include the Oracle version in addition to the Python version in the build
1128 directories that are created and in the names of the binary packages that
1129 are created.
1130 #) Remove unnecessary dependency on win32api to build module on Windows.
1131
1132
1133 Version 4.3.2 (August 2007)
1134 ---------------------------
1135
1136 #) Added methods open(), close(), isopen() and getchunksize() in order to
1137 improve performance of reading/writing LOB values in chunks.
1138 #) Fixed support for native doubles and floats in Oracle 10g; added new type
1139 NATIVE_FLOAT to allow specification of a variable of that specific type
1140 where desired. Thanks to D.R. Boxhoorn for pointing out the fact that this
1141 was not working properly when the arraysize was anything other than 1.
1142 #) When calling connection.begin(), only create a new tranasction handle if
1143 one is not already associated with the connection. Thanks to Andreas Mock
1144 for discovering this and for Amaury Forgeot d'Arc for diagnosing the
1145 problem and pointing the way to a solution.
1146 #) Added attribute cursor.rowfactory which allows a method to be called for
1147 each row that is returned; this is about 20% faster than calling the method
1148 in Python using the idiom [method(\*r) for r in cursor].
1149 #) Attempt to locate an Oracle installation by looking at the PATH if the
1150 environment variable ORACLE_HOME is not set; this is of primary use on
1151 Windows where this variable should not normally be set.
1152 #) Added support for autocommit mode as requested by Ian Kelly.
1153 #) Added support for connection.stmtcachesize which allows for both reading
1154 and writing the size of the statement cache size. This parameter can make a
1155 huge difference with the length of time taken to prepare statements. Added
1156 support for setting the statement tag when preparing a statement. Both of
1157 these were requested by Bjorn Sandberg who also provided an initial patch.
1158 #) When copying the value of a variable, copy the return code as well.
1159
1160
1161 Version 4.3.1 (April 2007)
1162 --------------------------
1163
1164 #) Ensure that if the client buffer size exceeds 4000 bytes that the server
1165 buffer size does not as strings may only contain 4000 bytes; this allows
1166 handling of multibyte character sets on the server as well as the client.
1167 #) Added support for using buffer objects to populate binary data and made the
1168 Binary() constructor the buffer type as requested by Ken Mason.
1169 #) Fix potential crash when using full optimization with some compilers.
1170 Thanks to Aris Motas for noticing this and providing the initial patch and
1171 to Amaury Forgeot d'Arc for providing an even simpler solution.
1172 #) Pass the correct charset form in to the write call in order to support
1173 writing to national character set LOB values properly. Thanks to Ian Kelly
1174 for noticing this discrepancy.
1175
1176
1177 Version 4.3 (March 2007)
1178 ------------------------
1179
1180 #) Added preliminary support for fetching Oracle objects (SQL types) as
1181 requested by Kristof Beyls (who kindly provided an initial patch).
1182 Additional work needs to be done to support binding and updating objects
1183 but the basic structure is now in place.
1184 #) Added connection.maxBytesPerCharacter which indicates the maximum number of
1185 bytes each character can use; use this value to also determine the size of
1186 local buffers in order to handle discrepancies between the client character
1187 set and the server character set. Thanks to Andreas Mock for providing the
1188 initial patch and working with me to resolve this issue.
1189 #) Added support for querying native floats in Oracle 10g as requested by
1190 Danny Boxhoorn.
1191 #) Add support for temporary LOB variables created via PL/SQL instead of only
1192 directly by cx_Oracle; thanks to Henning von Bargen for discovering this
1193 problem.
1194 #) Added support for specifying variable types using the builtin types int,
1195 float, str and datetime.date which allows for finer control of what type of
1196 Python object is returned from cursor.callfunc() for example.
1197 #) Added support for passing booleans to callproc() and callfunc() as
1198 requested by Anana Aiyer.
1199 #) Fixed support for 64-bit environments in Python 2.5.
1200 #) Thanks to Filip Ballegeer and a number of his co-workers, an intermittent
1201 crash was tracked down; specifically, if a connection is closed, then the
1202 call to OCIStmtRelease() will free memory twice. Preventing the call when
1203 the connection is closed solves the problem.
1204
1205
1206 Version 4.2.1 (September 2006)
1207 ------------------------------
1208
1209 #) Added additional type (NCLOB) to handle CLOBs that use the national
1210 character set as requested by Chris Dunscombe.
1211 #) Added support for returning cursors from functions as requested by Daniel
1212 Steinmann.
1213 #) Added support for getting/setting the "get" mode on session pools as
1214 requested by Anand Aiyer.
1215 #) Added support for binding subclassed cursors.
1216 #) Fixed binding of decimal objects with absolute values less than 0.1.
1217
1218
1219 Version 4.2 (July 2006)
1220 -----------------------
1221
1222 #) Added support for parsing an Oracle statement as requested by Patrick
1223 Blackwill.
1224 #) Added support for BFILEs at the request of Matthew Cahn.
1225 #) Added support for binding decimal.Decimal objects to cursors.
1226 #) Added support for reading from NCLOBs as requested by Chris Dunscombe.
1227 #) Added connection attributes encoding and nencoding which return the IANA
1228 character set name for the character set and national character set in use
1229 by the client.
1230 #) Rework module initialization to use the techniques recommended by the
1231 Python documentation as one user was experiencing random segfaults due
1232 to the use of the module dictionary after the initialization was complete.
1233 #) Removed support for the OPT_Threading attribute. Use the threaded keyword
1234 when creating connections and session pools instead.
1235 #) Removed support for the OPT_NumbersAsStrings attribute. Use the
1236 numbersAsStrings attribute on cursors instead.
1237 #) Use type long rather than type int in order to support long integers on
1238 64-bit machines as reported by Uwe Hoffmann.
1239 #) Add cursor attribute "bindarraysize" which is defaulted to 1 and is used
1240 to determine the size of the arrays created for bind variables.
1241 #) Added repr() methods to provide something a little more useful than the
1242 standard type name and memory address.
1243 #) Added keyword parameter support to the functions that imply such in the
1244 documentation as requested by Harald Armin Massa.
1245 #) Treat an empty dictionary passed through to cursor.execute() as keyword
1246 parameters the same as if no keyword parameters were specified at all, as
1247 requested by Fabien Grumelard.
1248 #) Fixed memory leak when a LOB read would fail.
1249 #) Set the LDFLAGS value in the environment rather than directly in the
1250 setup.py file in order to satisfy those who wish to enable the use of
1251 debugging symbols.
1252 #) Use __DATE__ and __TIME__ to determine the date and time of the build
1253 rather than passing it through directly.
1254 #) Use Oracle types and add casts to reduce warnings as requested by Amaury
1255 Forgeot d'Arc.
1256 #) Fixed typo in error message.
1257
1258
1259 Version 4.1.2 (December 2005)
1260 -----------------------------
1261
1262 #) Restore support of Oracle 9i features when using the Oracle 10g client.
1263
1264
1265 Version 4.1.1 (December 2005)
1266 -----------------------------
1267
1268 #) Add support for dropping a connection from a session pool.
1269 #) Add support for write only attributes "module", "action" and "clientinfo"
1270 which work only in Oracle 10g as requested by Egor Starostin.
1271 #) Add support for pickling database errors.
1272 #) Use the previously created bind variable as a template if available when
1273 creating a new variable of a larger size. Thanks to Ted Skolnick for the
1274 initial patch.
1275 #) Fixed tests to work properly in the Python 2.4 environment where dates and
1276 timestamps are different Python types. Thanks to Henning von Bargen for
1277 pointing this out.
1278 #) Added additional directories to search for include files and libraries in
1279 order to better support the Oracle 10g instant client.
1280 #) Set the internal fetch number to 0 in order to satisfy very picky source
1281 analysis tools as requested by Amaury Fogeot d'Arc.
1282 #) Improve the documentation for building and installing the module from
1283 source as some people are unaware of the standard methods for building
1284 Python modules using distutils.
1285 #) Added note in the documentation indicating that the arraysize attribute
1286 can drastically affect performance of queries since this seems to be a
1287 common misunderstanding of first time users of cx_Oracle.
1288 #) Add a comment indicating that on HP-UX Itanium with Oracle 10g the library
1289 ttsh10 must alos be linked against. Thanks to Bernard Delmee for the
1290 information.
1291
1292
1293 Version 4.1 (January 2005)
1294 --------------------------
1295
1296 #) Fixed bug where subclasses of Cursor do not pass the connection in the
1297 constructor causing a segfault.
1298 #) DDL statements must be reparsed before execution as noted by Mihai
1299 Ibanescu.
1300 #) Add support for setting input sizes by position.
1301 #) Fixed problem with catching an exception during execute and then still
1302 attempting to perform a fetch afterwards as noted by Leith Parkin.
1303 #) Rename the types so that they can be pickled and unpickled. Thanks to Harri
1304 Pasanen for pointing out the problem.
1305 #) Handle invalid NLS_LANG setting properly (Oracle seems to like to provide a
1306 handle back even though it is invalid) and determine the number of bytes
1307 per character in order to allow for proper support in the future of
1308 multibyte and variable width character sets.
1309 #) Remove date checking from the native case since Python already checks that
1310 dates are valid; enhance error message when invalid dates are encountered
1311 so that additional processing can be done.
1312 #) Fix bug executing SQL using numeric parameter names with predefined
1313 variables (such as what takes place when calling stored procedures with out
1314 parameters).
1315 #) Add support for reading CLOB values using multibyte or variable length
1316 character sets.
1317
1318
1319 Version 4.1 beta 1 (September 2004)
1320 -----------------------------------
1321
1322 #) Added support for Python 2.4. In Python 2.4, the datetime module is used
1323 for both binding and fetching of date and timestamp data. In Python 2.3,
1324 objects from the datetime module can be bound but the internal datetime
1325 objects will be returned from queries.
1326 #) Added pickling support for LOB and datetime data.
1327 #) Fully qualified the table name that was missing in an alter table
1328 statement in the setup test script as noted by Marc Gehling.
1329 #) Added a section allowing for the setting of the RPATH linker directive in
1330 setup.py as requested by Iustin Pop.
1331 #) Added code to raise a programming error exception when an attempt is made
1332 to access a LOB locator variable in a subsequent fetch.
1333 #) The username, password and dsn (tnsentry) are stored on the connection
1334 object when specified, regardless of whether or not a standard connection
1335 takes place.
1336 #) Added additional module level constant called "LOB" as requested by Joseph
1337 Canedo.
1338 #) Changed exception type to IntegrityError for constraint violations as
1339 requested by Joseph Canedo.
1340 #) If scale and precision are not specified, an attempt is made to return a
1341 long integer as requested by Joseph Canedo.
1342 #) Added workaround for Oracle bug which returns an invalid handle when the
1343 prepare call fails. Thanks to [email protected] for providing the code that
1344 demonstrated the problem.
1345 #) The cursor method arrayvar() will now accept the actual list so that it is
1346 not necessary to call cursor.arrayvar() followed immediately by
1347 var.setvalue().
1348 #) Fixed bug where attempts to execute the statement "None" with bind
1349 variables would cause a segmentation fault.
1350 #) Added support for binding by position (paramstyle = "numeric").
1351 #) Removed memory leak created by calls to OCIParamGet() which were not
1352 mirrored by calls to OCIDescriptorFree(). Thanks to Mihai Ibanescu for
1353 pointing this out and providing a patch.
1354 #) Added support for calling cursor.executemany() with statement None
1355 implying that the previously prepared statement ought to be executed.
1356 Thanks to Mihai Ibanescu for providing a patch.
1357 #) Added support for rebinding variables when a subsequent call to
1358 cursor.executemany() uses a different number of rows. Thanks to Mihai
1359 Ibanescu for supplying a patch.
1360 #) The microseconds are now displayed in datetime variables when nonzero
1361 similar to method used in the datetime module.
1362 #) Added support for binary_float and binary_double columns in Oracle 10g.
1363
1364
1365 Version 4.0.1 (February 2004)
1366 -----------------------------
1367
1368 #) Fixed bugs on 64-bit platforms that caused segmentation faults and bus
1369 errors in session pooling and determining the bind variables associated
1370 with a statement.
1371 #) Modified test suite so that 64-bit platforms are tested properly.
1372 #) Added missing commit statements in the test setup scripts. Thanks to Keith
1373 Lyon for pointing this out.
1374 #) Fix setup.py for Cygwin environments. Thanks to Doug Henderson for
1375 providing the necessary fix.
1376 #) Added support for compiling cx_Oracle without thread support. Thanks to
1377 Andre Reitz for pointing this out.
1378 #) Added support for a new keyword parameter called threaded on connections
1379 and session pools. This parameter defaults to False and indicates whether
1380 threaded mode ought to be used. It replaces the module level attribute
1381 OPT_Threading although examining the attribute will be retained until the
1382 next release at least.
1383 #) Added support for a new keyword parameter called twophase on connections.
1384 This parameter defaults to False and indicates whether support for two
1385 phase (distributed or global) transactions ought to be present. Note that
1386 support for distributed transactions is buggy when crossing major version
1387 boundaries (Oracle 8i to Oracle 9i for example).
1388 #) Ensure that the rowcount attribute is set properly when an exception is
1389 raised during execution. Thanks to Gary Aviv for pointing out this problem
1390 and its solution.
1391
1392
1393 Version 4.0 (December 2003)
1394 ---------------------------
1395
1396 #) Added support for subclassing connections, cursors and session pools. The
1397 changes involved made it necessary to drop support for Python 2.1 and
1398 earlier although a branch exists in CVS to allow for support of Python 2.1
1399 and earlier if needed.
1400 #) Connections and session pools can now be created with keyword parameters,
1401 not just sequential parameters.
1402 #) Queries now return integers whenever possible and long integers if the
1403 number will overflow a simple integer. Floats are only returned when it is
1404 known that the number is a floating point number or the integer conversion
1405 fails.
1406 #) Added initial support for user callbacks on OCI functions. See the
1407 documentation for more details.
1408 #) Add support for retrieving the bind variable names associated with a
1409 cursor with a new method bindnames().
1410 #) Add support for temporary LOB variables. This means that setinputsizes()
1411 can be used with the values CLOB and BLOB to create these temporary LOB
1412 variables and allow for the equivalent of empty_clob() and empty_blob()
1413 since otherwise Oracle will treat empty strings as NULL values.
1414 #) Automatically switch to long strings when the data size exceeds the
1415 maximum string size that Oracle allows (4000 characters) and raise an
1416 error if an attempt is made to set a string variable to a size that it
1417 does not support. This avoids truncation errors as reported by Jon Franz.
1418 #) Add support for global (distributed) transactions and two phase commit.
1419 #) Force the NLS settings for the session so that test tables are populated
1420 correctly in all circumstances; problems were noted by Ralf Braun and
1421 Allan Poulsen.
1422 #) Display error messages using the environment handle when the error handle
1423 has not yet been created; this provides better error messages during this
1424 rather rare situation.
1425 #) Removed memory leak in callproc() that was reported by Todd Whiteman.
1426 #) Make consistent the calls to manipulate memory; otherwise segfaults can
1427 occur when the pymalloc option is used, as reported by Matt Hoskins.
1428 #) Force a rollback when a session is released back to the session pool.
1429 Apparently the connections are not as stateless as Oracle's documentation
1430 suggests and this makes the logic consistent with normal connections.
1431 #) Removed module method attach(). This can be replaced with a call to
1432 Connection(handle=) if needed.
1433
1434
1435 Version 3.1 (August 2003)
1436 -------------------------
1437
1438 #) Added support for connecting with SYSDBA and SYSOPER access which is
1439 needed for connecting as sys in Oracle 9i.
1440 #) Only check the dictionary size if the variable is not NULL; otherwise, an
1441 error takes place which is not caught or cleared; this eliminates a
1442 spurious "Objects/dictobject.c:1258: bad argument to internal function" in
1443 Python 2.3.
1444 #) Add support for session pooling. This is only support for Oracle 9i but
1445 is amazingly fast -- about 100 times faster than connecting.
1446 #) Add support for statement caching when pooling sessions, this reduces the
1447 parse time considerably. Unfortunately, the Oracle OCI does not allow this
1448 to be easily turned on for normal sessions.
1449 #) Add method trim() on CLOB and BLOB variables for trimming the size.
1450 #) Add support for externally identified users; to use this feature leave the
1451 username and password fields empty when connecting.
1452 #) Add method cancel() on connection objects to cancel long running queries.
1453 Note that this only works on non-Windows platforms.
1454 #) Add method callfunc() on cursor objects to allow calling a function
1455 without using an anonymous PL/SQL block.
1456 #) Added documentation on objects that were not documented. At this point all
1457 objects, methods and constants in cx_Oracle have been documented.
1458 #) Added support for timestamp columns in Oracle 9i.
1459 #) Added module level method makedsn() which creates a data source name given
1460 the host, port and SID.
1461 #) Added constant "buildtime" which is the time when the module was built as
1462 an additional means of identifying the build that is in use.
1463 #) Binding a value that is incompatible to the previous value that was bound
1464 (data types do not match or array size is larger) will now result in a
1465 new bind taking place. This is more consistent with the DB API although
1466 it does imply a performance penalty when used.
1467
1468
1469 Version 3.0a (June 2003)
1470 ------------------------
1471
1472 #) Fixed bug where zero length PL/SQL arrays were being mishandled
1473 #) Fixed support for the data type "float" in Oracle; added one to the
1474 display size to allow for the sign of the number, if necessary; changed
1475 the display size of unconstrained numbers to 127, which is the largest
1476 number that Oracle can handle
1477 #) Added support for retrieving the description of a bound cursor before
1478 fetching it
1479 #) Fixed a couple of build issues on Mac OS X, AIX and Solaris (64-bit)
1480 #) Modified documentation slightly based on comments from several people
1481 #) Included files in MANIFEST that are needed to generate the binaries
1482 #) Modified test suite to work within the test environment at Computronix
1483 as well as within the packages that are distributed
1484
1485
1486 Version 3.0 (March 2003)
1487 ------------------------
1488
1489 #) Removed support for connection to Oracle7 databases; it is entirely
1490 possible that it will still work but I no longer have any way of testing
1491 and Oracle has dropped any meaningful support for Oracle7 anyway
1492 #) Fetching of strings is now done with predefined memory areas rather than
1493 dynamic memory areas; dynamic fetching of strings was causing problems
1494 with Oracle 9i in some instances and databases using a different character
1495 set other than US ASCII
1496 #) Fixed bug where segfault would occur if the '/' character preceded the '@'
1497 character in a connect string
1498 #) Added two new cursor methods var() and arrayvar() in order to eliminate
1499 the need for setinputsizes() when defining PL/SQL arrays and as a generic
1500 method of acquiring bind variables directly when needed
1501 #) Fixed support for binding cursors and added support for fetching cursors
1502 (these are known as ref cursors in PL/SQL).
1503 #) Eliminated discrepancy between the array size used internally and the
1504 array size specified by the interface user; this was done earlier to avoid
1505 bus errors on 64-bit platforms but another way has been found to get
1506 around that issue and a number of people were getting confused because of
1507 the discrepancy
1508 #) Added support for the attribute "connection" on cursors, an optional
1509 DB API extension
1510 #) Added support for passing a dictionary as the second parameter for the
1511 cursor.execute() method in order to comply with the DB API more closely;
1512 the method of passing parameters with keyword parameters is still supported
1513 and is in fact preferred
1514 #) Added support for the attribute "statement" on cursors which is a
1515 reference to the last SQL statement prepared or executed
1516 #) Added support for passing any sequence to callproc() rather than just
1517 lists as before
1518 #) Fixed bug where segfault would occur if the array size was changed after
1519 the cursor was executed but before it was fetched
1520 #) Ignore array size when performing executemany() and use the length of the
1521 list of parameters instead
1522 #) Rollback when connection is closed or destroyed to follow DB API rather
1523 than use the Oracle default (which is commit)
1524 #) Added check for array size too large causing an integer overflow
1525 #) Added support for iterators for Python 2.2 and above
1526 #) Added test suite based on PyUnitTest
1527 #) Added documentation in HTML format similar to the documentation for the
1528 core Python library
1529
1530
1531 Version 2.5a (August 2002)
1532 --------------------------
1533
1534 #) Fix problem with Oracle 9i and retrieving strings; it seems that Oracle 9i
1535 uses the correct method for dynamic callback but Oracle 8i will not work
1536 with that method so an #ifdef was added to check for the existence of an
1537 Oracle 9i feature; thanks to Paul Denize for discovering this problem
1538
1539
1540 Version 2.5 (July 2002)
1541 -----------------------
1542
1543 #) Added flag OPT_NoOracle7 which, if set, assumes that connections are being
1544 made to Oracle8 or higher databases; this allows for eliminating the
1545 overhead in performing this check at connect time
1546 #) Added flag OPT_NumbersAsStrings which, if set, returns all numbers as
1547 strings rather than integers or floats; this flag is used when defined
1548 variables are created (during select statements only)
1549 #) Added flag OPT_Threading which, if set, uses OCI threading mode; there is a
1550 significant performance degradation in this mode (about 15-20%) but it does
1551 allow threads to share connections (threadsafety level 2 according to the
1552 Python Database API 2.0); note that in order to support this, Oracle 8i or
1553 higher is now required
1554 #) Added Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS pairs where
1555 applicable to support threading during blocking OCI calls
1556 #) Added global method attach() to cx_Oracle to support attaching to an
1557 existing database handle (as provided by PowerBuilder, for example)
1558 #) Eliminated the cursor method fetchbinds() which was used for returning the
1559 list of bind variables after execution to get the values of out variables;
1560 the cursor method setinputsizes() was modified to return the list of bind
1561 variables and the cursor method execute() was modified to return the list
1562 of defined variables in the case of a select statement being executed;
1563 these variables have three methods available to them: getvalue([<pos>]) to
1564 get the value of a variable, setvalue(<pos>, <value>) to set its value and
1565 copy(<var>, <src_pos>, <targ_pos>) to copy the value from a variable in a
1566 more efficient manner than setvalue(getvalue())
1567 #) Implemented cursor method executemany() which expects a list of
1568 dictionaries for the parameters
1569 #) Implemented cursor method callproc()
1570 #) Added cursor method prepare() which parses (prepares) the statement for
1571 execution; subsequent execute() or executemany() calls can pass None as the
1572 statement which will imply use of the previously prepared statement; used
1573 for high performance only
1574 #) Added cursor method fetchraw() which will perform a raw fetch of the cursor
1575 returning the number of rows thus fetched; this is used to avoid the
1576 overhead of generating result sets; used for high performance only
1577 #) Added cursor method executemanyprepared() which is identical to the method
1578 executemany() except that it takes a single parameter which is the number
1579 of times to execute a previously prepared statement and it assumes that the
1580 bind variables already have their values set; used for high performance
1581 only
1582 #) Added support for rowid being returned in a select statement
1583 #) Added support for comparing dates returned by cx_Oracle
1584 #) Integrated patch from Andre Reitz to set the null ok flag in the
1585 description attribute of the cursor
1586 #) Integrated patch from Andre Reitz to setup.py to support compilation with
1587 Python 1.5
1588 #) Integrated patch from Benjamin Kearns to setup.py to support compilation
1589 on Cygwin
1590
1591
1592 Version 2.4 (January 2002)
1593 --------------------------
1594
1595 #) String variables can now be made any length (previously restricted to the
1596 64K limit imposed by Oracle for default binding); use the type
1597 cx_Oracle.LONG_STRING as the parameter to setinputsizes() for binding in
1598 string values larger than 4000 bytes.
1599 #) Raw and long raw columns are now supported; use the types cx_Oracle.BINARY
1600 and cx_Oracle.LONG_BINARY as the parameter to setinputsizes() for binding
1601 in values of these types.
1602 #) Functions DateFromTicks(), TimeFromTicks() and TimestampFromTicks()
1603 are now implemented.
1604 #) Function cursor.setoutputsize() implemented
1605 #) Added the ability to bind arrays as out parameters to procedures; use the
1606 format [cx_Oracle.<DataType>, <NumElems>] as the input to the function
1607 setinputsizes() for binding arrays
1608 #) Discovered from the Oracle 8.1.6 version of the documentation of the OCI
1609 libraries, that the size of the memory location required for the precision
1610 variable is larger than the printed documentation says; this was causing a
1611 problem with the code on the Sun platform.
1612 #) Now support building RPMs for Linux.
1613
1614
1615 Version 2.3 (October 2001)
1616 --------------------------
1617
1618 #) Incremental performance enhancements (dealing with reusing cursors and
1619 bind handles)
1620 #) Ensured that arrays of integers with a single float in them are all
1621 treated as floats, as suggested by Martin Koch.
1622 #) Fixed code dealing with scale and precision for both defining a numeric
1623 variable and for providing the cursor description; this eliminates the
1624 problem of an underflow error (OCI-22054) when retrieving data with
1625 non-zero scale.
1626
1627
1628 Version 2.2 (July 2001)
1629 -----------------------
1630
1631 #) Upgraded thread safety to level 1 (according to the Python DB API 2.0) as
1632 an internal project required the ability to share the module between
1633 threads.
1634 #) Added ability to bind ref cursors to PL/SQL blocks as requested by
1635 Brad Powell.
1636 #) Added function write(Value, [Offset]) to LOB variables as requested by
1637 Matthias Kirst.
1638 #) Procedure execute() on Cursor objects now permits a value None for the
1639 statement which means that the previously prepared statement will be
1640 executed and any input sizes set earlier will be retained. This was done to
1641 improve the performance of scripts that execute one statement many times.
1642 #) Modified module global constants BINARY and DATETIME to point to the
1643 external representations of those types so that the expression
1644 type(var) == cx_Oracle.DATETIME will work as expected.
1645 #) Added global constant version to provide means of determining the current
1646 version of the module.
1647 #) Modified error checking routine to distinguish between an Oracle error and
1648 invalid handles.
1649 #) Added error checking to avoid setting the value of a bind variable to a
1650 value that it cannot support and raised an exception to indicate this fact.
1651 #) Added extra compile arguments for the AIX platform as suggested by Jehwan
1652 Ryu.
1653 #) Added section to the README to indicate the method for a binary
1654 installation as suggested by Steve Holden.
1655 #) Added simple usage example as requested by many people.
1656 #) Added HISTORY file to the distribution.
1657
+0
-186
doc/src/session_pool.rst less more
0 .. _sesspool:
1
2 ******************
3 SessionPool Object
4 ******************
5
6 .. note::
7
8 This object is an extension to the DB API.
9
10
11 .. method:: SessionPool.acquire(user=None, password=None, cclass=None, \
12 purity=cx_Oracle.ATTR_PURITY_DEFAULT, tag=None, matchanytag=False, \
13 shardingkey=[], supershardingkey=[])
14
15 Acquire a connection from the session pool and return a
16 :ref:`connection object <connobj>`.
17
18 If the pool is homogeneous, the user and password parameters cannot be
19 specified. If they are, an exception will be raised.
20
21 The cclass parameter, if specified, should be a string corresponding to the
22 connection class for database resident connection pooling (DRCP).
23
24 The purity parameter is expected to be one of
25 :data:`~cx_Oracle.ATTR_PURITY_NEW`, :data:`~cx_Oracle.ATTR_PURITY_SELF`, or
26 :data:`~cx_Oracle.ATTR_PURITY_DEFAULT`.
27
28 The tag parameter, if specified, is expected to be a string with name=value
29 pairs like "k1=v1;k2=v2" and will limit the sessions that can be returned
30 from a session pool unless the matchanytag parameter is set to True. In
31 that case sessions with the specified tag will be preferred over others,
32 but if no such sessions are available a session with a different tag may be
33 returned instead. In any case, untagged sessions will always be returned if
34 no sessions with the specified tag are available. Sessions are tagged when
35 they are :meth:`released <SessionPool.release>` back to the pool.
36
37 The shardingkey and supershardingkey parameters, if specified, are expected
38 to be a sequence of values which will be used to identify the database
39 shard to connect to. Currently only strings are supported for the key
40 values.
41
42 .. attribute:: SessionPool.busy
43
44 This read-only attribute returns the number of sessions currently acquired.
45
46
47 .. method:: SessionPool.close(force=False)
48
49 Close the session pool now, rather than when the last reference to it is
50 released, which makes it unsable for further work.
51
52 If any connections have been acquired and not released back to the pool
53 this method will fail unless the force parameter is set to True.
54
55
56 .. method:: SessionPool.drop(connection)
57
58 Drop the connection from the pool which is useful if the connection is no
59 longer usable (such as when the session is killed).
60
61
62 .. attribute:: SessionPool.dsn
63
64 This read-only attribute returns the TNS entry of the database to which a
65 connection has been established.
66
67
68 .. attribute:: SessionPool.homogeneous
69
70 This read-write boolean attribute indicates whether the pool is considered
71 homogeneous or not. If the pool is not homogeneous different authentication
72 can be used for each connection acquired from the pool.
73
74
75 .. attribute:: SessionPool.increment
76
77 This read-only attribute returns the number of sessions that will be
78 established when additional sessions need to be created.
79
80
81 .. attribute:: SessionPool.max
82
83 This read-only attribute returns the maximum number of sessions that the
84 session pool can control.
85
86
87 .. attribute:: SessionPool.max_lifetime_session
88
89 This read-write attribute returns the maximum length of time (in seconds)
90 that a pooled session may exist. Sessions that are in use will not be
91 closed. They become candidates for termination only when they are released
92 back to the pool and have existed for longer than max_lifetime_session
93 seconds. Note that termination only occurs when the pool is accessed. A
94 value of 0 means that there is no maximum length of time that a pooled
95 session may exist. This attribute is only available in Oracle Database
96 12.1.
97
98
99
100 .. versionadded:: 5.3
101
102
103 .. attribute:: SessionPool.min
104
105 This read-only attribute returns the number of sessions with which the
106 session pool was created and the minimum number of sessions that will be
107 controlled by the session pool.
108
109
110 .. attribute:: SessionPool.name
111
112 This read-only attribute returns the name assigned to the session pool by
113 Oracle.
114
115
116 .. attribute:: SessionPool.opened
117
118 This read-only attribute returns the number of sessions currently opened by
119 the session pool.
120
121
122 .. method:: SessionPool.release(connection, tag=None)
123
124 Release the connection back to the pool now, rather than whenever __del__
125 is called. The connection will be unusable from this point forward; an
126 Error exception will be raised if any operation is attempted with the
127 connection. Any cursors or LOBs created by the connection will also be
128 marked unusable and an Error exception will be raised if any operation is
129 attempted with them.
130
131 Internally, references to the connection are held by cursor objects,
132 LOB objects, etc. Once all of these references are released, the connection
133 itself will be released back to the pool automatically. Either control
134 references to these related objects carefully or explicitly release
135 connections back to the pool in order to ensure sufficient resources are
136 available.
137
138 If the tag is not None, it is expected to be a string with name=value pairs
139 like "k1=v1;k2=v2" and will override the value in the property
140 :attr:`Connection.tag`. If either :attr:`Connection.tag` or the tag
141 parameter are not None, the connection will be retagged when it is released
142 back to the pool.
143
144
145 .. attribute:: SessionPool.stmtcachesize
146
147 This read-write attribute specifies the size of the statement cache that
148 will be used as the starting point for any connections that are created by
149 the session pool. Once created, the connection's statement cache size can
150 only be changed by setting the stmtcachesize attribute on the connection
151 itself.
152
153 .. versionadded:: 6.0
154
155
156 .. attribute:: SessionPool.timeout
157
158 This read-write attribute specifies the time (in seconds) after which idle
159 sessions will be terminated in order to maintain an optimum number of open
160 sessions. Note that termination only occurs when the pool is accessed. A
161 value of 0 means that no idle sessions are terminated.
162
163
164 .. attribute:: SessionPool.tnsentry
165
166 This read-only attribute returns the TNS entry of the database to which a
167 connection has been established.
168
169
170 .. attribute:: SessionPool.username
171
172 This read-only attribute returns the name of the user which established the
173 connection to the database.
174
175
176 .. attribute:: SessionPool.wait_timeout
177
178 This read-write attribute specifies the time (in milliseconds) that the
179 caller should wait for a session to become available in the pool before
180 returning with an error. This value is only used if the getmode parameter
181 to :meth:`cx_Oracle.SessionPool()` was the value
182 :data:`cx_Oracle.SPOOL_ATTRVAL_TIMEDWAIT`.
183
184 .. versionadded:: 6.4
185
+0
-496
doc/src/soda.rst less more
0 .. _soda:
1
2 ****
3 SODA
4 ****
5
6 An overview of Simple Oracle Document Access (SODA) can be found
7 `here
8 <https://docs.oracle.com/en/database/oracle/simple-oracle-document-access>`__.
9
10 SODA requires Oracle Client 18.3 or higher and Oracle Database 18.1 and higher.
11 The role SODA_APP must be granted to the user.
12
13 SODA support in cx_Oracle is in Preview status and should not be used in
14 production. It will be supported with a future version of Oracle Client
15 libraries.
16
17 .. _sodadb:
18
19 --------------------
20 SODA Database Object
21 --------------------
22
23 .. note::
24
25 This object is an extension the DB API. It is returned by the method
26 :meth:`Connection.getSodaDatabase()`.
27
28
29 .. method:: SodaDatabase.createCollection(name, metadata=None, mapMode=False)
30
31 Creates a SODA collection with the given name and returns a new
32 :ref:`SODA collection object <sodacoll>`. If you try to create a
33 collection, and a collection with the same name and metadata already
34 exists, then that existing collection is opened without error.
35
36 If metadata is specified, it is expected to be a string containing valid
37 JSON or a dictionary that will be transformed into a JSON string. This JSON
38 permits you to specify the configuration of the collection including
39 storage options; specifying the presence or absence of columns for creation
40 timestamp, last modified timestamp and version; whether the collection can
41 store only JSON documents; and methods of key and version generation. The
42 default metadata creates a collection that only supports JSON documents and
43 uses system generated keys. See this `collection metadata reference
44 <https://www.oracle.com/pls/topic/
45 lookup?ctx=dblatest&id=GUID-49EFF3D3-9FAB-4DA6-BDE2-2650383566A3>`__
46 for more information.
47
48 If the mapMode parameter is set to True, the new collection is mapped to an
49 existing table instead of creating a table. If a collection is created in
50 this way, dropping the collection will not drop the existing table either.
51
52 .. versionadded:: 7.0
53
54
55 .. method:: SodaDatabase.createDocument(content, key=None, mediaType="application/json")
56
57 Creates a :ref:`SODA document <sodadoc>` usable for SODA write operations.
58 You only need to use this method if your collection requires
59 client-assigned keys or has non-JSON content; otherwise, you can pass your
60 content directly to SODA write operations. SodaDocument attributes
61 'createdOn', 'lastModified' and 'version' will be None.
62
63 The content parameter can be a dictionary or list which will be transformed
64 into a JSON string and then UTF-8 encoded. It can also be a string which
65 will be UTF-8 encoded or it can be a bytes object which will be stored
66 unchanged. If a bytes object is provided and the content is expected to be
67 JSON, note that SODA only supports UTF-8, UTF-16LE and UTF-16BE encodings.
68
69 The key parameter should only be supplied if the collection in which the
70 document is to be placed requires client-assigned keys.
71
72 The mediaType parameter should only be supplied if the collection in which
73 the document is to be placed supports non-JSON documents and the content
74 for this document is non-JSON. Using a standard MIME type for this value is
75 recommended but any string will be accepted.
76
77 .. versionadded:: 7.0
78
79
80 .. method:: SodaDatabase.getCollectionNames(startName=None, limit=0)
81
82 Returns a list of the names of collections in the database that match the
83 criteria, in alphabetical order.
84
85 If the startName parameter is specified, the list of names returned will
86 start with this value and also contain any names that fall after this value
87 in alphabetical order.
88
89 If the limit parameter is specified and is non-zero, the number of
90 collection names returned will be limited to this value.
91
92 .. versionadded:: 7.0
93
94
95 .. method:: SodaDatabase.openCollection(name)
96
97 Opens an existing collection with the given name and returns a new
98 :ref:`SODA collection object <sodacoll>`. If a collection with that name
99 does not exist, None is returned.
100
101 .. versionadded:: 7.0
102
103
104 .. _sodacoll:
105
106 ----------------------
107 SODA Collection Object
108 ----------------------
109
110 .. note::
111
112 This object is an extension the DB API. It is used to represent SODA
113 collections and is created by methods
114 :meth:`SodaDatabase.createCollection()` and
115 :meth:`SodaDatabase.openCollection()`.
116
117
118 .. method:: SodaCollection.createIndex(spec)
119
120 Creates an index on a SODA collection. The spec is expected to be a
121 dictionary or a JSON-encoded string. See this `overview
122 <https://www.oracle.com/pls/topic/
123 lookup?ctx=dblatest&id=GUID-4848E6A0-58A7-44FD-8D6D-A033D0CCF9CB>`__
124 for information on indexes in SODA.
125
126 Note that a commit should be performed before attempting to create an
127 index.
128
129 .. versionadded:: 7.0
130
131
132 .. method:: SodaCollection.drop()
133
134 Drops the collection from the database, if it exists. Note that if the
135 collection was created with mapMode set to True the underlying table will
136 not be dropped.
137
138 A boolean value is returned indicating if the collection was actually
139 dropped.
140
141 .. versionadded:: 7.0
142
143
144 .. method:: SodaCollection.dropIndex(name, force=False)
145
146 Drops the index with the specified name, if it exists.
147
148 The force parameter, if set to True, can be used to force the dropping of
149 an index that the underlying Oracle Database domain index doesn't normally
150 permit. This is only applicable to spatial and JSON search indexes.
151 See `here <https://www.oracle.com/pls/topic/
152 lookup?ctx=dblatest&id=GUID-F60F75DF-2866-4F93-BB7F-8FCE64BF67B6>`__
153 for more information.
154
155 A boolean value is returned indicating if the index was actually dropped.
156
157 .. versionadded:: 7.0
158
159
160 .. method:: SodaCollection.find()
161
162 This method is used to begin an operation that will act upon documents in
163 the collection. It creates and returns a
164 :ref:`SodaOperation object <sodaop>` which is used to specify the criteria
165 and the operation that will be performed on the documents that match that
166 criteria.
167
168 .. versionadded:: 7.0
169
170
171 .. method:: SodaCollection.getDataGuide()
172
173 Returns a :ref:`SODA document object <sodadoc>` containing property names,
174 data types and lengths inferred from the JSON documents in the collection.
175 It can be useful for exploring the schema of a collection. Note that this
176 method is only supported for JSON-only collections where a JSON search
177 index has been created with the 'dataguide' option enabled. If there are
178 no documents in the collection, None is returned.
179
180 .. versionadded:: 7.0
181
182
183 .. method:: SodaCollection.insertOne(doc)
184
185 Inserts a given document into the collection. The input document can be a
186 dictionary or list or an existing :ref:`SODA document object <sodadoc>`.
187
188 .. versionadded:: 7.0
189
190
191 .. method:: SodaCollection.insertOneAndGet(doc)
192
193 Similarly to :meth:`~SodaCollection.insertOne()` this method inserts a
194 given document into the collection. The only difference is that it
195 returns a :ref:`SODA Document object <sodadoc>`. Note that for performance
196 reasons the returned document does not contain the content.
197
198 .. versionadded:: 7.0
199
200
201 .. attribute:: SodaCollection.metadata
202
203 This read-only attribute returns a dicationary containing the metadata that
204 was used to create the collection. See this `collection metadata reference
205 <https://www.oracle.com/pls/topic/
206 lookup?ctx=dblatest&id=GUID-49EFF3D3-9FAB-4DA6-BDE2-2650383566A3>`__
207 for more information.
208
209 .. versionadded:: 7.0
210
211
212 .. attribute:: SodaCollection.name
213
214 This read-only attribute returns the name of the collection.
215
216 .. versionadded:: 7.0
217
218
219 .. _sodadoc:
220
221 --------------------
222 SODA Document Object
223 --------------------
224
225 .. note::
226
227 This object is an extension the DB API. It is returned by the methods
228 :meth:`SodaDatabase.createDocument()`,
229 :meth:`SodaOperation.getDocuments()` and
230 :meth:`SodaOperation.getOne()` as well as by iterating over
231 :ref:`SODA document cursors <sodadoccur>`.
232
233
234 .. attribute:: SodaDoc.createdOn
235
236 This read-only attribute returns the creation time of the document in
237 `ISO 8601 <https://www.iso.org/iso-8601-date-and-time-format.html>`__
238 format. Documents created by :meth:`SodaDatabase.createDocument()` or
239 fetched from collections where this attribute is not stored will return
240 None.
241
242 .. versionadded:: 7.0
243
244
245 .. method:: SodaDoc.getContent()
246
247 Returns the content of the document as a dictionary or list. This method
248 assumes that the content is application/json and will raise an exception if
249 this is not the case. If there is no content, however, None will be
250 returned.
251
252 .. versionadded:: 7.0
253
254
255 .. method:: SodaDoc.getContentAsBytes()
256
257 Returns the content of the document as a bytes object. If there is no
258 content, however, None will be returned.
259
260 .. versionadded:: 7.0
261
262
263 .. method:: SodaDoc.getContentAsString()
264
265 Returns the content of the document as a string. If the document encoding
266 is not known, UTF-8 will be used. If there is no content, however, None
267 will be returned.
268
269 .. versionadded:: 7.0
270
271
272 .. attribute:: SodaDoc.key
273
274 This read-only attribute returns the unique key assigned to this document.
275 Documents created by :meth:`SodaDatabase.createDocument()` may not have a
276 value assigned to them and return None.
277
278 .. versionadded:: 7.0
279
280
281 .. attribute:: SodaDoc.lastModified
282
283 This read-only attribute returns the last modified time of the document in
284 `ISO 8601 <https://www.iso.org/iso-8601-date-and-time-format.html>`__
285 format. Documents created by :meth:`SodaDatabase.createDocument()` or
286 fetched from collections where this attribute is not stored will return
287 None.
288
289 .. versionadded:: 7.0
290
291
292 .. attribute:: SodaDoc.mediaType
293
294 This read-only attribute returns the media type assigned to the document.
295 By convention this is expected to be a MIME type but no checks are
296 performed on this value. If a value is not specified when calling
297 :meth:`SodaDatabase.createDocument()` or the document is fetched from a
298 collection where this component is not stored, the string
299 "application/json" is returned.
300
301 .. versionadded:: 7.0
302
303
304 .. attribute:: SodaDoc.version
305
306 This read-only attribute returns the version assigned to this document.
307 Documents created by :meth:`SodaDatabase.createDocument()` or fetched
308 from collections where this attribute is not stored will return None.
309
310 .. versionadded:: 7.0
311
312
313 .. _sodadoccur:
314
315 ---------------------------
316 SODA Document Cursor Object
317 ---------------------------
318
319 .. note::
320
321 This object is an extension the DB API. It is returned by the method
322 :meth:`SodaOperation.getCursor()` and implements the iterator protocol.
323 Each iteration will return a :ref:`SODA document object <sodadoc>`.
324
325
326 .. method:: SodaDocCursor.close()
327
328 Close the cursor now, rather than whenever __del__ is called. The cursor
329 will be unusable from this point forward; an Error exception will be raised
330 if any operation is attempted with the cursor.
331
332 .. versionadded:: 7.0
333
334
335 .. _sodaop:
336
337 ---------------------
338 SODA Operation Object
339 ---------------------
340
341 .. note::
342
343 This object is an extension to the DB API. It represents an operation that
344 will be performed on all or some of the documents in a SODA collection. It
345 is created by the method :meth:`SodaCollection.find()`.
346
347
348 .. method:: SodaOperation.count()
349
350 Returns a count of the number of documents in the collection that match
351 the criteria. If :meth:`~SodaOperation.skip()` or
352 :meth:`~SodaOperation.limit()` were called on this object, an exception is
353 raised.
354
355 .. versionadded:: 7.0
356
357
358 .. method:: SodaOperation.filter(value)
359
360 Sets a filter specification for complex document queries and ordering of
361 JSON documents. Filter specifications must be provided as a dictionary or
362 JSON-encoded string and can include comparisons, regular expressions,
363 logical and spatial operators, among others. See the
364 `overview of SODA filter specifications
365 <https://www.oracle.com/pls/topic/
366 lookup?ctx=dblatest&id=GUID-CB09C4E3-BBB1-40DC-88A8-8417821B0FBE>`__
367 for more information.
368
369 As a convenience, the SodaOperation object is returned so that further
370 criteria can be specified by chaining methods together.
371
372 .. versionadded:: 7.0
373
374
375 .. method:: SodaOperation.getCursor()
376
377 Returns a :ref:`SODA Document Cursor object <sodadoccur>` that can be used
378 to iterate over the documents that match the criteria.
379
380 .. versionadded:: 7.0
381
382
383 .. method:: SodaOperation.getDocuments()
384
385 Returns a list of :ref:`SODA Document objects <sodadoc>` that match the
386 criteria.
387
388 .. versionadded:: 7.0
389
390
391 .. method:: SodaOperation.getOne()
392
393 Returns a single :ref:`SODA Document object <sodadoc>` that matches the
394 criteria. Note that if multiple documents match the criteria only the first
395 one is returned.
396
397 .. versionadded:: 7.0
398
399
400 .. method:: SodaOperation.key(value)
401
402 Specifies that the document with the specified key should be returned.
403 This causes any previous calls made to this method and
404 :meth:`~SodaOperation.keys()` to be ignored.
405
406 As a convenience, the SodaOperation object is returned so that further
407 criteria can be specified by chaining methods together.
408
409 .. versionadded:: 7.0
410
411
412 .. method:: SodaOperation.keys(seq)
413
414 Specifies that documents that match the keys found in the supplied sequence
415 should be returned. This causes any previous calls made to this method and
416 :meth:`~SodaOperation.key()` to be ignored.
417
418 As a convenience, the SodaOperation object is returned so that further
419 criteria can be specified by chaining methods together.
420
421 .. versionadded:: 7.0
422
423
424 .. method:: SodaOperation.limit(value)
425
426 Specifies that only the specified number of documents should be returned.
427 This method is only usable for read operations such as
428 :meth:`~SodaOperation.getCursor()` and
429 :meth:`~SodaOperation.getDocuments()`. For write operations, any value set
430 using this method is ignored.
431
432 As a convenience, the SodaOperation object is returned so that further
433 criteria can be specified by chaining methods together.
434
435 .. versionadded:: 7.0
436
437
438 .. method:: SodaOperation.remove()
439
440 Removes all of the documents in the collection that match the criteria. The
441 number of documents that have been removed is returned.
442
443 .. versionadded:: 7.0
444
445
446 .. method:: SodaOperation.replaceOne(doc)
447
448 Replaces a single document in the collection with the specified document.
449 The input document can be a dictionary or list or an existing
450 :ref:`SODA document object <sodadoc>`. A boolean indicating if a document
451 was replaced or not is returned.
452
453 Currently the method :meth:`~SodaOperation.key()` must be called before
454 this method can be called.
455
456 .. versionadded:: 7.0
457
458
459 .. method:: SodaOperation.replaceOneAndGet(doc)
460
461 Similarly to :meth:`~SodaOperation.replaceOne()`, this method replaces a
462 single document in the collection with the specified document. The only
463 difference is that it returns a :ref:`SODA document object <sodadoc>`.
464 Note that for performance reasons the returned document does not contain
465 the content.
466
467 .. versionadded:: 7.0
468
469
470 .. method:: SodaOperation.skip(value)
471
472 Specifies the number of documents that match the other criteria that will
473 be skipped. This method is only usable for read operations such as
474 :meth:`~SodaOperation.getCursor()` and
475 :meth:`~SodaOperation.getDocuments()`. For write operations, any value set
476 using this method is ignored.
477
478 As a convenience, the SodaOperation object is returned so that further
479 criteria can be specified by chaining methods together.
480
481 .. versionadded:: 7.0
482
483
484 .. method:: SodaOperation.version(value)
485
486 Specifies that documents with the specified version should be returned.
487 Typically this is used with :meth:`~SodaOperation.key()` to implement
488 optimistic locking, so that the write operation called later does not
489 affect a document that someone else has modified.
490
491 As a convenience, the SodaOperation object is returned so that further
492 criteria can be specified by chaining methods together.
493
494 .. versionadded:: 7.0
495
+0
-259
doc/src/subscription.rst less more
0 .. _subscrobj:
1
2 *******************
3 Subscription Object
4 *******************
5
6 .. note::
7
8 This object is an extension the DB API.
9
10
11 .. attribute:: Subscription.callback
12
13 This read-only attribute returns the callback that was registered when the
14 subscription was created.
15
16
17 .. attribute:: Subscription.connection
18
19 This read-only attribute returns the connection that was used to register
20 the subscription when it was created.
21
22
23 .. attribute:: Subscription.id
24
25 This read-only attribute returns the value 0.
26
27 .. deprecated:: 6.0
28 This attribute was never intended to be exposed and will be removed
29 in cx_Oracle 7.
30
31
32 .. attribute:: Subscription.ipAddress
33
34 This read-only attribute returns the IP address used for callback
35 notifications from the database server. If not set during construction,
36 this value is None.
37
38 .. versionadded:: 6.4
39
40
41 .. attribute:: Subscription.name
42
43 This read-only attribute returns the name used to register the subscription
44 when it was created.
45
46 .. versionadded:: 6.4
47
48
49 .. attribute:: Subscription.namespace
50
51 This read-only attribute returns the namespace used to register the
52 subscription when it was created.
53
54
55 .. attribute:: Subscription.operations
56
57 This read-only attribute returns the operations that will send
58 notifications for each table or query that is registered using this
59 subscription.
60
61
62 .. attribute:: Subscription.port
63
64 This read-only attribute returns the port used for callback notifications
65 from the database server. If not set during construction, this value is
66 zero.
67
68
69 .. attribute:: Subscription.protocol
70
71 This read-only attribute returns the protocol used to register the
72 subscription when it was created.
73
74
75 .. attribute:: Subscription.qos
76
77 This read-only attribute returns the quality of service flags used to
78 register the subscription when it was created.
79
80
81 .. method:: Subscription.registerquery(statement, [args])
82
83 Register the query for subsequent notification when tables referenced by
84 the query are changed. This behaves similarly to cursor.execute() but only
85 queries are permitted and the args parameter must be a sequence or
86 dictionary. If the qos parameter included the flag
87 cx_Oracle.SUBSCR_QOS_QUERY when the subscription was created, then the ID
88 for the registered query is returned; otherwise, None is returned.
89
90
91 .. attribute:: Subscription.timeout
92
93 This read-only attribute returns the timeout (in seconds) that was
94 specified when the subscription was created. A value of 0 indicates that
95 there is no timeout.
96
97
98 .. _msgobjects:
99
100 Message Objects
101 ===============
102
103 .. note::
104
105 This object is created internally when notification is received and passed
106 to the callback procedure specified when a subscription is created.
107
108
109 .. attribute:: Message.consumerName
110
111 This read-only attribute returns the name of the consumer which generated
112 the notification. It will be populated if the subscription was created with
113 the namespace :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ` and the queue is a
114 multiple consumer queue.
115
116 .. versionadded:: 6.4
117
118
119 .. attribute:: Message.dbname
120
121 This read-only attribute returns the name of the database that generated
122 the notification.
123
124
125 .. attribute:: Message.queries
126
127 This read-only attribute returns a list of message query objects that give
128 information about query result sets changed for this notification. This
129 attribute will be None if the qos parameter did not include the flag
130 :data:`~cx_Oracle.SUBSCR_QOS_QUERY` when the subscription was created.
131
132
133 .. attribute:: Message.queueName
134
135 This read-only attribute returns the name of the queue which generated the
136 notification. It will only be populated if the subscription was created
137 with the namespace :data:`cx_Oracle.SUBSCR_NAMESPACE_AQ`.
138
139 .. versionadded:: 6.4
140
141
142 .. attribute:: Message.registered
143
144 This read-only attribute returns whether the subscription which generated
145 this notification is still registered with the database. The subscription
146 is automatically deregistered with the database when the subscription
147 timeout value is reached or when the first notification is sent (when the
148 quality of service flag :data:`cx_Oracle.SUBSCR_QOS_DEREG_NFY` is used).
149
150 .. versionadded:: 6.4
151
152
153 .. attribute:: Message.subscription
154
155 This read-only attribute returns the subscription object for which this
156 notification was generated.
157
158
159 .. attribute:: Message.tables
160
161 This read-only attribute returns a list of message table objects that give
162 information about the tables changed for this notification. This
163 attribute will be None if the qos parameter included the flag
164 :data:`~cx_Oracle.SUBSCR_QOS_QUERY` when the subscription was created.
165
166
167 .. attribute:: Message.txid
168
169 This read-only attribute returns the id of the transaction that generated
170 the notification.
171
172
173 .. attribute:: Message.type
174
175 This read-only attribute returns the type of message that has been sent.
176 See the constants section on event types for additional information.
177
178
179 Message Table Objects
180 =====================
181
182 .. note::
183
184 This object is created internally for each table changed when notification
185 is received and is found in the tables attribute of message objects, and
186 the tables attribute of message query objects.
187
188
189 .. attribute:: MessageTable.name
190
191 This read-only attribute returns the name of the table that was changed.
192
193
194 .. attribute:: MessageTable.operation
195
196 This read-only attribute returns the operation that took place on the table
197 that was changed.
198
199
200 .. attribute:: MessageTable.rows
201
202 This read-only attribute returns a list of message row objects that give
203 information about the rows changed on the table. This value is only filled
204 in if the qos parameter to the :meth:`Connection.subscribe()` method
205 included the flag :data:`~cx_Oracle.SUBSCR_QOS_ROWIDS`.
206
207
208 Message Row Objects
209 ===================
210
211 .. note::
212
213 This object is created internally for each row changed on a table when
214 notification is received and is found in the rows attribute of message
215 table objects.
216
217
218 .. attribute:: MessageRow.operation
219
220 This read-only attribute returns the operation that took place on the row
221 that was changed.
222
223
224 .. attribute:: MessageRow.rowid
225
226 This read-only attribute returns the rowid of the row that was changed.
227
228
229 Message Query Objects
230 =====================
231
232 .. note::
233
234 This object is created internally for each query result set changed when
235 notification is received and is found in the queries attribute of message
236 objects.
237
238
239 .. attribute:: MessageQuery.id
240
241 This read-only attribute returns the query id of the query for which the
242 result set changed. The value will match the value returned by
243 Subscription.registerquery when the related query was registered.
244
245
246 .. attribute:: MessageQuery.operation
247
248 This read-only attribute returns the operation that took place on the query
249 result set that was changed. Valid values for this attribute are
250 :data:`~cx_Oracle.EVENT_DEREG` and :data:`~cx_Oracle.EVENT_QUERYCHANGE`.
251
252
253 .. attribute:: MessageQuery.tables
254
255 This read-only attribute returns a list of message table objects that give
256 information about the table changes that caused the query result set to
257 change for this notification.
258
0 .. _aqusermanual:
1
2 ****************************
3 Oracle Advanced Queuing (AQ)
4 ****************************
5
6 `Oracle Advanced Queuing
7 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=ADQUE>`__ is a highly
8 configurable and scalable messaging feature of Oracle Database. It has
9 interfaces in various languages, letting you integrate multiple tools in your
10 architecture.
11
12 cx_Oracle 7.2 introduced an updated interface for Oracle Advanced
13 Queuing.
14
15 There are Advanced Queuing examples in the `GitHub examples
16 <https://github.com/oracle/python-cx_Oracle/tree/master/samples>`__ directory.
17
18
19 Creating a Queue
20 ================
21
22 Before being used, queues need to be created in the database, for example in
23 SQL*Plus:
24
25 .. code-block:: sql
26
27 begin
28 dbms_aqadm.create_queue_table('MY_QUEUE_TABLE', 'RAW');
29 dbms_aqadm.create_queue('DEMO_RAW_QUEUE', 'MY_QUEUE_TABLE');
30 dbms_aqadm.start_queue('DEMO_RAW_QUEUE');
31 end;
32 /
33
34 This examples creates a RAW queue suitable for sending string or raw bytes
35 messages.
36
37
38 Enqueuing Messages
39 ==================
40
41 To send messages in Python you connect and get a :ref:`queue <queue>`. The
42 queue can be used for enqueuing, dequeuing, or both as needed.
43
44 .. code-block:: python
45
46 queue = connection.queue("DEMO_RAW_QUEUE")
47
48 Now messages can be queued using :meth:`Queue.enqOne()`. To send three
49 messages:
50
51 .. code-block:: python
52
53 PAYLOAD_DATA = [
54 "The first message",
55 "The second message",
56 "The third message"
57 ]
58 for data in PAYLOAD_DATA:
59 queue.enqOne(connection.msgproperties(payload=data))
60 connection.commit()
61
62 Since the queue sending the messages is a RAW queue, the strings in this
63 example will be internally encoded to bytes using :attr:`Connection.encoding`
64 before being enqueued.
65
66
67 Dequeuing Messages
68 ==================
69
70 Dequeuing is performed similarly. To dequeue a message call the method
71 :meth:`Queue.deqOne()` as shown. Note that if the message is expected to be a
72 string, the bytes must be decoded using :attr:`Connection.encoding`.
73
74 .. code-block:: python
75
76 queue = connection.queue("DEMO_RAW_QUEUE")
77 msg = queue.deqOne()
78 connection.commit()
79 print(msg.payload.decode(connection.encoding))
80
81
82 Using Object Queues
83 ===================
84
85 Named Oracle objects can be enqueued and dequeued as well. Given an object
86 type called ``UDT_BOOK``:
87
88 .. code-block:: sql
89
90 CREATE OR REPLACE TYPE udt_book AS OBJECT (
91 Title VARCHAR2(100),
92 Authors VARCHAR2(100),
93 Price NUMBER(5,2)
94 );
95 /
96
97 And a queue that accepts this type:
98
99 .. code-block:: sql
100
101 begin
102 dbms_aqadm.create_queue_table('BOOK_QUEUE_TAB', 'UDT_BOOK');
103 dbms_aqadm.create_queue('DEMO_BOOK_QUEUE', 'BOOK_QUEUE_TAB');
104 dbms_aqadm.start_queue('DEMO_BOOK_QUEUE');
105 end;
106 /
107
108 You can queue messages:
109
110 .. code-block:: python
111
112 booksType = connection.gettype("UDT_BOOK")
113 queue = connection.queue("DEMO_BOOK_QUEUE", booksType)
114
115 book = booksType.newobject()
116 book.TITLE = "Quick Brown Fox"
117 book.AUTHORS = "The Dog"
118 book.PRICE = 123
119
120 queue.enqOne(connection.msgproperties(payload=book))
121 connection.commit()
122
123 Dequeuing is done like this:
124
125 .. code-block:: python
126
127 booksType = connection.gettype("UDT_BOOK")
128 queue = connection.queue("DEMO_BOOK_QUEUE", booksType)
129
130 msg = queue.deqOne()
131 connection.commit()
132 print(msg.payload.TITLE) # will print Quick Brown Fox
133
134
135 Changing Queue and Message Options
136 ==================================
137
138 Refer to the :ref:`cx_Oracle AQ API <aq>` and
139 `Oracle Advanced Queuing documentation
140 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=ADQUE>`__ for details
141 on all of the enqueue and dequeue options available.
142
143 Enqueue options can be set. For example, to make it so that an explicit
144 call to :meth:`~Connection.commit()` on the connection is not needed to commit
145 messages:
146
147 .. code-block:: python
148
149 queue = connection.queue("DEMO_RAW_QUEUE")
150 queue.enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
151
152 Dequeue options can also be set. For example, to specify not to block on
153 dequeuing if no messages are available:
154
155 .. code-block:: python
156
157 queue = connection.queue("DEMO_RAW_QUEUE")
158 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
159
160 Message properties can be set when enqueuing. For example, to set an
161 expiration of 60 seconds on a message:
162
163 .. code-block:: python
164
165 queue.enqOne(connection.msgproperties(payload="Message", expiration=60))
166
167 This means that if no dequeue operation occurs within 60 seconds that the
168 message will be dropped from the queue.
169
170
171 Bulk Enqueue and Dequeue
172 ========================
173
174 The :meth:`Queue.enqMany()` and :meth:`Queue.deqMany()` methods can be used for
175 efficient bulk message handling.
176
177 :meth:`Queue.enqMany()` is similar to :meth:`Queue.enqOne()` but accepts an
178 array of messages:
179
180 .. code-block:: python
181
182 messages = [
183 "The first message",
184 "The second message",
185 "The third message",
186 ]
187 queue = connection.queue("DEMO_RAW_QUEUE")
188 queue.enqMany(connection.msgproperties(payload=m) for m in messages)
189 connection.commit()
190
191 Warning: calling :meth:`Queue.enqMany()` in parallel on different connections
192 acquired from the same pool may fail due to Oracle bug 29928074. Ensure that
193 this function is not run in parallel, use standalone connections or connections
194 from different pools, or make multiple calls to :meth:`Queue.enqOne()` instead.
195 The function :meth:`Queue.deqMany()` call is not affected.
196
197 To dequeue multiple messages at one time, use :meth:`Queue.deqMany()`. This
198 takes an argument specifying the maximum number of messages to dequeue at one
199 time:
200
201 .. code-block:: python
202
203 for m in queue.deqMany(maxMessages=10):
204 print(m.payload.decode(connection.encoding))
205
206 Depending on the queue properties and the number of messages available to
207 dequeue, this code will print out from zero to ten messages.
0 .. _batchstmnt:
1
2 ******************************************
3 Batch Statement Execution and Bulk Loading
4 ******************************************
5
6 Inserting or updating multiple rows can be performed efficiently with
7 :meth:`Cursor.executemany()`, making it easy to work with large data sets with
8 cx_Oracle. This method can significantly outperform repeated calls to
9 :meth:`Cursor.execute()` by reducing network transfer costs and database overheads.
10 The :meth:`~Cursor.executemany()` method can also be used to execute PL/SQL
11 statements multiple times at once.
12
13 There are examples in the `GitHub examples
14 <https://github.com/oracle/python-cx_Oracle/tree/master/samples>`__
15 directory.
16
17 The following tables will be used in the samples that follow:
18
19 .. code-block:: sql
20
21 create table ParentTable (
22 ParentId number(9) not null,
23 Description varchar2(60) not null,
24 constraint ParentTable_pk primary key (ParentId)
25 );
26
27 create table ChildTable (
28 ChildId number(9) not null,
29 ParentId number(9) not null,
30 Description varchar2(60) not null,
31 constraint ChildTable_pk primary key (ChildId),
32 constraint ChildTable_fk foreign key (ParentId)
33 references ParentTable
34 );
35
36
37 Batch Execution of SQL
38 ======================
39
40 The following example inserts five rows into the table ``ParentTable``:
41
42 .. code-block:: python
43
44 dataToInsert = [
45 (10, 'Parent 10'),
46 (20, 'Parent 20'),
47 (30, 'Parent 30'),
48 (40, 'Parent 40'),
49 (50, 'Parent 50')
50 ]
51 cursor.executemany("insert into ParentTable values (:1, :2)", dataToInsert)
52
53 This code requires only one :ref:`round-trip <roundtrips>` from the client to
54 the database instead of the five round-trips that would be required for
55 repeated calls to :meth:`~Cursor.execute()`. For very large data sets there
56 may be an external buffer or network limits to how many rows can be processed,
57 so repeated calls to ``executemany()`` may be required. The limits are based
58 on both the number of rows being processed as well as the "size" of each row
59 that is being processed. Repeated calls to :meth:`~Cursor.executemany()` are
60 still better than repeated calls to :meth:`~Cursor.execute()`.
61
62
63 Batch Execution of PL/SQL
64 =========================
65
66 PL/SQL functions and procedures and anonymous PL/SQL blocks can also be called
67 using :meth:`~Cursor.executemany()` in order to improve performance. For
68 example:
69
70 .. code-block:: python
71
72 dataToInsert = [
73 (10, 'Parent 10'),
74 (20, 'Parent 20'),
75 (30, 'Parent 30'),
76 (40, 'Parent 40'),
77 (50, 'Parent 50')
78 ]
79 cursor.executemany("begin mypkg.create_parent(:1, :2); end;", dataToInsert)
80
81 Note that the ``batcherrors`` parameter (discussed below) cannot be used with
82 PL/SQL block execution.
83
84
85 Handling Data Errors
86 ====================
87
88 Large datasets may contain some invalid data. When using batch execution as
89 discussed above, the entire batch will be discarded if a single error is
90 detected, potentially eliminating the performance benefits of batch execution
91 and increasing the complexity of the code required to handle those errors. If
92 the parameter ``batchErrors`` is set to the value ``True`` when calling
93 :meth:`~Cursor.executemany()`, however, processing will continue even if there
94 are data errors in some rows, and the rows containing errors can be examined
95 afterwards to determine what course the application should take. Note that if
96 any errors are detected, a transaction will be started but not committed, even
97 if :attr:`Connection.autocommit` is set to ``True``. After examining the errors
98 and deciding what to do with them, the application needs to explicitly commit
99 or roll back the transaction with :meth:`Connection.commit()` or
100 :meth:`Connection.rollback()`, as needed.
101
102 This example shows how data errors can be identified:
103
104 .. code-block:: python
105
106 dataToInsert = [
107 (60, 'Parent 60'),
108 (70, 'Parent 70'),
109 (70, 'Parent 70 (duplicate)'),
110 (80, 'Parent 80'),
111 (80, 'Parent 80 (duplicate)'),
112 (90, 'Parent 90')
113 ]
114 cursor.executemany("insert into ParentTable values (:1, :2)", dataToInsert,
115 batcherrors=True)
116 for error in cursor.getbatcherrors():
117 print("Error", error.message, "at row offset", error.offset)
118
119 The output is::
120
121 Error ORA-00001: unique constraint (PYTHONDEMO.PARENTTABLE_PK) violated at row offset 2
122 Error ORA-00001: unique constraint (PYTHONDEMO.PARENTTABLE_PK) violated at row offset 4
123
124 The row offset is the index into the array of the data that could not be
125 inserted due to errors. The application could choose to commit or rollback the
126 other rows that were successfully inserted. Alternatively, it could correct
127 the data for the two invalid rows and attempt to insert them again before
128 committing.
129
130
131 Identifying Affected Rows
132 =========================
133
134 When executing a DML statement using :meth:`~Cursor.execute()`, the number of
135 rows affected can be examined by looking at the attribute
136 :attr:`~Cursor.rowcount`. When performing batch executing with
137 :meth:`Cursor.executemany()`, however, the row count will return the *total*
138 number of rows that were affected. If you want to know the total number of rows
139 affected by each row of data that is bound you must set the parameter
140 ``arraydmlrowcounts`` to ``True``, as shown:
141
142 .. code-block:: python
143
144 parentIdsToDelete = [20, 30, 50]
145 cursor.executemany("delete from ChildTable where ParentId = :1",
146 [(i,) for i in parentIdsToDelete],
147 arraydmlrowcounts=True)
148 rowCounts = cursor.getarraydmlrowcounts()
149 for parentId, count in zip(parentIdsToDelete, rowCounts):
150 print("Parent ID:", parentId, "deleted", count, "rows.")
151
152 Using the data found in the `GitHub samples
153 <https://github.com/oracle/python-cx_Oracle/tree/master/samples>`__ the output
154 is as follows::
155
156 Parent ID: 20 deleted 3 rows.
157 Parent ID: 30 deleted 2 rows.
158 Parent ID: 50 deleted 4 rows.
159
160
161 DML RETURNING
162 =============
163
164 DML statements like INSERT, UPDATE, DELETE and MERGE can return values by using
165 the DML RETURNING syntax. A bind variable can be created to accept this data.
166 See :ref:`bind` for more information.
167
168 If, instead of merely deleting the rows as shown in the previous example, you
169 also wanted to know some information about each of the rows that were deleted,
170 you could use the following code:
171
172 .. code-block:: python
173
174 parentIdsToDelete = [20, 30, 50]
175 childIdVar = cursor.var(int, arraysize=len(parentIdsToDelete))
176 cursor.setinputsizes(None, childIdVar)
177 cursor.executemany("""
178 delete from ChildTable
179 where ParentId = :1
180 returning ChildId into :2""",
181 [(i,) for i in parentIdsToDelete])
182 for ix, parentId in enumerate(parentIdsToDelete):
183 print("Child IDs deleted for parent ID", parentId, "are",
184 childIdVar.getvalue(ix))
185
186 The output would then be::
187
188 Child IDs deleted for parent ID 20 are [1002, 1003, 1004]
189 Child IDs deleted for parent ID 30 are [1005, 1006]
190 Child IDs deleted for parent ID 50 are [1012, 1013, 1014, 1015]
191
192 Note that the bind variable created to accept the returned data must have an
193 arraysize large enough to hold data for each row that is processed. Also,
194 the call to :meth:`Cursor.setinputsizes()` binds this variable immediately so
195 that it does not have to be passed in each row of data.
196
197
198 Predefining Memory Areas
199 ========================
200
201 When multiple rows of data are being processed there is the possibility that
202 the data is not uniform in type and size. In such cases, cx_Oracle makes some
203 effort to accommodate such differences. Type determination for each column is
204 deferred until a value that is not ``None`` is found in the column's data. If
205 all values in a particular column are ``None``, then cx_Oracle assumes the type
206 is a string and has a length of 1. cx_Oracle will also adjust the size of the
207 buffers used to store strings and bytes when a longer value is encountered in
208 the data. These sorts of operations incur overhead as memory has to be
209 reallocated and data copied. To eliminate this overhead, using
210 :meth:`~Cursor.setinputsizes()` tells cx_Oracle about the type and size of the
211 data that is going to be used.
212
213 Consider the following code:
214
215 .. code-block:: python
216
217 data = [
218 ( 110, "Parent 110"),
219 ( 2000, "Parent 2000"),
220 ( 30000, "Parent 30000"),
221 ( 400000, "Parent 400000"),
222 (5000000, "Parent 5000000")
223 ]
224 cursor.setinputsizes(None, 20)
225 cursor.executemany("""
226 insert into ParentTable (ParentId, Description)
227 values (:1, :2)""", data)
228
229 In this example, without the call to :meth:`~Cursor.setinputsizes()`, cx_Oracle
230 would perform five allocations of increasing size as it discovered each new,
231 longer string. However ``cursor.setinputsizes(None, 20)`` tells cx_Oracle that
232 the maximum size of the strings that will be processed is 20 characters. Since
233 cx_Oracle allocates memory for each row based on this value, it is best not to
234 oversize it. The first parameter of ``None`` tells cx_Oracle that its default
235 processing will be sufficient.
236
237 Loading CSV Files into Oracle Database
238 ======================================
239
240 The :meth:`Cursor.executemany()` method and `csv module
241 <https://docs.python.org/3/library/csv.html#module-csv>`__ can be used to
242 efficiently load CSV (Comma Separated Values) files. For example, consider the
243 file ``data.csv``::
244
245 101,Abel
246 154,Baker
247 132,Charlie
248 199,Delta
249 . . .
250
251 And the schema:
252
253 .. code-block:: sql
254
255 create table test (id number, name varchar2(25));
256
257 Instead of looping through each line of the CSV file and inserting it
258 individually, you can insert batches of records using
259 :meth:`Cursor.executemany()`:
260
261 .. code-block:: python
262
263 import cx_Oracle
264 import csv
265
266 . . .
267
268 # Predefine the memory areas to match the table definition
269 cursor.setinputsizes(None, 25)
270
271 # Adjust the batch size to meet your memory and performance requirements
272 batch_size = 10000
273
274 with open('testsp.csv', 'r') as csv_file:
275 csv_reader = csv.reader(csv_file, delimiter=',')
276 sql = "insert into test (id,name) values (:1, :2)"
277 data = []
278 for line in csv_reader:
279 data.append((line[0], line[1]))
280 if len(data) % batch_size == 0:
281 cursor.executemany(sql, data)
282 data = []
283 if data:
284 cursor.executemany(sql, data)
285 con.commit()
0 .. _bind:
1
2 ********************
3 Using Bind Variables
4 ********************
5
6 SQL and PL/SQL statements that pass data to and from Oracle Database should use
7 placeholders in SQL and PL/SQL statements that mark where data is supplied or
8 returned. These placeholders are referred to as bind variables or bind
9 parameters A bind variable is a colon-prefixed identifier or numeral. For
10 example, there are two bind variables (``dept_id`` and ``dept_name``) in this
11 SQL statement:
12
13 .. code-block:: python
14
15 sql = """insert into departments (department_id, department_name)
16 values (:dept_id, :dept_name)"""
17 cursor.execute(sql, [280, "Facility"])
18
19 Using bind variables is important for scalability and security. They help avoid
20 SQL Injection security problems because data is never treated as part of an
21 executable statement. Never concatenate or interpolate user data into SQL
22 statements:
23
24 .. code-block:: python
25
26 did = 280
27 dnm = "Facility"
28
29 # !! Never do this !!
30 sql = f"""insert into departments (department_id, department_name)
31 values ({did}, {dnm})"""
32 cursor.execute(sql)
33
34 Bind variables reduce parsing and execution costs when statements are executed
35 more than once with different data values. If you do not use bind variables,
36 Oracle must reparse and cache multiple statements. When using bind variables,
37 Oracle Database may be able to reuse the statement execution plan and context.
38
39 Bind variables can be used to substitute data, but cannot be used to substitute
40 the text of the statement. You cannot, for example, use a bind variable where
41 a column name or a table name is required. Bind variables also cannot be used
42 in Data Definition Language (DDL) statements, such as CREATE TABLE or ALTER
43 statements.
44
45 Binding By Name or Position
46 ===========================
47
48 Binding can be done by name or by position. A named bind is performed when the
49 bind variables in a statement are associated with a name. For example:
50
51 .. code-block:: python
52
53 cursor.execute("""
54 insert into departments (department_id, department_name)
55 values (:dept_id, :dept_name)""", dept_id=280,
56 dept_name="Facility")
57
58 # alternatively, the parameters can be passed as a dictionary instead of as
59 # keyword parameters
60 data = { "dept_id": 280, "dept_name": "Facility" }
61 cursor.execute("""
62 insert into departments (department_id, department_name)
63 values (:dept_id, :dept_name)""", data)
64
65 In the above example, the keyword parameter names or the keys of the dictionary
66 must match the bind variable names. The advantages of this approach are that
67 the location of the bind variables in the statement is not important, the
68 names can be meaningful and the names can be repeated while still only
69 supplying the value once.
70
71 A positional bind is performed when a list of bind values are passed to the
72 execute() call. For example:
73
74 .. code-block:: python
75
76 cursor.execute("""
77 insert into departments (department_id, department_name)
78 values (:dept_id, :dept_name)""", [280, "Facility"])
79
80 Note that for SQL statements, the order of the bind values must exactly match
81 the order of each bind variable and duplicated names must have their values
82 repeated. For PL/SQL statements, however, the order of the bind values must
83 exactly match the order of each **unique** bind variable found in the PL/SQL
84 block and values should not be repeated. In order to avoid this difference,
85 binding by name is recommended when bind variable names are repeated.
86
87
88 Bind Direction
89 ==============
90
91 The caller can supply data to the database (IN), the database can return
92 data to the caller (OUT) or the caller can supply initial data to the
93 database and the database can supply the modified data back to the caller
94 (IN/OUT). This is known as the bind direction.
95
96 The examples shown above have all supplied data to the database and are
97 therefore classified as IN bind variables. In order to have the database return
98 data to the caller, a variable must be created. This is done by calling the
99 method :func:`Cursor.var()`, which identifies the type of data that will be
100 found in that bind variable and its maximum size among other things.
101
102 Here is an example showing how to use OUT binds. It calculates the sum of the
103 integers 8 and 7 and stores the result in an OUT bind variable of type integer:
104
105 .. code-block:: python
106
107 outVal = cursor.var(int)
108 cursor.execute("""
109 begin
110 :outVal := :inBindVar1 + :inBindVar2;
111 end;""", outVal=outVal, inBindVar1=8, inBindVar2=7)
112 print(outVal.getvalue()) # will print 15
113
114 If instead of simply getting data back you wish to supply an initial value to
115 the database, you can set the variable's initial value. This example is the
116 same as the previous one but it sets the initial value first:
117
118 .. code-block:: python
119
120 inOutVal = cursor.var(int)
121 inOutVal.setvalue(0, 25)
122 cursor.execute("""
123 begin
124 :inOutBindVar := :inOutBindVar + :inBindVar1 + :inBindVar2;
125 end;""", inOutBindVar=inOutVal, inBindVar1=8, inBindVar2=7)
126 print(inOutVal.getvalue()) # will print 40
127
128 When binding data to parameters of PL/SQL procedures that are declared as OUT
129 parameters, it is worth noting that any value that is set in the bind variable
130 will be ignored. In addition, any parameters declared as IN/OUT that do not
131 have a value set will start out with a value of ``null``.
132
133
134 Binding Null Values
135 ===================
136
137 In cx_Oracle, null values are represented by the Python singleton ``None``.
138
139 For example:
140
141 .. code-block:: python
142
143 cursor.execute("""
144 insert into departments (department_id, department_name)
145 values (:dept_id, :dept_name)""", dept_id=280, dept_name=None)
146
147 In this specific case, because the ``DEPARTMENT_NAME`` column is defined as a
148 ``NOT NULL`` column, an error will occur::
149
150 cx_Oracle.IntegrityError: ORA-01400: cannot insert NULL into ("HR"."DEPARTMENTS"."DEPARTMENT_NAME")
151
152
153 If this value is bound directly, cx_Oracle assumes it to be a string
154 (equivalent to a VARCHAR2 column). If you need to use a different Oracle type
155 you will need to make a call to :func:`Cursor.setinputsizes()` or create a bind
156 variable with the correct type by calling :func:`Cursor.var()`.
157
158
159 Binding ROWID Values
160 ====================
161
162 The pseudo-column ``ROWID`` uniquely identifies a row within a table. In
163 cx_Oracle, ROWID values are represented as strings. The example below shows
164 fetching a row and then updating that row by binding its rowid:
165
166 .. code-block:: python
167
168 # fetch the row
169 cursor.execute("""
170 select rowid, manager_id
171 from departments
172 where department_id = :dept_id""", dept_id=280)
173 rowid, manager_id = cursor.fetchone()
174
175 # update the row by binding ROWID
176 cursor.execute("""
177 update departments set
178 manager_id = :manager_id
179 where rowid = :rid""", manager_id=205, rid=rowid)
180
181
182 DML RETURNING Bind Variables
183 ============================
184
185 When a RETURNING clause is used with a DML statement like UPDATE,
186 INSERT, or DELETE, the values are returned to the application through
187 the use of OUT bind variables. Consider the following example:
188
189 .. code-block:: python
190
191 # The RETURNING INTO bind variable is a string
192 dept_name = cursor.var(str)
193
194 cursor.execute("""
195 update departments set
196 location_id = :loc_id
197 where department_id = :dept_id
198 returning department_name into :dept_name""",
199 loc_id=1700, dept_id=50, dept_name=dept_name)
200 print(dept_name.getvalue()) # will print ['Shipping']
201
202 In the above example, since the WHERE clause matches only one row, the output
203 contains a single item in the list. If the WHERE clause matched multiple rows,
204 however, the output would contain as many items as there were rows that were
205 updated.
206
207 No duplicate binds are allowed in a DML statement with a RETURNING clause, and
208 no duplication is allowed between bind variables in the DML section and the
209 RETURNING section of the statement.
210
211
212 LOB Bind Variables
213 ==================
214
215 Database CLOBs, NCLOBS, BLOBs and BFILEs can be bound with types
216 :attr:`cx_Oracle.DB_TYPE_CLOB`, :attr:`cx_Oracle.DB_TYPE_NCLOB`,
217 :attr:`cx_Oracle.DB_TYPE_BLOB` and :attr:`cx_Oracle.DB_TYPE_BFILE`
218 respectively. LOBs fetched from the database or created with
219 :meth:`Connection.createlob()` can also be bound.
220
221 LOBs may represent Oracle Database persistent LOBs (those stored in tables) or
222 temporary LOBs (such as those created with :meth:`Connection.createlob()` or
223 returned by some SQL and PL/SQL operations).
224
225 LOBs can be used as IN, OUT or IN/OUT bind variables.
226
227 See :ref:`lobdata` for examples.
228
229 .. _refcur:
230
231 REF CURSOR Bind Variables
232 =========================
233
234 cx_Oracle provides the ability to bind and define PL/SQL REF cursors. As an
235 example, consider the PL/SQL procedure:
236
237 .. code-block:: sql
238
239 CREATE OR REPLACE PROCEDURE find_employees (
240 p_query IN VARCHAR2,
241 p_results OUT SYS_REFCURSOR
242 ) AS
243 BEGIN
244 OPEN p_results FOR
245 SELECT employee_id, first_name, last_name
246 FROM employees
247 WHERE UPPER(first_name || ' ' || last_name || ' ' || email)
248 LIKE '%' || UPPER(p_query) || '%';
249 END;
250 /
251
252 A newly opened cursor can be bound to the REF CURSOR parameter, as shown in the
253 following Python code. After the PL/SQL procedure has been called with
254 :meth:`Cursor.callproc()`, the cursor can then be fetched just like any other
255 cursor which had executed a SQL query:
256
257 .. code-block:: python
258
259 refCursor = connection.cursor()
260 cursor.callproc("find_employees", ['Smith', refCursor])
261 for row in refCursor:
262 print(row)
263
264 With Oracle's `sample HR schema
265 <https://github.com/oracle/db-sample-schemas>`__ there are two
266 employees with the last name 'Smith' so the result is::
267
268 (159, 'Lindsey', 'Smith')
269 (171, 'William', 'Smith')
270
271 To return a REF CURSOR from a PL/SQL function, use ``cx_Oracle.DB_TYPE_CURSOR`` for the
272 return type of :meth:`Cursor.callfunc()`:
273
274 .. code-block:: python
275
276 refCursor = cursor.callfunc('example_package.f_get_cursor', cx_Oracle.DB_TYPE_CURSOR)
277 for row in refCursor:
278 print(row)
279
280 Binding PL/SQL Collections
281 ==========================
282
283 PL/SQL Collections like Associative Arrays can be bound as IN, OUT, and IN/OUT
284 variables. When binding IN values, an array can be passed directly as shown in
285 this example, which sums up the lengths of all of the strings in the provided
286 array. First the PL/SQL package definition:
287
288 .. code-block:: sql
289
290 create or replace package mypkg as
291
292 type udt_StringList is table of varchar2(100) index by binary_integer;
293
294 function DemoCollectionIn (
295 a_Values udt_StringList
296 ) return number;
297
298 end;
299 /
300
301 create or replace package body mypkg as
302
303 function DemoCollectionIn (
304 a_Values udt_StringList
305 ) return number is
306 t_ReturnValue number := 0;
307 begin
308 for i in 1..a_Values.count loop
309 t_ReturnValue := t_ReturnValue + length(a_Values(i));
310 end loop;
311 return t_ReturnValue;
312 end;
313
314 end;
315 /
316
317 Then the Python code:
318
319 .. code-block:: python
320
321 values = ["String One", "String Two", "String Three"]
322 returnVal = cursor.callfunc("mypkg.DemoCollectionIn", int, [values])
323 print(returnVal) # will print 32
324
325 In order get values back from the database, a bind variable must be created
326 using :meth:`Cursor.arrayvar()`. The first parameter to this method is a Python
327 type that cx_Oracle knows how to handle or one of the cx_Oracle :ref:`types`.
328 The second parameter is the maximum number of elements that the array can hold
329 or an array providing the value (and indirectly the maximum length). The final
330 parameter is optional and only used for strings and bytes. It identifies the
331 maximum length of the strings and bytes that can be stored in the array. If not
332 specified, the length defaults to 4000 bytes.
333
334 Consider the following PL/SQL package:
335
336 .. code-block:: sql
337
338 create or replace package mypkg as
339
340 type udt_StringList is table of varchar2(100) index by binary_integer;
341
342 procedure DemoCollectionOut (
343 a_NumElements number,
344 a_Values out nocopy udt_StringList
345 );
346
347 procedure DemoCollectionInOut (
348 a_Values in out nocopy udt_StringList
349 );
350
351 end;
352 /
353
354 create or replace package body mypkg as
355
356 procedure DemoCollectionOut (
357 a_NumElements number,
358 a_Values out nocopy udt_StringList
359 ) is
360 begin
361 for i in 1..a_NumElements loop
362 a_Values(i) := 'Demo out element #' || to_char(i);
363 end loop;
364 end;
365
366 procedure DemoCollectionInOut (
367 a_Values in out nocopy udt_StringList
368 ) is
369 begin
370 for i in 1..a_Values.count loop
371 a_Values(i) := 'Converted element #' || to_char(i) ||
372 ' originally had length ' || length(a_Values(i));
373 end loop;
374 end;
375
376 end;
377 /
378
379 The Python code to process an OUT collection would look as follows. Note the
380 call to :meth:`Cursor.arrayvar()` which creates space for an array of strings.
381 Each string would permit up to 100 bytes and only 10 strings would be
382 permitted. If the PL/SQL block exceeds the maximum number of strings allowed
383 the error ``ORA-06513: PL/SQL: index for PL/SQL table out of range for host
384 language array`` would be raised.
385
386 .. code-block:: python
387
388 outArrayVar = cursor.arrayvar(str, 10, 100)
389 cursor.callproc("mypkg.DemoCollectionOut", [5, outArrayVar])
390 for val in outArrayVar.getvalue():
391 print(val)
392
393 This would produce the following output::
394
395 Demo out element #1
396 Demo out element #2
397 Demo out element #3
398 Demo out element #4
399 Demo out element #5
400
401 The Python code to process an IN/OUT collections is similar. Note the different
402 call to :meth:`Cursor.arrayvar()` which creates space for an array of strings,
403 but uses an array to determine both the maximum length of the array and its
404 initial value.
405
406 .. code-block:: python
407
408 inValues = ["String One", "String Two", "String Three", "String Four"]
409 inOutArrayVar = cursor.arrayvar(str, inValues)
410 cursor.callproc("mypkg.DemoCollectionInOut", [inOutArrayVar])
411 for val in inOutArrayVar.getvalue():
412 print(val)
413
414 This would produce the following output::
415
416 Converted element #1 originally had length 10
417 Converted element #2 originally had length 10
418 Converted element #3 originally had length 12
419 Converted element #4 originally had length 11
420
421 If an array variable needs to have an initial value but also needs to allow
422 for more elements than the initial value contains, the following code can be
423 used instead:
424
425 .. code-block:: python
426
427 inOutArrayVar = cursor.arrayvar(str, 10, 100)
428 inOutArrayVar.setvalue(0, ["String One", "String Two"])
429
430 All of the collections that have been bound in preceding examples have used
431 contiguous array elements. If an associative array with sparse array elements
432 is needed, a different approach is required. Consider the following PL/SQL
433 code:
434
435 .. code-block:: sql
436
437 create or replace package mypkg as
438
439 type udt_StringList is table of varchar2(100) index by binary_integer;
440
441 procedure DemoCollectionOut (
442 a_Value out nocopy udt_StringList
443 );
444
445 end;
446 /
447
448 create or replace package body mypkg as
449
450 procedure DemoCollectionOut (
451 a_Value out nocopy udt_StringList
452 ) is
453 begin
454 a_Value(-1048576) := 'First element';
455 a_Value(-576) := 'Second element';
456 a_Value(284) := 'Third element';
457 a_Value(8388608) := 'Fourth element';
458 end;
459
460 end;
461 /
462
463 Note that the collection element indices are separated by large values. The
464 technique used above would fail with the exception ``ORA-06513: PL/SQL: index
465 for PL/SQL table out of range for host language array``. The code required to
466 process this collection looks like this instead:
467
468 .. code-block:: python
469
470 collectionType = connection.gettype("MYPKG.UDT_STRINGLIST")
471 collection = collectionType.newobject()
472 cursor.callproc("mypkg.DemoCollectionOut", [collection])
473 print(collection.aslist())
474
475 This produces the output::
476
477 ['First element', 'Second element', 'Third element', 'Fourth element']
478
479 Note the use of :meth:`Object.aslist()` which returns the collection element
480 values in index order as a simple Python list. The indices themselves are lost
481 in this approach. Starting from cx_Oracle 7.0, the associative array can be
482 turned into a Python dictionary using :meth:`Object.asdict()`. If that value
483 was printed in the previous example instead, the output would be::
484
485 {-1048576: 'First element', -576: 'Second element', 284: 'Third element', 8388608: 'Fourth element'}
486
487 If the elements need to be traversed in index order, the methods
488 :meth:`Object.first()` and :meth:`Object.next()` can be used. The method
489 :meth:`Object.getelement()` can be used to acquire the element at a particular
490 index. This is shown in the following code:
491
492 .. code-block:: python
493
494 ix = collection.first()
495 while ix is not None:
496 print(ix, "->", collection.getelement(ix))
497 ix = collection.next(ix)
498
499 This produces the output::
500
501 -1048576 -> First element
502 -576 -> Second element
503 284 -> Third element
504 8388608 -> Fourth element
505
506 Similarly, the elements can be traversed in reverse index order using the
507 methods :meth:`Object.last()` and :meth:`Object.prev()` as shown in the
508 following code:
509
510 .. code-block:: python
511
512 ix = collection.last()
513 while ix is not None:
514 print(ix, "->", collection.getelement(ix))
515 ix = collection.prev(ix)
516
517 This produces the output::
518
519 8388608 -> Fourth element
520 284 -> Third element
521 -576 -> Second element
522 -1048576 -> First element
523
524
525 Binding PL/SQL Records
526 ======================
527
528 PL/SQL record type objects can also be bound for IN, OUT and IN/OUT
529 bind variables. For example:
530
531 .. code-block:: sql
532
533 create or replace package mypkg as
534
535 type udt_DemoRecord is record (
536 NumberValue number,
537 StringValue varchar2(30),
538 DateValue date,
539 BooleanValue boolean
540 );
541
542 procedure DemoRecordsInOut (
543 a_Value in out nocopy udt_DemoRecord
544 );
545
546 end;
547 /
548
549 create or replace package body mypkg as
550
551 procedure DemoRecordsInOut (
552 a_Value in out nocopy udt_DemoRecord
553 ) is
554 begin
555 a_Value.NumberValue := a_Value.NumberValue * 2;
556 a_Value.StringValue := a_Value.StringValue || ' (Modified)';
557 a_Value.DateValue := a_Value.DateValue + 5;
558 a_Value.BooleanValue := not a_Value.BooleanValue;
559 end;
560
561 end;
562 /
563
564 Then this Python code can be used to call the stored procedure which will
565 update the record:
566
567 .. code-block:: python
568
569 # create and populate a record
570 recordType = connection.gettype("MYPKG.UDT_DEMORECORD")
571 record = recordType.newobject()
572 record.NUMBERVALUE = 6
573 record.STRINGVALUE = "Test String"
574 record.DATEVALUE = datetime.datetime(2016, 5, 28)
575 record.BOOLEANVALUE = False
576
577 # show the original values
578 print("NUMBERVALUE ->", record.NUMBERVALUE)
579 print("STRINGVALUE ->", record.STRINGVALUE)
580 print("DATEVALUE ->", record.DATEVALUE)
581 print("BOOLEANVALUE ->", record.BOOLEANVALUE)
582 print()
583
584 # call the stored procedure which will modify the record
585 cursor.callproc("mypkg.DemoRecordsInOut", [record])
586
587 # show the modified values
588 print("NUMBERVALUE ->", record.NUMBERVALUE)
589 print("STRINGVALUE ->", record.STRINGVALUE)
590 print("DATEVALUE ->", record.DATEVALUE)
591 print("BOOLEANVALUE ->", record.BOOLEANVALUE)
592
593 This will produce the following output::
594
595 NUMBERVALUE -> 6
596 STRINGVALUE -> Test String
597 DATEVALUE -> 2016-05-28 00:00:00
598 BOOLEANVALUE -> False
599
600 NUMBERVALUE -> 12
601 STRINGVALUE -> Test String (Modified)
602 DATEVALUE -> 2016-06-02 00:00:00
603 BOOLEANVALUE -> True
604
605 Note that when manipulating records, all of the attributes must be set by the
606 Python program in order to avoid an Oracle Client bug which will result in
607 unexpected values or the Python application segfaulting.
608
609 .. _spatial:
610
611 Binding Spatial Datatypes
612 =========================
613
614 Oracle Spatial datatypes objects can be represented by Python objects and their
615 attribute values can be read and updated. The objects can further be bound and
616 committed to database. This is similar to the examples above.
617
618 An example of fetching SDO_GEOMETRY is in :ref:`Oracle Database Objects and
619 Collections <fetchobjects>`.
620
621
622 .. _inputtypehandlers:
623
624 Changing Bind Data Types using an Input Type Handler
625 ====================================================
626
627 Input Type Handlers allow applications to change how data is bound to
628 statements, or even to enable new types to be bound directly.
629
630 An input type handler is enabled by setting the attribute
631 :attr:`Cursor.inputtypehandler` or :attr:`Connection.inputtypehandler`.
632
633 Input type handlers can be combined with variable converters to bind Python
634 objects seamlessly:
635
636 .. code-block:: python
637
638 # A standard Python object
639 class Building(object):
640 def __init__(self, buildingId, description, numFloors, dateBuilt):
641 self.buildingId = buildingId
642 self.description = description
643 self.numFloors = numFloors
644 self.dateBuilt = dateBuilt
645
646 building = Building(1, "Skyscraper 1", 5, datetime.date(2001, 5, 24))
647
648 # Get Python representation of the Oracle user defined type UDT_BUILDING
649 objType = con.gettype("UDT_BUILDING")
650
651 # convert a Python Building object to the Oracle user defined type UDT_BUILDING
652 def BuildingInConverter(value):
653 obj = objType.newobject()
654 obj.BUILDINGID = value.buildingId
655 obj.DESCRIPTION = value.description
656 obj.NUMFLOORS = value.numFloors
657 obj.DATEBUILT = value.dateBuilt
658 return obj
659
660 def InputTypeHandler(cursor, value, numElements):
661 if isinstance(value, Building):
662 return cursor.var(cx_Oracle.DB_TYPE_OBJECT, arraysize = numElements,
663 inconverter = BuildingInConverter, typename = objType.name)
664
665
666 # With the input type handler, the bound Python object is converted
667 # to the required Oracle object before being inserted
668 cur.inputtypehandler = InputTypeHandler
669 cur.execute("insert into myTable values (:1, :2)", (1, building))
670
671
672 Binding Multiple Values to a SQL WHERE IN Clause
673 ================================================
674
675 To use an IN clause with multiple values in a WHERE clause, you must define and
676 bind multiple values. You cannot bind an array of values. For example:
677
678 .. code-block:: python
679
680 cursor.execute("""
681 select employee_id, first_name, last_name
682 from employees
683 where last_name in (:name1, :name2)""",
684 name1="Smith", name2="Taylor")
685 for row in cursor:
686 print(row)
687
688 This will produce the following output::
689
690 (159, 'Lindsey', 'Smith')
691 (171, 'William', 'Smith')
692 (176, 'Jonathon', 'Taylor')
693 (180, 'Winston', 'Taylor')
694
695 If this sort of query is executed multiple times with differing numbers of
696 values, a bind variable should be included for each possible value up to the
697 maximum number of values that can be provided. Missing values can be bound with
698 the value ``None``. For example, if the query above is used for up to 5 values,
699 the code should be adjusted as follows:
700
701 .. code-block:: python
702
703 cursor.execute("""
704 select employee_id, first_name, last_name
705 from employees
706 where last_name in (:name1, :name2, :name3, :name4, :name5)""",
707 name1="Smith", name2="Taylor", name3=None, name4=None, name5=None)
708 for row in cursor:
709 print(row)
710
711 This will produce the same output as the original example.
712
713 If the number of values is only going to be known at runtime, then a SQL
714 statement can be built up as follows:
715
716 .. code-block:: python
717
718 bindValues = ["Gates", "Marvin", "Fay"]
719 bindNames = [":" + str(i + 1) for i in range(len(bindValues))]
720 sql = "select employee_id, first_name, last_name from employees " + \
721 "where last_name in (%s)" % (",".join(bindNames))
722 cursor.execute(sql, bindValues)
723 for row in cursor:
724 print(row)
725
726 Another solution for a larger number of values is to construct a SQL
727 statement like::
728
729 SELECT ... WHERE col IN ( <something that returns a list of rows> )
730
731 The easiest way to do the '<something that returns a list of rows>'
732 will depend on how the data is initially represented and the number of
733 items. You might look at using CONNECT BY or nested tables. Or,
734 for really large numbers of items, you might prefer to use a global
735 temporary table.
736
737 Binding Column and Table Names
738 ==============================
739
740 Column and table names cannot be bound in SQL queries. You can concatenate
741 text to build up a SQL statement, but make sure you use an Allow List or other
742 means to validate the data in order to avoid SQL Injection security issues:
743
744 .. code-block:: python
745
746 tableAllowList = ['employees', 'departments']
747 tableName = getTableName() # get the table name from user input
748 if tableName not in tableAllowList:
749 raise Exception('Invalid table name')
750 sql = 'select * from ' + tableName
751
752 Binding column names can be done either by using the above method or by using a
753 CASE statement. The example below demonstrates binding a column name in an
754 ORDER BY clause:
755
756 .. code-block:: python
757
758 sql = """
759 SELECT * FROM departments
760 ORDER BY
761 CASE :bindvar
762 WHEN 'department_id' THEN DEPARTMENT_ID
763 ELSE MANAGER_ID
764 END"""
765
766 columnName = getColumnName() # Obtain a column name from the user
767 cursor.execute(sql, [colname])
768
769 Depending on the name provided by the user, the query results will be
770 ordered either by the column ``DEPARTMENT_ID`` or the column ``MANAGER_ID``.
0 .. _connhandling:
1
2 *****************************
3 Connecting to Oracle Database
4 *****************************
5
6 Connections between cx_Oracle and Oracle Database are used for executing
7 :ref:`SQL <sqlexecution>`, :ref:`PL/SQL <plsqlexecution>`, and :ref:`SODA
8 <sodausermanual>`.
9
10 Establishing Database Connections
11 =================================
12
13 There are two ways to connect to Oracle Database using cx_Oracle:
14
15 * **Standalone connections**
16
17 These are useful when the application maintains a single user
18 session to a database. Connections are created by
19 :meth:`cx_Oracle.connect()` or its alias
20 :meth:`cx_Oracle.Connection()`.
21
22 * **Pooled connections**
23
24 :ref:`Connection pooling <connpool>` is important for performance when
25 applications frequently connect and disconnect from the database. Pools
26 support Oracle's :ref:`high availability <highavailability>` features and are
27 recommended for applications that must be reliable. Small pools can also be
28 useful for applications that want a few connections available for infrequent
29 use. Pools are created with :meth:`cx_Oracle.SessionPool()` at application
30 initialization time, and then :meth:`SessionPool.acquire()` can be called to
31 obtain a connection from a pool.
32
33 Many connection behaviors can be controlled by cx_Oracle options. Other
34 settings can be configured in :ref:`optnetfiles` or in :ref:`optclientfiles`.
35 These include limiting the amount of time that opening a connection can take, or
36 enabling :ref:`network encryption <netencrypt>`.
37
38 **Example: Standalone Connection to Oracle Database**
39
40 .. code-block:: python
41
42 import cx_Oracle
43
44 userpwd = ". . ." # Obtain password string from a user prompt or environment variable
45
46 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1", encoding="UTF-8")
47
48 cx_Oracle also supports :ref:`external authentication <extauth>` so
49 passwords do not need to be in the application.
50
51
52 Closing Connections
53 ===================
54
55 Connections should be released when they are no longer needed by calling
56 :meth:`Connection.close()`. Alternatively, you may prefer to let connections
57 be automatically cleaned up when references to them go out of scope. This lets
58 cx_Oracle close dependent resources in the correct order. One other approach is
59 the use of a "with" block, for example:
60
61 .. code-block:: python
62
63 with cx_Oracle.connect(userName, password, "dbhost.example.com/orclpdb1",
64 encoding="UTF-8") as connection:
65 cursor = connection.cursor()
66 cursor.execute("insert into SomeTable values (:1, :2)",
67 (1, "Some string"))
68 connection.commit()
69
70 This code ensures that, once the block is completed, the connection is closed
71 and resources have been reclaimed by the database. In addition, any attempt to
72 use the variable ``connection`` outside of the block will simply fail.
73
74 Prompt closing of connections is important when using connection pools so
75 connections are available for reuse by other pool users.
76
77 .. _connstr:
78
79 Connection Strings
80 ==================
81
82 The data source name parameter ``dsn`` of :meth:`cx_Oracle.connect()` and
83 :meth:`cx_Oracle.SessionPool()` is the Oracle Database connection string
84 identifying which database service to connect to. The ``dsn`` string can be one
85 of:
86
87 * An Oracle Easy Connect string
88 * An Oracle Net Connect Descriptor string
89 * A Net Service Name mapping to a connect descriptor
90
91 For more information about naming methods, see `Oracle Net Service Reference <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-E5358DEA-D619-4B7B-A799-3D2F802500F1>`__.
92
93 .. _easyconnect:
94
95 Easy Connect Syntax for Connection Strings
96 ------------------------------------------
97
98 An Easy Connect string is often the simplest connection string to use for the
99 data source name parameter ``dsn`` of :meth:`cx_Oracle.connect()` and
100 :meth:`cx_Oracle.SessionPool()`. This method does not need configuration files
101 such as ``tnsnames.ora``.
102
103 For example, to connect to the Oracle Database service ``orclpdb1`` that is
104 running on the host ``dbhost.example.com`` with the default Oracle
105 Database port 1521, use::
106
107 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
108 encoding="UTF-8")
109
110 If the database is using a non-default port, it must be specified::
111
112 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com:1984/orclpdb1",
113 encoding="UTF-8")
114
115 The Easy Connect syntax supports Oracle Database service names. It cannot be
116 used with the older System Identifiers (SID).
117
118 The Easy Connect syntax has been extended in recent versions of Oracle Database
119 client since its introduction in 10g. Check the Easy Connect Naming method in
120 `Oracle Net Service Administrator's Guide
121 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
122 id=GUID-B0437826-43C1-49EC-A94D-B650B6A4A6EE>`__ for the syntax to use in your
123 version of the Oracle Client libraries.
124
125 If you are using Oracle Client 19c, the latest `Easy Connect Plus
126 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
127 id=GUID-8C85D289-6AF3-41BC-848B-BF39D32648BA>`__ syntax allows the use of
128 multiple hosts or ports, along with optional entries for the wallet location,
129 the distinguished name of the database server, and even lets some network
130 configuration options be set. This means that a :ref:`sqlnet.ora <optnetfiles>`
131 file is not needed for some common connection scenarios.
132
133 Oracle Net Connect Descriptor Strings
134 -------------------------------------
135
136 The :meth:`cx_Oracle.makedsn()` function can be used to construct a connect
137 descriptor string for the data source name parameter ``dsn`` of
138 :meth:`cx_Oracle.connect()` and :meth:`cx_Oracle.SessionPool()`. The
139 :meth:`~cx_Oracle.makedsn()` function accepts the database hostname, the port
140 number, and the service name. It also supports :ref:`sharding <connsharding>`
141 syntax.
142
143 For example, to connect to the Oracle Database service ``orclpdb1`` that is
144 running on the host ``dbhost.example.com`` with the default Oracle
145 Database port 1521, use::
146
147 dsn = cx_Oracle.makedsn("dbhost.example.com", 1521, service_name="orclpdb1")
148 connection = cx_Oracle.connect("hr", userpwd, dsn, encoding="UTF-8")
149
150 Note the use of the named argument ``service_name``. By default, the third
151 parameter of :meth:`~cx_Oracle.makedsn()` is a database System Identifier (SID),
152 not a service name. However, almost all current databases use service names.
153
154 The value of ``dsn`` in this example is the connect descriptor string::
155
156 (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbhost.example.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))
157
158 You can manually create similar connect descriptor strings. This lets you
159 extend the syntax, for example to support failover. These strings can be
160 embedded directly in the application::
161
162 dsn = """(DESCRIPTION=
163 (FAILOVER=on)
164 (ADDRESS_LIST=
165 (ADDRESS=(PROTOCOL=tcp)(HOST=sales1-svr)(PORT=1521))
166 (ADDRESS=(PROTOCOL=tcp)(HOST=sales2-svr)(PORT=1521)))
167 (CONNECT_DATA=(SERVICE_NAME=sales.example.com)))"""
168
169 connection = cx_Oracle.connect("hr", userpwd, dsn, encoding="UTF-8")
170
171 .. _netservice:
172
173 Net Service Names for Connection Strings
174 ----------------------------------------
175
176 Connect Descriptor Strings are commonly stored in a :ref:`tnsnames.ora
177 <optnetfiles>` file and associated with a Net Service Name. This name can be
178 used directly for the data source name parameter ``dsn`` of
179 :meth:`cx_Oracle.connect()` and :meth:`cx_Oracle.SessionPool()`. For example,
180 given a ``tnsnames.ora`` file with the following contents::
181
182 ORCLPDB1 =
183 (DESCRIPTION =
184 (ADDRESS = (PROTOCOL = TCP)(HOST = dbhost.example.com)(PORT = 1521))
185 (CONNECT_DATA =
186 (SERVER = DEDICATED)
187 (SERVICE_NAME = orclpdb1)
188 )
189 )
190
191 then you could connect using the following code::
192
193 connection = cx_Oracle.connect("hr", userpwd, "orclpdb1", encoding="UTF-8")
194
195 For more information about Net Service Names, see
196 `Database Net Services Reference
197 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-12C94B15-2CE1-4B98-9D0C-8226A9DDF4CB>`__.
198
199 JDBC and Oracle SQL Developer Connection Strings
200 ------------------------------------------------
201
202 The cx_Oracle connection string syntax is different to Java JDBC and the common
203 Oracle SQL Developer syntax. If these JDBC connection strings reference a
204 service name like::
205
206 jdbc:oracle:thin:@hostname:port/service_name
207
208 for example::
209
210 jdbc:oracle:thin:@dbhost.example.com:1521/orclpdb1
211
212 then use Oracle's Easy Connect syntax in cx_Oracle::
213
214 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com:1521/orclpdb1", encoding="UTF-8")
215
216 Alternatively, if a JDBC connection string uses an old-style Oracle SID "system
217 identifier", and the database does not have a service name::
218
219 jdbc:oracle:thin:@hostname:port:sid
220
221 for example::
222
223 jdbc:oracle:thin:@dbhost.example.com:1521:orcl
224
225 then a connect descriptor string from ``makedsn()`` can be used in the
226 application::
227
228 dsn = cx_Oracle.makedsn("dbhost.example.com", 1521, sid="orcl")
229 connection = cx_Oracle.connect("hr", userpwd, dsn, encoding="UTF-8")
230
231 Alternatively, create a ``tnsnames.ora`` (see :ref:`optnetfiles`) entry, for
232 example::
233
234 finance =
235 (DESCRIPTION =
236 (ADDRESS = (PROTOCOL = TCP)(HOST = dbhost.example.com)(PORT = 1521))
237 (CONNECT_DATA =
238 (SID = ORCL)
239 )
240 )
241
242 This can be referenced in cx_Oracle::
243
244 connection = cx_Oracle.connect("hr", userpwd, "finance", encoding="UTF-8")
245
246 .. _connpool:
247
248 Connection Pooling
249 ==================
250
251 cx_Oracle's connection pooling lets applications create and maintain a pool of
252 connections to the database. Connection pooling is important for performance
253 when applications frequently connect and disconnect from the database. The pool
254 implementation uses Oracle's `session pool technology
255 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
256 id=GUID-F9662FFB-EAEF-495C-96FC-49C6D1D9625C>`__ which supports Oracle's
257 :ref:`high availability <highavailability>` features and is recommended for
258 applications that must be reliable. This also means that small pools can be
259 useful for applications that want a few connections available for infrequent
260 use.
261
262 A connection pool is created by calling :meth:`~cx_Oracle.SessionPool()`. This
263 is generally called during application initialization. The initial pool size
264 and the maximum pool size are provided at the time of pool creation. When the
265 pool needs to grow, new connections are created automatically. The pool can
266 shrink back to the minimum size when connections are no longer in use. For
267 pools created with :ref:`external authentication <extauth>`, with
268 :ref:`homogeneous <connpooltypes>` set to False, or when using :ref:`drcp`, then
269 the number of connections initially created is zero even if a larger value is
270 specified for ``min``. Also in these cases the pool increment is always 1,
271 regardless of the value of ``increment``.
272
273 After a pool has been created, connections can be obtained from it by calling
274 :meth:`~SessionPool.acquire()`. These connections can be used in the same way
275 that standalone connections are used.
276
277 Connections acquired from the pool should be released back to the pool using
278 :meth:`SessionPool.release()` or :meth:`Connection.close()` when they are no
279 longer required. Otherwise, they will be released back to the pool
280 automatically when all of the variables referencing the connection go out of
281 scope. This make connections available for other users of the pool.
282
283 The session pool can be completely closed using :meth:`SessionPool.close()`.
284
285 The example below shows how to connect to Oracle Database using a
286 connection pool:
287
288 .. code-block:: python
289
290 # Create the session pool
291 pool = cx_Oracle.SessionPool("hr", userpwd,
292 "dbhost.example.com/orclpdb1", min=2, max=5, increment=1, encoding="UTF-8")
293
294 # Acquire a connection from the pool
295 connection = pool.acquire()
296
297 # Use the pooled connection
298 cursor = connection.cursor()
299 for result in cursor.execute("select * from mytab"):
300 print(result)
301
302 # Release the connection to the pool
303 pool.release(connection)
304
305 # Close the pool
306 pool.close()
307
308 Other :meth:`cx_Oracle.SessionPool()` options can be used at pool creation. For
309 example the ``getmode`` value can be set so that any ``aquire()`` call will wait
310 for a connection to become available if all are currently in use, for example:
311
312 .. code-block:: python
313
314 # Create the session pool
315 pool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orclpdb1",
316 min=2, max=5, increment=1, getmode=cx_Oracle.SPOOL_ATTRVAL_WAIT, encoding="UTF-8")
317
318
319 Applications that are using connections concurrently in multiple threads should
320 set the ``threaded`` parameter to *True* when creating a connection pool:
321
322 .. code-block:: python
323
324 # Create the session pool
325 pool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orclpdb1",
326 min=2, max=5, increment=1, threaded=True, encoding="UTF-8")
327
328
329 See `ConnectionPool.py
330 <https://github.com/oracle/python-cx_Oracle/tree/master/samples/ConnectionPool.py>`__
331 for an example.
332
333 Before :meth:`SessionPool.acquire()` returns, cx_Oracle does a lightweight check
334 to see if the network transport for the selected connection is still open. If
335 it is not, then :meth:`~SessionPool.acquire()` will clean up the connection and
336 return a different one. This check will not detect cases such as where the
337 database session has been killed by the DBA, or reached a database resource
338 manager quota limit. To help in those cases, :meth:`~SessionPool.acquire()`
339 will also do a full :ref:`round-trip <roundtrips>` ping to the database when it
340 is about to return a connection that was unused in the pool for 60 seconds. If
341 the ping fails, the connection will be discarded and another one obtained before
342 :meth:`~SessionPool.acquire()` returns to the application. Because this full
343 ping is time based, it won't catch every failure. Also network timeouts and
344 session kills may occur after :meth:`~SessionPool.acquire()` and before
345 :meth:`Cursor.execute()`. To handle these cases, applications need to check
346 for errors after each :meth:`~Cursor.execute()` and make application-specific
347 decisions about retrying work if there was a connection failure. Oracle's
348 :ref:`Application Continuity <highavailability>` can do this automatically in
349 some cases. Note both the lightweight and full ping connection checks can mask
350 performance-impacting configuration issues, for example firewalls killing
351 connections, so monitor the connection rate in `AWR
352 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-56AEF38E-9400-427B-A818-EDEC145F7ACD>`__
353 for an unexpected value. You can explicitly initiate a full ping to check
354 connection liveness with :meth:`Connection.ping()` but overuse will impact
355 performance and scalability.
356
357 Connection Pool Sizing
358 ----------------------
359
360 The Oracle Real-World Performance Group's recommendation is to use fixed size
361 connection pools. The values of ``min`` and ``max`` should be the same (and the
362 ``increment`` equal to zero). This avoids connection storms which can decrease
363 throughput. See `Guideline for Preventing Connection Storms: Use Static Pools
364 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7DFBA826-7CC0-4D16-B19C-31D168069B54>`__,
365 which contains more details about sizing of pools. Having a fixed size will
366 guarantee that the database can handle the upper pool size. For example, if a
367 pool needs to grow but the database resources are limited, then
368 :meth:`SessionPool.acquire()` may return errors such as ORA-28547. With a fixed
369 pool size, this class of error will occur when the pool is created, allowing you
370 to change the size before users access the application. With a dynamically
371 growing pool, the error may occur much later after the pool has been in use for
372 some time.
373
374 The Real-World Performance Group also recommends keeping pool sizes small, as
375 they may perform better than larger pools. The pool attributes should be
376 adjusted to handle the desired workload within the bounds of available resources
377 in cx_Oracle and the database.
378
379 Make sure the :ref:`firewall <hanetwork>`, `resource manager
380 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-2BEF5482-CF97-4A85-BD90-9195E41E74EF>`__
381 or user profile `IDLE_TIME
382 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-ABC7AE4D-64A8-4EA9-857D-BEF7300B64C3>`__
383 do not expire idle sessions, since this will require connections be recreated,
384 which will impact performance and scalability.
385
386 .. _sessioncallback:
387
388 Session CallBacks for Setting Pooled Connection State
389 -----------------------------------------------------
390
391 Applications can set "session" state in each connection. Examples of session
392 state are NLS settings from ``ALTER SESSION`` statements. Pooled connections
393 will retain their session state after they have been released back to the pool.
394 However, because pools can grow, or connections in the pool can be recreated,
395 there is no guarantee a subsequent :meth:`~SessionPool.acquire()` call will
396 return a database connection that has any particular state.
397
398 The :meth:`~cx_Oracle.SessionPool()` parameter ``sessionCallback``
399 enables efficient setting of session state so that connections have a
400 known session state, without requiring that state to be explicitly set
401 after each :meth:`~SessionPool.acquire()` call.
402
403 Connections can also be tagged when they are released back to the pool. The
404 tag is a user-defined string that represents the session state of the
405 connection. When acquiring connections, a particular tag can be requested. If
406 a connection with that tag is available, it will be returned. If not, then
407 another session will be returned. By comparing the actual and requested tags,
408 applications can determine what exact state a session has, and make any
409 necessary changes.
410
411 The session callback can be a Python function or a PL/SQL procedure.
412
413 There are three common scenarios for ``sessionCallback``:
414
415 - When all connections in the pool should have the same state, use a
416 Python callback without tagging.
417
418 - When connections in the pool require different state for different
419 users, use a Python callback with tagging.
420
421 - When using :ref:`drcp`: use a PL/SQL callback with tagging.
422
423
424 **Python Callback**
425
426 If the ``sessionCallback`` parameter is a Python procedure, it will be called
427 whenever :meth:`~SessionPool.acquire()` will return a newly created database
428 connection that has not been used before. It is also called when connection
429 tagging is being used and the requested tag is not identical to the tag in the
430 connection returned by the pool.
431
432 An example is:
433
434 .. code-block:: python
435
436 # Set the NLS_DATE_FORMAT for a session
437 def initSession(connection, requestedTag):
438 cursor = connection.cursor()
439 cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI'")
440
441 # Create the pool with session callback defined
442 pool = cx_Oracle.SessionPool("hr", userpwd, "orclpdb1",
443 sessionCallback=initSession, encoding="UTF-8")
444
445 # Acquire a connection from the pool (will always have the new date format)
446 connection = pool.acquire()
447
448 If needed, the ``initSession()`` procedure is called internally before
449 ``acquire()`` returns. It will not be called when previously used connections
450 are returned from the pool. This means that the ALTER SESSION does not need to
451 be executed after every ``acquire()`` call. This improves performance and
452 scalability.
453
454 In this example tagging was not being used, so the ``requestedTag`` parameter
455 is ignored.
456
457 Note: if you need to execute multiple SQL statements in the callback, use an
458 anonymous PL/SQL block to save :ref:`round-trips <roundtrips>` of repeated
459 ``execute()`` calls. With ALTER SESSION, pass multiple settings in the one
460 statement:
461
462 .. code-block:: python
463
464 cursor.execute("""
465 begin
466 execute immediate
467 'alter session set nls_date_format = ''YYYY-MM-DD'' nls_language = AMERICAN';
468 -- other SQL statements could be put here
469 end;""")
470
471 **Connection Tagging**
472
473 Connection tagging is used when connections in a pool should have differing
474 session states. In order to retrieve a connection with a desired state, the
475 ``tag`` attribute in :meth:`~SessionPool.acquire()` needs to be set.
476
477 When cx_Oracle is using Oracle Client libraries 12.2 or later, then cx_Oracle
478 uses 'multi-property tags' and the tag string must be of the form of one or
479 more "name=value" pairs separated by a semi-colon, for example
480 ``"loc=uk;lang=cy"``.
481
482 When a connection is requested with a given tag, and a connection with that tag
483 is not present in the pool, then a new connection, or an existing connection
484 with cleaned session state, will be chosen by the pool and the session callback
485 procedure will be invoked. The callback can then set desired session state and
486 update the connection's tag. However if the ``matchanytag`` parameter of
487 :meth:`~SessionPool.acquire()` is *True*, then any other tagged connection may
488 be chosen by the pool and the callback procedure should parse the actual and
489 requested tags to determine which bits of session state should be reset.
490
491 The example below demonstrates connection tagging:
492
493 .. code-block:: python
494
495 def initSession(connection, requestedTag):
496 if requestedTag == "NLS_DATE_FORMAT=SIMPLE":
497 sql = "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'"
498 elif requestedTag == "NLS_DATE_FORMAT=FULL":
499 sql = "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI'"
500 cursor = connection.cursor()
501 cursor.execute(sql)
502 connection.tag = requestedTag
503
504 pool = cx_Oracle.SessionPool("hr", userpwd, "orclpdb1",
505 sessionCallback=initSession, encoding="UTF-8")
506
507 # Two connections with different session state:
508 connection1 = pool.acquire(tag = "NLS_DATE_FORMAT=SIMPLE")
509 connection2 = pool.acquire(tag = "NLS_DATE_FORMAT=FULL")
510
511 See `SessionCallback.py
512 <https://github.com/oracle/python-cx_Oracle/tree/master/
513 samples/SessionCallback.py>`__ for an example.
514
515 **PL/SQL Callback**
516
517 When cx_Oracle uses Oracle Client 12.2 or later, the session callback can also
518 be the name of a PL/SQL procedure. A PL/SQL callback will be initiated only
519 when the tag currently associated with a connection does not match the tag that
520 is requested. A PL/SQL callback is most useful when using :ref:`drcp` because
521 DRCP does not require a :ref:`round-trip <roundtrips>` to invoke a PL/SQL
522 session callback procedure.
523
524 The PL/SQL session callback should accept two VARCHAR2 arguments:
525
526 .. code-block:: sql
527
528 PROCEDURE myPlsqlCallback (
529 requestedTag IN VARCHAR2,
530 actualTag IN VARCHAR2
531 );
532
533 The logic in this procedure can parse the actual tag in the session that has
534 been selected by the pool and compare it with the tag requested by the
535 application. The procedure can then change any state required before the
536 connection is returned to the application from :meth:`~SessionPool.acquire()`.
537
538 If the ``matchanytag`` attribute of :meth:`~SessionPool.acquire()` is *True*,
539 then a connection with any state may be chosen by the pool.
540
541 Oracle 'multi-property tags' must be used. The tag string must be of the form
542 of one or more "name=value" pairs separated by a semi-colon, for example
543 ``"loc=uk;lang=cy"``.
544
545 In cx_Oracle set ``sessionCallback`` to the name of the PL/SQL procedure. For
546 example:
547
548 .. code-block:: python
549
550 pool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orclpdb1:pooled",
551 sessionCallback="myPlsqlCallback", encoding="UTF-8")
552
553 connection = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE",
554 # DRCP options, if you are using DRCP
555 cclass='MYCLASS', purity=cx_Oracle.ATTR_PURITY_SELF)
556
557 See `SessionCallbackPLSQL.py
558 <https://github.com/oracle/python-cx_Oracle/tree/master/
559 samples/SessionCallbackPLSQL.py>`__ for an example.
560
561 .. _connpooltypes:
562
563 Heterogeneous and Homogeneous Connection Pools
564 ----------------------------------------------
565
566 By default, connection pools are ‘homogeneous’, meaning that all connections
567 use the same database credentials. However, if the pool option ``homogeneous``
568 is False at the time of pool creation, then a ‘heterogeneous’ pool will be
569 created. This allows different credentials to be used each time a connection
570 is acquired from the pool with :meth:`~SessionPool.acquire()`.
571
572 **Heterogeneous Pools**
573
574 When a heterogeneous pool is created by setting ``homogeneous`` to False and no
575 credentials are supplied during pool creation, then a user name and password
576 may be passed to :meth:`~SessionPool.acquire()` as shown in this example:
577
578 .. code-block:: python
579
580 pool = cx_Oracle.SessionPool(dsn="dbhost.example.com/orclpdb1", homogeneous=False,
581 encoding="UTF-8")
582 connection = pool.acquire(user="hr", password=userpwd)
583
584 .. _drcp:
585
586 Database Resident Connection Pooling (DRCP)
587 ===========================================
588
589 `Database Resident Connection Pooling (DRCP)
590 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
591 id=GUID-015CA8C1-2386-4626-855D-CC546DDC1086>`__ enables database resource
592 sharing for applications that run in multiple client processes, or run on
593 multiple middle-tier application servers. By default each connection from
594 Python will use one database server process. DRCP allows pooling of these
595 server processes. This reduces the amount of memory required on the database
596 host. The DRCP pool can be shared by multiple applications.
597
598 DRCP is useful for applications which share the same database credentials, have
599 similar session settings (for example date format settings or PL/SQL package
600 state), and where the application gets a database connection, works on it for a
601 relatively short duration, and then releases it.
602
603 Applications can choose whether or not to use pooled connections at runtime.
604
605 For efficiency, it is recommended that DRCP connections should be used
606 in conjunction with cx_Oracle’s local :ref:`connection pool <connpool>`.
607
608 **Using DRCP in Python**
609
610 Using DRCP with cx_Oracle applications involves the following steps:
611
612 1. Configuring and enabling DRCP in the database
613 2. Configuring the application to use a DRCP connection
614 3. Deploying the application
615
616 **Configuring and enabling DRCP**
617
618 Every instance of Oracle Database uses a single, default connection
619 pool. The pool can be configured and administered by a DBA using the
620 ``DBMS_CONNECTION_POOL`` package:
621
622 .. code-block:: sql
623
624 EXECUTE DBMS_CONNECTION_POOL.CONFIGURE_POOL(
625 pool_name => 'SYS_DEFAULT_CONNECTION_POOL',
626 minsize => 4,
627 maxsize => 40,
628 incrsize => 2,
629 session_cached_cursors => 20,
630 inactivity_timeout => 300,
631 max_think_time => 600,
632 max_use_session => 500000,
633 max_lifetime_session => 86400)
634
635 Alternatively the method ``DBMS_CONNECTION_POOL.ALTER_PARAM()`` can
636 set a single parameter:
637
638 .. code-block:: sql
639
640 EXECUTE DBMS_CONNECTION_POOL.ALTER_PARAM(
641 pool_name => 'SYS_DEFAULT_CONNECTION_POOL',
642 param_name => 'MAX_THINK_TIME',
643 param_value => '1200')
644
645 The ``inactivity_timeout`` setting terminates idle pooled servers, helping
646 optimize database resources. To avoid pooled servers permanently being held
647 onto by a selfish Python script, the ``max_think_time`` parameter can be set.
648 The parameters ``num_cbrok`` and ``maxconn_cbrok`` can be used to distribute
649 the persistent connections from the clients across multiple brokers. This may
650 be needed in cases where the operating system per-process descriptor limit is
651 small. Some customers have found that having several connection brokers
652 improves performance. The ``max_use_session`` and ``max_lifetime_session``
653 parameters help protect against any unforeseen problems affecting server
654 processes. The default values will be suitable for most users. See the
655 `Oracle DRCP documentation
656 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
657 id=GUID-015CA8C1-2386-4626-855D-CC546DDC1086>`__ for details on parameters.
658
659 In general, if pool parameters are changed, the pool should be restarted,
660 otherwise server processes will continue to use old settings.
661
662 There is a ``DBMS_CONNECTION_POOL.RESTORE_DEFAULTS()`` procedure to
663 reset all values.
664
665 When DRCP is used with RAC, each database instance has its own connection
666 broker and pool of servers. Each pool has the identical configuration. For
667 example, all pools start with ``minsize`` server processes. A single
668 DBMS_CONNECTION_POOL command will alter the pool of each instance at the same
669 time. The pool needs to be started before connection requests begin. The
670 command below does this by bringing up the broker, which registers itself with
671 the database listener:
672
673 .. code-block:: sql
674
675 EXECUTE DBMS_CONNECTION_POOL.START_POOL()
676
677 Once enabled this way, the pool automatically restarts when the database
678 instance restarts, unless explicitly stopped with the
679 ``DBMS_CONNECTION_POOL.STOP_POOL()`` command:
680
681 .. code-block:: sql
682
683 EXECUTE DBMS_CONNECTION_POOL.STOP_POOL()
684
685 The pool cannot be stopped while connections are open.
686
687 **Application Deployment for DRCP**
688
689 In order to use DRCP, the ``cclass`` and ``purity`` parameters should
690 be passed to :meth:`cx_Oracle.connect()` or :meth:`SessionPool.acquire()`. If
691 ``cclass`` is not set, the pooled server sessions will not be reused optimally,
692 and the DRCP statistic views will record large values for NUM_MISSES.
693
694 The DRCP ``purity`` can be one of ``ATTR_PURITY_NEW``, ``ATTR_PURITY_SELF``,
695 or ``ATTR_PURITY_DEFAULT``. The value ``ATTR_PURITY_SELF`` allows reuse of
696 both the pooled server process and session memory, giving maximum benefit from
697 DRCP. See the Oracle documentation on `benefiting from scalability
698 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
699 id=GUID-661BB906-74D2-4C5D-9C7E-2798F76501B3>`__.
700
701 The connection string used for :meth:`~cx_Oracle.connect()` or
702 :meth:`~SessionPool.acquire()` must request a pooled server by
703 following one of the syntaxes shown below:
704
705 Using Oracle’s Easy Connect syntax, the connection would look like:
706
707 .. code-block:: python
708
709 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orcl:pooled",
710 encoding="UTF-8")
711
712 Or if you connect using a Net Service Name named ``customerpool``:
713
714 .. code-block:: python
715
716 connection = cx_Oracle.connect("hr", userpwd, "customerpool", encoding="UTF-8")
717
718 Then only the Oracle Network configuration file ``tnsnames.ora`` needs
719 to be modified::
720
721 customerpool = (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)
722 (HOST=dbhost.example.com)
723 (PORT=1521))(CONNECT_DATA=(SERVICE_NAME=CUSTOMER)
724 (SERVER=POOLED)))
725
726 If these changes are made and the database is not actually configured for DRCP,
727 or the pool is not started, then connections will not succeed and an error will
728 be returned to the Python application.
729
730 Although applications can choose whether or not to use pooled connections at
731 runtime, care must be taken to configure the database appropriately for the
732 number of expected connections, and also to stop inadvertent use of non-DRCP
733 connections leading to a database server resource shortage. Conversely, avoid
734 using DRCP connections for long-running operations.
735
736 The example below shows how to connect to Oracle Database using Database
737 Resident Connection Pooling:
738
739 .. code-block:: python
740
741 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orcl:pooled",
742 cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF, encoding="UTF-8")
743
744 The example below shows connecting to Oracle Database using DRCP and
745 cx_Oracle's connection pooling:
746
747 .. code-block:: python
748
749 mypool = cx_Oracle.SessionPool("hr", userpwd, "dbhost.example.com/orcl:pooled",
750 encoding="UTF-8")
751 connection = mypool.acquire(cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF)
752
753 For more information about DRCP see `Oracle Database Concepts Guide
754 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
755 id=GUID-531EEE8A-B00A-4C03-A2ED-D45D92B3F797>`__, and for DRCP Configuration
756 see `Oracle Database Administrator's Guide
757 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
758 id=GUID-82FF6896-F57E-41CF-89F7-755F3BC9C924>`__.
759
760 **Closing Connections**
761
762 Python scripts where cx_Oracle connections do not go out of scope quickly
763 (which releases them), or do not currently use :meth:`Connection.close()`,
764 should be examined to see if :meth:`~Connection.close()` can be used, which
765 then allows maximum use of DRCP pooled servers by the database:
766
767 .. code-block:: python
768
769 # Do some database operations
770 connection = mypool.acquire(cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF)
771 . . .
772 connection.close();
773
774 # Do lots of non-database work
775 . . .
776
777 # Do some more database operations
778 connection = mypool.acquire(cclass="MYCLASS", purity=cx_Oracle.ATTR_PURITY_SELF)
779 . . .
780 connection.close();
781
782 **Monitoring DRCP**
783
784 Data dictionary views are available to monitor the performance of DRCP.
785 Database administrators can check statistics such as the number of busy and
786 free servers, and the number of hits and misses in the pool against the total
787 number of requests from clients. The views are:
788
789 * ``DBA_CPOOL_INFO``
790 * ``V$PROCESS``
791 * ``V$SESSION``
792 * ``V$CPOOL_STATS``
793 * ``V$CPOOL_CC_STATS``
794 * ``V$CPOOL_CONN_INFO``
795
796 **DBA_CPOOL_INFO View**
797
798 ``DBA_CPOOL_INFO`` displays configuration information about the DRCP pool. The
799 columns are equivalent to the ``dbms_connection_pool.configure_pool()``
800 settings described in the table of DRCP configuration options, with the
801 addition of a ``STATUS`` column. The status is ``ACTIVE`` if the pool has been
802 started and ``INACTIVE`` otherwise. Note the pool name column is called
803 ``CONNECTION_POOL``. This example checks whether the pool has been started and
804 finds the maximum number of pooled servers::
805
806 SQL> SELECT connection_pool, status, maxsize FROM dba_cpool_info;
807
808 CONNECTION_POOL STATUS MAXSIZE
809 ---------------------------- ---------- ----------
810 SYS_DEFAULT_CONNECTION_POOL ACTIVE 40
811
812 **V$PROCESS and V$SESSION Views**
813
814 The ``V$SESSION`` view shows information about the currently active DRCP
815 sessions. It can also be joined with ``V$PROCESS`` via
816 ``V$SESSION.PADDR = V$PROCESS.ADDR`` to correlate the views.
817
818 **V$CPOOL_STATS View**
819
820 The ``V$CPOOL_STATS`` view displays information about the DRCP statistics for
821 an instance. The V$CPOOL_STATS view can be used to assess how efficient the
822 pool settings are. T his example query shows an application using the pool
823 effectively. The low number of misses indicates that servers and sessions were
824 reused. The wait count shows just over 1% of requests had to wait for a pooled
825 server to become available::
826
827 NUM_REQUESTS NUM_HITS NUM_MISSES NUM_WAITS
828 ------------ ---------- ---------- ----------
829 10031 99990 40 1055
830
831 If ``cclass`` was set (allowing pooled servers and sessions to be
832 reused) then NUM_MISSES will be low. If the pool maxsize is too small for
833 the connection load, then NUM_WAITS will be high.
834
835 **V$CPOOL_CC_STATS View**
836
837 The view ``V$CPOOL_CC_STATS`` displays information about the connection class
838 level statistics for the pool per instance::
839
840 SQL> SELECT cclass_name, num_requests, num_hits, num_misses
841 FROM v$cpool_cc_stats;
842
843 CCLASS_NAME NUM_REQUESTS NUM_HITS NUM_MISSES
844 -------------------------------- ------------ ---------- ----------
845 HR.MYCLASS 100031 99993 38
846
847 **V$CPOOL_CONN_INFO View**
848
849 The ``V$POOL_CONN_INFO`` view gives insight into client processes that are
850 connected to the connection broker, making it easier to monitor and trace
851 applications that are currently using pooled servers or are idle. This view was
852 introduced in Oracle 11gR2.
853
854 You can monitor the view ``V$CPOOL_CONN_INFO`` to, for example, identify
855 misconfigured machines that do not have the connection class set correctly.
856 This view maps the machine name to the class name::
857
858 SQL> SELECT cclass_name, machine FROM v$cpool_conn_info;
859
860 CCLASS_NAME MACHINE
861 --------------------------------------- ------------
862 CJ.OCI:SP:wshbIFDtb7rgQwMyuYvodA cjlinux
863 . . .
864
865 In this example you would examine applications on ``cjlinux`` and make
866 sure ``cclass`` is set.
867
868
869 .. _proxyauth:
870
871 Connecting Using Proxy Authentication
872 =====================================
873
874 Proxy authentication allows a user (the "session user") to connect to Oracle
875 Database using the credentials of a 'proxy user'. Statements will run as the
876 session user. Proxy authentication is generally used in three-tier applications
877 where one user owns the schema while multiple end-users access the data. For
878 more information about proxy authentication, see the `Oracle documentation
879 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
880 id=GUID-D77D0D4A-7483-423A-9767-CBB5854A15CC>`__.
881
882 An alternative to using proxy users is to set
883 :attr:`Connection.client_identifier` after connecting and use its value in
884 statements and in the database, for example for :ref:`monitoring
885 <endtoendtracing>`.
886
887 The following proxy examples use these schemas. The ``mysessionuser`` schema is
888 granted access to use the password of ``myproxyuser``:
889
890 .. code-block:: sql
891
892 CREATE USER myproxyuser IDENTIFIED BY myproxyuserpw;
893 GRANT CREATE SESSION TO myproxyuser;
894
895 CREATE USER mysessionuser IDENTIFIED BY itdoesntmatter;
896 GRANT CREATE SESSION TO mysessionuser;
897
898 ALTER USER mysessionuser GRANT CONNECT THROUGH myproxyuser;
899
900 After connecting to the database, the following query can be used to show the
901 session and proxy users:
902
903 .. code-block:: sql
904
905 SELECT SYS_CONTEXT('USERENV', 'PROXY_USER'),
906 SYS_CONTEXT('USERENV', 'SESSION_USER')
907 FROM DUAL;
908
909 Standalone connection examples:
910
911 .. code-block:: python
912
913 # Basic Authentication without a proxy
914 connection = cx_Oracle.connect("myproxyuser", "myproxyuserpw", "dbhost.example.com/orclpdb1",
915 encoding="UTF-8")
916 # PROXY_USER: None
917 # SESSION_USER: MYPROXYUSER
918
919 # Basic Authentication with a proxy
920 connection = cx_Oracle.connect(user="myproxyuser[mysessionuser]", "myproxyuserpw",
921 "dbhost.example.com/orclpdb1", encoding="UTF-8")
922 # PROXY_USER: MYPROXYUSER
923 # SESSION_USER: MYSESSIONUSER
924
925 Pooled connection examples:
926
927 .. code-block:: python
928
929 # Basic Authentication without a proxy
930 pool = cx_Oracle.SessionPool("myproxyuser", "myproxyuser", "dbhost.example.com/orclpdb1",
931 encoding="UTF-8")
932 connection = pool.acquire()
933 # PROXY_USER: None
934 # SESSION_USER: MYPROXYUSER
935
936 # Basic Authentication with proxy
937 pool = cx_Oracle.SessionPool("myproxyuser[mysessionuser]", "myproxyuser",
938 "dbhost.example.com/orclpdb1", homogeneous=False, encoding="UTF-8")
939 connection = pool.acquire()
940 # PROXY_USER: MYPROXYUSER
941 # SESSION_USER: MYSESSIONUSER
942
943 Note the use of a :ref:`heterogeneous <connpooltypes>` pool in the example
944 above. This is required in this scenario.
945
946 .. _extauth:
947
948 Connecting Using External Authentication
949 ========================================
950
951 Instead of storing the database username and password in Python scripts or
952 environment variables, database access can be authenticated by an outside
953 system. External Authentication allows applications to validate user access by
954 an external password store (such as an Oracle Wallet), by the operating system,
955 or with an external authentication service.
956
957 Using an Oracle Wallet for External Authentication
958 --------------------------------------------------
959
960 The following steps give an overview of using an Oracle Wallet. Wallets should
961 be kept securely. Wallets can be managed with `Oracle Wallet Manager
962 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
963 id=GUID-E3E16C82-E174-4814-98D5-EADF1BCB3C37>`__.
964
965 In this example the wallet is created for the ``myuser`` schema in the directory
966 ``/home/oracle/wallet_dir``. The ``mkstore`` command is available from a full
967 Oracle client or Oracle Database installation. If you have been given wallet by
968 your DBA, skip to step 3.
969
970 1. First create a new wallet as the ``oracle`` user::
971
972 mkstore -wrl "/home/oracle/wallet_dir" -create
973
974 This will prompt for a new password for the wallet.
975
976 2. Create the entry for the database user name and password that are currently
977 hardcoded in your Python scripts. Use either of the methods shown below.
978 They will prompt for the wallet password that was set in the first step.
979
980 **Method 1 - Using an Easy Connect string**::
981
982 mkstore -wrl "/home/oracle/wallet_dir" -createCredential dbhost.example.com/orclpdb1 myuser myuserpw
983
984 **Method 2 - Using a connect name identifier**::
985
986 mkstore -wrl "/home/oracle/wallet_dir" -createCredential mynetalias myuser myuserpw
987
988 The alias key ``mynetalias`` immediately following the
989 ``-createCredential`` option will be the connect name to be used in Python
990 scripts. If your application connects with multiple different database
991 users, you could create a wallet entry with different connect names for
992 each.
993
994 You can see the newly created credential with::
995
996 mkstore -wrl "/home/oracle/wallet_dir" -listCredential
997
998 3. Skip this step if the wallet was created using an Easy Connect String.
999 Otherwise, add an entry in :ref:`tnsnames.ora <optnetfiles>` for the connect
1000 name as follows::
1001
1002 mynetalias =
1003 (DESCRIPTION =
1004 (ADDRESS = (PROTOCOL = TCP)(HOST = dbhost.example.com)(PORT = 1521))
1005 (CONNECT_DATA =
1006 (SERVER = DEDICATED)
1007 (SERVICE_NAME = orclpdb1)
1008 )
1009 )
1010
1011 The file uses the description for your existing database and sets the
1012 connect name alias to ``mynetalias``, which is the identifier used when
1013 adding the wallet entry.
1014
1015 4. Add the following wallet location entry in the :ref:`sqlnet.ora
1016 <optnetfiles>` file, using the ``DIRECTORY`` you created the wallet in::
1017
1018 WALLET_LOCATION =
1019 (SOURCE =
1020 (METHOD = FILE)
1021 (METHOD_DATA =
1022 (DIRECTORY = /home/oracle/wallet_dir)
1023 )
1024 )
1025 SQLNET.WALLET_OVERRIDE = TRUE
1026
1027 Examine the Oracle documentation for full settings and values.
1028
1029 5. Ensure the configuration files are in a default location or set TNS_ADMIN is
1030 set to the directory containing them. See :ref:`optnetfiles`.
1031
1032 With an Oracle wallet configured, and readable by you, your scripts
1033 can connect using::
1034
1035 connection = cx_Oracle.connect(dsn="mynetalias", encoding="UTF-8")
1036
1037 or::
1038
1039 pool = cx_Oracle.SessionPool(externalauth=True, homogeneous=False, dsn="mynetalias",
1040 encoding="UTF-8")
1041 pool.acquire()
1042
1043 The ``dsn`` must match the one used in the wallet.
1044
1045 After connecting, the query::
1046
1047 SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') FROM DUAL;
1048
1049 will show::
1050
1051 MYUSER
1052
1053 .. note::
1054
1055 Wallets are also used to configure TLS connections. If you are using a
1056 wallet like this, you may need a database username and password in
1057 :meth:`cx_Oracle.connect()` and :meth:`cx_Oracle.SessionPool()` calls.
1058
1059 **External Authentication and Proxy Authentication**
1060
1061 The following examples show external wallet authentication combined with
1062 :ref:`proxy authentication <proxyauth>`. These examples use the wallet
1063 configuration from above, with the addition of a grant to another user::
1064
1065 ALTER USER mysessionuser GRANT CONNECT THROUGH myuser;
1066
1067 After connection, you can check who the session user is with:
1068
1069 .. code-block:: sql
1070
1071 SELECT SYS_CONTEXT('USERENV', 'PROXY_USER'),
1072 SYS_CONTEXT('USERENV', 'SESSION_USER')
1073 FROM DUAL;
1074
1075 Standalone connection example:
1076
1077 .. code-block:: python
1078
1079 # External Authentication with proxy
1080 connection = cx_Oracle.connect(user="[mysessionuser]", dsn="mynetalias", encoding="UTF-8")
1081 # PROXY_USER: MYUSER
1082 # SESSION_USER: MYSESSIONUSER
1083
1084 Pooled connection example:
1085
1086 .. code-block:: python
1087
1088 # External Authentication with proxy
1089 pool = cx_Oracle.SessionPool(externalauth=True, homogeneous=False, dsn="mynetalias",
1090 encoding="UTF-8")
1091 pool.acquire(user="[mysessionuser]")
1092 # PROXY_USER: MYUSER
1093 # SESSION_USER: MYSESSIONUSER
1094
1095 The following usage is not supported:
1096
1097 .. code-block:: python
1098
1099 pool = cx_Oracle.SessionPool("[mysessionuser]", externalauth=True, homogeneous=False,
1100 dsn="mynetalias", encoding="UTF-8")
1101 pool.acquire()
1102
1103
1104 Operating System Authentication
1105 -------------------------------
1106
1107 With Operating System authentication, Oracle allows user authentication to be
1108 performed by the operating system. The following steps give an overview of how
1109 to implement OS Authentication on Linux.
1110
1111 1. Login to your computer. The commands used in these steps assume the
1112 operating system user name is "oracle".
1113
1114 2. Login to SQL*Plus as the SYSTEM user and verify the value for the
1115 ``OS_AUTHENT_PREFIX`` parameter::
1116
1117 SQL> SHOW PARAMETER os_authent_prefix
1118
1119 NAME TYPE VALUE
1120 ------------------------------------ ----------- ------------------------------
1121 os_authent_prefix string ops$
1122
1123 3. Create an Oracle database user using the ``os_authent_prefix`` determined in
1124 step 2, and the operating system user name:
1125
1126 .. code-block:: sql
1127
1128 CREATE USER ops$oracle IDENTIFIED EXTERNALLY;
1129 GRANT CONNECT, RESOURCE TO ops$oracle;
1130
1131 In Python, connect using the following code::
1132
1133 connection = cx_Oracle.connect(dsn="mynetalias", encoding="UTF-8")
1134
1135 Your session user will be ``OPS$ORACLE``.
1136
1137 If your database is not on the same computer as python, you can perform testing
1138 by setting the database configuration parameter ``remote_os_authent=true``.
1139 Beware this is insecure.
1140
1141 See `Oracle Database Security Guide
1142 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
1143 id=GUID-37BECE32-58D5-43BF-A098-97936D66968F>`__ for more information about
1144 Operating System Authentication.
1145
1146 Privileged Connections
1147 ======================
1148
1149 The ``mode`` parameter of the function :meth:`cx_Oracle.connect()` specifies
1150 the database privilege that you want to associate with the user.
1151
1152 The example below shows how to connect to Oracle Database as SYSDBA:
1153
1154 .. code-block:: python
1155
1156 connection = cx_Oracle.connect("sys", syspwd, "dbhost.example.com/orclpdb1",
1157 mode=cx_Oracle.SYSDBA, encoding="UTF-8")
1158
1159 cursor = con.cursor()
1160 sql = "GRANT SYSOPER TO hr"
1161 cursor.execute(sql)
1162
1163 This is equivalent to executing the following in SQL*Plus:
1164
1165 .. code-block:: sql
1166
1167 CONNECT sys/syspwd AS SYSDBA
1168
1169 GRANT SYSOPER TO hr;
1170
1171 .. _netencrypt:
1172
1173 Securely Encrypting Network Traffic to Oracle Database
1174 ======================================================
1175
1176 You can encrypt data transferred between the Oracle Database and the Oracle
1177 Client libraries used by cx_Oracle so that unauthorized parties are not able to
1178 view plain text values as the data passes over the network. The easiest
1179 configuration is Oracle’s native network encryption. The standard SSL protocol
1180 can also be used if you have a PKI, but setup is necessarily more involved.
1181
1182 With native network encryption, the client and database server negotiate a key
1183 using Diffie-Hellman key exchange. This provides protection against
1184 man-in-the-middle attacks.
1185
1186 Native network encryption can be configured by editing Oracle Net’s optional
1187 :ref:`sqlnet.ora <optnetfiles>` configuration file, on either the database
1188 server and/or on each cx_Oracle 'client' machine. Parameters control whether
1189 data integrity checking and encryption is required or just allowed, and which
1190 algorithms the client and server should consider for use.
1191
1192 As an example, to ensure all connections to the database are checked for
1193 integrity and are also encrypted, create or edit the Oracle Database
1194 ``$ORACLE_HOME/network/admin/sqlnet.ora`` file. Set the checksum negotiation
1195 to always validate a checksum and set the checksum type to your desired value.
1196 The network encryption settings can similarly be set. For example, to use the
1197 SHA512 checksum and AES256 encryption use::
1198
1199 SQLNET.CRYPTO_CHECKSUM_SERVER = required
1200 SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER = (SHA512)
1201 SQLNET.ENCRYPTION_SERVER = required
1202 SQLNET.ENCRYPTION_TYPES_SERVER = (AES256)
1203
1204 If you definitely know that the database server enforces integrity and
1205 encryption, then you do not need to configure cx_Oracle separately. However
1206 you can also, or alternatively, do so depending on your business needs. Create
1207 a ``sqlnet.ora`` on your client machine and locate it with other
1208 :ref:`optnetfiles`::
1209
1210 SQLNET.CRYPTO_CHECKSUM_CLIENT = required
1211 SQLNET.CRYPTO_CHECKSUM_TYPES_CLIENT = (SHA512)
1212 SQLNET.ENCRYPTION_CLIENT = required
1213 SQLNET.ENCRYPTION_TYPES_CLIENT = (AES256)
1214
1215 The client and server sides can negotiate the protocols used if the settings
1216 indicate more than one value is accepted.
1217
1218 Note that these are example settings only. You must review your security
1219 requirements and read the documentation for your Oracle version. In particular
1220 review the available algorithms for security and performance.
1221
1222 The ``NETWORK_SERVICE_BANNER`` column of the database view
1223 `V$SESSION_CONNECT_INFO
1224 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
1225 id=GUID-9F0DCAEA-A67E-4183-89E7-B1555DC591CE>`__ can be used to verify the
1226 encryption status of a connection.
1227
1228 For more information on Oracle Data Network Encryption and Integrity,
1229 configuring SSL network encryption and Transparent Data Encryption of
1230 data-at-rest in the database, see `Oracle Database Security Guide
1231 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
1232 id=GUID-41040F53-D7A6-48FA-A92A-0C23118BC8A0>`__.
1233
1234
1235 Resetting Passwords
1236 ===================
1237
1238 After connecting, passwords can be changed by calling
1239 :meth:`Connection.changepassword()`:
1240
1241 .. code-block:: python
1242
1243 # Get the passwords from somewhere, such as prompting the user
1244 oldpwd = getpass.getpass("Old Password for %s: " % username)
1245 newpwd = getpass.getpass("New Password for %s: " % username)
1246
1247 connection.changepassword(oldpwd, newpwd)
1248
1249 When a password has expired and you cannot connect directly, you can connect
1250 and change the password in one operation by using the ``newpassword`` parameter
1251 of the function :meth:`cx_Oracle.connect()` constructor:
1252
1253 .. code-block:: python
1254
1255 # Get the passwords from somewhere, such as prompting the user
1256 oldpwd = getpass.getpass("Old Password for %s: " % username)
1257 newpwd = getpass.getpass("New Password for %s: " % username)
1258
1259 connection = cx_Oracle.connect(username, oldpwd, "dbhost.example.com/orclpdb1",
1260 newpassword=newpwd, encoding="UTF-8")
1261
1262 .. _autononmousdb:
1263
1264 Connecting to Autononmous Databases
1265 ===================================
1266
1267 To enable connection to Oracle Autonomous Database in Oracle Cloud, a wallet
1268 needs be downloaded from the cloud GUI, and cx_Oracle needs to be configured to
1269 use it. A database username and password is still required. The wallet only
1270 enables SSL/TLS.
1271
1272 Install the Wallet and Network Configuration Files
1273 --------------------------------------------------
1274
1275 From the Oracle Cloud console for the database, download the wallet zip file. It
1276 contains the wallet and network configuration files. Note: keep wallet files in
1277 a secure location and share them only with authorized users.
1278
1279 Unzip the wallet zip file.
1280
1281 For cx_Oracle, only these files from the zip are needed:
1282
1283 - ``tnsnames.ora`` - Maps net service names used for application connection strings to your database services
1284 - ``sqlnet.ora`` - Configures Oracle Network settings
1285 - ``cwallet.sso`` - Enables SSL/TLS connections
1286
1287 The other files and the wallet password are not needed.
1288
1289 Place these files as shown in :ref:`Optional Oracle Net Configuration Files <optnetfiles>`.
1290
1291 Run Your Application
1292 --------------------
1293
1294 The ``tnsnames.ora`` file contains net service names for various levels of
1295 database service. For example, if you create a database called CJDB1 with the
1296 Always Free services from the `Oracle Cloud Free Tier
1297 <https://www.oracle.com//cloud/free/>`__, then you might decide to use the
1298 connection string in ``tnsnames.ora`` called ``cjdb1_high``.
1299
1300 Update your application to use your schema username, its database password, and
1301 a net service name, for example:
1302
1303 .. code-block:: python
1304
1305 connection = cx_Oracle.connect("scott", userpwd, "cjdb1_high", encoding="UTF-8")
1306
1307 Once you have set Oracle environment variables required by your application,
1308 such as ``TNS_ADMIN``, you can start your application.
1309
1310 If you need to create a new database schema so you do not login as the
1311 privileged ADMIN user, refer to the relevant Oracle Cloud documentation, for
1312 example see `Create Database Users
1313 <https://docs.oracle.com/en/cloud/paas/atp-cloud/atpud/manage.html>`__ in the
1314 Oracle Autonomous Transaction Processing Dedicated Deployments manual.
1315
1316 Access Through a Proxy
1317 ----------------------
1318
1319 If you are behind a firewall, you can tunnel TLS/SSL connections via a proxy
1320 using `HTTPS_PROXY
1321 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-C672E92D-CE32-4759-9931-92D7960850F7>`__
1322 in the connect descriptor. Successful connection depends on specific proxy
1323 configurations. Oracle does not recommend doing this when performance is
1324 critical.
1325
1326 Edit ``sqlnet.ora`` and add a line:
1327
1328 SQLNET.USE_HTTPS_PROXY=on
1329
1330 Edit ``tnsnames.ora`` and add an ``HTTPS_PROXY`` proxy name and
1331 ``HTTPS_PROXY_PORT`` port to the connect descriptor address list of any service
1332 name you plan to use, for example:
1333
1334
1335 cjdb1_high = (description=
1336 (address=
1337 (https_proxy=myproxy.example.com)(https_proxy_port=80)
1338 (protocol=tcps)(port=1522)(host= . . . )
1339
1340 .. _connsharding:
1341
1342 Connecting to Sharded Databases
1343 ===============================
1344
1345 `Oracle Sharding
1346 <https://www.oracle.com/database/technologies/high-availability/sharding.html>`__
1347 can be used to horizontally partition data across independent databases. A
1348 database table can be split so each shard contains a table with the same columns
1349 but a different subset of rows. These tables are known as sharded tables.
1350 Sharding is configured in Oracle Database, see the `Oracle Sharding
1351 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=SHARD>`__ manual.
1352 Sharding requires Oracle Database and Oracle Client libraries 12.2, or later.
1353
1354 The :meth:`cx_Oracle.connect()` and :meth:`SessionPool.acquire()` functions
1355 accept ``shardingkey`` and ``supershardingkey`` parameters that are a sequence
1356 of values used to route the connection directly to a given shard. A sharding
1357 key is always required. A super sharding key is additionally required when
1358 using composite sharding, which is when data has been partitioned by a list or
1359 range (the super sharding key), and then further partitioned by a sharding key.
1360
1361 When creating a connection pool, the :meth:`cx_Oracle.SessionPool()` attribute
1362 ``maxSessionsPerShard`` can be set. This is used to balance connections in the
1363 pool equally across shards. It requires Oracle Client libraries 18.3, or later.
1364
1365 Shard key values may be of type string (mapping to VARCHAR2 shard keys), number
1366 (NUMBER), bytes (RAW), or date (DATE). Multiple types may be used in each
1367 array. Sharding keys of TIMESTAMP type are not supported.
1368
1369 When connected to a shard, queries will only return data from that shard. For
1370 queries that need to access data from multiple shards, connections can be
1371 established to the coordinator shard catalog database. In this case, no shard
1372 key or super shard key is used.
1373
1374 As an example of direct connection, if sharding had been configured on a single
1375 VARCHAR2 column like:
1376
1377 .. code-block:: sql
1378
1379 CREATE SHARDED TABLE customers (
1380 cust_id NUMBER,
1381 cust_name VARCHAR2(30),
1382 class VARCHAR2(10) NOT NULL,
1383 signup_date DATE,
1384 cust_code RAW(20),
1385 CONSTRAINT cust_name_pk PRIMARY KEY(cust_name))
1386 PARTITION BY CONSISTENT HASH (cust_name)
1387 PARTITIONS AUTO TABLESPACE SET ts1;
1388
1389 then direct connection to a shard can be made by passing a single sharding key:
1390
1391 .. code-block:: python
1392
1393 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
1394 encoding="UTF-8", shardingkey=["SCOTT"])
1395
1396 Numbers keys can be used in a similar way:
1397
1398 .. code-block:: python
1399
1400 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
1401 encoding="UTF-8", shardingkey=[110])
1402
1403 When sharding by DATE, you can connect like:
1404
1405 .. code-block:: python
1406
1407 import datetime
1408
1409 d = datetime.datetime(2014, 7, 3)
1410
1411 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
1412 encoding="UTF-8", shardingkey=[d])
1413
1414 When sharding by RAW, you can connect like:
1415
1416 .. code-block:: python
1417
1418 b = b'\x01\x04\x08';
1419
1420 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
1421 encoding="UTF-8", shardingkey=[b])
1422
1423 Multiple keys can be specified, for example:
1424
1425 .. code-block:: python
1426
1427 keyArray = [70, "SCOTT", "gold", b'\x00\x01\x02']
1428
1429 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
1430 encoding="UTF-8", shardingkey=keyArray)
1431
1432 A super sharding key example is:
1433
1434 .. code-block:: python
1435
1436 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
1437 encoding="UTF-8", supershardingkey=["goldclass"], shardingkey=["SCOTT"])
0 .. _cqn:
1
2 ***********************************
3 Continuous Query Notification (CQN)
4 ***********************************
5
6 `Continuous Query Notification (CQN)
7 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
8 id=GUID-373BAF72-3E63-42FE-8BEA-8A2AEFBF1C35>`__ allows applications to receive
9 notifications when a table changes, such as when rows have been updated,
10 regardless of the user or the application that made the change. This can be
11 useful in many circumstances, such as near real-time monitoring, auditing
12 applications, or for such purposes as mid-tier cache invalidation. A cache
13 might hold some values that depend on data in a table. If the data in the
14 table changes, the cached values must then be updated with the new information.
15
16 CQN notification behavior is widely configurable. Choices include specifying
17 what types of SQL should trigger a notification, whether notifications should
18 survive database loss, and control over unsubscription. You can also choose
19 whether notification messages will include ROWIDs of affected rows.
20
21 By default, object-level (previously known as Database Change Notification)
22 occurs and the Python notification method is invoked whenever a database
23 transaction is committed that changes an object that a registered query
24 references, regardless of whether the actual query result changed. However if
25 the :meth:`subscription <Connection.subscribe>` option ``qos`` is
26 :data:`cx_Oracle.SUBSCR_QOS_QUERY` then query-level notification occurs. In
27 this mode, the database notifies the application whenever a transaction changing
28 the result of the registered query is committed.
29
30 CQN is best used to track infrequent data changes.
31
32
33 Requirements
34 ============
35
36 Before using CQN, users must have appropriate permissions:
37
38 .. code-block:: sql
39
40 GRANT CHANGE NOTIFICATION TO <user-name>;
41
42 To use CQN, connections must have ``events`` mode set to ``True``, for
43 example:
44
45 .. code-block:: python
46
47 connection = cx_Oracle.connect(userName, password, "dbhost.example.com/orclpdb1", events=True)
48
49 The default CQN connection mode means the database must be able to connect back
50 to the application using cx_Oracle in order to receive notification events.
51 Alternatively, when using Oracle Database and Oracle client libraries 19.4, or
52 later, subscriptions can set the optional ``clientInitiated`` parameter to
53 ``True``, see ``Connection.subscribe()`` below.
54
55 The default CQN connection mode typically means that the machine running
56 cx_Oracle needs a fixed IP address. Note :meth:`Connection.subscribe()` does
57 not verify that this reverse connection is possible. If there is any problem
58 sending a notification, then the callback method will not be invoked.
59 Configuration options can include an IP address and port on which cx_Oracle will
60 listen for notifications; otherwise, the database chooses values.
61
62
63 Creating a Subscription
64 =======================
65
66 Subscriptions allow Python to receives notifications for events that take place
67 in the database that match the given parameters.
68
69 For example, a basic CQN subscription might be created like:
70
71 .. code-block:: python
72
73 connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE,
74 callback=MyCallback)
75
76 See :meth:`Connection.subscribe()` for details on all of the parameters.
77
78 See :ref:`cqn-operation-codes` for the types of operations that are supported.
79
80 See :ref:`subscr-qos` for the quality of service values that are supported.
81
82 See :ref:`subscr-namespaces` and :ref:`subscr-protocols` for the namespaces and
83 protocols that are supported.
84
85 See :ref:`subscrobj` for more details on the subscription object that is
86 created.
87
88 When using Oracle Database and Oracle client libraries 19.4, or later, the
89 optional subscription parameter ``clientInitiated`` can be set:
90
91 .. code-block:: python
92
93 connection.subscribe(namespace= . . ., callback=MyCallback, clientInitiated=True)
94
95 This enables CQN "client initiated" connections which internally use the same
96 approach as normal cx_Oracle connections to the database, and do not require the
97 database to be able to connect back to the application. Since client initiated
98 connections do not need special network configuration they have ease-of-use and
99 security advantages.
100
101
102 Registering Queries
103 ===================
104
105 Once a subscription has been created, one or more queries must be registered by
106 calling :meth:`Subscription.registerquery()`. Registering a query behaves
107 similarly to :meth:`Cursor.execute()`, but only queries are permitted and the
108 ``args`` parameter must be a sequence or dictionary.
109
110 An example script to receive query notifications when the 'CUSTOMER' table data
111 changes is:
112
113 .. code-block:: python
114
115 def CQNCallback(message):
116 print("Notification:")
117 for query in message.queries:
118 for tab in query.tables:
119 print("Table:", tab.name)
120 print("Operation:", tab.operation)
121 for row in tab.rows:
122 if row.operation & cx_Oracle.OPCODE_INSERT:
123 print("INSERT of rowid:", row.rowid)
124 if row.operation & cx_Oracle.OPCODE_DELETE:
125 print("DELETE of rowid:", row.rowid)
126
127 subscr = connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE,
128 callback=CQNCallback,
129 operations=cx_Oracle.OPCODE_INSERT | cx_Oracle.OPCODE_DELETE,
130 qos = cx_Oracle.SUBSCR_QOS_QUERY | cx_Oracle.SUBSCR_QOS_ROWIDS)
131 subscr.registerquery("select * from regions")
132 input("Hit enter to stop CQN demo\n")
133
134 Running the above script, shows the initial output as::
135
136 Hit enter to stop CQN demo
137
138 Use SQL*Plus or another tool to commit a change to the table:
139
140 .. code-block:: sql
141
142 insert into regions values(120, 'L');
143 commit;
144
145 When the commit is executed, a notification will be received by the callback
146 which should print something like the following::
147
148 Hit enter to stop CQN demo
149 Notification:
150 Table: HR.REGIONS
151 Operation: 2
152 INSERT of rowid: AAA7EsAAHAAAFS/AAA
153
154 See `GitHub Samples
155 <https://github.com/oracle/python-cx_Oracle/blob/master/samples/CQN.py>`__
156 for a runnable CQN example.
0 .. _exception:
1
2 ******************
3 Exception Handling
4 ******************
5
6 All exceptions raised by cx_Oracle are inherited from :attr:`cx_Oracle.Error`.
7 See :ref:`Exceptions <exceptions>` for more details on the various exceptions
8 defined by cx_Oracle. See the exception handling section in the
9 :ref:`API manual <exchandling>` for more details on the information available
10 when an exception is raised.
11
12 Applications can catch exceptions as needed. For example, when trying to add a
13 customer that already exists in the database, the following could could be used
14 to catch the exception:
15
16 .. code-block:: python
17
18 try:
19 cursor.execute("insert into customer values (101, 'Customer A')")
20 except cx_Oracle.IntegrityError:
21 print("Customer ID already exists")
22 else:
23 print("Customer added")
24
25
26 If information about the exception needs to be processed instead, the following
27 code can be used:
28
29 .. code-block:: python
30
31 try:
32 cursor.execute("insert into customer values (101, 'Customer A')")
33 except cx_Oracle.IntegrityError as e:
34 errorObj, = e.args
35 print("Customer ID already exists")
36 print("Error Code:", errorObj.code)
37 print("Error Message:", errorObj.message)
38 else:
39 print("Customer added")
0 .. _globalization:
1
2 ********************************
3 Character Sets and Globalization
4 ********************************
5
6 Data fetched from, and sent to, Oracle Database will be mapped between the
7 database character set and the "Oracle client" character set of the Oracle
8 Client libraries used by cx_Oracle. If data cannot be correctly mapped between
9 client and server character sets, then it may be corrupted or queries may fail
10 with :ref:`"codec can't decode byte" <codecerror>`.
11
12 cx_Oracle uses Oracle’s National Language Support (NLS) to assist in
13 globalizing applications. As well as character set support, there are many
14 other features that will be useful in applications. See the
15 `Database Globalization Support Guide
16 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=NLSPG>`__.
17
18
19 Setting the Client Character Set
20 ================================
21
22 In cx_Oracle 8 the default encoding used for all character data changed to
23 "UTF-8". This universal encoding is suitable for most applications. If you
24 have a special need, you can pass the ``encoding`` and ``nencoding`` parameters
25 to the :meth:`cx_Oracle.connect` and :meth:`cx_Oracle.SessionPool` methods to
26 specify different Oracle Client character sets. For example:
27
28 .. code-block:: python
29
30 import cx_Oracle
31 connection = cx_Oracle.connect(connectString, encoding="US-ASCII",
32 nencoding="UTF-8")
33
34 The ``encoding`` parameter affects character data such as VARCHAR2 and CLOB
35 columns. The ``nencoding`` parameter affects "National Character" data such as
36 NVARCHAR2 and NCLOB. If you are not using national character types, then you
37 can omit ``nencoding``. Both the ``encoding`` and ``nencoding`` parameters are
38 expected to be one of the `Python standard encodings
39 <https://docs.python.org/3/library/codecs.html#standard-encodings>`__ such as
40 ``UTF-8``. Do not accidentally use ``UTF8``, which Oracle uses to specify the
41 older Unicode 3.0 Universal character set, ``CESU-8``. Note that Oracle does
42 not recognize all of the encodings that Python recognizes. You can see which
43 encodings are usable in cx_Oracle by issuing this query:
44
45 .. code-block:: sql
46
47 select distinct utl_i18n.map_charset(value)
48 from v$nls_valid_values
49 where parameter = 'CHARACTERSET'
50 and utl_i18n.map_charset(value) is not null
51 order by 1
52
53 .. note::
54
55 From cx_Oracle 8, it is no longer possible to change the character set
56 using the ``NLS_LANG`` environment variable. The character set component
57 of that variable is ignored. The language and territory components of
58 ``NLS_LANG`` are still respected by the Oracle Client libraries.
59
60 Character Set Example
61 ---------------------
62
63 The script below tries to display data containing a Euro symbol from the
64 database.
65
66 .. code-block:: python
67
68 connection = cx_Oracle.connect(userName, password, "dbhost.example.com/orclpdb1",
69 encoding="US-ASCII")
70 cursor = connection.cursor()
71 for row in cursor.execute("select nvarchar2_column from nchar_test"):
72 print(row)
73
74 Because the '€' symbol is not supported by the ``US-ASCII`` character set, all
75 '€' characters are replaced by '¿' in the cx_Oracle output::
76
77 ('¿',)
78
79 When the ``encoding`` parameter is removed (or set to "UTF-8") during connection:
80
81 .. code-block:: python
82
83 connection = cx_Oracle.connect(userName, password, "dbhost.example.com/orclpdb1")
84
85 Then the output displays the Euro symbol as desired::
86
87 ('€',)
88
89 .. _findingcharset:
90
91 Finding the Database and Client Character Set
92 ---------------------------------------------
93
94 To find the database character set, execute the query:
95
96 .. code-block:: sql
97
98 SELECT value AS db_charset
99 FROM nls_database_parameters
100 WHERE parameter = 'NLS_CHARACTERSET';
101
102 To find the database 'national character set' used for NCHAR and related types,
103 execute the query:
104
105 .. code-block:: sql
106
107 SELECT value AS db_ncharset
108 FROM nls_database_parameters
109 WHERE parameter = 'NLS_NCHAR_CHARACTERSET';
110
111 To find the current "client" character set used by cx_Oracle, execute the
112 query:
113
114 .. code-block:: sql
115
116 SELECT DISTINCT client_charset AS client_charset
117 FROM v$session_connect_info
118 WHERE sid = SYS_CONTEXT('USERENV', 'SID');
119
120 If these character sets do not match, characters transferred over Oracle Net
121 will be mapped from one character set to another. This may impact performance
122 and may result in invalid data.
123
124 Setting the Oracle Client Locale
125 ================================
126
127 You can use the ``NLS_LANG`` environment variable to set the language and
128 territory used by the Oracle Client libraries. For example, on Linux you could
129 set::
130
131 export NLS_LANG=JAPANESE_JAPAN
132
133 The language ("JAPANESE" in this example) specifies conventions such as the
134 language used for Oracle Database messages, sorting, day names, and month
135 names. The territory ("JAPAN") specifies conventions such as the default date,
136 monetary, and numeric formats. If the language is not specified, then the value
137 defaults to AMERICAN. If the territory is not specified, then the value is
138 derived from the language value. See `Choosing a Locale with the NLS_LANG
139 Environment Variable
140 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-86A29834-AE29-4BA5-8A78-E19C168B690A>`__
141
142 If the ``NLS_LANG`` environment variable is set in the application with
143 ``os.environ['NLS_LANG']``, it must be set before any connection pool is
144 created, or before any standalone connections are created.
145
146 Other Oracle globalization variables, such as ``NLS_DATE_FORMAT`` can also be
147 set to change the behavior of cx_Oracle, see `Setting NLS Parameters
148 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
149 id=GUID-6475CA50-6476-4559-AD87-35D431276B20>`__.
0 .. _highavailability:
1
2 ********************************
3 High Availability with cx_Oracle
4 ********************************
5
6 Applications can utilize many features for high availability (HA) during planned and
7 unplanned outages in order to:
8
9 * Reduce application downtime
10 * Eliminate compromises between high availability and performance
11 * Increase operational productivity
12
13 .. _harecommend:
14
15 General HA Recommendations
16 --------------------------
17
18 General recommendations for creating highly available cx_Oracle programs are:
19
20 * Tune operating system and Oracle Network parameters to avoid long TCP timeouts, to prevent firewalls killing connections, and to avoid connection storms.
21 * Implement application error handling and recovery.
22 * Use the most recent version of the Oracle client libraries. New versions have improvements to features such as dead database server detection, and make it easier to set connection options.
23 * Use the most recent version of Oracle Database. New database versions introduce, and enhance, features such as Application Continuity (AC) and Transparent Application Continuity (TAC).
24 * Utilize Oracle Database technologies such as `RAC <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=RACAD>`__ or standby databases.
25 * Configure database services to emit :ref:`FAN <fan>` events.
26 * Use a :ref:`connection pool <connpool>`, because pools can handle database events and take proactive and corrective action for draining, run time load balancing, and fail over. Set the minimum and maximum pool sizes to the same values to avoid connection storms. Remove resource manager or user profiles that prematurely close sessions.
27 * Test all scenarios thoroughly.
28
29 .. _hanetwork:
30
31 Network Configuration
32 ---------------------
33
34 The operating system TCP and :ref:`Oracle Net configuration <optnetfiles>`
35 should be configured for performance and availability.
36
37 Options such as `SQLNET.OUTBOUND_CONNECT_TIMEOUT
38 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-0857C817-675F-4CF0-BFBB-C3667F119176>`__,
39 `SQLNET.RECV_TIMEOUT
40 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-4A19D81A-75F0-448E-B271-24E5187B5909>`__
41 and `SQLNET.SEND_TIMEOUT
42 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-48547756-9C0B-4D14-BE85-E7ADDD1A3A66>`__
43 can be explored.
44
45 `Oracle Net Services
46 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=NETRF>`__ options may
47 also be useful for high availability and performance tuning. For example the
48 database's `listener.ora` file can have `RATE_LIMIT
49 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-F302BF91-64F2-4CE8-A3C7-9FDB5BA6DCF8>`__
50 and `QUEUESIZE
51 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-FF87387C-1779-4CC3-932A-79BB01391C28>`__
52 parameters that can help handle connection storms.
53
54 With Oracle Client 19c, `EXPIRE_TIME
55 <https://docs.oracle.com/en/database/oracle/oracle-database/20/netrf/local-naming-parameters-in-tns-ora-file.html#GUID-6140611A-83FC-4C9C-B31F-A41FC2A5B12D>`__
56 can be used in :ref:`tnsnames.ora <optnetfiles>` connect descriptors to prevent
57 firewalls from terminating idle connections and to adjust keepalive timeouts.
58 The general recommendation for ``EXPIRE_TIME`` is to use a value that is
59 slightly less than half of the termination period. In older versions of Oracle
60 Client, a ``tnsnames.ora`` connect descriptor option `ENABLE=BROKEN
61 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-7A18022A-E40D-4880-B3CE-7EE9864756CA>`_
62 can be used instead of ``EXPIRE_TIME``. These settings can also aid detection
63 of a terminated remote database server.
64
65 When cx_Oracle uses :ref:`Oracle Client libraries 19c <archfig>`, then the
66 :ref:`Easy Connect Plus syntax <easyconnect>` syntax enables some options to be
67 used without needing a ``sqlnet.ora`` file. For example, if your firewall times
68 out every 4 minutes, and you cannot alter the firewall settings, then you may
69 decide to use ``EXPIRE_TIME`` in your connect string to send a probe every 2
70 minutes to the database to keep connections 'alive'::
71
72 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1?expire_time=2")
73
74 .. _fan:
75
76 Fast Application Notification (FAN)
77 -----------------------------------
78
79 Users of `Oracle Database FAN
80 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-F3FBE48B-468B-4393-8B0C-D5C8E0E4374D>`__
81 must connect to a FAN-enabled database service. The application should have
82 ``events`` set to True when connecting. This value can also be changed via
83 :ref:`Oracle Client Configuration <optclientfiles>`.
84
85 FAN support is useful for planned and unplanned outages. It provides immediate
86 notification to cx_Oracle following outages related to the database, computers,
87 and networks. Without FAN, cx_Oracle can hang until a TCP timeout occurs and an
88 error is returned, which might be several minutes.
89
90 FAN allows cx_Oracle to provide high availability features without the
91 application being aware of an outage. Unused, idle connections in a
92 :ref:`connection pool <connpool>` will be automatically cleaned up. A future
93 :meth:`SessionPool.acquire()` call will establish a fresh connection to a
94 surviving database instance without the application being aware of any service
95 disruption.
96
97 To handle errors that affect active connections, you can add application logic
98 to re-connect (this will connect to a surviving database instance) and replay
99 application logic without having to return an error to the application user.
100
101 FAN benefits users of Oracle Database's clustering technology `Oracle RAC
102 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-D04AA2A7-2E68-4C5C-BD6E-36C62427B98E>`__
103 because connections to surviving database instances can be immediately made.
104 Users of Oracle's Data Guard with a broker will get FAN events generated when
105 the standby database goes online. Standalone databases will send FAN events
106 when the database restarts.
107
108 For a more information on FAN see the `white paper on Fast Application
109 Notification
110 <http://www.oracle.com/technetwork/database/options/clustering/applicationcontinuity/learnmore/fastapplicationnotification12c-2538999.pdf>`__.
111
112 .. _appcont:
113
114 Application Continuity (AC)
115 ---------------------------
116
117 Oracle Application Continuity and Transparent Application Continuity are Oracle
118 Database technologies that record application interaction with the database and,
119 in the event of a database instance outage, attempt to replay the interaction on
120 a surviving database instance. If successful, users will be unaware of any
121 database issue. AC and TAC are best suited for OLTP applications.
122
123 When AC or TAC are configured on the database service, they are transparently
124 available to cx_Oracle applications.
125
126 You must thoroughly test your application because not all lower level calls in
127 the cx_Oracle implementation can be replayed.
128
129 See `OCI and Application Continuity
130 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-A8DD9422-2F82-42A9-9555-134296416E8F>`__
131 for more information.
132
133 .. _tg:
134
135 Transaction Guard
136 -----------------
137
138 cx_Oracle supports `Transaction Guard
139 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
140 id=GUID-A675AF7B-6FF0-460D-A6E6-C15E7C328C8F>`__ which enables Python
141 application to verify the success or failure of the last transaction in the
142 event of an unplanned outage. This feature is available when both client and
143 database are 12.1 or higher.
144
145 Using Transaction Guard helps to:
146
147 * Preserve the commit outcome
148 * Ensure a known outcome for every transaction
149
150 See `Oracle Database Development Guide
151 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
152 id=GUID-6C5880E5-C45F-4858-A069-A28BB25FD1DB>`__ for more information about
153 using Transaction Guard.
154
155 When an error occurs during commit, the Python application can acquire the
156 logical transaction id (``ltxid``) from the connection and then call a
157 procedure to determine the outcome of the commit for this logical transaction
158 id.
159
160 Follow the steps below to use the Transaction Guard feature in Python:
161
162 1. Grant execute privileges to the database users who will be checking the
163 outcome of the commit. Login as SYSDBA and run the following command:
164
165 .. code-block:: sql
166
167 GRANT EXECUTE ON DBMS_APP_CONT TO <username>;
168
169 2. Create a new service by executing the following PL/SQL block as SYSDBA.
170 Replace the ``<service-name>``, ``<network-name>`` and
171 ``<retention-value>`` values with suitable values. It is important that the
172 ``COMMIT_OUTCOME`` parameter be set to true for Transaction Guard to
173 function properly.
174
175 .. code-block:: sql
176
177 DECLARE
178 t_Params dbms_service.svc_parameter_array;
179 BEGIN
180 t_Params('COMMIT_OUTCOME') := 'true';
181 t_Params('RETENTION_TIMEOUT') := <retention-value>;
182 DBMS_SERVICE.CREATE_SERVICE('<service-name>', '<network-name>', t_Params);
183 END;
184 /
185
186 3. Start the service by executing the following PL/SQL block as SYSDBA:
187
188 .. code-block:: sql
189
190 BEGIN
191 DBMS_SERVICE.start_service('<service-name>');
192 END;
193 /
194
195 Ensure the service is running by examining the output of the following query:
196
197 .. code-block:: sql
198
199 SELECT name, network_name FROM V$ACTIVE_SERVICES ORDER BY 1;
200
201
202 **Python Application code requirements to use Transaction Guard**
203
204 In the Python application code:
205
206 * Use the connection attribute :attr:`~Connection.ltxid` to determine the
207 logical transaction id.
208 * Call the ``DBMS_APP_CONT.GET_LTXID_OUTCOME`` PL/SQL procedure with the
209 logical transaction id acquired from the connection attribute. This returns
210 a boolean value indicating if the last transaction was committed and whether
211 the last call was completed successfully or not.
212
213 See the `Transaction Guard Sample
214 <https://github.com/oracle/python-cx_Oracle/blob/master/
215 samples/TransactionGuard.py>`__ for further details.
0 .. _initialization:
1
2 **************************
3 cx_Oracle 8 Initialization
4 **************************
5
6 The cx_Oracle module loads Oracle Client libraries which communicate over
7 Oracle Net to an existing database. The Oracle Client libraries need to be
8 installed separately. See :ref:`installation`. Oracle Net is not a separate
9 product: it is how the Oracle Client and Oracle Database communicate.
10
11 .. figure:: /images/cx_Oracle_arch.png
12
13 cx_Oracle Architecture
14
15 .. _libinit:
16
17 Locating the Oracle Client Libraries
18 ====================================
19
20 cx_Oracle dynamically loads the Oracle Client libraries using a search
21 heuristic. Only the first set of libraries found are loaded. The libraries
22 can be in an installation of Oracle Instant Client, in a full Oracle Client
23 installation, or in an Oracle Database installation (if Python is running on
24 the same machine as the database). The versions of Oracle Client and Oracle
25 Database do not have to be the same. For certified configurations see Oracle
26 Support's `Doc ID 207303.1
27 <https://support.oracle.com/epmos/faces/DocumentDisplay?id=207303.1>`__.
28
29 cx_Oracle looks for the Oracle Client libraries as follows:
30
31 * On Windows:
32
33 - In the ``lib_dir`` directory specified in a call to
34 :meth:`cx_Oracle.init_oracle_client()`. This directory should contain
35 the libraries from an unzipped Instant Client 'Basic' or 'Basic Light'
36 package. If you pass the library directory from a full client or
37 database installation, such as Oracle Database "XE" Express Edition, then
38 you will need to have previously set your environment to use that
39 software installation, otherwise files such as message files will not be
40 located. On Windows when the path contains backslashes, use a 'raw'
41 string like ``lib_dir = r"C:\instantclient_19_6"``. If the Oracle Client
42 libraries cannot be loaded from ``lib_dir``, then an exception is raised.
43
44 - If ``lib_dir`` was not specified, then Oracle Client libraries are looked
45 for in the directory where the cx_Oracle binary module is installed.
46 This directory should contain the libraries from an unzipped Instant
47 Client 'Basic' or 'Basic Light' package. If the libraries are not found,
48 no exception is raised and the search continues, see next bullet point.
49
50 - In the directories on the system library search path, e.g. the ``PATH``
51 environment variable. If the Oracle Client libraries cannot be loaded,
52 then an exception is raised.
53
54 * On macOS:
55
56 - In the ``lib_dir`` directory specified in a call to
57 :meth:`cx_Oracle.init_oracle_client()`. This directory should contain
58 the libraries from an unzipped Instant Client 'Basic' or 'Basic Light'
59 package. If the Oracle Client libraries cannot be loaded from
60 ``lib_dir``, then an exception is raised.
61
62 - If ``lib_dir`` was not specified, then Oracle Client libraries are looked
63 for in the directory where the cx_Oracle binary module is. This directory
64 should contain the libraries from an unzipped Instant Client 'Basic' or
65 'Basic Light' package. For example if
66 ``/Users/your_username/Library/Python/3.8/lib/python/site-packages``
67 contains ``cx_Oracle.cpython-38-darwin.so``, then you could run ``ln -s
68 ~/instantclient_19_3/libclntsh.dylib
69 ~/Library/Python/3.8/lib/python/site-packages``. If the libraries are not
70 found, no exception is raised and the search continues, see next bullet
71 point.
72
73 - In the directories on the system library search path, e.g. ``~/lib/`` and
74 ``/usr/local/lib``, or in ``$DYLD_LIBRARY_PATH``. These paths will vary
75 with macOS version and Python version. Any value in
76 ``DYLD_LIBRARY_PATH`` will not propagate to a sub-shell. If the Oracle
77 Client libraries cannot be loaded, then an exception is raised.
78
79 * On Linux and related platforms:
80
81 - In the ``lib_dir`` directory specified in a call to
82 :meth:`cx_Oracle.init_oracle_client()`. Note on Linux this is only
83 useful to force immediate loading of the libraries because the libraries
84 must also be in the system library search path. This directory should
85 contain the libraries from an unzipped Instant Client 'Basic' or 'Basic
86 Light' package. If you pass the library directory from a full client or
87 database installation, such as Oracle Database "XE" Express Edition then
88 you will need to have previously set the ``ORACLE_HOME`` environment
89 variable. If the Oracle Client libraries cannot be loaded from
90 ``lib_dir``, then an exception is raised.
91
92 - If ``lib_dir`` was not specified, then Oracle Client libraries are looked
93 for in the operating system library search path, such as configured with
94 ``ldconfig`` or set in the environment variable ``LD_LIBRARY_PATH``. On
95 some UNIX platforms an OS specific equivalent, such as ``LIBPATH`` or
96 ``SHLIB_PATH`` is used instead of ``LD_LIBRARY_PATH``. If the libraries
97 are not found, no exception is raised and the search continues, see next
98 bullet point.
99
100 - In ``$ORACLE_HOME/lib``. Note the environment variable ``ORACLE_HOME``
101 should only ever be set when you have a full database installation or
102 full client installation. It should not be set if you are using Oracle
103 Instant Client. The ``ORACLE_HOME`` variable, and other necessary
104 variables, should be set before starting Python. See :ref:`envset`. If
105 the Oracle Client libraries cannot be loaded, then an exception is
106 raised.
107
108 If you call :meth:`cx_Oracle.init_oracle_client()` with a ``lib_dir``
109 parameter, the Oracle Client libraries are loaded immediately from that
110 directory. If you call :meth:`cx_Oracle.init_oracle_client()` but do *not* set
111 the ``lib_dir`` parameter, the Oracle Client libraries are loaded immediately
112 using the search heuristic above. If you do not call
113 :meth:`cx_Oracle.init_oracle_client()`, then the libraries are loaded using the
114 search heuristic when the first cx_Oracle function that depends on the
115 libraries is called, for example when a connection pool is created. If there
116 is a problem loading the libraries, then an exception is raised.
117
118 Make sure the Python process has directory and file access permissions for the
119 Oracle Client libraries. On Linux ensure a ``libclntsh.so`` file exists. On
120 macOS ensure a ``libclntsh.dylib`` file exists. cx_Oracle will not directly
121 load ``libclntsh.*.XX.1`` files in ``lib_dir`` or from the directory where the
122 cx_Oracle binary module is. Note other libraries used by ``libclntsh*`` are
123 also required.
124
125 To trace the loading of Oracle Client libraries, the environment variable
126 ``DPI_DEBUG_LEVEL`` can be set to 64 before starting Python. For example, on
127 Linux, you might use::
128
129 $ export DPI_DEBUG_LEVEL=64
130 $ python myapp.py 2> log.txt
131
132
133 Using cx_Oracle.init_oracle_client() to set the Oracle Client directory
134 -----------------------------------------------------------------------
135
136 Applications can call the function :meth:`cx_Oracle.init_oracle_client()` to
137 specify the directory containing Oracle Instant Client libraries. The Oracle
138 Client Libraries are loaded when ``init_oracle_client()`` is called. For
139 example, if the Oracle Instant Client Libraries are in
140 ``C:\oracle\instantclient_19_6`` on Windows, then you can use:
141
142 .. code-block:: python
143
144 import cx_Oracle
145 import sys
146
147 try:
148 cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_6")
149 except Exception as err:
150 print("Whoops!")
151 print(err);
152 sys.exit(1);
153
154 The :meth:`~cx_Oracle.init_oracle_client()` function should only be called
155 once.
156
157 If you set ``lib_dir`` on Linux and related platforms, you must still have
158 configured the system library search path to include that directory before
159 starting Python.
160
161 On any operating system, if you set ``lib_dir`` to the library directory of a
162 full database or full client installation, you will need to have previously set
163 the Oracle environment, for example by setting the ``ORACLE_HOME`` environment
164 variable. Otherwise you will get errors like ORA-1804. You should set this,
165 and other Oracle environment variables, before starting Python, as
166 shown in :ref:`envset`.
167
168 .. _optnetfiles:
169
170 Optional Oracle Net Configuration Files
171 =======================================
172
173 Optional Oracle Net configuration files are read when cx_Oracle is loaded.
174 These files affect connections and applications. The common files are:
175
176 * ``tnsnames.ora``: A configuration file that defines databases addresses
177 for establishing connections. See :ref:`Net Service Name for Connection
178 Strings <netservice>`.
179
180 * ``sqlnet.ora``: A profile configuration file that may contain information
181 on features such as connection failover, network encryption, logging, and
182 tracing. See `Oracle Net Services Reference
183 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
184 id=GUID-19423B71-3F6C-430F-84CC-18145CC2A818>`__ for more information.
185
186 The files should be in a directory accessible to Python, not on the database
187 server host.
188
189 For example, if the file ``/etc/my-oracle-config/tnsnames.ora`` should be used,
190 you can call :meth:`cx_Oracle.init_oracle_client()`:
191
192 .. code-block:: python
193
194 import cx_Oracle
195 import sys
196
197 try:
198 cx_Oracle.init_oracle_client(config_dir="/etc/my-oracle-config")
199 except Exception as err:
200 print("Whoops!")
201 print(err);
202 sys.exit(1);
203
204 This is equivalent to setting the environment variable `TNS_ADMIN
205 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-12C94B15-2CE1-4B98-9D0C-8226A9DDF4CB>`__
206 to ``/etc/my-oracle-config``.
207
208 If :meth:`~cx_Oracle.init_oracle_client()` is not called, or it is called but
209 ``config_dir`` is not specified, then default directories searched for the
210 configuration files. They include:
211
212 * ``$TNS_ADMIN``
213 * ``/opt/oracle/instantclient_19_6/network/admin`` if Instant Client is in ``/opt/oracle/instantclient_19_6``.
214 * ``/usr/lib/oracle/19.6/client64/lib/network/admin`` if Oracle 19.6 Instant Client RPMs are used on Linux.
215 * ``$ORACLE_HOME/network/admin`` if cx_Oracle is using libraries from a database installation.
216
217 A wallet configuration file ``cwallet.sso`` for secure connection can be
218 located with, or separately from, the ``tnsnames.ora`` and ``sqlnet.ora``
219 files. It should be securely stored. The ``sqlnet.ora`` file's
220 ``WALLET_LOCATION`` path should be set to the directory containing
221 ``cwallet.sso``. For Oracle Autonomous Database use of wallets, see
222 :ref:`autononmousdb`.
223
224 Note the :ref:`easyconnect` can set many common configuration options without
225 needing ``tnsnames.ora`` or ``sqlnet.ora`` files.
226
227 The section :ref:`Network Configuration <hanetwork>` has some discussion about
228 Oracle Net configuration.
229
230 .. _optclientfiles:
231
232 Optional Oracle Client Configuration Files
233 ==========================================
234
235 When cx_Oracle uses Oracle Client libraries version 12.1, or later, an optional
236 client parameter file called ``oraaccess.xml`` can be used to configure some
237 behviors of those libraries, such as statement caching and prefetching. This can
238 be useful if the application cannot be altered. The file is read from the same
239 directory as the `Optional Oracle Net Configuration Files`_.
240
241 A sample ``oraaccess.xml`` file that sets the Oracle client ‘prefetch’ value to
242 1000 rows. This value affects every SQL query in the application::
243
244 <?xml version="1.0"?>
245 <oraaccess xmlns="http://xmlns.oracle.com/oci/oraaccess"
246 xmlns:oci="http://xmlns.oracle.com/oci/oraaccess"
247 schemaLocation="http://xmlns.oracle.com/oci/oraaccess
248 http://xmlns.oracle.com/oci/oraaccess.xsd">
249 <default_parameters>
250 <prefetch>
251 <rows>1000</rows>
252 </prefetch>
253 </default_parameters>
254 </oraaccess>
255
256 Prefetching is the number of additional rows the underlying Oracle client
257 library fetches whenever cx_Oracle requests query data from the database.
258 Prefetching is a tuning option to maximize data transfer efficiency and minimize
259 :ref:`round-trips <roundtrips>` to the database. The prefetch size does not
260 affect when, or how many, rows are returned by cx_Oracle to the application.
261 The cache management is transparently handled by the Oracle client libraries.
262 Note, standard cx_Oracle fetch tuning is via :attr:`Cursor.arraysize`, but
263 changing the prefetch value can be useful in some cases such as when modifying
264 the application is not feasible.
265
266 The `oraaccess.xml` file has other uses including:
267
268 - Changing the value of Fast Application Notification :ref:`FAN <fan>` events which affects notifications and Runtime Load Balancing (RLB).
269 - Configuring `Client Result Caching <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-D2FA7B29-301B-4AB8-8294-2B1B015899F9>`__ parameters
270 - Turning on `Client Statement Cache Auto-tuning <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-6E21AA56-5BBE-422A-802C-197CAC8AAEA4>`__
271
272 Refer to the documentation on `oraaccess.xml
273 <https://www.oracle.com/pls/topic/lookup?
274 ctx=dblatest&id=GUID-9D12F489-EC02-46BE-8CD4-5AECED0E2BA2>`__
275 for more details.
276
277 .. _envset:
278
279 Oracle Environment Variables
280 ============================
281
282 Some common environment variables that influence cx_Oracle are shown below. The
283 variables that may be needed depend on how Python is installed, how you connect
284 to the database, and what optional settings are desired. It is recommended to
285 set Oracle variables in the environment before invoking Python, however they may
286 also be set in the application with ``os.putenv()`` before the first connection
287 is established. System environment variables like ``LD_LIBRARY_PATH`` must be
288 set before Python starts.
289
290 .. list-table:: Common Oracle environment variables
291 :header-rows: 1
292 :widths: 1 2
293 :align: left
294
295 * - Oracle Environment Variables
296 - Purpose
297 * - LD_LIBRARY_PATH
298 - The library search path for platforms like Linux should include the
299 Oracle libraries, for example ``$ORACLE_HOME/lib`` or
300 ``/opt/instantclient_19_3``. This variable is not needed if the
301 libraries are located by an alternative method, such as with
302 ``ldconfig``. On other UNIX platforms you may need to set an OS
303 specific equivalent, such as ``LIBPATH`` or ``SHLIB_PATH``.
304 * - PATH
305 - The library search path for Windows should include the location where
306 ``OCI.DLL`` is found. Not needed if you set ``lib_dir`` in a call to
307 :meth:`cx_Oracle.init_oracle_client()`
308 * - TNS_ADMIN
309 - The directory of optional Oracle Client configuration files such as
310 ``tnsnames.ora`` and ``sqlnet.ora``. Not needed if the configuration
311 files are in a default location or if ``config_dir`` was not used in
312 :meth:`cx_Oracle.init_oracle_client()`. See :ref:`optnetfiles`.
313 * - ORA_SDTZ
314 - The default session time zone.
315 * - ORA_TZFILE
316 - The name of the Oracle time zone file to use. See below.
317 * - ORACLE_HOME
318 - The directory containing the Oracle Database software. The directory
319 and various configuration files must be readable by the Python process.
320 This variable should not be set if you are using Oracle Instant Client.
321 * - NLS_LANG
322 - Determines the 'national language support' globalization options for
323 cx_Oracle. Note: from cx_Oracle 8, the character set component is
324 ignored and only the language and territory components of ``NLS_LANG``
325 are used. The character set can instead be specified during connection
326 or connection pool creation. See :ref:`globalization`.
327 * - NLS_DATE_FORMAT, NLS_TIMESTAMP_FORMAT
328 - Often set in Python applications to force a consistent date format
329 independent of the locale. The variables are ignored if the environment
330 variable ``NLS_LANG`` is not set.
331
332 Oracle Instant Client includes a small and big time zone file, for example
333 ``timezone_32.dat`` and ``timezlrg_32.dat``. The versions can be shown by running
334 the utility ``genezi -v`` located in the Instant Client directory. The small file
335 contains only the most commonly used time zones. By default the larger
336 ``timezlrg_n.dat`` file is used. If you want to use the smaller ``timezone_n.dat``
337 file, then set the ``ORA_TZFILE`` environment variable to the name of the file
338 without any directory prefix, for example ``export ORA_TZFILE=timezone_32.dat``.
339 With Oracle Instant Client 12.2 or later, you can also use an external time zone
340 file. Create a subdirectory ``oracore/zoneinfo`` under the Instant Client
341 directory, and move the file into it. Then set ``ORA_TZFILE`` to the file name,
342 without any directory prefix. The ``genezi -v`` utility will show the time zone
343 file in use.
344
345 If cx_Oracle is using Oracle Client libraries from an Oracle Database or full
346 Oracle Client software installation, and you want to use a non-default time zone
347 file, then set ``ORA_TZFILE`` to the file name with a directory prefix, for
348 example: ``export ORA_TZFILE=/opt/oracle/myconfig/timezone_31.dat``.
349
350 The Oracle Database documentation contains more information about time zone
351 files, see `Choosing a Time Zone File
352 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-805AB986-DE12-4FEA-AF56-5AABCD2132DF>`__.
353
354 .. _otherinit:
355
356 Other cx_Oracle Initialization
357 ==============================
358
359 The :meth:`cx_Oracle.init_oracle_client()` function allows ``driver_name`` and
360 ``error_url`` parameters to be set. These are useful for applications whose
361 end-users are not aware cx_Oracle is being used. An example of setting the
362 parameters is:
363
364 .. code-block:: python
365
366 import cx_Oracle
367 import sys
368
369 try:
370 cx_Oracle.init_oracle_client(driver_name = "My Great App : 3.1.4",
371 error_url: "https://example.com/MyInstallInstructions.html")
372 except Exception as err:
373 print("Whoops!")
374 print(err);
375 sys.exit(1);
376
377 The convention for ``driver_name`` is to separate the product name from the
378 product version by a colon and single blank characters. The value will be shown
379 in Oracle Database views like ``V$SESSION_CONNECT_INFO``. If this parameter is
380 not specified, then the value "cx_Oracle : *version*" is used.
381
382 The ``error_url`` string will be shown in the exception raised if
383 ``init_oracle_client()`` cannot load the Oracle Client libraries. This allows
384 applications that use node-oracledb to refer users to application-specific
385 installation instructions. If this value is not specified, then the
386 :ref:`installation` URL is used.
0 .. _installation:
1
2 ************************
3 cx_Oracle 8 Installation
4 ************************
5
6 Overview
7 ========
8
9 To use cx_Oracle 8 with Python and Oracle Database you need:
10
11 - Python 3.5 and higher. Older versions of cx_Oracle may work with older
12 versions of Python, for example see :ref:`Installing cx_Oracle in Python 2
13 <python2>`
14
15 - Oracle Client libraries. These can be from the free `Oracle Instant
16 Client
17 <https://www.oracle.com/database/technologies/instant-client.html>`__,
18 or those included in Oracle Database if Python is on the same
19 machine as the database. Oracle client libraries versions 19, 18, 12,
20 and 11.2 are supported on Linux, Windows and macOS. Users have
21 also reported success with other platforms. Use the latest client possible:
22 Oracle's standard client-server version interoperability allows connection to
23 both older and newer databases.
24
25 - An Oracle Database, either local or remote.
26
27 The cx_Oracle module loads Oracle Client libraries which communicate
28 over Oracle Net to an existing database. Oracle Net is not a separate
29 product: it is how the Oracle Client and Oracle Database communicate.
30
31 .. figure:: /images/cx_Oracle_arch.png
32
33 cx_Oracle Architecture
34
35
36 Quick Start cx_Oracle Installation
37 ==================================
38
39 - Install `Python <https://www.python.org/downloads>`__ 3, if not already
40 available. On macOS you must always install your own Python.
41
42 Python 3.5 and higher are supported by cx_Oracle 8. For Python 2, see
43 :ref:`Installing cx_Oracle in Python 2 <python2>`.
44
45 - Install cx_Oracle from `PyPI
46 <https://pypi.org/project/cx-Oracle/>`__ with:
47
48 .. code-block:: shell
49
50 python -m pip install cx_Oracle --upgrade
51
52 Note: if a binary wheel package is not available for your platform,
53 the source package will be downloaded instead. This will be compiled
54 and the resulting binary installed.
55
56 The ``--user`` option may be useful, if you don't have permission to write to
57 system directories:
58
59 .. code-block:: shell
60
61 python -m pip install cx_Oracle --upgrade --user
62
63 If you are behind a proxy, add a proxy server to the command, for example add
64 ``--proxy=http://proxy.example.com:80``
65
66 - Add Oracle 19, 18, 12 or 11.2 client libraries to your operating system
67 library search path such as ``PATH`` on Windows or ``LD_LIBRARY_PATH`` on
68 Linux. On macOS use :meth:`~cx_Oracle.init_oracle_client()` in your
69 application to pass the Oracle Client directory name, see :ref:`libinit`.
70 This is also usable on Windows.
71
72 To get the libraries:
73
74 - If your database is on a remote computer, then download and unzip the client
75 libraries from the free `Oracle Instant Client
76 <https://www.oracle.com/database/technologies/instant-client.html>`__
77 "Basic" or "Basic Light" package for your operating system
78 architecture.
79
80 Instant Client on Windows requires an appropriate Microsoft Windows
81 Redistributables, see :ref:`wininstall`. On Linux, the ``libaio``
82 (sometimes called ``libaio1``) package is needed. Oracle Linux 8 also
83 needs the ``libnsl`` package.
84
85 - Alternatively, use the client libraries already available in a
86 locally installed database such as the free `Oracle Database
87 Express Edition ("XE")
88 <https://www.oracle.com/database/technologies/appdev/xe.html>`__
89 release.
90
91 Version 19, 18 and 12.2 client libraries can connect to Oracle Database 11.2
92 or greater. Version 12.1 client libraries can connect to Oracle Database 10.2
93 or greater. Version 11.2 client libraries can connect to Oracle Database 9.2
94 or greater.
95
96 - Create a script like the one below:
97
98 .. code-block:: python
99
100 # myscript.py
101
102 import cx_Oracle
103
104 # Connect as user "hr" with password "welcome" to the "orclpdb1" service running on this computer.
105 connection = cx_Oracle.connect("hr", "welcome", "localhost/orclpdb1")
106
107 cursor = connection.cursor()
108 cursor.execute("""
109 SELECT first_name, last_name
110 FROM employees
111 WHERE department_id = :did AND employee_id > :eid""",
112 did = 50,
113 eid = 190)
114 for fname, lname in cursor:
115 print("Values:", fname, lname)
116
117 Locate your Oracle Database username and password, and the database
118 connection string. The connection string is commonly of the format
119 ``hostname/servicename``, using the hostname where the database is
120 running, and using the service name of the Oracle Database instance.
121
122 Substitute your username, password and connection string in the
123 code. Run the Python script, for example::
124
125 python myscript.py
126
127 You can learn how to use cx_Oracle from the :ref:`API documentation <module>`
128 and `samples
129 <https://github.com/oracle/python-cx_Oracle/blob/master/samples>`__.
130
131 If you run into installation trouble, check out the section on `Troubleshooting`_.
132
133
134 Oracle Client and Oracle Database Interoperability
135 ==================================================
136
137 cx_Oracle requires Oracle Client libraries. The libraries provide the
138 necessary network connectivity to access an Oracle Database instance.
139 They also provide basic and advanced connection management and data
140 features to cx_Oracle.
141
142 The simplest way to get Oracle Client libraries is to install the free
143 `Oracle Instant Client
144 <https://www.oracle.com/database/technologies/instant-client.html>`__
145 "Basic" or "Basic Light" package. The libraries are also available in
146 any Oracle Database installation or full Oracle Client installation.
147
148 Oracle's standard client-server network interoperability allows
149 connections between different versions of Oracle Client libraries and
150 Oracle Database. For certified configurations see Oracle Support's
151 `Doc ID 207303.1
152 <https://support.oracle.com/epmos/faces/DocumentDisplay?id=207303.1>`__.
153 In summary, Oracle Client 19, 18 and 12.2 can connect to Oracle Database 11.2 or
154 greater. Oracle Client 12.1 can connect to Oracle Database 10.2 or
155 greater. Oracle Client 11.2 can connect to Oracle Database 9.2 or
156 greater. The technical restrictions on creating connections may be
157 more flexible. For example Oracle Client 12.2 can successfully
158 connect to Oracle Database 10.2.
159
160 cx_Oracle uses the shared library loading mechanism available on each
161 supported platform to load the Oracle Client libraries at runtime. It
162 does not need to be rebuilt for different versions of the libraries.
163 Since a single cx_Oracle binary can use different client versions and
164 also access multiple database versions, it is important your
165 application is tested in your intended release environments. Newer
166 Oracle clients support new features, such as the `oraaccess.xml
167 <http://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-9D12F489-EC02-46BE-8CD4-5AECED0E2BA2>`__ external configuration
168 file available with 12.1 or later clients, session pool improvements,
169 improved high availability features, call timeouts, and `other enhancements
170 <http://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-D60519C3-406F-4588-8DA1-D475D5A3E1F6>`__.
171
172 The cx_Oracle function :func:`~cx_Oracle.clientversion()` can be used
173 to determine which Oracle Client version is in use and the attribute
174 :attr:`Connection.version` can be used to determine which Oracle
175 Database version a connection is accessing. These can then be used to
176 adjust application behavior accordingly. Attempts to use some Oracle
177 features that are not supported by a particular client/server
178 combination may result in runtime errors. These include:
179
180 - when attempting to access attributes that are not supported by the
181 current Oracle Client library you will get the error "ORA-24315: illegal
182 attribute type"
183
184 - when attempting to use implicit results with Oracle Client 11.2
185 against Oracle Database 12c you will get the error "ORA-29481:
186 Implicit results cannot be returned to client"
187
188 - when attempting to get array DML row counts with Oracle Client
189 11.2 you will get the error "DPI-1050: Oracle Client library must be at
190 version 12.1 or higher"
191
192
193 Installing cx_Oracle on Linux
194 =============================
195
196 This section discusses the generic installation methods on Linux. To use Python
197 and cx_Oracle RPM packages from yum on Oracle Linux, see :ref:`oraclelinux`.
198
199 Install cx_Oracle
200 -----------------
201
202 The generic way to install cx_Oracle on Linux is to use Python's `Pip
203 <http://pip.readthedocs.io/en/latest/installing/>`__ package to
204 install cx_Oracle from `PyPI
205 <https://pypi.org/project/cx-Oracle/>`__:
206
207 .. code-block:: shell
208
209 python -m pip install cx_Oracle --upgrade
210
211 The ``--user`` option may be useful, if you don't have permission to write to
212 system directories:
213
214 .. code-block:: shell
215
216 python -m pip install cx_Oracle --upgrade --user
217
218 If you are behind a proxy, add a proxy server to the command, for example add
219 ``--proxy=http://proxy.example.com:80``
220
221 This will download and install a pre-compiled binary `if one is
222 available <https://pypi.org/project/cx-Oracle/>`__ for your
223 architecture. If a pre-compiled binary is not available, the source
224 will be downloaded, compiled, and the resulting binary installed.
225 Compiling cx_Oracle requires the ``Python.h`` header file. If you are
226 using the default ``python`` package, this file is in the ``python-devel``
227 package or equivalent.
228
229 Install Oracle Client
230 ---------------------
231
232 Using cx_Oracle requires Oracle Client libraries to be installed.
233 These provide the necessary network connectivity allowing cx_Oracle
234 to access an Oracle Database instance.
235
236 - If your database is on a remote computer, then download the free `Oracle
237 Instant Client
238 <https://www.oracle.com/database/technologies/instant-client.html>`__
239 "Basic" or "Basic Light" package for your operating system
240 architecture. Use the RPM or ZIP packages, based on your
241 preferences.
242
243 - Alternatively, use the client libraries already available in a
244 locally installed database such as the free `Oracle Database
245 Express Edition ("XE")
246 <https://www.oracle.com/database/technologies/appdev/xe.html>`__
247 release.
248
249 Oracle Instant Client Zip Files
250 +++++++++++++++++++++++++++++++
251
252 To use cx_Oracle with Oracle Instant Client zip files:
253
254 1. Download an Oracle 19, 18, 12, or 11.2 "Basic" or "Basic Light" zip file: `64-bit
255 <https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html>`__
256 or `32-bit
257 <https://www.oracle.com/database/technologies/instant-client/linux-x86-32-downloads.html>`__, matching your
258 Python architecture.
259
260 The latest version is recommended. Oracle Instant Client 19 will
261 connect to Oracle Database 11.2 or later.
262
263 2. Unzip the package into a single directory that is accessible to your
264 application. For example:
265
266 .. code-block:: shell
267
268 mkdir -p /opt/oracle
269 cd /opt/oracle
270 unzip instantclient-basic-linux.x64-19.6.0.0.0dbru.zip
271
272 3. Install the ``libaio`` package with sudo or as the root user. For example::
273
274 sudo yum install libaio
275
276 On some Linux distributions this package is called ``libaio1`` instead.
277
278 On recent Linux versions, such as Oracle Linux 8, you may also need to
279 install the ``libnsl`` package.
280
281 4. If there is no other Oracle software on the machine that will be
282 impacted, permanently add Instant Client to the runtime link
283 path. For example, with sudo or as the root user:
284
285 .. code-block:: shell
286
287 sudo sh -c "echo /opt/oracle/instantclient_19_6 > /etc/ld.so.conf.d/oracle-instantclient.conf"
288 sudo ldconfig
289
290 Alternatively, set the environment variable ``LD_LIBRARY_PATH`` to
291 the appropriate directory for the Instant Client version. For
292 example::
293
294 export LD_LIBRARY_PATH=/opt/oracle/instantclient_19_6:$LD_LIBRARY_PATH
295
296 5. If you use optional Oracle configuration files such as ``tnsnames.ora``,
297 ``sqlnet.ora`` or ``oraaccess.xml`` with Instant Client, then put the files
298 in an accessible directory, for example in
299 ``/opt/oracle/your_config_dir``. Then use:
300
301 .. code-block:: python
302
303 import cx_Oracle
304 cx_Oracle.init_oracle_client(config_dir="/home/your_username/oracle/your_config_dir")
305
306 Or set the environment variable ``TNS_ADMIN`` to that directory name.
307
308 Alternatively, put the files in the ``network/admin`` subdirectory of Instant
309 Client, for example in ``/opt/oracle/instantclient_19_6/network/admin``.
310 This is the default Oracle configuration directory for executables linked
311 with this Instant Client.
312
313 Oracle Instant Client RPMs
314 ++++++++++++++++++++++++++
315
316 To use cx_Oracle with Oracle Instant Client RPMs:
317
318 1. Download an Oracle 19, 18, 12, or 11.2 "Basic" or "Basic Light" RPM: `64-bit
319 <https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html>`__
320 or `32-bit
321 <https://www.oracle.com/database/technologies/instant-client/linux-x86-32-downloads.html>`__, matching your
322 Python architecture.
323
324 Oracle's yum server has `Instant Client RPMs for Oracle Linux 7
325 <http://yum.oracle.com/repo/OracleLinux/OL7/oracle/instantclient/x86_64/index.html>`__
326 and `Instant Client RPMs for Oracle Linux 6
327 <http://yum.oracle.com/repo/OracleLinux/OL6/oracle/instantclient/x86_64/index.html>`__
328 that can be downloaded without needing a click-through.
329
330 The latest version is recommended. Oracle Instant Client 19 will
331 connect to Oracle Database 11.2 or later.
332
333 2. Install the downloaded RPM with sudo or as the root user. For example:
334
335 .. code-block:: shell
336
337 sudo yum install oracle-instantclient19.6-basic-19.6.0.0.0-1.x86_64.rpm
338
339 Yum will automatically install required dependencies, such as ``libaio``.
340
341 On recent Linux versions, such as Oracle Linux 8, you may need to manually
342 install the ``libnsl`` package.
343
344 3. For Instant Client 19, the system library search path is
345 automatically configured during installation.
346
347 For older versions, if there is no other Oracle software on the machine that will be
348 impacted, permanently add Instant Client to the runtime link
349 path. For example, with sudo or as the root user:
350
351 .. code-block:: shell
352
353 sudo sh -c "echo /usr/lib/oracle/18.3/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf"
354 sudo ldconfig
355
356 Alternatively, for version 18 and earlier, every shell running
357 Python will need to have the environment variable
358 ``LD_LIBRARY_PATH`` set to the appropriate directory for the
359 Instant Client version. For example::
360
361 export LD_LIBRARY_PATH=/usr/lib/oracle/18.3/client64/lib:$LD_LIBRARY_PATH
362
363 4. If you use optional Oracle configuration files such as ``tnsnames.ora``,
364 ``sqlnet.ora`` or ``oraaccess.xml`` with Instant Client, then put the files
365 in an accessible directory, for example in
366 ``/opt/oracle/your_config_dir``. Then use:
367
368 .. code-block:: python
369
370 import cx_Oracle
371 cx_Oracle.init_oracle_client(config_dir="/opt/oracle/your_config_dir")
372
373 Or set the environment variable ``TNS_ADMIN`` to that directory name.
374
375 Alternatively, put the files in the ``network/admin`` subdirectory of Instant
376 Client, for example in ``/usr/lib/oracle/19.6/client64/lib/network/admin``.
377 This is the default Oracle configuration directory for executables linked
378 with this Instant Client.
379
380 Local Database or Full Oracle Client
381 ++++++++++++++++++++++++++++++++++++
382
383 cx_Oracle applications can use Oracle Client 19, 18, 12, or 11.2 libraries
384 from a local Oracle Database or full Oracle Client installation.
385
386 The libraries must be either 32-bit or 64-bit, matching your
387 Python architecture.
388
389 1. Set required Oracle environment variables by running the Oracle environment
390 script. For example:
391
392 .. code-block:: shell
393
394 source /usr/local/bin/oraenv
395
396 For Oracle Database Express Edition ("XE") 11.2, run:
397
398 .. code-block:: shell
399
400 source /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh
401
402 2. Optional Oracle configuration files such as ``tnsnames.ora``,
403 ``sqlnet.ora`` or ``oraaccess.xml`` can be placed in
404 ``$ORACLE_HOME/network/admin``.
405
406 Alternatively, Oracle configuration files can be put in another,
407 accessible directory. Then set the environment variable
408 ``TNS_ADMIN`` to that directory name.
409
410
411 .. _oraclelinux:
412
413 Installing cx_Oracle RPMs on Oracle Linux
414 =========================================
415
416 Python and cx_Oracle RPM packages are available from the `Oracle Linux yum server
417 <http://yum.oracle.com/>`__. Various versions of Python are easily installed.
418 Using the yum server makes it easy to keep up to date.
419
420 Installation instructions are at `Oracle Linux for Python
421 Developers <https://yum.oracle.com/oracle-linux-python.html>`__.
422
423 .. _wininstall:
424
425 Installing cx_Oracle on Windows
426 ===============================
427
428 Install cx_Oracle
429 -----------------
430
431 Use Python's `Pip <http://pip.readthedocs.io/en/latest/installing/>`__
432 package to install cx_Oracle from `PyPI
433 <https://pypi.org/project/cx-Oracle/>`__::
434
435 python -m pip install cx_Oracle --upgrade
436
437 If you are behind a proxy, specify your proxy server:
438
439 .. code-block:: shell
440
441 python -m pip install cx_Oracle --proxy=http://proxy.example.com:80 --upgrade
442
443 This will download and install a pre-compiled binary `if one is
444 available <https://pypi.org/project/cx-Oracle/>`__ for your
445 architecture. If a pre-compiled binary is not available, the source
446 will be downloaded, compiled, and the resulting binary installed.
447
448 Install Oracle Client
449 ---------------------
450
451 Using cx_Oracle requires Oracle Client libraries to be installed.
452 These provide the necessary network connectivity allowing cx_Oracle
453 to access an Oracle Database instance. Oracle Client versions 19, 18,
454 12 and 11.2 are supported.
455
456 - If your database is on a remote computer, then download the free `Oracle
457 Instant Client
458 <https://www.oracle.com/database/technologies/instant-client.html>`__
459 "Basic" or "Basic Light" package for your operating system
460 architecture.
461
462 - Alternatively, use the client libraries already available in a
463 locally installed database such as the free `Oracle Database
464 Express Edition ("XE")
465 <https://www.oracle.com/database/technologies/appdev/xe.html>`__
466 release.
467
468
469 Oracle Instant Client Zip Files
470 +++++++++++++++++++++++++++++++
471
472 To use cx_Oracle with Oracle Instant Client zip files:
473
474 1. Download an Oracle 19, 18, 12, or 11.2 "Basic" or "Basic Light" zip
475 file: `64-bit
476 <https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html>`__
477 or `32-bit
478 <https://www.oracle.com/database/technologies/instant-client/microsoft-windows-32-downloads.html>`__, matching your
479 Python architecture.
480
481 The latest version is recommended. Oracle Instant Client 19 will
482 connect to Oracle Database 11.2 or later.
483
484 Windows 7 users: Note that Oracle 19c is not supported on Windows 7.
485
486 2. Unzip the package into a directory that is accessible to your
487 application. For example unzip
488 ``instantclient-basic-windows.x64-19.6.0.0.0dbru.zip`` to
489 ``C:\oracle\instantclient_19_6``.
490
491 3. There are several alternative ways to tell cx_Oracle where your Oracle Client
492 libraries are, see :ref:`initialization`.
493
494 * With Oracle Instant Client you can use :meth:`~cx_Oracle.init_oracle_client()`
495 in your application, for example:
496
497 .. code-block:: python
498
499 import cx_Oracle
500 cx_Oracle.init_oracle_client(lib_dir=r"C:\oracle\instantclient_19_6")
501
502 Note a 'raw' string is used because backslashes occur in the path.
503
504 * Alternatively, add the Oracle Instant Client directory to the ``PATH``
505 environment variable. The directory must occur in ``PATH`` before any
506 other Oracle directories. Restart any open command prompt windows.
507
508 * Another way to set ``PATH`` is to use a batch file that sets it before Python
509 is executed, for example::
510
511 REM mypy.bat
512 SET PATH=C:\oracle\instantclient_19_6;%PATH%
513 python %*
514
515 Invoke this batch file every time you want to run Python.
516
517 4. Oracle Instant Client libraries require a Visual Studio redistributable with
518 a 64-bit or 32-bit architecture to match Instant Client's architecture.
519 Each Instant Client version requires a different redistributable version:
520
521 - For Instant Client 19 install `VS 2017 <https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads>`__.
522 - For Instant Client 18 or 12.2 install `VS 2013 <https://support.microsoft.com/en-us/kb/2977003#bookmark-vs2013>`__
523 - For Instant Client 12.1 install `VS 2010 <https://support.microsoft.com/en-us/kb/2977003#bookmark-vs2010>`__
524 - For Instant Client 11.2 install `VS 2005 64-bit <https://www.microsoft.com/en-us/download/details.aspx?id=18471>`__ or `VS 2005 32-bit <https://www.microsoft.com/en-ca/download/details.aspx?id=3387>`__
525
526 5. If you use optional Oracle configuration files such as ``tnsnames.ora``,
527 ``sqlnet.ora`` or ``oraaccess.xml`` with Instant Client, then put the files
528 in an accessible directory, for example in
529 ``C:\oracle\your_config_dir``. Then use:
530
531 .. code-block:: python
532
533 import cx_Oracle
534 cx_Oracle.init_oracle_client(config_dir=r"C:\oracle\your_config_dir")
535
536 Or set the environment variable ``TNS_ADMIN`` to that directory name.
537
538 Alternatively, put the files in a ``network\admin`` subdirectory of
539 Instant Client, for example in
540 ``C:\oracle\instantclient_19_6\network\admin``. This is the default
541 Oracle configuration directory for executables linked with this
542 Instant Client.
543
544
545 Local Database or Full Oracle Client
546 ++++++++++++++++++++++++++++++++++++
547
548 cx_Oracle applications can use Oracle Client 19, 18, 12, or 11.2
549 libraries libraries from a local Oracle Database or full Oracle
550 Client.
551
552 The Oracle libraries must be either 32-bit or 64-bit, matching your
553 Python architecture.
554
555 1. Set the environment variable ``PATH`` to include the path that contains
556 ``OCI.DLL``, if it is not already set.
557
558 Restart any open command prompt windows.
559
560 2. Optional Oracle configuration files such as ``tnsnames.ora``,
561 ``sqlnet.ora`` or ``oraaccess.xml`` can be placed in the
562 ``network\admin`` subdirectory of the Oracle Database software
563 installation.
564
565 Alternatively, pass ``config_dir`` to :meth:`~cx_Oracle.init_oracle_client()`
566 as shown in the previous section, or set ``TNS_ADMIN`` to the directory name.
567
568 Installing cx_Oracle on macOS
569 =============================
570
571 Install Python
572 --------------
573
574 Make sure you are not using a bundled Python. These have restricted
575 entitlements and will fail to load Oracle client libraries. Instead use
576 `Homebrew <https://brew.sh>`__ or `Python.org
577 <https://www.python.org/downloads>`__.
578
579 Note Instant Client 19 and earlier are not supported on macOS 10.15 Catalina.
580 You will need to allow access to several Instant Client libraries from the
581 Security & Privacy preference pane.
582
583 Install cx_Oracle
584 -----------------
585
586 Use Python's `Pip <http://pip.readthedocs.io/en/latest/installing/>`__
587 package to install cx_Oracle from `PyPI
588 <https://pypi.org/project/cx-Oracle/>`__::
589
590 python -m pip install cx_Oracle --upgrade
591
592 The ``--user`` option may be useful, if you don't have permission to write to
593 system directories:
594
595 .. code-block:: shell
596
597 python -m pip install cx_Oracle --upgrade --user
598
599 If you are behind a proxy, add a proxy server to the command, for example add
600 ``--proxy=http://proxy.example.com:80``
601
602 The source will be downloaded, compiled, and the resulting binary
603 installed.
604
605 Install Oracle Instant Client
606 -----------------------------
607
608 cx_Oracle requires Oracle Client libraries, which are found in Oracle
609 Instant Client for macOS. These provide the necessary network
610 connectivity allowing cx_Oracle to access an Oracle Database instance.
611
612 To use cx_Oracle with Oracle Instant Client zip files:
613
614 1. Download the Oracle 19, 18, 12 or 11.2 "Basic" or "Basic Light" zip file from `here
615 <https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html>`__.
616 Choose either a 64-bit or 32-bit package, matching your
617 Python architecture.
618
619 The latest version is recommended. Oracle Instant Client 19 will
620 connect to Oracle Database 11.2 or later.
621
622 2. Unzip the package into a single directory that is accessible to your
623 application. For example, in Terminal you could unzip in your home directory:
624
625 .. code-block:: shell
626
627 cd ~
628 unzip instantclient-basic-macos.x64-19.3.0.0.0dbru.zip
629
630 This will create a directory ``/Users/your_username/instantclient_19_3``.
631
632 3. There are several alternative ways to tell cx_Oracle where your Oracle
633 Instant Client libraries are, see :ref:`initialization`.
634
635 * You can use :meth:`~cx_Oracle.init_oracle_client()` in your
636 application:
637
638 .. code-block:: python
639
640 import cx_Oracle
641 cx_Oracle.init_oracle_client(lib_dir="/Users/your_username/instantclient_19_3")
642
643 * Alternatively, locate the directory with the cx_Oracle module binary and
644 link or copy Oracle Instant Client to that directory. For example, if you
645 installed cx_Oracle with ``--user`` in Python 3.8, then
646 ``cx_Oracle.cpython-38-darwin.so`` might be in
647 ``~/Library/Python/3.8/lib/python/site-packages``. You can then run
648 ``ln -s ~/instantclient_19_3/libclntsh.dylib
649 ~/Library/Python/3.8/lib/python/site-packages`` or copy the Instant Client
650 libraries to that directory.
651
652 * Alternatively, you can set ``DYLD_LIBRARY_PATH`` to the directory
653 containing Oracle Instant Client, however this needs to be set in each
654 terminal or process that invokes Python. The variable will not propagate
655 to sub-shells.
656
657 * Alternatively, on older versions of macOS, you could add a link to
658 ``$HOME/lib`` or ``/usr/local/lib`` to enable applications to find Instant
659 Client. If the ``lib`` sub-directory does not exist, you can create
660 it. For example:
661
662 .. code-block:: shell
663
664 mkdir ~/lib
665 ln -s ~/instantclient_19_3/libclntsh.dylib ~/lib/
666
667 Instead of linking, you can copy the required OCI libraries. For example:
668
669 .. code-block:: shell
670
671 mkdir ~/lib
672 cp ~/instantclient_19_3/{libclntsh.dylib.19.1,libclntshcore.dylib.19.1,libnnz19.dylib,libociei.dylib} ~/lib/
673
674 For Instant Client 11.2, the OCI libraries must be copied. For example:
675
676 .. code-block:: shell
677
678 mkdir ~/lib
679 cp ~/instantclient_11_2/{libclntsh.dylib.11.1,libnnz11.dylib,libociei.dylib} ~/lib/
680
681 4. If you use optional Oracle configuration files such as ``tnsnames.ora``,
682 ``sqlnet.ora`` or ``oraaccess.xml`` with Oracle Instant Client, then put the
683 files in an accessible directory, for example in
684 ``/Users/your_username/oracle/your_config_dir``. Then use:
685
686 .. code-block:: python
687
688 import cx_Oracle
689 cx_Oracle.init_oracle_client(config_dir="/Users/your_username/oracle/your_config_dir")
690
691 Or set the environment variable ``TNS_ADMIN`` to that directory name.
692
693 Alternatively, put the files in the ``network/admin`` subdirectory of Oracle
694 Instant Client, for example in
695 ``/Users/your_username/instantclient_19_3/network/admin``. This is the
696 default Oracle configuration directory for executables linked with this
697 Instant Client.
698
699 Installing cx_Oracle without Internet Access
700 ============================================
701
702 To install cx_Oracle on a computer that is not connected to the
703 internet, download the appropriate cx_Oracle file from `PyPI
704 <https://pypi.org/project/cx-Oracle/#files>`__. Transfer this file to
705 the offline computer and install it with::
706
707 python -m pip install "<file_name>"
708
709 Then follow the general cx_Oracle platform installation instructions
710 to install Oracle client libraries.
711
712 Install Using GitHub
713 ====================
714
715 In order to install using the source on GitHub, use the following commands::
716
717 git clone https://github.com/oracle/python-cx_Oracle.git cx_Oracle
718 cd cx_Oracle
719 git submodule init
720 git submodule update
721 python setup.py install
722
723 Note that if you download a source zip file directly from GitHub then
724 you will also need to download an `ODPI-C
725 <https://github.com/oracle/odpi>`__ source zip file and extract it
726 inside the directory called "odpi".
727
728 cx_Oracle source code is also available from oss.oracle.com. This can
729 be cloned with::
730
731 git clone git://oss.oracle.com/git/oracle/python-cx_Oracle.git cx_Oracle
732 cd cx_Oracle
733 git submodule init
734 git submodule update
735
736
737 Install Using Source from PyPI
738 ==============================
739
740 The source package can be downloaded manually from
741 `PyPI <https://pypi.org/project/cx-Oracle/>`__ and extracted, after
742 which the following commands should be run::
743
744 python setup.py build
745 python setup.py install
746
747
748 Upgrading from Older Versions
749 =============================
750
751 Review the :ref:`release notes <releasenotes>` for deprecations and modify any
752 affected code.
753
754 If you are upgrading from cx_Oracle 7 note these changes:
755
756 - The default character set used by cx_Oracle 8 is now "UTF-8". Also, the
757 character set component of the ``NLS_LANG`` environment variable is
758 ignored. If you need to change the character set, then pass ``encoding``
759 and ``nendcoding`` parameters when creating a connection or connection
760 pool. See :ref:`globalization`.
761
762 - Any uses of ``type(var)`` need to be changed to ``var.type``.
763
764 - Any uses of ``var.type is not None`` need to be changed to
765 ``isinstance(var.type, cx_Oracle.ObjectType)``
766
767 - Note that ``TIMESTAMP WITH TIME ZONE`` columns will now be reported as
768 :data:`cx_Oracle.DB_TYPE_TIMESTAMP_TZ` instead of
769 :data:`cx_Oracle.TIMESTAMP` in :data:`Cursor.description`.
770
771 - Note that ``TIMESTAMP WITH LOCAL TIME ZONE`` columns will now be reported
772 as :data:`cx_Oracle.DB_TYPE_TIMESTAMP_LTZ` instead of
773 :data:`cx_Oracle.TIMESTAMP` in :data:`Cursor.description`.
774
775 - Note that ``BINARY_FLOAT`` columns will now be reported as
776 :data:`cx_Oracle.DB_TYPE_BINARY_FLOAT` instead of
777 :data:`cx_Oracle.NATIVE_DOUBLE` in :data:`Cursor.description`.
778
779 If you are upgrading from cx_Oracle 5 note these installation changes:
780
781 - When using Oracle Instant Client, you should not set ``ORACLE_HOME``.
782
783 - On Linux, cx_Oracle 6 and higher no longer uses Instant Client RPMs
784 automatically. You must set ``LD_LIBRARY_PATH`` or use ``ldconfig`` to
785 locate the Oracle client library.
786
787 - PyPI no longer allows Windows installers or Linux RPMs to be
788 hosted. Use the supplied cx_Oracle Wheels instead, or use RPMs
789 from Oracle, see :ref:`oraclelinux`.
790
791 .. _python2:
792
793 Installing cx_Oracle in Python 2
794 ================================
795
796 To install cx_Oracle in Python 2, use a command like::
797
798 python -m pip install cx_Oracle==7.3 --upgrade --user
799
800 cx_Oracle 7.3 was the last version with support for Python 2.
801
802 For other installation options such as installing through a proxy, see
803 instructions above. Make sure the Oracle Client libraries are in the system
804 library search path because cx_Oracle 7 does not support the
805 :meth:`cx_Oracle.init_oracle_client()` method and does not support loading the
806 Oracle Client libraries from the directory containing the cx_Oracle module
807 binary.
808
809 Installing cx_Oracle 5.3
810 ========================
811
812 If you require cx_Oracle 5.3, download a Windows installer from `PyPI
813 <https://pypi.org/project/cx-Oracle/>`__ or use ``python -m pip
814 install cx-oracle==5.3`` to install from source.
815
816 Very old versions of cx_Oracle can be found in the files section at
817 `SourceForce <https://sourceforge.net/projects/cx-oracle/files/>`__.
818
819
820 Troubleshooting
821 ===============
822
823 If installation fails:
824
825 - Use option ``-v`` with pip. Review your output and logs. Try to install
826 using a different method. **Google anything that looks like an error.**
827 Try some potential solutions.
828
829 - Was there a network connection error? Do you need to set the
830 environment variables ``http_proxy`` and/or ``https_proxy``? Or
831 try ``pip install --proxy=http://proxy.example.com:80 cx_Oracle
832 --upgrade``?
833
834 - If upgrading gave no errors but the old version is still
835 installed, try ``pip install cx_Oracle --upgrade
836 --force-reinstall``
837
838 - If you do not have access to modify your system version of
839 Python, can you use ``pip install cx_Oracle --upgrade --user``
840 or venv?
841
842 - Do you get the error "``No module named pip``"? The pip module is builtin
843 to Python but is sometimes removed by the OS. Use the venv module
844 (builtin to Python 3.x) or virtualenv module instead.
845
846 - Do you get the error "``fatal error: dpi.h: No such file or directory``"
847 when building from source code? Ensure that your source installation has
848 a subdirectory called "odpi" containing files. If missing, review the
849 section on `Install Using GitHub`_.
850
851 If using cx_Oracle fails:
852
853 - Do you get the error "``DPI-1047: Oracle Client library cannot be
854 loaded``"?
855
856 - Check that Python, cx_Oracle and your Oracle Client libraries
857 are all 64-bit or all 32-bit. The ``DPI-1047`` message will
858 tell you whether the 64-bit or 32-bit Oracle Client is needed
859 for your Python.
860 - On Windows, if you used :meth:`~cx_Oracle.init_oracle_client()` and have
861 a full database installation, make sure this database is the `currently
862 configured database
863 <http://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-33D575DD-47FF-42B1-A82F-049D3F2A8791>`__.
864 - On Windows, if you are not using
865 :meth:`~cx_Oracle.init_oracle_client()`, then restart your command prompt
866 and use ``set PATH`` to check the environment variable has the correct
867 Oracle Client listed before any other Oracle directories.
868 - On Windows, use the ``DIR`` command to verify that ``OCI.DLL`` exists in
869 the directory passed to ``init_oracle_client()`` or set in ``PATH``.
870 - On Windows, check that the correct `Windows Redistributables
871 <https://oracle.github.io/odpi/doc/installation.html#windows>`__ have
872 been installed.
873 - On Linux, check the ``LD_LIBRARY_PATH`` environment variable contains
874 the Oracle Client library directory. If you are using Oracle Instant
875 Client, a preferred alternative is to ensure a file in the
876 ``/etc/ld.so.conf.d`` directory contains the path to the Instant Client
877 directory, and then run ``ldconfig``.
878 - On macOS, make sure you are not using the bundled Python (use `Homebrew
879 <https://brew.sh>`__ or `Python.org
880 <https://www.python.org/downloads>`__ instead). If you are not using
881 :meth:`~cx_Oracle.init_oracle_client()`, then put the Oracle Instant
882 Client libraries in ``~/lib`` or ``/usr/local/lib``.
883
884 - If you got "``DPI-1072: the Oracle Client library version is
885 unsupported``", then review the installation requirements. cx_Oracle
886 needs Oracle client libraries 11.2 or later. Note that version 19 is not
887 supported on Windows 7. Similar steps shown above for ``DPI-1047`` may
888 help.
889
890 - If you have multiple versions of Python installed, make sure you are
891 using the correct python and pip (or python3 and pip3) executables.
0 .. _introduction:
1
2 *************************
3 Introduction to cx_Oracle
4 *************************
5
6 cx_Oracle is a Python extension module that enables Python access to Oracle
7 Database. It conforms to the `Python Database API v2.0 Specification
8 <https://www.python.org/dev/peps/pep-0249/>`__ with a considerable number of
9 additions and a couple of exclusions.
10
11 Architecture
12 ------------
13
14 Python programs call cx_Oracle functions. Internally cx_Oracle dynamically
15 loads Oracle Client libraries to access Oracle Database. The database can be on
16 the same machine as Python, or it can be remote.
17
18 .. _archfig:
19 .. figure:: /images/cx_Oracle_arch.png
20
21 cx_Oracle Architecture
22
23 cx_Oracle is typically installed from `PyPI
24 <https://pypi.org/project/cx-Oracle/>`__ using `pip
25 <http://pip.readthedocs.io/en/latest/installing/>`__. The Oracle Client
26 libraries need to be installed separately. The libraries can be obtained from
27 an installation of `Oracle Instant Client
28 <https://www.oracle.com/database/technologies/instant-client.html>`__, from a
29 full Oracle Client installation, or even from an Oracle Database installation
30 (if Python is running on the same machine as the database).
31
32 Some behaviors of the Oracle Client libraries can optionally be configured with
33 an ``oraaccess.xml`` file, for example to enable auto-tuning of a statement
34 cache. See :ref:`optclientfiles`.
35
36 The Oracle Net layer can optionally be configured with files such as
37 ``tnsnames.ora`` and ``sqlnet.ora``, for example to enable :ref:`network
38 encryption <netencrypt>`. See :ref:`optnetfiles`.
39
40 Oracle environment variables that are set before cx_Oracle first creates a
41 database connection will affect cx_Oracle behavior. Optional variables include
42 NLS_LANG, NLS_DATE_FORMAT and TNS_ADMIN. See :ref:`envset`.
43
44 Features
45 --------
46
47 The cx_Oracle feature highlights are:
48
49 * Easily installed from PyPI
50 * Support for multiple Oracle Client and Database versions
51 * Execution of SQL and PL/SQL statements
52 * Extensive Oracle data type support, including large objects (CLOB and
53 BLOB) and binding of SQL objects
54 * Connection management, including connection pooling
55 * Oracle Database High Availability features
56 * Full use of Oracle Network Service infrastructure, including encrypted
57 network traffic and security features
58
59 A complete list of supported features can be seen `here
60 <https://oracle.github.io/python-cx_Oracle/index.html#features>`_.
61
62 Getting Started
63 ---------------
64
65 Install cx_Oracle using the :ref:`installation <installation>` steps.
66
67 Create a script ``query.py`` as shown below:
68
69 .. code-block:: python
70
71 # query.py
72
73 import cx_Oracle
74
75 # Establish the database connection
76 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1")
77
78 # Obtain a cursor
79 cursor = connection.cursor()
80
81 # Data for binding
82 managerId = 145
83 firstName = "Peter"
84
85 # Execute the query
86 sql = """SELECT first_name, last_name
87 FROM employees
88 WHERE manager_id = :mid AND first_name = :fn"""
89 cursor.execute(sql, mid = managerId, fn = firstName)
90
91 # Loop over the result set
92 for row in cursor:
93 print(row)
94
95 This uses Oracle's `sample HR schema
96 <https://github.com/oracle/db-sample-schemas>`__.
97
98 Simple :ref:`connection <connhandling>` to the database requires a username,
99 password and connection string. Locate your Oracle Database `user name and
100 password <https://www.youtube.com/watch?v=WDJacg0NuLo>`_ and the database
101 :ref:`connection string <connstr>`, and use them in ``query.py``. For
102 cx_Oracle the connection string is commonly of the format
103 ``hostname/servicename``, using the host name where the database is running and
104 the Oracle Database service name of the database instance.
105
106 The :ref:`cursor <cursorobj>` is the object that allows statements to be
107 executed and results (if any) fetched.
108
109 The data values in ``managerId`` and ``firstName`` are 'bound' to the statement
110 placeholder 'bind variables' ``:mid`` and ``:fn`` when the statement is
111 executed. This separates the statement text from the data, which helps avoid
112 SQL Injection security risks. :ref:`Binding <bind>` is also important for
113 performance and scalability.
114
115 The cursor allows rows to be iterated over and displayed.
116
117 Run the script::
118
119 python query.py
120
121 The output is::
122
123 ('Peter', 'Hall')
124 ('Peter', 'Tucker')
125
126 Examples and Tutorials
127 ----------------------
128
129 Runnable examples are in the `GitHub samples directory
130 <https://github.com/oracle/python-cx_Oracle/tree/master/samples>`__. A `Python
131 cx_Oracle tutorial
132 <https://oracle.github.io/python-cx_Oracle/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html>`__
133 is also available.
0 .. _jsondatatype:
1
2 *******************************
3 Working with the JSON Data Type
4 *******************************
5
6 Native support for JSON data was introduced in Oracle database 12c. You can use
7 the relational database to store and query JSON data and benefit from the easy
8 extensibility of JSON data while retaining the performance and structure of the
9 relational database. JSON data is stored in the database in BLOB, CLOB or
10 VARCHAR2 columns. For performance reasons, it is always a good idea to store
11 JSON data in BLOB columns. To ensure that only JSON data is stored in that
12 column, use a check constraint with the clause ``is JSON`` as shown in the
13 following SQL to create a table containing JSON data:
14
15 .. code-block:: sql
16
17 create table customers (
18 id integer not null primary key,
19 json_data blob check (json_data is json)
20 );
21
22 The following Python code can then be used to insert some data into the
23 database:
24
25 .. code-block:: python
26
27 import json
28
29 customerData = dict(name="Rod", dept="Sales", location="Germany")
30 cursor.execute("insert into customers (id, json_data) values (:1, :2)",
31 [1, json.dumps(customerData)])
32
33 The data can be retrieved in its entirety using the following code:
34
35 .. code-block:: python
36
37 import json
38
39 for blob, in cursor.execute("select json_data from customers"):
40 data = json.loads(blob.read())
41 print(data["name"]) # will print Rod
42
43 If only the department needs to be read, the following code can be used
44 instead:
45
46 .. code-block:: python
47
48 for deptName, in cursor.execute("select c.json_data.dept from customers c"):
49 print(deptName) # will print Sales
50
51 You can convert the data stored in relational tables into JSON data by using
52 the JSON_OBJECT SQL operator. For example:
53
54 .. code-block:: python
55
56 import json
57 cursor.execute("""
58 select json_object(
59 'id' value employee_id,
60 'name' value (first_name || ' ' || last_name))
61 from employees where rownum <= 3""")
62 for value, in cursor:
63 print(json.loads(value,))
64
65 The result is::
66
67 {'id': 100, 'name': 'Steven King'}
68 {'id': 101, 'name': 'Neena Kochhar'}
69 {'id': 102, 'name': 'Lex De Haan'}
70
71
72 See `JSON Developer's Guide
73 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
74 id=GUID-17642E43-7D87-4590-8870-06E9FDE9A6E9>`__ for more information about
75 using JSON in Oracle Database.
0 .. _lobdata:
1
2 ************************
3 Using CLOB and BLOB Data
4 ************************
5
6 Oracle Database uses :ref:`lobobj` to store large data such as text, images,
7 videos and other multimedia formats. The maximum size of a LOB is limited to
8 the size of the tablespace storing it.
9
10 There are four types of LOB (large object):
11
12 * BLOB - Binary Large Object, used for storing binary data. cx_Oracle uses
13 the type :attr:`cx_Oracle.DB_TYPE_BLOB`.
14 * CLOB - Character Large Object, used for string strings in the database
15 character set format. cx_Oracle uses the type
16 :attr:`cx_Oracle.DB_TYPE_CLOB`.
17 * NCLOB - National Character Large Object, used for string strings in the
18 national character set format. cx_Oracle uses the type
19 :attr:`cx_Oracle.DB_TYPE_NCLOB`.
20 * BFILE - External Binary File, used for referencing a file stored on the
21 host operating system outside of the database. cx_Oracle uses the type
22 :attr:`cx_Oracle.DB_TYPE_BFILE`.
23
24 LOBs can be streamed to, and from, Oracle Database.
25
26 LOBs up to 1 GB in length can be also be handled directly as strings or bytes in
27 cx_Oracle. This makes LOBs easy to work with, and has significant performance
28 benefits over streaming. However it requires the entire LOB data to be present
29 in Python memory, which may not be possible.
30
31 See `GitHub <https://github.com/oracle/python-cx_Oracle/tree/master/samples>`__ for LOB examples.
32
33
34 Simple Insertion of LOBs
35 ------------------------
36
37 Consider a table with CLOB and BLOB columns:
38
39 .. code-block:: sql
40
41 CREATE TABLE lob_tbl (
42 id NUMBER,
43 c CLOB,
44 b BLOB
45 );
46
47 With cx_Oracle, LOB data can be inserted in the table by binding strings or
48 bytes as needed:
49
50 .. code-block:: python
51
52 with open('example.txt', 'r') as f:
53 textdata = f.read()
54
55 with open('image.png', 'rb') as f:
56 imgdata = f.read()
57
58 cursor.execute("""
59 insert into lob_tbl (id, c, b)
60 values (:lobid, :clobdata, :blobdata)""",
61 lobid=10, clobdata=textdata, blobdata=imgdata)
62
63 Note that with this approach, LOB data is limited to 1 GB in size.
64
65 .. _directlobs:
66
67 Fetching LOBs as Strings and Bytes
68 ----------------------------------
69
70 CLOBs and BLOBs smaller than 1 GB can queried from the database directly as
71 strings and bytes. This can be much faster than streaming.
72
73 A :attr:`Connection.outputtypehandler` or :attr:`Cursor.outputtypehandler` needs
74 to be used as shown in this example:
75
76 .. code-block:: python
77
78 def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
79 if defaultType == cx_Oracle.DB_TYPE_CLOB:
80 return cursor.var(cx_Oracle.DB_TYPE_LONG, arraysize=cursor.arraysize)
81 if defaultType == cx_Oracle.DB_TYPE_BLOB:
82 return cursor.var(cx_Oracle.DB_TYPE_LONG_RAW, arraysize=cursor.arraysize)
83
84 idVal = 1
85 textData = "The quick brown fox jumps over the lazy dog"
86 bytesData = b"Some binary data"
87 cursor.execute("insert into lob_tbl (id, c, b) values (:1, :2, :3)",
88 [idVal, textData, bytesData])
89
90 connection.outputtypehandler = OutputTypeHandler
91 cursor.execute("select c, b from lob_tbl where id = :1", [idVal])
92 clobData, blobData = cursor.fetchone()
93 print("CLOB length:", len(clobData))
94 print("CLOB data:", clobData)
95 print("BLOB length:", len(blobData))
96 print("BLOB data:", blobData)
97
98 This displays::
99
100 CLOB length: 43
101 CLOB data: The quick brown fox jumps over the lazy dog
102 BLOB length: 16
103 BLOB data: b'Some binary data'
104
105
106 Streaming LOBs (Read)
107 ---------------------
108
109 Without the output type handler, the CLOB and BLOB values are fetched as
110 :ref:`LOB objects<lobobj>`. The size of the LOB object can be obtained by
111 calling :meth:`LOB.size()` and the data can be read by calling
112 :meth:`LOB.read()`:
113
114 .. code-block:: python
115
116 idVal = 1
117 textData = "The quick brown fox jumps over the lazy dog"
118 bytesData = b"Some binary data"
119 cursor.execute("insert into lob_tbl (id, c, b) values (:1, :2, :3)",
120 [idVal, textData, bytesData])
121
122 cursor.execute("select b, c from lob_tbl where id = :1", [idVal])
123 b, c = cursor.fetchone()
124 print("CLOB length:", c.size())
125 print("CLOB data:", c.read())
126 print("BLOB length:", b.size())
127 print("BLOB data:", b.read())
128
129 This approach produces the same results as the previous example but it will
130 perform more slowly because it requires more :ref:`round-trips <roundtrips>` to
131 Oracle Database and has higher overhead. It is needed, however, if the LOB data
132 cannot be fetched as one block of data from the server.
133
134 To stream the BLOB column, the :meth:`LOB.read()` method can be called
135 repeatedly until all of the data has been read, as shown below:
136
137 .. code-block:: python
138
139 cursor.execute("select b from lob_tbl where id = :1", [10])
140 blob, = cursor.fetchone()
141 offset = 1
142 numBytesInChunk = 65536
143 with open("image.png", "wb") as f:
144 while True:
145 data = blob.read(offset, numBytesInChunk)
146 if data:
147 f.write(data)
148 if len(data) < numBytesInChunk:
149 break
150 offset += len(data)
151
152
153 Streaming LOBs (Write)
154 ----------------------
155
156 If a row containing a LOB is being inserted or updated, and the quantity of
157 data that is to be inserted or updated cannot fit in a single block of data,
158 the data can be streamed using the method :meth:`LOB.write()` instead as shown
159 in the following code:
160
161 .. code-block:: python
162
163 idVal = 9
164 lobVar = cursor.var(cx_Oracle.DB_TYPE_BLOB)
165 cursor.execute("""
166 insert into lob_tbl (id, b)
167 values (:1, empty_blob())
168 returning b into :2""", [idVal, lobVar])
169 blob, = lobVar.getvalue()
170 offset = 1
171 numBytesInChunk = 65536
172 with open("image.png", "rb") as f:
173 while True:
174 data = f.read(numBytesInChunk)
175 if data:
176 blob.write(data, offset)
177 if len(data) < numBytesInChunk:
178 break
179 offset += len(data)
180 connection.commit()
181
182
183 Temporary LOBs
184 --------------
185
186 All of the examples shown thus far have made use of permanent LOBs. These are
187 LOBs that are stored in the database. Oracle also supports temporary LOBs that
188 are not stored in the database but can be used to pass large quantities of
189 data. These LOBs use space in the temporary tablespace until all variables
190 referencing them go out of scope or the connection in which they are created is
191 explicitly closed.
192
193 When calling PL/SQL procedures with data that exceeds 32,767 bytes in length,
194 cx_Oracle automatically creates a temporary LOB internally and passes that
195 value through to the procedure. If the data that is to be passed to the
196 procedure exceeds that which can fit in a single block of data, however, you
197 can use the method :meth:`Connection.createlob()` to create a temporary LOB.
198 This LOB can then be read and written just like in the examples shown above for
199 persistent LOBs.
0 .. _plsqlexecution:
1
2 ****************
3 PL/SQL Execution
4 ****************
5
6 PL/SQL stored procedures, functions and anonymous blocks can be called from
7 cx_Oracle.
8
9 .. _plsqlproc:
10
11 PL/SQL Stored Procedures
12 ------------------------
13
14 The :meth:`Cursor.callproc()` method is used to call PL/SQL procedures.
15
16 If a procedure with the following definition exists:
17
18 .. code-block:: sql
19
20 create or replace procedure myproc (
21 a_Value1 number,
22 a_Value2 out number
23 ) as
24 begin
25 a_Value2 := a_Value1 * 2;
26 end;
27
28 then the following Python code can be used to call it:
29
30 .. code-block:: python
31
32 outVal = cursor.var(int)
33 cursor.callproc('myproc', [123, outVal])
34 print(outVal.getvalue()) # will print 246
35
36 Calling :meth:`Cursor.callproc()` actually generates an anonymous PL/SQL block
37 as shown below, which is then executed:
38
39 .. code-block:: python
40
41 cursor.execute("begin myproc(:1,:2); end;", [123, outval])
42
43 See :ref:`bind` for information on binding.
44
45
46 .. _plsqlfunc:
47
48 PL/SQL Stored Functions
49 -----------------------
50
51 The :meth:`Cursor.callfunc()` method is used to call PL/SQL functions.
52
53 The ``returnType`` parameter for :meth:`~Cursor.callfunc()` is
54 expected to be a Python type, one of the :ref:`cx_Oracle types <types>` or
55 an :ref:`Object Type <objecttype>`.
56
57 If a function with the following definition exists:
58
59 .. code-block:: sql
60
61 create or replace function myfunc (
62 a_StrVal varchar2,
63 a_NumVal number
64 ) return number as
65 begin
66 return length(a_StrVal) + a_NumVal * 2;
67 end;
68
69 then the following Python code can be used to call it:
70
71 .. code-block:: python
72
73 returnVal = cursor.callfunc("myfunc", int, ["a string", 15])
74 print(returnVal) # will print 38
75
76 A more complex example that returns a spatial (SDO) object can be seen below.
77 First, the SQL statements necessary to set up the example:
78
79 .. code-block:: sql
80
81 create table MyPoints (
82 id number(9) not null,
83 point sdo_point_type not null
84 );
85
86 insert into MyPoints values (1, sdo_point_type(125, 375, 0));
87
88 create or replace function spatial_queryfn (
89 a_Id number
90 ) return sdo_point_type is
91 t_Result sdo_point_type;
92 begin
93 select point
94 into t_Result
95 from MyPoints
96 where Id = a_Id;
97
98 return t_Result;
99 end;
100 /
101
102 The Python code that will call this procedure looks as follows:
103
104 .. code-block:: python
105
106 objType = connection.gettype("SDO_POINT_TYPE")
107 cursor = connection.cursor()
108 returnVal = cursor.callfunc("spatial_queryfn", objType, [1])
109 print("(%d, %d, %d)" % (returnVal.X, returnVal.Y, returnVal.Z))
110 # will print (125, 375, 0)
111
112 See :ref:`bind` for information on binding.
113
114
115 Anonymous PL/SQL Blocks
116 -----------------------
117
118 An anonymous PL/SQL block can be called as shown:
119
120 .. code-block:: python
121
122 var = cursor.var(int)
123 cursor.execute("""
124 begin
125 :outVal := length(:inVal);
126 end;""", inVal="A sample string", outVal=var)
127 print(var.getvalue()) # will print 15
128
129 See :ref:`bind` for information on binding.
130
131
132 Using DBMS_OUTPUT
133 -----------------
134
135 The standard way to print output from PL/SQL is with the package `DBMS_OUTPUT
136 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
137 id=GUID-C1400094-18D5-4F36-A2C9-D28B0E12FD8C>`__. Note, PL/SQL code that uses
138 ``DBMS_OUTPUT`` runs to completion before any output is available to the user.
139 Also, other database connections cannot access the buffer.
140
141 To use DBMS_OUTPUT:
142
143 * Call the PL/SQL procedure ``DBMS_OUTPUT.ENABLE()`` to enable output to be
144 buffered for the connection.
145 * Execute some PL/SQL that calls ``DBMS_OUTPUT.PUT_LINE()`` to put text in the
146 buffer.
147 * Call ``DBMS_OUTPUT.GET_LINE()`` or ``DBMS_OUTPUT.GET_LINES()`` repeatedly to
148 fetch the text from the buffer until there is no more output.
149
150
151 For example:
152
153 .. code-block:: python
154
155 # enable DBMS_OUTPUT
156 cursor.callproc("dbms_output.enable")
157
158 # execute some PL/SQL that calls DBMS_OUTPUT.PUT_LINE
159 cursor.execute("""
160 begin
161 dbms_output.put_line('This is the cx_Oracle manual');
162 dbms_output.put_line('Demonstrating how to use DBMS_OUTPUT');
163 end;""")
164
165 # tune this size for your application
166 chunk_size = 100
167
168 # create variables to hold the output
169 lines_var = cursor.arrayvar(str, chunk_size)
170 num_lines_var = cursor.var(int)
171 num_lines_var.setvalue(0, chunk_size)
172
173 # fetch the text that was added by PL/SQL
174 while True:
175 cursor.callproc("dbms_output.get_lines", (lines_var, num_lines_var))
176 num_lines = num_lines_var.getvalue()
177 lines = lines_var.getvalue()[:num_lines]
178 for line in lines:
179 print(line or "")
180 if num_lines < chunk_size:
181 break
182
183 This will produce the following output::
184
185 This is the cx_Oracle manual
186 Demonstrating use of DBMS_OUTPUT
187
188 An alternative is to call ``DBMS_OUTPUT.GET_LINE()`` once per output line, which
189 may be much slower:
190
191 .. code-block:: python
192
193 textVar = cursor.var(str)
194 statusVar = cursor.var(int)
195 while True:
196 cursor.callproc("dbms_output.get_line", (textVar, statusVar))
197 if statusVar.getvalue() != 0:
198 break
199 print(textVar.getvalue())
200
201 Implicit results
202 ----------------
203
204 Implicit results permit a Python program to consume cursors returned by a
205 PL/SQL block without the requirement to use OUT REF CURSOR parameters. The
206 method :meth:`Cursor.getimplicitresults()` can be used for this purpose. It
207 requires both the Oracle Client and Oracle Database to be 12.1 or higher.
208
209 An example using implicit results is as shown:
210
211 .. code-block:: python
212
213 cursor.execute("""
214 declare
215 cust_cur sys_refcursor;
216 sales_cur sys_refcursor;
217 begin
218 open cust_cur for SELECT * FROM cust_table;
219 dbms_sql.return_result(cust_cur);
220
221 open sales_cur for SELECT * FROM sales_table;
222 dbms_sql.return_result(sales_cur);
223 end;""")
224
225 for implicitCursor in cursor.getimplicitresults():
226 for row in implicitCursor:
227 print(row)
228
229 Data from both the result sets are returned::
230
231 (1, 'Tom')
232 (2, 'Julia')
233 (1000, 1, 'BOOKS')
234 (2000, 2, 'FURNITURE')
235
236 .. _ebr:
237
238 Edition-Based Redefinition (EBR)
239 --------------------------------
240
241 Oracle Database's `Edition-Based Redefinition
242 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
243 id=GUID-58DE05A0-5DEF-4791-8FA8-F04D11964906>`__ feature enables upgrading of
244 the database component of an application while it is in use, thereby minimizing
245 or eliminating down time. This feature allows multiple versions of views,
246 synonyms, PL/SQL objects and SQL Translation profiles to be used concurrently.
247 Different versions of the database objects are associated with an "edition".
248
249 The simplest way to set an edition is to pass the ``edition`` parameter to
250 :meth:`cx_Oracle.connect()` or :meth:`cx_Oracle.SessionPool()`:
251
252 .. code-block:: python
253
254 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
255 edition="newsales", encoding="UTF-8")
256
257
258 The edition could also be set by setting the environment variable
259 ``ORA_EDITION`` or by executing the SQL statement:
260
261 .. code-block:: sql
262
263 alter session set edition = <edition name>;
264
265 Regardless of which method is used to set the edition, the value that is in use
266 can be seen by examining the attribute :attr:`Connection.edition`. If no value
267 has been set, the value will be None. This corresponds to the database default
268 edition ``ORA$BASE``.
269
270 Consider an example where one version of a PL/SQL function ``Discount`` is
271 defined in the database default edition ``ORA$BASE`` and the other version of
272 the same function is defined in a user created edition ``DEMO``.
273
274 .. code-block:: sql
275
276 connect <username>/<password>
277
278 -- create function using the database default edition
279 CREATE OR REPLACE FUNCTION Discount(price IN NUMBER) RETURN NUMBER IS
280 BEGIN
281 return price * 0.9;
282 END;
283 /
284
285 A new edition named 'DEMO' is created and the user given permission to use
286 editions. The use of ``FORCE`` is required if the user already contains one or
287 more objects whose type is editionable and that also have non-editioned
288 dependent objects.
289
290 .. code-block:: sql
291
292 connect system/<password>
293
294 CREATE EDITION demo;
295 ALTER USER <username> ENABLE EDITIONS FORCE;
296 GRANT USE ON EDITION demo to <username>;
297
298 The ``Discount`` function for the demo edition is as follows:
299
300 .. code-block:: sql
301
302 connect <username>/<password>
303
304 alter session set edition = demo;
305
306 -- Function for the demo edition
307 CREATE OR REPLACE FUNCTION Discount(price IN NUMBER) RETURN NUMBER IS
308 BEGIN
309 return price * 0.5;
310 END;
311 /
312
313 The Python application can then call the required version of the PL/SQL
314 function as shown:
315
316 .. code-block:: python
317
318 connection = cx_Oracle.connect(<username>, <password>, "dbhost.example.com/orclpdb1",
319 encoding="UTF-8")
320 print("Edition is:", repr(connection.edition))
321
322 cursor = connection.cursor()
323 discountedPrice = cursor.callfunc("Discount", int, [100])
324 print("Price after discount is:", discountedPrice)
325
326 # Use the edition parameter for the connection
327 connection = cx_Oracle.connect(<username>, <password>, "dbhost.example.com/orclpdb1",
328 edition = "demo", encoding="UTF-8")
329 print("Edition is:", repr(connection.edition))
330
331 cursor = connection.cursor()
332 discountedPrice = cursor.callfunc("Discount", int, [100])
333 print("Price after discount is:", discountedPrice)
334
335 The output of the function call for the default and demo edition is as shown::
336
337 Edition is: None
338 Price after discount is: 90
339 Edition is: 'DEMO'
340 Price after discount is: 50
0 .. _sodausermanual:
1
2 ************************************
3 Simple Oracle Document Access (SODA)
4 ************************************
5
6 Overview
7 ========
8
9 Oracle Database Simple Oracle Document Access (SODA) allows documents to be
10 inserted, queried, and retrieved from Oracle Database using a set of
11 NoSQL-style cx_Oracle methods. Documents are generally JSON data but they can
12 be any data at all (including video, images, sounds, or other binary content).
13 Documents can be fetched from the database by key lookup or by using
14 query-by-example (QBE) pattern-matching.
15
16 SODA uses a SQL schema to store documents but you do not need to know SQL or
17 how the documents are stored. However, access via SQL does allow use of
18 advanced Oracle Database functionality such as analytics for reporting.
19
20 For general information on SODA, see the `SODA home page
21 <https://docs.oracle.com/en/database/oracle/simple-oracle-document-access/index.html>`__
22 and `Oracle Database Introduction to SODA
23 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=ADSDI>`__.
24
25 cx_Oracle uses the following objects for SODA:
26
27 * :ref:`SODA Database Object <sodadb>`: The top level object for cx_Oracle SODA
28 operations. This is acquired from an Oracle Database connection. A 'SODA
29 database' is an abstraction, allowing access to SODA collections in that
30 'SODA database', which then allow access to documents in those collections.
31 A SODA database is analogous to an Oracle Database user or schema, a
32 collection is analogous to a table, and a document is analogous to a table
33 row with one column for a unique document key, a column for the document
34 content, and other columns for various document attributes.
35
36 * :ref:`SODA Collection Object <sodacoll>`: Represents a collection of SODA
37 documents. By default, collections allow JSON documents to be stored. This
38 is recommended for most SODA users. However optional metadata can set
39 various details about a collection, such as its database storage, whether it
40 should track version and time stamp document components, how such components
41 are generated, and what document types are supported. By default, the name of
42 the Oracle Database table storing a collection is the same as the collection
43 name. Note: do not use SQL to drop the database table, since SODA metadata
44 will not be correctly removed. Use the :meth:`SodaCollection.drop()` method
45 instead.
46
47 * :ref:`SODA Document Object <sodadoc>`: Represents a document. Typically the
48 document content will be JSON. The document has properties including the
49 content, a key, timestamps, and the media type. By default, document keys
50 are automatically generated. See :ref:`SODA Document objects <sodadoc>` for
51 the forms of SodaDoc.
52
53 * :ref:`SODA Document Cursor <sodadoccur>`: A cursor object representing the
54 result of the :meth:`SodaOperation.getCursor()` method from a
55 :meth:`SodaCollection.find()` operation. It can be iterated over to access
56 each SodaDoc.
57
58 * :ref:`SODA Operation Object <sodaop>`: An internal object used with
59 :meth:`SodaCollection.find()` to perform read and write operations on
60 documents. Chained methods set properties on a SodaOperation object which is
61 then used by a terminal method to find, count, replace, or remove documents.
62 This is an internal object that should not be directly accessed.
63
64 SODA Example
65 ============
66
67 Creating and adding documents to a collection can be done as follows:
68
69 .. code-block:: python
70
71 soda = connection.getSodaDatabase()
72
73 # create a new SODA collection; this will open an existing collection, if
74 # the name is already in use
75 collection = soda.createCollection("mycollection")
76
77 # insert a document into the collection; for the common case of a JSON
78 # document, the content can be a simple Python dictionary which will
79 # internally be converted to a JSON document
80 content = {'name': 'Matilda', 'address': {'city': 'Melbourne'}}
81 returnedDoc = collection.insertOneAndGet(content)
82 key = returnedDoc.key
83 print('The key of the new SODA document is: ', key)
84
85 By default, a system generated key is created when documents are inserted.
86 With a known key, you can retrieve a document:
87
88 .. code-block:: python
89
90 # this will return a dictionary (as was inserted in the previous code)
91 content = collection.find().key(key).getOne().getContent()
92 print(content)
93
94 You can also search for documents using query-by-example syntax:
95
96 .. code-block:: python
97
98 # Find all documents with names like 'Ma%'
99 print("Names matching 'Ma%'")
100 qbe = {'name': {'$like': 'Ma%'}}
101 for doc in collection.find().filter(qbe).getDocuments():
102 content = doc.getContent()
103 print(content["name"])
104
105 See the `samples directory
106 <https://github.com/oracle/python-cx_Oracle/tree/master/samples>`__
107 for runnable SODA examples.
0 .. _sqlexecution:
1
2 *************
3 SQL Execution
4 *************
5
6 Executing SQL statements is the primary way in which a Python application
7 communicates with Oracle Database. Statements are executed using the methods
8 :meth:`Cursor.execute()` or :meth:`Cursor.executemany()`. Statements include
9 queries, Data Manipulation Language (DML), and Data Definition Language (DDL).
10 A few other `specialty statements
11 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
12 id=GUID-E1749EF5-2264-44DF-99EF-AEBEB943BED6>`__ can also be executed.
13
14 PL/SQL statements are discussed in :ref:`plsqlexecution`. Other chapters
15 contain information on specific data types and features. See :ref:`batchstmnt`,
16 :ref:`lobdata`, :ref:`jsondatatype`, and :ref:`xmldatatype`.
17
18 cx_Oracle can be used to execute individual statements, one at a time. It does
19 not read SQL*Plus ".sql" files. To read SQL files, use a technique like the one
20 in ``RunSqlScript()`` in `samples/SampleEnv.py
21 <https://github.com/oracle/python-cx_Oracle/blob/master/samples/SampleEnv.py>`__
22
23 SQL statements should not contain a trailing semicolon (";") or forward slash
24 ("/"). This will fail:
25
26 .. code-block:: python
27
28 cur.execute("select * from MyTable;")
29
30 This is correct:
31
32 .. code-block:: python
33
34 cur.execute("select * from MyTable")
35
36
37 SQL Queries
38 ===========
39
40 Queries (statements beginning with SELECT or WITH) can only be executed using
41 the method :meth:`Cursor.execute()`. Rows can then be iterated over, or can be
42 fetched using one of the methods :meth:`Cursor.fetchone()`,
43 :meth:`Cursor.fetchmany()` or :meth:`Cursor.fetchall()`. There is a
44 :ref:`default type mapping <defaultfetchtypes>` to Python types that can be
45 optionally :ref:`overridden <outputtypehandlers>`.
46
47 .. IMPORTANT::
48
49 Interpolating or concatenating user data with SQL statements, for example
50 ``cur.execute("SELECT * FROM mytab WHERE mycol = '" + myvar + "'")``, is a security risk
51 and impacts performance. Use :ref:`bind variables <bind>` instead. For
52 example, ``cur.execute("SELECT * FROM mytab WHERE mycol = :mybv", mybv=myvar)``.
53
54 .. _fetching:
55
56 Fetch Methods
57 -------------
58
59 After :meth:`Cursor.execute()`, the cursor is returned as a convenience. This
60 allows code to iterate over rows like:
61
62 .. code-block:: python
63
64 cur = connection.cursor()
65 for row in cur.execute("select * from MyTable"):
66 print(row)
67
68 Rows can also be fetched one at a time using the method
69 :meth:`Cursor.fetchone()`:
70
71 .. code-block:: python
72
73 cur = connection.cursor()
74 cur.execute("select * from MyTable")
75 while True:
76 row = cur.fetchone()
77 if row is None:
78 break
79 print(row)
80
81 If rows need to be processed in batches, the method :meth:`Cursor.fetchmany()`
82 can be used. The size of the batch is controlled by the ``numRows`` parameter,
83 which defaults to the value of :attr:`Cursor.arraysize`.
84
85 .. code-block:: python
86
87 cur = connection.cursor()
88 cur.execute("select * from MyTable")
89 numRows = 10
90 while True:
91 rows = cur.fetchmany(numRows)
92 if not rows:
93 break
94 for row in rows:
95 print(row)
96
97 If all of the rows need to be fetched, and can be contained in memory, the
98 method :meth:`Cursor.fetchall()` can be used.
99
100 .. code-block:: python
101
102 cur = connection.cursor()
103 cur.execute("select * from MyTable")
104 rows = cur.fetchall()
105 for row in rows:
106 print(row)
107
108 The fetch methods return data as tuples. To return results as dictionaries, see
109 :ref:`rowfactories`.
110
111 Closing Cursors
112 ---------------
113
114 A cursor may be used to execute multiple statements. Once it is no longer
115 needed, it should be closed by calling :meth:`~Cursor.close()` in order to
116 reclaim resources in the database. It will be closed automatically when the
117 variable referencing it goes out of scope (and no further references are
118 retained). One other way to control the lifetime of a cursor is to use a "with"
119 block, which ensures that a cursor is closed once the block is completed. For
120 example:
121
122 .. code-block:: python
123
124 with connection.cursor() as cursor:
125 for row in cursor.execute("select * from MyTable"):
126 print(row)
127
128 This code ensures that, once the block is completed, the cursor is closed and
129 resources have been reclaimed by the database. In addition, any attempt to use
130 the variable ``cursor`` outside of the block will simply fail.
131
132 .. _querymetadata:
133
134 Query Column Metadata
135 ---------------------
136
137 After executing a query, the column metadata such as column names and data types
138 can be obtained using :attr:`Cursor.description`:
139
140 .. code-block:: python
141
142 cur = connection.cursor()
143 cur.execute("select * from MyTable")
144 for column in cur.description:
145 print(column)
146
147 This could result in metadata like::
148
149 ('ID', <class 'cx_Oracle.DB_TYPE_NUMBER'>, 39, None, 38, 0, 0)
150 ('NAME', <class 'cx_Oracle.DB_TYPE_VARCHAR'>, 20, 20, None, None, 1)
151
152
153 .. _defaultfetchtypes:
154
155 Fetch Data Types
156 ----------------
157
158 The following table provides a list of all of the data types that cx_Oracle
159 knows how to fetch. The middle column gives the type that is returned in the
160 :ref:`query metadata <querymetadata>`. The last column gives the type of
161 Python object that is returned by default. Python types can be changed with
162 :ref:`Output Type Handlers <outputtypehandlers>`.
163
164 .. list-table::
165 :header-rows: 1
166 :widths: 1 1 1
167 :align: left
168
169 * - Oracle Database Type
170 - cx_Oracle Database Type
171 - Default Python type
172 * - BFILE
173 - :attr:`cx_Oracle.DB_TYPE_BFILE`
174 - :ref:`cx_Oracle.LOB <lobobj>`
175 * - BINARY_DOUBLE
176 - :attr:`cx_Oracle.DB_TYPE_BINARY_DOUBLE`
177 - float
178 * - BINARY_FLOAT
179 - :attr:`cx_Oracle.DB_TYPE_BINARY_FLOAT`
180 - float
181 * - BLOB
182 - :attr:`cx_Oracle.DB_TYPE_BLOB`
183 - :ref:`cx_Oracle.LOB <lobobj>`
184 * - CHAR
185 - :attr:`cx_Oracle.DB_TYPE_CHAR`
186 - str
187 * - CLOB
188 - :attr:`cx_Oracle.DB_TYPE_CLOB`
189 - :ref:`cx_Oracle.LOB <lobobj>`
190 * - CURSOR
191 - :attr:`cx_Oracle.DB_TYPE_CURSOR`
192 - :ref:`cx_Oracle.Cursor <cursorobj>`
193 * - DATE
194 - :attr:`cx_Oracle.DB_TYPE_DATE`
195 - datetime.datetime
196 * - INTERVAL DAY TO SECOND
197 - :attr:`cx_Oracle.DB_TYPE_INTERVAL_DS`
198 - datetime.timedelta
199 * - LONG
200 - :attr:`cx_Oracle.DB_TYPE_LONG`
201 - str
202 * - LONG RAW
203 - :attr:`cx_Oracle.DB_TYPE_LONG_RAW`
204 - bytes
205 * - NCHAR
206 - :attr:`cx_Oracle.DB_TYPE_NCHAR`
207 - str
208 * - NCLOB
209 - :attr:`cx_Oracle.DB_TYPE_NCLOB`
210 - :ref:`cx_Oracle.LOB <lobobj>`
211 * - NUMBER
212 - :attr:`cx_Oracle.DB_TYPE_NUMBER`
213 - float or int [1]_
214 * - NVARCHAR2
215 - :attr:`cx_Oracle.DB_TYPE_NVARCHAR`
216 - str
217 * - OBJECT [3]_
218 - :attr:`cx_Oracle.DB_TYPE_OBJECT`
219 - :ref:`cx_Oracle.Object <objecttype>`
220 * - RAW
221 - :attr:`cx_Oracle.DB_TYPE_RAW`
222 - bytes
223 * - ROWID
224 - :attr:`cx_Oracle.DB_TYPE_ROWID`
225 - str
226 * - TIMESTAMP
227 - :attr:`cx_Oracle.DB_TYPE_TIMESTAMP`
228 - datetime.datetime
229 * - TIMESTAMP WITH LOCAL TIME ZONE
230 - :attr:`cx_Oracle.DB_TYPE_TIMESTAMP_LTZ`
231 - datetime.datetime [2]_
232 * - TIMESTAMP WITH TIME ZONE
233 - :attr:`cx_Oracle.DB_TYPE_TIMESTAMP_TZ`
234 - datetime.datetime [2]_
235 * - UROWID
236 - :attr:`cx_Oracle.DB_TYPE_ROWID`
237 - str
238 * - VARCHAR2
239 - :attr:`cx_Oracle.DB_TYPE_VARCHAR`
240 - str
241
242 .. [1] If the precision and scale obtained from query column metadata indicate
243 that the value can be expressed as an integer, the value will be
244 returned as an int. If the column is unconstrained (no precision and
245 scale specified), the value will be returned as a float or an int
246 depending on whether the value itself is an integer. In all other cases
247 the value is returned as a float.
248 .. [2] The timestamps returned are naive timestamps without any time zone
249 information present.
250 .. [3] These include all user-defined types such as VARRAY, NESTED TABLE, etc.
251
252
253 .. _outputtypehandlers:
254
255 Changing Fetched Data Types with Output Type Handlers
256 -----------------------------------------------------
257
258 Sometimes the default conversion from an Oracle Database type to a Python type
259 must be changed in order to prevent data loss or to fit the purposes of the
260 Python application. In such cases, an output type handler can be specified for
261 queries. Output type handlers do not affect values returned from
262 :meth:`Cursor.callfunc()` or :meth:`Cursor.callproc()`.
263
264 Output type handlers can be specified on the :attr:`connection
265 <Connection.outputtypehandler>` or on the :attr:`cursor
266 <Cursor.outputtypehandler>`. If specified on the cursor, fetch type handling is
267 only changed on that particular cursor. If specified on the connection, all
268 cursors created by that connection will have their fetch type handling changed.
269
270 The output type handler is expected to be a function with the following
271 signature::
272
273 handler(cursor, name, defaultType, size, precision, scale)
274
275 The parameters are the same information as the query column metadata found in
276 :attr:`Cursor.description`. The function is called once for each column that is
277 going to be fetched. The function is expected to return a
278 :ref:`variable object <varobj>` (generally by a call to :func:`Cursor.var()`)
279 or the value ``None``. The value ``None`` indicates that the default type
280 should be used.
281
282 Examples of output handlers are shown in :ref:`numberprecision` and
283 :ref:`directlobs`. Also see samples such as `samples/TypeHandlers.py
284 <https://github.com/oracle/python-cx_Oracle/blob/master/samples/TypeHandlers.py>`__
285
286 .. _numberprecision:
287
288 Fetched Number Precision
289 ------------------------
290
291 One reason for using an output type handler is to ensure that numeric precision
292 is not lost when fetching certain numbers. Oracle Database uses decimal numbers
293 and these cannot be converted seamlessly to binary number representations like
294 Python floats. In addition, the range of Oracle numbers exceeds that of
295 floating point numbers. Python has decimal objects which do not have these
296 limitations and cx_Oracle knows how to perform the conversion between Oracle
297 numbers and Python decimal values if directed to do so.
298
299 The following code sample demonstrates the issue:
300
301 .. code-block:: python
302
303 cur = connection.cursor()
304 cur.execute("create table test_float (X number(5, 3))")
305 cur.execute("insert into test_float values (7.1)")
306 connection.commit()
307 cur.execute("select * from test_float")
308 val, = cur.fetchone()
309 print(val, "* 3 =", val * 3)
310
311 This displays ``7.1 * 3 = 21.299999999999997``
312
313 Using Python decimal objects, however, there is no loss of precision:
314
315 .. code-block:: python
316
317 import decimal
318
319 def NumberToDecimal(cursor, name, defaultType, size, precision, scale):
320 if defaultType == cx_Oracle.DB_TYPE_NUMBER:
321 return cursor.var(decimal.Decimal, arraysize=cursor.arraysize)
322
323 cur = connection.cursor()
324 cur.outputtypehandler = NumberToDecimal
325 cur.execute("select * from test_float")
326 val, = cur.fetchone()
327 print(val, "* 3 =", val * 3)
328
329 This displays ``7.1 * 3 = 21.3``
330
331 The Python ``decimal.Decimal`` converter gets called with the string
332 representation of the Oracle number. The output from ``decimal.Decimal`` is
333 returned in the output tuple.
334
335 See `samples/ReturnNumbersAsDecimals.py
336 <https://github.com/oracle/python-cx_Oracle/blob/master/samples/ReturnNumbersAsDecimals.py>`__
337
338
339 .. _outconverters:
340
341 Changing Query Results with Outconverters
342 -----------------------------------------
343
344 cx_Oracle "outconverters" can be used with :ref:`output type handlers
345 <outputtypehandlers>` to change returned data.
346
347 For example, to make queries return empty strings instead of NULLs:
348
349 .. code-block:: python
350
351 def OutConverter(value):
352 if value is None:
353 return ''
354 return value
355
356 def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
357 if defaultType in (cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.DB_TYPE_CHAR):
358 return cursor.var(str, size, cur.arraysize, outconverter=OutConverter)
359
360 connection.outputtypehandler = OutputTypeHandler
361
362
363 .. _rowfactories:
364
365 Changing Query Results with Rowfactories
366 ----------------------------------------
367
368 cx_Oracle "rowfactories" are methods called for each row that is retrieved from
369 the database. The :meth:`Cursor.rowfactory` method is called with the tuple that
370 would normally be returned from the database. The method can convert the tuple
371 to a different value and return it to the application in place of the tuple.
372
373 For example, to fetch each row of a query as a dictionary:
374
375 .. code-block:: python
376
377 cursor.execute("select * from locations where location_id = 1000")
378 columns = [col[0] for col in cursor.description]
379 cursor.rowfactory = lambda *args: dict(zip(columns, args))
380 data = cursor.fetchone()
381 print(data)
382
383 The output is::
384
385 {'LOCATION_ID': 1000, 'STREET_ADDRESS': '1297 Via Cola di Rie', 'POSTAL_CODE': '00989', 'CITY': 'Roma', 'STATE_PROVINCE': None, 'COUNTRY_ID': 'IT'}
386
387 If you join tables where the same column name occurs in both tables with
388 different meanings or values, then use a column alias in the query. Otherwise
389 only one of the similarly named columns will be included in the dictionary:
390
391 .. code-block:: sql
392
393 select
394 cat_name,
395 cats.color as cat_color,
396 dog_name,
397 dogs.color
398 from cats, dogs
399
400 .. _scrollablecursors:
401
402 Scrollable Cursors
403 ------------------
404
405 Scrollable cursors enable applications to move backwards, forwards, to skip
406 rows, and to move to a particular row in a query result set. The result set is
407 cached on the database server until the cursor is closed. In contrast, regular
408 cursors are restricted to moving forward.
409
410 A scrollable cursor is created by setting the parameter ``scrollable=True``
411 when creating the cursor. The method :meth:`Cursor.scroll()` is used to move to
412 different locations in the result set.
413
414 Examples are:
415
416 .. code-block:: python
417
418 cursor = connection.cursor(scrollable=True)
419 cursor.execute("select * from ChildTable order by ChildId")
420
421 cursor.scroll(mode="last")
422 print("LAST ROW:", cursor.fetchone())
423
424 cursor.scroll(mode="first")
425 print("FIRST ROW:", cursor.fetchone())
426
427 cursor.scroll(8, mode="absolute")
428 print("ROW 8:", cursor.fetchone())
429
430 cursor.scroll(6)
431 print("SKIP 6 ROWS:", cursor.fetchone())
432
433 cursor.scroll(-4)
434 print("SKIP BACK 4 ROWS:", cursor.fetchone())
435
436 .. _fetchobjects:
437
438 Fetching Oracle Database Objects and Collections
439 ------------------------------------------------
440
441 Oracle Database named object types and user-defined types can be fetched
442 directly in queries. Each item is represented as a :ref:`Python object
443 <objecttype>` corresponding to the Oracle Database object. This Python object
444 can be traversed to access its elements. Attributes including
445 :attr:`ObjectType.name` and :attr:`ObjectType.iscollection`, and methods
446 including :meth:`Object.aslist` and :meth:`Object.asdict` are available.
447
448 For example, if a table ``mygeometrytab`` contains a column ``geometry`` of
449 Oracle's predefined Spatial object type `SDO_GEOMETRY
450 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-683FF8C5-A773-4018-932D-2AF6EC8BC119>`__,
451 then it can be queried and printed:
452
453 .. code-block:: python
454
455 cur.execute("select geometry from mygeometrytab")
456 for obj, in cur:
457 dumpobject(obj)
458
459 Where ``dumpobject()`` is defined as:
460
461 .. code-block:: python
462
463 def dumpobject(obj, prefix = ""):
464 if obj.type.iscollection:
465 print(prefix, "[")
466 for value in obj.aslist():
467 if isinstance(value, cx_Oracle.Object):
468 dumpobject(value, prefix + " ")
469 else:
470 print(prefix + " ", repr(value))
471 print(prefix, "]")
472 else:
473 print(prefix, "{")
474 for attr in obj.type.attributes:
475 value = getattr(obj, attr.name)
476 if isinstance(value, cx_Oracle.Object):
477 print(prefix + " " + attr.name + ":")
478 dumpobject(value, prefix + " ")
479 else:
480 print(prefix + " " + attr.name + ":", repr(value))
481 print(prefix, "}")
482
483 This might produce output like::
484
485 {
486 SDO_GTYPE: 2003
487 SDO_SRID: None
488 SDO_POINT:
489 {
490 X: 1
491 Y: 2
492 Z: 3
493 }
494 SDO_ELEM_INFO:
495 [
496 1
497 1003
498 3
499 ]
500 SDO_ORDINATES:
501 [
502 1
503 1
504 5
505 7
506 ]
507 }
508
509 Other information on using Oracle objects is in :ref:`Using Bind Variables
510 <bind>`.
511
512 Performance-sensitive applications should consider using scalar types instead of
513 objects. If you do use objects, avoid calling :meth:`Connection.gettype()`
514 unnecessarily, and avoid objects with large numbers of attributes.
515
516 .. _rowlimit:
517
518 Limiting Rows
519 -------------
520
521 Query data is commonly broken into one or more sets:
522
523 - To give an upper bound on the number of rows that a query has to process,
524 which can help improve database scalability.
525
526 - To perform 'Web pagination' that allows moving from one set of rows to a
527 next, or previous, set on demand.
528
529 - For fetching of all data in consecutive small sets for batch processing.
530 This happens because the number of records is too large for Python to handle
531 at one time.
532
533 The latter can be handled by calling :meth:`Cursor.fetchmany()` with one
534 execution of the SQL query.
535
536 'Web pagination' and limiting the maximum number of rows are discussed in this
537 section. For each 'page' of results, a SQL query is executed to get the
538 appropriate set of rows from a table. Since the query may be executed more
539 than once, make sure to use :ref:`bind variables <bind>` for row numbers and
540 row limits.
541
542 Oracle Database 12c SQL introduced an ``OFFSET`` / ``FETCH`` clause which is
543 similar to the ``LIMIT`` keyword of MySQL. In Python you can fetch a set of
544 rows using:
545
546 .. code-block:: python
547
548 myoffset = 0 // do not skip any rows (start at row 1)
549 mymaxnumrows = 20 // get 20 rows
550
551 sql =
552 """SELECT last_name
553 FROM employees
554 ORDER BY last_name
555 OFFSET :offset ROWS FETCH NEXT :maxnumrows ROWS ONLY"""
556
557 cur = connection.cursor()
558 for row in cur.execute(sql, offset=myoffset, maxnumrows=mymaxnumrows):
559 print(row)
560
561 In applications where the SQL query is not known in advance, this method
562 sometimes involves appending the ``OFFSET`` clause to the 'real' user query. Be
563 very careful to avoid SQL injection security issues.
564
565 For Oracle Database 11g and earlier there are several alternative ways
566 to limit the number of rows returned. The old, canonical paging query
567 is::
568
569 SELECT *
570 FROM (SELECT a.*, ROWNUM AS rnum
571 FROM (YOUR_QUERY_GOES_HERE -- including the order by) a
572 WHERE ROWNUM <= MAX_ROW)
573 WHERE rnum >= MIN_ROW
574
575 Here, ``MIN_ROW`` is the row number of first row and ``MAX_ROW`` is the row
576 number of the last row to return. For example::
577
578 SELECT *
579 FROM (SELECT a.*, ROWNUM AS rnum
580 FROM (SELECT last_name FROM employees ORDER BY last_name) a
581 WHERE ROWNUM <= 20)
582 WHERE rnum >= 1
583
584 This always has an 'extra' column, here called RNUM.
585
586 An alternative and preferred query syntax for Oracle Database 11g uses the
587 analytic ``ROW_NUMBER()`` function. For example to get the 1st to 20th names the
588 query is::
589
590 SELECT last_name FROM
591 (SELECT last_name,
592 ROW_NUMBER() OVER (ORDER BY last_name) AS myr
593 FROM employees)
594 WHERE myr BETWEEN 1 and 20
595
596 Make sure to use :ref:`bind variables <bind>` for the upper and lower limit
597 values.
598
599 .. _crc:
600
601 Client Result Cache
602 -------------------
603
604 Python cx_Oracle applications can use Oracle Database's `Client Result Cache
605 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-35CB2592-7588-4C2D-9075-6F639F25425E>`__
606 The CRC enables client-side caching of SQL query (SELECT statement) results in
607 client memory for immediate use when the same query is re-executed. This is
608 useful for reducing the cost of queries for small, mostly static, lookup tables,
609 such as for postal codes. CRC reduces network :ref:`round-trips <roundtrips>`,
610 and also reduces database server CPU usage.
611
612 The cache is at the application process level. Access and invalidation is
613 managed by the Oracle Client libraries. This removes the need for extra
614 application logic, or external utilities, to implement a cache.
615
616 CRC can be enabled by setting the `database parameters
617 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-A9D4A5F5-B939-48FF-80AE-0228E7314C7D>`__
618 ``CLIENT_RESULT_CACHE_SIZE`` and ``CLIENT_RESULT_CACHE_LAG``, and then
619 restarting the database. For example, to set the parameters:
620
621 .. code-block:: sql
622
623 SQL> ALTER SYSTEM SET CLIENT_RESULT_CACHE_LAG = 3000 SCOPE=SPFILE;
624 SQL> ALTER SYSTEM SET CLIENT_RESULT_CACHE_SIZE = 64K SCOPE=SPFILE;
625
626 CRC can alternatively be configured in an :ref:`oraaccess.xml <optclientfiles>`
627 or :ref:`sqlnet.ora <optnetfiles>` file on the Python host, see `Client
628 Configuration Parameters
629 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-E63D75A1-FCAA-4A54-A3D2-B068442CE766>`__.
630
631 Tables can then be created, or altered, so repeated queries use CRC. This
632 allows existing applications to use CRC without needing modification. For example:
633
634 .. code-block:: sql
635
636 SQL> CREATE TABLE cities (id number, name varchar2(40)) RESULT_CACHE (MODE FORCE);
637 SQL> ALTER TABLE locations RESULT_CACHE (MODE FORCE);
638
639 Alternatively, hints can be used in SQL statements. For example:
640
641 .. code-block:: sql
642
643 SELECT /*+ result_cache */ postal_code FROM locations
644
645 .. _codecerror:
646
647 Querying Corrupt Data
648 ---------------------
649
650 If queries fail with the error "codec can't decode byte" when you select data,
651 then:
652
653 * Check your :ref:`character set <globalization>` is correct. Review the
654 :ref:`client and database character sets <findingcharset>`. Consider using
655 UTF-8, if this is appropriate:
656
657 .. code-block:: python
658
659 connection = cx_Oracle.connect("hr", userpwd, "dbhost.example.com/orclpdb1",
660 encoding="UTF-8", nencoding="UTF-8")
661
662 * Check for corrupt data in the database.
663
664 If data really is corrupt, you can pass options to the internal `decode()
665 <https://docs.python.org/3/library/stdtypes.html#bytes.decode>`__ used by
666 cx_Oracle to allow it to be selected and prevent the whole query failing. Do
667 this by creating an :ref:`outputtypehandler <outputtypehandlers>` and setting
668 ``encodingErrors``. For example to replace corrupt characters in character
669 columns:
670
671 .. code-block:: python
672
673 def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
674 if defaultType == cx_Oracle.STRING:
675 return cursor.var(defaultType, size, arraysize=cursor.arraysize,
676 encodingErrors="replace")
677
678 cursor.outputtypehandler = OutputTypeHandler
679
680 cursor.execute("select column1, column2 from SomeTableWithBadData")
681
682 Other codec behaviors can be chosen for ``encodingErrors``, see `Error Handlers
683 <https://docs.python.org/3/library/codecs.html#error-handlers>`__.
684
685 .. _dml:
686
687
688 INSERT and UPDATE Statements
689 ============================
690
691 SQL Data Manipulation Language statements (DML) such as INSERT and UPDATE can
692 easily be executed with cx_Oracle. For example:
693
694 .. code-block:: python
695
696 cur = connection.cursor()
697 cur.execute("insert into MyTable values (:idbv, :nmbv)", [1, "Fredico"])
698
699 Do not concatenate or interpolate user data into SQL statements. See
700 :ref:`bind` instead.
701
702 See :ref:`txnmgmnt` for best practices on committing and rolling back data
703 changes.
704
705 When handling multiple data values, use :meth:`~Cursor.executemany()` for
706 performance. See :ref:`batchstmnt`
707
708
709 Inserting NULLs
710 ---------------
711
712 Oracle requires a type, even for null values. When you pass the value None, then
713 cx_Oracle assumes the type is STRING. If this is not the desired type, you can
714 explicitly set it. For example, to insert a null :ref:`Oracle Spatial
715 SDO_GEOMETRY <spatial>` object:
716
717 .. code-block:: python
718
719 typeObj = connection.gettype("SDO_GEOMETRY")
720 cur = connection.cursor()
721 cur.setinputsizes(typeObj)
722 cur.execute("insert into sometable values (:1)", [None])
0 .. _startup:
1
2 *************************************
3 Starting and Stopping Oracle Database
4 *************************************
5
6 This chapter covers how to start up and shutdown Oracle Database using
7 cx_Oracle.
8
9 ===========================
10 Starting Oracle Database Up
11 ===========================
12
13 cx_Oracle can start up a database instance. A privileged connection is
14 required. This example shows a script that could be run as the 'oracle'
15 operating system user who administers a local database installation on Linux.
16 It assumes that the environment variable ``ORACLE_SID`` has been set to the SID
17 of the database that should be started:
18
19 .. code-block:: python
20
21 # the connection must be in PRELIM_AUTH mode to perform startup
22 connection = cx_Oracle.connect("/",
23 mode = cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH)
24 connection.startup()
25
26 # the following statements must be issued in normal SYSDBA mode
27 connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA, encoding="UTF-8")
28 cursor = connection.cursor()
29 cursor.execute("alter database mount")
30 cursor.execute("alter database open")
31
32 To start up a remote database, you may need to configure the Oracle Net
33 listener to use `static service registration
34 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
35 id=GUID-0203C8FA-A4BE-44A5-9A25-3D1E578E879F>`_
36 by adding a ``SID_LIST_LISTENER`` entry to the database `listener.ora` file.
37
38
39 =============================
40 Shutting Oracle Database Down
41 =============================
42
43 cx_Oracle has the ability to shutdown the database using a privileged
44 connection. This example also assumes that the environment variable
45 ``ORACLE_SID`` has been set:
46
47 .. code-block:: python
48
49 # need to connect as SYSDBA or SYSOPER
50 connection = cx_Oracle.connect("/", mode = cx_Oracle.SYSDBA)
51
52 # first shutdown() call must specify the mode, if DBSHUTDOWN_ABORT is used,
53 # there is no need for any of the other steps
54 connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_IMMEDIATE)
55
56 # now close and dismount the database
57 cursor = connection.cursor()
58 cursor.execute("alter database close normal")
59 cursor.execute("alter database dismount")
60
61 # perform the final shutdown call
62 connection.shutdown(mode = cx_Oracle.DBSHUTDOWN_FINAL)
0 .. _tracingsql:
1
2 *********************************
3 Tracing SQL and PL/SQL Statements
4 *********************************
5
6 Subclass Connections
7 ====================
8
9 Subclassing enables applications to add "hooks" for connection and statement
10 execution. This can be used to alter, or log, connection and execution
11 parameters, and to extend cx_Oracle functionality.
12
13 The example below demonstrates subclassing a connection to log SQL execution
14 to a file. This example also shows how connection credentials can be embedded
15 in the custom subclass, so application code does not need to supply them.
16
17 .. code-block:: python
18
19 class Connection(cx_Oracle.Connection):
20 logFileName = "log.txt"
21
22 def __init__(self):
23 connectString = "hr/[email protected]/orclpdb1"
24 self._log("Connect to the database")
25 return super(Connection, self).__init__(connectString)
26
27 def _log(self, message):
28 with open(self.logFileName, "a") as f:
29 print(message, file=f)
30
31 def execute(self, sql, parameters):
32 self._log(sql)
33 cursor = self.cursor()
34 try:
35 return cursor.execute(sql, parameters)
36 except cx_Oracle.Error as e:
37 errorObj, = e.args
38 self._log(errorObj.message)
39
40 connection = Connection()
41 connection.execute("""
42 select department_name
43 from departments
44 where department_id = :id""", dict(id=270))
45
46 The messages logged in ``log.txt`` are::
47
48 Connect to the database
49
50 select department_name
51 from departments
52 where department_id = :id
53
54 If an error occurs, perhaps due to a missing table, the log file would contain
55 instead::
56
57 Connect to the database
58
59 select department_name
60 from departments
61 where department_id = :id
62 ORA-00942: table or view does not exist
63
64 In production applications be careful not to log sensitive information.
65
66 See `Subclassing.py
67 <https://github.com/oracle/python-cx_Oracle/blob/master/
68 samples/Subclassing.py>`__ for an example.
69
70
71 .. _endtoendtracing:
72
73 Oracle Database End-to-End Tracing
74 ==================================
75
76 Oracle Database End-to-end application tracing simplifies diagnosing application
77 code flow and performance problems in multi-tier or multi-user environments.
78
79 The connection attributes, :attr:`~Connection.client_identifier`,
80 :attr:`~Connection.clientinfo`, :attr:`~Connection.dbop`,
81 :attr:`~Connection.module` and :attr:`~Connection.action`, set the metadata for
82 end-to-end tracing. You can use data dictionary and ``V$`` views to monitor
83 tracing or use other application tracing utilities.
84
85 The attributes are sent to the database when the next :ref:`round-trip
86 <roundtrips>` to the database occurs, for example when the next SQL statement is
87 executed.
88
89 The attribute values will remain set in connections released back to connection
90 pools. When the application re-acquires a connection from the pool it should
91 initialize the values to a desired state before using that connection.
92
93 The example below shows setting the action, module and client identifier
94 attributes on the connection object:
95
96 .. code-block:: python
97
98 # Set the tracing metadata
99 connection.client_identifier = "pythonuser"
100 connection.action = "Query Session tracing parameters"
101 connection.module = "End-to-end Demo"
102
103 for row in cursor.execute("""
104 SELECT username, client_identifier, module, action
105 FROM V$SESSION
106 WHERE username = 'SYSTEM'"""):
107 print(row)
108
109 The output will be::
110
111 ('SYSTEM', 'pythonuser', 'End-to-end Demo', 'Query Session tracing parameters')
112
113 The values can also be manually set as shown by calling
114 `DBMS_APPLICATION_INFO procedures
115 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
116 id=GUID-14484F86-44F2-4B34-B34E-0C873D323EAD>`__
117 or `DBMS_SESSION.SET_IDENTIFIER
118 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&
119 id=GUID-988EA930-BDFE-4205-A806-E54F05333562>`__. These incur round-trips to
120 the database, however, reducing scalability.
121
122 .. code-block:: sql
123
124 BEGIN
125 DBMS_SESSION.SET_IDENTIFIER('pythonuser');
126 DBMS_APPLICATION_INFO.set_module('End-to-End Demo');
127 DBMS_APPLICATION_INFO.set_action(action_name => 'Query Session tracing parameters');
128 END;
129
130
131 Low Level SQL Tracing in cx_Oracle
132 ==================================
133
134 cx_Oracle is implemented using the `ODPI-C <https://oracle.github.io/odpi>`__
135 wrapper on top of the Oracle Client libraries. The ODPI-C tracing capability
136 can be used to log executed cx_Oracle statements to the standard error stream.
137 Before executing Python, set the environment variable ``DPI_DEBUG_LEVEL`` to
138 16.
139
140 At a Windows command prompt, this could be done with::
141
142 set DPI_DEBUG_LEVEL=16
143
144 On Linux, you might use::
145
146 export DPI_DEBUG_LEVEL=16
147
148 After setting the variable, run the Python Script, for example on Linux::
149
150 python end-to-endtracing.py 2> log.txt
151
152 For an application that does a single query, the log file might contain a
153 tracing line consisting of the prefix 'ODPI', a thread identifier, a timestamp,
154 and the SQL statement executed::
155
156 ODPI [26188] 2019-03-26 09:09:03.909: ODPI-C 3.1.1
157 ODPI [26188] 2019-03-26 09:09:03.909: debugging messages initialized at level 16
158 ODPI [26188] 2019-03-26 09:09:09.917: SQL SELECT * FROM jobss
159 Traceback (most recent call last):
160 File "end-to-endtracing.py", line 14, in <module>
161 cursor.execute("select * from jobss")
162 cx_Oracle.DatabaseError: ORA-00942: table or view does not exist
163
164 See `ODPI-C Debugging
165 <https://oracle.github.io/odpi/doc/user_guide/debugging.html>`__ for
166 documentation on ``DPI_DEBUG_LEVEL``.
0 .. _tuning:
1
2 ****************
3 Tuning cx_Oracle
4 ****************
5
6 Some general tuning tips are:
7
8 * Tune your application architecture.
9
10 A general application goal is to reduce the number of :ref:`round-trips
11 <roundtrips>` between cx_Oracle and the database.
12
13 For multi-user applications, make use of connection pooling. Create the pool
14 once during application initialization. Do not oversize the pool, see
15 :ref:`connpool` . Use a session callback function to set session state, see
16 :ref:`Session CallBacks for Setting Pooled Connection State <sessioncallback>`.
17
18 Make use of efficient cx_Oracle functions. For example, to insert
19 multiple rows use :meth:`Cursor.executemany()` instead of
20 :meth:`Cursor.execute()`.
21
22 * Tune your SQL statements. See the `SQL Tuning Guide
23 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=TGSQL>`__.
24
25 Use :ref:`bind variables <bind>` to avoid statement reparsing.
26
27 Tune :attr:`Cursor.arraysize` and :attr:`Cursor.prefetchrows` for each query,
28 see :ref:`Tuning Fetch Performance <tuningfetch>`.
29
30 Do simple optimizations like :ref:`limiting the number of rows <rowlimit>` and
31 avoiding selecting columns not used in the application.
32
33 It may be faster to work with simple scalar relational values than to use
34 Oracle Database object types.
35
36 Make good use of PL/SQL to avoid executing many individual statements from
37 cx_Oracle.
38
39 Tune the :ref:`Statement Cache <stmtcache>`.
40
41 Enable :ref:`Client Result Caching <clientresultcache>` for small lookup tables.
42
43 * Tune your database. See the `Database Performance Tuning Guide
44 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=TGDBA>`__.
45
46 * Tune your network. For example, when inserting or retrieving a large number
47 of rows (or for large data), or when using a slow network, then tune the
48 Oracle Network Session Data Unit (SDU) and socket buffer sizes, see `Oracle
49 Net Services: Best Practices for Database Performance and High Availability
50 <https://static.rainfocus.com/oracle/oow19/sess/1553616880266001WLIh/PF/OOW19_Net_CON4641_1569022126580001esUl.pdf>`__.
51
52 * Do not commit or rollback unnecessarily. Use :attr:`Connection.autocommit` on
53 the last of a sequence of DML statements.
54
55 .. _tuningfetch:
56
57 Tuning Fetch Performance
58 ========================
59
60 To tune queries you can adjust cx_Oracle's internal buffer sizes to improve the
61 speed of fetching rows across the network from the database, and to optimize
62 memory usage. Regardless of which cx_Oracle method is used to get query
63 results, internally all rows are fetched in batches from the database and
64 buffered before being returned to the application. The internal buffer sizes
65 can have a significant performance impact. The sizes do not affect how, or
66 when, rows are returned to your application. They do not affect the minimum or
67 maximum number of rows returned by a query.
68
69 For best performance, tune "array fetching" with :attr:`Cursor.arraysize` and
70 "row prefetching" with :attr:`Cursor.prefetchrows` before calling
71 :meth:`Cursor.execute()`. Queries that return LOBs and similar types will never
72 prefetch rows, so the ``prefetchrows`` value is ignored in those cases.
73
74 The common query tuning scenario is for SELECT statements that return a large
75 number of rows over a slow network. Increasing ``arraysize`` can improve
76 performance by reducing the number of :ref:`round-trips <roundtrips>` to the
77 database. However increasing this value increases the amount of memory
78 required. Adjusting ``prefetchrows`` will also affect performance and memory
79 usage.
80
81 Row prefetching and array fetching are both internal buffering techniques to
82 reduce :ref:`round-trips <roundtrips>` to the database. The difference is the
83 code layer that is doing the buffering, and when the buffering occurs. The
84 Oracle Client libraries used by cx_Oracle have separate "execute SQL statement"
85 and "fetch data" calls. Prefetching allows query results to be returned to the
86 application when the successful statement execution acknowledgment is returned
87 from the database. This means that a subsequent internal "fetch data" operation
88 does not always need to make a round-trip to the database because rows are
89 already buffered in the Oracle Client libraries. Reducing round-trips helps
90 performance and scalability. An overhead of prefetching is the need for an
91 additional data copy from Oracle Client's prefetch buffers.
92
93 Choosing values for ``arraysize`` and ``prefetchrows``
94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
95
96 The best :attr:`Cursor.arraysize` and :attr:`Cursor.prefetchrows` values can be
97 found by experimenting with your application under the expected load of normal
98 application use. This is because the cost of the extra memory copy from the
99 prefetch buffers when fetching a large quantity of rows or very "wide" rows may
100 outweigh the cost of a round-trip for a single cx_Oracle user on a fast network.
101 However under production application load, the reduction of round-trips may help
102 performance and overall system scalability. The documentation in
103 :ref:`round-trips <roundtrips>` shows how to measure round-trips.
104
105 Here are some suggestions for the starting point to begin your tuning:
106
107 * To tune queries that return an unknown number of rows, estimate the number of
108 rows returned and start with an appropriate :attr:`Cursor.arraysize` value.
109 The default is 100. Then set :attr:`Cursor.prefetchrows` to the ``arraysize``
110 value. Do not make the sizes unnecessarily large. For example:
111
112 .. code-block:: python
113
114 cur = connection.cursor()
115
116 cur.prefetchrows = 1000
117 cur.arraysize = 1000
118
119 for row in cur.execute("SELECT * FROM very_big_table"):
120 print(row)
121
122 Adjust the values as needed for performance, memory and round-trip usage. For
123 a large quantity of rows or very "wide" rows on fast networks you may prefer
124 to leave ``prefetchrows`` at its default value of 2. Keep ``arraysize`` as
125 big, or bigger than, ``prefetchrows``.
126
127 * If you are fetching a fixed number of rows, start your tuning by setting
128 ``arraysize`` to the number of expected rows, and set ``prefetchrows`` to one
129 greater than this value. (Adding one removes the need for a round-trip to check
130 for end-of-fetch). For example, if you are querying 20 rows, perhaps to
131 :ref:`display a page <rowlimit>` of data, set ``prefetchrows`` to 21 and
132 ``arraysize`` to 20:
133
134 .. code-block:: python
135
136 cur = connection.cursor()
137
138 cur.prefetchrows = 21
139 cur.arraysize = 20
140
141 for row in cur.execute("""
142 SELECT last_name
143 FROM employees
144 ORDER BY last_name
145 OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY"""):
146 print(row)
147
148 This will return all rows for the query in one round-trip.
149
150 * If you know that a query returns just one row then set :attr:`Cursor.arraysize`
151 to 1 to minimize memory usage. The default prefetch value of 2 allows minimal
152 round-trips for single-row queries:
153
154 .. code-block:: python
155
156 cur = connection.cursor()
157 cur.arraysize = 1
158 cur.execute("select * from MyTable where id = 1"):
159 row = cur.fetchone()
160 print(row)
161
162 In cx_Oracle, the ``arraysize`` and ``prefetchrows`` values are only examined
163 when a statement is executed the first time. To change the values, create a new
164 cursor. For example, to change ``arraysize`` for a repeated statement:
165
166 .. code-block:: python
167
168 array_sizes = (10, 100, 1000)
169 for size in array_sizes:
170 cursor = connection.cursor()
171 cursor.arraysize = size
172 start = time.time()
173 cursor.execute(sql).fetchall()
174 elapsed = time.time() - start
175 print("Time for", size, elapsed, "seconds")
176
177 There are two cases that will benefit from setting :attr:`Cursor.prefetchrows`
178 to 0:
179
180 * When passing REF CURSORS into PL/SQL packages. Setting ``prefetchrows`` to 0
181 can stop rows being prematurely (and silently) fetched into cx_Oracle's
182 internal buffers, making them unavailable to the PL/SQL code that receives the
183 REF CURSOR.
184
185 * When querying a PL/SQL function that uses PIPE ROW to emit rows at
186 intermittent intervals. By default, several rows needs to be emitted by the
187 function before cx_Oracle can return them to the application. Setting
188 ``prefetchrows`` to 0 helps give a consistent flow of data to the application.
189
190 Prefetching can also be enabled in an external :ref:`oraaccess.xml
191 <optclientfiles>` file, which may be useful for tuning an application when
192 modifying its code is not feasible. Setting the size in ``oraaccess.xml`` will
193 affect the whole application, so it should not be the first tuning choice.
194
195 One place where increasing ``arraysize`` is particularly useful is in copying
196 data from one database to another:
197
198 .. code-block:: python
199
200 # setup cursors
201 sourceCursor = sourceConnection.cursor()
202 sourceCursor.arraysize = 1000
203 targetCursor = targetConnection.cursor()
204
205 # perform fetch and bulk insertion
206 sourceCursor.execute("select * from MyTable")
207 while True:
208 rows = sourceCursor.fetchmany()
209 if not rows:
210 break
211 targetCursor.executemany("insert into MyTable values (:1, :2)", rows)
212 targetConnection.commit()
213
214 .. _roundtrips:
215
216 Database Round-trips
217 ====================
218
219 A round-trip is defined as the trip from the Oracle Client libraries (used by
220 cx_Oracle) to the database and back. Calling each cx_Oracle function, or
221 accessing each attribute, will require zero or more round-trips. Along with
222 tuning an application's architecture and `tuning its SQL statements
223 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=TGSQL>`__, a general
224 performance and scalability goal is to minimize `round-trips
225 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-9B2F05F9-D841-4493-A42D-A7D89694A2D1>`__.
226
227 Some general tips for reducing round-trips are:
228
229 * Tune :attr:`Cursor.arraysize` and :attr:`Cursor.prefetchrows` for each query.
230 * Use :meth:`Cursor.executemany()` for optimal DML execution.
231 * Only commit when necessary. Use :attr:`Connection.autocommit` on the last statement of a transaction.
232 * For connection pools, use a callback to set connection state, see :ref:`Session CallBacks for Setting Pooled Connection State <sessioncallback>`.
233 * Make use of PL/SQL procedures which execute multiple SQL statements instead of executing them individually from cx_Oracle.
234 * Use scalar types instead of Oracle Database object types.
235 * Avoid overuse of :meth:`Connection.ping()`.
236
237 Finding the Number of Round-Trips
238 +++++++++++++++++++++++++++++++++
239
240 Oracle's `Automatic Workload Repository
241 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-56AEF38E-9400-427B-A818-EDEC145F7ACD>`__
242 (AWR) reports show 'SQL*Net roundtrips to/from client' and are useful for
243 finding the overall behavior of a system.
244
245 Sometimes you may wish to find the number of round-trips used for a
246 specific application. Snapshots of the ``V$SESSTAT`` view taken before
247 and after doing some work can be used for this:
248
249 .. code-block:: sql
250
251 SELECT ss.value, sn.display_name
252 FROM v$sesstat ss, v$statname sn
253 WHERE ss.sid = SYS_CONTEXT('USERENV','SID')
254 AND ss.statistic# = sn.statistic#
255 AND sn.name LIKE '%roundtrip%client%';
256
257 .. _stmtcache:
258
259 Statement Caching
260 =================
261
262 cx_Oracle's :meth:`Cursor.execute()` and :meth:`Cursor.executemany()` functions
263 use the `Oracle Call Interface statement cache
264 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-4947CAE8-1F00-4897-BB2B-7F921E495175>`__
265 to make re-execution of statements efficient. Each standalone or pooled
266 connection has its own cache of statements with a default size of 20. Statement
267 caching lets cursors be used without re-parsing the statement. Statement
268 caching also reduces metadata transfer costs between the cx_Oracle and the
269 database. Performance and scalability are improved.
270
271 The statement cache size can be set with :attr:`Connection.stmtcachesize` or
272 :attr:`SessionPool.stmtcachesize`. In general, set the statement cache size to
273 the size of the working set of statements being executed by the application. To
274 manually tune the cache, monitor the general application load and the `Automatic
275 Workload Repository
276 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-56AEF38E-9400-427B-A818-EDEC145F7ACD>`__
277 (AWR) "bytes sent via SQL*Net to client" values. The latter statistic should
278 benefit from not shipping statement metadata to cx_Oracle. Adjust the statement
279 cache size to your satisfaction.
280
281 Statement caching can be disabled by setting the size to 0. Disabling
282 the cache may be beneficial when the quantity or order of statements
283 causes cache entries to be flushed before they get a chance to be
284 reused. For example if there are more distinct statements than cache
285 slots, and the order of statement execution causes older statements to
286 be flushed from the cache before the statements are re-executed.
287
288 With Oracle Database 12c, or later, the statement cache size can be
289 automatically tuned using the :ref:`oraaccess.xml <optclientfiles>` file.
290
291 When it is inconvenient to pass statement text through an application, the
292 :meth:`Cursor.prepare()` call can be used to avoid statement re-parsing.
293 Subsequent ``execute()`` calls use the value ``None`` instead of the SQL text:
294
295 .. code-block:: python
296
297 cur.prepare("select * from dept where deptno = :id order by deptno")
298
299 cur.execute(None, id = 20)
300 res = cur.fetchall()
301 print(res)
302
303 cur.execute(None, id = 10)
304 res = cur.fetchall()
305 print(res)
306
307 Statements passed to :meth:`~Cursor.prepare()` are also stored in the statement
308 cache.
309
310 .. _clientresultcache:
311
312 Client Result Caching
313 =====================
314
315 cx_Oracle applications can use Oracle Database's `Client Result Cache
316 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-35CB2592-7588-4C2D-9075-6F639F25425E>`__.
317 The CRC enables client-side caching of SQL query (SELECT statement) results in
318 client memory for immediate use when the same query is re-executed. This is
319 useful for reducing the cost of queries for small, mostly static, lookup tables,
320 such as for postal codes. CRC reduces network :ref:`round-trips <roundtrips>`,
321 and also reduces database server CPU usage.
322
323 The cache is at the application process level. Access and invalidation is
324 managed by the Oracle Client libraries. This removes the need for extra
325 application logic, or external utilities, to implement a cache.
326
327 CRC can be enabled by setting the `database parameters
328 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-A9D4A5F5-B939-48FF-80AE-0228E7314C7D>`__
329 ``CLIENT_RESULT_CACHE_SIZE`` and ``CLIENT_RESULT_CACHE_LAG``, and then
330 restarting the database, for example:
331
332 .. code-block:: sql
333
334 SQL> ALTER SYSTEM SET CLIENT_RESULT_CACHE_LAG = 3000 SCOPE=SPFILE;
335 SQL> ALTER SYSTEM SET CLIENT_RESULT_CACHE_SIZE = 64K SCOPE=SPFILE;
336 SQL> STARTUP FORCE
337
338 CRC can alternatively be configured in an :ref:`oraaccess.xml <optclientfiles>`
339 or :ref:`sqlnet.ora <optnetfiles>` file on the Python host, see `Client
340 Configuration Parameters
341 <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-E63D75A1-FCAA-4A54-A3D2-B068442CE766>`__.
342
343 Tables can then be created, or altered, so repeated queries use CRC. This
344 allows existing applications to use CRC without needing modification. For example:
345
346 .. code-block:: sql
347
348 SQL> CREATE TABLE cities (id number, name varchar2(40)) RESULT_CACHE (MODE FORCE);
349 SQL> ALTER TABLE locations RESULT_CACHE (MODE FORCE);
350
351 Alternatively, hints can be used in SQL statements. For example:
352
353 .. code-block:: sql
354
355 SELECT /*+ result_cache */ postal_code FROM locations
0 .. _txnmgmnt:
1
2 **********************
3 Transaction Management
4 **********************
5
6 A database transaction is a grouping of SQL statements that make a logical data
7 change to the database.
8
9 When :meth:`Cursor.execute()` executes a SQL statement, a transaction is
10 started or continued. By default, cx_Oracle does not commit this transaction
11 to the database. The methods :meth:`Connection.commit()` and
12 :meth:`Connection.rollback()` methods can be used to explicitly commit
13 or rollback a transaction:
14
15 .. code-block:: python
16
17 cursor.execute("INSERT INTO mytab (name) VALUES ('John')")
18 connection.commit()
19
20 When a database connection is closed, such as with :meth:`Connection.close()`,
21 or when variables referencing the connection go out of scope, any uncommitted
22 transaction will be rolled back.
23
24
25 Autocommitting
26 ==============
27
28 An alternative way to commit is to set the attribute
29 :attr:`~Connection.autocommit` of the connection to ``True``. This ensures all
30 :ref:`DML <dml>` statements (INSERT, UPDATE etc) are committed as they are
31 executed. Unlike :meth:`Connection.commit()`, this does not require an
32 additional :ref:`round-trip <roundtrips>` to the database so it is more
33 efficient when used appropriately.
34
35 Note that irrespective of the autocommit value, Oracle Database will always
36 commit an open transaction when a DDL statement is executed.
37
38 When executing multiple DML statements that constitute a single transaction, it
39 is recommended to use autocommit mode only for the last DML statement in the
40 sequence of operations. Unnecessarily committing causes extra database load,
41 and can destroy transactional consistency.
42
43 The example below shows a new customer being added to the table ``CUST_TABLE``.
44 The corresponding ``SALES`` table is updated with a purchase of 3000 pens from
45 the customer. The final insert uses autocommit mode to commit both new
46 records:
47
48 .. code-block:: python
49
50 # Add a new customer
51 idVar = cursor.var(int)
52 connection.autocommit = False # make sure any previous value is off
53 cursor.execute("""
54 INSERT INTO cust_table (name) VALUES ('John')
55 RETURNING id INTO :bvid""", bvid=idVar)
56
57 # Add sales data for the new customer and commit all new values
58 idVal = idVar.getvalue()[0]
59 connection.autocommit = True
60 cursor.execute("INSERT INTO sales_table VALUES (:bvid, 'pens', 3000)",
61 bvid=idVal)
62
63
64 Explicit Transactions
65 =====================
66
67 The method :meth:`Connection.begin()` can be used to explicitly start a local
68 or global transaction.
69
70 Without parameters, this explicitly begins a local transaction; otherwise, this
71 explicitly begins a distributed (global) transaction with the given parameters.
72 See the Oracle documentation for more details.
73
74 Note that in order to make use of global (distributed) transactions, the
75 attributes :attr:`Connection.internal_name` and
76 :attr:`Connection.external_name` attributes must be set.
0 .. _xmldatatype:
1
2 ********************
3 Working with XMLTYPE
4 ********************
5
6 Oracle XMLType columns are fetched as strings by default. This is currently
7 limited to the maximum length of a ``VARCHAR2`` column. To return longer XML
8 values, they must be queried as LOB values instead.
9
10 The examples below demonstrate using XMLType data with cx_Oracle. The
11 following table will be used in these examples:
12
13 .. code-block:: sql
14
15 CREATE TABLE xml_table (
16 id NUMBER,
17 xml_data SYS.XMLTYPE
18 );
19
20 Inserting into the table can be done by simply binding a string as shown:
21
22 .. code-block:: python
23
24 xmlData = """<?xml version="1.0"?>
25 <customer>
26 <name>John Smith</name>
27 <Age>43</Age>
28 <Designation>Professor</Designation>
29 <Subject>Mathematics</Subject>
30 </customer>"""
31 cursor.execute("insert into xml_table values (:id, :xml)",
32 id=1, xml=xmlData)
33
34 This approach works with XML strings up to 1 GB in size. For longer strings, a
35 temporary CLOB must be created using :meth:`Connection.createlob()` and bound
36 as shown:
37
38 .. code-block:: python
39
40 clob = connection.createlob(cx_Oracle.DB_TYPE_CLOB)
41 clob.write(xmlData)
42 cursor.execute("insert into xml_table values (:id, sys.xmltype(:xml))",
43 id=2, xml=clob)
44
45 Fetching XML data can be done simply for values that are shorter than the
46 length of a VARCHAR2 column, as shown:
47
48 .. code-block:: python
49
50 cursor.execute("select xml_data from xml_table where id = :id", id=1)
51 xmlData, = cursor.fetchone()
52 print(xmlData) # will print the string that was originally stored
53
54 For values that exceed the length of a VARCHAR2 column, a CLOB must be returned
55 instead by using the function ``XMLTYPE.GETCLOBVAL()`` as shown:
56
57 .. code-block:: python
58
59 cursor.execute("""
60 select xmltype.getclobval(xml_data)
61 from xml_table
62 where id = :id""", id=1)
63 clob, = cursor.fetchone()
64 print(clob.read())
65
66 The LOB that is returned can be streamed or a string can be returned instead of
67 a CLOB. See :ref:`lobdata` for more information about processing LOBs.
+0
-84
doc/src/variable.rst less more
0 .. _varobj:
1
2 ****************
3 Variable Objects
4 ****************
5
6 .. note::
7
8 The DB API definition does not define this object.
9
10
11 .. attribute:: Variable.actualElements
12
13 This read-only attribute returns the actual number of elements in the
14 variable. This corresponds to the number of elements in a PL/SQL index-by
15 table for variables that are created using the method
16 :func:`Cursor.arrayvar()`. For all other variables this value will be
17 identical to the attribute :attr:`~Variable.numElements`.
18
19 .. attribute:: Variable.bufferSize
20
21 This read-only attribute returns the size of the buffer allocated for each
22 element in bytes.
23
24
25 .. method:: Variable.getvalue([pos=0])
26
27 Return the value at the given position in the variable. For variables
28 created using the method :func:`Cursor.arrayvar()` the value returned will
29 be a list of each of the values in the PL/SQL index-by table. For variables
30 bound to DML returning statements, the value returned will also be a list
31 corresponding to the returned data for the given execution of the statement
32 (as identified by the pos parameter).
33
34
35 .. attribute:: Variable.inconverter
36
37 This read-write attribute specifies the method used to convert data from
38 Python to the Oracle database. The method signature is converter(value)
39 and the expected return value is the value to bind to the database. If this
40 attribute is None, the value is bound directly without any conversion.
41
42
43 .. attribute:: Variable.numElements
44
45 This read-only attribute returns the number of elements allocated in an
46 array, or the number of scalar items that can be fetched into the variable
47 or bound to the variable.
48
49
50 .. attribute:: Variable.outconverter
51
52 This read-write attribute specifies the method used to convert data from
53 from the Oracle to Python. The method signature is converter(value)
54 and the expected return value is the value to return to Python. If this
55 attribute is None, the value is returned directly without any conversion.
56
57
58 .. method:: Variable.setvalue(pos, value)
59
60 Set the value at the given position in the variable.
61
62
63 .. attribute:: Variable.size
64
65 This read-only attribute returns the size of the variable. For strings this
66 value is the size in characters. For all others, this is same value as the
67 attribute bufferSize.
68
69
70 .. attribute:: Variable.type
71
72 This read-only attribute returns the type of the variable for those
73 variables that bind Oracle objects (it is not present for any other type of
74 variable).
75
76
77 .. attribute:: Variable.values
78
79 This read-only attribute returns a copy of the value of all actual
80 positions in the variable as a list. This is the equivalent of calling
81 :meth:`~Variable.getvalue()` for each valid position and the length will
82 correspond to the value of the :attr:`~Variable.actualElements` attribute.
83
+0
-171
doc/src/whatsnew.rst less more
0 .. _whatsnew:
1
2 **********
3 What's New
4 **********
5
6 .. _whatsnew60:
7
8 cx_Oracle 6.0
9 =============
10
11 This document contains a summary of the changes in cx_Oracle 6 compared to
12 cx_Oracle 5.3. cx_Oracle 6.0 was released on August 14, 2017. See the
13 :ref:`release notes <releasenotes60>` for complete details.
14
15 Highlights
16 ----------
17
18 - Has been re-implemented to use the new
19 `ODPI-C <https://oracle.github.io/odpi>`__ abstraction layer for Oracle
20 Database. The cx_Oracle API is unchanged. The cx_Oracle design, build and
21 linking process has improved because of ODPI-C.
22
23 - Now has Python Wheels available for install. This is made possible by the
24 ODPI-C architecture. Windows installers and Linux RPMs are no longer
25 produced since PyPI no longer supports them.
26
27 - Has less code in Python's Global Interpreter Lock, giving better
28 scalability.
29
30 - Added support for universal rowids.
31
32 - Added support for DML returning of multiple rows.
33
34 - Now associates LOB locators to LOB objects so they are not overwritten on
35 database round trips.
36
37
38 Installation Changes
39 --------------------
40
41 - On Linux, cx_Oracle 6 no longer uses instant client RPMs automatically.
42 You must set LD_LIBRARY_PATH or use ldconfig to locate the Oracle Client
43 library.
44
45 - On platforms other than Windows, if ORACLE_HOME is set (in a database or
46 full client installation), remove requirement to set LD_LIBRARY_PATH in
47 order to locate the Oracle Client library
48 (`issue 20 <https://github.com/oracle/odpi/issues/20>`__).
49
50
51 Connection Management Enhancements
52 ----------------------------------
53
54 - Prevent closing the connection when there are any open statements or LOBs
55 and add new error "DPI-1054: connection cannot be closed when open
56 statements or LOBs exist" when this situation is detected; this is needed
57 to prevent crashes under certain conditions when statements or LOBs are
58 being acted upon while at the same time (in another thread) a connection
59 is being closed; it also prevents leaks of statements and LOBs when a
60 connection is returned to a session pool.
61
62 - Added attribute :attr:`SessionPool.stmtcachesize` to support getting and
63 setting the default statement cache size for connections in the pool.
64
65 - Added attribute :attr:`Connection.dbop` to support setting the database
66 operation that is to be monitored.
67
68 - Added attribute :attr:`Connection.handle` to facilitate testing the
69 creation of a connection using a OCI service context handle.
70
71 - Added parameters tag and matchanytag to the :meth:`cx_Oracle.connect` and
72 :meth:`SessionPool.acquire` methods and added parameters tag and retag to
73 the :meth:`SessionPool.release` method in order to support session
74 tagging.
75
76 - Added parameter edition to the :meth:`cx_Oracle.SessionPool` method.
77
78 - Added parameters region, sharding_key and super_sharding_key to the
79 :meth:`cx_Oracle.makedsn()` method to support connecting to a sharded
80 database (new in Oracle Database 12.2).
81
82 - Removed requirement that encoding and nencoding both be specified when
83 creating a connection or session pool. The missing value is set to its
84 default value if one of the values is set and the other is not
85 (`issue 36 <https://github.com/oracle/python-cx_Oracle/issues/36>`__).
86
87 - Permit use of both string and unicode for Python 2.7 for creating session
88 pools and for changing passwords
89 (`issue 23 <https://github.com/oracle/python-cx_Oracle/issues/23>`__).
90
91
92 Data Type and Data Handling Enhancements
93 ----------------------------------------
94
95 - Added attributes :attr:`Variable.actualElements` and
96 :attr:`Variable.values` to variables.
97
98 - Added support for smallint and float data types in Oracle objects, as
99 requested
100 (`issue 4 <https://github.com/oracle/python-cx_Oracle/issues/4>`__).
101
102 - Added support for getting/setting attributes of objects or element values
103 in collections that contain LOBs, BINARY_FLOAT values, BINARY_DOUBLE
104 values and NCHAR and NVARCHAR2 values. The error message for any types
105 that are not supported has been improved as well.
106
107 - An exception is no longer raised when a collection is empty for methods
108 :meth:`Object.first()` and :meth:`Object.last()`. Instead, the value None
109 is returned to be consistent with the methods :meth:`Object.next()` and
110 :meth:`Object.prev()`.
111
112 - Removed requirement for specifying a maximum size when fetching LONG or
113 LONG raw columns. This also allows CLOB, NCLOB, BLOB and BFILE columns to
114 be fetched as strings or bytes without needing to specify a maximum size.
115 The method :meth:`Cursor.setoutputsize` no longer does anything, since
116 ODPI-C automatically manages buffer sizes of LONG and LONG RAW columns.
117
118 - Enable temporary LOB caching in order to avoid disk I/O as suggested
119 (`issue 10 <https://github.com/oracle/odpi/issues/10>`__).
120
121
122 Error Handling Enhancements
123 ---------------------------
124
125 - Provide improved error message when OCI environment cannot be created,
126 such as when the oraaccess.xml file cannot be processed properly.
127
128 - Define exception classes on the connection object in addition to at
129 module scope in order to simplify error handling in multi-connection
130 environments, as specified in the Python DB API.
131
132
133 Test Enhancements
134 -----------------
135
136 - Reworked test suite and samples so that they are independent of each
137 other and so that the SQL scripts used to create/drop schemas are easily
138 adjusted to use different schema names, if desired.
139
140 - Updated DB API test suite stub to support Python 3.
141
142
143 Removals
144 --------
145
146 - Dropped deprecated parameter twophase from the :meth:`cx_Oracle.connect`
147 method. Applications should set the :attr:`Connection.internal_name` and
148 :attr:`Connection.external_name` attributes instead to a value
149 appropriate to the application.
150
151 - Dropped deprecated parameters action, module and clientinfo from the
152 :meth:`cx_Oracle.connect` method. The appcontext parameter should be used
153 instead as shown in this `sample <https://github.com/oracle/
154 python-cx_Oracle/blob/master/samples/AppContext.py>`__.
155
156 - Dropped deprecated attribute numbersAsString from
157 :ref:`cursor objects <cursorobj>`. Use an output type handler instead as
158 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
159 master/samples/ReturnNumbersAsDecimals.py>`__.
160
161 - Dropped deprecated attributes cqqos and rowids from
162 :ref:`subscription objects <subscrobj>`. Use the qos attribute instead as
163 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
164 master/samples/CQN.py>`__.
165
166 - Dropped deprecated parameters cqqos and rowids from the
167 :meth:`Connection.subscribe()` method. Use the qos parameter instead as
168 shown in this `sample <https://github.com/oracle/python-cx_Oracle/blob/
169 master/samples/CQN.py>`__.
170
+0
-64
samples/AdvancedQueuing.py less more
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2 #
3 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
4 #
5 # Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
6 # Canada. All rights reserved.
7 #------------------------------------------------------------------------------
8
9 #------------------------------------------------------------------------------
10 # AdvancedQueuing.py
11 # This script demonstrates how to use advanced queuing using cx_Oracle. It
12 # makes use of a simple type and queue created in the sample setup.
13 #
14 # This script requires cx_Oracle 5.3 and higher.
15 #------------------------------------------------------------------------------
16
17 from __future__ import print_function
18
19 BOOK_TYPE_NAME = "UDT_BOOK"
20 QUEUE_NAME = "BOOKS"
21 QUEUE_TABLE_NAME = "BOOK_QUEUE"
22
23 import cx_Oracle
24 import SampleEnv
25 import decimal
26
27 # connect to database
28 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
29 cursor = connection.cursor()
30
31 # dequeue all existing messages to ensure the queue is empty, just so that
32 # the results are consistent
33 booksType = connection.gettype(BOOK_TYPE_NAME)
34 book = booksType.newobject()
35 options = connection.deqoptions()
36 options.wait = cx_Oracle.DEQ_NO_WAIT
37 messageProperties = connection.msgproperties()
38 while connection.deq(QUEUE_NAME, options, messageProperties, book):
39 pass
40
41 # enqueue a few messages
42 book1 = booksType.newobject()
43 book1.TITLE = "The Fellowship of the Ring"
44 book1.AUTHORS = "Tolkien, J.R.R."
45 book1.PRICE = decimal.Decimal("10.99")
46 book2 = booksType.newobject()
47 book2.TITLE = "Harry Potter and the Philosopher's Stone"
48 book2.AUTHORS = "Rowling, J.K."
49 book2.PRICE = decimal.Decimal("7.99")
50 options = connection.enqoptions()
51 for book in (book1, book2):
52 print("Enqueuing book", book.TITLE)
53 connection.enq(QUEUE_NAME, options, messageProperties, book)
54 connection.commit()
55
56 # dequeue the messages
57 options = connection.deqoptions()
58 options.navigation = cx_Oracle.DEQ_FIRST_MSG
59 options.wait = cx_Oracle.DEQ_NO_WAIT
60 while connection.deq(QUEUE_NAME, options, messageProperties, book):
61 print("Dequeued book", book.TITLE)
62 connection.commit()
63
55 # AdvancedQueuingNotification.py
66 # This script demonstrates using advanced queuing notification. Once this
77 # script is running, use another session to enqueue a few messages to the
8 # "BOOKS" queue. This is most easily accomplished by running the
9 # AdvancedQueuing sample.
8 # "DEMO_BOOK_QUEUE" queue. This is most easily accomplished by running the
9 # ObjectAQ.py sample.
1010 #
1111 # This script requires cx_Oracle 6.4 and higher.
1212 #------------------------------------------------------------------------------
13
14 from __future__ import print_function
1513
1614 import cx_Oracle
1715 import SampleEnv
2018
2119 registered = True
2220
23 def callback(message):
21 def ProcessMessages(message):
2422 global registered
2523 print("Message type:", message.type)
2624 if message.type == cx_Oracle.EVENT_DEREG:
3129 print("Consumer name:", message.consumerName)
3230
3331 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString(), events = True)
34 sub = connection.subscribe(namespace = cx_Oracle.SUBSCR_NAMESPACE_AQ,
35 name = "BOOKS", callback = callback, timeout = 300)
32 sub = connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_AQ,
33 name="DEMO_BOOK_QUEUE", callback=ProcessMessages, timeout=300)
3634 print("Subscription:", sub)
3735 print("--> Connection:", sub.connection)
3836 print("--> Callback:", sub.callback)
1414 #
1515 # This script requires cx_Oracle 5.3 and higher.
1616 #------------------------------------------------------------------------------
17
18 from __future__ import print_function
1917
2018 import cx_Oracle
2119 import SampleEnv
1111 #
1212 # This script requires cx_Oracle 5.2 and higher.
1313 #------------------------------------------------------------------------------
14
15 from __future__ import print_function
1614
1715 import cx_Oracle
1816 import SampleEnv
1313 #
1414 # This script requires cx_Oracle 5.2 and higher.
1515 #------------------------------------------------------------------------------
16
17 from __future__ import print_function
1816
1917 import cx_Oracle
2018 import SampleEnv
66 #
77 # Demonstrate how to insert a row into a table using bind variables.
88 #------------------------------------------------------------------------------
9
10 from __future__ import print_function
119
1210 import cx_Oracle
1311 import SampleEnv
1010 # also permits data to be bound without having to be concerned about escaping
1111 # special characters or SQL injection attacks.
1212 #------------------------------------------------------------------------------
13
14 from __future__ import print_function
1513
1614 import cx_Oracle
1715 import SampleEnv
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2 #
3 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
4 #
5 # Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
6 # Canada. All rights reserved.
7 #------------------------------------------------------------------------------
8
9 #------------------------------------------------------------------------------
10 # BulkAQ.py
11 # This script demonstrates how to use bulk enqueuing and dequeuing of
12 # messages with advanced queuing using cx_Oracle. It makes use of a RAW queue
13 # created in the sample setup.
14 #
15 # This script requires cx_Oracle 7.2 and higher.
16 #------------------------------------------------------------------------------
17
18 import cx_Oracle
19 import SampleEnv
20
21 QUEUE_NAME = "DEMO_RAW_QUEUE"
22 PAYLOAD_DATA = [
23 "The first message",
24 "The second message",
25 "The third message",
26 "The fourth message",
27 "The fifth message",
28 "The sixth message",
29 "The seventh message",
30 "The eighth message",
31 "The ninth message",
32 "The tenth message",
33 "The eleventh message",
34 "The twelfth and final message"
35 ]
36
37 # connect to database
38 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
39 cursor = connection.cursor()
40
41 # create queue
42 queue = connection.queue(QUEUE_NAME)
43 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
44 queue.deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
45
46 # dequeue all existing messages to ensure the queue is empty, just so that
47 # the results are consistent
48 while queue.deqOne():
49 pass
50
51 # enqueue a few messages
52 print("Enqueuing messages...")
53 batchSize = 6
54 dataToEnq = PAYLOAD_DATA
55 while dataToEnq:
56 batchData = dataToEnq[:batchSize]
57 dataToEnq = dataToEnq[batchSize:]
58 messages = [connection.msgproperties(payload=d) for d in batchData]
59 for data in batchData:
60 print(data)
61 queue.enqMany(messages)
62 connection.commit()
63
64 # dequeue the messages
65 print("\nDequeuing messages...")
66 batchSize = 8
67 while True:
68 messages = queue.deqMany(batchSize)
69 if not messages:
70 break
71 for props in messages:
72 print(props.payload.decode())
73 connection.commit()
74 print("\nDone.")
1616 # This script requires cx_Oracle 5.3 and higher.
1717 #------------------------------------------------------------------------------
1818
19 from __future__ import print_function
20
2119 import cx_Oracle
2220 import SampleEnv
23 import threading
2421 import time
2522
2623 registered = True
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # CQN2.py
6 # This script demonstrates using continuous query notification in Python, a
7 # feature that is available in Oracle 11g and later. Once this script is
8 # running, use another session to insert, update or delete rows from the table
9 # cx_Oracle.TestTempTable and you will see the notification of that change.
10 #
11 # This script differs from CQN.py in that it shows how a connection can be
12 # acquired from a session pool and used to query the changes that have been
13 # made.
14 #
15 # This script requires cx_Oracle 7 or higher.
16 #------------------------------------------------------------------------------
17
18 import cx_Oracle
19 import SampleEnv
20 import time
21
22 registered = True
23
24 def callback(message):
25 global registered
26 if not message.registered:
27 print("Deregistration has taken place...")
28 registered = False
29 return
30 connection = pool.acquire()
31 for query in message.queries:
32 for table in query.tables:
33 if table.rows is None:
34 print("Too many row changes detected in table", table.name)
35 continue
36 numRowsDeleted = 0
37 print(len(table.rows), "row changes detected in table", table.name)
38 for row in table.rows:
39 if row.operation & cx_Oracle.OPCODE_DELETE:
40 numRowsDeleted += 1
41 continue
42 ops = []
43 if row.operation & cx_Oracle.OPCODE_INSERT:
44 ops.append("inserted")
45 if row.operation & cx_Oracle.OPCODE_UPDATE:
46 ops.append("updated")
47 cursor = connection.cursor()
48 cursor.execute("""
49 select IntCol
50 from TestTempTable
51 where rowid = :rid""",
52 rid=row.rowid)
53 intCol, = cursor.fetchone()
54 print(" Row with IntCol", intCol, "was", " and ".join(ops))
55 if numRowsDeleted > 0:
56 print(" ", numRowsDeleted, "rows deleted")
57 print("=" * 60)
58
59 pool = cx_Oracle.SessionPool(SampleEnv.GetMainUser(),
60 SampleEnv.GetMainPassword(), SampleEnv.GetConnectString(), min=2,
61 max=5, increment=1, events=True, threaded=True)
62 with pool.acquire() as connection:
63 sub = connection.subscribe(callback=callback, timeout=1800,
64 qos=cx_Oracle.SUBSCR_QOS_QUERY | cx_Oracle.SUBSCR_QOS_ROWIDS)
65 print("Subscription created with ID:", sub.id)
66 queryId = sub.registerquery("select * from TestTempTable")
67 print("Registered query with ID:", queryId)
68
69 while registered:
70 print("Waiting for notifications....")
71 time.sleep(5)
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # CallTimeout.py
6 #
7 # Demonstrate the use of the Oracle Client 18c feature that enables round trips
8 # to the database to time out if a specified amount of time (in milliseconds)
9 # has passed without a response from the database.
10 #
11 # This script requires cx_Oracle 7.0 and higher and Oracle Client 18.1 and
12 # higher.
13 #------------------------------------------------------------------------------
14
15 import cx_Oracle
16 import SampleEnv
17
18 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
19 connection.callTimeout = 2000
20 print("Call timeout set at", connection.callTimeout, "milliseconds...")
21
22 cursor = connection.cursor()
23 cursor.execute("select sysdate from dual")
24 today, = cursor.fetchone()
25 print("Fetch of current date before timeout:", today)
26
27 # dbms_session.sleep() replaces dbms_lock.sleep() from Oracle Database 18c
28 sleepProcName = "dbms_session.sleep" \
29 if int(connection.version.split(".")[0]) >= 18 \
30 else "dbms_lock.sleep"
31
32 print("Sleeping...should time out...")
33 try:
34 cursor.callproc(sleepProcName, (3,))
35 except cx_Oracle.DatabaseError as e:
36 print("ERROR:", e)
37
38 cursor.execute("select sysdate from dual")
39 today, = cursor.fetchone()
40 print("Fetch of current date after timeout:", today)
41
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # ConnectionPool.py
6 # This script demonstrates the use of connection pooling in cx_Oracle. Pools
7 # can significantly reduce connection times for long running applications that
8 # repeatedly open and close connections. Internal features help protect against
9 # dead connections, and also aid use of Oracle Database features such as FAN
10 # and Application Continuity.
11 # The script uses threading to show multiple users of the pool. One thread
12 # performs a database sleep while another performs a query. A more typical
13 # application might be a web service that handles requests from multiple users.
14 # Applications that use connections concurrently in multiple threads should set
15 # the 'threaded' parameter to True. Note only one operation (such as an execute
16 # or fetch) can take place at a time on each connection.
17 #
18 # Also see SessionCallback.py.
19 #
20 #------------------------------------------------------------------------------
21
22 import cx_Oracle
23 import SampleEnv
24 import threading
25
26 # Create a Connection Pool
27 pool = cx_Oracle.SessionPool(SampleEnv.GetMainUser(),
28 SampleEnv.GetMainPassword(), SampleEnv.GetConnectString(), min=2,
29 max=5, increment=1, threaded=True)
30
31 # dbms_session.sleep() replaces dbms_lock.sleep() from Oracle Database 18c
32 with pool.acquire() as conn:
33 sleepProcName = "dbms_session.sleep" \
34 if int(conn.version.split(".")[0]) >= 18 \
35 else "dbms_lock.sleep"
36
37 def TheLongQuery():
38 with pool.acquire() as conn:
39 cursor = conn.cursor()
40 cursor.arraysize = 25000
41 print("TheLongQuery(): beginning execute...")
42 cursor.execute("""
43 select *
44 from
45 TestNumbers
46 cross join TestNumbers
47 cross join TestNumbers
48 cross join TestNumbers
49 cross join TestNumbers
50 cross join TestNumbers""")
51 print("TheLongQuery(): done execute...")
52 while True:
53 rows = cursor.fetchmany()
54 if not rows:
55 break
56 print("TheLongQuery(): fetched", len(rows), "rows...")
57 print("TheLongQuery(): all done!")
58
59
60 def DoALock():
61 with pool.acquire() as conn:
62 cursor = conn.cursor()
63 print("DoALock(): beginning execute...")
64 cursor.callproc(sleepProcName, (5,))
65 print("DoALock(): done execute...")
66
67
68 thread1 = threading.Thread(None, TheLongQuery)
69 thread1.start()
70
71 thread2 = threading.Thread(None, DoALock)
72 thread2.start()
73
74 thread1.join()
75 thread2.join()
76
77 print("All done!")
1313 #
1414 # This script requires cx_Oracle 6.0 and higher.
1515 #------------------------------------------------------------------------------
16
17 from __future__ import print_function
1816
1917 import cx_Oracle
2018 import datetime
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 #
33 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 #
2424 # There is no difference in how a connection is used once it has been
2525 # established.
2626 #
27 # This script requires cx_Oracle 5.0 and higher.
27 # DRCP has most benefit when used in conjunction with cx_Oracle's local
28 # connection pool, see the cx_Oracle documentation.
29 #
30 # This script requires cx_Oracle 5.0 or higher.
31 #
2832 #------------------------------------------------------------------------------
29
30 from __future__ import print_function
3133
3234 import cx_Oracle
3335 import SampleEnv
1616 # This script requires cx_Oracle 5.3 and higher.
1717 #------------------------------------------------------------------------------
1818
19 from __future__ import print_function
20
2119 import cx_Oracle
2220 import SampleEnv
23 import threading
2421 import time
2522
2623 registered = True
5148 qos = cx_Oracle.SUBSCR_QOS_ROWIDS)
5249 print("Subscription:", sub)
5350 print("--> Connection:", sub.connection)
51 print("--> ID:", sub.id)
5452 print("--> Callback:", sub.callback)
5553 print("--> Namespace:", sub.namespace)
5654 print("--> Protocol:", sub.protocol)
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # DbmsOutput.py
6 # This script demonstrates one method of fetching the lines produced by
7 # the DBMS_OUTPUT package.
8 #------------------------------------------------------------------------------
9
10 import cx_Oracle
11 import SampleEnv
12
13 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
14 cursor = connection.cursor()
15
16 # enable DBMS_OUTPUT
17 cursor.callproc("dbms_output.enable")
18
19 # execute some PL/SQL that generates output with DBMS_OUTPUT.PUT_LINE
20 cursor.execute("""
21 begin
22 dbms_output.put_line('This is the cx_Oracle manual');
23 dbms_output.put_line('');
24 dbms_output.put_line('Demonstrating use of DBMS_OUTPUT');
25 end;""")
26
27 # tune this size for your application
28 chunk_size = 10
29
30 # create variables to hold the output
31 lines_var = cursor.arrayvar(str, chunk_size)
32 num_lines_var = cursor.var(int)
33 num_lines_var.setvalue(0, chunk_size)
34
35 # fetch the text that was added by PL/SQL
36 while True:
37 cursor.callproc("dbms_output.get_lines", (lines_var, num_lines_var))
38 num_lines = num_lines_var.getvalue()
39 lines = lines_var.getvalue()[:num_lines]
40 for line in lines:
41 print(line or "")
42 if num_lines < chunk_size:
43 break
66 #
77 # Drops the database objects used for the cx_Oracle samples.
88 #------------------------------------------------------------------------------
9
10 from __future__ import print_function
119
1210 import cx_Oracle
1311 import SampleEnv
2018 edition_name = SampleEnv.GetEditionName())
2119
2220 if __name__ == "__main__":
23 conn = cx_Oracle.connect(SampleEnv.GetSysdbaConnectString(),
24 mode = cx_Oracle.SYSDBA)
21 conn = cx_Oracle.connect(SampleEnv.GetAdminConnectString())
2522 DropSamples(conn)
2623 print("Done.")
27
1515 #
1616 # This script requires cx_Oracle 5.3 and higher.
1717 #------------------------------------------------------------------------------
18
19 from __future__ import print_function
2018
2119 import cx_Oracle
2220 import SampleEnv
77 # Demonstrate the ability to return named tuples for all queries using a
88 # subclassed cursor and row factory.
99 #------------------------------------------------------------------------------
10
11 from __future__ import print_function
1210
1311 import collections
1412 import cx_Oracle
1414 #
1515 # This script requires cx_Oracle 5.3 and higher.
1616 #------------------------------------------------------------------------------
17
18 from __future__ import print_function
1917
2018 import cx_Oracle
2119 import SampleEnv
1313 #
1414 # This script requires cx_Oracle 5.3 and higher.
1515 #------------------------------------------------------------------------------
16
17 from __future__ import print_function
1816
1917 import cx_Oracle
2018 import SampleEnv
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # LastRowid.py
6 # Demonstrates the use of the cursor.lastrowid attribute.
7 #
8 # This script requires cx_Oracle 7.3 and higher.
9 #------------------------------------------------------------------------------
10
11 import cx_Oracle
12 import SampleEnv
13
14 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
15
16 row1 = [1, "First"]
17 row2 = [2, "Second"]
18
19 # insert a couple of rows and retain the rowid of each
20 cursor = connection.cursor()
21 cursor.execute("insert into mytab (id, data) values (:1, :2)", row1)
22 rowid1 = cursor.lastrowid
23 print("Row 1:", row1)
24 print("Rowid 1:", rowid1)
25 print()
26
27 cursor.execute("insert into mytab (id, data) values (:1, :2)", row2)
28 rowid2 = cursor.lastrowid
29 print("Row 2:", row2)
30 print("Rowid 2:", rowid2)
31 print()
32
33 # the row can be fetched with the rowid that was retained
34 cursor.execute("select id, data from mytab where rowid = :1", [rowid1])
35 print("Row 1:", cursor.fetchone())
36 cursor.execute("select id, data from mytab where rowid = :1", [rowid2])
37 print("Row 2:", cursor.fetchone())
38 print()
39
40 # updating multiple rows only returns the rowid of the last updated row
41 cursor.execute("update mytab set data = data || ' (Modified)'")
42 cursor.execute("select id, data from mytab where rowid = :1",
43 [cursor.lastrowid])
44 print("Last updated row:", cursor.fetchone())
45
46 # deleting multiple rows only returns the rowid of the last deleted row
47 cursor.execute("delete from mytab")
48 print("Rowid of last deleted row:", cursor.lastrowid)
49
50 # deleting no rows results in a value of None
51 cursor.execute("delete from mytab")
52 print("Rowid when no rows are deleted:", cursor.lastrowid)
53
54 # Don't commit - this lets us run the demo multiple times
55 #connection.commit()
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2 #
3 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
4 #
5 # Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
6 # Canada. All rights reserved.
7 #------------------------------------------------------------------------------
8
9 #------------------------------------------------------------------------------
10 # MultiConsumerAQ.py
11 # This script demonstrates how to use multi-consumer
12 # advanced queuing using cx_Oracle. It makes use of a RAW queue
13 # created in the sample setup.
14 #
15 # This script requires cx_Oracle 7.2 and higher.
16 #------------------------------------------------------------------------------
17
18 import cx_Oracle
19 import SampleEnv
20
21 QUEUE_NAME = "DEMO_RAW_QUEUE_MULTI"
22 PAYLOAD_DATA = [
23 "The first message",
24 "The second message",
25 "The third message",
26 "The fourth and final message"
27 ]
28
29 # connect to database
30 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
31 cursor = connection.cursor()
32
33 # create queue
34 queue = connection.queue(QUEUE_NAME)
35 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
36 queue.deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
37
38 # enqueue a few messages
39 print("Enqueuing messages...")
40 for data in PAYLOAD_DATA:
41 print(data)
42 queue.enqOne(connection.msgproperties(payload=data))
43 connection.commit()
44 print()
45
46 # dequeue the messages for consumer A
47 print("Dequeuing the messages for consumer A...")
48 queue.deqOptions.consumername = "SUBSCRIBER_A"
49 while True:
50 props = queue.deqOne()
51 if not props:
52 break
53 print(props.payload.decode())
54 connection.commit()
55 print()
56
57 # dequeue the message for consumer B
58 print("Dequeuing the messages for consumer B...")
59 queue.deqOptions.consumername = "SUBSCRIBER_B"
60 while True:
61 props = queue.deqOne()
62 if not props:
63 break
64 print(props.payload.decode())
65 connection.commit()
66
67 print("\nDone.")
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2 #
3 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
4 #
5 # Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
6 # Canada. All rights reserved.
7 #------------------------------------------------------------------------------
8
9 #------------------------------------------------------------------------------
10 # ObjectAQ.py
11 # This script demonstrates how to use advanced queuing with objects using
12 # cx_Oracle. It makes use of a simple type and queue created in the sample
13 # setup.
14 #
15 # This script requires cx_Oracle 7.2 and higher.
16 #------------------------------------------------------------------------------
17
18 import cx_Oracle
19 import SampleEnv
20 import decimal
21
22 BOOK_TYPE_NAME = "UDT_BOOK"
23 QUEUE_NAME = "DEMO_BOOK_QUEUE"
24 BOOK_DATA = [
25 ("The Fellowship of the Ring", "Tolkien, J.R.R.",
26 decimal.Decimal("10.99")),
27 ("Harry Potter and the Philosopher's Stone", "Rowling, J.K.",
28 decimal.Decimal("7.99"))
29 ]
30
31 # connect to database
32 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
33 cursor = connection.cursor()
34
35 # create queue
36 booksType = connection.gettype(BOOK_TYPE_NAME)
37 queue = connection.queue(QUEUE_NAME, booksType)
38 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
39 queue.deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
40
41 # dequeue all existing messages to ensure the queue is empty, just so that
42 # the results are consistent
43 while queue.deqOne():
44 pass
45
46 # enqueue a few messages
47 print("Enqueuing messages...")
48 for title, authors, price in BOOK_DATA:
49 book = booksType.newobject()
50 book.TITLE = title
51 book.AUTHORS = authors
52 book.PRICE = price
53 print(title)
54 queue.enqOne(connection.msgproperties(payload=book))
55 connection.commit()
56
57 # dequeue the messages
58 print("\nDequeuing messages...")
59 while True:
60 props = queue.deqOne()
61 if not props:
62 break
63 print(props.payload.TITLE)
64 connection.commit()
65 print("\nDone.")
1111 # Database 12.1 and higher. The ability to get the collection as a dictionary
1212 # is new in cx_Oracle 7.0.
1313 #------------------------------------------------------------------------------
14
15 from __future__ import print_function
1614
1715 import cx_Oracle
1816 import SampleEnv
77 # Demonstrate how to call a PL/SQL function and get its return value.
88 #------------------------------------------------------------------------------
99
10 from __future__ import print_function
11
1210 import cx_Oracle
1311 import SampleEnv
1412
88 # OUT variable.
99 #------------------------------------------------------------------------------
1010
11 from __future__ import print_function
12
1311 import cx_Oracle
1412 import SampleEnv
1513
99 # This feature is new in cx_Oracle 5.3 and is only available in Oracle
1010 # Database 12.1 and higher.
1111 #------------------------------------------------------------------------------
12
13 from __future__ import print_function
1412
1513 import cx_Oracle
1614 import SampleEnv
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
66 #
77 # Demonstrate how to perform a query in different ways.
88 #------------------------------------------------------------------------------
9
10 from __future__ import print_function
119
1210 import cx_Oracle
1311 import SampleEnv
3735 cursor.execute(sql)
3836 res = cursor.fetchmany(numRows=3)
3937 print(res)
38 print()
4039
40 print("Fetch each row as a Dictionary")
41 cursor.execute(sql)
42 columns = [col[0] for col in cursor.description]
43 cursor.rowfactory = lambda *args: dict(zip(columns, args))
44 for row in cursor:
45 print(row)
88 # number of network round trips and overhead required to fetch all of the rows
99 # from a large table.
1010 #------------------------------------------------------------------------------
11
12 from __future__ import print_function
1311
1412 import time
1513 import cx_Oracle
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2 #
3 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
4 #
5 # Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
6 # Canada. All rights reserved.
7 #------------------------------------------------------------------------------
8
9 #------------------------------------------------------------------------------
10 # RawAQ.py
11 # This script demonstrates how to use advanced queuing with RAW data using
12 # cx_Oracle. It makes use of a RAW queue created in the sample setup.
13 #
14 # This script requires cx_Oracle 7.2 and higher.
15 #------------------------------------------------------------------------------
16
17 import cx_Oracle
18 import SampleEnv
19
20 QUEUE_NAME = "DEMO_RAW_QUEUE"
21 PAYLOAD_DATA = [
22 "The first message",
23 "The second message",
24 "The third message",
25 "The fourth and final message"
26 ]
27
28 # connect to database
29 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
30 cursor = connection.cursor()
31
32 # create queue
33 queue = connection.queue(QUEUE_NAME)
34 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
35 queue.deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
36
37 # dequeue all existing messages to ensure the queue is empty, just so that
38 # the results are consistent
39 while queue.deqOne():
40 pass
41
42 # enqueue a few messages
43 print("Enqueuing messages...")
44 for data in PAYLOAD_DATA:
45 print(data)
46 queue.enqOne(connection.msgproperties(payload=data))
47 connection.commit()
48
49 # dequeue the messages
50 print("\nDequeuing messages...")
51 while True:
52 props = queue.deqOne()
53 if not props:
54 break
55 print(props.payload.decode())
56 connection.commit()
57 print("\nDone.")
55 # RefCursor.py
66 # Demonstrates the use of REF cursors with cx_Oracle.
77 #------------------------------------------------------------------------------
8
9 from __future__ import print_function
108
119 import cx_Oracle
1210 import SampleEnv
1616 #
1717 # This script requires cx_Oracle 5.0 and higher.
1818 #------------------------------------------------------------------------------
19
20 from __future__ import print_function
2119
2220 import cx_Oracle
2321 import SampleEnv
1313 # This script requires cx_Oracle 5.0 and higher.
1414 #------------------------------------------------------------------------------
1515
16 from __future__ import print_function
17
1816 import cx_Oracle
1917 import decimal
2018 import SampleEnv
+0
-33
samples/ReturnUnicode.py less more
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2 #
3 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
4 #
5 # Portions Copyright 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
6 # Canada. All rights reserved.
7 #------------------------------------------------------------------------------
8
9 #------------------------------------------------------------------------------
10 # ReturnUnicode.py
11 # Returns all strings as unicode. This also demonstrates the use of an output
12 # type handler to change the way in which data is returned from a cursor.
13 #
14 # This script requires cx_Oracle 5.0 and higher and will only work in Python 2.
15 #------------------------------------------------------------------------------
16
17 from __future__ import print_function
18
19 import cx_Oracle
20 import SampleEnv
21
22 def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
23 if defaultType in (cx_Oracle.STRING, cx_Oracle.FIXED_CHAR):
24 return cursor.var(unicode, size, cursor.arraysize)
25
26 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
27 connection.outputtypehandler = OutputTypeHandler
28 cursor = connection.cursor()
29 cursor.execute("select * from TestStrings")
30 for row in cursor:
31 print("Row:", row)
32
1414 #
1515 # This script requires cx_Oracle 4.3 and higher.
1616 #------------------------------------------------------------------------------
17
18 from __future__ import print_function
1917
2018 import cx_Oracle
2119 import SampleEnv
1515 # CX_ORACLE_SAMPLES_EDITION_PASSWORD: password of user for editioning
1616 # CX_ORACLE_SAMPLES_EDITION_NAME: name of edition for editioning
1717 # CX_ORACLE_SAMPLES_CONNECT_STRING: connect string
18 # CX_ORACLE_SAMPLES_SYSDBA_USER: SYSDBA user for setting up samples
19 # CX_ORACLE_SAMPLES_SYSDBA_PASSWORD: SYSDBA password for setting up samples
18 # CX_ORACLE_SAMPLES_DRCP_CONNECT_STRING: DRCP connect string
19 # CX_ORACLE_SAMPLES_ADMIN_USER: admin user for setting up samples
20 # CX_ORACLE_SAMPLES_ADMIN_PASSWORD: admin password for setting up samples
2021 #
2122 # CX_ORACLE_SAMPLES_CONNECT_STRING can be set to an Easy Connect string, or a
2223 # Net Service Name from a tnsnames.ora file or external naming service,
2829 # [//]host_name[:port][/service_name][:server_type][/instance_name]
2930 #
3031 # Commonly just the host_name and service_name are needed
31 # e.g. "localhost/orclpdb" or "localhost/XE"
32 # e.g. "localhost/orclpdb1" or "localhost/XEPDB1"
3233 #
3334 # If using a tnsnames.ora file, the file can be in a default
3435 # location such as $ORACLE_HOME/network/admin/tnsnames.ora or
3536 # /etc/tnsnames.ora. Alternatively set the TNS_ADMIN environment
3637 # variable and put the file in $TNS_ADMIN/tnsnames.ora.
38 #
39 # The administrative user for cloud databases is ADMIN and the administrative
40 # user for on premises databases is SYSTEM.
3741 #------------------------------------------------------------------------------
38
39 from __future__ import print_function
4042
4143 import getpass
4244 import os
4648 DEFAULT_MAIN_USER = "pythondemo"
4749 DEFAULT_EDITION_USER = "pythoneditions"
4850 DEFAULT_EDITION_NAME = "python_e1"
49 DEFAULT_CONNECT_STRING = "localhost/orclpdb"
51 DEFAULT_CONNECT_STRING = "localhost/orclpdb1"
52 DEFAULT_DRCP_CONNECT_STRING = "localhost/orclpdb1:pooled"
5053
5154 # dictionary containing all parameters; these are acquired as needed by the
5255 # methods below (which should be used instead of consulting this dictionary
6972 value = getpass.getpass(label)
7073 if not value:
7174 value = defaultValue
75 PARAMETERS[name] = value
7276 return value
7377
7478 def GetMainUser():
9599 return "%s/%s@%s" % (GetMainUser(), password, GetConnectString())
96100
97101 def GetDrcpConnectString():
98 return GetMainConnectString() + ":pooled"
102 connectString = GetValue("DRCP_CONNECT_STRING", "DRCP Connect String",
103 DEFAULT_DRCP_CONNECT_STRING)
104 return "%s/%s@%s" % (GetMainUser(), GetMainPassword(), connectString)
99105
100106 def GetEditionConnectString():
101107 return "%s/%s@%s" % \
102108 (GetEditionUser(), GetEditionPassword(), GetConnectString())
103109
104 def GetSysdbaConnectString():
105 sysdbaUser = GetValue("SYSDBA_USER", "SYSDBA user", "sys")
106 sysdbaPassword = GetValue("SYSDBA_PASSWORD",
107 "Password for %s" % sysdbaUser)
108 return "%s/%s@%s" % (sysdbaUser, sysdbaPassword, GetConnectString())
110 def GetAdminConnectString():
111 adminUser = GetValue("ADMIN_USER", "Administrative user", "admin")
112 adminPassword = GetValue("ADMIN_PASSWORD", "Password for %s" % adminUser)
113 return "%s/%s@%s" % (adminUser, adminPassword, GetConnectString())
109114
110115 def RunSqlScript(conn, scriptName, **kwargs):
111116 statementParts = []
120125 if statement:
121126 for searchValue, replaceValue in replaceValues:
122127 statement = statement.replace(searchValue, replaceValue)
123 cursor.execute(statement)
128 try:
129 cursor.execute(statement)
130 except:
131 print("Failed to execute SQL:", statement)
132 raise
124133 statementParts = []
125134 else:
126135 statementParts.append(line)
137146 prevName = name
138147 prevObjType = objType
139148 print(" %s/%s %s" % (lineNum, position, text))
140
1414 #
1515 # This script requires cx_Oracle 5.3 and higher.
1616 #------------------------------------------------------------------------------
17
18 from __future__ import print_function
1917
2018 import cx_Oracle
2119 import SampleEnv
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
55 # SessionCallback.py
66 #
7 # Demonstrate how to use a session callback written in Python. The callback is
8 # invoked whenever a newly created session is acquired from the pool, or when
9 # the requested tag does not match the tag that is associated with the
10 # session. It is generally used to set session state, so that the application
11 # can count on known session state, which allows the application to reduce the
12 # number of round trips made to the database.
7 # Demonstrate how to use a connection pool session callback written in
8 # Python. The callback is invoked whenever a newly created session is acquired
9 # from the pool, or when the requested tag does not match the tag that is
10 # associated with the session. It is generally used to set session state, so
11 # that the application can count on known session state, which allows the
12 # application to reduce the number of round trips made to the database.
13 # If all your connections should have the same session state, you can simplify
14 # the session callback by removing the tagging logic.
1315 #
14 # This script requires cx_Oracle 7.1 and higher.
16 # This script requires cx_Oracle 7.1 or higher.
17 #
18 # Also see SessionCallbackPLSQL.py
19 #
1520 #------------------------------------------------------------------------------
16
17 from __future__ import print_function
1821
1922 import cx_Oracle
2023 import SampleEnv
8285 # newly created, the callback will be invoked but since there is no tag
8386 # specified, no session state will be changed
8487 print("(1) acquire session without tag")
85 conn = pool.acquire()
86 cursor = conn.cursor()
87 cursor.execute("select to_char(current_date) from dual")
88 result, = cursor.fetchone()
89 print("main(): result is", repr(result))
90 conn.close()
88 with pool.acquire() as conn:
89 cursor = conn.cursor()
90 cursor.execute("select to_char(current_date) from dual")
91 result, = cursor.fetchone()
92 print("main(): result is", repr(result))
9193
9294 # acquire session, specifying a tag; since the session returned has no tag,
9395 # the callback will be invoked; session state will be changed and the tag will
9496 # be saved when the connection is closed
9597 print("(2) acquire session with tag")
96 conn = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE")
97 cursor = conn.cursor()
98 cursor.execute("select to_char(current_date) from dual")
99 result, = cursor.fetchone()
100 print("main(): result is", repr(result))
101 conn.close()
98 with pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE") as conn:
99 cursor = conn.cursor()
100 cursor.execute("select to_char(current_date) from dual")
101 result, = cursor.fetchone()
102 print("main(): result is", repr(result))
102103
103104 # acquire session, specifying the same tag; since a session exists in the pool
104105 # with this tag, it will be returned and the callback will not be invoked but
105106 # the connection will still have the session state defined previously
106107 print("(3) acquire session with same tag")
107 conn = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE")
108 cursor = conn.cursor()
109 cursor.execute("select to_char(current_date) from dual")
110 result, = cursor.fetchone()
111 print("main(): result is", repr(result))
112 conn.close()
108 with pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE") as conn:
109 cursor = conn.cursor()
110 cursor.execute("select to_char(current_date) from dual")
111 result, = cursor.fetchone()
112 print("main(): result is", repr(result))
113113
114114 # acquire session, specifying a different tag; since no session exists in the
115115 # pool with this tag, a new session will be returned and the callback will be
116116 # invoked; session state will be changed and the tag will be saved when the
117117 # connection is closed
118118 print("(4) acquire session with different tag")
119 conn = pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC")
120 cursor = conn.cursor()
121 cursor.execute("select to_char(current_date) from dual")
122 result, = cursor.fetchone()
123 print("main(): result is", repr(result))
124 conn.close()
119 with pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC") as conn:
120 cursor = conn.cursor()
121 cursor.execute("select to_char(current_date) from dual")
122 result, = cursor.fetchone()
123 print("main(): result is", repr(result))
125124
126125 # acquire session, specifying a different tag but also specifying that a
127126 # session with any tag can be acquired from the pool; a session with one of the
129128 # session state will be changed and the tag will be saved when the connection
130129 # is closed
131130 print("(4) acquire session with different tag but match any also specified")
132 conn = pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=MST", matchanytag=True)
133 cursor = conn.cursor()
134 cursor.execute("select to_char(current_date) from dual")
135 result, = cursor.fetchone()
136 print("main(): result is", repr(result))
137 conn.close()
138
131 with pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=MST", matchanytag=True) \
132 as conn:
133 cursor = conn.cursor()
134 cursor.execute("select to_char(current_date) from dual")
135 result, = cursor.fetchone()
136 print("main(): result is", repr(result))
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
55 # SessionCallbackPLSQL.py
66 #
7 # Demonstrate how to use a session callback written in PL/SQL. The callback is
8 # invoked whenever the tag requested by the application does not match the tag
9 # associated with the session in the pool. It should be used to set session
10 # state, so that the application can count on known session state, which allows
11 # the application to reduce the number of round trips to the database.
7 # Demonstrate how to use a connection pool session callback written in
8 # PL/SQL. The callback is invoked whenever the tag requested by the application
9 # does not match the tag associated with the session in the pool. It should be
10 # used to set session state, so that the application can count on known session
11 # state, which allows the application to reduce the number of round trips to the
12 # database.
1213 #
1314 # The primary advantage to this approach over the equivalent approach shown in
1415 # SessionCallback.py is when DRCP is used, as the callback is invoked on the
1516 # server and no round trip is required to set state.
1617 #
17 # This script requires cx_Oracle 7.1 and higher.
18 # This script requires cx_Oracle 7.1 or higher.
19 #
20 # Also see SessionCallback.py
21 #
1822 #------------------------------------------------------------------------------
19
20 from __future__ import print_function
2123
2224 import cx_Oracle
2325 import SampleEnv
2931 sessionCallback="pkg_SessionCallback.TheCallback")
3032
3133 # truncate table logging calls to PL/SQL session callback
32 conn = pool.acquire()
33 cursor = conn.cursor()
34 cursor.execute("truncate table PLSQLSessionCallbacks")
35 conn.close()
34 with pool.acquire() as conn:
35 cursor = conn.cursor()
36 cursor.execute("truncate table PLSQLSessionCallbacks")
3637
3738 # acquire session without specifying a tag; the callback will not be invoked as
3839 # a result and no session state will be changed
3940 print("(1) acquire session without tag")
40 conn = pool.acquire()
41 cursor = conn.cursor()
42 cursor.execute("select to_char(current_date) from dual")
43 result, = cursor.fetchone()
44 print("main(): result is", repr(result))
45 conn.close()
41 with pool.acquire() as conn:
42 cursor = conn.cursor()
43 cursor.execute("select to_char(current_date) from dual")
44 result, = cursor.fetchone()
45 print("main(): result is", repr(result))
4646
4747 # acquire session, specifying a tag; since the session returned has no tag,
4848 # the callback will be invoked; session state will be changed and the tag will
4949 # be saved when the connection is closed
5050 print("(2) acquire session with tag")
51 conn = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE")
52 cursor = conn.cursor()
53 cursor.execute("select to_char(current_date) from dual")
54 result, = cursor.fetchone()
55 print("main(): result is", repr(result))
56 conn.close()
51 with pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE") as conn:
52 cursor = conn.cursor()
53 cursor.execute("select to_char(current_date) from dual")
54 result, = cursor.fetchone()
55 print("main(): result is", repr(result))
5756
5857 # acquire session, specifying the same tag; since a session exists in the pool
5958 # with this tag, it will be returned and the callback will not be invoked but
6059 # the connection will still have the session state defined previously
6160 print("(3) acquire session with same tag")
62 conn = pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE")
63 cursor = conn.cursor()
64 cursor.execute("select to_char(current_date) from dual")
65 result, = cursor.fetchone()
66 print("main(): result is", repr(result))
67 conn.close()
61 with pool.acquire(tag="NLS_DATE_FORMAT=SIMPLE") as conn:
62 cursor = conn.cursor()
63 cursor.execute("select to_char(current_date) from dual")
64 result, = cursor.fetchone()
65 print("main(): result is", repr(result))
6866
6967 # acquire session, specifying a different tag; since no session exists in the
7068 # pool with this tag, a new session will be returned and the callback will be
7169 # invoked; session state will be changed and the tag will be saved when the
7270 # connection is closed
7371 print("(4) acquire session with different tag")
74 conn = pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC")
75 cursor = conn.cursor()
76 cursor.execute("select to_char(current_date) from dual")
77 result, = cursor.fetchone()
78 print("main(): result is", repr(result))
79 conn.close()
72 with pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC") as conn:
73 cursor = conn.cursor()
74 cursor.execute("select to_char(current_date) from dual")
75 result, = cursor.fetchone()
76 print("main(): result is", repr(result))
8077
8178 # acquire session, specifying a different tag but also specifying that a
8279 # session with any tag can be acquired from the pool; a session with one of the
8481 # session state will be changed and the tag will be saved when the connection
8582 # is closed
8683 print("(4) acquire session with different tag but match any also specified")
87 conn = pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=MST", matchanytag=True)
88 cursor = conn.cursor()
89 cursor.execute("select to_char(current_date) from dual")
90 result, = cursor.fetchone()
91 print("main(): result is", repr(result))
92 conn.close()
84 with pool.acquire(tag="NLS_DATE_FORMAT=FULL;TIME_ZONE=MST", matchanytag=True) \
85 as conn:
86 cursor = conn.cursor()
87 cursor.execute("select to_char(current_date) from dual")
88 result, = cursor.fetchone()
89 print("main(): result is", repr(result))
9390
9491 # acquire session and display results from PL/SQL session logs
95 conn = pool.acquire()
96 cursor = conn.cursor()
97 cursor.execute("""
98 select RequestedTag, ActualTag
99 from PLSQLSessionCallbacks
100 order by FixupTimestamp""")
101 print("(5) PL/SQL session callbacks")
102 for requestedTag, actualTag in cursor:
103 print("Requested:", requestedTag, "Actual:", actualTag)
104
92 with pool.acquire() as conn:
93 cursor = conn.cursor()
94 cursor.execute("""
95 select RequestedTag, ActualTag
96 from PLSQLSessionCallbacks
97 order by FixupTimestamp""")
98 print("(5) PL/SQL session callbacks")
99 for requestedTag, actualTag in cursor:
100 print("Requested:", requestedTag, "Actual:", actualTag)
99 # demonstration of PL/SQL editioning.
1010 #------------------------------------------------------------------------------
1111
12 from __future__ import print_function
13
1412 import cx_Oracle
1513
1614 import SampleEnv
1715 import DropSamples
1816
19 # connect as SYSDBA
20 conn = cx_Oracle.connect(SampleEnv.GetSysdbaConnectString(),
21 mode = cx_Oracle.SYSDBA)
17 # connect as administrative user (usually SYSTEM or ADMIN)
18 conn = cx_Oracle.connect(SampleEnv.GetAdminConnectString())
2219
2320 # drop existing users and editions, if applicable
2421 DropSamples.DropSamples(conn)
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # ShardingNumberKey.py
6 # This script demonstrates how to use sharding keys with a sharded database.
7 # The sample schema provided does not include support for running this demo. A
8 # sharded database must first be created. Information on how to create a
9 # sharded database can be found in the documentation:
10 # https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=SHARD
11 #
12 # This script requires cx_Oracle 6.1 and higher but it is recommended to use
13 # cx_Oracle 7.3 and higher in order to avoid a set of known issues when using
14 # sharding capabilities.
15 #------------------------------------------------------------------------------
16
17 import cx_Oracle
18 import SampleEnv
19
20 pool = cx_Oracle.SessionPool(SampleEnv.GetMainUser(),
21 SampleEnv.GetMainPassword(), SampleEnv.GetConnectString(), min=1,
22 max=5, increment=1)
23
24 def ConnectAndDisplay(shardingKey):
25 print("Connecting with sharding key:", shardingKey)
26 with pool.acquire(shardingkey=[shardingKey]) as conn:
27 cursor = conn.cursor()
28 cursor.execute("select sys_context('userenv', 'db_name') from dual")
29 name, = cursor.fetchone()
30 print("--> connected to database", name)
31
32 ConnectAndDisplay(100)
33 ConnectAndDisplay(167)
1010 # Oracle Database must be at 18.1 or higher.
1111 # The user must have been granted the SODA_APP privilege.
1212 #------------------------------------------------------------------------------
13
14 from __future__ import print_function
1513
1614 import cx_Oracle
1715 import SampleEnv
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # SodaBulkInsert.py
6 # Demonstrates the use of SODA bulk insert.
7 #
8 # This script requires cx_Oracle 7.2 and higher.
9 # Oracle Client must be at 18.5 or higher.
10 # Oracle Database must be at 18.1 or higher.
11 # The user must have been granted the SODA_APP privilege.
12 #------------------------------------------------------------------------------
13
14 import cx_Oracle
15 import SampleEnv
16
17 connection = cx_Oracle.connect(SampleEnv.GetMainConnectString())
18
19 # the general recommendation for simple SODA usage is to enable autocommit
20 connection.autocommit = True
21
22 # create the parent object for all SODA work
23 soda = connection.getSodaDatabase()
24
25 # create a new (or open an existing) SODA collection
26 collection = soda.createCollection("SodaBulkInsert")
27
28 # remove all documents from the collection
29 collection.find().remove()
30
31 # define some documents that will be stored
32 inDocs = [
33 dict(name="Sam", age=8),
34 dict(name="George", age=46),
35 dict(name="Bill", age=35),
36 dict(name="Sally", age=43),
37 dict(name="Jill", age=28),
38 dict(name="Cynthia", age=12)
39 ]
40
41 # perform bulk insert
42 resultDocs = collection.insertManyAndGet(inDocs)
43 for doc in resultDocs:
44 print("Inserted SODA document with key", doc.key)
45 print()
46
47 # perform search of all persons under the age of 40
48 print("Persons under the age of 40:")
49 for doc in collection.find().filter({'age': {'$lt': 40}}).getDocuments():
50 print(doc.getContent()["name"] + ",", "key", doc.key)
2020 # This script requires cx_Oracle (5.3 and higher) as well as GeoPandas and its
2121 # dependencies (see http://geopandas.org/install.html).
2222 #------------------------------------------------------------------------------
23
24 from __future__ import print_function
2523
2624 import SampleEnv
2725 import cx_Oracle
88 # add additional functionality (like logging) or create specialized interfaces
99 # for paticular applications.
1010 #------------------------------------------------------------------------------
11
12 from __future__ import print_function
1311
1412 import cx_Oracle
1513 import SampleEnv
+0
-67
samples/Threads.py less more
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # Threads.py
6 # This script demonstrates the use of threads with cx_Oracle. A session pool
7 # is used so that multiple connections are available to perform work on the
8 # database. Only one operation (such as an execute or fetch) can take place at
9 # a time on a connection. In the below example, one of the threads performs
10 # dbms_lock.sleep while the other performs a query.
11 #
12 # This script requires cx_Oracle 2.5 and higher.
13 #------------------------------------------------------------------------------
14
15 from __future__ import print_function
16
17 import cx_Oracle
18 import SampleEnv
19 import threading
20
21 pool = cx_Oracle.SessionPool(SampleEnv.GetMainUser(),
22 SampleEnv.GetMainPassword(), SampleEnv.GetConnectString(), min=2,
23 max=5, increment=1, threaded=True)
24
25 def TheLongQuery():
26 conn = pool.acquire()
27 cursor = conn.cursor()
28 cursor.arraysize = 25000
29 print("TheLongQuery(): beginning execute...")
30 cursor.execute("""
31 select *
32 from
33 TestNumbers
34 cross join TestNumbers
35 cross join TestNumbers
36 cross join TestNumbers
37 cross join TestNumbers
38 cross join TestNumbers""")
39 print("TheLongQuery(): done execute...")
40 while True:
41 rows = cursor.fetchmany()
42 if not rows:
43 break
44 print("TheLongQuery(): fetched", len(rows), "rows...")
45 print("TheLongQuery(): all done!")
46
47
48 def DoALock():
49 conn = pool.acquire()
50 cursor = conn.cursor()
51 print("DoALock(): beginning execute...")
52 cursor.callproc("dbms_lock.sleep", (5,))
53 print("DoALock(): done execute...")
54
55
56 thread1 = threading.Thread(None, TheLongQuery)
57 thread1.start()
58
59 thread2 = threading.Thread(None, DoALock)
60 thread2.start()
61
62 thread1.join()
63 thread2.join()
64
65 print("All done!")
66
3232 # This script requires cx_Oracle 5.3 and higher.
3333 #------------------------------------------------------------------------------
3434
35 from __future__ import print_function
36
3735 import cx_Oracle
3836 import SampleEnv
3937 import sys
4038
4139 # constants
4240 CONNECT_STRING = "localhost/orcl-tg"
43
44 # for Python 2.7 we need raw_input
45 try:
46 input = raw_input
47 except NameError:
48 pass
4941
5042 # create transaction and generate a recoverable error
5143 pool = cx_Oracle.SessionPool(SampleEnv.GetMainUser(),
1515 #
1616 # This script requires cx_Oracle 5.0 and higher.
1717 #------------------------------------------------------------------------------
18
19
20 from __future__ import print_function
2118
2219 import cx_Oracle
2320 import datetime
1313 #
1414 # This script requires cx_Oracle 6.0 and higher.
1515 #------------------------------------------------------------------------------
16
17 from __future__ import print_function
1816
1917 import cx_Oracle
2018 import datetime
00 /*-----------------------------------------------------------------------------
1 * Copyright 2017, 2019, Oracle and/or its affiliates. All rights reserved.
1 * Copyright 2017, 2020, Oracle and/or its affiliates. All rights reserved.
22 *---------------------------------------------------------------------------*/
33
44 /*-----------------------------------------------------------------------------
1616 /
1717
1818 create user &main_user identified by &main_password
19 quota unlimited on users
20 default tablespace users
2119 /
2220
2321 grant
2624 create procedure,
2725 create type,
2826 select any dictionary,
29 change notification
27 change notification,
28 unlimited tablespace
3029 to &main_user
3130 /
3231
3332 grant execute on dbms_aqadm to &main_user
3433 /
35 grant execute on dbms_lock to &main_user
34
35 begin
36 execute immediate 'begin dbms_session.sleep(0); end;';
37 exception
38 when others then
39 begin
40 execute immediate 'grant execute on dbms_lock to &main_user';
41 exception
42 when others then
43 raise_application_error(-20000,
44 'Ensure the following grant is made: ' ||
45 'grant execute on dbms_lock to ' || user ||
46 ' with grant option');
47 end;
48 end;
3649 /
3750
3851 begin
189202 )
190203 /
191204
192 -- create queue table and queues for demonstrating advanced queuing
193 begin
194 dbms_aqadm.create_queue_table('&main_user..BOOK_QUEUE',
205 -- create queue table, queues and subscribers for demonstrating Advanced Queuing
206 begin
207
208 dbms_aqadm.create_queue_table('&main_user..BOOK_QUEUE_TAB',
195209 '&main_user..UDT_BOOK');
196 dbms_aqadm.create_queue('&main_user..BOOKS', '&main_user..BOOK_QUEUE');
197 dbms_aqadm.start_queue('&main_user..BOOKS');
210 dbms_aqadm.create_queue('&main_user..DEMO_BOOK_QUEUE',
211 '&main_user..BOOK_QUEUE_TAB');
212 dbms_aqadm.start_queue('&main_user..DEMO_BOOK_QUEUE');
213
214 dbms_aqadm.create_queue_table('&main_user..RAW_QUEUE_TAB', 'RAW');
215 dbms_aqadm.create_queue('&main_user..DEMO_RAW_QUEUE',
216 '&main_user..RAW_QUEUE_TAB');
217 dbms_aqadm.start_queue('&main_user..DEMO_RAW_QUEUE');
218
219 dbms_aqadm.create_queue_table('&main_user..RAW_QUEUE_MULTI_TAB', 'RAW',
220 multiple_consumers => true);
221 dbms_aqadm.create_queue('&main_user..DEMO_RAW_QUEUE_MULTI',
222 '&main_user..RAW_QUEUE_MULTI_TAB');
223 dbms_aqadm.start_queue('&main_user..DEMO_RAW_QUEUE_MULTI');
224
225 dbms_aqadm.add_subscriber('&main_user..DEMO_RAW_QUEUE_MULTI',
226 sys.aq$_agent('SUBSCRIBER_A', null, null));
227 dbms_aqadm.add_subscriber('&main_user..DEMO_RAW_QUEUE_MULTI',
228 sys.aq$_agent('SUBSCRIBER_B', null, null));
229
198230 end;
199231 /
200232
00 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
11 <html xmlns="http://www.w3.org/1999/xhtml">
22 <head>
3 <title>Python and Oracle Database: Scripting for the Future</title>
3 <title>Python and Oracle Database Tutorial: Scripting for the Future</title>
44 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
55
66 <link rel="stylesheet" href="resources/base.css" type="text/css"/>
88 </head>
99 <body bgcolor="#ffffff" text="#000000">
1010
11 <h1>Python and Oracle Database: Scripting for the Future</h1>
12
13 <img src="resources/community-py-200.png" alt="Python cx_Oracle logo">
11 <h1>Python and Oracle Database Tutorial: Scripting for the Future</h1>
12
13 <img src="resources/community-py-200.png" alt="Python cx_Oracle logo" />
1414
1515 <h2>Contents</h2>
1616
1717 <ul>
18 <li><a href="#preface" >Preface</a></li>
18 <li><a href="#overview" >Overview</a></li>
19 <li><a href="#preface" >Setup</a></li>
1920 <li><a href="#connectioninformation" >Connection Information</a></li>
20 <li><a href="#overview" >Overview</a></li>
21 <li><a href="#lab" >Using Python cx_Oracle 7 with Oracle Database</a></li>
21 <li><a href="#lab" >Using Python cx_Oracle 8 with Oracle Database</a>
2222 <ul>
2323 <li><a href="#connecting">1. Connecting to Oracle</a>
2424 <ul>
3232 </li>
3333 <li><a href="#pooling">2. Connection Pooling</a>
3434 <ul>
35 <li>2.1 Session pooling</li>
36 <li>2.2 Session pool experiments</li>
35 <li>2.1 Connection pooling</li>
36 <li>2.2 Connection pool experiments</li>
3737 <li>2.3 Creating a DRCP Connection</li>
38 <li>2.4 Session pooling and DRCP</li>
38 <li>2.4 Connection pooling and DRCP</li>
3939 <li>2.5 More DRCP investigation</li>
4040 </ul>
4141 </li>
9191 <li>10.1 Message passing with Oracle Advanced Queuing</li>
9292 </ul>
9393 </li>
94 <li><a href="#soda" >11. Simple Oracle Document Access (SODA)</a>
95 <ul>
96 <li>11.1 Inserting JSON Documents</li>
97 <li>11.2 Searching SODA Documents</li>
98 </ul>
99 </li>
94100 </ul>
101 </li>
95102 <li><a href="#summary" >Summary</a></li>
96103 <li><a href="#primer" >Appendix: Python Primer</a></li>
97104 <li><a href="#resources" >Resources</a></li>
98105 </ul>
99106
100 <h2><a name="preface">Preface</a></h2>
101
102 <p>If you are running this tutorial in your own environment, install the following required software:</p>
103
104 <ol>
105 <li><a target="_blank" href="https://www.python.org/">Python</a> (3.6 preferred but 2.7 should work)</li>
106 <li>cx_Oracle (version 7 preferred but 6.3 or later should work) and Oracle Instant Client Package - Basic (version 18.3 preferred but 12.2 should work)
107 <ul>
108 <li><a target="_blank" href="http://cx-oracle.readthedocs.io/en/latest/installation.html#installing-cx-oracle-on-linux">Linux</a></li>
109 <li><a target="_blank" href="http://cx-oracle.readthedocs.io/en/latest/installation.html#installing-cx-oracle-on-macos">macOS</a> - please note the special instructions for macOS in the link.</li>
110 <li><a target="_blank" href="http://cx-oracle.readthedocs.io/en/latest/installation.html#installing-cx-oracle-on-windows">Windows</a></li>
111 </ul>
112 </li>
113 <li>Oracle <a target="_blank" href="http://www.oracle.com/technetwork/database/database-technologies/instant-client/overview/index.html">Instant Client Package - SQL*Plus</a>.</li>
114 </ol>
115
116 <p>To create the schema run:</p>
117
118 <pre>
119 sqlplus sys/yoursyspassword@localhost/orclpdb as sysdba @sql/SetupSamples
120 </pre>
121
122 <h2><a name="connectioninformation">Connection Information</a></h2>
123
124 <p>The database connection information is set in two files:
125 <ul>
126 <li>db_config.py which is imported by the other Python modules.</li>
127 <li>db_config.sql which is used by the other SQL scripts.</li>
128 </ul>
129 </p>
130
131 <p>The username is "pythonhol" with
132 the password "welcome". The connect string is "localhost/orclpdb".
133 See <code>sql/SampleEnv.sql</code>.</p>
134
135 <p>It is easist to have a local pluggable database with the service
136 'orclpdb' configured. If your database is not local, or has a
137 different service, you will need to modify the connection information in db_config.py and db_config.sql.</p>
138
139 <p>The following sections may need adjusting, depending on how you
140 have set up your environment.</p>
141
142107 <h2><a name="overview">Overview</a></h2>
143108
144109 <p>This tutorial is an introduction to using Python with Oracle
151116 <code>tutorial/solutions</code> directory has scripts with the
152117 suggested code changes.</p>
153118
154 <p>Use the Desktop icons to start editors and terminal windows.</p>
155
156119 <p>If you are new to Python review the <a href="#primer">Appendix:
157120 Python Primer</a> to gain an understanding of the language. </p>
121
122 <p>When you have finished this tutorial, we recommend reviewing the <a
123 href="http://cx-oracle.readthedocs.org/en/latest/index.html" >cx_Oracle
124 documention</a>. </p>
125
126 <h2><a name="preface">Setup</a></h2>
127
128 <p>These cx_Oracle tutorial instructions can be found <a href="https://oracle.github.io/python-cx_Oracle/samples/tutorial/Python-and-Oracle-Database-Scripting-for-the-Future.html" >here</a>. The files used in them can be found in the <a href="https://github.com/oracle/python-cx_Oracle/tree/master/samples/tutorial" >cx_Oracle GitHub repository</a>.</p>
129
130 <p>If you are running this tutorial in your own environment, install the required software:</p>
131
132 <ol>
133 <li><p><a target="_blank" href="https://www.python.org/">Python</a>. Version 3.6 (or later) is preferred.</p></li>
134 <li><p>cx_Oracle version 7.3, or version 8, or later.</p></li>
135 <li><p>Oracle Client libraries.</p>
136 <ul>
137 <li><a target="_blank" href="https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html#installing-cx-oracle-on-linux">Linux</a></li>
138 <li><a target="_blank" href="https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html#installing-cx-oracle-on-macos">macOS</a> - please note the special instructions for macOS in the link.</li>
139 <li><a target="_blank" href="https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html#installing-cx-oracle-on-windows">Windows</a></li>
140 </ul>
141 </li>
142
143 <li><p>SQL*Plus such as from the Oracle <a target="_blank" href="https://www.oracle.com/database/technologies/instant-client.html">Instant Client SQL*Plus Package</a>.</p></li>
144 </ol>
145
146 <p>The Advanced Queuing section requires Oracle client 12.2 or later. The SODA section requires Oracle client 18.5, or later, and Oracle Database 18 or later.</p>
147
148 <p>To create the schema run:</p>
149
150 <pre>
151 sqlplus sys/yoursyspassword@localhost/orclpdb1 as sysdba @sql/SetupSamples
152 </pre>
153
154 <p>If DRCP is not already running, connect to the SYS user again in
155 SQL*Plus and execute the command:</p>
156
157 <pre>
158 execute dbms_connection_pool.start_pool()
159 </pre>
160
161
162 <h2><a name="connectioninformation">Connection Information</a></h2>
163
164 <p>Database credentials and the connection string are set in two files:</p>
165
166 <ul>
167 <li><p>db_config.py which is imported by the other Python modules.</p></li>
168 <li><p>db_config.sql which is used by the other SQL scripts.</p></li>
169 </ul>
170
171 <p>The username is "pythonhol" with
172 the password "welcome". The connect string is "localhost/orclpdb1".</p>
173
174 <p>If your database is not local, or has a different service, you will need to
175 modify the connection information in these two files. If you are installing
176 your own schema, you can also modify the default username and password in
177 <code>sql/SampleEnv.sql</code>.</p>
178
179 <p>The following sections may need adjusting, depending on how you
180 have set up your environment.</p>
158181
159182 <h2><a name="lab">Using Python cx_Oracle 7 with Oracle Database</a></h2>
160183
165188 <ul>
166189 <li>
167190 <h3><a name="connecting">1. Connecting to Oracle</a></h3>
191
192 <p>You can connect from Python to a local or remote database. <i>Documentation
193 link for further reading: <a
194 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html"
195 >Connecting to Oracle Database</a></i>.</p>
196
168197 <ul>
169198 <li>
170199 <h4>1.1 Review the connection credentials</h4>
173202 <pre>
174203 user = "pythonhol"
175204 pw = "welcome"
176 dsn = "localhost/orclpdb"
205 dsn = "localhost/orclpdb1"
177206 </pre>
178207 <code>db_config.sql</code>
179208 <pre>
180209 def user = "pythonhol"
181210 def pw = "welcome"
182 def connect_string = "localhost/orclpdb"
211 def connect_string = "localhost/orclpdb1"
183212 </pre>
184213
185 <p>By default they connect to the 'orclpdb' database service on the same machine as Python. You can modify the values in both files to match the connection information for your environment.</p>
214 <p>By default they connect to the 'orclpdb1' database service on the same machine as Python. You can modify the values in both files to match the connection information for your environment.</p>
186215
187216 </li>
188217
206235 the db_config.py module. In this case, Oracle's Easy Connect connection
207236 string syntax is used. It consists of the hostname of your
208237 machine, <code>localhost</code>, and the database service name
209 <code>orclpdb</code>. </p>
238 <code>orclpdb1</code>. </p>
210239
211240 <p>Open a command terminal and change to the <code>tutorial</code> directory:</p>
212241
396425
397426 <li><h3><a name="pooling">2. Connection Pooling</a></h3>
398427
428 <p>Connection pooling is important for performance when applications
429 frequently connect and disconnect from the database. Pooling also gives
430 the best support for Oracle high availability features. <i>Documentation
431 link for further reading: <a
432 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html#connection-pooling"
433 >Connection Pooling</a></i>.</p>
434
435
399436 <ul>
400 <li> <h4>2.1 Session pooling</h4>
437 <li> <h4>2.1 Connection pooling</h4>
401438
402439 <p>Review the code contained in <code>connect_pool.py</code>:</p>
403440 <pre>
429466 </pre>
430467
431468 <p>The <code>SessionPool()</code> function creates a pool of
432 Oracle "sessions" for the user. Sessions in the pool
433 can be used by cx_Oracle connections by calling
434 <code>pool.acquire()</code>. The initial pool size is 2 sessions.
435 The maximum size is 5 sessions. When the pool needs to grow, 1 new
436 session will be created at a time. The pool can shrink back to the
437 minimum size of 2 when sessions are no longer in use.</p>
469 Oracle connections for the user. Connections in the pool can
470 be used by cx_Oracle by calling <code>pool.acquire()</code>.
471 The initial pool size is 2 connections. The maximum size is 5
472 connections. When the pool needs to grow, 1 new connection
473 will be created at a time. The pool can shrink back to the
474 minimum size of 2 when connections are no longer in use.</p>
438475
439476 <p>The <code>def Query():</code> line creates a method that
440477 is called by each thread. </p>
441478
442479 <p>In the method, the <code>pool.acquire()</code> call gets
443 one session from the pool (as long as less than 5 are
444 already in use). This session is used in a loop of 4
480 one connection from the pool (as long as less than 5 are
481 already in use). This connection is used in a loop of 4
445482 iterations to query the sequence <code>myseq</code>. At the
446483 end of the method, cx_Oracle will automatically close the
447 cursor and release the session back to the pool for
484 cursor and release the connection back to the pool for
448485 reuse.</p>
449486
450487 <p>The <code>seqval, = cur.fetchone()</code> line fetches a
467504 </li>
468505
469506 <li>
470 <h4>2.2 Session pool experiments</h4>
507 <h4>2.2 Connection pool experiments</h4>
471508
472509
473510 <p>Review <code>connect_pool2.py</code>, which has a loop for the number
509546
510547 <p>Experiment with different values of the pool parameters and
511548 <code>numberOfThreads</code>. Larger initial pool sizes will make the
512 pool creation slower, but the sessions will be available immediately
513 when needed. When <code>numberOfThreads</code> exceeds the maximum
514 size of the pool, the <code>acquire()</code> call will generate an
515 error. Adding the additional argument <code>getmode =
549 pool creation slower, but the connections will be available immediately
550 when needed. When <code>numberOfThreads</code> exceeds the maximum size
551 of the pool, the <code>acquire()</code> call will generate an error such
552 as "ORA-24459: OCISessionGet() timed out waiting for pool to create new
553 connections". Adding the additional argument <code>getmode =
516554 cx_Oracle.SPOOL_ATTRVAL_WAIT</code> to the
517555 <code>cx_Oracle.SessionPool()</code> call will prevent the exception
518 from taking place, but will cause the thread to wait until a session
556 from taking place, but will cause the thread to wait until a connection
519557 is available.</p>
520558
521559 <p>Pool configurations where <code>min</code> is the same as
522560 <code>max</code> (and <code>increment = 0</code>) are often
523 recommended as a way to avoid connection storms on the database
524 server.</p>
561 recommended as a best practice. This avoids connection storms on the
562 database server.</p>
525563
526564 </li>
527565
533571 server processes.</p>
534572
535573 <p>Below left is a diagram without DRCP. Every application
536 connection or session has its own 'dedicated' database server
574 connection has its own 'dedicated' database server
537575 process. Application connect and close calls require the expensive
538576 create and destroy of those database server processes. To avoid these
539577 costs, scripts may hold connections open even when not doing
545583 <table cellspacing="0" cellpadding="30" border="0" >
546584 <tr>
547585 <td>
548 <img width="400" src="resources/python_nopool.png" >
549 <p><center><strong>Without DRCP</strong></center></p>
586 <img width="400" src="resources/python_nopool.png" alt="Picture of 3-tier application architecture without DRCP showing connections from multiple application processes each going to a server process in the database tier" />
587 <div align="center"><p><strong>Without DRCP</strong></p></div>
550588 </td>
551589 <td>
552 <img width="400" src="resources/python_pool.png" >
553 <p><center><strong>With DRCP</strong></center></p>
590 <img width="400" src="resources/python_pool.png" alt="Picture of 3-tier application architecture with DRCP showing connections from multiple application processes going to a pool of server process in the database tier" />
591 <div align="center"><p><strong>With DRCP</strong></p></div>
554592 </td>
555593 </tr>
556594 </table>
560598 required. However, if database host memory is large enough, then
561599 the default, 'dedicated' server process model is generally
562600 recommended. If DRCP is enabled, it is best used in conjunction
563 with cx_Oracle session pooling.</p>
601 with cx_Oracle's middle-tier connection pooling.</p>
564602
565603 <p>Batch scripts doing long running jobs should generally use
566604 dedicated connections. Both dedicated and DRCP servers can be used
605643 </li>
606644
607645 <li>
608 <h4>2.4 Session pooling and DRCP</h4>
609
610 <p>DRCP works well with session pooling.</p>
646 <h4>2.4 Connection pooling and DRCP</h4>
647
648 <p>DRCP works well with cx_Oracle's connection pooling.</p>
611649
612650 <p>Edit <code>connect_pool2.py</code>, reset any changed pool options, and modify it to use DRCP:</p>
613651 <pre>
646684
647685 <pre><strong>python connect_pool2.py</strong></pre>
648686
649 <p>If you get the error "ORA-24418: Cannot open further
687 <p>If you get an error "ORA-24459: OCISessionGet() timed out waiting for
688 pool to create new connections" or "ORA-24418: Cannot open further
650689 sessions", it is because connection requests are being made
651690 while the pool is starting or growing. Add the argument
652691 <code>getmode = cx_Oracle.SPOOL_ATTRVAL_WAIT</code> to the
653692 <code>cx_Oracle.SessionPool()</code> call so connection
654 requests wait for pooled sessions to be available.</p>
693 requests wait for pooled connections to be available.</p>
655694
656695 <p>Open a new a terminal window and invoke SQL*Plus:</p>
657696
669708 <li>
670709 <h4>2.5 More DRCP investigation</h4>
671710
672 <p>To explore the behaviors of session and DRCP pooling futher,
711 <p>To explore the behaviors of cx_Oracle connection pooling and DRCP pooling futher,
673712 you could try changing the purity to
674713 <code>cx_Oracle.ATTR_PURITY_NEW</code> to see the effect on the
675714 DRCP NUM_MISSES statistic.</p>
687726
688727 </li>
689728 </ul>
729 </li>
690730
691731 <li><h3><a name="fetching">3. Fetching Data</a> </h3>
732
733
734 <p>Executing SELECT queries is the primary way to get data from Oracle
735 Database. <i>Documentation link for further reading: <a
736 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/sql_execution.html"
737 >SQL Queries</a></i>.</p>
692738
693739 <ul>
694740 <li><h4>3.1 A simple query</h4>
696742 <p>There are a number of functions you can use to query an Oracle
697743 database, but the basics of querying are always the same:</p>
698744
699 <p>1. Parse the statement for execution.<br />
745 <p>1. Execute the statement.<br />
700746 2. Bind data values (optional).<br />
701 3. Execute the statement.<br />
702 4. Fetch the results from the database.</p>
747 3. Fetch the results from the database.</p>
703748
704749 <p>Review the code contained in <code>query2.py</code>:</p>
705750
731776
732777 </li>
733778
734 <li><h4>3.2 Using fetchone()</h3>
779 <li><h4>3.2 Using fetchone()</h4>
735780
736781 <p>When the number of rows is large, the <code>fetchall()</code>
737782 call may use too much memory.</p>
909954
910955 <pre><strong>python query_arraysize.py</strong></pre>
911956
912 <p>Reload a few times to see the average times.</p>
957 <p>Rerun a few times to see the average times.</p>
913958
914959 <p>Experiment with different arraysize values. For example, edit
915960 <code>query_arraysize.py</code> and change the arraysize to:</p>
932977 <p>If you know a query only returns a few records,
933978 decrease the arraysize from the default to reduce memory
934979 usage.</p>
935
936 </ul>
980 </li>
981 </ul>
937982
938983 </li>
939984
940985 <li><h3><a name="binding">4. Binding Data</a></h3>
941986
942 <p>Bind variables enable you to re-execute statements with new data
943 values, without the overhead of reparsing the statement. Bind
944 variables improve code reusability, and can reduce the risk of SQL
945 injection attacks.</p>
987 <p>Bind variables enable you to re-execute statements with new data values
988 without the overhead of re-parsing the statement. Binding improves code
989 reusability, improves application scalability, and can reduce the risk of SQL
990 injection attacks. Using bind variables is strongly recommended.
991 <i>Documentation link for further reading: <a
992 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html" >Using
993 Bind Variables</a></i>.</p>
946994
947995 <ul>
948996
949 <li><h4>4.1 Binding in queries</h3>
997 <li><h4>4.1 Binding in queries</h4>
950998
951999 <p>Review the code contained in <code>bind_query.py</code>:</p>
9521000
9571005 con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
9581006 cur = con.cursor()
9591007
960 cur.prepare("select * from dept where deptno = :id order by deptno")
961
962 cur.execute(None, id = 20)
1008 sql = "select * from dept where deptno = :id order by deptno"
1009
1010 cur.execute(sql, id = 20)
9631011 res = cur.fetchall()
9641012 print(res)
9651013
966 cur.execute(None, id = 10)
1014 cur.execute(sql, id = 10)
9671015 res = cur.fetchall()
9681016 print(res)
9691017 </pre>
9701018
971 <p>The statement contains a bind variable "<code>:id</code>"
972 placeholder. The statement is only prepared once but executed
973 twice with different values for the <code>WHERE</code>
974 clause.</p>
975
976 <p> The special symbol "<code>None</code>" is used in place of
977 the statement text argument to <code>execute()</code> because
978 the <code>prepare()</code> method has already set the
979 statement. The second argument to the <code>execute()</code>
980 call can be a sequence (binding by position) or a dictionary (binding
981 by name) or an arbitrary number of named arguments (also binding by
982 name), which is what has been done in this example. In the first execute
983 call, this dictionary has the value 20 for the key of "id". The second
984 execute uses the value 10. </p>
1019 <p>The statement contains a bind variable "<code>:id</code>" placeholder.
1020 The statement is executed twice with different values for the
1021 <code>WHERE</code> clause.</p>
9851022
9861023 <p>From a terminal window, run:</p>
9871024
9891026
9901027 <p>The output shows the details for the two departments.</p>
9911028
1029 <p>An arbitrary number of named arguments can be used in an
1030 <code>execute()</code> call. Each argument name must match a bind
1031 variable name. Alternatively, instead of passing multiple arguments you
1032 could pass a second argument to <code>execute()</code> that is a sequence
1033 or a dictionary. Later examples show these syntaxes.</p>
1034
1035 <p>cx_Oracle uses Oracle Database's Statement Cache. As long as the
1036 statement you pass to <code>execute()</code> is in that cache, you can use
1037 different bind values and still avoid a full statement parse. The
1038 statement cache size is configurable for each connection. To see the
1039 default statement cache size, edit <code>bind_query.py</code> and add a
1040 line at the end:</p>
1041
1042 <pre>
1043 print(con.stmtcachesize)
1044 </pre>
1045
1046 <p>Re-run the file.</p>
1047
1048 <p>In your applications you would set the statement cache size to the
1049 number of unique statements commonly executed.</p>
1050
9921051 </li>
993 <li><h4>4.2 Binding in inserts</h3>
1052
1053 <li><h4>4.2 Binding in inserts</h4>
9941054
9951055 <p>Review the code in <code>bind_insert.sql </code> creating a table
9961056 for inserting data:</p>
10301090 <p>The '<code>rows</code>' array contains the data to be inserted.</p>
10311091
10321092 <p>The <code>executemany()</code> call inserts all rows. This
1033 calls allows "array binding", which is an efficient way to
1093 call uses "array binding", which is an efficient way to
10341094 insert multiple records.</p>
10351095
10361096 <p>The final part of the script queries the results back and displays them as a list of tuples.</p>
10451105
10461106 </li>
10471107
1048 <li><h4>4.3 Batcherrors</h3>
1108 <li><h4>4.3 Batcherrors</h4>
10491109
10501110 <p>The Batcherrors features allows invalid data to be identified
10511111 while allowing valid data to be inserted.</p>
11091169
11101170 <p>The other data gets inserted and is queried back.</p>
11111171
1112 <p>At the end of the script, cx_Oracle will rollback an uncommitted transaction. If you want to commit results, you can use:</p>
1172 <p>At the end of the script, cx_Oracle will roll back an uncommitted transaction. If you want to commit results, you can use:</p>
11131173
11141174 <pre>con.commit()</pre>
11151175
1116 <p>To force a rollback in cx_Oracle, use:</p>
1176 <p>To force cx_Oracle to roll back, use:</p>
11171177
11181178 <pre>con.rollback()</pre>
11191179
11201180 </li>
11211181
1122 <li><h4>4.4 Binding named objects</h3>
1182 <li><h4>4.4 Binding named objects</h4>
11231183
11241184 <p>cx_Oracle can fetch and bind named object types such as Oracle's
11251185 Spatial Data Objects (SDO).</p>
11271187 <p>In a terminal window, start SQL*Plus using the lab credentials and connection string, such as:</p>
11281188
11291189 <pre>
1130 sqlplus pythonhol/welcome@localhost/orclpdb
1190 sqlplus pythonhol/welcome@localhost/orclpdb1
11311191 </pre>
11321192
11331193 <p>Use the SQL*Plus DESCRIBE command to look at the SDO definition:</p>
11611221 cur.execute("""begin
11621222 execute immediate 'drop table testgeometry';
11631223 exception when others then
1164 if sqlcode <> -942 then
1224 if sqlcode &lt;&gt; -942 then
11651225 raise;
11661226 end if;
11671227 end;""")
12781338 <p>The <code>gettype()</code> and <code>newobject()</code> methods can
12791339 also be used to bind PL/SQL Records and Collections.</p>
12801340
1341 <p>Before deciding to use objects, review your performance goals because
1342 working with scalar values can be faster.</p>
1343
12811344 </li>
12821345 </ul>
12831346
12901353 PL/SQL lets all database applications reuse logic, no matter how the
12911354 application accesses the database. Many data-related operations can
12921355 be performed in PL/SQL faster than extracting the data into a
1293 program (for example, Python) and then processing it.</p>
1356 program (for example, Python) and then processing it. <i>Documentation link
1357 for further reading: <a
1358 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/plsql_execution.html"
1359 >PL/SQL Execution</a></i>.</p>
12941360
12951361 <ul>
1296 <li><h4>5.1 PL/SQL functions</h3>
1362 <li><h4>5.1 PL/SQL functions</h4>
12971363
12981364 <p>Review <code>plsql_func.sql</code> which creates a PL/SQL
12991365 stored function <code>myfunc()</code> to insert a row into a new
13431409
13441410 </li>
13451411
1346 <li><h4>5.2 PL/SQL procedures</h3>
1412 <li><h4>5.2 PL/SQL procedures</h4>
13471413
13481414 <p>Review <code>plsql_proc.sql</code> which creates a PL/SQL procedure
13491415 <code>myproc()</code> to accept two parameters. The second parameter
13951461
13961462 <li><h3><a name="handlers">6. Type Handlers</a></h3>
13971463
1464 <p>Type handlers enable applications to alter data that is fetched from, or sent
1465 to, the database. <i>Documentation links for further reading: <a
1466 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/sql_execution.html#changing-fetched-data-types-with-output-type-handlers"
1467 >Changing Fetched Data Types with Output Type Handlers</a> and <a
1468 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html#changing-bind-data-types-using-an-input-type-handler"
1469 >Changing Bind Data Types using an Input Type Handler</a></i>.</p>
1470
13981471 <ul>
13991472 <li>
14001473 <h4>6.1 Basic output type handler</h4>
15571630 cur.execute("""begin
15581631 execute immediate 'drop table testgeometry';
15591632 exception when others then
1560 if sqlcode <> -942 then
1633 if sqlcode &lt;&gt; -942 then
15611634 raise;
15621635 end if;
15631636 end;""")
16601733
16611734 <li><h3><a name="lobs">7. LOBs</a></h3>
16621735
1736 <p>Oracle Database "LOB" long objects can be streamed using a LOB
1737 locator, or worked with directly as strings or bytes. <i>Documentation link
1738 for further reading: <a
1739 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/lob_data.html"
1740 >Using CLOB and BLOB Data</a></i>.</p>
1741
16631742 <ul>
16641743 <li>
16651744 <h4>7.1 Fetching a CLOB using a locator</h4>
16841763 con.commit()
16851764
16861765 print("Querying data...")
1687 cur.prepare("select * from testclobs where id = :id")
1688 cur.execute(None, {'id': 1})
1766 cur.execute("select * from testclobs where id = :id", {'id': 1})
16891767 (id, clob) = cur.fetchone()
16901768 print("CLOB length:", clob.size())
16911769 clobdata = clob.read()
16931771 </pre>
16941772
16951773 <p>This inserts some test string data and then fetches one
1696 record into <code>clob</code>, which is a cx_Oracle LOB Object.
1697 Methods on LOB include <code>size()</code> and
1774 record into <code>clob</code>, which is a cx_Oracle character
1775 LOB Object. Methods on LOB include <code>size()</code> and
16981776 <code>read()</code>.</p>
16991777
17001778 <p>To see the output, run the file:</p>
17401818 con.outputtypehandler = OutputTypeHandler</strong>
17411819
17421820 print("Querying data...")
1743 cur.prepare("select * from testclobs where id = :id")
1744 cur.execute(None, {'id': 1})
1821 cur.execute("select * from testclobs where id = :id", {'id': 1})
17451822 <strong>(id, clobdata) = cur.fetchone()
17461823 print("CLOB length:", len(clobdata))
17471824 print("CLOB data:", clobdata)</strong>
18401917
18411918 <p>Subclassing enables application to "hook" connection and cursor
18421919 creation. This can be used to alter or log connection and execution
1843 parameters, and to extend cx_Oracle functionality. </p>
1920 parameters, and to extend cx_Oracle functionality. <i>Documentation link for
1921 further reading: <a
1922 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/tracing_sql.html"
1923 >Tracing SQL and PL/SQL Statements</a></i>.</p>
18441924
18451925 <ul>
18461926 <li><h4>9.1 Subclassing connections</h4>
19452025 </li>
19462026
19472027 <li><h3><a name="aq">10. Advanced Queuing</a></h3>
2028
2029 <p>Oracle Advanced Queuing (AQ) allows messages to be passed between
2030 applications. <i>Documentation link for further reading: <a
2031 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/aq.html" >Oracle
2032 Advanced Queuing (AQ)</a></i>.</p>
2033
19482034 <ul>
1949 <li><h4>10.1 Message passing with Oracle Advanced Queuing</h4></li>
2035 <li><h4>10.1 Message passing with Oracle Advanced Queuing</h4>
19502036
19512037 <p>Review <code>aq.py</code>:</p>
19522038
19702056 dbms_aqadm.drop_queue_table('""" + QUEUE_TABLE_NAME + """');
19712057 execute immediate 'drop type """ + BOOK_TYPE_NAME + """';
19722058 exception when others then
1973 if sqlcode <> -24010 then
2059 if sqlcode &lt;&gt; -24010 then
19742060 raise;
19752061 end if;
19762062 end;""")
19772063
1978 # Create type
2064 # Create a type
19792065 print("Creating books type UDT_BOOK...")
19802066 cur.execute("""
19812067 create type %s as object (
19872073 # Create queue table and queue and start the queue
19882074 print("Creating queue table...")
19892075 cur.callproc("dbms_aqadm.create_queue_table",
1990 (QUEUE_TABLE_NAME, BOOK_TYPE_NAME))
2076 (QUEUE_TABLE_NAME, BOOK_TYPE_NAME))
19912077 cur.callproc("dbms_aqadm.create_queue", (QUEUE_NAME, QUEUE_TABLE_NAME))
19922078 cur.callproc("dbms_aqadm.start_queue", (QUEUE_NAME,))
19932079
2080 booksType = con.gettype(BOOK_TYPE_NAME)
2081 queue = con.queue(QUEUE_NAME, booksType)
2082
19942083 # Enqueue a few messages
1995 booksType = con.gettype(BOOK_TYPE_NAME)
1996 book1 = booksType.newobject()
1997 book1.TITLE = "The Fellowship of the Ring"
1998 book1.AUTHORS = "Tolkien, J.R.R."
1999 book1.PRICE = decimal.Decimal("10.99")
2000 book2 = booksType.newobject()
2001 book2.TITLE = "Harry Potter and the Philosopher's Stone"
2002 book2.AUTHORS = "Rowling, J.K."
2003 book2.PRICE = decimal.Decimal("7.99")
2004 options = con.enqoptions()
2005 messageProperties = con.msgproperties()
2006 for book in (book1, book2):
2007 print("Enqueuing book", book.TITLE)
2008 con.enq(QUEUE_NAME, options, messageProperties, book)
2009 con.commit()
2084 print("Enqueuing messages...")
2085
2086 BOOK_DATA = [
2087 ("The Fellowship of the Ring", "Tolkien, J.R.R.", decimal.Decimal("10.99")),
2088 ("Harry Potter and the Philosopher's Stone", "Rowling, J.K.",
2089 decimal.Decimal("7.99"))
2090 ]
2091
2092 for title, authors, price in BOOK_DATA:
2093 book = booksType.newobject()
2094 book.TITLE = title
2095 book.AUTHORS = authors
2096 book.PRICE = price
2097 print(title)
2098 queue.enqOne(con.msgproperties(payload=book))
2099 con.commit()
20102100
20112101 # Dequeue the messages
2012 options = con.deqoptions()
2013 options.navigation = cx_Oracle.DEQ_FIRST_MSG
2014 options.wait = cx_Oracle.DEQ_NO_WAIT
2015 while con.deq(QUEUE_NAME, options, messageProperties, book):
2016 print("Dequeued book", book.TITLE)
2017 con.commit()
2102 print("\nDequeuing messages...")
2103 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
2104 while True:
2105 props = queue.deqOne()
2106 if not props:
2107 break
2108 print(props.payload.TITLE)
2109 con.commit()
2110
2111 print("\nDone.")
20182112 </pre>
20192113
20202114 <p>This file sets up Advanced Queuing using Oracle's DBMS_AQADM
2021 package. The queue is used for passing Oracle UDT_BOOK objects.</p>
2115 package. The queue is used for passing Oracle UDT_BOOK objects. The
2116 file uses AQ interface features enhanced in cx_Oracle 7.2.</p>
20222117
20232118 <p>Run the file:</p>
20242119
20292124 <p>To experiment, split the code into three files: one to create and
20302125 start the queue, and two other files to queue and dequeue messages.
20312126 Experiment running the queue and dequeue files concurrently in
2032 separate terminal windows. If you are stuck, look in the
2033 <code>solutions</code> directory at the <code>aq-dequeue.py</code>,
2034 <code>aq-enqueue.py</code> and <code>aq-queuestart.py</code>
2035 files.</p>
2036
2037 <p>Try changing the dequeue options and mode. For example change the
2038 dequeue <code>options.wait</code> value to
2039 <code>cx_Oracle.DEQ_WAIT_FOREVER</code>.</p>
2040
2127 separate terminal windows.</p>
2128
2129 <p>Try removing the <code>commit()</code> call in
2130 <code>aq-dequeue.py</code>. Now run <code>aq-enqueue.py</code> once
2131 and then <code>aq-dequeue.py</code> several times. The same messages
2132 will be available each time you try to dequeue them.</p>
2133
2134 <p>Change <code>aq-dequeue.py</code> to commit in a separate
2135 transaction by changing the "visibility" setting:</p>
2136
2137 <pre>
2138 queue.deqOptions.visibility = cx_Oracle.DEQ_IMMEDIATE
2139 </pre>
2140
2141 <p>This gives the same behavior as the original code.</p>
2142
2143 <p>Now change the options of enqueued messages so that they expire from the
2144 queue if they have not been dequeued after four seconds:</p>
2145
2146 <pre>
2147 queue.enqOne(con.msgproperties(payload=book, expiration=4))
2148 </pre>
2149
2150 <p>Now run <code>aq-enqueue.py</code> and wait four seconds before you
2151 run <code>aq-dequeue.py</code>. There should be no messages to
2152 dequeue. </p>
2153
2154 <p>If you are stuck, look in the <code>solutions</code> directory at
2155 the <code>aq-dequeue.py</code>, <code>aq-enqueue.py</code> and
2156 <code>aq-queuestart.py</code> files.</p>
2157
2158 </li>
20412159 </ul>
20422160 </li>
20432161
2044 </ol>
2162 <li><h3><a name="soda">11. Simple Oracle Document Access (SODA)</a></h3>
2163
2164 <p>Simple Oracle Document Access (SODA) is a set of NoSQL-style APIs.
2165 Documents can be inserted, queried, and retrieved from Oracle
2166 Database. By default, documents are JSON strings. SODA APIs
2167 exist in many languages. <i>Documentation link for further reading: <a
2168 href="https://cx-oracle.readthedocs.io/en/latest/user_guide/soda.html" >Simple
2169 Oracle Document Access (SODA)</a></i>.</p>
2170
2171 <ul>
2172
2173 <li><h4>11.1 Inserting JSON Documents</h4>
2174
2175 <p>Review <code>soda.py</code>:</p>
2176
2177 <pre>
2178 import cx_Oracle
2179 import db_config
2180
2181 con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
2182
2183 soda = con.getSodaDatabase()
2184
2185 collection = soda.createCollection("friends")
2186
2187 content = {'name': 'Jared', 'age': 35, 'address': {'city': 'Melbourne'}}
2188
2189 doc = collection.insertOneAndGet(content)
2190 key = doc.key
2191
2192 doc = collection.find().key(key).getOne()
2193 content = doc.getContent()
2194 print('Retrieved SODA document dictionary is:')
2195 print(content)
2196 </pre>
2197
2198 <p><code>soda.createCollection()</code> will create a new
2199 collection, or open an existing collection, if the name is
2200 already in use.</p>
2201
2202 <p><code>insertOneAndGet()</code> inserts the content of a
2203 document into the database and returns a SODA Document Object.
2204 This allows access to meta data such as the document key. By
2205 default, document keys are automatically generated.</p>
2206
2207 <p>The <code>find()</code> method is used to begin an operation
2208 that will act upon documents in the collection.</p>
2209
2210 <p><code>content</code> is a dictionary. You can also get a JSON string
2211 by calling <code>doc.getContentAsString()</code>.</p>
2212
2213 <p>Run the file:</p>
2214
2215 <pre><strong>python soda.py</strong></pre>
2216
2217 <p>The output shows the content of the new document.</p>
2218
2219 </li>
2220
2221 <li><h4>11.2 Searching SODA Documents</h4>
2222
2223 <p>Extend <code>soda.py</code> to insert some more documents and
2224 perform a find filter operation:</p>
2225
2226 <pre>
2227 myDocs = [
2228 {'name': 'Gerald', 'age': 21, 'address': {'city': 'London'}},
2229 {'name': 'David', 'age': 28, 'address': {'city': 'Melbourne'}},
2230 {'name': 'Shawn', 'age': 20, 'address': {'city': 'San Francisco'}}
2231 ]
2232 collection.insertMany(myDocs)
2233
2234 filterSpec = { "address.city": "Melbourne" }
2235 myDocuments = collection.find().filter(filterSpec).getDocuments()
2236
2237 print('Melbourne people:')
2238 for doc in myDocuments:
2239 print(doc.getContent()["name"])
2240 </pre>
2241
2242 <p>Run the script again:</p>
2243
2244 <pre><strong>python soda.py</strong></pre>
2245
2246 <p>The find operation filters the collection and returns
2247 documents where the city is Melbourne. Note the
2248 <code>insertMany()</code> method is currently in preview.</p>
2249
2250 <p>SODA supports query by example (QBE) with an extensive set of
2251 operators. Extend <code>soda.py</code> with a QBE to find
2252 documents where the age is less than 25:</p>
2253
2254 <pre>
2255 filterSpec = {'age': {'$lt': 25}}
2256 myDocuments = collection.find().filter(filterSpec).getDocuments()
2257
2258 print('Young people:')
2259 for doc in myDocuments:
2260 print(doc.getContent()["name"])
2261 </pre>
2262
2263 <p>Running the script displays the names.</p>
2264
2265 </li>
2266 </ul>
2267
2268 </li>
2269
2270 </ul>
20452271
20462272 <h2><a name="summary">Summary</a></h2>
20472273 <p>In this tutorial, you have learned how to: </p>
20482274 <ul>
20492275 <li>Create connections</li>
2050 <li>Use sessions pooling and Database Resident Connection Pooling</li>
2276 <li>Use cx_Oracle connection pooling and Database Resident Connection Pooling</li>
20512277 <li>Execute queries and fetch data</li>
20522278 <li>Use bind variables</li>
20532279 <li>Use PL/SQL stored functions and procedures</li>
20542280 <li>Extend cx_Oracle classes</li>
20552281 <li>Use Oracle Advanced Queuing</li>
2282 <li>Use the "SODA" document store API</li>
20562283 </ul>
20572284
2285 <p>For further reading see the <a
2286 href="https://cx-oracle.readthedocs.io/en/latest/index.html" >cx_Oracle
2287 documentation</a>.</p>
20582288
20592289 <h2><a name="primer">Appendix: Python Primer</a></h2>
20602290
20612291 <p>Python is a dynamically typed scripting language. It is most
2062 often used to run command-line scripts but is also used in Web
2063 applications.</p>
2292 often used to run command-line scripts but is also used for web
2293 applications and web services.</p>
20642294
20652295 <h4>Running Python</h4>
20662296
21422372 <p> Strings and variables can be displayed with a <code>print()</code> function:</p>
21432373 <pre>print('Hello, World!')
21442374 print('Value:', count)</pre>
2145
2146 <P>Note the <a
2147 href="https://docs.python.org/3.0/whatsnew/3.0.html#print-is-a-function"
2148 ><code>print</code></a> syntax and output is different in Python
2149 2. Examples in this lab use <code>from __future__ import print_function
2150 </code> so that they run with Python 2 and Python 3.</p>
21512375
21522376 <h4>Data Structures</h4>
21532377
22742498 <div class="footer"></div>
22752499 <table border="0" cellpadding="10" cellspacing="0" width="100%">
22762500 <tbody><tr>
2277 <td align="right" width="54%">Copyright &copy; 2017, Oracle and/or its affiliates. All rights reserved</td>
2501 <td align="right" width="54%">Copyright &copy; 2017, 2020, Oracle and/or its affiliates. All rights reserved</td>
22782502 </tr>
22792503 <tr><td colspan="2"></td></tr>
22802504 </tbody>
22812505 </table>
22822506
2283
2284 </div>
22852507 </body>
22862508 </html>
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import decimal
3129 end if;
3230 end;""")
3331
34 # Create type
32 # Create a type
3533 print("Creating books type UDT_BOOK...")
3634 cur.execute("""
3735 create type %s as object (
4341 # Create queue table and queue and start the queue
4442 print("Creating queue table...")
4543 cur.callproc("dbms_aqadm.create_queue_table",
46 (QUEUE_TABLE_NAME, BOOK_TYPE_NAME))
44 (QUEUE_TABLE_NAME, BOOK_TYPE_NAME))
4745 cur.callproc("dbms_aqadm.create_queue", (QUEUE_NAME, QUEUE_TABLE_NAME))
4846 cur.callproc("dbms_aqadm.start_queue", (QUEUE_NAME,))
4947
48 booksType = con.gettype(BOOK_TYPE_NAME)
49 queue = con.queue(QUEUE_NAME, booksType)
50
5051 # Enqueue a few messages
51 booksType = con.gettype(BOOK_TYPE_NAME)
52 book1 = booksType.newobject()
53 book1.TITLE = "The Fellowship of the Ring"
54 book1.AUTHORS = "Tolkien, J.R.R."
55 book1.PRICE = decimal.Decimal("10.99")
56 book2 = booksType.newobject()
57 book2.TITLE = "Harry Potter and the Philosopher's Stone"
58 book2.AUTHORS = "Rowling, J.K."
59 book2.PRICE = decimal.Decimal("7.99")
60 options = con.enqoptions()
61 messageProperties = con.msgproperties()
62 for book in (book1, book2):
63 print("Enqueuing book", book.TITLE)
64 con.enq(QUEUE_NAME, options, messageProperties, book)
65 con.commit()
52 print("Enqueuing messages...")
53
54 BOOK_DATA = [
55 ("The Fellowship of the Ring", "Tolkien, J.R.R.", decimal.Decimal("10.99")),
56 ("Harry Potter and the Philosopher's Stone", "Rowling, J.K.",
57 decimal.Decimal("7.99"))
58 ]
59
60 for title, authors, price in BOOK_DATA:
61 book = booksType.newobject()
62 book.TITLE = title
63 book.AUTHORS = authors
64 book.PRICE = price
65 print(title)
66 queue.enqOne(con.msgproperties(payload=book))
67 con.commit()
6668
6769 # Dequeue the messages
68 options = con.deqoptions()
69 options.navigation = cx_Oracle.DEQ_FIRST_MSG
70 options.wait = cx_Oracle.DEQ_NO_WAIT
71 while con.deq(QUEUE_NAME, options, messageProperties, book):
72 print("Dequeued book", book.TITLE)
73 con.commit()
70 print("\nDequeuing messages...")
71 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
72 while True:
73 props = queue.deqOne()
74 if not props:
75 break
76 print(props.payload.TITLE)
77 con.commit()
78
79 print("\nDone.")
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
1311 con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
1412 cur = con.cursor()
1513
16 cur.prepare("select * from dept where deptno = :id order by deptno")
14 sql = "select * from dept where deptno = :id order by deptno"
1715
18 cur.execute(None, id = 20)
16 cur.execute(sql, id = 20)
1917 res = cur.fetchall()
2018 print(res)
2119
22 cur.execute(None, id = 10)
20 cur.execute(sql, id = 10)
2321 res = cur.fetchall()
2422 print(res)
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
2018 char = chr(ord('A') + i)
2119 longString += char * 250
2220 cur.execute("insert into testclobs values (:1, :2)",
23 (i + 1, "String data " + longString + ' End of string'))
21 (i + 1, "String data " + longString + ' End of string'))
2422 con.commit()
2523
2624 print("Querying data...")
27 cur.prepare("select * from testclobs where id = :id")
28 cur.execute(None, {'id': 1})
25 cur.execute("select * from testclobs where id = :id", {'id': 1})
2926 (id, clob) = cur.fetchone()
3027 print("CLOB length:", clob.size())
3128 clobdata = clob.read()
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
3028 con.outputtypehandler = OutputTypeHandler
3129
3230 print("Querying data...")
33 cur.prepare("select * from testclobs where id = :id")
34 cur.execute(None, {'id': 1})
31 cur.execute("select * from testclobs where id = :id", {'id': 1})
3532 (id, clobdata) = cur.fetchone()
3633 print("CLOB length:", len(clobdata))
3734 print("CLOB data:", clobdata)
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import threading
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import threading
00 user = "pythonhol"
11 pw = "welcome"
2 dsn = "localhost/orclpdb"
2 dsn = "localhost/orclpdb1"
00 def user = "pythonhol"
11 def pw = "welcome"
2 def connect_string = "localhost/orclpdb"
2 def connect_string = "localhost/orclpdb1"
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import time
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import collections
119 import cx_Oracle
0 #------------------------------------------------------------------------------
1 # soda.py (Section 11.1)
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
6 #------------------------------------------------------------------------------
7
8 import cx_Oracle
9 import db_config
10
11 con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
12
13 soda = con.getSodaDatabase()
14
15 collection = soda.createCollection("friends")
16
17 content = {'name': 'Jared', 'age': 35, 'address': {'city': 'Melbourne'}}
18
19 doc = collection.insertOneAndGet(content)
20 key = doc.key
21
22 doc = collection.find().key(key).getOne()
23 content = doc.getContent()
24 print('Retrieved SODA document dictionary is:')
25 print(content)
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import decimal
1917 QUEUE_TABLE_NAME = "BOOK_QUEUE_TABLE"
2018
2119 # Dequeue the messages
22 options = con.deqoptions()
23 options.navigation = cx_Oracle.DEQ_FIRST_MSG
24 options.wait = cx_Oracle.DEQ_NO_WAIT
25 messageProperties = con.msgproperties()
2620 booksType = con.gettype(BOOK_TYPE_NAME)
27 book = booksType.newobject()
28 while con.deq(QUEUE_NAME, options, messageProperties, book):
29 print("Dequeued book", book.TITLE)
30 con.commit()
21 queue = con.queue(QUEUE_NAME, booksType)
22 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
23 queue.deqOptions.visibility = cx_Oracle.DEQ_IMMEDIATE
24
25 print("\nDequeuing messages...")
26 while True:
27 props = queue.deqOne()
28 if not props:
29 break
30 print(props.payload.TITLE)
31
32 print("\nDone.")
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import decimal
1917 QUEUE_TABLE_NAME = "BOOK_QUEUE_TABLE"
2018
2119 # Enqueue a few messages
20 print("Enqueuing messages...")
21
22 BOOK_DATA = [
23 ("The Fellowship of the Ring", "Tolkien, J.R.R.", decimal.Decimal("10.99")),
24 ("Harry Potter and the Philosopher's Stone", "Rowling, J.K.", decimal.Decimal("7.99"))
25 ]
26
2227 booksType = con.gettype(BOOK_TYPE_NAME)
23 book1 = booksType.newobject()
24 book1.TITLE = "The Fellowship of the Ring"
25 book1.AUTHORS = "Tolkien, J.R.R."
26 book1.PRICE = decimal.Decimal("10.99")
27 book2 = booksType.newobject()
28 book2.TITLE = "Harry Potter and the Philosopher's Stone"
29 book2.AUTHORS = "Rowling, J.K."
30 book2.PRICE = decimal.Decimal("7.99")
31 options = con.enqoptions()
32 messageProperties = con.msgproperties()
33 for book in (book1, book2):
34 print("Enqueuing book", book.TITLE)
35 con.enq(QUEUE_NAME, options, messageProperties, book)
36 con.commit()
28 queue = con.queue(QUEUE_NAME, booksType)
29
30 for title, authors, price in BOOK_DATA:
31 book = booksType.newobject()
32 book.TITLE = title
33 book.AUTHORS = authors
34 book.PRICE = price
35 print(title)
36 queue.enqOne(con.msgproperties(payload=book, expiration=4))
37 con.commit()
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import decimal
3129 end if;
3230 end;""")
3331
34 # Create type
32 # Create a type
3533 print("Creating books type UDT_BOOK...")
3634 cur.execute("""
3735 create type %s as object (
4341 # Create queue table and queue and start the queue
4442 print("Creating queue table...")
4543 cur.callproc("dbms_aqadm.create_queue_table",
46 (QUEUE_TABLE_NAME, BOOK_TYPE_NAME))
44 (QUEUE_TABLE_NAME, BOOK_TYPE_NAME))
4745 cur.callproc("dbms_aqadm.create_queue", (QUEUE_NAME, QUEUE_TABLE_NAME))
4846 cur.callproc("dbms_aqadm.start_queue", (QUEUE_NAME,))
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import threading
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import collections
119 import cx_Oracle
0 #------------------------------------------------------------------------------
1 # soda.py (Section 11.2)
2 #------------------------------------------------------------------------------
3
4 #------------------------------------------------------------------------------
5 # Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
6 #------------------------------------------------------------------------------
7
8 import cx_Oracle
9 import db_config
10
11 con = cx_Oracle.connect(db_config.user, db_config.pw, db_config.dsn)
12
13 soda = con.getSodaDatabase()
14
15 collection = soda.createCollection("friends")
16
17 content = {'name': 'Jared', 'age': 35, 'address': {'city': 'Melbourne'}}
18
19 doc = collection.insertOneAndGet(content)
20 key = doc.key
21
22 doc = collection.find().key(key).getOne()
23 content = doc.getContent()
24 print('Retrieved SODA document dictionary is:')
25 print(content)
26
27 myDocs = [
28 {'name': 'Gerald', 'age': 21, 'address': {'city': 'London'}},
29 {'name': 'David', 'age': 28, 'address': {'city': 'Melbourne'}},
30 {'name': 'Shawn', 'age': 20, 'address': {'city': 'San Francisco'}}
31 ]
32 collection.insertMany(myDocs)
33
34 filterSpec = { "address.city": "Melbourne" }
35 myDocuments = collection.find().filter(filterSpec).getDocuments()
36
37 print('Melbourne people:')
38 for doc in myDocuments:
39 print(doc.getContent()["name"])
40
41 filterSpec = {'age': {'$lt': 25}}
42 myDocuments = collection.find().filter(filterSpec).getDocuments()
43
44 print('Young people:')
45 for doc in myDocuments:
46 print(doc.getContent()["name"])
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import decimal
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
3636
3737 grant execute on dbms_aqadm to &main_user;
3838 grant execute on dbms_lock to &main_user;
39
40 begin
41
42 for r in
43 ( select role
44 from dba_roles
45 where role in ('SODA_APP')
46 ) loop
47 execute immediate 'grant ' || r.role || ' to &main_user';
48 end loop;
49
50 end;
51 /
3952
4053 create table &main_user..testclobs (
4154 id number not null,
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
5 # Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
5 # Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
66 #------------------------------------------------------------------------------
7
8 from __future__ import print_function
97
108 import cx_Oracle
119 import db_config
1111 import os
1212 import sys
1313
14 # check minimum supported Python version
15 if sys.version_info[:2] < (3, 5):
16 raise Exception("Python 3.5 or higher is required. " +
17 "For python 2, use 'pip install cx_Oracle==7.3'")
18
1419 # if setuptools is detected, use it to add support for eggs
1520 try:
1621 from setuptools import setup, Extension
1924 from distutils.extension import Extension
2025
2126 # define build constants
22 BUILD_VERSION = "7.1.0"
27 BUILD_VERSION = "8.0.1"
2328
2429 # setup extra link and compile args
2530 extraLinkArgs = []
5964 "Natural Language :: English",
6065 "Operating System :: OS Independent",
6166 "Programming Language :: C",
62 "Programming Language :: Python",
63 "Programming Language :: Python :: 2",
64 "Programming Language :: Python :: 3",
67 "Programming Language :: Python :: 3 :: Only",
6568 "Topic :: Database"
6669 ]
6770
119122 author = "Anthony Tuininga",
120123 author_email = "[email protected]",
121124 url = "https://oracle.github.io/python-cx_Oracle",
125 python_requires = ">=3.5",
122126 ext_modules = [extension],
123127 keywords = "Oracle",
124128 license = "BSD License",
0 //-----------------------------------------------------------------------------
1 // Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2 //-----------------------------------------------------------------------------
3
4 //-----------------------------------------------------------------------------
5 // cxoApiType.c
6 // Defines the objects used for identifying types defined by the Python
7 // Database API.
8 //-----------------------------------------------------------------------------
9
10 #include "cxoModule.h"
11
12 //-----------------------------------------------------------------------------
13 // declaration of functions
14 //-----------------------------------------------------------------------------
15 static void cxoApiType_free(cxoApiType*);
16 static PyObject *cxoApiType_repr(cxoApiType*);
17
18
19 //-----------------------------------------------------------------------------
20 // declaration of members
21 //-----------------------------------------------------------------------------
22 static PyMemberDef cxoMembers[] = {
23 { "name", T_STRING, offsetof(cxoApiType, name), READONLY },
24 { NULL }
25 };
26
27
28 //-----------------------------------------------------------------------------
29 // Python type declaration
30 //-----------------------------------------------------------------------------
31 PyTypeObject cxoPyTypeApiType = {
32 PyVarObject_HEAD_INIT(NULL, 0)
33 .tp_name = "cx_Oracle.ApiType",
34 .tp_basicsize = sizeof(cxoApiType),
35 .tp_dealloc = (destructor) cxoApiType_free,
36 .tp_repr = (reprfunc) cxoApiType_repr,
37 .tp_flags = Py_TPFLAGS_DEFAULT,
38 .tp_members = cxoMembers
39 };
40
41
42 //-----------------------------------------------------------------------------
43 // cxoApiType_free()
44 // Free the API type object.
45 //-----------------------------------------------------------------------------
46 static void cxoApiType_free(cxoApiType *apiType)
47 {
48 Py_CLEAR(apiType->dbTypes);
49 Py_TYPE(apiType)->tp_free((PyObject*) apiType);
50 }
51
52
53 //-----------------------------------------------------------------------------
54 // cxoApiType_repr()
55 // Return a string representation of a queue.
56 //-----------------------------------------------------------------------------
57 static PyObject *cxoApiType_repr(cxoApiType *apiType)
58 {
59 PyObject *module, *name, *apiTypeName, *result;
60
61 apiTypeName = PyUnicode_DecodeASCII(apiType->name, strlen(apiType->name),
62 NULL);
63 if (!apiTypeName)
64 return NULL;
65 if (cxoUtils_getModuleAndName(Py_TYPE(apiType), &module, &name) < 0) {
66 Py_DECREF(apiTypeName);
67 return NULL;
68 }
69 result = cxoUtils_formatString("<%s.%s %s>",
70 PyTuple_Pack(3, module, name, apiTypeName));
71 Py_DECREF(module);
72 Py_DECREF(name);
73 Py_DECREF(apiTypeName);
74 return result;
75 }
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
3030 return -1;
3131 buf->ptr = PyBytes_AS_STRING(buf->obj);
3232 buf->size = (uint32_t) PyBytes_GET_SIZE(buf->obj);
33 #if PY_MAJOR_VERSION < 3
34 buf->numCharacters = (uint32_t) PyUnicode_GET_SIZE(obj);
35 #else
3633 buf->numCharacters = (uint32_t) PyUnicode_GET_LENGTH(obj);
37 #endif
3834 } else if (PyBytes_Check(obj)) {
3935 Py_INCREF(obj);
4036 buf->obj = obj;
4137 buf->ptr = PyBytes_AS_STRING(buf->obj);
4238 buf->size = buf->numCharacters = (uint32_t) PyBytes_GET_SIZE(buf->obj);
43 #if PY_MAJOR_VERSION < 3
44 } else if (PyBuffer_Check(obj)) {
45 Py_ssize_t temp;
46 if (PyObject_AsReadBuffer(obj, (void*) &buf->ptr, &temp) < 0)
47 return -1;
48 Py_INCREF(obj);
49 buf->obj = obj;
50 buf->numCharacters = buf->size = (uint32_t) temp;
51 #endif
5239 } else {
53 #if PY_MAJOR_VERSION >= 3
5440 PyErr_SetString(PyExc_TypeError, "expecting string or bytes object");
55 #else
56 PyErr_SetString(PyExc_TypeError,
57 "expecting string, unicode or buffer object");
58 #endif
5941 return -1;
6042 }
6143 return 0;
7557 buf->obj = NULL;
7658 return 0;
7759 }
78
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
4040 static PyObject *cxoConnection_getStmtCacheSize(cxoConnection*, void*);
4141 static PyObject *cxoConnection_newEnqueueOptions(cxoConnection*, PyObject*);
4242 static PyObject *cxoConnection_newDequeueOptions(cxoConnection*, PyObject*);
43 static PyObject *cxoConnection_newMessageProperties(cxoConnection*, PyObject*);
43 static PyObject *cxoConnection_newMessageProperties(cxoConnection*, PyObject*,
44 PyObject*);
4445 static PyObject *cxoConnection_dequeue(cxoConnection*, PyObject*, PyObject*);
4546 static PyObject *cxoConnection_enqueue(cxoConnection*, PyObject*, PyObject*);
4647 static PyObject *cxoConnection_ping(cxoConnection*, PyObject*);
48 static PyObject *cxoConnection_queue(cxoConnection*, PyObject*, PyObject*);
4749 static PyObject *cxoConnection_shutdown(cxoConnection*, PyObject*, PyObject*);
4850 static PyObject *cxoConnection_startup(cxoConnection*, PyObject*, PyObject*);
4951 static PyObject *cxoConnection_subscribe(cxoConnection*, PyObject*, PyObject*);
102104 { "enqoptions", (PyCFunction) cxoConnection_newEnqueueOptions,
103105 METH_NOARGS },
104106 { "msgproperties", (PyCFunction) cxoConnection_newMessageProperties,
105 METH_NOARGS },
107 METH_VARARGS | METH_KEYWORDS },
106108 { "deq", (PyCFunction) cxoConnection_dequeue,
107109 METH_VARARGS | METH_KEYWORDS },
108110 { "enq", (PyCFunction) cxoConnection_enqueue,
111 METH_VARARGS | METH_KEYWORDS },
112 { "queue", (PyCFunction) cxoConnection_queue,
109113 METH_VARARGS | METH_KEYWORDS },
110114 { "createlob", (PyCFunction) cxoConnection_createLob, METH_O },
111115 { "getSodaDatabase", (PyCFunction) cxoConnection_getSodaDatabase,
184188
185189
186190 //-----------------------------------------------------------------------------
187 // declaration of Python type "Connection"
191 // declaration of Python type
188192 //-----------------------------------------------------------------------------
189193 PyTypeObject cxoPyTypeConnection = {
190194 PyVarObject_HEAD_INIT(NULL, 0)
191 "cx_Oracle.Connection", // tp_name
192 sizeof(cxoConnection), // tp_basicsize
193 0, // tp_itemsize
194 (destructor) cxoConnection_free, // tp_dealloc
195 0, // tp_print
196 0, // tp_getattr
197 0, // tp_setattr
198 0, // tp_compare
199 (reprfunc) cxoConnection_repr, // tp_repr
200 0, // tp_as_number
201 0, // tp_as_sequence
202 0, // tp_as_mapping
203 0, // tp_hash
204 0, // tp_call
205 0, // tp_str
206 0, // tp_getattro
207 0, // tp_setattro
208 0, // tp_as_buffer
209 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
210 // tp_flags
211 0, // tp_doc
212 0, // tp_traverse
213 0, // tp_clear
214 0, // tp_richcompare
215 0, // tp_weaklistoffset
216 0, // tp_iter
217 0, // tp_iternext
218 cxoConnectionMethods, // tp_methods
219 cxoConnectionMembers, // tp_members
220 cxoConnectionCalcMembers, // tp_getset
221 0, // tp_base
222 0, // tp_dict
223 0, // tp_descr_get
224 0, // tp_descr_set
225 0, // tp_dictoffset
226 (initproc) cxoConnection_init, // tp_init
227 0, // tp_alloc
228 (newfunc) cxoConnection_new, // tp_new
229 0, // tp_free
230 0, // tp_is_gc
231 0 // tp_bases
195 .tp_name = "cx_Oracle.Connection",
196 .tp_basicsize = sizeof(cxoConnection),
197 .tp_dealloc = (destructor) cxoConnection_free,
198 .tp_repr = (reprfunc) cxoConnection_repr,
199 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
200 .tp_methods = cxoConnectionMethods,
201 .tp_members = cxoConnectionMembers,
202 .tp_getset = cxoConnectionCalcMembers,
203 .tp_init = (initproc) cxoConnection_init,
204 .tp_new = (newfunc) cxoConnection_new
232205 };
233206
234207
370343 cxoConnectionParams *params, PyObject *value,
371344 dpiShardingKeyColumn *column, cxoBuffer *buffer)
372345 {
346 dpiNativeTypeNum nativeTypeNum;
373347 cxoTransformNum transformNum;
374348
375 transformNum = cxoTransform_getNumFromValue(value, 0);
376 if (cxoTransform_fromPython(transformNum, value, &column->value, buffer,
377 params->encoding, params->nencoding, NULL, 0) < 0)
349 transformNum = cxoTransform_getNumFromPythonValue(value, 0);
350 if (cxoTransform_fromPython(transformNum, &nativeTypeNum, value,
351 &column->value, buffer, params->encoding, params->nencoding, NULL,
352 0) < 0)
378353 return -1;
379354 cxoTransform_getTypeInfo(transformNum, &column->oracleTypeNum,
380355 &column->nativeTypeNum);
408383 return 0;
409384
410385 // allocate memory for the sharding key values
411 columns = PyMem_Malloc(numColumns * sizeof(dpiShardingKeyColumn));
412 buffers = PyMem_Malloc(numColumns * sizeof(cxoBuffer));
386 columns = PyMem_Calloc(numColumns, sizeof(dpiShardingKeyColumn));
387 buffers = PyMem_Calloc(numColumns, sizeof(cxoBuffer));
388 if (!columns || !buffers) {
389 PyErr_NoMemory();
390 return -1;
391 }
413392 if (isSuperShardingKey) {
414393 params->superShardingKeyColumns = columns;
415394 params->superShardingKeyBuffers = buffers;
419398 params->shardingKeyBuffers = buffers;
420399 params->numShardingKeyColumns = numColumns;
421400 }
422 if (!columns || !buffers) {
423 PyErr_NoMemory();
424 return -1;
425 }
426401
427402 // process each value
428403 for (i = 0; i < numColumns; i++) {
429 cxoBuffer_init(&buffers[i]);
430404 value = PySequence_GetItem(shardingKeyObj, i);
431405 if (!value)
432406 return -1;
433407 if (cxoConnectionParams_processShardingKeyValue(params, value,
434408 &columns[i], &buffers[i]) < 0)
435409 return -1;
410 Py_DECREF(value);
436411 }
437412
438413 return 0;
549524 return cxoError_raiseAndReturnNull();
550525 if (!value)
551526 Py_RETURN_NONE;
552 return cxoPyString_fromEncodedString(value, valueLength,
553 conn->encodingInfo.encoding, NULL);
527 return PyUnicode_Decode(value, valueLength, conn->encodingInfo.encoding,
528 NULL);
554529 }
555530
556531
589564 int status;
590565
591566 // parse the arguments
567 if (cxoConnection_isConnected(conn) < 0)
568 return NULL;
592569 if (!PyArg_ParseTuple(args, "OO", &oldPasswordObj, &newPasswordObj))
593570 return NULL;
594571
637614
638615 //-----------------------------------------------------------------------------
639616 // cxoConnection_splitComponent()
640 // Split the component out of the source and replace the source with the
641 // characters up to the split string and put the characters after the split
642 // string in to the target.
643 //-----------------------------------------------------------------------------
644 static int cxoConnection_splitComponent(PyObject **sourceObj,
645 PyObject **targetObj, const char *splitString)
646 {
647 PyObject *temp, *posObj;
617 // Split the component out of the source if the split string is found and
618 // return the "before" and "after" parts.
619 //-----------------------------------------------------------------------------
620 static int cxoConnection_splitComponent(PyObject *sourceObj,
621 const char *splitString, const char *methodName,
622 PyObject **beforePartObj, PyObject **afterPartObj)
623 {
648624 Py_ssize_t size, pos;
649
650 if (!*sourceObj || *targetObj)
651 return 0;
652 posObj = PyObject_CallMethod(*sourceObj, "find", "s", splitString);
625 PyObject *posObj;
626
627 posObj = PyObject_CallMethod(sourceObj, methodName, "s", splitString);
653628 if (!posObj)
654629 return -1;
655 pos = PyInt_AsLong(posObj);
630 pos = PyLong_AsLong(posObj);
656631 Py_DECREF(posObj);
657632 if (PyErr_Occurred())
658633 return -1;
659 if (pos >= 0) {
660 size = PySequence_Size(*sourceObj);
634 if (pos < 0) {
635 *beforePartObj = *afterPartObj = NULL;
636 } else {
637 size = PySequence_Size(sourceObj);
661638 if (PyErr_Occurred())
662639 return -1;
663 *targetObj = PySequence_GetSlice(*sourceObj, pos + 1, size);
664 if (!*targetObj)
640 *afterPartObj = PySequence_GetSlice(sourceObj, pos + 1, size);
641 if (!*afterPartObj)
665642 return -1;
666 temp = PySequence_GetSlice(*sourceObj, 0, pos);
667 if (!temp)
643 *beforePartObj = PySequence_GetSlice(sourceObj, 0, pos);
644 if (!*beforePartObj) {
645 Py_DECREF(*afterPartObj);
646 *afterPartObj = NULL;
668647 return -1;
669 *sourceObj = temp;
648 }
670649 }
671650 return 0;
672651 }
683662 PyObject *usernameObj, *passwordObj, *dsnObj, *cclassObj, *editionObj;
684663 PyObject *shardingKeyObj, *superShardingKeyObj, *tempObj;
685664 int status, temp, invokeSessionCallback;
665 PyObject *beforePartObj, *afterPartObj;
686666 dpiCommonCreateParams dpiCommonParams;
687667 dpiConnCreateParams dpiCreateParams;
688668 unsigned long long externalHandle;
703683 passwordObj = dsnObj = cclassObj = editionObj = NULL;
704684 threadedObj = eventsObj = newPasswordObj = usernameObj = NULL;
705685 matchAnyTagObj = contextObj = shardingKeyObj = superShardingKeyObj = NULL;
706 if (cxoUtils_initializeDPI() < 0)
686 if (cxoUtils_initializeDPI(NULL) < 0)
707687 return -1;
708688 if (dpiContext_initCommonCreateParams(cxoDpiContext, &dpiCommonParams) < 0)
709689 return cxoError_raiseAndReturnInt();
710 dpiCommonParams.driverName = CXO_DRIVER_NAME;
711 dpiCommonParams.driverNameLength =
712 (uint32_t) strlen(dpiCommonParams.driverName);
713690 if (dpiContext_initConnCreateParams(cxoDpiContext, &dpiCreateParams) < 0)
714691 return cxoError_raiseAndReturnInt();
715692 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs,
739716 conn->username = usernameObj;
740717 Py_XINCREF(dsnObj);
741718 conn->dsn = dsnObj;
742
743 // perform some parsing, if necessary
744 if (cxoConnection_splitComponent(&conn->username, &passwordObj, "/") < 0)
745 return -1;
746 if (cxoConnection_splitComponent(&passwordObj, &conn->dsn, "@") < 0)
747 return -1;
719 Py_XINCREF(passwordObj);
720
721 // perform some parsing, if no password and DSN are provided but the user
722 // name is provided
723 if (conn->username && !passwordObj && !dsnObj) {
724 if (cxoConnection_splitComponent(conn->username, "/", "find",
725 &beforePartObj, &afterPartObj) < 0)
726 return -1;
727 if (beforePartObj) {
728 Py_DECREF(conn->username);
729 conn->username = beforePartObj;
730 passwordObj = afterPartObj;
731 if (cxoConnection_splitComponent(passwordObj, "@", "rfind",
732 &beforePartObj, &afterPartObj) < 0)
733 return -1;
734 if (beforePartObj) {
735 Py_DECREF(passwordObj);
736 passwordObj = beforePartObj;
737 conn->dsn = afterPartObj;
738 }
739 }
740 }
748741
749742 // setup parameters
750743 cxoConnectionParams_initialize(&params);
778771 cxoBuffer_fromObject(&params.editionBuffer, editionObj,
779772 params.encoding) < 0 ||
780773 cxoBuffer_fromObject(&params.tagBuffer, tagObj,
781 params.encoding) < 0)
774 params.encoding) < 0) {
775 Py_XDECREF(passwordObj);
782776 return cxoConnectionParams_finalize(&params);
777 }
778 Py_XDECREF(passwordObj);
783779 if (params.userNameBuffer.size == 0 && params.passwordBuffer.size == 0)
784780 dpiCreateParams.externalAuth = 1;
785781 dpiCreateParams.connectionClass = params.connectionClassBuffer.ptr;
844840
845841 // set tag property
846842 if (dpiCreateParams.outTagLength > 0) {
847 conn->tag = cxoPyString_fromEncodedString(dpiCreateParams.outTag,
843 conn->tag = PyUnicode_Decode(dpiCreateParams.outTag,
848844 dpiCreateParams.outTagLength, conn->encodingInfo.encoding,
849845 NULL);
850846 if (!conn->tag)
928924 return NULL;
929925 if (dpiConn_getStmtCacheSize(conn->handle, &cacheSize) < 0)
930926 return cxoError_raiseAndReturnNull();
931 return PyInt_FromLong(cacheSize);
927 return PyLong_FromLong(cacheSize);
932928 }
933929
934930
943939
944940 if (cxoConnection_isConnected(conn) < 0)
945941 return -1;
946 if (!PyInt_Check(value)) {
942 if (!PyLong_Check(value)) {
947943 PyErr_SetString(PyExc_TypeError, "value must be an integer");
948944 return -1;
949945 }
950 cacheSize = (uint32_t) PyInt_AsLong(value);
946 cacheSize = (uint32_t) PyLong_AsLong(value);
951947 if (dpiConn_setStmtCacheSize(conn->handle, cacheSize) < 0)
952948 return cxoError_raiseAndReturnInt();
953949 return 0;
967963 return NULL;
968964 if (dpiConn_getCallTimeout(conn->handle, &callTimeout) < 0)
969965 return cxoError_raiseAndReturnNull();
970 return PyInt_FromLong(callTimeout);
966 return PyLong_FromLong(callTimeout);
971967 }
972968
973969
998994 //-----------------------------------------------------------------------------
999995 static PyObject *cxoConnection_getType(cxoConnection *conn, PyObject *nameObj)
1000996 {
997 if (cxoConnection_isConnected(conn) < 0)
998 return NULL;
1001999 return (PyObject*) cxoObjectType_newByName(conn, nameObj);
10021000 }
10031001
10091007 static PyObject *cxoConnection_createLob(cxoConnection *conn,
10101008 PyObject *lobType)
10111009 {
1012 dpiOracleTypeNum oracleTypeNum;
1010 cxoDbType *dbType;
10131011 dpiLob *handle;
10141012 PyObject *lob;
10151013
10181016 return NULL;
10191017
10201018 // verify the LOB type
1021 if (lobType == (PyObject*) &cxoPyTypeClobVar)
1022 oracleTypeNum = DPI_ORACLE_TYPE_CLOB;
1023 else if (lobType == (PyObject*) &cxoPyTypeBlobVar)
1024 oracleTypeNum = DPI_ORACLE_TYPE_BLOB;
1025 else if (lobType == (PyObject*) &cxoPyTypeNclobVar)
1026 oracleTypeNum = DPI_ORACLE_TYPE_NCLOB;
1027 else {
1019 if (lobType != (PyObject*) cxoDbTypeClob &&
1020 lobType != (PyObject*) cxoDbTypeBlob &&
1021 lobType != (PyObject*) cxoDbTypeNclob) {
10281022 PyErr_SetString(PyExc_TypeError,
1029 "parameter should be one of cx_Oracle.CLOB, cx_Oracle.BLOB "
1030 "or cx_Oracle.NCLOB");
1023 "parameter should be one of cx_Oracle.DB_TYPE_CLOB, "
1024 "cx_Oracle.DB_TYPE_BLOB or cx_Oracle.DB_TYPE_NCLOB");
10311025 return NULL;
10321026 }
10331027
10341028 // create a temporary LOB
1035 if (dpiConn_newTempLob(conn->handle, oracleTypeNum, &handle) < 0)
1036 return cxoError_raiseAndReturnNull();
1037 lob = cxoLob_new(conn, oracleTypeNum, handle);
1029 dbType = (cxoDbType*) lobType;
1030 if (dpiConn_newTempLob(conn->handle, dbType->num, &handle) < 0)
1031 return cxoError_raiseAndReturnNull();
1032 lob = cxoLob_new(conn, dbType, handle);
10381033 if (!lob)
10391034 dpiLob_release(handle);
10401035 return lob;
10491044 //-----------------------------------------------------------------------------
10501045 static PyObject *cxoConnection_getVersion(cxoConnection *conn, void *unused)
10511046 {
1052 uint32_t releaseStringLength;
10531047 dpiVersionInfo versionInfo;
1054 const char *releaseString;
10551048 char buffer[25];
1056 int status;
1057
1049 int status, len;
1050
1051 if (cxoConnection_isConnected(conn) < 0)
1052 return NULL;
10581053 Py_BEGIN_ALLOW_THREADS
1059 status = dpiConn_getServerVersion(conn->handle, &releaseString,
1060 &releaseStringLength, &versionInfo);
1054 status = dpiConn_getServerVersion(conn->handle, NULL, NULL, &versionInfo);
10611055 Py_END_ALLOW_THREADS
10621056 if (status < 0)
10631057 return cxoError_raiseAndReturnNull();
1064 snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.%d", versionInfo.versionNum,
1065 versionInfo.releaseNum, versionInfo.updateNum,
1066 versionInfo.portReleaseNum, versionInfo.portUpdateNum);
1067 return cxoPyString_fromAscii(buffer);
1058 len = snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.%d",
1059 versionInfo.versionNum, versionInfo.releaseNum,
1060 versionInfo.updateNum, versionInfo.portReleaseNum,
1061 versionInfo.portUpdateNum);
1062 return PyUnicode_DecodeASCII(buffer, len, NULL);
10681063 }
10691064
10701065
10741069 //-----------------------------------------------------------------------------
10751070 static PyObject *cxoConnection_getEncoding(cxoConnection *conn, void *unused)
10761071 {
1077 return cxoPyString_fromAscii(conn->encodingInfo.encoding);
1072 return PyUnicode_DecodeASCII(conn->encodingInfo.encoding,
1073 strlen(conn->encodingInfo.encoding), NULL);
10781074 }
10791075
10801076
11191115 static PyObject *cxoConnection_getNationalEncoding(cxoConnection *conn,
11201116 void *unused)
11211117 {
1122 return cxoPyString_fromAscii(conn->encodingInfo.nencoding);
1118 return PyUnicode_DecodeASCII(conn->encodingInfo.nencoding,
1119 strlen(conn->encodingInfo.nencoding), NULL);
11231120 }
11241121
11251122
11301127 static PyObject *cxoConnection_getMaxBytesPerCharacter(cxoConnection *conn,
11311128 void *unused)
11321129 {
1133 return PyInt_FromLong(conn->encodingInfo.maxBytesPerCharacter);
1130 return PyLong_FromLong(conn->encodingInfo.maxBytesPerCharacter);
11341131 }
11351132
11361133
11551152 Py_BEGIN_ALLOW_THREADS
11561153 status = dpiConn_close(conn->handle, mode, (char*) tagBuffer.ptr,
11571154 tagBuffer.size);
1155 if (status == DPI_SUCCESS)
1156 dpiConn_release(conn->handle);
11581157 Py_END_ALLOW_THREADS
11591158 cxoBuffer_clear(&tagBuffer);
11601159 if (status < 0)
11611160 return cxoError_raiseAndReturnNull();
1161 conn->handle = NULL;
11621162
11631163 Py_RETURN_NONE;
11641164 }
11901190 //-----------------------------------------------------------------------------
11911191 static PyObject *cxoConnection_begin(cxoConnection *conn, PyObject *args)
11921192 {
1193 uint32_t transactionIdLength, branchIdLength;
1193 Py_ssize_t transactionIdLength, branchIdLength;
11941194 const char *transactionId, *branchId;
11951195 int formatId, status;
11961196
12741274 PyObject *createArgs, *result, *arg;
12751275 Py_ssize_t numArgs = 0, i;
12761276
1277 if (cxoConnection_isConnected(conn) < 0)
1278 return NULL;
12771279 if (args)
12781280 numArgs = PyTuple_GET_SIZE(args);
12791281 createArgs = PyTuple_New(1 + numArgs);
13161318 static PyObject *cxoConnection_newEnqueueOptions(cxoConnection *conn,
13171319 PyObject *args)
13181320 {
1319 return (PyObject*) cxoEnqOptions_new(conn);
1321 if (cxoConnection_isConnected(conn) < 0)
1322 return NULL;
1323 return (PyObject*) cxoEnqOptions_new(conn, NULL);
13201324 }
13211325
13221326
13271331 static PyObject *cxoConnection_newDequeueOptions(cxoConnection *conn,
13281332 PyObject *args)
13291333 {
1330 return (PyObject*) cxoDeqOptions_new(conn);
1334 if (cxoConnection_isConnected(conn) < 0)
1335 return NULL;
1336 return (PyObject*) cxoDeqOptions_new(conn, NULL);
13311337 }
13321338
13331339
13361342 // Creates a new message properties object and returns it.
13371343 //-----------------------------------------------------------------------------
13381344 static PyObject *cxoConnection_newMessageProperties(cxoConnection *conn,
1339 PyObject *args)
1340 {
1341 return (PyObject*) cxoMsgProps_new(conn);
1345 PyObject *args, PyObject *keywordArgs)
1346 {
1347 static char *keywordList[] = { "payload", "correlation", "delay",
1348 "exceptionq", "expiration", "priority", NULL };
1349 PyObject *payloadObj, *correlationObj, *exceptionQObj;
1350 int delay, expiration, priority, status;
1351 cxoMsgProps *props;
1352 cxoBuffer buffer;
1353
1354 // parse arguments
1355 expiration = -1;
1356 delay = priority = 0;
1357 payloadObj = correlationObj = exceptionQObj = NULL;
1358 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|OOiOii", keywordList,
1359 &payloadObj, &correlationObj, &delay, &exceptionQObj, &expiration,
1360 &priority))
1361 return NULL;
1362 if (cxoConnection_isConnected(conn) < 0)
1363 return NULL;
1364
1365 // create new message properties object
1366 props = cxoMsgProps_new(conn, NULL);
1367 if (!props)
1368 return NULL;
1369
1370 // set payload, if applicable
1371 if (payloadObj) {
1372 Py_INCREF(payloadObj);
1373 props->payload = payloadObj;
1374 }
1375
1376 // set correlation, if applicable
1377 if (correlationObj) {
1378 if (cxoBuffer_fromObject(&buffer, correlationObj,
1379 props->encoding) < 0) {
1380 Py_DECREF(props);
1381 return NULL;
1382 }
1383 status = dpiMsgProps_setCorrelation(props->handle, buffer.ptr,
1384 buffer.size);
1385 cxoBuffer_clear(&buffer);
1386 if (status < 0) {
1387 cxoError_raiseAndReturnNull();
1388 Py_DECREF(props);
1389 return NULL;
1390 }
1391 }
1392
1393 // set delay, if applicable
1394 if (delay != 0) {
1395 if (dpiMsgProps_setDelay(props->handle, (int32_t) delay) < 0) {
1396 cxoError_raiseAndReturnNull();
1397 Py_DECREF(props);
1398 return NULL;
1399 }
1400 }
1401
1402 // set exception queue, if applicable
1403 if (exceptionQObj) {
1404 if (cxoBuffer_fromObject(&buffer, exceptionQObj,
1405 props->encoding) < 0) {
1406 Py_DECREF(props);
1407 return NULL;
1408 }
1409 status = dpiMsgProps_setExceptionQ(props->handle, buffer.ptr,
1410 buffer.size);
1411 cxoBuffer_clear(&buffer);
1412 if (status < 0) {
1413 cxoError_raiseAndReturnNull();
1414 Py_DECREF(props);
1415 return NULL;
1416 }
1417 }
1418
1419 // set expiration, if applicable
1420 if (expiration != -1) {
1421 if (dpiMsgProps_setExpiration(props->handle,
1422 (int32_t) expiration) < 0) {
1423 cxoError_raiseAndReturnNull();
1424 Py_DECREF(props);
1425 return NULL;
1426 }
1427 }
1428
1429 // set priority, if applicable
1430 if (priority != 0) {
1431 if (dpiMsgProps_setPriority(props->handle, (int32_t) priority) < 0) {
1432 cxoError_raiseAndReturnNull();
1433 Py_DECREF(props);
1434 return NULL;
1435 }
1436 }
1437
1438 return (PyObject*) props;
13421439 }
13431440
13441441
13661463 &nameObj, &cxoPyTypeDeqOptions, &optionsObj, &cxoPyTypeMsgProps,
13671464 &propertiesObj, &cxoPyTypeObject, &payloadObj))
13681465 return NULL;
1466 if (cxoConnection_isConnected(conn) < 0)
1467 return NULL;
13691468 if (cxoBuffer_fromObject(&nameBuffer, nameObj,
13701469 conn->encodingInfo.encoding) < 0)
13711470 return NULL;
13721471
13731472 // dequeue payload
1473 Py_BEGIN_ALLOW_THREADS
13741474 status = dpiConn_deqObject(conn->handle, nameBuffer.ptr, nameBuffer.size,
13751475 optionsObj->handle, propertiesObj->handle, payloadObj->handle,
13761476 &messageIdValue, &messageIdLength);
1477 Py_END_ALLOW_THREADS
13771478 cxoBuffer_clear(&nameBuffer);
13781479 if (status < 0)
13791480 return cxoError_raiseAndReturnNull();
14091510 &nameObj, &cxoPyTypeEnqOptions, &optionsObj, &cxoPyTypeMsgProps,
14101511 &propertiesObj, &cxoPyTypeObject, &payloadObj))
14111512 return NULL;
1513 if (cxoConnection_isConnected(conn) < 0)
1514 return NULL;
14121515 if (cxoBuffer_fromObject(&nameBuffer, nameObj,
14131516 conn->encodingInfo.encoding) < 0)
14141517 return NULL;
14151518
14161519 // enqueue payload
1520 Py_BEGIN_ALLOW_THREADS
14171521 status = dpiConn_enqObject(conn->handle, nameBuffer.ptr, nameBuffer.size,
14181522 optionsObj->handle, propertiesObj->handle, payloadObj->handle,
14191523 &messageIdValue, &messageIdLength);
1524 Py_END_ALLOW_THREADS
14201525 cxoBuffer_clear(&nameBuffer);
14211526 if (status < 0)
14221527 return cxoError_raiseAndReturnNull();
14231528
14241529 // return message id
14251530 return PyBytes_FromStringAndSize(messageIdValue, messageIdLength);
1531 }
1532
1533
1534 //-----------------------------------------------------------------------------
1535 // cxoConnection_queue()
1536 // Creates a new queue associated with the connection and returns it to the
1537 // caller.
1538 //-----------------------------------------------------------------------------
1539 static PyObject *cxoConnection_queue(cxoConnection *conn, PyObject* args,
1540 PyObject* keywordArgs)
1541 {
1542 static char *keywordList[] = { "name", "payloadType", NULL };
1543 cxoObjectType *typeObj;
1544 cxoBuffer nameBuffer;
1545 PyObject *nameObj;
1546 dpiQueue *handle;
1547 cxoQueue *queue;
1548 int status;
1549
1550 // parse arguments
1551 typeObj = NULL;
1552 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|O!", keywordList,
1553 &nameObj, &cxoPyTypeObjectType, &typeObj))
1554 return NULL;
1555 if (cxoConnection_isConnected(conn) < 0)
1556 return NULL;
1557 if (cxoBuffer_fromObject(&nameBuffer, nameObj,
1558 conn->encodingInfo.encoding) < 0)
1559 return NULL;
1560
1561 // create queue
1562 status = dpiConn_newQueue(conn->handle, nameBuffer.ptr, nameBuffer.size,
1563 (typeObj) ? typeObj->handle : NULL, &handle);
1564 cxoBuffer_clear(&nameBuffer);
1565 if (status < 0)
1566 return cxoError_raiseAndReturnNull();
1567 queue = cxoQueue_new(conn, handle);
1568 if (!queue)
1569 return NULL;
1570 Py_INCREF(nameObj);
1571 queue->name = nameObj;
1572 Py_XINCREF(typeObj);
1573 queue->payloadType = typeObj;
1574
1575 return (PyObject*) queue;
14261576 }
14271577
14281578
14341584 static PyObject *cxoConnection_contextManagerEnter(cxoConnection *conn,
14351585 PyObject* args)
14361586 {
1587 if (cxoConnection_isConnected(conn) < 0)
1588 return NULL;
14371589 Py_INCREF(conn);
14381590 return (PyObject*) conn;
14391591 }
15181670 static PyObject *cxoConnection_startup(cxoConnection *conn, PyObject* args,
15191671 PyObject* keywordArgs)
15201672 {
1521 static char *keywordList[] = { "force", "restrict", NULL };
1522 PyObject *forceObj, *restrictObj;
1673 static char *keywordList[] = { "force", "restrict", "pfile", NULL };
1674 PyObject *forceObj, *restrictObj, *pfileObj;
1675 cxoBuffer pfileBuffer;
15231676 dpiStartupMode mode;
15241677 int temp;
15251678
15261679 // parse arguments
1527 forceObj = restrictObj = NULL;
1528 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|OO", keywordList,
1529 &forceObj, &restrictObj))
1680 forceObj = restrictObj = pfileObj = NULL;
1681 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|OOO", keywordList,
1682 &forceObj, &restrictObj, &pfileObj))
15301683 return NULL;
15311684
15321685 // set the flags to use during startup
15401693 if (temp)
15411694 mode |= DPI_MODE_STARTUP_RESTRICT;
15421695
1696 // check the pfile parameter
1697 if (cxoBuffer_fromObject(&pfileBuffer, pfileObj,
1698 conn->encodingInfo.encoding) < 0)
1699 return NULL;
1700
15431701 // make sure we are actually connected
1544 if (cxoConnection_isConnected(conn) < 0)
1545 return NULL;
1702 if (cxoConnection_isConnected(conn) < 0) {
1703 cxoBuffer_clear(&pfileBuffer);
1704 return NULL;
1705 }
15461706
15471707 // perform the work
1548 if (dpiConn_startupDatabase(conn->handle, mode) < 0)
1708 temp = dpiConn_startupDatabaseWithPfile(conn->handle, pfileBuffer.ptr,
1709 pfileBuffer.size, mode);
1710 cxoBuffer_clear(&pfileBuffer);
1711 if (temp < 0)
15491712 return cxoError_raiseAndReturnNull();
15501713
15511714 Py_RETURN_NONE;
15611724 {
15621725 static char *keywordList[] = { "namespace", "protocol", "callback",
15631726 "timeout", "operations", "port", "qos", "ipAddress",
1564 "groupingClass", "groupingValue", "groupingType", "name", NULL };
1565 PyObject *callback, *ipAddress, *name;
1727 "groupingClass", "groupingValue", "groupingType", "name",
1728 "clientInitiated", NULL };
1729 PyObject *callback, *ipAddress, *name, *clientInitiatedObj;
15661730 cxoBuffer ipAddressBuffer, nameBuffer;
15671731 dpiSubscrCreateParams params;
15681732 cxoSubscr *subscr;
15721736 return cxoError_raiseAndReturnNull();
15731737
15741738 // validate parameters
1575 callback = name = ipAddress = NULL;
1576 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|IIOIIIIObIbO",
1739 callback = name = ipAddress = clientInitiatedObj = NULL;
1740 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|IIOIIIIObIbOO",
15771741 keywordList, &params.subscrNamespace, &params.protocol, &callback,
15781742 &params.timeout, &params.operations, &params.portNumber,
15791743 &params.qos, &ipAddress, &params.groupingClass,
1580 &params.groupingValue, &params.groupingType, &name))
1744 &params.groupingValue, &params.groupingType, &name,
1745 &clientInitiatedObj))
1746 return NULL;
1747 if (cxoConnection_isConnected(conn) < 0)
1748 return NULL;
1749 if (cxoUtils_getBooleanValue(clientInitiatedObj, 0,
1750 &params.clientInitiated) < 0)
15811751 return NULL;
15821752
15831753 // populate IP address in parameters, if applicable
16411811 Py_DECREF(subscr);
16421812 return NULL;
16431813 }
1814 subscr->id = params.outRegId;
16441815 cxoBuffer_clear(&ipAddressBuffer);
16451816 cxoBuffer_clear(&nameBuffer);
16461817
16631834 // validate parameters
16641835 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!", keywordList,
16651836 &cxoPyTypeSubscr, &subscrObj))
1837 return NULL;
1838 if (cxoConnection_isConnected(conn) < 0)
16661839 return NULL;
16671840
16681841 // destroy ODPI-C subscription
16791852
16801853
16811854 //-----------------------------------------------------------------------------
1682 // cxoConnection_commit()
1683 // Commit the transaction on the connection.
1855 // cxoConnection_getSodaDatabase()
1856 // Create and return a new SODA database object associated with the
1857 // connection.
16841858 //-----------------------------------------------------------------------------
16851859 static PyObject *cxoConnection_getSodaDatabase(cxoConnection *conn,
16861860 PyObject *args)
18332007 {
18342008 return cxoConnection_setAttrText(conn, value, dpiConn_setModule);
18352009 }
1836
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
3838 static PyObject *cxoCursor_arrayVar(cxoCursor*, PyObject*);
3939 static PyObject *cxoCursor_bindNames(cxoCursor*, PyObject*);
4040 static PyObject *cxoCursor_getDescription(cxoCursor*, void*);
41 static PyObject *cxoCursor_getLastRowid(cxoCursor*, void*);
42 static PyObject *cxoCursor_getPrefetchRows(cxoCursor*, void*);
4143 static PyObject *cxoCursor_new(PyTypeObject*, PyObject*, PyObject*);
4244 static int cxoCursor_init(cxoCursor*, PyObject*, PyObject*);
4345 static PyObject *cxoCursor_repr(cxoCursor*);
4749 static PyObject *cxoCursor_contextManagerEnter(cxoCursor*, PyObject*);
4850 static PyObject *cxoCursor_contextManagerExit(cxoCursor*, PyObject*);
4951 static int cxoCursor_performDefine(cxoCursor*, uint32_t);
50
51
52 //-----------------------------------------------------------------------------
53 // declaration of methods for Python type "Cursor"
52 static int cxoCursor_setPrefetchRows(cxoCursor*, PyObject*, void*);
53
54
55 //-----------------------------------------------------------------------------
56 // declaration of methods for Python type
5457 //-----------------------------------------------------------------------------
5558 static PyMethodDef cxoCursorMethods[] = {
5659 { "execute", (PyCFunction) cxoCursor_execute,
9194
9295
9396 //-----------------------------------------------------------------------------
94 // declaration of members for Python type "Cursor"
97 // declaration of members for Python type
9598 //-----------------------------------------------------------------------------
9699 static PyMemberDef cxoCursorMembers[] = {
97100 { "arraysize", T_UINT, offsetof(cxoCursor, arraySize), 0 },
112115
113116
114117 //-----------------------------------------------------------------------------
115 // declaration of calculated members for Python type "Connection"
118 // declaration of calculated members for Python type
116119 //-----------------------------------------------------------------------------
117120 static PyGetSetDef cxoCursorCalcMembers[] = {
118121 { "description", (getter) cxoCursor_getDescription, 0, 0, 0 },
122 { "lastrowid", (getter) cxoCursor_getLastRowid, 0, 0, 0 },
123 { "prefetchrows", (getter) cxoCursor_getPrefetchRows,
124 (setter) cxoCursor_setPrefetchRows, 0, 0 },
119125 { NULL }
120126 };
121127
125131 //-----------------------------------------------------------------------------
126132 PyTypeObject cxoPyTypeCursor = {
127133 PyVarObject_HEAD_INIT(NULL, 0)
128 "cx_Oracle.Cursor", // tp_name
129 sizeof(cxoCursor), // tp_basicsize
130 0, // tp_itemsize
131 (destructor) cxoCursor_free, // tp_dealloc
132 0, // tp_print
133 0, // tp_getattr
134 0, // tp_setattr
135 0, // tp_compare
136 (reprfunc) cxoCursor_repr, // tp_repr
137 0, // tp_as_number
138 0, // tp_as_sequence
139 0, // tp_as_mapping
140 0, // tp_hash
141 0, // tp_call
142 0, // tp_str
143 0, // tp_getattro
144 0, // tp_setattro
145 0, // tp_as_buffer
146 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
147 // tp_flags
148 0, // tp_doc
149 0, // tp_traverse
150 0, // tp_clear
151 0, // tp_richcompare
152 0, // tp_weaklistoffset
153 (getiterfunc) cxoCursor_getIter, // tp_iter
154 (iternextfunc) cxoCursor_getNext, // tp_iternext
155 cxoCursorMethods, // tp_methods
156 cxoCursorMembers, // tp_members
157 cxoCursorCalcMembers, // tp_getset
158 0, // tp_base
159 0, // tp_dict
160 0, // tp_descr_get
161 0, // tp_descr_set
162 0, // tp_dictoffset
163 (initproc) cxoCursor_init, // tp_init
164 0, // tp_alloc
165 cxoCursor_new, // tp_new
166 0, // tp_free
167 0, // tp_is_gc
168 0 // tp_bases
134 .tp_name = "cx_Oracle.Cursor",
135 .tp_basicsize = sizeof(cxoCursor),
136 .tp_dealloc = (destructor) cxoCursor_free,
137 .tp_repr = (reprfunc) cxoCursor_repr,
138 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
139 .tp_iter = (getiterfunc) cxoCursor_getIter,
140 .tp_iternext = (iternextfunc) cxoCursor_getNext,
141 .tp_methods = cxoCursorMethods,
142 .tp_members = cxoCursorMembers,
143 .tp_getset = cxoCursorCalcMembers,
144 .tp_init = (initproc) cxoCursor_init,
145 .tp_new = cxoCursor_new
169146 };
170147
171148
190167 static char *keywordList[] = { "connection", "scrollable", NULL };
191168 cxoConnection *connection;
192169 PyObject *scrollableObj;
170 int isScrollable;
193171
194172 // parse arguments
195173 scrollableObj = NULL;
196174 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!|O", keywordList,
197175 &cxoPyTypeConnection, &connection, &scrollableObj))
198176 return -1;
199 if (cxoUtils_getBooleanValue(scrollableObj, 0, &cursor->isScrollable) < 0)
177 if (cxoUtils_getBooleanValue(scrollableObj, 0, &isScrollable) < 0)
200178 return -1;
179 cursor->isScrollable = (char) isScrollable;
201180
202181 // initialize members
203182 Py_INCREF(connection);
204183 cursor->connection = connection;
205184 cursor->arraySize = 100;
206185 cursor->fetchArraySize = 100;
186 cursor->prefetchRows = DPI_DEFAULT_PREFETCH_ROWS;
207187 cursor->bindArraySize = 1;
208188 cursor->isOpen = 1;
209189
353333 static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
354334 {
355335 PyObject *outputTypeHandler, *result;
336 cxoTransformNum transformNum;
356337 cxoObjectType *objectType;
357 cxoVarType *varType;
358338 dpiQueryInfo queryInfo;
359339 uint32_t pos, size;
340 cxoDbType *dbType;
341 char message[120];
360342 cxoVar *var;
361343
362344 // initialize fetching variables; these are used to reduce the number of
396378 return -1;
397379 }
398380
399 // determine the default type
400 varType = cxoVarType_fromDataTypeInfo(&queryInfo.typeInfo);
401 if (!varType)
381 // determine the default types to use
382 transformNum =
383 cxoTransform_getNumFromDataTypeInfo(&queryInfo.typeInfo);
384 if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
385 snprintf(message, sizeof(message), "Oracle type %d not supported.",
386 queryInfo.typeInfo.oracleTypeNum);
387 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
388 return -1;
389 }
390 dbType = cxoDbType_fromTransformNum(transformNum);
391 if (!dbType)
402392 return -1;
403393
404394 // see if an output type handler should be used
413403 // if using an output type handler, None implies default behavior
414404 if (outputTypeHandler) {
415405 result = PyObject_CallFunction(outputTypeHandler, "Os#Oiii",
416 cursor, queryInfo.name, queryInfo.nameLength,
417 varType->pythonType, size, queryInfo.typeInfo.precision,
406 cursor, queryInfo.name, (Py_ssize_t) queryInfo.nameLength,
407 dbType, size, queryInfo.typeInfo.precision,
418408 queryInfo.typeInfo.scale);
419409 if (!result) {
420410 Py_XDECREF(objectType);
442432
443433 // if no variable created yet, use the database metadata
444434 if (!var) {
445 var = cxoVar_new(cursor, cursor->fetchArraySize, varType, size, 0,
446 objectType);
435 var = cxoVar_new(cursor, cursor->fetchArraySize, transformNum,
436 size, 0, objectType);
447437 if (!var) {
448438 Py_XDECREF(objectType);
449439 return -1;
468458 //-----------------------------------------------------------------------------
469459 static PyObject *cxoCursor_itemDescription(cxoCursor *cursor, uint32_t pos)
470460 {
471 cxoVarType *varType;
472461 int displaySize, index;
473462 dpiQueryInfo queryInfo;
474463 PyObject *tuple, *temp;
464 cxoDbType *dbType;
475465
476466 // get information about the column position
477467 if (dpiStmt_getQueryInfo(cursor->handle, pos, &queryInfo) < 0)
478468 return NULL;
479 varType = cxoVarType_fromDataTypeInfo(&queryInfo.typeInfo);
480 if (!varType)
469 dbType = cxoDbType_fromDataTypeInfo(&queryInfo.typeInfo);
470 if (!dbType)
481471 return NULL;
482472
483473 // set display size based on data type
517507 return NULL;
518508
519509 // set each of the items in the tuple
520 PyTuple_SET_ITEM(tuple, 0, cxoPyString_fromEncodedString(queryInfo.name,
510 PyTuple_SET_ITEM(tuple, 0, PyUnicode_Decode(queryInfo.name,
521511 queryInfo.nameLength, cursor->connection->encodingInfo.encoding,
522512 NULL));
523 Py_INCREF(varType->pythonType);
524 PyTuple_SET_ITEM(tuple, 1, (PyObject*) varType->pythonType);
513 Py_INCREF(dbType);
514 PyTuple_SET_ITEM(tuple, 1, (PyObject*) dbType);
525515 if (displaySize)
526 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(displaySize));
516 PyTuple_SET_ITEM(tuple, 2, PyLong_FromLong(displaySize));
527517 else {
528518 Py_INCREF(Py_None);
529519 PyTuple_SET_ITEM(tuple, 2, Py_None);
530520 }
531521 if (queryInfo.typeInfo.clientSizeInBytes)
532522 PyTuple_SET_ITEM(tuple, 3,
533 PyInt_FromLong(queryInfo.typeInfo.clientSizeInBytes));
523 PyLong_FromLong(queryInfo.typeInfo.clientSizeInBytes));
534524 else {
535525 Py_INCREF(Py_None);
536526 PyTuple_SET_ITEM(tuple, 3, Py_None);
538528 if (queryInfo.typeInfo.precision || queryInfo.typeInfo.scale ||
539529 queryInfo.typeInfo.fsPrecision) {
540530 PyTuple_SET_ITEM(tuple, 4,
541 PyInt_FromLong(queryInfo.typeInfo.precision));
531 PyLong_FromLong(queryInfo.typeInfo.precision));
542532 PyTuple_SET_ITEM(tuple, 5,
543 PyInt_FromLong(queryInfo.typeInfo.scale +
533 PyLong_FromLong(queryInfo.typeInfo.scale +
544534 queryInfo.typeInfo.fsPrecision));
545535 } else {
546536 Py_INCREF(Py_None);
548538 Py_INCREF(Py_None);
549539 PyTuple_SET_ITEM(tuple, 5, Py_None);
550540 }
551 PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(queryInfo.nullOk != 0));
541 PyTuple_SET_ITEM(tuple, 6, PyLong_FromLong(queryInfo.nullOk != 0));
552542
553543 // make sure the tuple is ok
554544 for (index = 0; index < 7; index++) {
606596
607597
608598 //-----------------------------------------------------------------------------
599 // cxoCursor_getLastRowid()
600 // Return the rowid of the last modified row if applicable. If no row was
601 // modified the value None is returned.
602 //-----------------------------------------------------------------------------
603 static PyObject *cxoCursor_getLastRowid(cxoCursor *cursor, void *unused)
604 {
605 uint32_t rowidStrLength;
606 const char *rowidStr;
607 dpiRowid *rowid;
608
609 // make sure the cursor is open
610 if (cxoCursor_isOpen(cursor) < 0)
611 return NULL;
612
613 // get the value, if applicable
614 if (cursor->handle) {
615 if (dpiStmt_getLastRowid(cursor->handle, &rowid) < 0)
616 return cxoError_raiseAndReturnNull();
617 if (rowid) {
618 if (dpiRowid_getStringValue(rowid, &rowidStr, &rowidStrLength) < 0)
619 return cxoError_raiseAndReturnNull();
620 return PyUnicode_Decode(rowidStr, rowidStrLength,
621 cursor->connection->encodingInfo.encoding, NULL);
622 }
623 }
624
625 Py_RETURN_NONE;
626 }
627
628
629 //-----------------------------------------------------------------------------
630 // cxoCursor_getPrefetchRows()
631 // Return an integer providing the number of rows that are prefetched by the
632 // Oracle Client library.
633 //-----------------------------------------------------------------------------
634 static PyObject *cxoCursor_getPrefetchRows(cxoCursor *cursor, void *unused)
635 {
636 if (cxoCursor_isOpen(cursor) < 0)
637 return NULL;
638 return PyLong_FromUnsignedLong(cursor->prefetchRows);
639 }
640
641
642 //-----------------------------------------------------------------------------
609643 // cxoCursor_close()
610644 // Close the cursor. Any action taken on this cursor from this point forward
611645 // results in an exception being raised.
666700 // can happen if all of the values in a previous invocation of
667701 // executemany() were None) and there is now a value; in this case,
668702 // discard the original variable and have a new one created
669 if (origVar->type->transformNum == CXO_TRANSFORM_NONE &&
703 if (origVar->transformNum == CXO_TRANSFORM_NONE &&
670704 value != Py_None) {
671705 origVar = NULL;
672706 varToSet = NULL;
675709 // variable this is only necessary for executemany() since
676710 // execute() always passes a value of 1 for the number of elements
677711 } else if (numElements > origVar->allocatedElements) {
678 *newVar = cxoVar_new(cursor, numElements, origVar->type,
679 origVar->size, origVar->isArray, origVar->objectType);
712 *newVar = cxoVar_new(cursor, numElements,
713 origVar->transformNum, origVar->size, origVar->isArray,
714 origVar->objectType);
680715 if (!*newVar)
681716 return -1;
682717 varToSet = *newVar;
764799 else cursor->bindVariables = PyDict_New();
765800 if (!cursor->bindVariables)
766801 return -1;
767 origNumParams = 0;
768802 }
769803
770804 // handle positional binds
9811015 return cxoError_raiseAndReturnInt();
9821016 }
9831017
1018 // set number of rows to prefetch on execute, if applicable
1019 if (cursor->prefetchRows != DPI_DEFAULT_PREFETCH_ROWS) {
1020 if (dpiStmt_setPrefetchRows(cursor->handle, cursor->prefetchRows) < 0)
1021 return cxoError_raiseAndReturnInt();
1022 }
1023
9841024 // clear row factory, if applicable
9851025 Py_CLEAR(cursor->rowFactory);
9861026
13251365 keywordArguments) < 0)
13261366 return NULL;
13271367
1328 // create the return value
1329 numArgs = PyList_GET_SIZE(cursor->bindVariables);
1368 // create the return value (only positional arguments are returned)
1369 numArgs = (listOfArguments) ? PySequence_Size(listOfArguments) : 0;
13301370 results = PyList_New(numArgs);
13311371 if (!results)
13321372 return NULL;
14381478 &statement, &parameters, &batchErrorsEnabled,
14391479 &arrayDMLRowCountsEnabled))
14401480 return NULL;
1441 if (!PyList_Check(parameters) && !PyInt_Check(parameters)) {
1481 if (!PyList_Check(parameters) && !PyLong_Check(parameters)) {
14421482 PyErr_SetString(PyExc_TypeError,
14431483 "parameters should be a list of sequences/dictionaries "
14441484 "or an integer specifying the number of times to execute "
14631503 return NULL;
14641504
14651505 // perform binds, as required
1466 if (PyInt_Check(parameters))
1467 numRows = (uint32_t) PyInt_AsLong(parameters);
1506 if (PyLong_Check(parameters))
1507 numRows = (uint32_t) PyLong_AsLong(parameters);
14681508 else {
14691509 numRows = (uint32_t) PyList_GET_SIZE(parameters);
14701510 for (i = 0; i < numRows; i++) {
16561696 return cxoError_raiseAndReturnNull();
16571697 cursor->rowCount += numRowsFetched;
16581698 cursor->numRowsInFetchBuffer = 0;
1659 return PyInt_FromLong(numRowsFetched);
1699 return PyLong_FromLong(numRowsFetched);
16601700 }
16611701
16621702
18191859 "inconverter", "outconverter", "typename", "encodingErrors",
18201860 NULL };
18211861 PyObject *inConverter, *outConverter, *typeNameObj;
1862 Py_ssize_t encodingErrorsLength;
1863 cxoTransformNum transformNum;
18221864 const char *encodingErrors;
18231865 cxoObjectType *objType;
1824 cxoVarType *varType;
18251866 int size, arraySize;
18261867 PyObject *type;
18271868 cxoVar *var;
18311872 encodingErrors = NULL;
18321873 arraySize = cursor->bindArraySize;
18331874 inConverter = outConverter = typeNameObj = NULL;
1834 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|iiOOOz",
1875 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|iiOOOz#",
18351876 keywordList, &type, &size, &arraySize, &inConverter, &outConverter,
1836 &typeNameObj, &encodingErrors))
1877 &typeNameObj, &encodingErrors, &encodingErrorsLength))
18371878 return NULL;
18381879
18391880 // determine the type of variable
1840 varType = cxoVarType_fromPythonType(type, &objType);
1841 if (!varType)
1881 if (cxoTransform_getNumFromType(type, &transformNum, &objType) < 0)
18421882 return NULL;
18431883 Py_XINCREF(objType);
1844 if (size == 0)
1845 size = varType->size;
18461884 if (typeNameObj && typeNameObj != Py_None && !objType) {
18471885 objType = cxoObjectType_newByName(cursor->connection, typeNameObj);
18481886 if (!objType)
18501888 }
18511889
18521890 // create the variable
1853 var = cxoVar_new(cursor, arraySize, varType, size, 0, objType);
1891 var = cxoVar_new(cursor, arraySize, transformNum, size, 0, objType);
18541892 Py_XDECREF(objType);
18551893 if (!var)
18561894 return NULL;
18611899
18621900 // assign encoding errors, if applicable
18631901 if (encodingErrors) {
1864 var->encodingErrors = PyMem_Malloc(strlen(encodingErrors) + 1);
1902 var->encodingErrors = PyMem_Malloc(encodingErrorsLength + 1);
18651903 if (!var->encodingErrors) {
18661904 Py_DECREF(var);
18671905 return NULL;
18791917 //-----------------------------------------------------------------------------
18801918 static PyObject *cxoCursor_arrayVar(cxoCursor *cursor, PyObject *args)
18811919 {
1920 cxoTransformNum transformNum;
18821921 uint32_t size, numElements;
18831922 PyObject *type, *value;
18841923 cxoObjectType *objType;
1885 cxoVarType *varType;
18861924 cxoVar *var;
18871925
18881926 // parse arguments
18891927 size = 0;
1890 if (!PyArg_ParseTuple(args, "O!O|i", &PyType_Type, &type, &value, &size))
1891 return NULL;
1892
1893 // determine the type of variable
1894 varType = cxoVarType_fromPythonType(type, &objType);
1895 if (!varType)
1896 return NULL;
1897 if (size == 0)
1898 size = varType->size;
1928 if (!PyArg_ParseTuple(args, "OO|i", &type, &value, &size))
1929 return NULL;
1930
1931 // determine the transform to use for the variable
1932 if (cxoTransform_getNumFromType(type, &transformNum, &objType) < 0)
1933 return NULL;
18991934
19001935 // determine the number of elements to create
19011936 if (PyList_Check(value))
19021937 numElements = (uint32_t) PyList_GET_SIZE(value);
1903 else if (PyInt_Check(value)) {
1904 numElements = (uint32_t) PyInt_AsLong(value);
1938 else if (PyLong_Check(value)) {
1939 numElements = (uint32_t) PyLong_AsLong(value);
19051940 if (PyErr_Occurred())
19061941 return NULL;
19071942 } else {
19111946 }
19121947
19131948 // create the variable
1914 var = cxoVar_new(cursor, numElements, varType, size, 1, objType);
1949 var = cxoVar_new(cursor, numElements, transformNum, size, 1, objType);
19151950 if (!var)
19161951 return NULL;
19171952
19742009 namesList = PyList_New(numBinds);
19752010 if (namesList) {
19762011 for (i = 0; i < numBinds; i++) {
1977 temp = cxoPyString_fromEncodedString(names[i], nameLengths[i],
2012 temp = PyUnicode_Decode(names[i], nameLengths[i],
19782013 cursor->connection->encodingInfo.encoding, NULL);
19792014 if (!temp) {
19802015 Py_CLEAR(namesList);
21822217 return Py_False;
21832218 }
21842219
2220
2221 //-----------------------------------------------------------------------------
2222 // cxoCursor_setPrefetchRows()
2223 // Set the number of rows that are prefetched by the Oracle Client library.
2224 //-----------------------------------------------------------------------------
2225 static int cxoCursor_setPrefetchRows(cxoCursor* cursor, PyObject *value,
2226 void* arg)
2227 {
2228 unsigned long numRows;
2229
2230 if (cxoCursor_isOpen(cursor) < 0)
2231 return -1;
2232 numRows = PyLong_AsUnsignedLong(value);
2233 if (PyErr_Occurred())
2234 return -1;
2235 cursor->prefetchRows = (uint32_t) numRows;
2236 if (cursor->handle && dpiStmt_setPrefetchRows(cursor->handle,
2237 cursor->prefetchRows) < 0)
2238 return cxoError_raiseAndReturnInt();
2239 return 0;
2240 }
0 //-----------------------------------------------------------------------------
1 // Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2 //-----------------------------------------------------------------------------
3
4 //-----------------------------------------------------------------------------
5 // cxoDbType.c
6 // Defines the objects used for identifying all types used by the database.
7 //-----------------------------------------------------------------------------
8
9 #include "cxoModule.h"
10
11 //-----------------------------------------------------------------------------
12 // declaration of functions
13 //-----------------------------------------------------------------------------
14 static void cxoDbType_free(cxoDbType*);
15 static PyObject *cxoDbType_repr(cxoDbType*);
16 static PyObject *cxoDbType_richCompare(cxoDbType*, PyObject*, int);
17 static Py_hash_t cxoDbType_hash(cxoDbType*);
18
19
20 //-----------------------------------------------------------------------------
21 // declaration of members
22 //-----------------------------------------------------------------------------
23 static PyMemberDef cxoMembers[] = {
24 { "name", T_STRING, offsetof(cxoDbType, name), READONLY },
25 { NULL }
26 };
27
28
29 //-----------------------------------------------------------------------------
30 // Python type declaration
31 //-----------------------------------------------------------------------------
32 PyTypeObject cxoPyTypeDbType = {
33 PyVarObject_HEAD_INIT(NULL, 0)
34 .tp_name = "cx_Oracle.DbType",
35 .tp_basicsize = sizeof(cxoDbType),
36 .tp_dealloc = (destructor) cxoDbType_free,
37 .tp_repr = (reprfunc) cxoDbType_repr,
38 .tp_flags = Py_TPFLAGS_DEFAULT,
39 .tp_members = cxoMembers,
40 .tp_richcompare = (richcmpfunc) cxoDbType_richCompare,
41 .tp_hash = (hashfunc) cxoDbType_hash
42 };
43
44
45 //-----------------------------------------------------------------------------
46 // cxoDbType_free()
47 // Free the database type object.
48 //-----------------------------------------------------------------------------
49 static void cxoDbType_free(cxoDbType *dbType)
50 {
51 Py_TYPE(dbType)->tp_free((PyObject*) dbType);
52 }
53
54
55 //-----------------------------------------------------------------------------
56 // cxoDbType_repr()
57 // Return a string representation of a queue.
58 //-----------------------------------------------------------------------------
59 static PyObject *cxoDbType_repr(cxoDbType *dbType)
60 {
61 PyObject *module, *name, *dbTypeName, *result;
62
63 dbTypeName = PyUnicode_DecodeASCII(dbType->name, strlen(dbType->name),
64 NULL);
65 if (!dbTypeName)
66 return NULL;
67 if (cxoUtils_getModuleAndName(Py_TYPE(dbType), &module, &name) < 0) {
68 Py_DECREF(dbTypeName);
69 return NULL;
70 }
71 result = cxoUtils_formatString("<%s.%s %s>",
72 PyTuple_Pack(3, module, name, dbTypeName));
73 Py_DECREF(module);
74 Py_DECREF(name);
75 Py_DECREF(dbTypeName);
76 return result;
77 }
78
79
80 //-----------------------------------------------------------------------------
81 // cxoDbType_richCompare()
82 // Peforms a comparison between the database type and another Python object.
83 // Equality (and inequality) are used to match database API types with their
84 // associated database types.
85 //-----------------------------------------------------------------------------
86 static PyObject *cxoDbType_richCompare(cxoDbType* dbType, PyObject* obj,
87 int op)
88 {
89 cxoApiType *apiType;
90 int status, equal;
91
92 // only equality and inequality can be checked
93 if (op != Py_EQ && op != Py_NE) {
94 Py_INCREF(Py_NotImplemented);
95 return Py_NotImplemented;
96 }
97
98 // check for exact object
99 equal = 0;
100 if (obj == (PyObject*) dbType) {
101 equal = 1;
102
103 // check for API type
104 } else {
105 status = PyObject_IsInstance(obj, (PyObject*) &cxoPyTypeApiType);
106 if (status < 0)
107 return NULL;
108 if (status == 1) {
109 apiType = (cxoApiType*) obj;
110 status = PySequence_Contains(apiType->dbTypes, (PyObject*) dbType);
111 if (status < 0)
112 return NULL;
113 equal = (status == 1) ? 1 : 0;
114 }
115 }
116
117 // determine return value
118 if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) {
119 Py_RETURN_TRUE;
120 }
121 Py_RETURN_FALSE;
122 }
123
124
125 //-----------------------------------------------------------------------------
126 // cxoDbType_hash()
127 // Return a hash value for the instance.
128 //-----------------------------------------------------------------------------
129 static Py_hash_t cxoDbType_hash(cxoDbType *dbType)
130 {
131 return (Py_hash_t) dbType->num;
132 }
133
134
135 //-----------------------------------------------------------------------------
136 // cxoDbType_fromDataTypeInfo()
137 // Return the database type given the data type info available from ODPI-C.
138 //-----------------------------------------------------------------------------
139 cxoDbType *cxoDbType_fromDataTypeInfo(dpiDataTypeInfo *info)
140 {
141 char message[120];
142
143 switch (info->oracleTypeNum) {
144 case DPI_ORACLE_TYPE_VARCHAR:
145 return cxoDbTypeVarchar;
146 case DPI_ORACLE_TYPE_NVARCHAR:
147 return cxoDbTypeNvarchar;
148 case DPI_ORACLE_TYPE_CHAR:
149 return cxoDbTypeChar;
150 case DPI_ORACLE_TYPE_NCHAR:
151 return cxoDbTypeNchar;
152 case DPI_ORACLE_TYPE_ROWID:
153 return cxoDbTypeRowid;
154 case DPI_ORACLE_TYPE_RAW:
155 return cxoDbTypeRaw;
156 case DPI_ORACLE_TYPE_NATIVE_DOUBLE:
157 return cxoDbTypeBinaryDouble;
158 case DPI_ORACLE_TYPE_NATIVE_FLOAT:
159 return cxoDbTypeBinaryFloat;
160 case DPI_ORACLE_TYPE_NATIVE_INT:
161 return cxoDbTypeBinaryInteger;
162 case DPI_ORACLE_TYPE_NUMBER:
163 return cxoDbTypeNumber;
164 case DPI_ORACLE_TYPE_DATE:
165 return cxoDbTypeDate;
166 case DPI_ORACLE_TYPE_TIMESTAMP:
167 return cxoDbTypeTimestamp;
168 case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
169 return cxoDbTypeTimestampTZ;
170 case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
171 return cxoDbTypeTimestampLTZ;
172 case DPI_ORACLE_TYPE_INTERVAL_DS:
173 return cxoDbTypeIntervalDS;
174 case DPI_ORACLE_TYPE_INTERVAL_YM:
175 return cxoDbTypeIntervalYM;
176 case DPI_ORACLE_TYPE_CLOB:
177 return cxoDbTypeClob;
178 case DPI_ORACLE_TYPE_NCLOB:
179 return cxoDbTypeNclob;
180 case DPI_ORACLE_TYPE_BLOB:
181 return cxoDbTypeBlob;
182 case DPI_ORACLE_TYPE_BFILE:
183 return cxoDbTypeBfile;
184 case DPI_ORACLE_TYPE_STMT:
185 return cxoDbTypeCursor;
186 case DPI_ORACLE_TYPE_OBJECT:
187 return cxoDbTypeObject;
188 case DPI_ORACLE_TYPE_LONG_VARCHAR:
189 return cxoDbTypeLong;
190 case DPI_ORACLE_TYPE_LONG_RAW:
191 return cxoDbTypeLongRaw;
192 case DPI_ORACLE_TYPE_BOOLEAN:
193 return cxoDbTypeBoolean;
194 default:
195 break;
196 }
197
198 snprintf(message, sizeof(message), "Oracle type %d not supported.",
199 info->oracleTypeNum);
200 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
201 return NULL;
202 }
203
204
205 //-----------------------------------------------------------------------------
206 // cxoDbType_fromTransformNum()
207 // Return the database type given the transformation number.
208 //-----------------------------------------------------------------------------
209 cxoDbType *cxoDbType_fromTransformNum(cxoTransformNum transformNum)
210 {
211 char message[120];
212
213 switch (transformNum) {
214 case CXO_TRANSFORM_BINARY:
215 return cxoDbTypeRaw;
216 case CXO_TRANSFORM_BFILE:
217 return cxoDbTypeBfile;
218 case CXO_TRANSFORM_BLOB:
219 return cxoDbTypeBlob;
220 case CXO_TRANSFORM_BOOLEAN:
221 return cxoDbTypeBoolean;
222 case CXO_TRANSFORM_CLOB:
223 return cxoDbTypeClob;
224 case CXO_TRANSFORM_CURSOR:
225 return cxoDbTypeCursor;
226 case CXO_TRANSFORM_DATE:
227 case CXO_TRANSFORM_DATETIME:
228 return cxoDbTypeDate;
229 case CXO_TRANSFORM_DECIMAL:
230 case CXO_TRANSFORM_FLOAT:
231 case CXO_TRANSFORM_INT:
232 return cxoDbTypeNumber;
233 case CXO_TRANSFORM_FIXED_CHAR:
234 return cxoDbTypeChar;
235 case CXO_TRANSFORM_FIXED_NCHAR:
236 return cxoDbTypeNchar;
237 case CXO_TRANSFORM_LONG_BINARY:
238 return cxoDbTypeLongRaw;
239 case CXO_TRANSFORM_LONG_STRING:
240 return cxoDbTypeLong;
241 case CXO_TRANSFORM_NATIVE_DOUBLE:
242 return cxoDbTypeBinaryDouble;
243 case CXO_TRANSFORM_NATIVE_FLOAT:
244 return cxoDbTypeBinaryFloat;
245 case CXO_TRANSFORM_NATIVE_INT:
246 return cxoDbTypeBinaryInteger;
247 case CXO_TRANSFORM_NCLOB:
248 return cxoDbTypeNclob;
249 case CXO_TRANSFORM_NSTRING:
250 return cxoDbTypeNvarchar;
251 case CXO_TRANSFORM_OBJECT:
252 return cxoDbTypeObject;
253 case CXO_TRANSFORM_ROWID:
254 return cxoDbTypeRowid;
255 case CXO_TRANSFORM_NONE:
256 case CXO_TRANSFORM_STRING:
257 return cxoDbTypeVarchar;
258 case CXO_TRANSFORM_TIMEDELTA:
259 return cxoDbTypeIntervalDS;
260 case CXO_TRANSFORM_TIMESTAMP:
261 return cxoDbTypeTimestamp;
262 case CXO_TRANSFORM_TIMESTAMP_LTZ:
263 return cxoDbTypeTimestampLTZ;
264 case CXO_TRANSFORM_TIMESTAMP_TZ:
265 return cxoDbTypeTimestampTZ;
266 default:
267 break;
268 }
269
270 snprintf(message, sizeof(message), "transform %d not supported.",
271 transformNum);
272 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
273 return NULL;
274 }
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
7070 //-----------------------------------------------------------------------------
7171 PyTypeObject cxoPyTypeDeqOptions = {
7272 PyVarObject_HEAD_INIT(NULL, 0)
73 "cx_Oracle.DeqOptions", // tp_name
74 sizeof(cxoDeqOptions), // tp_basicsize
75 0, // tp_itemsize
76 (destructor) cxoDeqOptions_free, // tp_dealloc
77 0, // tp_print
78 0, // tp_getattr
79 0, // tp_setattr
80 0, // tp_compare
81 0, // tp_repr
82 0, // tp_as_number
83 0, // tp_as_sequence
84 0, // tp_as_mapping
85 0, // tp_hash
86 0, // tp_call
87 0, // tp_str
88 0, // tp_getattro
89 0, // tp_setattro
90 0, // tp_as_buffer
91 Py_TPFLAGS_DEFAULT, // tp_flags
92 0, // tp_doc
93 0, // tp_traverse
94 0, // tp_clear
95 0, // tp_richcompare
96 0, // tp_weaklistoffset
97 0, // tp_iter
98 0, // tp_iternext
99 0, // tp_methods
100 0, // tp_members
101 cxoDeqOptionsCalcMembers, // tp_getset
102 0, // tp_base
103 0, // tp_dict
104 0, // tp_descr_get
105 0, // tp_descr_set
106 0, // tp_dictoffset
107 0, // tp_init
108 0, // tp_alloc
109 0, // tp_new
110 0, // tp_free
111 0, // tp_is_gc
112 0 // tp_bases
73 .tp_name = "cx_Oracle.DeqOptions",
74 .tp_basicsize = sizeof(cxoDeqOptions),
75 .tp_dealloc = (destructor) cxoDeqOptions_free,
76 .tp_flags = Py_TPFLAGS_DEFAULT,
77 .tp_getset = cxoDeqOptionsCalcMembers
11378 };
11479
11580
11782 // cxoDeqOptions_new()
11883 // Create a new dequeue options object.
11984 //-----------------------------------------------------------------------------
120 cxoDeqOptions *cxoDeqOptions_new(cxoConnection *connection)
85 cxoDeqOptions *cxoDeqOptions_new(cxoConnection *connection,
86 dpiDeqOptions *handle)
12187 {
12288 cxoDeqOptions *options;
89 int status;
12390
12491 options = (cxoDeqOptions*)
12592 cxoPyTypeDeqOptions.tp_alloc(&cxoPyTypeDeqOptions, 0);
12693 if (!options)
12794 return NULL;
128 if (dpiConn_newDeqOptions(connection->handle, &options->handle) < 0) {
95 if (handle) {
96 status = dpiDeqOptions_addRef(handle);
97 } else {
98 status = dpiConn_newDeqOptions(connection->handle, &handle);
99 }
100 if (status < 0) {
101 cxoError_raiseAndReturnNull();
129102 Py_DECREF(options);
130 cxoError_raiseAndReturnNull();
131103 return NULL;
132104 }
105 options->handle = handle;
133106 options->encoding = connection->encodingInfo.encoding;
134107
135108 return options;
164137 return cxoError_raiseAndReturnNull();
165138 if (!value)
166139 Py_RETURN_NONE;
167 return cxoPyString_fromEncodedString(value, valueLength, options->encoding,
168 NULL);
140 return PyUnicode_Decode(value, valueLength, options->encoding, NULL);
169141 }
170142
171143
232204
233205 if (dpiDeqOptions_getMode(options->handle, &value) < 0)
234206 return cxoError_raiseAndReturnNull();
235 return PyInt_FromLong(value);
207 return PyLong_FromLong(value);
236208 }
237209
238210
264236
265237 if (dpiDeqOptions_getNavigation(options->handle, &value) < 0)
266238 return cxoError_raiseAndReturnNull();
267 return PyInt_FromLong(value);
239 return PyLong_FromLong(value);
268240 }
269241
270242
290262
291263 if (dpiDeqOptions_getVisibility(options->handle, &value) < 0)
292264 return cxoError_raiseAndReturnNull();
293 return PyInt_FromLong(value);
265 return PyLong_FromLong(value);
294266 }
295267
296268
304276
305277 if (dpiDeqOptions_getWait(options->handle, &value) < 0)
306278 return cxoError_raiseAndReturnNull();
307 return PyInt_FromLong(value);
279 return PyLong_FromLong(value);
308280 }
309281
310282
353325 {
354326 dpiMessageDeliveryMode value;
355327
356 value = PyInt_AsLong(valueObj);
328 value = PyLong_AsLong(valueObj);
357329 if (PyErr_Occurred())
358330 return -1;
359331 if (dpiDeqOptions_setDeliveryMode(options->handle, value) < 0)
371343 {
372344 dpiDeqMode value;
373345
374 value = PyInt_AsLong(valueObj);
346 value = PyLong_AsLong(valueObj);
375347 if (PyErr_Occurred())
376348 return -1;
377349 if (dpiDeqOptions_setMode(options->handle, value) < 0)
408380 {
409381 dpiDeqNavigation value;
410382
411 value = PyInt_AsLong(valueObj);
383 value = PyLong_AsLong(valueObj);
412384 if (PyErr_Occurred())
413385 return -1;
414386 if (dpiDeqOptions_setNavigation(options->handle, value) < 0)
438410 {
439411 dpiVisibility value;
440412
441 value = PyInt_AsLong(valueObj);
413 value = PyLong_AsLong(valueObj);
442414 if (PyErr_Occurred())
443415 return -1;
444416 if (dpiDeqOptions_setVisibility(options->handle, value) < 0)
456428 {
457429 uint32_t value;
458430
459 value = PyInt_AsLong(valueObj);
431 value = PyLong_AsLong(valueObj);
460432 if (PyErr_Occurred())
461433 return -1;
462434 if (dpiDeqOptions_setWait(options->handle, value) < 0)
463435 return cxoError_raiseAndReturnInt();
464436 return 0;
465437 }
466
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
4242 //-----------------------------------------------------------------------------
4343 PyTypeObject cxoPyTypeEnqOptions = {
4444 PyVarObject_HEAD_INIT(NULL, 0)
45 "cx_Oracle.EnqOptions", // tp_name
46 sizeof(cxoEnqOptions), // tp_basicsize
47 0, // tp_itemsize
48 (destructor) cxoEnqOptions_free, // tp_dealloc
49 0, // tp_print
50 0, // tp_getattr
51 0, // tp_setattr
52 0, // tp_compare
53 0, // tp_repr
54 0, // tp_as_number
55 0, // tp_as_sequence
56 0, // tp_as_mapping
57 0, // tp_hash
58 0, // tp_call
59 0, // tp_str
60 0, // tp_getattro
61 0, // tp_setattro
62 0, // tp_as_buffer
63 Py_TPFLAGS_DEFAULT, // tp_flags
64 0, // tp_doc
65 0, // tp_traverse
66 0, // tp_clear
67 0, // tp_richcompare
68 0, // tp_weaklistoffset
69 0, // tp_iter
70 0, // tp_iternext
71 0, // tp_methods
72 0, // tp_members
73 cxoEnqOptionsCalcMembers, // tp_getset
74 0, // tp_base
75 0, // tp_dict
76 0, // tp_descr_get
77 0, // tp_descr_set
78 0, // tp_dictoffset
79 0, // tp_init
80 0, // tp_alloc
81 0, // tp_new
82 0, // tp_free
83 0, // tp_is_gc
84 0 // tp_bases
45 .tp_name = "cx_Oracle.EnqOptions",
46 .tp_basicsize = sizeof(cxoEnqOptions),
47 .tp_dealloc = (destructor) cxoEnqOptions_free,
48 .tp_flags = Py_TPFLAGS_DEFAULT,
49 .tp_getset = cxoEnqOptionsCalcMembers
8550 };
8651
8752
8954 // cxoEnqOptions_new()
9055 // Create a new enqueue options object.
9156 //-----------------------------------------------------------------------------
92 cxoEnqOptions *cxoEnqOptions_new(cxoConnection *connection)
57 cxoEnqOptions *cxoEnqOptions_new(cxoConnection *connection,
58 dpiEnqOptions *handle)
9359 {
94 cxoEnqOptions *self;
60 cxoEnqOptions *options;
61 int status;
9562
96 self = (cxoEnqOptions*)
63 options = (cxoEnqOptions*)
9764 cxoPyTypeEnqOptions.tp_alloc(&cxoPyTypeEnqOptions, 0);
98 if (!self)
65 if (!options)
9966 return NULL;
100 if (dpiConn_newEnqOptions(connection->handle, &self->handle) < 0) {
101 Py_DECREF(self);
67 if (handle) {
68 status = dpiEnqOptions_addRef(handle);
69 } else {
70 status = dpiConn_newEnqOptions(connection->handle, &handle);
71 }
72 if (status < 0) {
10273 cxoError_raiseAndReturnNull();
74 Py_DECREF(options);
10375 return NULL;
10476 }
105 self->encoding = connection->encodingInfo.encoding;
77 options->handle = handle;
78 options->encoding = connection->encodingInfo.encoding;
10679
107 return self;
80 return options;
10881 }
10982
11083
137110 return cxoError_raiseAndReturnNull();
138111 if (!value)
139112 Py_RETURN_NONE;
140 return cxoPyString_fromEncodedString(value, valueLength, self->encoding,
141 NULL);
113 return PyUnicode_Decode(value, valueLength, self->encoding, NULL);
142114 }
143115
144116
152124
153125 if (dpiEnqOptions_getVisibility(self->handle, &value) < 0)
154126 return cxoError_raiseAndReturnNull();
155 return PyInt_FromLong(value);
127 return PyLong_FromLong(value);
156128 }
157129
158130
165137 {
166138 dpiMessageDeliveryMode value;
167139
168 value = PyInt_AsLong(valueObj);
140 value = PyLong_AsLong(valueObj);
169141 if (PyErr_Occurred())
170142 return -1;
171143 if (dpiEnqOptions_setDeliveryMode(self->handle, value) < 0)
204176 {
205177 dpiVisibility value;
206178
207 value = PyInt_AsLong(valueObj);
179 value = PyLong_AsLong(valueObj);
208180 if (PyErr_Occurred())
209181 return -1;
210182 if (dpiEnqOptions_setVisibility(self->handle, value) < 0)
211183 return cxoError_raiseAndReturnInt();
212184 return 0;
213185 }
214
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
5050 //-----------------------------------------------------------------------------
5151 PyTypeObject cxoPyTypeError = {
5252 PyVarObject_HEAD_INIT(NULL, 0)
53 "cx_Oracle._Error", // tp_name
54 sizeof(cxoError), // tp_basicsize
55 0, // tp_itemsize
56 (destructor) cxoError_free, // tp_dealloc
57 0, // tp_print
58 0, // tp_getattr
59 0, // tp_setattr
60 0, // tp_compare
61 0, // tp_repr
62 0, // tp_as_number
63 0, // tp_as_sequence
64 0, // tp_as_mapping
65 0, // tp_hash
66 0, // tp_call
67 (reprfunc) cxoError_str, // tp_str
68 0, // tp_getattro
69 0, // tp_setattro
70 0, // tp_as_buffer
71 Py_TPFLAGS_DEFAULT, // tp_flags
72 0, // tp_doc
73 0, // tp_traverse
74 0, // tp_clear
75 0, // tp_richcompare
76 0, // tp_weaklistoffset
77 0, // tp_iter
78 0, // tp_iternext
79 cxoErrorMethods, // tp_methods
80 cxoErrorMembers, // tp_members
81 0, // tp_getset
82 0, // tp_base
83 0, // tp_dict
84 0, // tp_descr_get
85 0, // tp_descr_set
86 0, // tp_dictoffset
87 0, // tp_init
88 0, // tp_alloc
89 cxoError_new, // tp_new
90 0, // tp_free
91 0, // tp_is_gc
92 0 // tp_bases
53 .tp_name = "cx_Oracle._Error",
54 .tp_basicsize = sizeof(cxoError),
55 .tp_dealloc = (destructor) cxoError_free,
56 .tp_str = (reprfunc) cxoError_str,
57 .tp_flags = Py_TPFLAGS_DEFAULT,
58 .tp_methods = cxoErrorMethods,
59 .tp_members = cxoErrorMembers,
60 .tp_new = cxoError_new
9361 };
9462
9563
156124 error->isRecoverable = (char) errorInfo->isRecoverable;
157125
158126 // create message
159 error->message = cxoPyString_fromEncodedString(errorInfo->message,
127 error->message = PyUnicode_Decode(errorInfo->message,
160128 errorInfo->messageLength, errorInfo->encoding, NULL);
161129 if (!error->message) {
162130 Py_DECREF(error);
164132 }
165133
166134 // create context composed of function name and action
167 #if PY_MAJOR_VERSION >= 3
168135 error->context = PyUnicode_FromFormat("%s: %s", errorInfo->fnName,
169136 errorInfo->action);
170 #else
171 error->context = PyString_FromFormat("%s: %s", errorInfo->fnName,
172 errorInfo->action);
173 #endif
174137 if (!error->context) {
175138 Py_DECREF(error);
176139 return NULL;
194157 return NULL;
195158 Py_INCREF(Py_None);
196159 error->context = Py_None;
197 error->message = cxoPyString_fromAscii(message);
160 error->message = PyUnicode_DecodeASCII(message, strlen(message), NULL);
198161 if (!error->message) {
199162 Py_DECREF(error);
200163 return NULL;
244207 if (!error)
245208 return -1;
246209 switch (errorInfo->code) {
247 case 1:
248 case 1400:
249 case 2290:
250 case 2291:
251 case 2292:
210 case 1: // unique constraint violated
211 case 1400: // cannot insert NULL
212 case 2290: // check constraint violated
213 case 2291: // integrity constraint violated - parent key not found
214 case 2292: // integrity constraint violated - child record found
215 case 40479: // internal JSON serializer error
252216 exceptionType = cxoIntegrityErrorException;
253217 break;
254 case 22:
255 case 378:
256 case 602:
257 case 603:
258 case 604:
259 case 609:
260 case 1012:
261 case 1013:
262 case 1033:
263 case 1034:
264 case 1041:
265 case 1043:
266 case 1089:
267 case 1090:
268 case 1092:
269 case 3113:
270 case 3114:
271 case 3122:
272 case 3135:
273 case 12153:
274 case 12203:
275 case 12500:
276 case 12571:
277 case 27146:
278 case 28511:
218 case 22: // invalid session ID; access denied
219 case 378: // buffer pools cannot be created as specified
220 case 600: // internal error code
221 case 602: // internal programming exception
222 case 603: // ORACLE server session terminated by fatal error
223 case 604: // error occurred at recursive SQL level
224 case 609: // could not attach to incoming connection
225 case 1012: // not logged on
226 case 1013: // user requested cancel of current operation
227 case 1033: // ORACLE initialization or shutdown in progress
228 case 1034: // ORACLE not available
229 case 1041: // internal error. hostdef extension doesn't exist
230 case 1043: // user side memory corruption
231 case 1089: // immediate shutdown or close in progress
232 case 1090: // shutdown in progress - connection is not permitted
233 case 1092: // ORACLE instance terminated. Disconnection forced
234 case 3113: // end-of-file on communication channel
235 case 3114: // not connected to ORACLE
236 case 3122: // attempt to close ORACLE-side window on user side
237 case 3135: // connection lost contact
238 case 12153: // TNS:not connected
239 case 12203: // TNS:unable to connect to destination
240 case 12500: // TNS:listener failed to start a dedicated server process
241 case 12571: // TNS:packet writer failure
242 case 27146: // post/wait initialization failed
243 case 28511: // lost RPC connection to heterogeneous remote agent
279244 exceptionType = cxoOperationalErrorException;
280245 break;
281246 default:
327292 Py_INCREF(error->message);
328293 return error->message;
329294 }
330
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
2222 //-----------------------------------------------------------------------------
2323 PyTypeObject cxoPyTypeFuture = {
2424 PyVarObject_HEAD_INIT(NULL, 0)
25 "cx_Oracle.__future__", // tp_name
26 sizeof(cxoFuture), // tp_basicsize
27 0, // tp_itemsize
28 (destructor) cxoFuture_free, // tp_dealloc
29 0, // tp_print
30 0, // tp_getattr
31 0, // tp_setattr
32 0, // tp_compare
33 0, // tp_repr
34 0, // tp_as_number
35 0, // tp_as_sequence
36 0, // tp_as_mapping
37 0, // tp_hash
38 0, // tp_call
39 0, // tp_str
40 (getattrofunc) cxoFuture_getAttr, // tp_getattro
41 (setattrofunc) cxoFuture_setAttr, // tp_setattro
42 0, // tp_as_buffer
43 Py_TPFLAGS_DEFAULT // tp_flags
25 .tp_name = "cx_Oracle.__future__",
26 .tp_basicsize = sizeof(cxoFuture),
27 .tp_dealloc = (destructor) cxoFuture_free,
28 .tp_getattro = (getattrofunc) cxoFuture_getAttr,
29 .tp_setattro = (setattrofunc) cxoFuture_setAttr,
30 .tp_flags = Py_TPFLAGS_DEFAULT
4431 };
4532
4633
7461 {
7562 return 0;
7663 }
77
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
3333
3434
3535 //-----------------------------------------------------------------------------
36 // declaration of methods for Python type "LOB"
36 // declaration of methods
3737 //-----------------------------------------------------------------------------
3838 static PyMethodDef cxoLobMethods[] = {
3939 { "size", (PyCFunction) cxoLob_size, METH_NOARGS },
5353
5454
5555 //-----------------------------------------------------------------------------
56 // declaration of members
57 //-----------------------------------------------------------------------------
58 static PyMemberDef cxoMembers[] = {
59 { "type", T_OBJECT, offsetof(cxoLob, dbType), READONLY },
60 { NULL }
61 };
62
63
64 //-----------------------------------------------------------------------------
5665 // Python type declaration
5766 //-----------------------------------------------------------------------------
5867 PyTypeObject cxoPyTypeLob = {
5968 PyVarObject_HEAD_INIT(NULL, 0)
60 "cx_Oracle.LOB", // tp_name
61 sizeof(cxoLob), // tp_basicsize
62 0, // tp_itemsize
63 (destructor) cxoLob_free, // tp_dealloc
64 0, // tp_print
65 0, // tp_getattr
66 0, // tp_setattr
67 0, // tp_compare
68 0, // tp_repr
69 0, // tp_as_number
70 0, // tp_as_sequence
71 0, // tp_as_mapping
72 0, // tp_hash
73 0, // tp_call
74 (reprfunc) cxoLob_str, // tp_str
75 0, // tp_getattro
76 0, // tp_setattro
77 0, // tp_as_buffer
78 Py_TPFLAGS_DEFAULT, // tp_flags
79 0, // tp_doc
80 0, // tp_traverse
81 0, // tp_clear
82 0, // tp_richcompare
83 0, // tp_weaklistoffset
84 0, // tp_iter
85 0, // tp_iternext
86 cxoLobMethods, // tp_methods
87 0, // tp_members
88 0, // tp_getset
89 0, // tp_base
90 0, // tp_dict
91 0, // tp_descr_get
92 0, // tp_descr_set
93 0, // tp_dictoffset
94 0, // tp_init
95 0, // tp_alloc
96 0, // tp_new
97 0, // tp_free
98 0, // tp_is_gc
99 0 // tp_bases
69 .tp_name = "cx_Oracle.LOB",
70 .tp_basicsize = sizeof(cxoLob),
71 .tp_dealloc = (destructor) cxoLob_free,
72 .tp_str = (reprfunc) cxoLob_str,
73 .tp_flags = Py_TPFLAGS_DEFAULT,
74 .tp_methods = cxoLobMethods,
75 .tp_members = cxoMembers
10076 };
10177
10278
10480 // cxoLob_new()
10581 // Create a new LOB.
10682 //-----------------------------------------------------------------------------
107 PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
83 PyObject *cxoLob_new(cxoConnection *connection, cxoDbType *dbType,
10884 dpiLob *handle)
10985 {
11086 cxoLob *lob;
11389 if (!lob)
11490 return NULL;
11591 lob->handle = handle;
116 lob->oracleTypeNum = oracleTypeNum;
11792 Py_INCREF(connection);
11893 lob->connection = connection;
94 Py_INCREF(dbType);
95 lob->dbType = dbType;
11996 return (PyObject*) lob;
12097 }
12198
130107 dpiLob_release(lob->handle);
131108 lob->handle = NULL;
132109 }
110 Py_CLEAR(lob->dbType);
133111 Py_CLEAR(lob->connection);
134112 Py_TYPE(lob)->tp_free((PyObject*) lob);
135113 }
174152 }
175153
176154 // return the result
177 if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
155 if (lob->dbType == cxoDbTypeNclob) {
178156 result = PyUnicode_Decode(buffer, (Py_ssize_t) bufferSize,
179157 lob->connection->encodingInfo.nencoding, NULL);
180 else if (lob->oracleTypeNum == DPI_ORACLE_TYPE_CLOB)
181 result = cxoPyString_fromEncodedString(buffer, (Py_ssize_t) bufferSize,
158 } else if (lob->dbType == cxoDbTypeClob) {
159 result = PyUnicode_Decode(buffer, (Py_ssize_t) bufferSize,
182160 lob->connection->encodingInfo.encoding, NULL);
183 else result = PyBytes_FromStringAndSize(buffer, (Py_ssize_t) bufferSize);
161 } else {
162 result = PyBytes_FromStringAndSize(buffer, (Py_ssize_t) bufferSize);
163 }
184164 PyMem_Free(buffer);
185165 return result;
186166 }
197177 cxoBuffer buffer;
198178 int status;
199179
200 if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
180 if (lob->dbType == cxoDbTypeNclob)
201181 encoding = lob->connection->encodingInfo.nencoding;
202182 else encoding = lob->connection->encodingInfo.encoding;
203183 if (cxoBuffer_fromObject(&buffer, dataObj, encoding) < 0)
363343
364344 if (dpiLob_getChunkSize(lob->handle, &size) < 0)
365345 return cxoError_raiseAndReturnNull();
366 return PyInt_FromLong(size);
346 return PyLong_FromLong(size);
367347 }
368348
369349
407387 result = PyTuple_New(2);
408388 if (!result)
409389 return NULL;
410 temp = cxoPyString_fromEncodedString(directoryAlias, directoryAliasLength,
390 temp = PyUnicode_Decode(directoryAlias, directoryAliasLength,
411391 lob->connection->encodingInfo.encoding, NULL);
412392 if (!temp) {
413393 Py_DECREF(result);
414394 return NULL;
415395 }
416396 PyTuple_SET_ITEM(result, 0, temp);
417 temp = cxoPyString_fromEncodedString(fileName, fileNameLength,
397 temp = PyUnicode_Decode(fileName, fileNameLength,
418398 lob->connection->encodingInfo.encoding, NULL);
419399 if (!temp) {
420400 Py_DECREF(result);
480460 Py_RETURN_TRUE;
481461 Py_RETURN_FALSE;
482462 }
483
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
1818 // define macro for adding integer constants
1919 #define CXO_ADD_INT_CONSTANT(name, value) \
2020 if (PyModule_AddIntConstant(module, name, value) < 0) \
21 return NULL;
22
23 // define macro for adding Python Database API types
24 #define CXO_ADD_API_TYPE(name, transformNum, typeObj) \
25 if (cxoModule_addApiType(module, name, transformNum, typeObj) < 0) \
26 return NULL;
27
28 // define macro for adding database types
29 #define CXO_ADD_DB_TYPE(num, name, transformNum, typeObj) \
30 if (cxoModule_addDbType(module, num, name, transformNum, typeObj) < 0) \
31 return NULL;
32
33 // define macro for associating database types with Database API types
34 #define CXO_ASSOCIATE_DB_TYPE(apiType, dbType) \
35 if (PyList_Append(apiType->dbTypes, (PyObject*) dbType) < 0) \
2136 return NULL;
2237
2338 // define macro for adding type objects
4762 PyObject *cxoNotSupportedErrorException = NULL;
4863 PyObject *cxoJsonDumpFunction = NULL;
4964 PyObject *cxoJsonLoadFunction = NULL;
65
66 cxoDbType *cxoDbTypeBfile = NULL;
67 cxoDbType *cxoDbTypeBinaryDouble = NULL;
68 cxoDbType *cxoDbTypeBinaryFloat = NULL;
69 cxoDbType *cxoDbTypeBinaryInteger = NULL;
70 cxoDbType *cxoDbTypeBlob = NULL;
71 cxoDbType *cxoDbTypeBoolean = NULL;
72 cxoDbType *cxoDbTypeChar = NULL;
73 cxoDbType *cxoDbTypeClob = NULL;
74 cxoDbType *cxoDbTypeCursor = NULL;
75 cxoDbType *cxoDbTypeDate = NULL;
76 cxoDbType *cxoDbTypeIntervalDS = NULL;
77 cxoDbType *cxoDbTypeIntervalYM = NULL;
78 cxoDbType *cxoDbTypeLong = NULL;
79 cxoDbType *cxoDbTypeLongRaw = NULL;
80 cxoDbType *cxoDbTypeNchar = NULL;
81 cxoDbType *cxoDbTypeNclob = NULL;
82 cxoDbType *cxoDbTypeNumber = NULL;
83 cxoDbType *cxoDbTypeNvarchar = NULL;
84 cxoDbType *cxoDbTypeObject = NULL;
85 cxoDbType *cxoDbTypeRaw = NULL;
86 cxoDbType *cxoDbTypeRowid = NULL;
87 cxoDbType *cxoDbTypeTimestamp = NULL;
88 cxoDbType *cxoDbTypeTimestampLTZ = NULL;
89 cxoDbType *cxoDbTypeTimestampTZ = NULL;
90 cxoDbType *cxoDbTypeVarchar = NULL;
91
92 cxoApiType *cxoApiTypeBinary = NULL;
93 cxoApiType *cxoApiTypeDatetime = NULL;
94 cxoApiType *cxoApiTypeNumber = NULL;
95 cxoApiType *cxoApiTypeRowid = NULL;
96 cxoApiType *cxoApiTypeString = NULL;
97
5098 cxoFuture *cxoFutureObj = NULL;
5199 dpiContext *cxoDpiContext = NULL;
52100 dpiVersionInfo cxoClientVersionInfo;
101
102
103 //-----------------------------------------------------------------------------
104 // cxoModule_addApiType()
105 // Create a Python Database API type and add it to the module.
106 //-----------------------------------------------------------------------------
107 static int cxoModule_addApiType(PyObject *module, const char *name,
108 cxoTransformNum defaultTransformNum, cxoApiType **apiType)
109 {
110 cxoApiType *tempApiType;
111
112 tempApiType =
113 (cxoApiType*) cxoPyTypeApiType.tp_alloc(&cxoPyTypeApiType, 0);
114 if (!tempApiType)
115 return -1;
116 tempApiType->name = name;
117 tempApiType->defaultTransformNum = defaultTransformNum;
118 tempApiType->dbTypes = PyList_New(0);
119 if (!tempApiType->dbTypes) {
120 Py_DECREF(tempApiType);
121 return -1;
122 }
123 if (PyModule_AddObject(module, name, (PyObject*) tempApiType) < 0) {
124 Py_DECREF(tempApiType);
125 return -1;
126 }
127 *apiType = tempApiType;
128 return 0;
129 }
130
131
132 //-----------------------------------------------------------------------------
133 // cxoModule_addDbType()
134 // Create a database type and add it to the module.
135 //-----------------------------------------------------------------------------
136 static int cxoModule_addDbType(PyObject *module, uint32_t num,
137 const char *name, cxoTransformNum defaultTransformNum,
138 cxoDbType **dbType)
139 {
140 cxoDbType *tempDbType;
141
142 tempDbType = (cxoDbType*) cxoPyTypeDbType.tp_alloc(&cxoPyTypeDbType, 0);
143 if (!tempDbType)
144 return -1;
145 tempDbType->num = num;
146 tempDbType->name = name;
147 tempDbType->defaultTransformNum = defaultTransformNum;
148 if (PyModule_AddObject(module, name, (PyObject*) tempDbType) < 0) {
149 Py_DECREF(tempDbType);
150 return -1;
151 }
152 *dbType = tempDbType;
153 return 0;
154 }
155
53156
54157 //-----------------------------------------------------------------------------
55158 // cxoModule_setException()
141244 //-----------------------------------------------------------------------------
142245 static PyObject* cxoModule_clientVersion(PyObject* self, PyObject* args)
143246 {
144 if (cxoUtils_initializeDPI() < 0)
247 if (cxoUtils_initializeDPI(NULL) < 0)
145248 return NULL;
146249 return Py_BuildValue("(iiiii)", cxoClientVersionInfo.versionNum,
147250 cxoClientVersionInfo.releaseNum, cxoClientVersionInfo.updateNum,
151254
152255
153256 //-----------------------------------------------------------------------------
257 // cxoModule_initClientLib()
258 // Initialize the client library now, rather than when the first call to
259 // get the Oracle Client library version, create a standalone connection or
260 // session pool is performed.
261 //-----------------------------------------------------------------------------
262 static PyObject* cxoModule_initClientLib(PyObject* self, PyObject* args,
263 PyObject* keywordArgs)
264 {
265 static char *keywordList[] = { "lib_dir", "config_dir", "error_url",
266 "driver_name", NULL };
267 Py_ssize_t libDirSize, configDirSize, errorUrlSize, driverNameSize;
268 dpiContextCreateParams params;
269
270 memset(&params, 0, sizeof(dpiContextCreateParams));
271 libDirSize = configDirSize = errorUrlSize = driverNameSize = 0;
272 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|z#z#z#z#",
273 keywordList, &params.oracleClientLibDir, &libDirSize,
274 &params.oracleClientConfigDir, &configDirSize,
275 &params.loadErrorUrl, &errorUrlSize, &params.defaultDriverName,
276 &driverNameSize))
277 return NULL;
278 if (libDirSize == 0)
279 params.oracleClientLibDir = NULL;
280 if (configDirSize == 0)
281 params.oracleClientConfigDir = NULL;
282 if (errorUrlSize == 0)
283 params.loadErrorUrl = NULL;
284 if (driverNameSize == 0)
285 params.defaultDriverName = NULL;
286 if (cxoUtils_initializeDPI(&params) < 0)
287 return NULL;
288
289 Py_RETURN_NONE;
290 }
291
292
293 //-----------------------------------------------------------------------------
154294 // cxoModule_time()
155295 // Returns a time value suitable for binding.
156296 //-----------------------------------------------------------------------------
193333
194334
195335 //-----------------------------------------------------------------------------
196 // Declaration of methods supported by this module
336 // Declaration of methods supported by this module
197337 //-----------------------------------------------------------------------------
198338 static PyMethodDef cxoModuleMethods[] = {
199339 { "makedsn", (PyCFunction) cxoModule_makeDSN,
204344 { "TimestampFromTicks", (PyCFunction) cxoModule_timestampFromTicks,
205345 METH_VARARGS },
206346 { "clientversion", (PyCFunction) cxoModule_clientVersion, METH_NOARGS },
347 { "init_oracle_client", (PyCFunction) cxoModule_initClientLib,
348 METH_VARARGS | METH_KEYWORDS },
207349 { NULL }
208350 };
209351
210352
211 #if PY_MAJOR_VERSION >= 3
212 //-----------------------------------------------------------------------------
213 // Declaration of module definition for Python 3.x.
353 //-----------------------------------------------------------------------------
354 // Declaration of module definition
214355 //-----------------------------------------------------------------------------
215356 static struct PyModuleDef cxoModuleDef = {
216357 PyModuleDef_HEAD_INIT,
223364 NULL, // clear
224365 NULL // free
225366 };
226 #endif
227367
228368
229369 //-----------------------------------------------------------------------------
234374 {
235375 PyObject *module;
236376
237 #ifdef WITH_THREAD
238 PyEval_InitThreads();
239 #endif
240
241377 // initialize transforms
242378 if (cxoTransform_init() < 0)
243379 return NULL;
244380
245381 // prepare the types for use by the module
246 CXO_MAKE_TYPE_READY(&cxoPyTypeBfileVar);
247 CXO_MAKE_TYPE_READY(&cxoPyTypeBinaryVar);
248 CXO_MAKE_TYPE_READY(&cxoPyTypeBlobVar);
249 CXO_MAKE_TYPE_READY(&cxoPyTypeBooleanVar);
250 CXO_MAKE_TYPE_READY(&cxoPyTypeClobVar);
382 CXO_MAKE_TYPE_READY(&cxoPyTypeApiType);
251383 CXO_MAKE_TYPE_READY(&cxoPyTypeConnection);
252384 CXO_MAKE_TYPE_READY(&cxoPyTypeCursor);
253 CXO_MAKE_TYPE_READY(&cxoPyTypeCursorVar);
254 CXO_MAKE_TYPE_READY(&cxoPyTypeDateTimeVar);
385 CXO_MAKE_TYPE_READY(&cxoPyTypeDbType);
255386 CXO_MAKE_TYPE_READY(&cxoPyTypeDeqOptions);
256387 CXO_MAKE_TYPE_READY(&cxoPyTypeEnqOptions);
257388 CXO_MAKE_TYPE_READY(&cxoPyTypeError);
258 CXO_MAKE_TYPE_READY(&cxoPyTypeFixedCharVar);
259 CXO_MAKE_TYPE_READY(&cxoPyTypeFixedNcharVar);
260389 CXO_MAKE_TYPE_READY(&cxoPyTypeFuture);
261 CXO_MAKE_TYPE_READY(&cxoPyTypeIntervalVar);
262390 CXO_MAKE_TYPE_READY(&cxoPyTypeLob);
263 CXO_MAKE_TYPE_READY(&cxoPyTypeLongBinaryVar);
264 CXO_MAKE_TYPE_READY(&cxoPyTypeLongStringVar);
265391 CXO_MAKE_TYPE_READY(&cxoPyTypeMsgProps);
266392 CXO_MAKE_TYPE_READY(&cxoPyTypeMessage);
267393 CXO_MAKE_TYPE_READY(&cxoPyTypeMessageQuery);
268394 CXO_MAKE_TYPE_READY(&cxoPyTypeMessageRow);
269395 CXO_MAKE_TYPE_READY(&cxoPyTypeMessageTable);
270 CXO_MAKE_TYPE_READY(&cxoPyTypeNativeFloatVar);
271 CXO_MAKE_TYPE_READY(&cxoPyTypeNativeIntVar);
272 CXO_MAKE_TYPE_READY(&cxoPyTypeNcharVar);
273 CXO_MAKE_TYPE_READY(&cxoPyTypeNclobVar);
274 CXO_MAKE_TYPE_READY(&cxoPyTypeNumberVar);
275396 CXO_MAKE_TYPE_READY(&cxoPyTypeObjectAttr);
276397 CXO_MAKE_TYPE_READY(&cxoPyTypeObject);
277398 CXO_MAKE_TYPE_READY(&cxoPyTypeObjectType);
278 CXO_MAKE_TYPE_READY(&cxoPyTypeObjectVar);
279 CXO_MAKE_TYPE_READY(&cxoPyTypeRowidVar);
399 CXO_MAKE_TYPE_READY(&cxoPyTypeQueue);
280400 CXO_MAKE_TYPE_READY(&cxoPyTypeSessionPool);
281401 CXO_MAKE_TYPE_READY(&cxoPyTypeSodaCollection);
282402 CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDatabase);
283403 CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDoc);
284404 CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDocCursor);
285405 CXO_MAKE_TYPE_READY(&cxoPyTypeSodaOperation);
286 CXO_MAKE_TYPE_READY(&cxoPyTypeStringVar);
287406 CXO_MAKE_TYPE_READY(&cxoPyTypeSubscr);
288 CXO_MAKE_TYPE_READY(&cxoPyTypeTimestampVar);
407 CXO_MAKE_TYPE_READY(&cxoPyTypeVar);
289408
290409 // initialize module and retrieve the dictionary
291 #if PY_MAJOR_VERSION >= 3
292410 module = PyModule_Create(&cxoModuleDef);
293 #else
294 module = Py_InitModule("cx_Oracle", cxoModuleMethods);
295 #endif
296411 if (!module)
297412 return NULL;
298413
299414 // create exception object and add it to the dictionary
300415 if (cxoModule_setException(module, &cxoWarningException,
301 "Warning", CXO_BASE_EXCEPTION) < 0)
416 "Warning", NULL) < 0)
302417 return NULL;
303418 if (cxoModule_setException(module, &cxoErrorException,
304 "Error", CXO_BASE_EXCEPTION) < 0)
419 "Error", NULL) < 0)
305420 return NULL;
306421 if (cxoModule_setException(module, &cxoInterfaceErrorException,
307422 "InterfaceError", cxoErrorException) < 0)
329444 return NULL;
330445
331446 // set up the types that are available
332 #if PY_MAJOR_VERSION >= 3
447 CXO_ADD_TYPE_OBJECT("ApiType", &cxoPyTypeApiType)
333448 CXO_ADD_TYPE_OBJECT("Binary", &PyBytes_Type)
334 #else
335 CXO_ADD_TYPE_OBJECT("Binary", &PyBuffer_Type)
336 #endif
337449 CXO_ADD_TYPE_OBJECT("Connection", &cxoPyTypeConnection)
338450 CXO_ADD_TYPE_OBJECT("Cursor", &cxoPyTypeCursor)
339 CXO_ADD_TYPE_OBJECT("Timestamp", cxoPyTypeDateTime)
340451 CXO_ADD_TYPE_OBJECT("Date", cxoPyTypeDate)
341 CXO_ADD_TYPE_OBJECT("SessionPool", &cxoPyTypeSessionPool)
452 CXO_ADD_TYPE_OBJECT("DbType", &cxoPyTypeDbType)
453 CXO_ADD_TYPE_OBJECT("DeqOptions", &cxoPyTypeDeqOptions)
454 CXO_ADD_TYPE_OBJECT("EnqOptions", &cxoPyTypeEnqOptions)
342455 CXO_ADD_TYPE_OBJECT("_Error", &cxoPyTypeError)
456 CXO_ADD_TYPE_OBJECT("LOB", &cxoPyTypeLob)
457 CXO_ADD_TYPE_OBJECT("MessageProperties", &cxoPyTypeMsgProps)
343458 CXO_ADD_TYPE_OBJECT("Object", &cxoPyTypeObject)
344459 CXO_ADD_TYPE_OBJECT("ObjectType", &cxoPyTypeObjectType)
345 CXO_ADD_TYPE_OBJECT("EnqOptions", &cxoPyTypeEnqOptions)
346 CXO_ADD_TYPE_OBJECT("DeqOptions", &cxoPyTypeDeqOptions)
347 CXO_ADD_TYPE_OBJECT("MessageProperties", &cxoPyTypeMsgProps)
460 CXO_ADD_TYPE_OBJECT("SessionPool", &cxoPyTypeSessionPool)
348461 CXO_ADD_TYPE_OBJECT("SodaCollection", &cxoPyTypeSodaCollection)
349462 CXO_ADD_TYPE_OBJECT("SodaDatabase", &cxoPyTypeSodaDatabase)
350463 CXO_ADD_TYPE_OBJECT("SodaDoc", &cxoPyTypeSodaDoc)
351464 CXO_ADD_TYPE_OBJECT("SodaDocCursor", &cxoPyTypeSodaDocCursor)
352465 CXO_ADD_TYPE_OBJECT("SodaOperation", &cxoPyTypeSodaOperation)
466 CXO_ADD_TYPE_OBJECT("Timestamp", cxoPyTypeDateTime)
467 CXO_ADD_TYPE_OBJECT("Var", &cxoPyTypeVar)
353468
354469 // the name "connect" is required by the DB API
355470 CXO_ADD_TYPE_OBJECT("connect", &cxoPyTypeConnection)
356471
357 // create the basic data types for setting input sizes
358 CXO_ADD_TYPE_OBJECT("BINARY", &cxoPyTypeBinaryVar)
359 CXO_ADD_TYPE_OBJECT("BFILE", &cxoPyTypeBfileVar)
360 CXO_ADD_TYPE_OBJECT("BLOB", &cxoPyTypeBlobVar)
361 CXO_ADD_TYPE_OBJECT("CLOB", &cxoPyTypeClobVar)
362 CXO_ADD_TYPE_OBJECT("CURSOR", &cxoPyTypeCursorVar)
363 CXO_ADD_TYPE_OBJECT("OBJECT", &cxoPyTypeObjectVar)
364 CXO_ADD_TYPE_OBJECT("DATETIME", &cxoPyTypeDateTimeVar)
365 CXO_ADD_TYPE_OBJECT("FIXED_CHAR", &cxoPyTypeFixedCharVar)
366 CXO_ADD_TYPE_OBJECT("FIXED_NCHAR", &cxoPyTypeFixedNcharVar)
367 CXO_ADD_TYPE_OBJECT("NCHAR", &cxoPyTypeNcharVar)
368 CXO_ADD_TYPE_OBJECT("INTERVAL", &cxoPyTypeIntervalVar)
369 CXO_ADD_TYPE_OBJECT("LOB", &cxoPyTypeLob)
370 CXO_ADD_TYPE_OBJECT("LONG_BINARY", &cxoPyTypeLongBinaryVar)
371 CXO_ADD_TYPE_OBJECT("LONG_STRING", &cxoPyTypeLongStringVar)
372 CXO_ADD_TYPE_OBJECT("NCLOB", &cxoPyTypeNclobVar)
373 CXO_ADD_TYPE_OBJECT("NUMBER", &cxoPyTypeNumberVar)
374 CXO_ADD_TYPE_OBJECT("ROWID", &cxoPyTypeRowidVar)
375 CXO_ADD_TYPE_OBJECT("STRING", &cxoPyTypeStringVar)
376 CXO_ADD_TYPE_OBJECT("TIMESTAMP", &cxoPyTypeTimestampVar)
377 CXO_ADD_TYPE_OBJECT("NATIVE_INT", &cxoPyTypeNativeIntVar)
378 CXO_ADD_TYPE_OBJECT("NATIVE_FLOAT", &cxoPyTypeNativeFloatVar)
379 CXO_ADD_TYPE_OBJECT("BOOLEAN", &cxoPyTypeBooleanVar)
472 // create the database types (preferred names)
473 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BFILE, "DB_TYPE_BFILE",
474 CXO_TRANSFORM_BFILE, &cxoDbTypeBfile)
475 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_DOUBLE, "DB_TYPE_BINARY_DOUBLE",
476 CXO_TRANSFORM_NATIVE_DOUBLE, &cxoDbTypeBinaryDouble)
477 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_FLOAT, "DB_TYPE_BINARY_FLOAT",
478 CXO_TRANSFORM_NATIVE_FLOAT, &cxoDbTypeBinaryFloat)
479 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_INT, "DB_TYPE_BINARY_INTEGER",
480 CXO_TRANSFORM_NATIVE_INT, &cxoDbTypeBinaryInteger)
481 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BLOB, "DB_TYPE_BLOB",
482 CXO_TRANSFORM_BLOB, &cxoDbTypeBlob)
483 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BOOLEAN, "DB_TYPE_BOOLEAN",
484 CXO_TRANSFORM_BOOLEAN, &cxoDbTypeBoolean)
485 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_CHAR, "DB_TYPE_CHAR",
486 CXO_TRANSFORM_FIXED_CHAR, &cxoDbTypeChar)
487 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_CLOB, "DB_TYPE_CLOB",
488 CXO_TRANSFORM_CLOB, &cxoDbTypeClob)
489 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_STMT, "DB_TYPE_CURSOR",
490 CXO_TRANSFORM_CURSOR, &cxoDbTypeCursor)
491 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_DATE, "DB_TYPE_DATE",
492 CXO_TRANSFORM_DATETIME, &cxoDbTypeDate)
493 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_INTERVAL_DS, "DB_TYPE_INTERVAL_DS",
494 CXO_TRANSFORM_TIMEDELTA, &cxoDbTypeIntervalDS)
495 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_INTERVAL_YM, "DB_TYPE_INTERVAL_YM",
496 CXO_TRANSFORM_UNSUPPORTED, &cxoDbTypeIntervalYM)
497 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_LONG_VARCHAR, "DB_TYPE_LONG",
498 CXO_TRANSFORM_LONG_STRING, &cxoDbTypeLong)
499 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_LONG_RAW, "DB_TYPE_LONG_RAW",
500 CXO_TRANSFORM_LONG_BINARY, &cxoDbTypeLongRaw)
501 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NCHAR, "DB_TYPE_NCHAR",
502 CXO_TRANSFORM_FIXED_NCHAR, &cxoDbTypeNchar)
503 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NCLOB, "DB_TYPE_NCLOB",
504 CXO_TRANSFORM_NCLOB, &cxoDbTypeNclob)
505 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NUMBER, "DB_TYPE_NUMBER",
506 CXO_TRANSFORM_FLOAT, &cxoDbTypeNumber)
507 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NVARCHAR, "DB_TYPE_NVARCHAR",
508 CXO_TRANSFORM_NSTRING, &cxoDbTypeNvarchar)
509 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_OBJECT, "DB_TYPE_OBJECT",
510 CXO_TRANSFORM_OBJECT, &cxoDbTypeObject)
511 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_RAW, "DB_TYPE_RAW",
512 CXO_TRANSFORM_BINARY, &cxoDbTypeRaw)
513 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_ROWID, "DB_TYPE_ROWID",
514 CXO_TRANSFORM_ROWID, &cxoDbTypeRowid)
515 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_TIMESTAMP, "DB_TYPE_TIMESTAMP",
516 CXO_TRANSFORM_TIMESTAMP, &cxoDbTypeTimestamp)
517 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_TIMESTAMP_LTZ, "DB_TYPE_TIMESTAMP_LTZ",
518 CXO_TRANSFORM_TIMESTAMP_LTZ, &cxoDbTypeTimestampLTZ)
519 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_TIMESTAMP_TZ, "DB_TYPE_TIMESTAMP_TZ",
520 CXO_TRANSFORM_TIMESTAMP_TZ, &cxoDbTypeTimestampTZ)
521 CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_VARCHAR, "DB_TYPE_VARCHAR",
522 CXO_TRANSFORM_STRING, &cxoDbTypeVarchar)
523
524 // create the synonyms for database types (deprecated names)
525 CXO_ADD_TYPE_OBJECT("BFILE", cxoDbTypeBfile)
526 CXO_ADD_TYPE_OBJECT("BLOB", cxoDbTypeBlob)
527 CXO_ADD_TYPE_OBJECT("CLOB", cxoDbTypeClob)
528 CXO_ADD_TYPE_OBJECT("CURSOR", cxoDbTypeCursor)
529 CXO_ADD_TYPE_OBJECT("OBJECT", cxoDbTypeObject)
530 CXO_ADD_TYPE_OBJECT("FIXED_CHAR", cxoDbTypeChar)
531 CXO_ADD_TYPE_OBJECT("FIXED_NCHAR", cxoDbTypeNchar)
532 CXO_ADD_TYPE_OBJECT("NCHAR", cxoDbTypeNvarchar)
533 CXO_ADD_TYPE_OBJECT("INTERVAL", cxoDbTypeIntervalDS)
534 CXO_ADD_TYPE_OBJECT("LONG_BINARY", cxoDbTypeLongRaw)
535 CXO_ADD_TYPE_OBJECT("LONG_STRING", cxoDbTypeLong)
536 CXO_ADD_TYPE_OBJECT("NCLOB", cxoDbTypeNclob)
537 CXO_ADD_TYPE_OBJECT("TIMESTAMP", cxoDbTypeTimestamp)
538 CXO_ADD_TYPE_OBJECT("NATIVE_INT", cxoDbTypeBinaryInteger)
539 CXO_ADD_TYPE_OBJECT("NATIVE_FLOAT", cxoDbTypeBinaryDouble)
540 CXO_ADD_TYPE_OBJECT("BOOLEAN", cxoDbTypeBoolean)
541
542 // create the Python Database API types
543 CXO_ADD_API_TYPE("BINARY", CXO_TRANSFORM_BINARY, &cxoApiTypeBinary)
544 CXO_ADD_API_TYPE("DATETIME", CXO_TRANSFORM_DATETIME, &cxoApiTypeDatetime)
545 CXO_ADD_API_TYPE("NUMBER", CXO_TRANSFORM_FLOAT, &cxoApiTypeNumber)
546 CXO_ADD_API_TYPE("ROWID", CXO_TRANSFORM_ROWID, &cxoApiTypeRowid)
547 CXO_ADD_API_TYPE("STRING", CXO_TRANSFORM_STRING, &cxoApiTypeString)
548
549 // associate the Python Database API types with the database types
550 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeBinary, cxoDbTypeLongRaw)
551 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeBinary, cxoDbTypeRaw)
552 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeDate)
553 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeTimestamp)
554 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeTimestampLTZ)
555 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeTimestampTZ)
556 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeBinaryDouble)
557 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeBinaryFloat)
558 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeBinaryInteger)
559 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeNumber)
560 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeRowid, cxoDbTypeRowid)
561 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeChar)
562 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeLong)
563 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeNchar)
564 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeNvarchar)
565 CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeVarchar)
380566
381567 // create constants required by Python DB API 2.0
382568 if (PyModule_AddStringConstant(module, "apilevel", "2.0") < 0)
405591 return NULL;
406592
407593 // add constants for authorization modes
594 CXO_ADD_INT_CONSTANT("DEFAULT_AUTH", DPI_MODE_AUTH_DEFAULT)
408595 CXO_ADD_INT_CONSTANT("SYSASM", DPI_MODE_AUTH_SYSASM)
409596 CXO_ADD_INT_CONSTANT("SYSBKP", DPI_MODE_AUTH_SYSBKP)
410597 CXO_ADD_INT_CONSTANT("SYSDBA", DPI_MODE_AUTH_SYSDBA)
528715 //-----------------------------------------------------------------------------
529716 // Start routine for the module.
530717 //-----------------------------------------------------------------------------
531 #if PY_MAJOR_VERSION >= 3
532718 PyMODINIT_FUNC PyInit_cx_Oracle(void)
533719 {
534720 return cxoModule_initialize();
535721 }
536 #else
537 void initcx_Oracle(void)
538 {
539 cxoModule_initialize();
540 }
541 #endif
542
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Licensed under BSD license (see LICENSE.txt).
44 //-----------------------------------------------------------------------------
77 // cxoModule.h
88 // Include file for all cx_Oracle source files.
99 //-----------------------------------------------------------------------------
10
11 #define PY_SSIZE_T_CLEAN 1
1012
1113 #include <Python.h>
1214 #include <structmember.h>
1315 #include <time.h>
1416 #include <dpi.h>
15
16 // define integer macros/methods for Python 3.x
17 #ifndef PyInt_Check
18 #define PyInt_Check PyLong_Check
19 #define PyInt_FromLong PyLong_FromLong
20 #define PyInt_AsLong PyLong_AsLong
21 #endif
22
23 // use the bytes methods in cx_Oracle and define them as the equivalent string
24 // type methods as is done in Python 2.6
25 #ifndef PyBytes_Check
26 #define PyBytes_Type PyString_Type
27 #define PyBytes_AS_STRING PyString_AS_STRING
28 #define PyBytes_GET_SIZE PyString_GET_SIZE
29 #define PyBytes_Check PyString_Check
30 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
31 #endif
32
33 // define string/binary types and methods
34 #if PY_MAJOR_VERSION >= 3
35 #define CXO_BASE_EXCEPTION NULL
36 #define cxoPyTypeBinary PyBytes_Type
37 #define cxoPyTypeString PyUnicode_Type
38 #define cxoPyString_fromAscii(str) \
39 PyUnicode_DecodeASCII(str, strlen(str), NULL)
40 #define cxoPyString_fromEncodedString(buffer, numBytes, encoding, errors) \
41 PyUnicode_Decode(buffer, numBytes, encoding, errors)
42 #else
43 #define CXO_BASE_EXCEPTION PyExc_StandardError
44 #define cxoPyTypeBinary PyBuffer_Type
45 #define cxoPyTypeString PyString_Type
46 #define cxoPyString_fromAscii(str) \
47 PyBytes_FromString(str)
48 #define cxoPyString_fromEncodedString(buffer, numBytes, encoding, errors) \
49 PyBytes_FromStringAndSize(buffer, numBytes)
50 #endif
5117
5218 // define macros to get the build version as a string and the driver name
5319 #define xstr(s) str(s)
6228 //-----------------------------------------------------------------------------
6329 // Forward Declarations
6430 //-----------------------------------------------------------------------------
31 typedef struct cxoApiType cxoApiType;
6532 typedef struct cxoBuffer cxoBuffer;
66 typedef struct cxoError cxoError;
6733 typedef struct cxoConnection cxoConnection;
6834 typedef struct cxoCursor cxoCursor;
35 typedef struct cxoDbType cxoDbType;
6936 typedef struct cxoDeqOptions cxoDeqOptions;
7037 typedef struct cxoEnqOptions cxoEnqOptions;
38 typedef struct cxoError cxoError;
7139 typedef struct cxoFuture cxoFuture;
7240 typedef struct cxoLob cxoLob;
7341 typedef struct cxoMessage cxoMessage;
7846 typedef struct cxoObject cxoObject;
7947 typedef struct cxoObjectAttr cxoObjectAttr;
8048 typedef struct cxoObjectType cxoObjectType;
49 typedef struct cxoQueue cxoQueue;
8150 typedef struct cxoSessionPool cxoSessionPool;
8251 typedef struct cxoSodaCollection cxoSodaCollection;
8352 typedef struct cxoSodaDatabase cxoSodaDatabase;
8655 typedef struct cxoSodaOperation cxoSodaOperation;
8756 typedef struct cxoSubscr cxoSubscr;
8857 typedef struct cxoVar cxoVar;
89 typedef struct cxoVarType cxoVarType;
9058
9159
9260 //-----------------------------------------------------------------------------
10674 extern PyObject *cxoNotSupportedErrorException;
10775
10876 // type objects
109 extern PyTypeObject cxoPyTypeBfileVar;
110 extern PyTypeObject cxoPyTypeBinaryVar;
111 extern PyTypeObject cxoPyTypeBlobVar;
112 extern PyTypeObject cxoPyTypeBooleanVar;
113 extern PyTypeObject cxoPyTypeClobVar;
77 extern PyTypeObject cxoPyTypeApiType;
11478 extern PyTypeObject cxoPyTypeConnection;
11579 extern PyTypeObject cxoPyTypeCursor;
116 extern PyTypeObject cxoPyTypeCursorVar;
117 extern PyTypeObject cxoPyTypeDateTimeVar;
80 extern PyTypeObject cxoPyTypeDbType;
11881 extern PyTypeObject cxoPyTypeDeqOptions;
11982 extern PyTypeObject cxoPyTypeEnqOptions;
12083 extern PyTypeObject cxoPyTypeError;
121 extern PyTypeObject cxoPyTypeFixedCharVar;
122 extern PyTypeObject cxoPyTypeFixedNcharVar;
12384 extern PyTypeObject cxoPyTypeFuture;
124 extern PyTypeObject cxoPyTypeIntervalVar;
12585 extern PyTypeObject cxoPyTypeLob;
126 extern PyTypeObject cxoPyTypeLongBinaryVar;
127 extern PyTypeObject cxoPyTypeLongStringVar;
12886 extern PyTypeObject cxoPyTypeMsgProps;
12987 extern PyTypeObject cxoPyTypeMessage;
13088 extern PyTypeObject cxoPyTypeMessageQuery;
13189 extern PyTypeObject cxoPyTypeMessageRow;
13290 extern PyTypeObject cxoPyTypeMessageTable;
133 extern PyTypeObject cxoPyTypeNativeFloatVar;
134 extern PyTypeObject cxoPyTypeNativeIntVar;
135 extern PyTypeObject cxoPyTypeNcharVar;
136 extern PyTypeObject cxoPyTypeNclobVar;
137 extern PyTypeObject cxoPyTypeNumberVar;
13891 extern PyTypeObject cxoPyTypeObject;
13992 extern PyTypeObject cxoPyTypeObjectAttr;
14093 extern PyTypeObject cxoPyTypeObjectType;
141 extern PyTypeObject cxoPyTypeObjectVar;
142 extern PyTypeObject cxoPyTypeRowidVar;
94 extern PyTypeObject cxoPyTypeQueue;
14395 extern PyTypeObject cxoPyTypeSessionPool;
14496 extern PyTypeObject cxoPyTypeSodaCollection;
14597 extern PyTypeObject cxoPyTypeSodaDatabase;
14698 extern PyTypeObject cxoPyTypeSodaDoc;
14799 extern PyTypeObject cxoPyTypeSodaDocCursor;
148100 extern PyTypeObject cxoPyTypeSodaOperation;
149 extern PyTypeObject cxoPyTypeStringVar;
150101 extern PyTypeObject cxoPyTypeSubscr;
151 extern PyTypeObject cxoPyTypeTimestampVar;
102 extern PyTypeObject cxoPyTypeVar;
152103
153104 // datetime types
154105 extern PyTypeObject *cxoPyTypeDate;
155106 extern PyTypeObject *cxoPyTypeDateTime;
107
108 // database types
109 extern cxoDbType *cxoDbTypeBfile;
110 extern cxoDbType *cxoDbTypeBinaryDouble;
111 extern cxoDbType *cxoDbTypeBinaryFloat;
112 extern cxoDbType *cxoDbTypeBinaryInteger;
113 extern cxoDbType *cxoDbTypeBlob;
114 extern cxoDbType *cxoDbTypeBoolean;
115 extern cxoDbType *cxoDbTypeChar;
116 extern cxoDbType *cxoDbTypeClob;
117 extern cxoDbType *cxoDbTypeCursor;
118 extern cxoDbType *cxoDbTypeDate;
119 extern cxoDbType *cxoDbTypeIntervalDS;
120 extern cxoDbType *cxoDbTypeIntervalYM;
121 extern cxoDbType *cxoDbTypeLong;
122 extern cxoDbType *cxoDbTypeLongRaw;
123 extern cxoDbType *cxoDbTypeNchar;
124 extern cxoDbType *cxoDbTypeNclob;
125 extern cxoDbType *cxoDbTypeNumber;
126 extern cxoDbType *cxoDbTypeNvarchar;
127 extern cxoDbType *cxoDbTypeObject;
128 extern cxoDbType *cxoDbTypeRaw;
129 extern cxoDbType *cxoDbTypeRowid;
130 extern cxoDbType *cxoDbTypeTimestamp;
131 extern cxoDbType *cxoDbTypeTimestampLTZ;
132 extern cxoDbType *cxoDbTypeTimestampTZ;
133 extern cxoDbType *cxoDbTypeVarchar;
134
135 // database API types
136 extern cxoApiType *cxoApiTypeBinary;
137 extern cxoApiType *cxoApiTypeDatetime;
138 extern cxoApiType *cxoApiTypeNumber;
139 extern cxoApiType *cxoApiTypeRowid;
140 extern cxoApiType *cxoApiTypeString;
156141
157142 // JSON dump and load functions for use with SODA
158143 extern PyObject *cxoJsonDumpFunction;
197182 CXO_TRANSFORM_TIMEDELTA,
198183 CXO_TRANSFORM_TIMESTAMP,
199184 CXO_TRANSFORM_TIMESTAMP_LTZ,
185 CXO_TRANSFORM_TIMESTAMP_TZ,
200186 CXO_TRANSFORM_UNSUPPORTED
201187 } cxoTransformNum;
202188
204190 //-----------------------------------------------------------------------------
205191 // Structures
206192 //-----------------------------------------------------------------------------
193 struct cxoApiType {
194 PyObject_HEAD
195 const char *name;
196 PyObject *dbTypes;
197 cxoTransformNum defaultTransformNum;
198 };
199
207200 struct cxoBuffer {
208201 const char *ptr;
209202 uint32_t numCharacters;
249242 uint32_t arraySize;
250243 uint32_t bindArraySize;
251244 uint32_t fetchArraySize;
245 uint32_t prefetchRows;
252246 int setInputSizes;
253247 uint64_t rowCount;
254248 uint32_t fetchBufferRowIndex;
255249 uint32_t numRowsInFetchBuffer;
256250 int moreRowsToFetch;
257 int isScrollable;
251 char isScrollable;
258252 int fixupRefCursor;
259253 int isOpen;
260254 };
261255
256 struct cxoDbType {
257 PyObject_HEAD
258 uint32_t num;
259 const char *name;
260 cxoTransformNum defaultTransformNum;
261 };
262
262263 struct cxoDeqOptions {
263264 PyObject_HEAD
264265 dpiDeqOptions *handle;
278279 struct cxoLob {
279280 PyObject_HEAD
280281 cxoConnection *connection;
281 dpiOracleTypeNum oracleTypeNum;
282 cxoDbType *dbType;
282283 dpiLob *handle;
283284 };
284285
318319 struct cxoMsgProps {
319320 PyObject_HEAD
320321 dpiMsgProps *handle;
322 PyObject *payload;
321323 const char *encoding;
322324 };
323325
333335 dpiObjectAttr *handle;
334336 dpiOracleTypeNum oracleTypeNum;
335337 cxoTransformNum transformNum;
336 cxoObjectType *type;
338 cxoObjectType *objectType;
339 cxoDbType *dbType;
337340 };
338341
339342 struct cxoObjectType {
346349 cxoConnection *connection;
347350 dpiOracleTypeNum elementOracleTypeNum;
348351 cxoTransformNum elementTransformNum;
349 PyObject *elementType;
352 cxoObjectType *elementObjectType;
353 cxoDbType *elementDbType;
350354 char isCollection;
355 };
356
357 struct cxoQueue {
358 PyObject_HEAD
359 cxoConnection *conn;
360 dpiQueue *handle;
361 PyObject *name;
362 PyObject *deqOptions;
363 PyObject *enqOptions;
364 cxoObjectType *payloadType;
351365 };
352366
353367 struct cxoSessionPool {
438452 int isArray;
439453 int isValueSet;
440454 int getReturnedData;
441 cxoVarType *type;
442 };
443
444 struct cxoVarType {
445455 cxoTransformNum transformNum;
446 PyTypeObject *pythonType;
447 uint32_t size;
456 dpiNativeTypeNum nativeTypeNum;
457 cxoDbType *dbType;
448458 };
449459
450460
461471 int cxoCursor_setBindVariables(cxoCursor *cursor, PyObject *parameters,
462472 unsigned numElements, unsigned arrayPos, int deferTypeAssignment);
463473
464 cxoDeqOptions *cxoDeqOptions_new(cxoConnection *connection);
465
466 cxoEnqOptions *cxoEnqOptions_new(cxoConnection *connection);
474 cxoDbType *cxoDbType_fromDataTypeInfo(dpiDataTypeInfo *info);
475 cxoDbType *cxoDbType_fromTransformNum(cxoTransformNum transformNum);
476
477 cxoDeqOptions *cxoDeqOptions_new(cxoConnection *connection,
478 dpiDeqOptions *handle);
479
480 cxoEnqOptions *cxoEnqOptions_new(cxoConnection *connection,
481 dpiEnqOptions *handle);
467482
468483 cxoError *cxoError_newFromInfo(dpiErrorInfo *errorInfo);
469484 int cxoError_raiseAndReturnInt(void);
472487 PyObject *cxoError_raiseFromString(PyObject *exceptionType,
473488 const char *message);
474489
475 PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
490 PyObject *cxoLob_new(cxoConnection *connection, cxoDbType *dbType,
476491 dpiLob *handle);
477492
478 cxoMsgProps *cxoMsgProps_new(cxoConnection*);
493 cxoMsgProps *cxoMsgProps_new(cxoConnection*, dpiMsgProps *handle);
479494
480495 int cxoObject_internalExtend(cxoObject *obj, PyObject *sequence);
481496 PyObject *cxoObject_new(cxoObjectType *objectType, dpiObject *handle);
488503 cxoObjectType *cxoObjectType_newByName(cxoConnection *connection,
489504 PyObject *name);
490505
506 cxoQueue *cxoQueue_new(cxoConnection *conn, dpiQueue *handle);
507
491508 cxoSodaCollection *cxoSodaCollection_new(cxoSodaDatabase *db,
492509 dpiSodaColl *handle);
493510
503520 void cxoSubscr_callback(cxoSubscr *subscr, dpiSubscrMessage *message);
504521
505522 PyObject *cxoTransform_dateFromTicks(PyObject *args);
506 int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue,
523 int cxoTransform_fromPython(cxoTransformNum transformNum,
524 dpiNativeTypeNum *nativeTypeNum, PyObject *pyValue,
507525 dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding,
508526 const char *nencoding, cxoVar *var, uint32_t arrayPos);
527 uint32_t cxoTransform_getDefaultSize(cxoTransformNum transformNum);
509528 cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info);
510 cxoTransformNum cxoTransform_getNumFromType(PyTypeObject *type);
511 cxoTransformNum cxoTransform_getNumFromValue(PyObject *value, int plsql);
529 cxoTransformNum cxoTransform_getNumFromPythonValue(PyObject *value,
530 int plsql);
531 int cxoTransform_getNumFromType(PyObject *type, cxoTransformNum *transformNum,
532 cxoObjectType **objType);
533 int cxoTransform_getNumFromValue(PyObject *value, int *isArray,
534 Py_ssize_t *size, Py_ssize_t *numElements, int plsql,
535 cxoTransformNum *transformNum);
512536 void cxoTransform_getTypeInfo(cxoTransformNum transformNum,
513537 dpiOracleTypeNum *oracleTypeNum, dpiNativeTypeNum *nativeTypeNum);
514538 int cxoTransform_init(void);
522546 int cxoUtils_getBooleanValue(PyObject *obj, int defaultValue, int *value);
523547 int cxoUtils_getModuleAndName(PyTypeObject *type, PyObject **module,
524548 PyObject **name);
525 int cxoUtils_initializeDPI(void);
549 int cxoUtils_initializeDPI(dpiContextCreateParams *params);
526550 int cxoUtils_processJsonArg(PyObject *arg, cxoBuffer *buffer);
527551 int cxoUtils_processSodaDocArg(cxoSodaDatabase *db, PyObject *arg,
528 cxoSodaDoc **doc);
529
530 cxoVarType *cxoVarType_fromDataTypeInfo(dpiDataTypeInfo *info);
531 cxoVarType *cxoVarType_fromPythonType(PyObject *type, cxoObjectType **objType);
532 cxoVarType *cxoVarType_fromPythonValue(PyObject *value, int *isArray,
533 Py_ssize_t *size, Py_ssize_t *numElements, int plsql);
552 dpiSodaDoc **handle);
534553
535554 int cxoVar_bind(cxoVar *var, cxoCursor *cursor, PyObject *name, uint32_t pos);
536555 int cxoVar_check(PyObject *object);
537556 PyObject *cxoVar_getSingleValue(cxoVar *var, dpiData *data, uint32_t arrayPos);
538557 PyObject *cxoVar_getValue(cxoVar *var, uint32_t arrayPos);
539 cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
540 Py_ssize_t size, int isArray, cxoObjectType *objType);
558 cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements,
559 cxoTransformNum transformNum, Py_ssize_t size, int isArray,
560 cxoObjectType *objType);
541561 cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
542562 uint32_t numElements);
543563 cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
544564 Py_ssize_t numElements);
545565 int cxoVar_setValue(cxoVar *var, uint32_t arrayPos, PyObject *value);
546
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
1414 #include "cxoModule.h"
1515
1616 //-----------------------------------------------------------------------------
17 // Declaration of methods used for message properties
17 // forward declarations
1818 //-----------------------------------------------------------------------------
1919 static void cxoMsgProps_free(cxoMsgProps*);
2020 static PyObject *cxoMsgProps_getNumAttempts(cxoMsgProps*, void*);
3636
3737
3838 //-----------------------------------------------------------------------------
39 // declaration of calculated members for Python type "MessageProperties"
40 //-----------------------------------------------------------------------------
41 static PyGetSetDef cxoMsgPropsCalcMembers[] = {
39 // declaration of members
40 //-----------------------------------------------------------------------------
41 static PyMemberDef cxoMembers[] = {
42 { "payload", T_OBJECT, offsetof(cxoMsgProps, payload), 0 },
43 { NULL }
44 };
45
46
47 //-----------------------------------------------------------------------------
48 // declaration of calculated members
49 //-----------------------------------------------------------------------------
50 static PyGetSetDef cxoCalcMembers[] = {
4251 { "attempts", (getter) cxoMsgProps_getNumAttempts, 0, 0, 0 },
4352 { "correlation", (getter) cxoMsgProps_getCorrelation,
4453 (setter) cxoMsgProps_setCorrelation, 0, 0 },
6473 //-----------------------------------------------------------------------------
6574 PyTypeObject cxoPyTypeMsgProps = {
6675 PyVarObject_HEAD_INIT(NULL, 0)
67 "cx_Oracle.MessageProperties", // tp_name
68 sizeof(cxoMsgProps), // tp_basicsize
69 0, // tp_itemsize
70 (destructor) cxoMsgProps_free, // tp_dealloc
71 0, // tp_print
72 0, // tp_getattr
73 0, // tp_setattr
74 0, // tp_compare
75 0, // tp_repr
76 0, // tp_as_number
77 0, // tp_as_sequence
78 0, // tp_as_mapping
79 0, // tp_hash
80 0, // tp_call
81 0, // tp_str
82 0, // tp_getattro
83 0, // tp_setattro
84 0, // tp_as_buffer
85 Py_TPFLAGS_DEFAULT, // tp_flags
86 0, // tp_doc
87 0, // tp_traverse
88 0, // tp_clear
89 0, // tp_richcompare
90 0, // tp_weaklistoffset
91 0, // tp_iter
92 0, // tp_iternext
93 0, // tp_methods
94 0, // tp_members
95 cxoMsgPropsCalcMembers, // tp_getset
96 0, // tp_base
97 0, // tp_dict
98 0, // tp_descr_get
99 0, // tp_descr_set
100 0, // tp_dictoffset
101 0, // tp_init
102 0, // tp_alloc
103 0, // tp_new
104 0, // tp_free
105 0, // tp_is_gc
106 0 // tp_bases
76 .tp_name = "cx_Oracle.MessageProperties",
77 .tp_basicsize = sizeof(cxoMsgProps),
78 .tp_dealloc = (destructor) cxoMsgProps_free,
79 .tp_flags = Py_TPFLAGS_DEFAULT,
80 .tp_members = cxoMembers,
81 .tp_getset = cxoCalcMembers
10782 };
10883
10984
11186 // cxoMsgProps_new()
11287 // Create a new message properties object.
11388 //-----------------------------------------------------------------------------
114 cxoMsgProps *cxoMsgProps_new(cxoConnection *connection)
89 cxoMsgProps *cxoMsgProps_new(cxoConnection *connection, dpiMsgProps *handle)
11590 {
11691 cxoMsgProps *props;
11792
11893 props = (cxoMsgProps*) cxoPyTypeMsgProps.tp_alloc(&cxoPyTypeMsgProps, 0);
119 if (!props)
94 if (!props) {
95 if (handle)
96 dpiMsgProps_release(handle);
12097 return NULL;
121 if (dpiConn_newMsgProps(connection->handle, &props->handle) < 0) {
98 }
99 if (!handle && dpiConn_newMsgProps(connection->handle, &handle) < 0) {
122100 Py_DECREF(props);
123101 cxoError_raiseAndReturnNull();
124102 return NULL;
125103 }
104 props->handle = handle;
126105 props->encoding = connection->encodingInfo.encoding;
127106
128107 return props;
139118 dpiMsgProps_release(props->handle);
140119 props->handle = NULL;
141120 }
121 Py_CLEAR(props->payload);
142122 Py_TYPE(props)->tp_free((PyObject*) props);
143123 }
144124
154134
155135 if ((*func)(props->handle, &value) < 0)
156136 return cxoError_raiseAndReturnNull();
157 return PyInt_FromLong(value);
137 return PyLong_FromLong(value);
158138 }
159139
160140
167147 {
168148 int32_t value;
169149
170 value = PyInt_AsLong(valueObj);
150 value = PyLong_AsLong(valueObj);
171151 if (PyErr_Occurred())
172152 return -1;
173153 if ((*func)(props->handle, value) < 0)
199179 return cxoError_raiseAndReturnNull();
200180 if (!value)
201181 Py_RETURN_NONE;
202 return cxoPyString_fromEncodedString(value, valueLength, props->encoding,
203 NULL);
182 return PyUnicode_Decode(value, valueLength, props->encoding, NULL);
204183 }
205184
206185
224203
225204 if (dpiMsgProps_getDeliveryMode(props->handle, &value) < 0)
226205 return cxoError_raiseAndReturnNull();
227 return PyInt_FromLong(value);
206 return PyLong_FromLong(value);
228207 }
229208
230209
256235 return cxoError_raiseAndReturnNull();
257236 if (!value)
258237 Py_RETURN_NONE;
259 return cxoPyString_fromEncodedString(value, valueLength, props->encoding,
260 NULL);
238 return PyUnicode_Decode(value, valueLength, props->encoding, NULL);
261239 }
262240
263241
308286
309287 if (dpiMsgProps_getState(props->handle, &value) < 0)
310288 return cxoError_raiseAndReturnNull();
311 return PyInt_FromLong(value);
289 return PyLong_FromLong(value);
312290 }
313291
314292
403381 {
404382 return cxoMsgProps_setAttrInt32(props, valueObj, dpiMsgProps_setPriority);
405383 }
406
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
7474 //-----------------------------------------------------------------------------
7575 PyTypeObject cxoPyTypeObject = {
7676 PyVarObject_HEAD_INIT(NULL, 0)
77 "cx_Oracle.Object", // tp_name
78 sizeof(cxoObject), // tp_basicsize
79 0, // tp_itemsize
80 (destructor) cxoObject_free, // tp_dealloc
81 0, // tp_print
82 0, // tp_getattr
83 0, // tp_setattr
84 0, // tp_compare
85 (reprfunc) cxoObject_repr, // tp_repr
86 0, // tp_as_number
87 0, // tp_as_sequence
88 0, // tp_as_mapping
89 0, // tp_hash
90 0, // tp_call
91 0, // tp_str
92 (getattrofunc) cxoObject_getAttr, // tp_getattro
93 (setattrofunc) cxoObject_setAttr, // tp_setattro
94 0, // tp_as_buffer
95 Py_TPFLAGS_DEFAULT, // tp_flags
96 0, // tp_doc
97 0, // tp_traverse
98 0, // tp_clear
99 0, // tp_richcompare
100 0, // tp_weaklistoffset
101 0, // tp_iter
102 0, // tp_iternext
103 cxoObjectMethods, // tp_methods
104 cxoObjectMembers // tp_members
77 .tp_name = "cx_Oracle.Object",
78 .tp_basicsize = sizeof(cxoObject),
79 .tp_dealloc = (destructor) cxoObject_free,
80 .tp_repr = (reprfunc) cxoObject_repr,
81 .tp_getattro = (getattrofunc) cxoObject_getAttr,
82 .tp_setattro = (setattrofunc) cxoObject_setAttr,
83 .tp_flags = Py_TPFLAGS_DEFAULT,
84 .tp_methods = cxoObjectMethods,
85 .tp_members = cxoObjectMembers
10586 };
10687
10788
175156
176157 // convert the different Python types
177158 cxoTransform_getTypeInfo(transformNum, &oracleTypeNum, nativeTypeNum);
178 if (cxoTransform_fromPython(transformNum, value, &data->value, buffer,
159 if (cxoTransform_fromPython(transformNum, nativeTypeNum, value,
160 &data->value, buffer,
179161 obj->objectType->connection->encodingInfo.encoding,
180162 obj->objectType->connection->encodingInfo.nencoding, NULL, 0) < 0)
181163 return -1;
228210 nativeTypeNum, &data) < 0)
229211 return cxoError_raiseAndReturnNull();
230212 return cxoObject_convertToPython(obj, attribute->transformNum, &data,
231 attribute->type);
213 attribute->objectType);
232214 }
233215
234216
384366 &data) < 0)
385367 return cxoError_raiseAndReturnNull();
386368 return cxoObject_convertToPython(obj, obj->objectType->elementTransformNum,
387 &data, (cxoObjectType*) obj->objectType->elementType);
369 &data, obj->objectType->elementObjectType);
388370 }
389371
390372
415397 Py_DECREF(dict);
416398 return NULL;
417399 }
418 key = PyInt_FromLong(index);
400 key = PyLong_FromLong(index);
419401 if (!key) {
420402 Py_DECREF(value);
421403 Py_DECREF(dict);
580562 if (dpiObject_getFirstIndex(obj->handle, &index, &exists) < 0)
581563 return cxoError_raiseAndReturnNull();
582564 if (exists)
583 return PyInt_FromLong(index);
565 return PyLong_FromLong(index);
584566 Py_RETURN_NONE;
585567 }
586568
597579 if (dpiObject_getLastIndex(obj->handle, &index, &exists) < 0)
598580 return cxoError_raiseAndReturnNull();
599581 if (exists)
600 return PyInt_FromLong(index);
582 return PyLong_FromLong(index);
601583 Py_RETURN_NONE;
602584 }
603585
617599 if (dpiObject_getNextIndex(obj->handle, index, &nextIndex, &exists) < 0)
618600 return cxoError_raiseAndReturnNull();
619601 if (exists)
620 return PyInt_FromLong(nextIndex);
602 return PyLong_FromLong(nextIndex);
621603 Py_RETURN_NONE;
622604 }
623605
637619 if (dpiObject_getPrevIndex(obj->handle, index, &prevIndex, &exists) < 0)
638620 return cxoError_raiseAndReturnNull();
639621 if (exists)
640 return PyInt_FromLong(prevIndex);
622 return PyLong_FromLong(prevIndex);
641623 Py_RETURN_NONE;
642624 }
643625
653635
654636 if (dpiObject_getSize(obj->handle, &size) < 0)
655637 return cxoError_raiseAndReturnNull();
656 return PyInt_FromLong(size);
638 return PyLong_FromLong(size);
657639 }
658640
659641
700682 return cxoError_raiseAndReturnNull();
701683 Py_RETURN_NONE;
702684 }
703
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
1313 //-----------------------------------------------------------------------------
1414 static void cxoObjectAttr_free(cxoObjectAttr*);
1515 static PyObject *cxoObjectAttr_repr(cxoObjectAttr*);
16 static PyObject *cxoObjectAttr_getType(cxoObjectAttr*, void*);
1617
1718
1819 //-----------------------------------------------------------------------------
19 // declaration of members for Python type "ObjectAttribute"
20 // declaration of members
2021 //-----------------------------------------------------------------------------
21 static PyMemberDef cxoObjectAttrMembers[] = {
22 static PyMemberDef cxoMembers[] = {
2223 { "name", T_OBJECT, offsetof(cxoObjectAttr, name), READONLY },
24 { NULL }
25 };
26
27
28 //-----------------------------------------------------------------------------
29 // declaration of calculated members
30 //-----------------------------------------------------------------------------
31 static PyGetSetDef cxoCalcMembers[] = {
32 { "type", (getter) cxoObjectAttr_getType, 0, 0, 0 },
2333 { NULL }
2434 };
2535
2939 //-----------------------------------------------------------------------------
3040 PyTypeObject cxoPyTypeObjectAttr = {
3141 PyVarObject_HEAD_INIT(NULL, 0)
32 "cx_Oracle.ObjectAttribute", // tp_name
33 sizeof(cxoObjectAttr), // tp_basicsize
34 0, // tp_itemsize
35 (destructor) cxoObjectAttr_free, // tp_dealloc
36 0, // tp_print
37 0, // tp_getattr
38 0, // tp_setattr
39 0, // tp_compare
40 (reprfunc) cxoObjectAttr_repr, // tp_repr
41 0, // tp_as_number
42 0, // tp_as_sequence
43 0, // tp_as_mapping
44 0, // tp_hash
45 0, // tp_call
46 0, // tp_str
47 0, // tp_getattro
48 0, // tp_setattro
49 0, // tp_as_buffer
50 Py_TPFLAGS_DEFAULT, // tp_flags
51 0, // tp_doc
52 0, // tp_traverse
53 0, // tp_clear
54 0, // tp_richcompare
55 0, // tp_weaklistoffset
56 0, // tp_iter
57 0, // tp_iternext
58 0, // tp_methods
59 cxoObjectAttrMembers, // tp_members
60 0, // tp_getset
61 0, // tp_base
62 0, // tp_dict
63 0, // tp_descr_get
64 0, // tp_descr_set
65 0, // tp_dictoffset
66 0, // tp_init
67 0, // tp_alloc
68 0, // tp_new
69 0, // tp_free
70 0, // tp_is_gc
71 0 // tp_bases
42 .tp_name = "cx_Oracle.ObjectAttribute",
43 .tp_basicsize = sizeof(cxoObjectAttr),
44 .tp_dealloc = (destructor) cxoObjectAttr_free,
45 .tp_repr = (reprfunc) cxoObjectAttr_repr,
46 .tp_flags = Py_TPFLAGS_DEFAULT,
47 .tp_members = cxoMembers,
48 .tp_getset = cxoCalcMembers
7249 };
7350
7451
8461 if (dpiObjectAttr_getInfo(attr->handle, &info) < 0)
8562 return cxoError_raiseAndReturnInt();
8663 attr->transformNum = cxoTransform_getNumFromDataTypeInfo(&info.typeInfo);
64 attr->dbType = cxoDbType_fromTransformNum(attr->transformNum);
65 if (!attr->dbType)
66 return -1;
67 Py_INCREF(attr->dbType);
8768 attr->oracleTypeNum = info.typeInfo.oracleTypeNum;
88 attr->name = cxoPyString_fromEncodedString(info.name, info.nameLength,
69 attr->name = PyUnicode_Decode(info.name, info.nameLength,
8970 connection->encodingInfo.encoding, NULL);
9071 if (!attr->name)
9172 return -1;
9273 if (info.typeInfo.objectType) {
93 attr->type = cxoObjectType_new(connection,
74 attr->objectType = cxoObjectType_new(connection,
9475 info.typeInfo.objectType);
95 if (!attr->type)
76 if (!attr->objectType)
9677 return -1;
9778 }
9879
136117 attr->handle = NULL;
137118 }
138119 Py_CLEAR(attr->name);
139 Py_CLEAR(attr->type);
120 Py_CLEAR(attr->objectType);
121 Py_CLEAR(attr->dbType);
140122 Py_TYPE(attr)->tp_free((PyObject*) attr);
123 }
124
125
126 //-----------------------------------------------------------------------------
127 // cxoObjectAttr_getType()
128 // Return the type associated with the attribute. This is either an object
129 // type or one of the database type constants.
130 //-----------------------------------------------------------------------------
131 static PyObject *cxoObjectAttr_getType(cxoObjectAttr *attr, void *unused)
132 {
133 if (attr->objectType) {
134 Py_INCREF(attr->objectType);
135 return (PyObject*) attr->objectType;
136 }
137
138 Py_INCREF(attr->dbType);
139 return (PyObject*) attr->dbType;
141140 }
142141
143142
157156 Py_DECREF(name);
158157 return result;
159158 }
160
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
1919 static void cxoObjectType_free(cxoObjectType*);
2020 static PyObject *cxoObjectType_repr(cxoObjectType*);
2121 static PyObject *cxoObjectType_newObject(cxoObjectType*, PyObject*, PyObject*);
22
23
24 //-----------------------------------------------------------------------------
25 // declaration of methods for Python type "ObjectType"
26 //-----------------------------------------------------------------------------
27 static PyMethodDef cxoObjectTypeMethods[] = {
22 static PyObject *cxoObjectType_richCompare(cxoObjectType*, PyObject*, int);
23 static PyObject *cxoObjectType_getElementType(cxoObjectType*, void*);
24
25
26 //-----------------------------------------------------------------------------
27 // declaration of methods
28 //-----------------------------------------------------------------------------
29 static PyMethodDef cxoMethods[] = {
2830 { "newobject", (PyCFunction) cxoObjectType_newObject,
2931 METH_VARARGS | METH_KEYWORDS },
3032 { NULL }
3234
3335
3436 //-----------------------------------------------------------------------------
35 // declaration of members for Python type "ObjectType"
36 //-----------------------------------------------------------------------------
37 static PyMemberDef cxoObjectTypeMembers[] = {
37 // declaration of members
38 //-----------------------------------------------------------------------------
39 static PyMemberDef cxoMembers[] = {
3840 { "schema", T_OBJECT, offsetof(cxoObjectType, schema), READONLY },
3941 { "name", T_OBJECT, offsetof(cxoObjectType, name), READONLY },
4042 { "attributes", T_OBJECT, offsetof(cxoObjectType, attributes), READONLY },
41 { "elementType", T_OBJECT, offsetof(cxoObjectType, elementType),
42 READONLY },
4343 { "iscollection", T_BOOL, offsetof(cxoObjectType, isCollection),
4444 READONLY },
4545 { NULL }
4747
4848
4949 //-----------------------------------------------------------------------------
50 // declaration of calculated members
51 //-----------------------------------------------------------------------------
52 static PyGetSetDef cxoCalcMembers[] = {
53 { "element_type", (getter) cxoObjectType_getElementType, 0, 0, 0 },
54 { NULL }
55 };
56
57
58 //-----------------------------------------------------------------------------
5059 // Python type declarations
5160 //-----------------------------------------------------------------------------
5261 PyTypeObject cxoPyTypeObjectType = {
5362 PyVarObject_HEAD_INIT(NULL, 0)
54 "cx_Oracle.ObjectType", // tp_name
55 sizeof(cxoObjectType), // tp_basicsize
56 0, // tp_itemsize
57 (destructor) cxoObjectType_free, // tp_dealloc
58 0, // tp_print
59 0, // tp_getattr
60 0, // tp_setattr
61 0, // tp_compare
62 (reprfunc) cxoObjectType_repr, // tp_repr
63 0, // tp_as_number
64 0, // tp_as_sequence
65 0, // tp_as_mapping
66 0, // tp_hash
67 (ternaryfunc) cxoObjectType_newObject, // tp_call
68 0, // tp_str
69 0, // tp_getattro
70 0, // tp_setattro
71 0, // tp_as_buffer
72 Py_TPFLAGS_DEFAULT, // tp_flags
73 0, // tp_doc
74 0, // tp_traverse
75 0, // tp_clear
76 0, // tp_richcompare
77 0, // tp_weaklistoffset
78 0, // tp_iter
79 0, // tp_iternext
80 cxoObjectTypeMethods, // tp_methods
81 cxoObjectTypeMembers, // tp_members
82 0, // tp_getset
83 0, // tp_base
84 0, // tp_dict
85 0, // tp_descr_get
86 0, // tp_descr_set
87 0, // tp_dictoffset
88 0, // tp_init
89 0, // tp_alloc
90 0, // tp_new
91 0, // tp_free
92 0, // tp_is_gc
93 0 // tp_bases
63 .tp_name = "cx_Oracle.ObjectType",
64 .tp_basicsize = sizeof(cxoObjectType),
65 .tp_dealloc = (destructor) cxoObjectType_free,
66 .tp_repr = (reprfunc) cxoObjectType_repr,
67 .tp_call = (ternaryfunc) cxoObjectType_newObject,
68 .tp_flags = Py_TPFLAGS_DEFAULT,
69 .tp_methods = cxoMethods,
70 .tp_members = cxoMembers,
71 .tp_getset = cxoCalcMembers,
72 .tp_richcompare = (richcmpfunc) cxoObjectType_richCompare
9473 };
9574
9675
11190 return cxoError_raiseAndReturnInt();
11291 Py_INCREF(connection);
11392 objType->connection = connection;
114 objType->schema = cxoPyString_fromEncodedString(info.schema,
115 info.schemaLength, connection->encodingInfo.encoding, NULL);
93 objType->schema = PyUnicode_Decode(info.schema, info.schemaLength,
94 connection->encodingInfo.encoding, NULL);
11695 if (!objType->schema)
11796 return -1;
118 objType->name = cxoPyString_fromEncodedString(info.name, info.nameLength,
97 objType->name = PyUnicode_Decode(info.name, info.nameLength,
11998 connection->encodingInfo.encoding, NULL);
12099 if (!objType->name)
121100 return -1;
122101 objType->isCollection = info.isCollection;
123 objType->elementOracleTypeNum = info.elementTypeInfo.oracleTypeNum;
124 objType->elementTransformNum =
125 cxoTransform_getNumFromDataTypeInfo(&info.elementTypeInfo);
126 if (info.elementTypeInfo.objectType) {
127 objType->elementType = (PyObject*) cxoObjectType_new(connection,
128 info.elementTypeInfo.objectType);
129 if (!objType->elementType)
102 if (info.isCollection) {
103 objType->elementOracleTypeNum = info.elementTypeInfo.oracleTypeNum;
104 objType->elementTransformNum =
105 cxoTransform_getNumFromDataTypeInfo(&info.elementTypeInfo);
106 objType->elementDbType =
107 cxoDbType_fromTransformNum(objType->elementTransformNum);
108 if (!objType->elementDbType)
130109 return -1;
110 Py_INCREF(objType->elementDbType);
111 if (info.elementTypeInfo.objectType) {
112 objType->elementObjectType = cxoObjectType_new(connection,
113 info.elementTypeInfo.objectType);
114 if (!objType->elementObjectType)
115 return -1;
116 }
131117 }
132118
133119 // allocate the attribute list (temporary and permanent) and dictionary
159145 }
160146 PyList_SET_ITEM(objType->attributes, i, (PyObject*) attr);
161147 if (PyDict_SetItem(objType->attributesByName, attr->name,
162 (PyObject*) attr) < 0)
148 (PyObject*) attr) < 0) {
149 PyMem_Free(attributes);
163150 return -1;
151 }
164152 }
165153 PyMem_Free(attributes);
166154 return 0;
236224 Py_CLEAR(objType->name);
237225 Py_CLEAR(objType->attributes);
238226 Py_CLEAR(objType->attributesByName);
239 Py_CLEAR(objType->elementType);
227 Py_CLEAR(objType->elementObjectType);
228 Py_CLEAR(objType->elementDbType);
240229 Py_TYPE(objType)->tp_free((PyObject*) objType);
230 }
231
232
233 //-----------------------------------------------------------------------------
234 // cxoObjectType_getElementType()
235 // Return the element type associated with a collection. This is either an
236 // object type or one of the database type constants. If the object type is not
237 // a collection, None is returned.
238 //-----------------------------------------------------------------------------
239 static PyObject *cxoObjectType_getElementType(cxoObjectType *type,
240 void *unused)
241 {
242 if (type->elementObjectType) {
243 Py_INCREF(type->elementObjectType);
244 return (PyObject*) type->elementObjectType;
245 }
246 if (type->elementDbType) {
247 Py_INCREF(type->elementDbType);
248 return (PyObject*) type->elementDbType;
249 }
250
251 Py_RETURN_NONE;
241252 }
242253
243254
260271
261272
262273 //-----------------------------------------------------------------------------
274 // cxoObjectType_richCompare()
275 // Peforms a comparison between the object type and another Python object.
276 // Equality (and inequality) are suppported to match object types; no other
277 // operations are supported.
278 //-----------------------------------------------------------------------------
279 static PyObject *cxoObjectType_richCompare(cxoObjectType* objType,
280 PyObject* otherObj, int op)
281 {
282 cxoObjectType *otherObjType;
283 int status, equal = 0;
284
285 // only equality and inequality can be checked
286 if (op != Py_EQ && op != Py_NE) {
287 Py_INCREF(Py_NotImplemented);
288 return Py_NotImplemented;
289 }
290
291 // check to see if the other object is an object type, too
292 status = PyObject_IsInstance(otherObj, (PyObject*) &cxoPyTypeObjectType);
293 if (status < 0)
294 return NULL;
295 if (status == 1) {
296 otherObjType = (cxoObjectType*) otherObj;
297 if (otherObjType->connection == objType->connection ||
298 otherObjType->connection->sessionPool ==
299 objType->connection->sessionPool) {
300 equal = PyObject_RichCompareBool(otherObjType->schema,
301 objType->schema, Py_EQ);
302 if (equal < 0)
303 return NULL;
304 if (equal) {
305 equal = PyObject_RichCompareBool(otherObjType->name,
306 objType->name, Py_EQ);
307 if (equal < 0)
308 return NULL;
309 }
310 }
311 }
312
313 // determine return value
314 if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) {
315 Py_RETURN_TRUE;
316 }
317 Py_RETURN_FALSE;
318 }
319
320
321 //-----------------------------------------------------------------------------
263322 // cxoObjectType_newObject()
264323 // Factory function for creating objects of the type which can be bound.
265324 //-----------------------------------------------------------------------------
298357
299358 return (PyObject*) obj;
300359 }
301
0 //-----------------------------------------------------------------------------
1 // Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
2 //-----------------------------------------------------------------------------
3
4 //-----------------------------------------------------------------------------
5 // cxoQueue.c
6 // Defines the routines for handling queues (advanced queuing). These queues
7 // permit sending and receiving messages defined by the database.
8 //-----------------------------------------------------------------------------
9
10 #include "cxoModule.h"
11
12 //-----------------------------------------------------------------------------
13 // Declaration of functions
14 //-----------------------------------------------------------------------------
15 static void cxoQueue_free(cxoQueue*);
16 static PyObject *cxoQueue_repr(cxoQueue*);
17 static PyObject *cxoQueue_deqMany(cxoQueue*, PyObject*);
18 static PyObject *cxoQueue_deqOne(cxoQueue*, PyObject*);
19 static PyObject *cxoQueue_enqMany(cxoQueue*, PyObject*);
20 static PyObject *cxoQueue_enqOne(cxoQueue*, PyObject*);
21
22
23 //-----------------------------------------------------------------------------
24 // declaration of methods
25 //-----------------------------------------------------------------------------
26 static PyMethodDef cxoMethods[] = {
27 { "deqMany", (PyCFunction) cxoQueue_deqMany, METH_VARARGS },
28 { "deqOne", (PyCFunction) cxoQueue_deqOne, METH_NOARGS },
29 { "enqMany", (PyCFunction) cxoQueue_enqMany, METH_VARARGS },
30 { "enqOne", (PyCFunction) cxoQueue_enqOne, METH_VARARGS },
31 { NULL }
32 };
33
34
35 //-----------------------------------------------------------------------------
36 // declaration of members
37 //-----------------------------------------------------------------------------
38 static PyMemberDef cxoMembers[] = {
39 { "connection", T_OBJECT, offsetof(cxoQueue, conn), READONLY },
40 { "deqOptions", T_OBJECT, offsetof(cxoQueue, deqOptions), READONLY },
41 { "enqOptions", T_OBJECT, offsetof(cxoQueue, enqOptions), READONLY },
42 { "name", T_OBJECT, offsetof(cxoQueue, name), READONLY },
43 { "payloadType", T_OBJECT, offsetof(cxoQueue, payloadType), READONLY },
44 { NULL }
45 };
46
47
48 //-----------------------------------------------------------------------------
49 // Python type declarations
50 //-----------------------------------------------------------------------------
51 PyTypeObject cxoPyTypeQueue = {
52 PyVarObject_HEAD_INIT(NULL, 0)
53 .tp_name = "cx_Oracle.Queue",
54 .tp_basicsize = sizeof(cxoQueue),
55 .tp_dealloc = (destructor) cxoQueue_free,
56 .tp_repr = (reprfunc) cxoQueue_repr,
57 .tp_flags = Py_TPFLAGS_DEFAULT,
58 .tp_methods = cxoMethods,
59 .tp_members = cxoMembers
60 };
61
62
63 //-----------------------------------------------------------------------------
64 // cxoQueue_new()
65 // Create a new queue (advanced queuing).
66 //-----------------------------------------------------------------------------
67 cxoQueue *cxoQueue_new(cxoConnection *conn, dpiQueue *handle)
68 {
69 dpiDeqOptions *deqOptions;
70 dpiEnqOptions *enqOptions;
71 cxoQueue *queue;
72
73 // create queue and populate basic attributes
74 queue = (cxoQueue*) cxoPyTypeQueue.tp_alloc(&cxoPyTypeQueue, 0);
75 if (!queue) {
76 dpiQueue_release(handle);
77 return NULL;
78 }
79 Py_INCREF(conn);
80 queue->conn = conn;
81 queue->handle = handle;
82
83 // get dequeue options
84 if (dpiQueue_getDeqOptions(queue->handle, &deqOptions) < 0) {
85 cxoError_raiseAndReturnNull();
86 Py_DECREF(queue);
87 return NULL;
88 }
89 queue->deqOptions = (PyObject*) cxoDeqOptions_new(conn, deqOptions);
90 if (!queue->deqOptions) {
91 Py_DECREF(queue);
92 return NULL;
93 }
94
95 // get enqueue options
96 if (dpiQueue_getEnqOptions(queue->handle, &enqOptions) < 0) {
97 cxoError_raiseAndReturnNull();
98 Py_DECREF(queue);
99 return NULL;
100 }
101 queue->enqOptions = (PyObject*) cxoEnqOptions_new(conn, enqOptions);
102 if (!queue->enqOptions) {
103 Py_DECREF(queue);
104 return NULL;
105 }
106
107 return queue;
108 }
109
110
111 //-----------------------------------------------------------------------------
112 // cxoQueue_free()
113 // Free the memory associated with a queue.
114 //-----------------------------------------------------------------------------
115 static void cxoQueue_free(cxoQueue *queue)
116 {
117 if (queue->handle) {
118 dpiQueue_release(queue->handle);
119 queue->handle = NULL;
120 }
121 Py_CLEAR(queue->conn);
122 Py_CLEAR(queue->name);
123 Py_CLEAR(queue->payloadType);
124 Py_CLEAR(queue->deqOptions);
125 Py_CLEAR(queue->enqOptions);
126 Py_TYPE(queue)->tp_free((PyObject*) queue);
127 }
128
129
130 //-----------------------------------------------------------------------------
131 // cxoQueue_repr()
132 // Return a string representation of a queue.
133 //-----------------------------------------------------------------------------
134 static PyObject *cxoQueue_repr(cxoQueue *queue)
135 {
136 PyObject *module, *name, *result;
137
138 if (cxoUtils_getModuleAndName(Py_TYPE(queue), &module, &name) < 0)
139 return NULL;
140 result = cxoUtils_formatString("<%s.%s %r>",
141 PyTuple_Pack(3, module, name, queue->name));
142 Py_DECREF(module);
143 Py_DECREF(name);
144 return result;
145 }
146
147
148 //-----------------------------------------------------------------------------
149 // cxoQueue_deqHelper()
150 // Helper for dequeuing messages from a queue.
151 //-----------------------------------------------------------------------------
152 int cxoQueue_deqHelper(cxoQueue *queue, uint32_t *numProps,
153 cxoMsgProps **props)
154 {
155 uint32_t bufferLength, i, j;
156 dpiMsgProps **handles;
157 dpiObject *objHandle;
158 const char *buffer;
159 cxoMsgProps *temp;
160 cxoObject *obj;
161 int ok, status;
162
163 // use the same array to store the intermediate values provided by ODPI-C;
164 // by doing so there is no need to allocate an additional array and any
165 // values created by this helper routine are cleaned up on error
166 handles = (dpiMsgProps**) props;
167
168 // perform dequeue
169 Py_BEGIN_ALLOW_THREADS
170 status = dpiQueue_deqMany(queue->handle, numProps, handles);
171 Py_END_ALLOW_THREADS
172 if (status < 0)
173 return cxoError_raiseAndReturnInt();
174
175 // create objects that are returned to the user
176 for (i = 0; i < *numProps; i++) {
177
178 // create message property object
179 temp = cxoMsgProps_new(queue->conn, handles[i]);
180 ok = (temp) ? 1 : 0;
181 props[i] = temp;
182
183 // get payload from ODPI-C message property
184 if (ok && dpiMsgProps_getPayload(temp->handle, &objHandle, &buffer,
185 &bufferLength) < 0) {
186 cxoError_raiseAndReturnInt();
187 ok = 0;
188 }
189
190 // store payload on cx_Oracle message property
191 if (ok && objHandle) {
192 obj = (cxoObject*) cxoObject_new(queue->payloadType, objHandle);
193 if (obj && dpiObject_addRef(objHandle) < 0) {
194 cxoError_raiseAndReturnInt();
195 obj->handle = NULL;
196 Py_CLEAR(obj);
197 ok = 0;
198 }
199 temp->payload = (PyObject*) obj;
200 } else if (ok) {
201 temp->payload = PyBytes_FromStringAndSize(buffer, bufferLength);
202 }
203
204 // if an error occurred, do some cleanup
205 if (!ok || !temp->payload) {
206 Py_XDECREF(temp);
207 for (j = 0; j < i; j++)
208 Py_DECREF(props[j]);
209 for (j = i + 1; j < *numProps; j++)
210 dpiMsgProps_release(handles[j]);
211 return -1;
212 }
213
214 }
215
216 return 0;
217 }
218
219
220 //-----------------------------------------------------------------------------
221 // cxoQueue_enqHelper()
222 // Helper for enqueuing messages from a queue.
223 //-----------------------------------------------------------------------------
224 int cxoQueue_enqHelper(cxoQueue *queue, uint32_t numProps,
225 cxoMsgProps **props)
226 {
227 dpiMsgProps **handles, *tempHandle;
228 cxoBuffer buffer;
229 cxoObject *obj;
230 uint32_t i;
231 int status;
232
233 // use the same array to store the intermediate values required by ODPI-C;
234 // by doing so there is no need to allocate an additional array
235 handles = (dpiMsgProps**) props;
236
237 // process array
238 for (i = 0; i < numProps; i++) {
239
240 // verify that the message property object has a payload
241 if (!props[i]->payload || props[i]->payload == Py_None) {
242 cxoError_raiseFromString(cxoProgrammingErrorException,
243 "message has no payload");
244 return -1;
245 }
246
247 // transfer payload to message properties object
248 tempHandle = props[i]->handle;
249 if (PyObject_IsInstance(props[i]->payload,
250 (PyObject*) &cxoPyTypeObject)) {
251 obj = (cxoObject*) props[i]->payload;
252 if (dpiMsgProps_setPayloadObject(props[i]->handle,
253 obj->handle) < 0)
254 return cxoError_raiseAndReturnInt();
255 } else {
256 if (cxoBuffer_fromObject(&buffer, props[i]->payload,
257 props[i]->encoding) < 0)
258 return -1;
259 status = dpiMsgProps_setPayloadBytes(props[i]->handle, buffer.ptr,
260 buffer.size);
261 cxoBuffer_clear(&buffer);
262 if (status < 0)
263 return cxoError_raiseAndReturnInt();
264 }
265 handles[i] = tempHandle;
266
267 }
268
269 // perform enqueue
270 Py_BEGIN_ALLOW_THREADS
271 status = dpiQueue_enqMany(queue->handle, numProps, handles);
272 Py_END_ALLOW_THREADS
273 if (status < 0)
274 return cxoError_raiseAndReturnInt();
275
276 return 0;
277 }
278
279
280 //-----------------------------------------------------------------------------
281 // cxoQueue_deqMany()
282 // Dequeue a single message to the queue.
283 //-----------------------------------------------------------------------------
284 static PyObject *cxoQueue_deqMany(cxoQueue *queue, PyObject *args)
285 {
286 unsigned int numPropsFromPython;
287 uint32_t numProps, i;
288 cxoMsgProps **props;
289 PyObject *result;
290
291 if (!PyArg_ParseTuple(args, "I", &numPropsFromPython))
292 return NULL;
293 numProps = (uint32_t) numPropsFromPython;
294 props = PyMem_Malloc(numProps * sizeof(cxoMsgProps*));
295 if (!props)
296 return NULL;
297 if (cxoQueue_deqHelper(queue, &numProps, props) < 0) {
298 PyMem_Free(props);
299 return NULL;
300 }
301 result = PyList_New(numProps);
302 if (!result) {
303 for (i = 0; i < numProps; i++)
304 Py_DECREF(props[i]);
305 PyMem_Free(props);
306 return NULL;
307 }
308 for (i = 0; i < numProps; i++)
309 PyList_SET_ITEM(result, i, (PyObject*) props[i]);
310 PyMem_Free(props);
311 return result;
312 }
313
314
315 //-----------------------------------------------------------------------------
316 // cxoQueue_deqOne()
317 // Dequeue a single message to the queue.
318 //-----------------------------------------------------------------------------
319 static PyObject *cxoQueue_deqOne(cxoQueue *queue, PyObject *args)
320 {
321 uint32_t numProps = 1;
322 cxoMsgProps *props;
323
324 if (cxoQueue_deqHelper(queue, &numProps, &props) < 0)
325 return NULL;
326 if (numProps > 0)
327 return (PyObject*) props;
328 Py_RETURN_NONE;
329 }
330
331
332 //-----------------------------------------------------------------------------
333 // cxoQueue_enqMany()
334 // Enqueue multiple messages to the queue.
335 //-----------------------------------------------------------------------------
336 static PyObject *cxoQueue_enqMany(cxoQueue *queue, PyObject *args)
337 {
338 PyObject *seq, *seqCheck, *temp;
339 Py_ssize_t seqLength, i;
340 cxoMsgProps **props;
341 int status;
342
343 // validate arguments
344 if (!PyArg_ParseTuple(args, "O", &seqCheck))
345 return NULL;
346 seq = PySequence_Fast(seqCheck, "expecting sequence");
347 if (!seq)
348 return NULL;
349
350 // zero messages means nothing to do
351 seqLength = PySequence_Length(seq);
352 if (seqLength == 0) {
353 Py_DECREF(seq);
354 Py_RETURN_NONE;
355 }
356
357 // populate array of properties
358 props = PyMem_Malloc(seqLength * sizeof(cxoMsgProps*));
359 if (!props) {
360 PyErr_NoMemory();
361 Py_DECREF(seq);
362 return NULL;
363 }
364 for (i = 0; i < seqLength; i++) {
365 temp = PySequence_Fast_GET_ITEM(seq, i);
366 if (Py_TYPE(temp) != &cxoPyTypeMsgProps) {
367 Py_DECREF(seq);
368 PyMem_Free(props);
369 PyErr_SetString(PyExc_TypeError,
370 "expecting sequence of message property objects");
371 return NULL;
372 }
373 props[i] = (cxoMsgProps*) temp;
374 }
375
376 // perform enqueue
377 status = cxoQueue_enqHelper(queue, (uint32_t) seqLength, props);
378 Py_DECREF(seq);
379 PyMem_Free(props);
380 if (status < 0)
381 return NULL;
382
383 Py_RETURN_NONE;
384 }
385
386
387 //-----------------------------------------------------------------------------
388 // cxoQueue_enqOne()
389 // Enqueue a single message to the queue.
390 //-----------------------------------------------------------------------------
391 static PyObject *cxoQueue_enqOne(cxoQueue *queue, PyObject *args)
392 {
393 cxoMsgProps *props;
394
395 if (!PyArg_ParseTuple(args, "O!", &cxoPyTypeMsgProps, &props))
396 return NULL;
397 if (cxoQueue_enqHelper(queue, 1, &props) < 0)
398 return NULL;
399
400 Py_RETURN_NONE;
401 }
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
9595 //-----------------------------------------------------------------------------
9696 PyTypeObject cxoPyTypeSessionPool = {
9797 PyVarObject_HEAD_INIT(NULL, 0)
98 "cx_Oracle.SessionPool", // tp_name
99 sizeof(cxoSessionPool), // tp_basicsize
100 0, // tp_itemsize
101 (destructor) cxoSessionPool_free, // tp_dealloc
102 0, // tp_print
103 0, // tp_getattr
104 0, // tp_setattr
105 0, // tp_compare
106 0, // tp_repr
107 0, // tp_as_number
108 0, // tp_as_sequence
109 0, // tp_as_mapping
110 0, // tp_hash
111 0, // tp_call
112 0, // tp_str
113 0, // tp_getattro
114 0, // tp_setattro
115 0, // tp_as_buffer
116 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
117 // tp_flags
118 0, // tp_doc
119 0, // tp_traverse
120 0, // tp_clear
121 0, // tp_richcompare
122 0, // tp_weaklistoffset
123 0, // tp_iter
124 0, // tp_iternext
125 cxoSessionPoolMethods, // tp_methods
126 cxoSessionPoolMembers, // tp_members
127 cxoSessionPoolCalcMembers, // tp_getset
128 0, // tp_base
129 0, // tp_dict
130 0, // tp_descr_get
131 0, // tp_descr_set
132 0, // tp_dictoffset
133 (initproc) cxoSessionPool_init, // tp_init
134 0, // tp_alloc
135 (newfunc) cxoSessionPool_new, // tp_new
136 0, // tp_free
137 0, // tp_is_gc
138 0 // tp_bases
98 .tp_name = "cx_Oracle.SessionPool",
99 .tp_basicsize = sizeof(cxoSessionPool),
100 .tp_dealloc = (destructor) cxoSessionPool_free,
101 .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
102 .tp_methods = cxoSessionPoolMethods,
103 .tp_members = cxoSessionPoolMembers,
104 .tp_getset = cxoSessionPoolCalcMembers,
105 .tp_init = (initproc) cxoSessionPool_init,
106 .tp_new = (newfunc) cxoSessionPool_new
139107 };
140108
141109
157125 static int cxoSessionPool_init(cxoSessionPool *pool, PyObject *args,
158126 PyObject *keywordArgs)
159127 {
128 uint32_t minSessions, maxSessions, sessionIncrement, maxSessionsPerShard;
160129 cxoBuffer userNameBuffer, passwordBuffer, dsnBuffer, editionBuffer;
161130 PyObject *threadedObj, *eventsObj, *homogeneousObj, *passwordObj;
162131 PyObject *usernameObj, *dsnObj, *sessionCallbackObj;
163 uint32_t minSessions, maxSessions, sessionIncrement;
164132 PyObject *externalAuthObj, *editionObj;
165133 dpiCommonCreateParams dpiCommonParams;
166134 dpiPoolCreateParams dpiCreateParams;
174142 "increment", "connectiontype", "threaded", "getmode", "events",
175143 "homogeneous", "externalauth", "encoding", "nencoding", "edition",
176144 "timeout", "waitTimeout", "maxLifetimeSession", "sessionCallback",
177 NULL };
145 "maxSessionsPerShard", NULL };
178146
179147 // parse arguments and keywords
180148 usernameObj = passwordObj = dsnObj = editionObj = Py_None;
184152 minSessions = 1;
185153 maxSessions = 2;
186154 sessionIncrement = 1;
187 if (cxoUtils_initializeDPI() < 0)
155 maxSessionsPerShard = 0;
156 if (cxoUtils_initializeDPI(NULL) < 0)
188157 return -1;
189158 if (dpiContext_initCommonCreateParams(cxoDpiContext, &dpiCommonParams) < 0)
190159 return cxoError_raiseAndReturnInt();
191 dpiCommonParams.driverName = CXO_DRIVER_NAME;
192 dpiCommonParams.driverNameLength =
193 (uint32_t) strlen(dpiCommonParams.driverName);
194160 if (dpiContext_initPoolCreateParams(cxoDpiContext, &dpiCreateParams) < 0)
195161 return cxoError_raiseAndReturnInt();
196 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|OOOiiiOObOOOssOiiiO",
197 keywordList, &usernameObj, &passwordObj, &dsnObj, &minSessions,
198 &maxSessions, &sessionIncrement, &connectionType, &threadedObj,
199 &dpiCreateParams.getMode, &eventsObj, &homogeneousObj,
200 &externalAuthObj, &dpiCommonParams.encoding,
201 &dpiCommonParams.nencoding, &editionObj, &dpiCreateParams.timeout,
202 &dpiCreateParams.waitTimeout, &dpiCreateParams.maxLifetimeSession,
203 &sessionCallbackObj))
162 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs,
163 "|OOOiiiOObOOOssOiiiOi", keywordList, &usernameObj, &passwordObj,
164 &dsnObj, &minSessions, &maxSessions, &sessionIncrement,
165 &connectionType, &threadedObj, &dpiCreateParams.getMode,
166 &eventsObj, &homogeneousObj, &externalAuthObj,
167 &dpiCommonParams.encoding, &dpiCommonParams.nencoding, &editionObj,
168 &dpiCreateParams.timeout, &dpiCreateParams.waitTimeout,
169 &dpiCreateParams.maxLifetimeSession, &sessionCallbackObj,
170 &maxSessionsPerShard))
204171 return -1;
205172 if (!PyType_Check(connectionType)) {
206173 cxoError_raiseFromString(cxoProgrammingErrorException,
268235 dpiCreateParams.sessionIncrement = sessionIncrement;
269236 dpiCreateParams.plsqlFixupCallback = sessionCallbackBuffer.ptr;
270237 dpiCreateParams.plsqlFixupCallbackLength = sessionCallbackBuffer.size;
238 dpiCreateParams.maxSessionsPerShard = maxSessionsPerShard;
271239 dpiCommonParams.edition = editionBuffer.ptr;
272240 dpiCommonParams.editionLength = editionBuffer.size;
273241
292260 cxoUtils_getAdjustedEncoding(pool->encodingInfo.encoding);
293261 pool->encodingInfo.nencoding =
294262 cxoUtils_getAdjustedEncoding(pool->encodingInfo.nencoding);
295 pool->name = cxoPyString_fromEncodedString(dpiCreateParams.outPoolName,
263 pool->name = PyUnicode_Decode(dpiCreateParams.outPoolName,
296264 dpiCreateParams.outPoolNameLength, pool->encodingInfo.encoding,
297265 NULL);
298266 if (!pool->name)
331299 "tag", "matchanytag", "shardingkey", "supershardingkey", NULL };
332300 PyObject *createKeywordArgs, *result, *cclassObj, *purityObj, *tagObj;
333301 PyObject *shardingKeyObj, *superShardingKeyObj;
334 unsigned usernameLength, passwordLength;
302 Py_ssize_t usernameLength, passwordLength;
335303 char *username, *password;
336304 PyObject *matchAnyTagObj;
337305
338306 // parse arguments
339 username = NULL;
340307 if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|s#s#OOOOOO",
341308 keywordList, &username, &usernameLength, &password,
342309 &passwordLength, &cclassObj, &purityObj, &tagObj, &matchAnyTagObj,
343310 &shardingKeyObj, &superShardingKeyObj))
344311 return NULL;
345 if (pool->homogeneous && username)
346 return cxoError_raiseFromString(cxoProgrammingErrorException,
347 "pool is homogeneous. Proxy authentication is not possible.");
348312
349313 // create arguments
350314 if (keywordArgs)
484448
485449 if ((*func)(pool->handle, &value) < 0)
486450 return cxoError_raiseAndReturnNull();
487 #if PY_MAJOR_VERSION >= 3
488451 return PyLong_FromUnsignedLong(value);
489 #else
490 return PyInt_FromLong(value);
491 #endif
492452 }
493453
494454
501461 {
502462 uint32_t cValue;
503463
504 if (!PyInt_Check(value)) {
464 if (!PyLong_Check(value)) {
505465 PyErr_SetString(PyExc_TypeError, "value must be an integer");
506466 return -1;
507467 }
508 #if PY_MAJOR_VERSION >= 3
509468 cValue = PyLong_AsUnsignedLong(value);
510 #else
511 cValue = PyInt_AsLong(value);
512 #endif
513469 if (PyErr_Occurred())
514470 return -1;
515471 if ((*func)(pool->handle, cValue) < 0)
540496
541497 if (dpiPool_getGetMode(pool->handle, &value) < 0)
542498 return cxoError_raiseAndReturnNull();
543 return PyInt_FromLong(value);
499 return PyLong_FromLong(value);
544500 }
545501
546502
607563 {
608564 dpiPoolGetMode cValue;
609565
610 cValue = PyInt_AsLong(value);
566 cValue = PyLong_AsLong(value);
611567 if (PyErr_Occurred())
612568 return -1;
613569 if (dpiPool_setGetMode(pool->handle, cValue) < 0)
661617 {
662618 return cxoSessionPool_setAttribute(pool, value, dpiPool_setWaitTimeout);
663619 }
664
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
1919 PyObject*);
2020 static PyObject *cxoSodaCollection_find(cxoSodaCollection*, PyObject*);
2121 static PyObject *cxoSodaCollection_getDataGuide(cxoSodaCollection*, PyObject*);
22 static PyObject *cxoSodaCollection_insertMany(cxoSodaCollection*, PyObject*);
23 static PyObject *cxoSodaCollection_insertManyAndGet(cxoSodaCollection*,
24 PyObject*);
25 static PyObject *cxoSodaCollection_insertManyHelper(cxoSodaCollection *coll,
26 PyObject *docs, Py_ssize_t numDocs, dpiSodaDoc **handles,
27 dpiSodaDoc **returnHandles);
2228 static PyObject *cxoSodaCollection_insertOne(cxoSodaCollection*, PyObject*);
2329 static PyObject *cxoSodaCollection_insertOneAndGet(cxoSodaCollection*,
2430 PyObject*);
2531 static PyObject *cxoSodaCollection_getMetadata(cxoSodaCollection*, PyObject*);
32 static PyObject *cxoSodaCollection_save(cxoSodaCollection*, PyObject*);
33 static PyObject *cxoSodaCollection_saveAndGet(cxoSodaCollection*, PyObject*);
34 static PyObject *cxoSodaCollection_truncate(cxoSodaCollection*, PyObject*);
2635
2736
2837 //-----------------------------------------------------------------------------
3948 { "insertOne", (PyCFunction) cxoSodaCollection_insertOne, METH_O },
4049 { "insertOneAndGet", (PyCFunction) cxoSodaCollection_insertOneAndGet,
4150 METH_O },
51 { "insertMany", (PyCFunction) cxoSodaCollection_insertMany, METH_O },
52 { "insertManyAndGet", (PyCFunction) cxoSodaCollection_insertManyAndGet,
53 METH_O },
54 { "save", (PyCFunction) cxoSodaCollection_save, METH_O },
55 { "saveAndGet", (PyCFunction) cxoSodaCollection_saveAndGet, METH_O },
56 { "truncate", (PyCFunction) cxoSodaCollection_truncate, METH_NOARGS },
4257 { NULL }
4358 };
4459
6681 //-----------------------------------------------------------------------------
6782 PyTypeObject cxoPyTypeSodaCollection = {
6883 PyVarObject_HEAD_INIT(NULL, 0)
69 "cx_Oracle.SodaCollection", // tp_name
70 sizeof(cxoSodaCollection), // tp_basicsize
71 0, // tp_itemsize
72 (destructor) cxoSodaCollection_free,// tp_dealloc
73 0, // tp_print
74 0, // tp_getattr
75 0, // tp_setattr
76 0, // tp_compare
77 (reprfunc) cxoSodaCollection_repr, // tp_repr
78 0, // tp_as_number
79 0, // tp_as_sequence
80 0, // tp_as_mapping
81 0, // tp_hash
82 0, // tp_call
83 0, // tp_str
84 0, // tp_getattro
85 0, // tp_setattro
86 0, // tp_as_buffer
87 Py_TPFLAGS_DEFAULT, // tp_flags
88 0, // tp_doc
89 0, // tp_traverse
90 0, // tp_clear
91 0, // tp_richcompare
92 0, // tp_weaklistoffset
93 0, // tp_iter
94 0, // tp_iternext
95 cxoMethods, // tp_methods
96 cxoMembers, // tp_members
97 cxoCalcMembers, // tp_getset
98 0, // tp_base
99 0, // tp_dict
100 0, // tp_descr_get
101 0, // tp_descr_set
102 0, // tp_dictoffset
103 0, // tp_init
104 0, // tp_alloc
105 0, // tp_new
106 0, // tp_free
107 0, // tp_is_gc
108 0 // tp_bases
84 .tp_name = "cx_Oracle.SodaCollection",
85 .tp_basicsize = sizeof(cxoSodaCollection),
86 .tp_dealloc = (destructor) cxoSodaCollection_free,
87 .tp_repr = (reprfunc) cxoSodaCollection_repr,
88 .tp_flags = Py_TPFLAGS_DEFAULT,
89 .tp_methods = cxoMethods,
90 .tp_members = cxoMembers,
91 .tp_getset = cxoCalcMembers
10992 };
11093
11194 //-----------------------------------------------------------------------------
121104 // get name from ODPI-C
122105 if (dpiSodaColl_getName(handle, &name, &nameLength) < 0)
123106 return cxoError_raiseAndReturnInt();
124 coll->name = cxoPyString_fromEncodedString(name, nameLength, encoding,
125 NULL);
107 coll->name = PyUnicode_Decode(name, nameLength, encoding, NULL);
126108 if (!coll->name)
127109 return -1;
128110
323305
324306
325307 //-----------------------------------------------------------------------------
308 // cxoSodaCollection_insertMany()
309 // Inserts multilple document into the collection at one time.
310 //-----------------------------------------------------------------------------
311 static PyObject *cxoSodaCollection_insertMany(cxoSodaCollection *coll,
312 PyObject *arg)
313 {
314 dpiSodaDoc **handles;
315 Py_ssize_t numDocs;
316 PyObject *result;
317
318 if (!PyList_Check(arg)) {
319 PyErr_SetString(PyExc_TypeError, "expecting list");
320 return NULL;
321 }
322 numDocs = PyList_GET_SIZE(arg);
323 handles = PyMem_Malloc(numDocs * sizeof(dpiSodaDoc*));
324 if (!handles) {
325 PyErr_NoMemory();
326 return NULL;
327 }
328 result = cxoSodaCollection_insertManyHelper(coll, arg, numDocs, handles,
329 NULL);
330 PyMem_Free(handles);
331 return result;
332 }
333
334
335 //-----------------------------------------------------------------------------
336 // cxoSodaCollection_insertManyAndGet()
337 // Inserts multiple documents into the collection at one time and return a
338 // list of documents containing all but the content itself.
339 //-----------------------------------------------------------------------------
340 static PyObject *cxoSodaCollection_insertManyAndGet(cxoSodaCollection *coll,
341 PyObject *arg)
342 {
343 dpiSodaDoc **handles, **returnHandles;
344 Py_ssize_t numDocs;
345 PyObject *result;
346
347 if (!PyList_Check(arg)) {
348 PyErr_SetString(PyExc_TypeError, "expecting list");
349 return NULL;
350 }
351 numDocs = PyList_GET_SIZE(arg);
352 handles = PyMem_Malloc(numDocs * sizeof(dpiSodaDoc*));
353 if (!handles) {
354 PyErr_NoMemory();
355 return NULL;
356 }
357 returnHandles = PyMem_Malloc(numDocs * sizeof(dpiSodaDoc*));
358 if (!returnHandles) {
359 PyErr_NoMemory();
360 PyMem_Free(handles);
361 return NULL;
362 }
363 result = cxoSodaCollection_insertManyHelper(coll, arg, numDocs, handles,
364 returnHandles);
365 PyMem_Free(handles);
366 PyMem_Free(returnHandles);
367 return result;
368 }
369
370
371 //-----------------------------------------------------------------------------
372 // cxoSodaCollection_insertManyHelper()
373 // Helper method to perform bulk insert of SODA documents into a collection.
374 //-----------------------------------------------------------------------------
375 static PyObject *cxoSodaCollection_insertManyHelper(cxoSodaCollection *coll,
376 PyObject *docs, Py_ssize_t numDocs, dpiSodaDoc **handles,
377 dpiSodaDoc **returnHandles)
378 {
379 PyObject *element, *returnDocs;
380 Py_ssize_t i, j;
381 cxoSodaDoc *doc;
382 uint32_t flags;
383 int status;
384
385 // determine flags to use
386 if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
387 return NULL;
388
389 // populate array of document handles
390 for (i = 0; i < numDocs; i++) {
391 element = PyList_GET_ITEM(docs, i);
392 if (cxoUtils_processSodaDocArg(coll->db, element, &handles[i]) < 0) {
393 for (j = 0; j < i; j++)
394 dpiSodaDoc_release(handles[j]);
395 return NULL;
396 }
397 }
398
399 // perform bulk insert
400 Py_BEGIN_ALLOW_THREADS
401 status = dpiSodaColl_insertMany(coll->handle, (uint32_t) numDocs, handles,
402 flags, returnHandles);
403 Py_END_ALLOW_THREADS
404 if (status < 0)
405 cxoError_raiseAndReturnNull();
406 for (i = 0; i < numDocs; i++)
407 dpiSodaDoc_release(handles[i]);
408 if (status < 0)
409 return NULL;
410
411 // if no documents are to be returned, None is returned
412 if (!returnHandles)
413 Py_RETURN_NONE;
414
415 // otherwise, return list of documents
416 returnDocs = PyList_New(numDocs);
417 if (!returnDocs) {
418 for (i = 0; i < numDocs; i++)
419 dpiSodaDoc_release(returnHandles[i]);
420 return NULL;
421 }
422 for (i = 0; i < numDocs; i++) {
423 doc = cxoSodaDoc_new(coll->db, returnHandles[i]);
424 if (!doc) {
425 for (j = i; j < numDocs; j++)
426 dpiSodaDoc_release(returnHandles[j]);
427 Py_DECREF(returnDocs);
428 return NULL;
429 }
430 PyList_SET_ITEM(returnDocs, i, (PyObject*) doc);
431 }
432 return returnDocs;
433 }
434
435
436 //-----------------------------------------------------------------------------
326437 // cxoSodaCollection_insertOne()
327438 // Insert a single document into the collection.
328439 //-----------------------------------------------------------------------------
329440 static PyObject *cxoSodaCollection_insertOne(cxoSodaCollection *coll,
330441 PyObject *arg)
331442 {
332 cxoSodaDoc *doc;
333 uint32_t flags;
334 int status;
335
336 if (cxoUtils_processSodaDocArg(coll->db, arg, &doc) < 0)
337 return NULL;
338 if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
339 return NULL;
340 Py_BEGIN_ALLOW_THREADS
341 status = dpiSodaColl_insertOne(coll->handle, doc->handle, flags, NULL);
342 Py_END_ALLOW_THREADS
343 if (status < 0) {
443 dpiSodaDoc *handle;
444 uint32_t flags;
445 int status;
446
447 if (cxoUtils_processSodaDocArg(coll->db, arg, &handle) < 0)
448 return NULL;
449 if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
450 return NULL;
451 Py_BEGIN_ALLOW_THREADS
452 status = dpiSodaColl_insertOne(coll->handle, handle, flags, NULL);
453 Py_END_ALLOW_THREADS
454 if (status < 0)
344455 cxoError_raiseAndReturnNull();
345 Py_DECREF(doc);
346 return NULL;
347 }
348 Py_DECREF(doc);
456 dpiSodaDoc_release(handle);
457 if (status < 0)
458 return NULL;
349459 Py_RETURN_NONE;
350460 }
351461
358468 static PyObject *cxoSodaCollection_insertOneAndGet(cxoSodaCollection *coll,
359469 PyObject *arg)
360470 {
361 dpiSodaDoc *returnedDoc;
362 cxoSodaDoc *doc;
363 uint32_t flags;
364 int status;
365
366 if (cxoUtils_processSodaDocArg(coll->db, arg, &doc) < 0)
367 return NULL;
368 if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
369 return NULL;
370 Py_BEGIN_ALLOW_THREADS
371 status = dpiSodaColl_insertOne(coll->handle, doc->handle, flags,
372 &returnedDoc);
373 Py_END_ALLOW_THREADS
374 if (status < 0) {
471 dpiSodaDoc *handle, *returnedHandle;
472 uint32_t flags;
473 int status;
474
475 if (cxoUtils_processSodaDocArg(coll->db, arg, &handle) < 0)
476 return NULL;
477 if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
478 return NULL;
479 Py_BEGIN_ALLOW_THREADS
480 status = dpiSodaColl_insertOne(coll->handle, handle, flags,
481 &returnedHandle);
482 Py_END_ALLOW_THREADS
483 if (status < 0)
375484 cxoError_raiseAndReturnNull();
376 Py_DECREF(doc);
377 return NULL;
378 }
379 Py_DECREF(doc);
380 return (PyObject*) cxoSodaDoc_new(coll->db, returnedDoc);
485 dpiSodaDoc_release(handle);
486 if (status < 0)
487 return NULL;
488 return (PyObject*) cxoSodaDoc_new(coll->db, returnedHandle);
381489 }
382490
383491
403511 return result;
404512 }
405513
514
515 //-----------------------------------------------------------------------------
516 // cxoSodaCollection_save()
517 // Insert a single document into the collection.
518 //-----------------------------------------------------------------------------
519 static PyObject *cxoSodaCollection_save(cxoSodaCollection *coll,
520 PyObject *arg)
521 {
522 dpiSodaDoc *handle;
523 uint32_t flags;
524 int status;
525
526 if (cxoUtils_processSodaDocArg(coll->db, arg, &handle) < 0)
527 return NULL;
528 if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
529 return NULL;
530 Py_BEGIN_ALLOW_THREADS
531 status = dpiSodaColl_save(coll->handle, handle, flags, NULL);
532 Py_END_ALLOW_THREADS
533 if (status < 0)
534 cxoError_raiseAndReturnNull();
535 dpiSodaDoc_release(handle);
536 if (status < 0)
537 return NULL;
538 Py_RETURN_NONE;
539 }
540
541
542 //-----------------------------------------------------------------------------
543 // cxoSodaCollection_saveAndGet()
544 // Insert a single document into the collection and return a document
545 // containing all but the content itself.
546 //-----------------------------------------------------------------------------
547 static PyObject *cxoSodaCollection_saveAndGet(cxoSodaCollection *coll,
548 PyObject *arg)
549 {
550 dpiSodaDoc *handle, *returnedHandle;
551 uint32_t flags;
552 int status;
553
554 if (cxoUtils_processSodaDocArg(coll->db, arg, &handle) < 0)
555 return NULL;
556 if (cxoConnection_getSodaFlags(coll->db->connection, &flags) < 0)
557 return NULL;
558 Py_BEGIN_ALLOW_THREADS
559 status = dpiSodaColl_save(coll->handle, handle, flags, &returnedHandle);
560 Py_END_ALLOW_THREADS
561 if (status < 0)
562 cxoError_raiseAndReturnNull();
563 dpiSodaDoc_release(handle);
564 if (status < 0)
565 return NULL;
566 return (PyObject*) cxoSodaDoc_new(coll->db, returnedHandle);
567 }
568
569
570 //-----------------------------------------------------------------------------
571 // cxoSodaCollection_truncate()
572 // Remove all of the documents from the SODA collection.
573 //-----------------------------------------------------------------------------
574 static PyObject *cxoSodaCollection_truncate(cxoSodaCollection *coll,
575 PyObject *arg)
576 {
577 int status;
578
579 Py_BEGIN_ALLOW_THREADS
580 status = dpiSodaColl_truncate(coll->handle);
581 Py_END_ALLOW_THREADS
582 if (status < 0)
583 return cxoError_raiseAndReturnNull();
584 Py_RETURN_NONE;
585 }
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
4242 //-----------------------------------------------------------------------------
4343 PyTypeObject cxoPyTypeSodaDatabase = {
4444 PyVarObject_HEAD_INIT(NULL, 0)
45 "cx_Oracle.SodaDatabase", // tp_name
46 sizeof(cxoSodaDatabase), // tp_basicsize
47 0, // tp_itemsize
48 (destructor) cxoSodaDatabase_free, // tp_dealloc
49 0, // tp_print
50 0, // tp_getattr
51 0, // tp_setattr
52 0, // tp_compare
53 (reprfunc) cxoSodaDatabase_repr, // tp_repr
54 0, // tp_as_number
55 0, // tp_as_sequence
56 0, // tp_as_mapping
57 0, // tp_hash
58 0, // tp_call
59 0, // tp_str
60 0, // tp_getattro
61 0, // tp_setattro
62 0, // tp_as_buffer
63 Py_TPFLAGS_DEFAULT, // tp_flags
64 0, // tp_doc
65 0, // tp_traverse
66 0, // tp_clear
67 0, // tp_richcompare
68 0, // tp_weaklistoffset
69 0, // tp_iter
70 0, // tp_iternext
71 cxoMethods, // tp_methods
72 0, // tp_members
73 0, // tp_getset
74 0, // tp_base
75 0, // tp_dict
76 0, // tp_descr_get
77 0, // tp_descr_set
78 0, // tp_dictoffset
79 0, // tp_init
80 0, // tp_alloc
81 0, // tp_new
82 0, // tp_free
83 0, // tp_is_gc
84 0 // tp_bases
45 .tp_name = "cx_Oracle.SodaDatabase",
46 .tp_basicsize = sizeof(cxoSodaDatabase),
47 .tp_dealloc = (destructor) cxoSodaDatabase_free,
48 .tp_repr = (reprfunc) cxoSodaDatabase_repr,
49 .tp_flags = Py_TPFLAGS_DEFAULT,
50 .tp_methods = cxoMethods
8551 };
8652
8753
324290 if (!result)
325291 return NULL;
326292 for (i = 0; i < collNames.numNames; i++) {
327 temp = cxoPyString_fromEncodedString(collNames.names[i],
328 collNames.nameLengths[i], encoding, NULL);
293 temp = PyUnicode_Decode(collNames.names[i], collNames.nameLengths[i],
294 encoding, NULL);
329295 if (!temp) {
330296 Py_DECREF(result);
331297 return NULL;
377343
378344 return (PyObject*) coll;
379345 }
380
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
5454 //-----------------------------------------------------------------------------
5555 PyTypeObject cxoPyTypeSodaDoc = {
5656 PyVarObject_HEAD_INIT(NULL, 0)
57 "cx_Oracle.SodaDoc", // tp_name
58 sizeof(cxoSodaDoc), // tp_basicsize
59 0, // tp_itemsize
60 (destructor) cxoSodaDoc_free, // tp_dealloc
61 0, // tp_print
62 0, // tp_getattr
63 0, // tp_setattr
64 0, // tp_compare
65 (reprfunc) cxoSodaDoc_repr, // tp_repr
66 0, // tp_as_number
67 0, // tp_as_sequence
68 0, // tp_as_mapping
69 0, // tp_hash
70 0, // tp_call
71 0, // tp_str
72 0, // tp_getattro
73 0, // tp_setattro
74 0, // tp_as_buffer
75 Py_TPFLAGS_DEFAULT, // tp_flags
76 0, // tp_doc
77 0, // tp_traverse
78 0, // tp_clear
79 0, // tp_richcompare
80 0, // tp_weaklistoffset
81 0, // tp_iter
82 0, // tp_iternext
83 cxoMethods, // tp_methods
84 0, // tp_members
85 cxoCalcMembers, // tp_getset
86 0, // tp_base
87 0, // tp_dict
88 0, // tp_descr_get
89 0, // tp_descr_set
90 0, // tp_dictoffset
91 0, // tp_init
92 0, // tp_alloc
93 0, // tp_new
94 0, // tp_free
95 0, // tp_is_gc
96 0 // tp_bases
57 .tp_name = "cx_Oracle.SodaDoc",
58 .tp_basicsize = sizeof(cxoSodaDoc),
59 .tp_dealloc = (destructor) cxoSodaDoc_free,
60 .tp_repr = (reprfunc) cxoSodaDoc_repr,
61 .tp_flags = Py_TPFLAGS_DEFAULT,
62 .tp_methods = cxoMethods,
63 .tp_getset = cxoCalcMembers
9764 };
9865
9966
144111
145112 if (dpiSodaDoc_getKey(doc->handle, &key, &keyLength) < 0)
146113 return cxoError_raiseAndReturnNull();
147 keyObj = cxoPyString_fromEncodedString(key, keyLength,
114 keyObj = PyUnicode_Decode(key, keyLength,
148115 doc->db->connection->encodingInfo.encoding, NULL);
149116 if (!keyObj)
150117 return NULL;
173140 if (dpiSodaDoc_getCreatedOn(doc->handle, &value, &valueLength) < 0)
174141 return cxoError_raiseAndReturnNull();
175142 if (valueLength > 0)
176 return cxoPyString_fromEncodedString(value, valueLength,
143 return PyUnicode_Decode(value, valueLength,
177144 doc->db->connection->encodingInfo.encoding, NULL);
178145 Py_RETURN_NONE;
179146 }
191158 if (dpiSodaDoc_getKey(doc->handle, &value, &valueLength) < 0)
192159 return cxoError_raiseAndReturnNull();
193160 if (valueLength > 0)
194 return cxoPyString_fromEncodedString(value, valueLength,
161 return PyUnicode_Decode(value, valueLength,
195162 doc->db->connection->encodingInfo.encoding, NULL);
196163 Py_RETURN_NONE;
197164 }
210177 if (dpiSodaDoc_getLastModified(doc->handle, &value, &valueLength) < 0)
211178 return cxoError_raiseAndReturnNull();
212179 if (valueLength > 0)
213 return cxoPyString_fromEncodedString(value, valueLength,
180 return PyUnicode_Decode(value, valueLength,
214181 doc->db->connection->encodingInfo.encoding, NULL);
215182 Py_RETURN_NONE;
216183 }
228195 if (dpiSodaDoc_getMediaType(doc->handle, &value, &valueLength) < 0)
229196 return cxoError_raiseAndReturnNull();
230197 if (valueLength > 0)
231 return cxoPyString_fromEncodedString(value, valueLength,
198 return PyUnicode_Decode(value, valueLength,
232199 doc->db->connection->encodingInfo.encoding, NULL);
233200 Py_RETURN_NONE;
234201 }
246213 if (dpiSodaDoc_getVersion(doc->handle, &value, &valueLength) < 0)
247214 return cxoError_raiseAndReturnNull();
248215 if (valueLength > 0)
249 return cxoPyString_fromEncodedString(value, valueLength,
216 return PyUnicode_Decode(value, valueLength,
250217 doc->db->connection->encodingInfo.encoding, NULL);
251218 Py_RETURN_NONE;
252219 }
305272 return PyUnicode_Decode(content, contentLength, encoding, NULL);
306273 Py_RETURN_NONE;
307274 }
308
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
3434 //-----------------------------------------------------------------------------
3535 PyTypeObject cxoPyTypeSodaDocCursor = {
3636 PyVarObject_HEAD_INIT(NULL, 0)
37 "cx_Oracle.SodaDocCursor", // tp_name
38 sizeof(cxoSodaDocCursor), // tp_basicsize
39 0, // tp_itemsize
40 (destructor) cxoSodaDocCursor_free, // tp_dealloc
41 0, // tp_print
42 0, // tp_getattr
43 0, // tp_setattr
44 0, // tp_compare
45 (reprfunc) cxoSodaDocCursor_repr, // tp_repr
46 0, // tp_as_number
47 0, // tp_as_sequence
48 0, // tp_as_mapping
49 0, // tp_hash
50 0, // tp_call
51 0, // tp_str
52 0, // tp_getattro
53 0, // tp_setattro
54 0, // tp_as_buffer
55 Py_TPFLAGS_DEFAULT, // tp_flags
56 0, // tp_doc
57 0, // tp_traverse
58 0, // tp_clear
59 0, // tp_richcompare
60 0, // tp_weaklistoffset
61 (getiterfunc) cxoSodaDocCursor_getIter, // tp_iter
62 (iternextfunc) cxoSodaDocCursor_getNext, // tp_iternext
63 cxoMethods, // tp_methods
64 0, // tp_members
65 0, // tp_getset
66 0, // tp_base
67 0, // tp_dict
68 0, // tp_descr_get
69 0, // tp_descr_set
70 0, // tp_dictoffset
71 0, // tp_init
72 0, // tp_alloc
73 0, // tp_new
74 0, // tp_free
75 0, // tp_is_gc
76 0 // tp_bases
37 .tp_name = "cx_Oracle.SodaDocCursor",
38 .tp_basicsize = sizeof(cxoSodaDocCursor),
39 .tp_dealloc = (destructor) cxoSodaDocCursor_free,
40 .tp_repr = (reprfunc) cxoSodaDocCursor_repr,
41 .tp_flags = Py_TPFLAGS_DEFAULT,
42 .tp_iter = (getiterfunc) cxoSodaDocCursor_getIter,
43 .tp_iternext = (iternextfunc) cxoSodaDocCursor_getNext,
44 .tp_methods = cxoMethods
7745 };
7846
7947
180148 return NULL;
181149 return (PyObject*) doc;
182150 }
183
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
2828 static PyObject *cxoSodaOperation_replaceOne(cxoSodaOperation*, PyObject*);
2929 static PyObject *cxoSodaOperation_replaceOneAndGet(cxoSodaOperation*,
3030 PyObject*);
31 static PyObject *cxoSodaOperation_fetchArraySize(cxoSodaOperation*, PyObject*);
3132
3233
3334 //-----------------------------------------------------------------------------
4950 { "replaceOne", (PyCFunction) cxoSodaOperation_replaceOne, METH_O },
5051 { "replaceOneAndGet", (PyCFunction) cxoSodaOperation_replaceOneAndGet,
5152 METH_O },
53 { "fetchArraySize", (PyCFunction) cxoSodaOperation_fetchArraySize,
54 METH_O },
5255 { NULL }
5356 };
5457
5861 //-----------------------------------------------------------------------------
5962 PyTypeObject cxoPyTypeSodaOperation = {
6063 PyVarObject_HEAD_INIT(NULL, 0)
61 "cx_Oracle.SodaOperation", // tp_name
62 sizeof(cxoSodaOperation), // tp_basicsize
63 0, // tp_itemsize
64 (destructor) cxoSodaOperation_free, // tp_dealloc
65 0, // tp_print
66 0, // tp_getattr
67 0, // tp_setattr
68 0, // tp_compare
69 (reprfunc) cxoSodaOperation_repr, // tp_repr
70 0, // tp_as_number
71 0, // tp_as_sequence
72 0, // tp_as_mapping
73 0, // tp_hash
74 0, // tp_call
75 0, // tp_str
76 0, // tp_getattro
77 0, // tp_setattro
78 0, // tp_as_buffer
79 Py_TPFLAGS_DEFAULT, // tp_flags
80 0, // tp_doc
81 0, // tp_traverse
82 0, // tp_clear
83 0, // tp_richcompare
84 0, // tp_weaklistoffset
85 0, // tp_iter
86 0, // tp_iternext
87 cxoMethods, // tp_methods
88 0, // tp_members
89 0, // tp_getset
90 0, // tp_base
91 0, // tp_dict
92 0, // tp_descr_get
93 0, // tp_descr_set
94 0, // tp_dictoffset
95 0, // tp_init
96 0, // tp_alloc
97 0, // tp_new
98 0, // tp_free
99 0, // tp_is_gc
100 0 // tp_bases
64 .tp_name = "cx_Oracle.SodaOperation",
65 .tp_basicsize = sizeof(cxoSodaOperation),
66 .tp_dealloc = (destructor) cxoSodaOperation_free,
67 .tp_repr = (reprfunc) cxoSodaOperation_repr,
68 .tp_flags = Py_TPFLAGS_DEFAULT,
69 .tp_methods = cxoMethods
10170 };
10271
10372
506475 PyObject *arg)
507476 {
508477 int status, replaced;
509 cxoSodaDoc *doc;
510 uint32_t flags;
511
512 if (cxoConnection_getSodaFlags(op->coll->db->connection, &flags) < 0)
513 return NULL;
514 if (cxoUtils_processSodaDocArg(op->coll->db, arg, &doc) < 0)
478 dpiSodaDoc *handle;
479 uint32_t flags;
480
481 if (cxoConnection_getSodaFlags(op->coll->db->connection, &flags) < 0)
482 return NULL;
483 if (cxoUtils_processSodaDocArg(op->coll->db, arg, &handle) < 0)
515484 return NULL;
516485 Py_BEGIN_ALLOW_THREADS
517486 status = dpiSodaColl_replaceOne(op->coll->handle, &op->options,
518 doc->handle, flags, &replaced, NULL);
519 Py_END_ALLOW_THREADS
520 if (status < 0) {
487 handle, flags, &replaced, NULL);
488 Py_END_ALLOW_THREADS
489 if (status < 0)
521490 cxoError_raiseAndReturnNull();
522 Py_DECREF(doc);
523 return NULL;
524 }
525 Py_DECREF(doc);
491 dpiSodaDoc_release(handle);
492 if (status < 0)
493 return NULL;
526494 if (replaced)
527495 Py_RETURN_TRUE;
528496 Py_RETURN_FALSE;
537505 static PyObject *cxoSodaOperation_replaceOneAndGet(cxoSodaOperation *op,
538506 PyObject *arg)
539507 {
540 dpiSodaDoc *replacedDoc;
541 cxoSodaDoc *doc;
508 dpiSodaDoc *handle, *replacedHandle;
542509 uint32_t flags;
543510 int status;
544511
545512 if (cxoConnection_getSodaFlags(op->coll->db->connection, &flags) < 0)
546513 return NULL;
547 if (cxoUtils_processSodaDocArg(op->coll->db, arg, &doc) < 0)
548 return NULL;
549 Py_BEGIN_ALLOW_THREADS
550 status = dpiSodaColl_replaceOne(op->coll->handle, &op->options,
551 doc->handle, flags, NULL, &replacedDoc);
552 Py_END_ALLOW_THREADS
553 if (status < 0) {
514 if (cxoUtils_processSodaDocArg(op->coll->db, arg, &handle) < 0)
515 return NULL;
516 Py_BEGIN_ALLOW_THREADS
517 status = dpiSodaColl_replaceOne(op->coll->handle, &op->options, handle,
518 flags, NULL, &replacedHandle);
519 Py_END_ALLOW_THREADS
520 if (status < 0)
554521 cxoError_raiseAndReturnNull();
555 Py_DECREF(doc);
556 return NULL;
557 }
558 Py_DECREF(doc);
559 if (replacedDoc)
560 return (PyObject*) cxoSodaDoc_new(op->coll->db, replacedDoc);
522 dpiSodaDoc_release(handle);
523 if (status < 0)
524 return NULL;
525 if (replacedHandle)
526 return (PyObject*) cxoSodaDoc_new(op->coll->db, replacedHandle);
561527 Py_RETURN_NONE;
562528 }
563529
530
531 //-----------------------------------------------------------------------------
532 // cxoSodaOperation_fetchArraySize()
533 // Set the fetch array size to be used for the operation.
534 //-----------------------------------------------------------------------------
535 static PyObject *cxoSodaOperation_fetchArraySize(cxoSodaOperation *op,
536 PyObject *fetchArraySizeObj)
537 {
538 op->options.fetchArraySize = PyLong_AsUnsignedLong(fetchArraySizeObj);
539 if (PyErr_Occurred())
540 return NULL;
541 Py_INCREF(op);
542 return (PyObject*) op;
543 }
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
9393 //-----------------------------------------------------------------------------
9494 PyTypeObject cxoPyTypeSubscr = {
9595 PyVarObject_HEAD_INIT(NULL, 0)
96 "cx_Oracle.Subscription", // tp_name
97 sizeof(cxoSubscr), // tp_basicsize
98 0, // tp_itemsize
99 (destructor) cxoSubscr_free, // tp_dealloc
100 0, // tp_print
101 0, // tp_getattr
102 0, // tp_setattr
103 0, // tp_compare
104 (reprfunc) cxoSubscr_repr, // tp_repr
105 0, // tp_as_number
106 0, // tp_as_sequence
107 0, // tp_as_mapping
108 0, // tp_hash
109 0, // tp_call
110 0, // tp_str
111 0, // tp_getattro
112 0, // tp_setattro
113 0, // tp_as_buffer
114 Py_TPFLAGS_DEFAULT, // tp_flags
115 0, // tp_doc
116 0, // tp_traverse
117 0, // tp_clear
118 0, // tp_richcompare
119 0, // tp_weaklistoffset
120 0, // tp_iter
121 0, // tp_iternext
122 cxoSubscrTypeMethods, // tp_methods
123 cxoSubscrTypeMembers, // tp_members
124 0, // tp_getset
125 0, // tp_base
126 0, // tp_dict
127 0, // tp_descr_get
128 0, // tp_descr_set
129 0, // tp_dictoffset
130 0, // tp_init
131 0, // tp_alloc
132 0, // tp_new
133 0, // tp_free
134 0, // tp_is_gc
135 0 // tp_bases
96 .tp_name = "cx_Oracle.Subscription",
97 .tp_basicsize = sizeof(cxoSubscr),
98 .tp_dealloc = (destructor) cxoSubscr_free,
99 .tp_repr = (reprfunc) cxoSubscr_repr,
100 .tp_flags = Py_TPFLAGS_DEFAULT,
101 .tp_methods = cxoSubscrTypeMethods,
102 .tp_members = cxoSubscrTypeMembers
136103 };
137104
138105 PyTypeObject cxoPyTypeMessage = {
139106 PyVarObject_HEAD_INIT(NULL, 0)
140 "cx_Oracle.Message", // tp_name
141 sizeof(cxoMessage), // tp_basicsize
142 0, // tp_itemsize
143 (destructor) cxoMessage_free, // tp_dealloc
144 0, // tp_print
145 0, // tp_getattr
146 0, // tp_setattr
147 0, // tp_compare
148 0, // tp_repr
149 0, // tp_as_number
150 0, // tp_as_sequence
151 0, // tp_as_mapping
152 0, // tp_hash
153 0, // tp_call
154 0, // tp_str
155 0, // tp_getattro
156 0, // tp_setattro
157 0, // tp_as_buffer
158 Py_TPFLAGS_DEFAULT, // tp_flags
159 0, // tp_doc
160 0, // tp_traverse
161 0, // tp_clear
162 0, // tp_richcompare
163 0, // tp_weaklistoffset
164 0, // tp_iter
165 0, // tp_iternext
166 0, // tp_methods
167 cxoMessageTypeMembers, // tp_members
168 0, // tp_getset
169 0, // tp_base
170 0, // tp_dict
171 0, // tp_descr_get
172 0, // tp_descr_set
173 0, // tp_dictoffset
174 0, // tp_init
175 0, // tp_alloc
176 0, // tp_new
177 0, // tp_free
178 0, // tp_is_gc
179 0 // tp_bases
107 .tp_name = "cx_Oracle.Message",
108 .tp_basicsize = sizeof(cxoMessage),
109 .tp_dealloc = (destructor) cxoMessage_free,
110 .tp_flags = Py_TPFLAGS_DEFAULT,
111 .tp_members = cxoMessageTypeMembers
180112 };
181113
182114 PyTypeObject cxoPyTypeMessageTable = {
183115 PyVarObject_HEAD_INIT(NULL, 0)
184 "cx_Oracle.MessageTable", // tp_name
185 sizeof(cxoMessageTable), // tp_basicsize
186 0, // tp_itemsize
187 (destructor) cxoMessageTable_free, // tp_dealloc
188 0, // tp_print
189 0, // tp_getattr
190 0, // tp_setattr
191 0, // tp_compare
192 0, // tp_repr
193 0, // tp_as_number
194 0, // tp_as_sequence
195 0, // tp_as_mapping
196 0, // tp_hash
197 0, // tp_call
198 0, // tp_str
199 0, // tp_getattro
200 0, // tp_setattro
201 0, // tp_as_buffer
202 Py_TPFLAGS_DEFAULT, // tp_flags
203 0, // tp_doc
204 0, // tp_traverse
205 0, // tp_clear
206 0, // tp_richcompare
207 0, // tp_weaklistoffset
208 0, // tp_iter
209 0, // tp_iternext
210 0, // tp_methods
211 cxoMessageTableTypeMembers, // tp_members
212 0, // tp_getset
213 0, // tp_base
214 0, // tp_dict
215 0, // tp_descr_get
216 0, // tp_descr_set
217 0, // tp_dictoffset
218 0, // tp_init
219 0, // tp_alloc
220 0, // tp_new
221 0, // tp_free
222 0, // tp_is_gc
223 0 // tp_bases
116 .tp_name = "cx_Oracle.MessageTable",
117 .tp_basicsize = sizeof(cxoMessageTable),
118 .tp_dealloc = (destructor) cxoMessageTable_free,
119 .tp_flags = Py_TPFLAGS_DEFAULT,
120 .tp_members = cxoMessageTableTypeMembers
224121 };
225122
226123
227124 PyTypeObject cxoPyTypeMessageRow = {
228125 PyVarObject_HEAD_INIT(NULL, 0)
229 "cx_Oracle.MessageRow", // tp_name
230 sizeof(cxoMessageRow), // tp_basicsize
231 0, // tp_itemsize
232 (destructor) cxoMessageRow_free, // tp_dealloc
233 0, // tp_print
234 0, // tp_getattr
235 0, // tp_setattr
236 0, // tp_compare
237 0, // tp_repr
238 0, // tp_as_number
239 0, // tp_as_sequence
240 0, // tp_as_mapping
241 0, // tp_hash
242 0, // tp_call
243 0, // tp_str
244 0, // tp_getattro
245 0, // tp_setattro
246 0, // tp_as_buffer
247 Py_TPFLAGS_DEFAULT, // tp_flags
248 0, // tp_doc
249 0, // tp_traverse
250 0, // tp_clear
251 0, // tp_richcompare
252 0, // tp_weaklistoffset
253 0, // tp_iter
254 0, // tp_iternext
255 0, // tp_methods
256 cxoMessageRowTypeMembers, // tp_members
257 0, // tp_getset
258 0, // tp_base
259 0, // tp_dict
260 0, // tp_descr_get
261 0, // tp_descr_set
262 0, // tp_dictoffset
263 0, // tp_init
264 0, // tp_alloc
265 0, // tp_new
266 0, // tp_free
267 0, // tp_is_gc
268 0 // tp_bases
126 .tp_name = "cx_Oracle.MessageRow",
127 .tp_basicsize = sizeof(cxoMessageRow),
128 .tp_dealloc = (destructor) cxoMessageRow_free,
129 .tp_flags = Py_TPFLAGS_DEFAULT,
130 .tp_members = cxoMessageRowTypeMembers
269131 };
270132
271133
272134 PyTypeObject cxoPyTypeMessageQuery = {
273135 PyVarObject_HEAD_INIT(NULL, 0)
274 "cx_Oracle.MessageQuery", // tp_name
275 sizeof(cxoMessageQuery), // tp_basicsize
276 0, // tp_itemsize
277 (destructor) cxoMessageQuery_free, // tp_dealloc
278 0, // tp_print
279 0, // tp_getattr
280 0, // tp_setattr
281 0, // tp_compare
282 0, // tp_repr
283 0, // tp_as_number
284 0, // tp_as_sequence
285 0, // tp_as_mapping
286 0, // tp_hash
287 0, // tp_call
288 0, // tp_str
289 0, // tp_getattro
290 0, // tp_setattro
291 0, // tp_as_buffer
292 Py_TPFLAGS_DEFAULT, // tp_flags
293 0, // tp_doc
294 0, // tp_traverse
295 0, // tp_clear
296 0, // tp_richcompare
297 0, // tp_weaklistoffset
298 0, // tp_iter
299 0, // tp_iternext
300 0, // tp_methods
301 cxoMessageQueryTypeMembers, // tp_members
302 0, // tp_getset
303 0, // tp_base
304 0, // tp_dict
305 0, // tp_descr_get
306 0, // tp_descr_set
307 0, // tp_dictoffset
308 0, // tp_init
309 0, // tp_alloc
310 0, // tp_new
311 0, // tp_free
312 0, // tp_is_gc
313 0 // tp_bases
136 .tp_name = "cx_Oracle.MessageQuery",
137 .tp_basicsize = sizeof(cxoMessageQuery),
138 .tp_dealloc = (destructor) cxoMessageQuery_free,
139 .tp_flags = Py_TPFLAGS_DEFAULT,
140 .tp_members = cxoMessageQueryTypeMembers
314141 };
315142
316143
322149 const char *encoding, dpiSubscrMessageRow *row)
323150 {
324151 rowObj->operation = row->operation;
325 rowObj->rowid = cxoPyString_fromEncodedString(row->rowid, row->rowidLength,
326 encoding, NULL);
152 rowObj->rowid = PyUnicode_Decode(row->rowid, row->rowidLength, encoding,
153 NULL);
327154 if (!rowObj->rowid)
328155 return -1;
329156
342169 uint32_t i;
343170
344171 tableObj->operation = table->operation;
345 tableObj->name = cxoPyString_fromEncodedString(table->name,
346 table->nameLength, encoding, NULL);
172 tableObj->name = PyUnicode_Decode(table->name, table->nameLength, encoding,
173 NULL);
347174 tableObj->rows = PyList_New(table->numRows);
348175 if (!tableObj->rows)
349176 return -1;
407234 encoding = subscription->connection->encodingInfo.encoding;
408235 messageObj->type = message->eventType;
409236 messageObj->registered = message->registered;
410 messageObj->dbname = cxoPyString_fromEncodedString(message->dbName,
237 messageObj->dbname = PyUnicode_Decode(message->dbName,
411238 message->dbNameLength, encoding, NULL);
412239 if (!messageObj->dbname)
413240 return -1;
418245 return -1;
419246 }
420247 if (message->queueName) {
421 messageObj->queueName = cxoPyString_fromEncodedString(
422 message->queueName, message->queueNameLength, encoding, NULL);
248 messageObj->queueName = PyUnicode_Decode(message->queueName,
249 message->queueNameLength, encoding, NULL);
423250 if (!messageObj->queueName)
424251 return -1;
425252 }
426253 if (message->consumerName) {
427 messageObj->consumerName = cxoPyString_fromEncodedString(
428 message->consumerName, message->consumerNameLength, encoding,
429 NULL);
254 messageObj->consumerName = PyUnicode_Decode(message->consumerName,
255 message->consumerNameLength, encoding, NULL);
430256 if (!messageObj->consumerName)
431257 return -1;
432258 }
541367 }
542368 Py_CLEAR(subscr->connection);
543369 Py_CLEAR(subscr->callback);
370 Py_CLEAR(subscr->name);
371 Py_CLEAR(subscr->ipAddress);
544372 Py_TYPE(subscr)->tp_free((PyObject*) subscr);
545373 }
546374
646474 return NULL;
647475 }
648476 Py_DECREF(cursor);
649 return PyInt_FromLong((long) queryId);
477 return PyLong_FromLong((long) queryId);
650478 }
651479
652480 Py_DECREF(cursor);
662490 {
663491 Py_CLEAR(message->subscription);
664492 Py_CLEAR(message->dbname);
493 Py_CLEAR(message->txId);
665494 Py_CLEAR(message->tables);
666495 Py_CLEAR(message->queries);
667496 Py_CLEAR(message->queueName);
671500
672501
673502 //-----------------------------------------------------------------------------
503 // cxoMessageQuery_free()
504 // Free the memory associated with a query in a message.
505 //-----------------------------------------------------------------------------
506 static void cxoMessageQuery_free(cxoMessageQuery *query)
507 {
508 Py_CLEAR(query->tables);
509 Py_TYPE(query)->tp_free((PyObject*) query);
510 }
511
512
513 //-----------------------------------------------------------------------------
514 // cxoMessageRow_free()
515 // Free the memory associated with a row in a message.
516 //-----------------------------------------------------------------------------
517 static void cxoMessageRow_free(cxoMessageRow *row)
518 {
519 Py_CLEAR(row->rowid);
520 Py_TYPE(row)->tp_free((PyObject*) row);
521 }
522
523
524 //-----------------------------------------------------------------------------
674525 // cxoMessageTable_free()
675526 // Free the memory associated with a table in a message.
676527 //-----------------------------------------------------------------------------
680531 Py_CLEAR(table->rows);
681532 Py_TYPE(table)->tp_free((PyObject*) table);
682533 }
683
684
685 //-----------------------------------------------------------------------------
686 // cxoMessageRow_free()
687 // Free the memory associated with a row in a message.
688 //-----------------------------------------------------------------------------
689 static void cxoMessageRow_free(cxoMessageRow *row)
690 {
691 Py_CLEAR(row->rowid);
692 Py_TYPE(row)->tp_free((PyObject*) row);
693 }
694
695
696 //-----------------------------------------------------------------------------
697 // cxoMessageQuery_free()
698 // Free the memory associated with a query in a message.
699 //-----------------------------------------------------------------------------
700 static void cxoMessageQuery_free(cxoMessageQuery *query)
701 {
702 Py_CLEAR(query->tables);
703 Py_TYPE(query)->tp_free((PyObject*) query);
704 }
705
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22 //-----------------------------------------------------------------------------
33
44 //-----------------------------------------------------------------------------
2222 #ifndef PyDateTime_DELTA_GET_MICROSECONDS
2323 #define PyDateTime_DELTA_GET_MICROSECONDS(x) ((x)->microseconds)
2424 #endif
25
26 // forward declarations
27 static Py_ssize_t cxoTransform_calculateSize(PyObject *value,
28 cxoTransformNum transformNum);
29 static cxoTransformNum cxoTransform_getNumFromPythonType(PyTypeObject *type);
30
2531
2632 //-----------------------------------------------------------------------------
2733 // Types
174180 CXO_TRANSFORM_TIMESTAMP_LTZ,
175181 DPI_ORACLE_TYPE_TIMESTAMP_LTZ,
176182 DPI_NATIVE_TYPE_TIMESTAMP
183 },
184 {
185 CXO_TRANSFORM_TIMESTAMP_TZ,
186 DPI_ORACLE_TYPE_TIMESTAMP_TZ,
187 DPI_NATIVE_TYPE_TIMESTAMP
177188 }
178189 };
190
191
192 //-----------------------------------------------------------------------------
193 // cxoTransform_calculateSize()
194 // Calculate the size to use with the specified transform and Python value.
195 // This function is only called by cxoTransform_getNumFromValue() and no
196 // attempt is made to verify the value further.
197 //-----------------------------------------------------------------------------
198 static Py_ssize_t cxoTransform_calculateSize(PyObject *value,
199 cxoTransformNum transformNum)
200 {
201 switch (transformNum) {
202 case CXO_TRANSFORM_NONE:
203 return 1;
204 case CXO_TRANSFORM_BINARY:
205 return PyBytes_GET_SIZE(value);
206 case CXO_TRANSFORM_NSTRING:
207 case CXO_TRANSFORM_STRING:
208 return PyUnicode_GET_SIZE(value);
209 default:
210 break;
211 }
212 return 0;
213 }
179214
180215
181216 //-----------------------------------------------------------------------------
192227 // cxoTransform_fromPython()
193228 // Transforms a Python object into its corresponding database value.
194229 //-----------------------------------------------------------------------------
195 int cxoTransform_fromPython(cxoTransformNum transformNum, PyObject *pyValue,
230 int cxoTransform_fromPython(cxoTransformNum transformNum,
231 dpiNativeTypeNum *nativeTypeNum, PyObject *pyValue,
196232 dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding,
197233 const char *nencoding, cxoVar *var, uint32_t arrayPos)
198234 {
206242
207243 switch (transformNum) {
208244 case CXO_TRANSFORM_BOOLEAN:
209 dbValue->asBoolean = (pyValue == Py_True);
245 dbValue->asBoolean = PyObject_IsTrue(pyValue);
246 if (PyErr_Occurred())
247 return -1;
210248 return 0;
211249 case CXO_TRANSFORM_BINARY:
212250 case CXO_TRANSFORM_FIXED_CHAR:
241279 encoding = nencoding;
242280 if (cxoBuffer_fromObject(buffer, pyValue, encoding) < 0)
243281 return -1;
244 Py_BEGIN_ALLOW_THREADS
245 status = dpiLob_setFromBytes(dbValue->asLOB, buffer->ptr,
246 buffer->size);
247 Py_END_ALLOW_THREADS
248 return status;
282 if (var) {
283 Py_BEGIN_ALLOW_THREADS
284 status = dpiLob_setFromBytes(dbValue->asLOB, buffer->ptr,
285 buffer->size);
286 Py_END_ALLOW_THREADS
287 if (status < 0)
288 return cxoError_raiseAndReturnInt();
289 } else {
290 *nativeTypeNum = DPI_NATIVE_TYPE_BYTES;
291 dbValue->asBytes.ptr = (char*) buffer->ptr;
292 dbValue->asBytes.length = buffer->size;
293 }
294 return 0;
249295 case CXO_TRANSFORM_NATIVE_INT:
250 #if PY_MAJOR_VERSION < 3
251 if (PyInt_Check(pyValue)) {
252 dbValue->asInt64 = PyInt_AS_LONG(pyValue);
253 return 0;
254 }
255 #endif
256296 if (PyBool_Check(pyValue)) {
257297 dbValue->asInt64 = (pyValue == Py_True);
258298 return 0;
264304 case CXO_TRANSFORM_INT:
265305 case CXO_TRANSFORM_DECIMAL:
266306 case CXO_TRANSFORM_FLOAT:
267 if (!PyFloat_Check(pyValue) &&
268 #if PY_MAJOR_VERSION < 3
269 !PyInt_Check(pyValue) &&
270 #endif
271 !PyLong_Check(pyValue) &&
272 !PyObject_TypeCheck(pyValue, cxoPyTypeDecimal)) {
273 PyErr_SetString(PyExc_TypeError, "expecting number");
274 return -1;
275 }
276 textValue = PyObject_Str(pyValue);
277 if (!textValue)
278 return -1;
279 status = cxoBuffer_fromObject(buffer, textValue, encoding);
280 Py_DECREF(textValue);
281 if (status < 0)
282 return -1;
307 if (PyBool_Check(pyValue)) {
308 buffer->ptr = (pyValue == Py_True) ? "1" : "0";
309 buffer->size = 1;
310 buffer->numCharacters = 1;
311 } else {
312 if (!PyFloat_Check(pyValue) &&
313 !PyLong_Check(pyValue) &&
314 !PyObject_TypeCheck(pyValue, cxoPyTypeDecimal)) {
315 PyErr_SetString(PyExc_TypeError, "expecting number");
316 return -1;
317 }
318 textValue = PyObject_Str(pyValue);
319 if (!textValue)
320 return -1;
321 status = cxoBuffer_fromObject(buffer, textValue, encoding);
322 Py_DECREF(textValue);
323 if (status < 0)
324 return -1;
325 }
283326 dbValue->asBytes.ptr = (char*) buffer->ptr;
284327 dbValue->asBytes.length = buffer->size;
285328 return 0;
286329 case CXO_TRANSFORM_NATIVE_DOUBLE:
287330 case CXO_TRANSFORM_NATIVE_FLOAT:
288331 if (!PyFloat_Check(pyValue) &&
289 #if PY_MAJOR_VERSION < 3
290 !PyInt_Check(pyValue) &&
291 #endif
292332 !PyObject_TypeCheck(pyValue, cxoPyTypeDecimal) &&
293333 !PyLong_Check(pyValue)) {
294334 PyErr_SetString(PyExc_TypeError, "expecting float");
316356 case CXO_TRANSFORM_DATETIME:
317357 case CXO_TRANSFORM_TIMESTAMP:
318358 case CXO_TRANSFORM_TIMESTAMP_LTZ:
359 case CXO_TRANSFORM_TIMESTAMP_TZ:
319360 if (PyDateTime_Check(pyValue)) {
320361 memset(&dbValue->asTimestamp, 0, sizeof(dbValue->asTimestamp));
321362 dbValue->asTimestamp.year = PyDateTime_GET_YEAR(pyValue);
361402 cxoError_raiseFromString(cxoNotSupportedErrorException,
362403 "Python value cannot be converted to a database value");
363404 return -1;
405 }
406
407
408 //-----------------------------------------------------------------------------
409 // cxoTransform_getDefaultSize()
410 // Return the default size for the specified transform.
411 //-----------------------------------------------------------------------------
412 uint32_t cxoTransform_getDefaultSize(cxoTransformNum transformNum)
413 {
414 switch (transformNum) {
415 case CXO_TRANSFORM_NONE:
416 return 1;
417 case CXO_TRANSFORM_BINARY:
418 case CXO_TRANSFORM_NSTRING:
419 case CXO_TRANSFORM_STRING:
420 return 4000;
421 case CXO_TRANSFORM_DECIMAL:
422 case CXO_TRANSFORM_FLOAT:
423 case CXO_TRANSFORM_INT:
424 return 1000;
425 case CXO_TRANSFORM_FIXED_CHAR:
426 case CXO_TRANSFORM_FIXED_NCHAR:
427 return 2000;
428 case CXO_TRANSFORM_LONG_BINARY:
429 case CXO_TRANSFORM_LONG_STRING:
430 return 128 * 1024;
431 default:
432 break;
433 }
434
435 return 0;
364436 }
365437
366438
399471 case DPI_ORACLE_TYPE_TIMESTAMP:
400472 return CXO_TRANSFORM_TIMESTAMP;
401473 case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
474 return CXO_TRANSFORM_TIMESTAMP_TZ;
402475 case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
403476 return CXO_TRANSFORM_TIMESTAMP_LTZ;
404477 case DPI_ORACLE_TYPE_INTERVAL_DS:
429502
430503
431504 //-----------------------------------------------------------------------------
432 // cxoTransform_getNumFromType()
505 // cxoTransform_getNumFromPythonType()
433506 // Get the appropriate transformation to use for the specified Python type.
434507 //-----------------------------------------------------------------------------
435 cxoTransformNum cxoTransform_getNumFromType(PyTypeObject *type)
436 {
437 if (type == &cxoPyTypeString)
508 static cxoTransformNum cxoTransform_getNumFromPythonType(PyTypeObject *type)
509 {
510 if (type == &PyUnicode_Type)
438511 return CXO_TRANSFORM_STRING;
439 if (type == &cxoPyTypeStringVar)
440 return CXO_TRANSFORM_STRING;
441 if (type == &cxoPyTypeFixedCharVar)
442 return CXO_TRANSFORM_FIXED_CHAR;
443 if (type == &cxoPyTypeNcharVar)
444 return CXO_TRANSFORM_NSTRING;
445 if (type == &cxoPyTypeFixedNcharVar)
446 return CXO_TRANSFORM_FIXED_NCHAR;
447 if (type == &cxoPyTypeRowidVar)
448 return CXO_TRANSFORM_ROWID;
449 #if PY_MAJOR_VERSION < 3
450 if (type == &PyUnicode_Type)
451 return CXO_TRANSFORM_NSTRING;
452 if (type == &PyInt_Type)
453 return CXO_TRANSFORM_INT;
454 #endif
455 if (type == &cxoPyTypeBinary)
456 return CXO_TRANSFORM_BINARY;
457 if (type == &cxoPyTypeBinaryVar)
512 if (type == &PyBytes_Type)
458513 return CXO_TRANSFORM_BINARY;
459514 if (type == &PyFloat_Type)
460515 return CXO_TRANSFORM_FLOAT;
462517 return CXO_TRANSFORM_INT;
463518 if (type == cxoPyTypeDecimal)
464519 return CXO_TRANSFORM_DECIMAL;
465 if (type == &cxoPyTypeNumberVar)
466 return CXO_TRANSFORM_FLOAT;
467 if (type == &cxoPyTypeNativeFloatVar)
468 return CXO_TRANSFORM_NATIVE_DOUBLE;
469 if (type == &cxoPyTypeNativeIntVar)
470 return CXO_TRANSFORM_NATIVE_INT;
471520 if (type == &PyBool_Type)
472 return CXO_TRANSFORM_BOOLEAN;
473 if (type == &cxoPyTypeBooleanVar)
474521 return CXO_TRANSFORM_BOOLEAN;
475522 if (type == PyDateTimeAPI->DateType)
476523 return CXO_TRANSFORM_DATE;
477524 if (type == PyDateTimeAPI->DateTimeType)
478525 return CXO_TRANSFORM_DATETIME;
479 if (type == &cxoPyTypeDateTimeVar)
480 return CXO_TRANSFORM_DATETIME;
481 if (type == &cxoPyTypeTimestampVar)
482 return CXO_TRANSFORM_TIMESTAMP;
483526 if (type == PyDateTimeAPI->DeltaType)
484527 return CXO_TRANSFORM_TIMEDELTA;
485 if (type == &cxoPyTypeIntervalVar)
486 return CXO_TRANSFORM_TIMEDELTA;
487 if (type == &cxoPyTypeObject)
488 return CXO_TRANSFORM_OBJECT;
489 if (type == &cxoPyTypeObjectVar)
490 return CXO_TRANSFORM_OBJECT;
491 if (type == &cxoPyTypeClobVar)
492 return CXO_TRANSFORM_CLOB;
493 if (type == &cxoPyTypeNclobVar)
494 return CXO_TRANSFORM_NCLOB;
495 if (type == &cxoPyTypeBlobVar)
496 return CXO_TRANSFORM_BLOB;
497 if (type == &cxoPyTypeBfileVar)
498 return CXO_TRANSFORM_BFILE;
499 if (type == &cxoPyTypeCursorVar)
500 return CXO_TRANSFORM_CURSOR;
501 if (type == &cxoPyTypeLongStringVar)
502 return CXO_TRANSFORM_LONG_STRING;
503 if (type == &cxoPyTypeLongBinaryVar)
504 return CXO_TRANSFORM_LONG_BINARY;
505528
506529 return CXO_TRANSFORM_UNSUPPORTED;
507530 }
508531
509532
510533 //-----------------------------------------------------------------------------
511 // cxoTransform_getNumFromValue()
512 // Get the appropriate transformation to use for the specified Python object.
513 //-----------------------------------------------------------------------------
514 cxoTransformNum cxoTransform_getNumFromValue(PyObject *value, int plsql)
534 // cxoTransform_getNumFromPythonValue()
535 // Get the appropriate transformation to use for the specified Python value.
536 //-----------------------------------------------------------------------------
537 cxoTransformNum cxoTransform_getNumFromPythonValue(PyObject *value, int plsql)
515538 {
516539 cxoLob *lob;
517540
522545 return CXO_TRANSFORM_NATIVE_INT;
523546 return CXO_TRANSFORM_BOOLEAN;
524547 }
525 #if PY_MAJOR_VERSION >= 3
526548 if (PyUnicode_Check(value))
527549 return CXO_TRANSFORM_STRING;
528550 if (PyBytes_Check(value))
529551 return CXO_TRANSFORM_BINARY;
530 #else
531 if (PyUnicode_Check(value))
532 return CXO_TRANSFORM_NSTRING;
533 if (PyString_Check(value))
534 return CXO_TRANSFORM_STRING;
535 if (PyBuffer_Check(value))
536 return CXO_TRANSFORM_BINARY;
537 if (PyInt_Check(value))
538 return CXO_TRANSFORM_INT;
539 #endif
540552 if (PyLong_Check(value))
541553 return CXO_TRANSFORM_INT;
542554 if (PyFloat_Check(value))
555567 return CXO_TRANSFORM_OBJECT;
556568 if (PyObject_TypeCheck(value, &cxoPyTypeLob)) {
557569 lob = (cxoLob*) value;
558 if (lob->oracleTypeNum == DPI_ORACLE_TYPE_CLOB)
559 return CXO_TRANSFORM_CLOB;
560 if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
561 return CXO_TRANSFORM_NCLOB;
562 if (lob->oracleTypeNum == DPI_ORACLE_TYPE_BLOB)
563 return CXO_TRANSFORM_BLOB;
564 if (lob->oracleTypeNum == DPI_ORACLE_TYPE_BFILE)
565 return CXO_TRANSFORM_BFILE;
570 return lob->dbType->defaultTransformNum;
566571 }
567572 return CXO_TRANSFORM_UNSUPPORTED;
573 }
574
575
576 //-----------------------------------------------------------------------------
577 // cxoTransform_getNumFromType()
578 // Get the appropriate transformation to use for the specified type. This
579 // can be either a database type constant defined at the module level or a
580 // Python type.
581 //-----------------------------------------------------------------------------
582 int cxoTransform_getNumFromType(PyObject *type, cxoTransformNum *transformNum,
583 cxoObjectType **objType)
584 {
585 PyTypeObject *pyType;
586 cxoApiType *apiType;
587 cxoDbType *dbType;
588 char message[250];
589 int status;
590
591 // check to see if a database type constant has been specified
592 status = PyObject_IsInstance(type, (PyObject*) &cxoPyTypeDbType);
593 if (status < 0)
594 return -1;
595 if (status == 1) {
596 dbType = (cxoDbType*) type;
597 *transformNum = dbType->defaultTransformNum;
598 *objType = NULL;
599 return 0;
600 }
601
602 // check to see if a DB API type constant has been specified
603 status = PyObject_IsInstance(type, (PyObject*) &cxoPyTypeApiType);
604 if (status < 0)
605 return -1;
606 if (status == 1) {
607 apiType = (cxoApiType*) type;
608 *transformNum = apiType->defaultTransformNum;
609 *objType = NULL;
610 return 0;
611 }
612
613 // check to see if an object type has been specified
614 if (Py_TYPE(type) == &cxoPyTypeObjectType) {
615 *transformNum = CXO_TRANSFORM_OBJECT;
616 *objType = (cxoObjectType*) type;
617 return 0;
618 }
619
620 // check to see if a Python type has been specified
621 if (Py_TYPE(type) != &PyType_Type) {
622 PyErr_SetString(PyExc_TypeError, "expecting type");
623 return -1;
624 }
625
626 // check to see if the Python type is a supported type
627 pyType = (PyTypeObject*) type;
628 *objType = NULL;
629 *transformNum = cxoTransform_getNumFromPythonType(pyType);
630 if (*transformNum != CXO_TRANSFORM_UNSUPPORTED)
631 return 0;
632
633 // no valid type specified
634 snprintf(message, sizeof(message), "Python type %s not supported.",
635 pyType->tp_name);
636 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
637 return -1;
638 }
639
640
641 //-----------------------------------------------------------------------------
642 // cxoTransform_getNumFromValue()
643 // Get the appropriate transformation to use for the specified value. If the
644 // value is an array, determine the transformation that can be used for all of
645 // the elements in that array.
646 //-----------------------------------------------------------------------------
647 int cxoTransform_getNumFromValue(PyObject *value, int *isArray,
648 Py_ssize_t *size, Py_ssize_t *numElements, int plsql,
649 cxoTransformNum *transformNum)
650 {
651 cxoTransformNum tempTransformNum;
652 PyObject *elementValue;
653 Py_ssize_t i, tempSize;
654 char message[250];
655
656 // initialization (except numElements which always has a valid value and is
657 // only overridden when a an array is encountered)
658 *size = 0;
659 *isArray = 0;
660
661 // handle arrays
662 if (PyList_Check(value)) {
663 *transformNum = CXO_TRANSFORM_NONE;
664 for (i = 0; i < PyList_GET_SIZE(value); i++) {
665 elementValue = PyList_GET_ITEM(value, i);
666 tempTransformNum = cxoTransform_getNumFromPythonValue(elementValue,
667 1);
668 if (tempTransformNum == CXO_TRANSFORM_UNSUPPORTED) {
669 snprintf(message, sizeof(message),
670 "element %u value of type %s is not supported",
671 (unsigned) i, Py_TYPE(value)->tp_name);
672 cxoError_raiseFromString(cxoNotSupportedErrorException,
673 message);
674 return -1;
675 } else if (*transformNum == CXO_TRANSFORM_NONE) {
676 *transformNum = tempTransformNum;
677 } else if (*transformNum != tempTransformNum) {
678 snprintf(message, sizeof(message),
679 "element %u value is not the same type as previous "
680 "elements", (unsigned) i);
681 cxoError_raiseFromString(cxoNotSupportedErrorException,
682 message);
683 return -1;
684 }
685 tempSize = cxoTransform_calculateSize(elementValue, *transformNum);
686 if (tempSize > *size)
687 *size = tempSize;
688 }
689 *isArray = 1;
690 *numElements = PyList_GET_SIZE(value);
691 return 0;
692 }
693
694 // handle scalar values
695 *transformNum = cxoTransform_getNumFromPythonValue(value, plsql);
696 if (*transformNum == CXO_TRANSFORM_UNSUPPORTED) {
697 snprintf(message, sizeof(message),
698 "Python value of type %s not supported.",
699 Py_TYPE(value)->tp_name);
700 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
701 return -1;
702 }
703 *size = cxoTransform_calculateSize(value, *transformNum);
704 return 0;
568705 }
569706
570707
631768 cxoConnection *connection, cxoObjectType *objType,
632769 dpiDataBuffer *dbValue, const char *encodingErrors)
633770 {
634 const cxoTransform *transform;
635771 PyObject *stringObj, *result;
636772 dpiIntervalDS *intervalDS;
637773 dpiTimestamp *timestamp;
638774 uint32_t rowidLength;
775 cxoDbType *dbType;
639776 const char *rowid;
640777 cxoCursor *cursor;
641778 dpiBytes *bytes;
642779 int32_t seconds;
643780
644 transform = &cxoAllTransforms[transformNum];
645781 switch (transformNum) {
646782 case CXO_TRANSFORM_BINARY:
647783 case CXO_TRANSFORM_LONG_BINARY:
651787 case CXO_TRANSFORM_BLOB:
652788 case CXO_TRANSFORM_CLOB:
653789 case CXO_TRANSFORM_NCLOB:
654 return cxoLob_new(connection, transform->oracleTypeNum,
655 dbValue->asLOB);
790 dbType = cxoDbType_fromTransformNum(transformNum);
791 return cxoLob_new(connection, dbType, dbValue->asLOB);
656792 case CXO_TRANSFORM_BOOLEAN:
657793 if (dbValue->asBoolean)
658794 Py_RETURN_TRUE;
673809 case CXO_TRANSFORM_DATETIME:
674810 case CXO_TRANSFORM_TIMESTAMP:
675811 case CXO_TRANSFORM_TIMESTAMP_LTZ:
812 case CXO_TRANSFORM_TIMESTAMP_TZ:
676813 timestamp = &dbValue->asTimestamp;
677 #if PY_MAJOR_VERSION < 3
678 if (timestamp->year < 1 || timestamp->year > 9999)
679 return PyErr_Format(PyExc_ValueError,
680 "year %d is out of range", timestamp->year);
681 #endif
682814 return PyDateTime_FromDateAndTime(timestamp->year,
683815 timestamp->month, timestamp->day, timestamp->hour,
684816 timestamp->minute, timestamp->second,
685817 timestamp->fsecond / 1000);
818 case CXO_TRANSFORM_FIXED_CHAR:
686819 case CXO_TRANSFORM_FIXED_NCHAR:
820 case CXO_TRANSFORM_LONG_STRING:
687821 case CXO_TRANSFORM_NSTRING:
822 case CXO_TRANSFORM_STRING:
688823 bytes = &dbValue->asBytes;
689824 return PyUnicode_Decode(bytes->ptr, bytes->length, bytes->encoding,
690825 encodingErrors);
693828 case CXO_TRANSFORM_NATIVE_FLOAT:
694829 return PyFloat_FromDouble(dbValue->asFloat);
695830 case CXO_TRANSFORM_NATIVE_INT:
696 #if PY_MAJOR_VERSION < 3
697 if (sizeof(long) == 8 || (dbValue->asInt64 <= INT_MAX &&
698 dbValue->asInt64 >= -INT_MAX))
699 return PyInt_FromLong((long) dbValue->asInt64);
700 #endif
701831 return PyLong_FromLongLong(dbValue->asInt64);
702832 case CXO_TRANSFORM_DECIMAL:
703833 case CXO_TRANSFORM_INT:
704834 case CXO_TRANSFORM_FLOAT:
705835 bytes = &dbValue->asBytes;
706 stringObj = cxoPyString_fromEncodedString(bytes->ptr,
707 bytes->length, bytes->encoding, encodingErrors);
836 stringObj = PyUnicode_Decode(bytes->ptr, bytes->length,
837 bytes->encoding, encodingErrors);
708838 if (!stringObj)
709839 return NULL;
710840 if (transformNum == CXO_TRANSFORM_INT &&
711841 memchr(bytes->ptr, '.', bytes->length) == NULL) {
712 #if PY_MAJOR_VERSION >= 3
713842 result = PyNumber_Long(stringObj);
714 #else
715 result = PyNumber_Int(stringObj);
716 #endif
717 Py_DECREF(stringObj);
718 return result;
719 } else if (transformNum != CXO_TRANSFORM_DECIMAL &&
720 bytes->length <= 15) {
843 } else if (transformNum == CXO_TRANSFORM_DECIMAL) {
844 result = PyObject_CallFunctionObjArgs(
845 (PyObject*) cxoPyTypeDecimal, stringObj, NULL);
846 } else {
721847 result = PyNumber_Float(stringObj);
722 Py_DECREF(stringObj);
723 return result;
724 }
725 result = PyObject_CallFunctionObjArgs(
726 (PyObject*) cxoPyTypeDecimal, stringObj, NULL);
848 }
727849 Py_DECREF(stringObj);
728850 return result;
729851 case CXO_TRANSFORM_OBJECT:
732854 if (dpiRowid_getStringValue(dbValue->asRowid, &rowid,
733855 &rowidLength) < 0)
734856 return cxoError_raiseAndReturnNull();
735 return cxoPyString_fromEncodedString(rowid, rowidLength,
857 return PyUnicode_Decode(rowid, rowidLength,
736858 connection->encodingInfo.encoding, NULL);
737 case CXO_TRANSFORM_FIXED_CHAR:
738 case CXO_TRANSFORM_STRING:
739 case CXO_TRANSFORM_LONG_STRING:
740 bytes = &dbValue->asBytes;
741 return cxoPyString_fromEncodedString(bytes->ptr, bytes->length,
742 bytes->encoding, encodingErrors);
743859 case CXO_TRANSFORM_TIMEDELTA:
744860 intervalDS = &dbValue->asIntervalDS;
745861 seconds = intervalDS->hours * 60 * 60 + intervalDS->minutes * 60 +
753869 return cxoError_raiseFromString(cxoNotSupportedErrorException,
754870 "Database value cannot be converted to a Python value");
755871 }
756
2424 return NULL;
2525
2626 // convert string format to Python object
27 #if PY_MAJOR_VERSION >= 3
2827 formatObj = PyUnicode_DecodeASCII(format, strlen(format), NULL);
29 #else
30 formatObj = PyString_FromString(format);
31 #endif
3228 if (!formatObj) {
3329 Py_DECREF(args);
3430 return NULL;
3531 }
3632
3733 // create formatted result
38 #if PY_MAJOR_VERSION >= 3
3934 result = PyUnicode_Format(formatObj, args);
40 #else
41 result = PyString_Format(formatObj, args);
42 #endif
4335 Py_DECREF(args);
4436 Py_DECREF(formatObj);
4537 return result;
113105 // work as expected. It also has the additional benefit of reducing the number
114106 // of errors that can take place when the module is imported.
115107 //-----------------------------------------------------------------------------
116 int cxoUtils_initializeDPI(void)
117 {
108 int cxoUtils_initializeDPI(dpiContextCreateParams *params)
109 {
110 dpiContextCreateParams localParams;
118111 dpiErrorInfo errorInfo;
119112 dpiContext *context;
120113
121 if (!cxoDpiContext) {
122 if (dpiContext_create(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
123 &context, &errorInfo) < 0)
124 return cxoError_raiseFromInfo(&errorInfo);
125 if (dpiContext_getClientVersion(context, &cxoClientVersionInfo) < 0)
126 return cxoError_raiseAndReturnInt();
127 cxoDpiContext = context;
128 }
129
114 // if already initialized and parameters were passed, raise an exception;
115 // otherwise do nothing as this is implicitly called when creating a
116 // standalone connection or session pool and when getting the Oracle Client
117 // library version
118 if (cxoDpiContext) {
119 if (!params)
120 return 0;
121 cxoError_raiseFromString(cxoProgrammingErrorException,
122 "Oracle Client library has already been initialized");
123 return -1;
124 }
125
126 // set up parameters used for initializing ODPI-C
127 if (params) {
128 memcpy(&localParams, params, sizeof(dpiContextCreateParams));
129 } else {
130 memset(&localParams, 0, sizeof(dpiContextCreateParams));
131 }
132 localParams.defaultEncoding = "UTF-8";
133 if (!localParams.defaultDriverName)
134 localParams.defaultDriverName = CXO_DRIVER_NAME;
135 if (!localParams.loadErrorUrl)
136 localParams.loadErrorUrl = "https://cx-oracle.readthedocs.io/en/"
137 "latest/user_guide/installation.html";
138
139 // create ODPI-C context with the specified parameters
140 if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION,
141 &localParams, &context, &errorInfo) < 0)
142 return cxoError_raiseFromInfo(&errorInfo);
143 if (dpiContext_getClientVersion(context, &cxoClientVersionInfo) < 0) {
144 cxoError_raiseAndReturnInt();
145 dpiContext_destroy(context);
146 return -1;
147 }
148
149 cxoDpiContext = context;
130150 return 0;
131151 }
132152
164184 // a key or media type specified.
165185 //-----------------------------------------------------------------------------
166186 int cxoUtils_processSodaDocArg(cxoSodaDatabase *db, PyObject *arg,
167 cxoSodaDoc **doc)
168 {
169 dpiSodaDoc *handle;
187 dpiSodaDoc **handle)
188 {
170189 cxoBuffer buffer;
190 cxoSodaDoc *doc;
171191
172192 if (PyObject_TypeCheck(arg, &cxoPyTypeSodaDoc)) {
173 Py_INCREF(arg);
174 *doc = (cxoSodaDoc*) arg;
193 doc = (cxoSodaDoc*) arg;
194 if (dpiSodaDoc_addRef(doc->handle) < 0)
195 return cxoError_raiseAndReturnInt();
196 *handle = doc->handle;
175197 } else if (PyDict_Check(arg) || PyList_Check(arg)) {
176198 arg = PyObject_CallFunctionObjArgs(cxoJsonDumpFunction, arg, NULL);
177199 if (!arg)
182204 }
183205 Py_DECREF(arg);
184206 if (dpiSodaDb_createDocument(db->handle, NULL, 0, buffer.ptr,
185 buffer.size, NULL, 0, DPI_SODA_FLAGS_DEFAULT, &handle) < 0) {
186 cxoError_raiseAndReturnNull();
207 buffer.size, NULL, 0, DPI_SODA_FLAGS_DEFAULT, handle) < 0) {
187208 cxoBuffer_clear(&buffer);
188 return -1;
209 return cxoError_raiseAndReturnInt();
189210 }
190211 cxoBuffer_clear(&buffer);
191 *doc = cxoSodaDoc_new(db, handle);
192 if (!*doc)
193 return -1;
194212 } else {
195213 PyErr_SetString(PyExc_TypeError,
196 "value must be a SODA document or dictionary");
197 return -1;
198 }
199
200 return 0;
201 }
202
214 "value must be a SODA document or a dictionary or list");
215 return -1;
216 }
217
218 return 0;
219 }
00 //-----------------------------------------------------------------------------
1 // Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
1 // Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 //
33 // Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 //
1414 #include "cxoModule.h"
1515
1616 //-----------------------------------------------------------------------------
17 // Declaration of common variable functions.
17 // forward declaration of functions
1818 //-----------------------------------------------------------------------------
1919 static void cxoVar_free(cxoVar*);
2020 static PyObject *cxoVar_repr(cxoVar*);
2323 static PyObject *cxoVar_externalGetValue(cxoVar*, PyObject*, PyObject*);
2424 static PyObject *cxoVar_externalGetActualElements(cxoVar*, void*);
2525 static PyObject *cxoVar_externalGetValues(cxoVar*, void*);
26
27
28 //-----------------------------------------------------------------------------
29 // declaration of members for variables
30 //-----------------------------------------------------------------------------
31 static PyMemberDef cxoVarMembers[] = {
26 static PyObject *cxoVar_getType(cxoVar*, void*);
27
28
29 //-----------------------------------------------------------------------------
30 // declaration of members
31 //-----------------------------------------------------------------------------
32 static PyMemberDef cxoMembers[] = {
3233 { "bufferSize", T_INT, offsetof(cxoVar, bufferSize), READONLY },
3334 { "inconverter", T_OBJECT, offsetof(cxoVar, inConverter), 0 },
3435 { "numElements", T_INT, offsetof(cxoVar, allocatedElements),
3536 READONLY },
3637 { "outconverter", T_OBJECT, offsetof(cxoVar, outConverter), 0 },
3738 { "size", T_INT, offsetof(cxoVar, size), READONLY },
38 { "type", T_OBJECT, offsetof(cxoVar, objectType), READONLY },
3939 { NULL }
4040 };
4141
4242
4343 //-----------------------------------------------------------------------------
44 // declaration of calculated members for variables
45 //-----------------------------------------------------------------------------
46 static PyGetSetDef cxoVarCalcMembers[] = {
44 // declaration of calculated members
45 //-----------------------------------------------------------------------------
46 static PyGetSetDef cxoCalcMembers[] = {
4747 { "actualElements", (getter) cxoVar_externalGetActualElements, 0, 0, 0 },
48 { "type", (getter) cxoVar_getType, 0, 0, 0 },
4849 { "values", (getter) cxoVar_externalGetValues, 0, 0, 0 },
4950 { NULL }
5051 };
5152
5253
5354 //-----------------------------------------------------------------------------
54 // declaration of methods for variables
55 // declaration of methods
5556 //-----------------------------------------------------------------------------
5657 static PyMethodDef cxoVarMethods[] = {
5758 { "copy", (PyCFunction) cxoVar_externalCopy, METH_VARARGS },
6364
6465
6566 //-----------------------------------------------------------------------------
66 // declaration of all variable types
67 //-----------------------------------------------------------------------------
68 #define DECLARE_VARIABLE_TYPE(INTERNAL_NAME, EXTERNAL_NAME) \
69 PyTypeObject INTERNAL_NAME = { \
70 PyVarObject_HEAD_INIT(NULL, 0) \
71 "cx_Oracle." #EXTERNAL_NAME, /* tp_name */ \
72 sizeof(cxoVar), /* tp_basicsize */ \
73 0, /* tp_itemsize */ \
74 (destructor) cxoVar_free, /* tp_dealloc */ \
75 0, /* tp_print */ \
76 0, /* tp_getattr */ \
77 0, /* tp_setattr */ \
78 0, /* tp_compare */ \
79 (reprfunc) cxoVar_repr, /* tp_repr */ \
80 0, /* tp_as_number */ \
81 0, /* tp_as_sequence */ \
82 0, /* tp_as_mapping */ \
83 0, /* tp_hash */ \
84 0, /* tp_call */ \
85 0, /* tp_str */ \
86 0, /* tp_getattro */ \
87 0, /* tp_setattro */ \
88 0, /* tp_as_buffer */ \
89 Py_TPFLAGS_DEFAULT, /* tp_flags */ \
90 0, /* tp_doc */ \
91 0, /* tp_traverse */ \
92 0, /* tp_clear */ \
93 0, /* tp_richcompare */ \
94 0, /* tp_weaklistoffset */ \
95 0, /* tp_iter */ \
96 0, /* tp_iternext */ \
97 cxoVarMethods, /* tp_methods */ \
98 cxoVarMembers, /* tp_members */ \
99 cxoVarCalcMembers /* tp_getset */ \
100 };
101
102 DECLARE_VARIABLE_TYPE(cxoPyTypeBfileVar, BFILE)
103 DECLARE_VARIABLE_TYPE(cxoPyTypeBinaryVar, BINARY)
104 DECLARE_VARIABLE_TYPE(cxoPyTypeBlobVar, BLOB)
105 DECLARE_VARIABLE_TYPE(cxoPyTypeBooleanVar, BOOLEAN)
106 DECLARE_VARIABLE_TYPE(cxoPyTypeClobVar, CLOB)
107 DECLARE_VARIABLE_TYPE(cxoPyTypeCursorVar, CURSOR)
108 DECLARE_VARIABLE_TYPE(cxoPyTypeDateTimeVar, DATETIME)
109 DECLARE_VARIABLE_TYPE(cxoPyTypeFixedCharVar, FIXED_CHAR)
110 DECLARE_VARIABLE_TYPE(cxoPyTypeFixedNcharVar, FIXED_NCHAR)
111 DECLARE_VARIABLE_TYPE(cxoPyTypeIntervalVar, INTERVAL)
112 DECLARE_VARIABLE_TYPE(cxoPyTypeLongBinaryVar, LONG_BINARY)
113 DECLARE_VARIABLE_TYPE(cxoPyTypeLongStringVar, LONG_STRING)
114 DECLARE_VARIABLE_TYPE(cxoPyTypeNativeFloatVar, NATIVE_FLOAT)
115 DECLARE_VARIABLE_TYPE(cxoPyTypeNativeIntVar, NATIVE_INT)
116 DECLARE_VARIABLE_TYPE(cxoPyTypeNcharVar, NCHAR)
117 DECLARE_VARIABLE_TYPE(cxoPyTypeNclobVar, NCLOB)
118 DECLARE_VARIABLE_TYPE(cxoPyTypeNumberVar, NUMBER)
119 DECLARE_VARIABLE_TYPE(cxoPyTypeObjectVar, OBJECT)
120 DECLARE_VARIABLE_TYPE(cxoPyTypeRowidVar, ROWID)
121 DECLARE_VARIABLE_TYPE(cxoPyTypeStringVar, STRING)
122 DECLARE_VARIABLE_TYPE(cxoPyTypeTimestampVar, TIMESTAMP)
67 // declaration of Python type
68 //-----------------------------------------------------------------------------
69 PyTypeObject cxoPyTypeVar = {
70 PyVarObject_HEAD_INIT(NULL, 0)
71 .tp_name = "cx_Oracle.Var",
72 .tp_basicsize = sizeof(cxoVar),
73 .tp_dealloc = (destructor) cxoVar_free,
74 .tp_repr = (reprfunc) cxoVar_repr,
75 .tp_flags = Py_TPFLAGS_DEFAULT,
76 .tp_methods = cxoVarMethods,
77 .tp_members = cxoMembers,
78 .tp_getset = cxoCalcMembers
79 };
12380
12481
12582 //-----------------------------------------------------------------------------
12683 // cxoVar_new()
12784 // Allocate a new variable.
12885 //-----------------------------------------------------------------------------
129 cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
130 Py_ssize_t size, int isArray, cxoObjectType *objType)
86 cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements,
87 cxoTransformNum transformNum, Py_ssize_t size, int isArray,
88 cxoObjectType *objType)
13189 {
13290 dpiObjectType *typeHandle = NULL;
13391 dpiOracleTypeNum oracleTypeNum;
134 dpiNativeTypeNum nativeTypeNum;
13592 cxoVar *var;
13693
13794 // attempt to allocate the object
138 var = (cxoVar*) type->pythonType->tp_alloc(type->pythonType, 0);
95 var = (cxoVar*) cxoPyTypeVar.tp_alloc(&cxoPyTypeVar, 0);
13996 if (!var)
14097 return NULL;
14198
150107 if (numElements == 0)
151108 numElements = 1;
152109 var->allocatedElements = (uint32_t) numElements;
153 var->type = type;
154 var->size = (size == 0) ? type->size : (uint32_t) size;
110 var->transformNum = transformNum;
111 var->size = (uint32_t) size;
112 if (var->size == 0)
113 var->size = cxoTransform_getDefaultSize(transformNum);
155114 var->isArray = isArray;
156115
116 // determine database type
117 var->dbType = cxoDbType_fromTransformNum(var->transformNum);
118 if (!var->dbType) {
119 Py_DECREF(var);
120 return NULL;
121 }
122 Py_INCREF(var->dbType);
123
157124 // acquire and initialize DPI variable
158 cxoTransform_getTypeInfo(type->transformNum, &oracleTypeNum,
159 &nativeTypeNum);
125 cxoTransform_getTypeInfo(transformNum, &oracleTypeNum,
126 &var->nativeTypeNum);
160127 if (dpiConn_newVar(cursor->connection->handle, oracleTypeNum,
161 nativeTypeNum, var->allocatedElements, var->size, 0, isArray,
128 var->nativeTypeNum, var->allocatedElements, var->size, 0, isArray,
162129 typeHandle, &var->handle, &var->data) < 0) {
163130 cxoError_raiseAndReturnNull();
164131 Py_DECREF(var);
194161 Py_CLEAR(var->inConverter);
195162 Py_CLEAR(var->outConverter);
196163 Py_CLEAR(var->objectType);
164 Py_CLEAR(var->dbType);
197165 Py_TYPE(var)->tp_free((PyObject*) var);
198166 }
199167
204172 //-----------------------------------------------------------------------------
205173 int cxoVar_check(PyObject *object)
206174 {
207 PyTypeObject *objectType = Py_TYPE(object);
208
209 return (objectType == &cxoPyTypeBfileVar ||
210 objectType == &cxoPyTypeBinaryVar ||
211 objectType == &cxoPyTypeBlobVar ||
212 objectType == &cxoPyTypeBooleanVar ||
213 objectType == &cxoPyTypeClobVar ||
214 objectType == &cxoPyTypeCursorVar ||
215 objectType == &cxoPyTypeDateTimeVar ||
216 objectType == &cxoPyTypeFixedCharVar ||
217 objectType == &cxoPyTypeFixedNcharVar ||
218 objectType == &cxoPyTypeIntervalVar ||
219 objectType == &cxoPyTypeLongBinaryVar ||
220 objectType == &cxoPyTypeLongStringVar ||
221 objectType == &cxoPyTypeNativeFloatVar ||
222 objectType == &cxoPyTypeNativeIntVar ||
223 objectType == &cxoPyTypeNcharVar ||
224 objectType == &cxoPyTypeNclobVar ||
225 objectType == &cxoPyTypeNumberVar ||
226 objectType == &cxoPyTypeObjectVar ||
227 objectType == &cxoPyTypeRowidVar ||
228 objectType == &cxoPyTypeStringVar ||
229 objectType == &cxoPyTypeTimestampVar);
175 return (Py_TYPE(object) == &cxoPyTypeVar);
230176 }
231177
232178
239185 {
240186 PyObject *result, *inputTypeHandler = NULL;
241187 cxoObjectType *objType = NULL;
242 cxoVarType *varType;
188 cxoTransformNum transformNum;
243189 Py_ssize_t size;
244190 cxoObject *obj;
245191 int isArray;
273219 }
274220
275221 // default processing
276 varType = cxoVarType_fromPythonValue(value,
277 &isArray, &size, &numElements, cursor->stmtInfo.isPLSQL);
278 if (!varType)
279 return NULL;
280 if (varType->transformNum == CXO_TRANSFORM_OBJECT) {
222 if (cxoTransform_getNumFromValue(value, &isArray, &size, &numElements,
223 cursor->stmtInfo.isPLSQL, &transformNum) < 0)
224 return NULL;
225 if (transformNum == CXO_TRANSFORM_OBJECT) {
281226 obj = (cxoObject*) value;
282227 objType = obj->objectType;
283228 }
284 return cxoVar_new(cursor, numElements, varType, size, isArray, objType);
229 return cxoVar_new(cursor, numElements, transformNum, size, isArray,
230 objType);
285231 }
286232
287233
293239 PyObject *value)
294240 {
295241 PyObject *typeObj, *numElementsObj;
242 cxoTransformNum transformNum;
296243 cxoObjectType *objType;
297 cxoVarType *varType;
298244 uint32_t numElements;
299245 int ok;
300246
302248 ok = (PyList_GET_SIZE(value) == 2);
303249 if (ok) {
304250 typeObj = PyList_GET_ITEM(value, 0);
305 ok = PyType_Check(typeObj);
306 }
307 if (ok) {
308251 numElementsObj = PyList_GET_ITEM(value, 1);
309 ok = PyInt_Check(numElementsObj);
252 ok = PyLong_Check(numElementsObj);
310253 }
311254 if (!ok) {
312255 cxoError_raiseFromString(cxoProgrammingErrorException,
315258 }
316259
317260 // create variable
318 varType = cxoVarType_fromPythonType(typeObj, &objType);
319 if (!varType)
320 return NULL;
321 numElements = PyInt_AsLong(numElementsObj);
261 if (cxoTransform_getNumFromType(typeObj, &transformNum, &objType) < 0)
262 return NULL;
263 numElements = PyLong_AsLong(numElementsObj);
322264 if (PyErr_Occurred())
323265 return NULL;
324 return cxoVar_new(cursor, numElements, varType, varType->size, 1, objType);
266 return cxoVar_new(cursor, numElements, transformNum, 0, 1, objType);
325267 }
326268
327269
332274 cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
333275 uint32_t numElements)
334276 {
277 cxoTransformNum transformNum;
335278 cxoObjectType *objType;
336 cxoVarType *varType;
337279 long size;
338280
339281 // passing an integer is assumed to be a string
340 if (PyInt_Check(value)) {
341 size = PyInt_AsLong(value);
282 if (PyLong_Check(value)) {
283 size = PyLong_AsLong(value);
342284 if (PyErr_Occurred())
343285 return NULL;
344 varType = cxoVarType_fromPythonType((PyObject*) &cxoPyTypeString,
345 &objType);
346 return cxoVar_new(cursor, numElements, varType, size, 0, objType);
286 return cxoVar_new(cursor, numElements, CXO_TRANSFORM_STRING, size, 0,
287 NULL);
347288 }
348289
349290 // passing an array of two elements to define an array
356297 return (cxoVar*) value;
357298 }
358299
359 // everything else ought to be a Python type
360 if (PyType_Check(value)) {
361 varType = cxoVarType_fromPythonType(value, &objType);
362 if (!varType)
363 return NULL;
364 return cxoVar_new(cursor, numElements, varType, varType->size, 0,
365 objType);
366 }
367
368 PyErr_SetString(PyExc_TypeError, "expecting type");
369 return NULL;
300 // everything else ought to be a Python type, database type constant or
301 // object type
302 if (cxoTransform_getNumFromType(value, &transformNum, &objType) < 0)
303 return NULL;
304 return cxoVar_new(cursor, numElements, transformNum, 0, 0, objType);
370305 }
371306
372307
452387 else data = &var->data[arrayPos];
453388 if (data->isNull)
454389 Py_RETURN_NONE;
455 value = cxoTransform_toPython(var->type->transformNum, var->connection,
390 value = cxoTransform_toPython(var->transformNum, var->connection,
456391 var->objectType, &data->value, var->encodingErrors);
457392 if (value) {
458 switch (var->type->transformNum) {
393 switch (var->transformNum) {
459394 case CXO_TRANSFORM_BFILE:
460395 case CXO_TRANSFORM_BLOB:
461396 case CXO_TRANSFORM_CLOB:
517452 int status;
518453
519454 if (buffer->size > var->bufferSize) {
520 cxoTransform_getTypeInfo(var->type->transformNum, &oracleTypeNum,
455 cxoTransform_getTypeInfo(var->transformNum, &oracleTypeNum,
521456 &nativeTypeNum);
522457 if (dpiConn_newVar(var->connection->handle, oracleTypeNum,
523458 nativeTypeNum, var->allocatedElements, buffer->size, 0,
606541 {
607542 dpiDataBuffer tempDbValue, *dbValue;
608543 PyObject *convertedValue = NULL;
544 dpiNativeTypeNum nativeTypeNum;
609545 cxoBuffer buffer;
610546 int result = 0;
611547 dpiData *data;
630566 data = &var->data[arrayPos];
631567 data->isNull = (value == Py_None);
632568 if (!data->isNull) {
633 if (var->type->transformNum == CXO_TRANSFORM_CURSOR)
569 if (var->transformNum == CXO_TRANSFORM_CURSOR)
634570 result = cxoVar_setValueCursor(var, arrayPos, data, value);
635571 else {
636572 cxoBuffer_init(&buffer);
637 if (var->type->size > 0)
573 if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES)
638574 dbValue = &tempDbValue;
639575 else dbValue = &data->value;
640 result = cxoTransform_fromPython(var->type->transformNum, value,
641 dbValue, &buffer, var->connection->encodingInfo.encoding,
576 result = cxoTransform_fromPython(var->transformNum,
577 &nativeTypeNum, value, dbValue, &buffer,
578 var->connection->encodingInfo.encoding,
642579 var->connection->encodingInfo.nencoding, var, arrayPos);
643 if (result == 0 && var->type->size > 0)
580 if (result == 0 && var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES)
644581 result = cxoVar_setValueBytes(var, arrayPos, data, &buffer);
645582 cxoBuffer_clear(&buffer);
646583 }
767704 if (var->isArray &&
768705 dpiVar_getNumElementsInArray(var->handle, &numElements) < 0)
769706 return cxoError_raiseAndReturnNull();
770 return PyInt_FromLong(numElements);
707 return PyLong_FromLong(numElements);
771708 }
772709
773710
787724
788725
789726 //-----------------------------------------------------------------------------
727 // cxoVar_getType()
728 // Return the type associated with the variable. This is either an object
729 // type or one of the database type constants.
730 //-----------------------------------------------------------------------------
731 static PyObject *cxoVar_getType(cxoVar *var, void *unused)
732 {
733 if (var->objectType) {
734 Py_INCREF(var->objectType);
735 return (PyObject*) var->objectType;
736 }
737
738 Py_INCREF(var->dbType);
739 return (PyObject*) var->dbType;
740 }
741
742
743 //-----------------------------------------------------------------------------
790744 // cxoVar_repr()
791745 // Return a string representation of the variable.
792746 //-----------------------------------------------------------------------------
793747 static PyObject *cxoVar_repr(cxoVar *var)
794748 {
795 PyObject *value, *module, *name, *result;
749 PyObject *value, *module, *name, *result, *typeName;
796750 uint32_t numElements;
797751
798752 if (var->isArray) {
804758 else value = cxoVar_getArrayValue(var, var->allocatedElements, NULL);
805759 if (!value)
806760 return NULL;
761 typeName = PyUnicode_DecodeASCII(var->dbType->name,
762 strlen(var->dbType->name), NULL);
763 if (!typeName) {
764 Py_DECREF(value);
765 return NULL;
766 }
807767 if (cxoUtils_getModuleAndName(Py_TYPE(var), &module, &name) < 0) {
768 Py_DECREF(typeName);
808769 Py_DECREF(value);
809770 return NULL;
810771 }
811 result = cxoUtils_formatString("<%s.%s with value %r>",
812 PyTuple_Pack(3, module, name, value));
772 result = cxoUtils_formatString("<%s.%s of type %s with value %r>",
773 PyTuple_Pack(4, module, name, typeName, value));
813774 Py_DECREF(module);
814775 Py_DECREF(name);
815776 Py_DECREF(value);
777 Py_DECREF(typeName);
816778 return result;
817779 }
818
+0
-309
src/cxoVarType.c less more
0 //-----------------------------------------------------------------------------
1 // Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2 //-----------------------------------------------------------------------------
3
4 //-----------------------------------------------------------------------------
5 // cxoVarType.c
6 // Defines variable types for various transformations.
7 //-----------------------------------------------------------------------------
8
9 #include "cxoModule.h"
10
11 // define variable types for each of the supported transforms
12 static cxoVarType cxoAllVarTypes[] = {
13 {
14 CXO_TRANSFORM_NONE,
15 &cxoPyTypeStringVar,
16 1
17 },
18 {
19 CXO_TRANSFORM_BINARY,
20 &cxoPyTypeBinaryVar,
21 4000
22 },
23 {
24 CXO_TRANSFORM_BFILE,
25 &cxoPyTypeBfileVar,
26 0
27 },
28 {
29 CXO_TRANSFORM_BLOB,
30 &cxoPyTypeBlobVar,
31 0
32 },
33 {
34 CXO_TRANSFORM_BOOLEAN,
35 &cxoPyTypeBooleanVar,
36 0
37 },
38 {
39 CXO_TRANSFORM_CLOB,
40 &cxoPyTypeClobVar,
41 0
42 },
43 {
44 CXO_TRANSFORM_CURSOR,
45 &cxoPyTypeCursorVar,
46 0
47 },
48 {
49 CXO_TRANSFORM_DATE,
50 &cxoPyTypeDateTimeVar,
51 0
52 },
53 {
54 CXO_TRANSFORM_DATETIME,
55 &cxoPyTypeDateTimeVar,
56 0
57 },
58 {
59 CXO_TRANSFORM_DECIMAL,
60 &cxoPyTypeNumberVar,
61 1000
62 },
63 {
64 CXO_TRANSFORM_FIXED_CHAR,
65 &cxoPyTypeFixedCharVar,
66 2000
67 },
68 {
69 CXO_TRANSFORM_FIXED_NCHAR,
70 &cxoPyTypeFixedNcharVar,
71 2000
72 },
73 {
74 CXO_TRANSFORM_FLOAT,
75 &cxoPyTypeNumberVar,
76 1000
77 },
78 {
79 CXO_TRANSFORM_INT,
80 &cxoPyTypeNumberVar,
81 1000
82 },
83 {
84 CXO_TRANSFORM_LONG_BINARY,
85 &cxoPyTypeLongBinaryVar,
86 128 * 1024
87 },
88 {
89 CXO_TRANSFORM_LONG_STRING,
90 &cxoPyTypeLongStringVar,
91 128 * 1024
92 },
93 {
94 CXO_TRANSFORM_NATIVE_DOUBLE,
95 &cxoPyTypeNativeFloatVar,
96 0
97 },
98 {
99 CXO_TRANSFORM_NATIVE_FLOAT,
100 &cxoPyTypeNativeFloatVar,
101 0
102 },
103 {
104 CXO_TRANSFORM_NATIVE_INT,
105 &cxoPyTypeNativeIntVar,
106 0
107 },
108 {
109 CXO_TRANSFORM_NCLOB,
110 &cxoPyTypeNclobVar,
111 0
112 },
113 {
114 CXO_TRANSFORM_NSTRING,
115 &cxoPyTypeNcharVar,
116 4000
117 },
118 {
119 CXO_TRANSFORM_OBJECT,
120 &cxoPyTypeObjectVar,
121 0
122 },
123 {
124 CXO_TRANSFORM_ROWID,
125 &cxoPyTypeRowidVar,
126 0
127 },
128 {
129 CXO_TRANSFORM_STRING,
130 &cxoPyTypeStringVar,
131 4000
132 },
133 {
134 CXO_TRANSFORM_TIMEDELTA,
135 &cxoPyTypeIntervalVar,
136 0
137 },
138 {
139 CXO_TRANSFORM_TIMESTAMP,
140 &cxoPyTypeTimestampVar,
141 0
142 },
143 {
144 CXO_TRANSFORM_TIMESTAMP_LTZ,
145 &cxoPyTypeTimestampVar,
146 0
147 }
148 };
149
150
151 //-----------------------------------------------------------------------------
152 // cxoVarType_fromDataTypeInfo()
153 // Return a variable type given query metadata, or NULL indicating that the
154 // data indicated by the query metadata is not supported.
155 //-----------------------------------------------------------------------------
156 cxoVarType *cxoVarType_fromDataTypeInfo(dpiDataTypeInfo *info)
157 {
158 cxoTransformNum transformNum;
159 char message[120];
160
161 transformNum = cxoTransform_getNumFromDataTypeInfo(info);
162 if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
163 snprintf(message, sizeof(message), "Oracle type %d not supported.",
164 info->oracleTypeNum);
165 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
166 return NULL;
167 }
168 return &cxoAllVarTypes[transformNum];
169 }
170
171
172 //-----------------------------------------------------------------------------
173 // cxoVarType_fromPythonType()
174 // Return a variable type given a Python type object or NULL if the Python
175 // type does not have a corresponding variable type. If the type provided is an
176 // object type, return that as well.
177 //-----------------------------------------------------------------------------
178 cxoVarType *cxoVarType_fromPythonType(PyObject *type, cxoObjectType **objType)
179 {
180 cxoTransformNum transformNum;
181 PyTypeObject *pyType;
182 char message[250];
183
184 if (Py_TYPE(type) == &cxoPyTypeObjectType) {
185 transformNum = CXO_TRANSFORM_OBJECT;
186 *objType = (cxoObjectType*) type;
187 } else if (Py_TYPE(type) != &PyType_Type) {
188 PyErr_SetString(PyExc_TypeError, "expecting type");
189 return NULL;
190 } else {
191 *objType = NULL;
192 pyType = (PyTypeObject*) type;
193 transformNum = cxoTransform_getNumFromType(pyType);
194 if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
195 snprintf(message, sizeof(message), "Python type %s not supported.",
196 pyType->tp_name);
197 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
198 return NULL;
199 }
200 }
201 return &cxoAllVarTypes[transformNum];
202 }
203
204
205 //-----------------------------------------------------------------------------
206 // cxoVarType_calculateSize()
207 // Calculate the size to use with the specified transform and Python value.
208 // This function is only called by cxoVarType_fromPythonValue() and no attempt
209 // is made to verify the value further.
210 //-----------------------------------------------------------------------------
211 static Py_ssize_t cxoVarType_calculateSize(PyObject *value,
212 cxoTransformNum transformNum)
213 {
214 Py_ssize_t size = 0;
215 #if PY_MAJOR_VERSION < 3
216 const void *ptr;
217 #endif
218
219 switch (transformNum) {
220 case CXO_TRANSFORM_NONE:
221 return 1;
222 case CXO_TRANSFORM_BINARY:
223 #if PY_MAJOR_VERSION >= 3
224 return PyBytes_GET_SIZE(value);
225 #else
226 PyObject_AsReadBuffer(value, &ptr, &size);
227 return size;
228 #endif
229 case CXO_TRANSFORM_NSTRING:
230 size = PyUnicode_GET_SIZE(value);
231 return (size == 0) ? 1 : size;
232 case CXO_TRANSFORM_STRING:
233 #if PY_MAJOR_VERSION >= 3
234 size = PyUnicode_GET_SIZE(value);
235 #else
236 size = PyString_GET_SIZE(value);
237 #endif
238 return (size == 0) ? 1 : size;
239 default:
240 break;
241 }
242 return 0;
243 }
244
245
246 //-----------------------------------------------------------------------------
247 // cxoVarType_fromPythonValue()
248 // Return a variable type given a Python object or NULL if the Python object
249 // does not have a corresponding variable type.
250 //-----------------------------------------------------------------------------
251 cxoVarType *cxoVarType_fromPythonValue(PyObject *value, int *isArray,
252 Py_ssize_t *size, Py_ssize_t *numElements, int plsql)
253 {
254 cxoTransformNum transformNum, tempTransformNum;
255 PyObject *elementValue;
256 Py_ssize_t i, tempSize;
257 char message[250];
258
259 // initialization (except numElements which always has a valid value and is
260 // only overridden when a an array is encountered)
261 *size = 0;
262 *isArray = 0;
263
264 // handle arrays
265 if (PyList_Check(value)) {
266 transformNum = CXO_TRANSFORM_NONE;
267 for (i = 0; i < PyList_GET_SIZE(value); i++) {
268 elementValue = PyList_GET_ITEM(value, i);
269 tempTransformNum = cxoTransform_getNumFromValue(elementValue, 1);
270 if (tempTransformNum == CXO_TRANSFORM_UNSUPPORTED) {
271 snprintf(message, sizeof(message),
272 "element %u value is unsupported", (unsigned) i);
273 cxoError_raiseFromString(cxoNotSupportedErrorException,
274 message);
275 return NULL;
276 } else if (transformNum == CXO_TRANSFORM_NONE) {
277 transformNum = tempTransformNum;
278 } else if (transformNum != tempTransformNum) {
279 snprintf(message, sizeof(message),
280 "element %u value is not the same type as previous "
281 "elements", (unsigned) i);
282 cxoError_raiseFromString(cxoNotSupportedErrorException,
283 message);
284 return NULL;
285 }
286 tempSize = cxoVarType_calculateSize(elementValue,
287 tempTransformNum);
288 if (tempSize > *size)
289 *size = tempSize;
290 }
291 *isArray = 1;
292 *numElements = PyList_GET_SIZE(value);
293 return &cxoAllVarTypes[transformNum];
294 }
295
296 // handle scalar values
297 transformNum = cxoTransform_getNumFromValue(value, plsql);
298 if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
299 snprintf(message, sizeof(message),
300 "Python value of type %s not supported.",
301 Py_TYPE(value)->tp_name);
302 cxoError_raiseFromString(cxoNotSupportedErrorException, message);
303 return NULL;
304 }
305 *size = cxoVarType_calculateSize(value, transformNum);
306 return &cxoAllVarTypes[transformNum];
307 }
308
1010 import threading
1111
1212 class TestCase(TestEnv.BaseTestCase):
13 bookQueueName = "TEST_BOOK_QUEUE"
1314 bookData = [
1415 ("Wings of Fire", "A.P.J. Abdul Kalam",
1516 decimal.Decimal("15.75")),
2728 options.deliverymode = cx_Oracle.MSG_PERSISTENT_OR_BUFFERED
2829 options.visibility = cx_Oracle.ENQ_IMMEDIATE
2930 props = self.connection.msgproperties()
30 while self.connection.deq("BOOKS", options, props, book):
31 while self.connection.deq(self.bookQueueName, options, props, book):
3132 pass
3233
3334 def __deqInThread(self, results):
3738 options = connection.deqoptions()
3839 options.wait = 10
3940 props = connection.msgproperties()
40 if connection.deq("BOOKS", options, props, book):
41 if connection.deq(self.bookQueueName, options, props, book):
4142 results.append((book.TITLE, book.AUTHORS, book.PRICE))
4243 connection.commit()
4344
5354 options = self.connection.deqoptions()
5455 options.wait = cx_Oracle.DEQ_NO_WAIT
5556 props = self.connection.msgproperties()
56 messageId = self.connection.deq("BOOKS", options, props, book)
57 messageId = self.connection.deq(self.bookQueueName, options, props,
58 book)
5759 self.assertTrue(messageId is None)
5860
5961 def testDeqEnq(self):
6769 book.TITLE = title
6870 book.AUTHORS = authors
6971 book.PRICE = price
70 self.connection.enq("BOOKS", options, props, book)
72 self.connection.enq(self.bookQueueName, options, props, book)
7173 options = self.connection.deqoptions()
7274 options.navigation = cx_Oracle.DEQ_FIRST_MSG
7375 options.wait = cx_Oracle.DEQ_NO_WAIT
7476 results = []
75 while self.connection.deq("BOOKS", options, props, book):
77 while self.connection.deq(self.bookQueueName, options, props, book):
7678 row = (book.TITLE, book.AUTHORS, book.PRICE)
7779 results.append(row)
7880 self.connection.commit()
8991 book.PRICE = price
9092 options = self.connection.enqoptions()
9193 props = self.connection.msgproperties()
92 self.connection.enq("BOOKS", options, props, book)
94 self.connection.enq(self.bookQueueName, options, props, book)
9395 options = self.connection.deqoptions()
9496 options.navigation = cx_Oracle.DEQ_FIRST_MSG
9597 options.wait = cx_Oracle.DEQ_NO_WAIT
9698 options.mode = cx_Oracle.DEQ_REMOVE_NODATA
9799 book = booksType.newobject()
98 messageId = self.connection.deq("BOOKS", options, props, book)
100 messageId = self.connection.deq(self.bookQueueName, options, props,
101 book)
99102 self.connection.commit()
100103 self.assertTrue(messageId is not None)
101104 self.assertEqual(book.TITLE, "")
130133 book.PRICE = price
131134 options = self.connection.enqoptions()
132135 props = self.connection.msgproperties()
133 self.connection.enq("BOOKS", options, props, book)
136 self.connection.enq(self.bookQueueName, options, props, book)
134137 self.connection.commit()
135138 thread.join()
136139 self.assertEqual(results, [(title, authors, price)])
146149 book = booksType.newobject()
147150 options = self.connection.enqoptions()
148151 props = self.connection.msgproperties()
149 self.assertRaises(TypeError, self.connection.deq, "BOOKS", options,
150 props, book)
151 options = self.connection.deqoptions()
152 self.assertRaises(TypeError, self.connection.enq, "BOOKS", options,
153 props, book)
152 self.assertRaises(TypeError, self.connection.deq, self.bookQueueName,
153 options, props, book)
154 options = self.connection.deqoptions()
155 self.assertRaises(TypeError, self.connection.enq, self.bookQueueName,
156 options, props, book)
154157
155158 def testMsgProps(self):
156159 "test getting/setting message properties attributes"
174177 enqOptions = self.connection.enqoptions()
175178 enqOptions.visibility = cx_Oracle.ENQ_ON_COMMIT
176179 props = self.connection.msgproperties()
177 self.connection.enq("BOOKS", enqOptions, props, book)
178
179 otherConnection = TestEnv.GetConnection()
180 deqOptions = otherConnection.deqoptions()
181 deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
182 deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
183 booksType = otherConnection.gettype("UDT_BOOK")
184 book = booksType.newobject()
185 props = otherConnection.msgproperties()
186 messageId = otherConnection.deq("BOOKS", deqOptions, props, book)
180 self.connection.enq(self.bookQueueName, enqOptions, props, book)
181
182 otherConnection = TestEnv.GetConnection()
183 deqOptions = otherConnection.deqoptions()
184 deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
185 deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
186 booksType = otherConnection.gettype("UDT_BOOK")
187 book = booksType.newobject()
188 props = otherConnection.msgproperties()
189 messageId = otherConnection.deq(self.bookQueueName, deqOptions, props,
190 book)
187191 self.assertTrue(messageId is None)
188192 self.connection.commit()
189 messageId = otherConnection.deq("BOOKS", deqOptions, props, book)
193 messageId = otherConnection.deq(self.bookQueueName, deqOptions, props,
194 book)
190195 self.assertTrue(messageId is not None)
191196
192197 def testVisibilityModeImmediate(self):
198203 enqOptions = self.connection.enqoptions()
199204 enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
200205 props = self.connection.msgproperties()
201 self.connection.enq("BOOKS", enqOptions, props, book)
206 self.connection.enq(self.bookQueueName, enqOptions, props, book)
202207
203208 otherConnection = TestEnv.GetConnection()
204209 deqOptions = otherConnection.deqoptions()
208213 booksType = otherConnection.gettype("UDT_BOOK")
209214 book = booksType.newobject()
210215 props = otherConnection.msgproperties()
211 otherConnection.deq("BOOKS", deqOptions, props, book)
216 otherConnection.deq(self.bookQueueName, deqOptions, props, book)
212217 results = (book.TITLE, book.AUTHORS, book.PRICE)
213218 otherConnection.commit()
214219 self.assertEqual(results, self.bookData[0])
223228 enqOptions.deliverymode = cx_Oracle.MSG_BUFFERED
224229 enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
225230 props = self.connection.msgproperties()
226 self.connection.enq("BOOKS", enqOptions, props, book)
231 self.connection.enq(self.bookQueueName, enqOptions, props, book)
227232
228233 otherConnection = TestEnv.GetConnection()
229234 deqOptions = otherConnection.deqoptions()
234239 booksType = otherConnection.gettype("UDT_BOOK")
235240 book = booksType.newobject()
236241 props = otherConnection.msgproperties()
237 otherConnection.deq("BOOKS", deqOptions, props, book)
242 otherConnection.deq(self.bookQueueName, deqOptions, props, book)
238243 results = (book.TITLE, book.AUTHORS, book.PRICE)
239244 otherConnection.commit()
240245 self.assertEqual(results, self.bookData[0])
249254 enqOptions.deliverymode = cx_Oracle.MSG_PERSISTENT
250255 enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
251256 props = self.connection.msgproperties()
252 self.connection.enq("BOOKS", enqOptions, props, book)
257 self.connection.enq(self.bookQueueName, enqOptions, props, book)
253258
254259 otherConnection = TestEnv.GetConnection()
255260 deqOptions = otherConnection.deqoptions()
260265 booksType = otherConnection.gettype("UDT_BOOK")
261266 book = booksType.newobject()
262267 props = otherConnection.msgproperties()
263 otherConnection.deq("BOOKS", deqOptions, props, book)
268 otherConnection.deq(self.bookQueueName, deqOptions, props, book)
264269 results = (book.TITLE, book.AUTHORS, book.PRICE)
265270 otherConnection.commit()
266271 self.assertEqual(results, self.bookData[0])
275280 enqOptions.deliverymode = cx_Oracle.MSG_PERSISTENT_OR_BUFFERED
276281 enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
277282 props = self.connection.msgproperties()
278 self.connection.enq("BOOKS", enqOptions, props, book)
283 self.connection.enq(self.bookQueueName, enqOptions, props, book)
279284
280285 otherConnection = TestEnv.GetConnection()
281286 deqOptions = otherConnection.deqoptions()
286291 booksType = otherConnection.gettype("UDT_BOOK")
287292 book = booksType.newobject()
288293 props = otherConnection.msgproperties()
289 otherConnection.deq("BOOKS", deqOptions, props, book)
294 otherConnection.deq(self.bookQueueName, deqOptions, props, book)
290295 results = (book.TITLE, book.AUTHORS, book.PRICE)
291296 otherConnection.commit()
292297 self.assertEqual(results, self.bookData[0])
301306 enqOptions.deliverymode = cx_Oracle.MSG_BUFFERED
302307 enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
303308 props = self.connection.msgproperties()
304 self.connection.enq("BOOKS", enqOptions, props, book)
309 self.connection.enq(self.bookQueueName, enqOptions, props, book)
305310
306311 otherConnection = TestEnv.GetConnection()
307312 deqOptions = otherConnection.deqoptions()
312317 booksType = otherConnection.gettype("UDT_BOOK")
313318 book = booksType.newobject()
314319 props = otherConnection.msgproperties()
315 messageId = otherConnection.deq("BOOKS", deqOptions, props, book)
320 messageId = otherConnection.deq(self.bookQueueName, deqOptions, props,
321 book)
316322 self.assertTrue(messageId is None)
317323
318324 def testDequeueTransformation(self):
324330 expectedPrice = book.PRICE + 10
325331 enqOptions = self.connection.enqoptions()
326332 props = self.connection.msgproperties()
327 self.connection.enq("BOOKS", enqOptions, props, book)
333 self.connection.enq(self.bookQueueName, enqOptions, props, book)
328334 self.connection.commit()
329335
330336 otherConnection = TestEnv.GetConnection()
336342 booksType = otherConnection.gettype("UDT_BOOK")
337343 book = booksType.newobject()
338344 props = otherConnection.msgproperties()
339 otherConnection.deq("BOOKS", deqOptions, props, book)
345 otherConnection.deq(self.bookQueueName, deqOptions, props, book)
340346 otherPrice = book.PRICE
341347 self.assertEqual(otherPrice, expectedPrice)
342348
350356 enqOptions = self.connection.enqoptions()
351357 enqOptions.transformation = "%s.transform1" % self.connection.username
352358 props = self.connection.msgproperties()
353 self.connection.enq("BOOKS", enqOptions, props, book)
354 self.connection.commit()
355
356 otherConnection = TestEnv.GetConnection()
357 deqOptions = otherConnection.deqoptions()
358 deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
359 deqOptions.visibility = cx_Oracle.DEQ_IMMEDIATE
360 deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
361 booksType = otherConnection.gettype("UDT_BOOK")
362 book = booksType.newobject()
363 props = otherConnection.msgproperties()
364 otherConnection.deq("BOOKS", deqOptions, props, book)
359 self.connection.enq(self.bookQueueName, enqOptions, props, book)
360 self.connection.commit()
361
362 otherConnection = TestEnv.GetConnection()
363 deqOptions = otherConnection.deqoptions()
364 deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
365 deqOptions.visibility = cx_Oracle.DEQ_IMMEDIATE
366 deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
367 booksType = otherConnection.gettype("UDT_BOOK")
368 book = booksType.newobject()
369 props = otherConnection.msgproperties()
370 otherConnection.deq(self.bookQueueName, deqOptions, props, book)
365371 otherPrice = book.PRICE
366372 self.assertEqual(otherPrice, expectedPrice)
367373
1414
1515 class TestCase(TestEnv.BaseTestCase):
1616
17 def __testBindValueAsBoolean(self, value):
18 expectedResult = str(bool(value)).upper()
19 var = self.cursor.var(bool)
20 var.setvalue(0, value)
21 result = self.cursor.callfunc("pkg_TestBooleans.GetStringRep", str,
22 (var,))
23 self.assertEqual(result, expectedResult)
24
1725 def testBindFalse(self):
1826 "test binding in a False value"
1927 result = self.cursor.callfunc("pkg_TestBooleans.GetStringRep", str,
2028 (False,))
2129 self.assertEqual(result, "FALSE")
30
31 def testBindFloatAsBoolean(self):
32 "test binding in a float as a boolean"
33 self.__testBindValueAsBoolean(0.0)
34 self.__testBindValueAsBoolean(1.0)
35
36 def testBindIntegerAsBoolean(self):
37 "test binding in an integer as a boolean"
38 self.__testBindValueAsBoolean(0)
39 self.__testBindValueAsBoolean(1)
2240
2341 def testBindNull(self):
2442 "test binding in a null value"
3048 def testBindOutFalse(self):
3149 "test binding out a boolean value (False)"
3250 result = self.cursor.callfunc("pkg_TestBooleans.IsLessThan10",
33 cx_Oracle.BOOLEAN, (15,))
51 cx_Oracle.DB_TYPE_BOOLEAN, (15,))
3452 self.assertEqual(result, False)
3553
3654 def testBindOutTrue(self):
3856 result = self.cursor.callfunc("pkg_TestBooleans.IsLessThan10", bool,
3957 (5,))
4058 self.assertEqual(result, True)
59
60 def testBindStringAsBoolean(self):
61 "test binding in a string as a boolean"
62 self.__testBindValueAsBoolean("")
63 self.__testBindValueAsBoolean("0")
4164
4265 def testBindTrue(self):
4366 "test binding in a True value"
4770
4871 if __name__ == "__main__":
4972 TestEnv.RunTestCases()
50
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 """Module for testing AQ Bulk enqueue/dequeue."""
5
6 import TestEnv
7
8 import cx_Oracle
9 import decimal
10 import threading
11
12 RAW_QUEUE_NAME = "TEST_RAW_QUEUE"
13 RAW_PAYLOAD_DATA = [
14 "The first message",
15 "The second message",
16 "The third message",
17 "The fourth message",
18 "The fifth message",
19 "The sixth message",
20 "The seventh message",
21 "The eighth message",
22 "The ninth message",
23 "The tenth message",
24 "The eleventh message",
25 "The twelfth and final message"
26 ]
27
28 class TestCase(TestEnv.BaseTestCase):
29
30 def __deqInThread(self, results):
31 connection = TestEnv.GetConnection(threaded=True)
32 queue = connection.queue(RAW_QUEUE_NAME)
33 queue.deqOptions.wait = 10
34 queue.deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
35 while len(results) < len(RAW_PAYLOAD_DATA):
36 messages = queue.deqMany(5)
37 if not messages:
38 break
39 for m in messages:
40 results.append(m.payload.decode(connection.encoding))
41 connection.commit()
42
43 def __getAndClearRawQueue(self):
44 queue = self.connection.queue(RAW_QUEUE_NAME)
45 queue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
46 queue.deqOptions.navigation = cx_Oracle.DEQ_FIRST_MSG
47 while queue.deqOne():
48 pass
49 self.connection.commit()
50 return queue
51
52 def testEnqAndDeq(self):
53 "test bulk enqueue and dequeue"
54 queue = self.__getAndClearRawQueue()
55 messages = [self.connection.msgproperties(payload=d) \
56 for d in RAW_PAYLOAD_DATA]
57 queue.enqMany(messages)
58 messages = queue.deqMany(len(RAW_PAYLOAD_DATA))
59 data = [m.payload.decode(self.connection.encoding) for m in messages]
60 self.connection.commit()
61 self.assertEqual(data, RAW_PAYLOAD_DATA)
62
63 def testDequeueEmpty(self):
64 "test empty bulk dequeue"
65 queue = self.__getAndClearRawQueue()
66 messages = queue.deqMany(5)
67 self.connection.commit()
68 self.assertEqual(messages, [])
69
70 def testDeqWithWait(self):
71 "test bulk dequeue with wait"
72 queue = self.__getAndClearRawQueue()
73 results = []
74 thread = threading.Thread(target=self.__deqInThread, args=(results,))
75 thread.start()
76 messages = [self.connection.msgproperties(payload=d) \
77 for d in RAW_PAYLOAD_DATA]
78 queue.enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
79 queue.enqMany(messages)
80 thread.join()
81 self.assertEqual(results, RAW_PAYLOAD_DATA)
82
83 def testEnqAndDeqMultipleTimes(self):
84 "test enqueue and dequeue multiple times"
85 queue = self.__getAndClearRawQueue()
86 dataToEnqueue = RAW_PAYLOAD_DATA
87 for num in (2, 6, 4):
88 messages = [self.connection.msgproperties(payload=d) \
89 for d in dataToEnqueue[:num]]
90 dataToEnqueue = dataToEnqueue[num:]
91 queue.enqMany(messages)
92 self.connection.commit()
93 allData = []
94 for num in (3, 5, 10):
95 messages = queue.deqMany(num)
96 allData.extend(m.payload.decode(self.connection.encoding) \
97 for m in messages)
98 self.connection.commit()
99 self.assertEqual(allData, RAW_PAYLOAD_DATA)
100
101 def testEnqAndDeqVisibility(self):
102 "test visibility option for enqueue and dequeue"
103 queue = self.__getAndClearRawQueue()
104
105 # first test with ENQ_ON_COMMIT (commit required)
106 queue.enqOptions.visibility = cx_Oracle.ENQ_ON_COMMIT
107 props1 = self.connection.msgproperties(payload="A first message")
108 props2 = self.connection.msgproperties(payload="A second message")
109 queue.enqMany([props1, props2])
110 otherConnection = TestEnv.GetConnection()
111 otherQueue = otherConnection.queue(RAW_QUEUE_NAME)
112 otherQueue.deqOptions.wait = cx_Oracle.DEQ_NO_WAIT
113 otherQueue.deqOptions.visibility = cx_Oracle.DEQ_ON_COMMIT
114 messages = otherQueue.deqMany(5)
115 self.assertEqual(len(messages), 0)
116 self.connection.commit()
117 messages = otherQueue.deqMany(5)
118 self.assertEqual(len(messages), 2)
119 otherConnection.rollback()
120
121 # second test with ENQ_IMMEDIATE (no commit required)
122 queue.enqOptions.visibility = cx_Oracle.ENQ_IMMEDIATE
123 otherQueue.deqOptions.visibility = cx_Oracle.DEQ_IMMEDIATE
124 queue.enqMany([props1, props2])
125 messages = otherQueue.deqMany(5)
126 self.assertEqual(len(messages), 4)
127 otherConnection.rollback()
128 messages = otherQueue.deqMany(5)
129 self.assertEqual(len(messages), 0)
130
131 if __name__ == "__main__":
132 TestEnv.RunTestCases()
7676 def testAttributes(self):
7777 "test connection end-to-end tracing attributes"
7878 connection = TestEnv.GetConnection()
79 if TestEnv.GetClientVersion() >= (12, 1):
79 if TestEnv.GetClientVersion() >= (12, 1) \
80 and not self.isOnOracleCloud(connection):
8081 self.__VerifyAttributes(connection, "dbop", "cx_OracleTest_DBOP",
8182 "select dbop_name from v$sql_monitor "
8283 "where sid = sys_context('userenv', 'sid')"
127128
128129 def testChangePassword(self):
129130 "test changing password"
131 connection = TestEnv.GetConnection()
132 if self.isOnOracleCloud(connection):
133 self.skipTest("passwords on Oracle Cloud are strictly controlled")
130134 sysRandom = random.SystemRandom()
131135 newPassword = "".join(sysRandom.choice(string.ascii_letters) \
132136 for i in range(20))
133 connection = TestEnv.GetConnection()
134137 connection.changepassword(TestEnv.GetMainPassword(), newPassword)
135138 cconnection = cx_Oracle.connect(TestEnv.GetMainUser(), newPassword,
136139 TestEnv.GetConnectString())
138141
139142 def testChangePasswordNegative(self):
140143 "test changing password to an invalid value"
144 connection = TestEnv.GetConnection()
145 if self.isOnOracleCloud(connection):
146 self.skipTest("passwords on Oracle Cloud are strictly controlled")
141147 newPassword = "1" * 150
142 connection = TestEnv.GetConnection()
143148 self.assertRaises(cx_Oracle.DatabaseError, connection.changepassword,
144149 TestEnv.GetMainPassword(), newPassword)
150
151 def testParsePassword(self):
152 "test connecting with password containing / and @ symbols"
153 connection = TestEnv.GetConnection()
154 if self.isOnOracleCloud(connection):
155 self.skipTest("passwords on Oracle Cloud are strictly controlled")
156 sysRandom = random.SystemRandom()
157 chars = list(sysRandom.choice(string.ascii_letters) for i in range(20))
158 chars[4] = "/"
159 chars[8] = "@"
160 newPassword = "".join(chars)
161 connection.changepassword(TestEnv.GetMainPassword(), newPassword)
162 try:
163 arg = "%s/%s@%s" % (TestEnv.GetMainUser(), newPassword,
164 TestEnv.GetConnectString())
165 cx_Oracle.connect(arg)
166 finally:
167 connection.changepassword(newPassword, TestEnv.GetMainPassword())
145168
146169 def testEncodings(self):
147170 "connection with only encoding or nencoding specified should work"
167190 encoding="UTF-8", nencoding="UTF-16")
168191 value = u"\u03b4\u4e2a"
169192 cursor = connection.cursor()
170 ncharVar = cursor.var(cx_Oracle.NCHAR, 100)
193 ncharVar = cursor.var(cx_Oracle.DB_TYPE_NVARCHAR, 100)
171194 ncharVar.setvalue(0, value)
172195 cursor.execute("select :value from dual", value = ncharVar)
173196 result, = cursor.fetchone()
177200 "confirm an exception is raised after closing a connection"
178201 connection = TestEnv.GetConnection()
179202 connection.close()
180 self.assertRaises(cx_Oracle.DatabaseError, connection.rollback)
203 self.assertRaises(cx_Oracle.InterfaceError, connection.rollback)
181204
182205 def testConnectWithHandle(self):
183206 "test creating a connection using a handle"
277300 cursor.execute("insert into TestTempTable (IntCol) values (1)")
278301 connection.commit()
279302 cursor.execute("insert into TestTempTable (IntCol) values (2)")
280 self.assertRaises(cx_Oracle.DatabaseError, connection.ping)
303 self.assertRaises(cx_Oracle.InterfaceError, connection.ping)
281304 connection = TestEnv.GetConnection()
282305 cursor = connection.cursor()
283306 cursor.execute("select count(*) from TestTempTable")
318341 if TestEnv.GetClientVersion() >= (12, 1):
319342 attrNames.append("ltxid")
320343 for name in attrNames:
321 self.assertRaises(cx_Oracle.DatabaseError, getattr, connection,
344 self.assertRaises(cx_Oracle.InterfaceError, getattr, connection,
322345 name)
323346
324347 def testPing(self):
8484 var = self.cursor.var(cx_Oracle.NUMBER)
8585 results = self.cursor.callproc("proc_Test", ("hi", 5, var))
8686 self.assertEqual(results, ["hi", 10, 2.0])
87
88 def testCallProcAllKeywords(self):
89 "test executing a stored procedure with args in keywordParameters"
90 kwargs = dict(a_InOutValue=self.cursor.var(cx_Oracle.NUMBER),
91 a_InValue="hi", a_OutValue=self.cursor.var(cx_Oracle.NUMBER))
92 kwargs['a_InOutValue'].setvalue(0, 5)
93 results = self.cursor.callproc("proc_Test", keywordParameters=kwargs)
94 self.assertEqual(results, [])
95 self.assertEqual(kwargs['a_InOutValue'].getvalue(), 10)
96 self.assertEqual(kwargs['a_OutValue'].getvalue(), 2.0)
97
98 def testCallProcOnlyLastKeyword(self):
99 "test executing a stored procedure with last arg in keywordParameters"
100 kwargs = dict(a_OutValue = self.cursor.var(cx_Oracle.NUMBER))
101 results = self.cursor.callproc("proc_Test", ("hi", 5), kwargs)
102 self.assertEqual(results, ["hi", 10])
103 self.assertEqual(kwargs['a_OutValue'].getvalue(), 2.0)
104
105 def testCallProcRepeatedKeywordParameters(self):
106 "test executing a stored procedure, repeated arg in keywordParameters"
107 kwargs = dict(a_InValue="hi",
108 a_OutValue=self.cursor.var(cx_Oracle.NUMBER))
109 self.assertRaises(cx_Oracle.DatabaseError, self.cursor.callproc,
110 "proc_Test", parameters=("hi", 5), keywordParameters=kwargs)
87111
88112 def testCallProcNoArgs(self):
89113 """test executing a stored procedure without any arguments"""
242266 insert into TestTempTable (IntCol, StringCol)
243267 values (t_Id, 'Test String ' || t_Id);
244268 end;""", numRows)
269 self.assertEqual(self.cursor.rowcount, numRows)
245270 self.cursor.execute("select count(*) from TestTempTable")
246271 count, = self.cursor.fetchone()
247272 self.assertEqual(count, numRows)
265290 select sum(IntCol) into :1
266291 from TestTempTable;
267292 end;""", numRows)
293 self.assertEqual(self.cursor.rowcount, numRows)
268294 expectedData = [1, 3, 6, 10, 15, 21, 28, 36, 45]
269295 self.assertEqual(var.values, expectedData)
270296
586612 self.cursor.parse(sql)
587613 self.assertEqual(self.cursor.statement, sql)
588614 self.assertEqual(self.cursor.description,
589 [ ('LONGINTCOL', cx_Oracle.NUMBER, 17, None, 16, 0, 0) ])
615 [ ('LONGINTCOL', cx_Oracle.DB_TYPE_NUMBER, 17, None, 16, 0,
616 0) ])
590617
591618 def testSetOutputSize(self):
592619 "test cursor.setoutputsize() does not fail (but does nothing)"
670697 result, = self.cursor.fetchone()
671698 self.assertEqual(result, expectedResult)
672699
700 def testLastRowid(self):
701 "test last rowid"
702
703 # no statement executed: no rowid
704 self.assertEqual(None, self.cursor.lastrowid)
705
706 # DDL statement executed: no rowid
707 self.cursor.execute("truncate table TestTempTable")
708 self.assertEqual(None, self.cursor.lastrowid)
709
710 # statement prepared: no rowid
711 self.cursor.prepare("insert into TestTempTable (IntCol) values (:1)")
712 self.assertEqual(None, self.cursor.lastrowid)
713
714 # multiple rows inserted: rowid of last row inserted
715 rows = [(n,) for n in range(225)]
716 self.cursor.executemany(None, rows)
717 rowid = self.cursor.lastrowid
718 self.cursor.execute("""
719 select rowid
720 from TestTempTable
721 where IntCol = :1""", rows[-1])
722 self.assertEqual(rowid, self.cursor.fetchone()[0])
723
724 # statement executed but no rows updated: no rowid
725 self.cursor.execute("delete from TestTempTable where 1 = 0")
726 self.assertEqual(None, self.cursor.lastrowid)
727
728 # stetement executed with one row updated: rowid of updated row
729 self.cursor.execute("""
730 update TestTempTable set
731 StringCol = 'Modified'
732 where IntCol = :1""", rows[-2])
733 rowid = self.cursor.lastrowid
734 self.cursor.execute("""
735 select rowid
736 from TestTempTable
737 where IntCol = :1""", rows[-2])
738 self.assertEqual(rowid, self.cursor.fetchone()[0])
739
740 # statement executed with many rows updated: rowid of last updated row
741 self.cursor.execute("""
742 update TestTempTable set
743 StringCol = 'Row ' || to_char(IntCol)
744 where IntCol = :1""", rows[-3])
745 rowid = self.cursor.lastrowid
746 self.cursor.execute("""
747 select StringCol
748 from TestTempTable
749 where rowid = :1""", [rowid])
750 self.assertEqual("Row %s" % rows[-3], self.cursor.fetchone()[0])
751
673752 if __name__ == "__main__":
674753 TestEnv.RunTestCases()
675
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 #
33 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 #
2525 end;""",
2626 cursor = cursor)
2727 self.assertEqual(cursor.description,
28 [ ('STRINGVALUE', cx_Oracle.FIXED_CHAR, 1,
28 [ ('STRINGVALUE', cx_Oracle.DB_TYPE_CHAR, 1,
2929 TestEnv.GetCharSetRatio(), None, None, 1) ])
3030 self.assertEqual(cursor.fetchall(), [('X',)])
3131
3535 self.assertEqual(cursor.description, None)
3636 self.cursor.callproc("pkg_TestRefCursors.TestOutCursor", (2, cursor))
3737 self.assertEqual(cursor.description,
38 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
39 ('STRINGCOL', cx_Oracle.STRING, 20, 20 *
38 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
39 ('STRINGCOL', cx_Oracle.DB_TYPE_VARCHAR, 20, 20 *
4040 TestEnv.GetCharSetRatio(), None, None, 0) ])
4141 self.assertEqual(cursor.fetchall(),
4242 [ (1, 'String 1'), (2, 'String 2') ])
7979 from TestNumbers
8080 order by IntCol""")
8181 self.assertEqual(self.cursor.description,
82 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
83 ('CURSORVALUE', cx_Oracle.CURSOR, None, None, None, None,
84 1) ])
82 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
83 ('CURSORVALUE', cx_Oracle.DB_TYPE_CURSOR, None, None, None,
84 None, 1) ])
8585 for i in range(1, 11):
8686 number, cursor = self.cursor.fetchone()
8787 self.assertEqual(number, i)
8989
9090 if __name__ == "__main__":
9191 TestEnv.RunTestCases()
92
173173 stringValue = "The string that will be verified"
174174 obj = typeObj.newobject()
175175 obj.STRINGVALUE = stringValue
176 outVar = self.cursor.var(cx_Oracle.OBJECT, typename = "UDT_OBJECT")
176 outVar = self.cursor.var(cx_Oracle.DB_TYPE_OBJECT,
177 typename = "UDT_OBJECT")
177178 self.cursor.execute("""
178179 insert into TestObjects (IntCol, ObjectCol)
179180 values (4, :obj)
4343 self.assertEqual(self.cursor.fetchall(), [self.dataByKey[4]])
4444
4545 def testBindDateTime(self):
46 "test binding in a Python 2.3 and higher date time"
46 "test binding in a datetime.datetime value"
4747 self.cursor.execute("""
4848 select * from TestDates
4949 where DateCol = :value""",
214214 "test cursor description is accurate"
215215 self.cursor.execute("select * from TestDates")
216216 self.assertEqual(self.cursor.description,
217 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
218 ('DATECOL', cx_Oracle.DATETIME, 23, None, None, None, 0),
219 ('NULLABLECOL', cx_Oracle.DATETIME, 23, None, None, None,
217 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
218 ('DATECOL', cx_Oracle.DB_TYPE_DATE, 23, None, None, None, 0),
219 ('NULLABLECOL', cx_Oracle.DB_TYPE_DATE, 23, None, None, None,
220220 1) ])
221221
222222 def testFetchAll(self):
0 #------------------------------------------------------------------------------
1 # Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2 #------------------------------------------------------------------------------
3
4 """
5 Module for testing comparisons with database types and API types. This also
6 contains tests for comparisons with database types and variable types, for
7 backwards compatibility.
8 """
9
10 import TestEnv
11
12 import cx_Oracle
13
14 class TestCase(TestEnv.BaseTestCase):
15
16 def __testCompare(self, dbType, apiType):
17 self.assertEqual(dbType, dbType)
18 self.assertEqual(dbType, apiType)
19 self.assertEqual(apiType, dbType)
20 self.assertNotEqual(dbType, 5)
21 self.assertNotEqual(dbType, cx_Oracle.DB_TYPE_OBJECT)
22
23 def testBfile(self):
24 "test cx_Oracle.DB_TYPE_BFILE comparisons"
25 self.assertEqual(cx_Oracle.DB_TYPE_BFILE, cx_Oracle.BFILE)
26
27 def testBinaryDouble(self):
28 "test cx_Oracle.DB_TYPE_BINARY_DOUBLE comparisons"
29 self.__testCompare(cx_Oracle.DB_TYPE_BINARY_DOUBLE, cx_Oracle.NUMBER)
30 self.assertEqual(cx_Oracle.DB_TYPE_BINARY_DOUBLE,
31 cx_Oracle.NATIVE_FLOAT)
32
33 def testBinaryFloat(self):
34 "test cx_Oracle.DB_TYPE_BINARY_FLOAT comparisons"
35 self.__testCompare(cx_Oracle.DB_TYPE_BINARY_FLOAT, cx_Oracle.NUMBER)
36
37 def testBinaryInteger(self):
38 "test cx_Oracle.DB_TYPE_BINARY_INTEGER comparisons"
39 self.__testCompare(cx_Oracle.DB_TYPE_BINARY_INTEGER, cx_Oracle.NUMBER)
40 self.assertEqual(cx_Oracle.DB_TYPE_BINARY_INTEGER,
41 cx_Oracle.NATIVE_INT)
42
43 def testBlob(self):
44 "test cx_Oracle.DB_TYPE_BLOB comparisons"
45 self.assertEqual(cx_Oracle.DB_TYPE_BLOB, cx_Oracle.BLOB)
46
47 def testBoolean(self):
48 "test cx_Oracle.DB_TYPE_BOOLEAN comparisons"
49 self.assertEqual(cx_Oracle.DB_TYPE_BOOLEAN, cx_Oracle.BOOLEAN)
50
51 def testChar(self):
52 "test cx_Oracle.DB_TYPE_CHAR comparisons"
53 self.__testCompare(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.STRING)
54 self.assertEqual(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.FIXED_CHAR)
55
56 def testClob(self):
57 "test cx_Oracle.DB_TYPE_CLOB comparisons"
58 self.assertEqual(cx_Oracle.DB_TYPE_CLOB, cx_Oracle.CLOB)
59
60 def testCursor(self):
61 "test cx_Oracle.DB_TYPE_CURSOR comparisons"
62 self.assertEqual(cx_Oracle.DB_TYPE_CURSOR, cx_Oracle.CURSOR)
63
64 def testDate(self):
65 "test cx_Oracle.DB_TYPE_DATE comparisons"
66 self.__testCompare(cx_Oracle.DB_TYPE_DATE, cx_Oracle.DATETIME)
67
68 def testIntervalDS(self):
69 "test cx_Oracle.DB_TYPE_INTERVAL_DS comparisons"
70 self.assertEqual(cx_Oracle.DB_TYPE_INTERVAL_DS, cx_Oracle.INTERVAL)
71
72 def testLong(self):
73 "test cx_Oracle.DB_TYPE_LONG comparisons"
74 self.__testCompare(cx_Oracle.DB_TYPE_LONG, cx_Oracle.STRING)
75 self.assertEqual(cx_Oracle.DB_TYPE_LONG, cx_Oracle.LONG_STRING)
76
77 def testLongRaw(self):
78 "test cx_Oracle.DB_TYPE_LONG_RAW comparisons"
79 self.__testCompare(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.BINARY)
80 self.assertEqual(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.LONG_BINARY)
81
82 def testNchar(self):
83 "test cx_Oracle.DB_TYPE_NCHAR comparisons"
84 self.__testCompare(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.STRING)
85 self.assertEqual(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.FIXED_NCHAR)
86
87 def testNclob(self):
88 "test cx_Oracle.DB_TYPE_NCLOB comparisons"
89 self.assertEqual(cx_Oracle.DB_TYPE_NCLOB, cx_Oracle.NCLOB)
90
91 def testNumber(self):
92 "test cx_Oracle.DB_TYPE_NUMBER comparisons"
93 self.__testCompare(cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.NUMBER)
94
95 def testNvarchar(self):
96 "test cx_Oracle.DB_TYPE_NVARCHAR comparisons"
97 self.__testCompare(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.STRING)
98 self.assertEqual(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.NCHAR)
99
100 def testObject(self):
101 "test cx_Oracle.DB_TYPE_OBJECT comparisons"
102 self.assertEqual(cx_Oracle.DB_TYPE_OBJECT, cx_Oracle.OBJECT)
103
104 def testRaw(self):
105 "test cx_Oracle.DB_TYPE_RAW comparisons"
106 self.__testCompare(cx_Oracle.DB_TYPE_RAW, cx_Oracle.BINARY)
107
108 def testRowid(self):
109 "test cx_Oracle.DB_TYPE_ROWID comparisons"
110 self.__testCompare(cx_Oracle.DB_TYPE_ROWID, cx_Oracle.ROWID)
111
112 def testTimestamp(self):
113 "test cx_Oracle.DB_TYPE_TIMESTAMP comparisons"
114 self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.DATETIME)
115 self.assertEqual(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.TIMESTAMP)
116
117 def testTimestampLTZ(self):
118 "test cx_Oracle.DB_TYPE_TIMESTAMP_LTZ comparisons"
119 self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_LTZ, cx_Oracle.DATETIME)
120
121 def testTimestampTZ(self):
122 "test cx_Oracle.DB_TYPE_TIMESTAMP_TZ comparisons"
123 self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_TZ, cx_Oracle.DATETIME)
124
125 def testVarchar(self):
126 "test cx_Oracle.DB_TYPE_VARCHAR comparisons"
127 self.__testCompare(cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.STRING)
128
129
130 if __name__ == "__main__":
131 TestEnv.RunTestCases()
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
22 #------------------------------------------------------------------------------
33
44 #------------------------------------------------------------------------------
66 #
77 # Drops the database objects used for the cx_Oracle test suite.
88 #------------------------------------------------------------------------------
9
10 from __future__ import print_function
119
1210 import cx_Oracle
1311 import TestEnv
1917 proxy_user = TestEnv.GetProxyUser())
2018
2119 if __name__ == "__main__":
22 conn = cx_Oracle.connect(TestEnv.GetSysdbaConnectString(),
23 mode = cx_Oracle.SYSDBA)
20 conn = cx_Oracle.connect(TestEnv.GetAdminConnectString())
2421 DropTests(conn)
2522 print("Done.")
26
1515
1616 class TestCase(TestEnv.BaseTestCase):
1717
18 def testParseError(self):
19 "test parse error returns offset correctly"
20 with self.assertRaises(cx_Oracle.Error) as cm:
21 self.cursor.execute("begin t_Missing := 5; end;")
22 errorObj, = cm.exception.args
23 self.assertEqual(errorObj.offset, 6)
24
1825 def testPickleError(self):
1926 "test picking/unpickling an error object"
20 errorObj = None
21 try:
27 with self.assertRaises(cx_Oracle.Error) as cm:
2228 self.cursor.execute("""
2329 begin
2430 raise_application_error(-20101, 'Test!');
2531 end;""")
26 except cx_Oracle.Error as e:
27 errorObj, = e.args
32 errorObj, = cm.exception.args
2833 self.assertEqual(type(errorObj), cx_Oracle._Error)
2934 self.assertTrue("Test!" in errorObj.message)
3035 self.assertEqual(errorObj.code, 20101)
4146
4247 if __name__ == "__main__":
4348 TestEnv.RunTestCases()
44
1212
1313 import cx_Oracle
1414 import datetime
15 # import sys
16
17 # if sys.version_info > (3,):
18 # long = int
1915
2016 class TestCase(TestEnv.BaseTestCase):
2117
142138 obj.DATEVALUE = datetime.datetime(2017, i + 1, 1)
143139 obj.TIMESTAMPVALUE = datetime.datetime(2017, 1, i + 1)
144140 obj.BOOLEANVALUE = (i % 2) == 1
141 obj.PLSINTEGERVALUE = i * 5
142 obj.BINARYINTEGERVALUE = i * 2
145143 arrayObj.append(obj)
146144 result = self.cursor.callfunc("pkg_TestRecords.TestInArrays", str,
147145 (arrayObj,))
149147 "udt_Record(1, 'String in record #1', " \
150148 "to_date('2017-01-01', 'YYYY-MM-DD'), " \
151149 "to_timestamp('2017-01-01 00:00:00', " \
152 "'YYYY-MM-DD HH24:MI:SS'), false); " \
150 "'YYYY-MM-DD HH24:MI:SS'), false, 0, 0); " \
153151 "udt_Record(2, 'String in record #2', " \
154152 "to_date('2017-02-01', 'YYYY-MM-DD'), " \
155153 "to_timestamp('2017-01-02 00:00:00', " \
156 "'YYYY-MM-DD HH24:MI:SS'), true); " \
154 "'YYYY-MM-DD HH24:MI:SS'), true, 5, 2); " \
157155 "udt_Record(3, 'String in record #3', " \
158156 "to_date('2017-03-01', 'YYYY-MM-DD'), " \
159157 "to_timestamp('2017-01-03 00:00:00', " \
160 "'YYYY-MM-DD HH24:MI:SS'), false)")
158 "'YYYY-MM-DD HH24:MI:SS'), false, 10, 4)")
161159
162160 def testBindPLSQLRecordIn(self):
163161 "test binding a PL/SQL record (in)"
168166 obj.DATEVALUE = datetime.datetime(2016, 2, 15)
169167 obj.TIMESTAMPVALUE = datetime.datetime(2016, 2, 12, 14, 25, 36)
170168 obj.BOOLEANVALUE = False
169 obj.PLSINTEGERVALUE = 21
170 obj.BINARYINTEGERVALUE = 5
171171 result = self.cursor.callfunc("pkg_TestRecords.GetStringRep", str,
172172 (obj,))
173173 self.assertEqual(result,
174174 "udt_Record(18, 'A string in a record', " \
175175 "to_date('2016-02-15', 'YYYY-MM-DD'), " \
176176 "to_timestamp('2016-02-12 14:25:36', " \
177 "'YYYY-MM-DD HH24:MI:SS'), false)")
177 "'YYYY-MM-DD HH24:MI:SS'), false, 21, 5)")
178178
179179 def testBindPLSQLRecordOut(self):
180180 "test binding a PL/SQL record (out)"
185185 obj.DATEVALUE = datetime.datetime.today()
186186 obj.TIMESTAMPVALUE = datetime.datetime.today()
187187 obj.BOOLEANVALUE = False
188 obj.PLSINTEGERVALUE = 23
189 obj.BINARYINTEGERVALUE = 9
188190 self.cursor.callproc("pkg_TestRecords.TestOut", (obj,))
189191 self.assertEqual(obj.NUMBERVALUE, 25)
190192 self.assertEqual(obj.STRINGVALUE, "String in record")
192194 self.assertEqual(obj.TIMESTAMPVALUE,
193195 datetime.datetime(2016, 2, 16, 18, 23, 55))
194196 self.assertEqual(obj.BOOLEANVALUE, True)
197 self.assertEqual(obj.PLSINTEGERVALUE, 45)
198 self.assertEqual(obj.BINARYINTEGERVALUE, 10)
195199
196200 def testBindPLSQLStringCollectionIn(self):
197201 "test binding a PL/SQL string collection (in)"
286290 statement = "delete from TestArrayDML where IntCol2 = :1"
287291 self.cursor.executemany(statement, rows, arraydmlrowcounts = True)
288292 self.assertEqual(self.cursor.getarraydmlrowcounts(), [1, 3, 2])
293 self.assertEqual(self.cursor.rowcount, 6)
289294
290295 def testExecutingUpdate(self):
291296 "test executing update statement with arraydmlrowcount mode"
308313 sql = "update TestArrayDML set StringCol = :1 where IntCol2 = :2"
309314 self.cursor.executemany(sql, rows, arraydmlrowcounts = True)
310315 self.assertEqual(self.cursor.getarraydmlrowcounts(), [1, 1, 3, 2])
316 self.assertEqual(self.cursor.rowcount, 7)
311317
312318 def testImplicitResults(self):
313319 "test getimplicitresults() returns the correct data"
3333
3434 def testBindInterval(self):
3535 "test binding in an interval"
36 self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
36 self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
3737 self.cursor.execute("""
3838 select * from TestIntervals
3939 where IntervalCol = :value""",
4343
4444 def testBindNull(self):
4545 "test binding in a null"
46 self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
46 self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
4747 self.cursor.execute("""
4848 select * from TestIntervals
4949 where IntervalCol = :value""",
5252
5353 def testBindOutSetInputSizes(self):
5454 "test binding out with set input sizes defined"
55 vars = self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
55 vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
5656 self.cursor.execute("""
5757 begin
5858 :value := to_dsinterval('8 09:24:18.123789');
6363
6464 def testBindInOutSetInputSizes(self):
6565 "test binding in/out with set input sizes defined"
66 vars = self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
66 vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
6767 self.cursor.execute("""
6868 begin
6969 :value := :value + to_dsinterval('5 08:30:00');
7474
7575 def testBindInOutFractionalSecond(self):
7676 "test binding in/out with set input sizes defined"
77 vars = self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
77 vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
7878 self.cursor.execute("""
7979 begin
8080 :value := :value + to_dsinterval('5 08:30:00');
8686
8787 def testBindOutVar(self):
8888 "test binding out with cursor.var() method"
89 var = self.cursor.var(cx_Oracle.INTERVAL)
89 var = self.cursor.var(cx_Oracle.DB_TYPE_INTERVAL_DS)
9090 self.cursor.execute("""
9191 begin
9292 :value := to_dsinterval('15 18:35:45.586');
9898
9999 def testBindInOutVarDirectSet(self):
100100 "test binding in/out with cursor.var() method"
101 var = self.cursor.var(cx_Oracle.INTERVAL)
101 var = self.cursor.var(cx_Oracle.DB_TYPE_INTERVAL_DS)
102102 var.setvalue(0, datetime.timedelta(days = 1, minutes = 50))
103103 self.cursor.execute("""
104104 begin
112112 "test cursor description is accurate"
113113 self.cursor.execute("select * from TestIntervals")
114114 self.assertEqual(self.cursor.description,
115 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
116 ('INTERVALCOL', cx_Oracle.INTERVAL, None, None, 2, 6, 0),
117 ('NULLABLECOL', cx_Oracle.INTERVAL, None, None, 2, 6, 1) ])
115 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
116 ('INTERVALCOL', cx_Oracle.DB_TYPE_INTERVAL_DS, None, None, 2,
117 6, 0),
118 ('NULLABLECOL', cx_Oracle.DB_TYPE_INTERVAL_DS, None, None, 2,
119 6, 1) ])
118120
119121 def testFetchAll(self):
120122 "test that fetching all of the data returns the correct results"
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 #
33 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 #
116116
117117 def __ValidateQuery(self, rows, lobType):
118118 longString = ""
119 dbType = getattr(cx_Oracle, "DB_TYPE_" + lobType)
119120 for row in rows:
120121 integerValue, lob = row
122 self.assertEqual(lob.type, dbType)
121123 if integerValue == 0:
122124 self.assertEqual(lob.size(), 0)
123125 expectedValue = ""
157159 "test cursor description is accurate for BLOBs"
158160 self.cursor.execute("select * from TestBLOBs")
159161 self.assertEqual(self.cursor.description,
160 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
161 ('BLOBCOL', cx_Oracle.BLOB, None, None, None, None, 0) ])
162 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
163 ('BLOBCOL', cx_Oracle.DB_TYPE_BLOB, None, None, None, None,
164 0) ])
162165
163166 def testBLOBsDirect(self):
164167 "test binding and fetching BLOB data (directly)"
165 self.__PerformTest("BLOB", cx_Oracle.BLOB)
168 self.__PerformTest("BLOB", cx_Oracle.DB_TYPE_BLOB)
166169
167170 def testBLOBsIndirect(self):
168171 "test binding and fetching BLOB data (indirectly)"
169 self.__PerformTest("BLOB", cx_Oracle.LONG_BINARY)
172 self.__PerformTest("BLOB", cx_Oracle.DB_TYPE_LONG_RAW)
170173
171174 def testBLOBOperations(self):
172175 "test operations on BLOBs"
176179 "test cursor description is accurate for CLOBs"
177180 self.cursor.execute("select * from TestCLOBs")
178181 self.assertEqual(self.cursor.description,
179 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
180 ('CLOBCOL', cx_Oracle.CLOB, None, None, None, None, 0) ])
182 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
183 ('CLOBCOL', cx_Oracle.DB_TYPE_CLOB, None, None, None, None,
184 0) ])
181185
182186 def testCLOBsDirect(self):
183187 "test binding and fetching CLOB data (directly)"
184 self.__PerformTest("CLOB", cx_Oracle.CLOB)
188 self.__PerformTest("CLOB", cx_Oracle.DB_TYPE_CLOB)
185189
186190 def testCLOBsIndirect(self):
187191 "test binding and fetching CLOB data (indirectly)"
188 self.__PerformTest("CLOB", cx_Oracle.LONG_STRING)
192 self.__PerformTest("CLOB", cx_Oracle.DB_TYPE_LONG)
189193
190194 def testCLOBOperations(self):
191195 "test operations on CLOBs"
214218 "test cursor description is accurate for NCLOBs"
215219 self.cursor.execute("select * from TestNCLOBs")
216220 self.assertEqual(self.cursor.description,
217 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
218 ('NCLOBCOL', cx_Oracle.NCLOB, None, None, None, None, 0) ])
221 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
222 ('NCLOBCOL', cx_Oracle.DB_TYPE_NCLOB, None, None, None, None,
223 0) ])
219224
220225 def testNCLOBsDirect(self):
221226 "test binding and fetching NCLOB data (directly)"
222 self.__PerformTest("NCLOB", cx_Oracle.NCLOB)
227 self.__PerformTest("NCLOB", cx_Oracle.DB_TYPE_NCLOB)
223228
224229 def testNCLOBDifferentEncodings(self):
225230 "test binding and fetching NCLOB data (different encodings)"
229234 value = u"\u03b4\u4e2a"
230235 cursor = connection.cursor()
231236 cursor.execute("truncate table TestNCLOBs")
232 cursor.setinputsizes(val = cx_Oracle.NCHAR)
237 cursor.setinputsizes(val = cx_Oracle.DB_TYPE_NVARCHAR)
233238 cursor.execute("insert into TestNCLOBs values (1, :val)", val = value)
234239 cursor.execute("select NCLOBCol from TestNCLOBs")
235240 nclob, = cursor.fetchone()
236 cursor.setinputsizes(val = cx_Oracle.NCHAR)
241 cursor.setinputsizes(val = cx_Oracle.DB_TYPE_NVARCHAR)
237242 cursor.execute("update TestNCLOBs set NCLOBCol = :val",
238243 val = nclob.read() + value)
239244 cursor.execute("select NCLOBCol from TestNCLOBs")
242247
243248 def testNCLOBsIndirect(self):
244249 "test binding and fetching NCLOB data (indirectly)"
245 self.__PerformTest("NCLOB", cx_Oracle.LONG_STRING)
250 self.__PerformTest("NCLOB", cx_Oracle.DB_TYPE_LONG)
246251
247252 def testNCLOBOperations(self):
248253 "test operations on NCLOBs"
253258 cursor = self.connection.cursor()
254259 cursor.arraysize = self.cursor.arraysize
255260 cursor.execute("""
256 select sid
257 from v$session
258 where audsid = userenv('sessionid')""")
261 select sys_context('USERENV', 'SID')
262 from dual""")
259263 sid, = cursor.fetchone()
260264 tempLobs = self.__GetTempLobs(sid)
261265 self.assertEqual(tempLobs, 0)
271275
272276 def testAssignStringBeyondArraySize(self):
273277 "test assign string to NCLOB beyond array size"
274 nclobVar = self.cursor.var(cx_Oracle.NCLOB)
278 nclobVar = self.cursor.var(cx_Oracle.DB_TYPE_NCLOB)
275279 self.assertRaises(IndexError, nclobVar.setvalue, 1, "test char")
276280
277281 if __name__ == "__main__":
5858
5959 def testLongs(self):
6060 "test binding and fetching long data"
61 self.__PerformTest("Long", cx_Oracle.LONG_STRING)
61 self.__PerformTest("Long", cx_Oracle.DB_TYPE_LONG)
6262
6363 def testLongWithExecuteMany(self):
6464 "test binding long data with executemany()"
7676
7777 def testLongRaws(self):
7878 "test binding and fetching long raw data"
79 self.__PerformTest("LongRaw", cx_Oracle.LONG_BINARY)
79 self.__PerformTest("LongRaw", cx_Oracle.DB_TYPE_LONG_RAW)
8080
8181 def testLongCursorDescription(self):
8282 "test cursor description is accurate for longs"
8383 self.cursor.execute("select * from TestLongs")
8484 self.assertEqual(self.cursor.description,
85 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
86 ('LONGCOL', cx_Oracle.LONG_STRING, None, None, None, None,
85 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
86 ('LONGCOL', cx_Oracle.DB_TYPE_LONG, None, None, None, None,
8787 0) ])
8888
8989 def testLongRawCursorDescription(self):
9090 "test cursor description is accurate for long raws"
9191 self.cursor.execute("select * from TestLongRaws")
9292 self.assertEqual(self.cursor.description,
93 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
94 ('LONGRAWCOL', cx_Oracle.LONG_BINARY, None, None, None, None,
95 0) ])
93 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
94 ('LONGRAWCOL', cx_Oracle.DB_TYPE_LONG_RAW, None, None, None,
95 None, 0) ])
9696
9797 def testArraySizeTooLarge(self):
9898 "test array size too large generates an exception"
4242
4343 def testBindUnicode(self):
4444 "test binding in a unicode"
45 self.cursor.setinputsizes(value = cx_Oracle.NCHAR)
45 self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_NVARCHAR)
4646 self.cursor.execute("""
4747 select * from TestUnicodes
4848 where UnicodeCol = :value""",
5151
5252 def testBindDifferentVar(self):
5353 "test binding a different variable on second execution"
54 retval_1 = self.cursor.var(cx_Oracle.NCHAR, 30)
55 retval_2 = self.cursor.var(cx_Oracle.NCHAR, 30)
54 retval_1 = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR, 30)
55 retval_2 = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR, 30)
5656 self.cursor.execute(r"begin :retval := unistr('Called \3042'); end;",
5757 retval = retval_1)
5858 self.assertEqual(retval_1.getvalue(), u"Called \u3042")
6262
6363 def testBindUnicodeAfterNumber(self):
6464 "test binding in a unicode after setting input sizes to a number"
65 unicodeVal = self.cursor.var(cx_Oracle.NCHAR)
65 unicodeVal = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR)
6666 unicodeVal.setvalue(0, u"Unicode \u3042 6")
6767 self.cursor.setinputsizes(value = cx_Oracle.NUMBER)
6868 self.cursor.execute("""
7575 "test binding in a unicode array"
7676 returnValue = self.cursor.var(cx_Oracle.NUMBER)
7777 array = [r[1] for r in self.rawData]
78 arrayVar = self.cursor.arrayvar(cx_Oracle.NCHAR, array)
78 arrayVar = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, array)
7979 statement = """
8080 begin
8181 :retval := pkg_TestUnicodeArrays.TestInArrays(
8787 array = arrayVar)
8888 self.assertEqual(returnValue.getvalue(), 116)
8989 array = [ u"Unicode - \u3042 %d" % i for i in range(15) ]
90 arrayVar = self.cursor.arrayvar(cx_Oracle.NCHAR, array)
90 arrayVar = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, array)
9191 self.cursor.execute(statement,
9292 integerValue = 8,
9393 array = arrayVar)
9696 def testBindUnicodeArrayBySizes(self):
9797 "test binding in a unicode array (with setinputsizes)"
9898 returnValue = self.cursor.var(cx_Oracle.NUMBER)
99 self.cursor.setinputsizes(array = [cx_Oracle.NCHAR, 10])
99 self.cursor.setinputsizes(array = [cx_Oracle.DB_TYPE_NVARCHAR, 10])
100100 array = [r[1] for r in self.rawData]
101101 self.cursor.execute("""
102102 begin
111111 def testBindUnicodeArrayByVar(self):
112112 "test binding in a unicode array (with arrayvar)"
113113 returnValue = self.cursor.var(cx_Oracle.NUMBER)
114 array = self.cursor.arrayvar(cx_Oracle.NCHAR, 10, 20)
114 array = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, 10, 20)
115115 array.setvalue(0, [r[1] for r in self.rawData])
116116 self.cursor.execute("""
117117 begin
125125
126126 def testBindInOutUnicodeArrayByVar(self):
127127 "test binding in/out a unicode array (with arrayvar)"
128 array = self.cursor.arrayvar(cx_Oracle.NCHAR, 10, 100)
128 array = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, 10, 100)
129129 originalData = [r[1] for r in self.rawData]
130130 format = u"Converted element \u3042 # %d originally had length %d"
131131 expectedData = [format % (i, len(originalData[i - 1])) \
141141
142142 def testBindOutUnicodeArrayByVar(self):
143143 "test binding out a unicode array (with arrayvar)"
144 array = self.cursor.arrayvar(cx_Oracle.NCHAR, 6, 100)
144 array = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, 6, 100)
145145 format = u"Test out element \u3042 # %d"
146146 expectedData = [format % i for i in range(1, 7)]
147147 self.cursor.execute("""
162162
163163 def testBindOutSetInputSizesByType(self):
164164 "test binding out with set input sizes defined (by type)"
165 vars = self.cursor.setinputsizes(value = cx_Oracle.NCHAR)
165 vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_NVARCHAR)
166166 self.cursor.execute(r"""
167167 begin
168168 :value := unistr('TSI \3042');
171171
172172 def testBindInOutSetInputSizesByType(self):
173173 "test binding in/out with set input sizes defined (by type)"
174 vars = self.cursor.setinputsizes(value = cx_Oracle.NCHAR)
174 vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_NVARCHAR)
175175 self.cursor.execute(r"""
176176 begin
177177 :value := :value || unistr(' TSI \3042');
182182
183183 def testBindOutVar(self):
184184 "test binding out with cursor.var() method"
185 var = self.cursor.var(cx_Oracle.NCHAR)
185 var = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR)
186186 self.cursor.execute(r"""
187187 begin
188188 :value := unistr('TSI (VAR) \3042');
192192
193193 def testBindInOutVarDirectSet(self):
194194 "test binding in/out with cursor.var() method"
195 var = self.cursor.var(cx_Oracle.NCHAR)
195 var = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR)
196196 var.setvalue(0, u"InVal \u3041")
197197 self.cursor.execute(r"""
198198 begin
205205 "test cursor description is accurate"
206206 self.cursor.execute("select * from TestUnicodes")
207207 self.assertEqual(self.cursor.description,
208 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
209 ('UNICODECOL', cx_Oracle.NCHAR, 20, 80, None, None, 0),
210 ('FIXEDUNICODECOL', cx_Oracle.FIXED_NCHAR, 40, 160, None,
208 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
209 ('UNICODECOL', cx_Oracle.DB_TYPE_NVARCHAR, 20, 80, None,
211210 None, 0),
212 ('NULLABLECOL', cx_Oracle.NCHAR, 50, 200, None, None, 1) ])
211 ('FIXEDUNICODECOL', cx_Oracle.DB_TYPE_NCHAR, 40, 160, None,
212 None, 0),
213 ('NULLABLECOL', cx_Oracle.DB_TYPE_NVARCHAR, 50, 200, None,
214 None, 1) ])
213215
214216 def testFetchAll(self):
215217 "test that fetching all of the data returns the correct results"
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 #
33 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 #
1818
1919 def outputTypeHandlerNativeInt(self, cursor, name, defaultType, size,
2020 precision, scale):
21 return cursor.var(cx_Oracle.NATIVE_INT, arraysize=cursor.arraysize)
21 return cursor.var(cx_Oracle.DB_TYPE_BINARY_INTEGER,
22 arraysize=cursor.arraysize)
2223
2324 def outputTypeHandlerDecimal(self, cursor, name, defaultType, size,
2425 precision, scale):
4950 (True,))
5051 self.assertEqual(result, "TRUE")
5152
53 def testBindBooleanAsNumber(self):
54 "test binding in a boolean as a number"
55 var = self.cursor.var(cx_Oracle.NUMBER)
56 var.setvalue(0, True)
57 self.cursor.execute("select :1 from dual", [var])
58 result, = self.cursor.fetchone()
59 self.assertEqual(result, 1)
60 var.setvalue(0, False)
61 self.cursor.execute("select :1 from dual", [var])
62 result, = self.cursor.fetchone()
63 self.assertEqual(result, 0)
64
5265 def testBindDecimal(self):
5366 "test binding in a decimal.Decimal"
5467 self.cursor.execute("""
259272 "test cursor description is accurate"
260273 self.cursor.execute("select * from TestNumbers")
261274 self.assertEqual(self.cursor.description,
262 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
263 ('LONGINTCOL', cx_Oracle.NUMBER, 17, None, 16, 0, 0),
264 ('NUMBERCOL', cx_Oracle.NUMBER, 13, None, 9, 2, 0),
265 ('FLOATCOL', cx_Oracle.NUMBER, 127, None, 126, -127, 0),
266 ('UNCONSTRAINEDCOL', cx_Oracle.NUMBER, 127, None, 0, -127, 0),
267 ('NULLABLECOL', cx_Oracle.NUMBER, 39, None, 38, 0, 1) ])
275 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
276 ('LONGINTCOL', cx_Oracle.DB_TYPE_NUMBER, 17, None, 16, 0, 0),
277 ('NUMBERCOL', cx_Oracle.DB_TYPE_NUMBER, 13, None, 9, 2, 0),
278 ('FLOATCOL', cx_Oracle.DB_TYPE_NUMBER, 127, None, 126, -127,
279 0),
280 ('UNCONSTRAINEDCOL', cx_Oracle.DB_TYPE_NUMBER, 127, None, 0,
281 -127, 0),
282 ('NULLABLECOL', cx_Oracle.DB_TYPE_NUMBER, 39, None, 38, 0,
283 1) ])
268284
269285 def testFetchAll(self):
270286 "test that fetching all of the data returns the correct results"
320336 decimal.Decimal("-9.99999999999999e+125"), 0.0, 1e-130,
321337 -1e-130]
322338 outValues = [int("9" * 15 + "0" * 111), -int("9" * 15 + "0" * 111),
323 0, decimal.Decimal("1e-130"), decimal.Decimal("-1e-130")]
339 0, 1e-130, -1e-130]
324340 for inValue, outValue in zip(inValues, outValues):
325341 self.cursor.execute("select :1 from dual", (inValue,))
326342 result, = self.cursor.fetchone()
350366 from TestNumbers
351367 where IntCol = 1""")
352368 result, = self.cursor.fetchone()
353 self.assertAlmostEqual(result,
354 decimal.Decimal("1") / decimal.Decimal("7"))
369 self.assertEqual(result, 1.0 / 7.0)
370 self.assertTrue(isinstance(result, float), "float not returned")
355371
356372 def testStringFormat(self):
357373 "test that string format is returned properly"
358374 var = self.cursor.var(cx_Oracle.NUMBER)
359 self.assertEqual(str(var), "<cx_Oracle.NUMBER with value None>")
375 self.assertEqual(str(var),
376 "<cx_Oracle.Var of type DB_TYPE_NUMBER with value None>")
360377 var.setvalue(0, 4)
361 self.assertEqual(str(var), "<cx_Oracle.NUMBER with value 4.0>")
378 self.assertEqual(str(var),
379 "<cx_Oracle.Var of type DB_TYPE_NUMBER with value 4.0>")
362380
363381 def testBindNativeFloat(self):
364382 "test that binding native float is possible"
365 self.cursor.setinputsizes(cx_Oracle.NATIVE_FLOAT)
383 self.cursor.setinputsizes(cx_Oracle.DB_TYPE_BINARY_DOUBLE)
366384 self.cursor.execute("select :1 from dual", (5,))
367 self.assertEqual(type(self.cursor.bindvars[0]), cx_Oracle.NATIVE_FLOAT)
385 self.assertEqual(self.cursor.bindvars[0].type,
386 cx_Oracle.DB_TYPE_BINARY_DOUBLE)
368387 value, = self.cursor.fetchone()
369388 self.assertEqual(value, 5)
370389 self.cursor.execute("select :1 from dual", (1.5,))
371 self.assertEqual(type(self.cursor.bindvars[0]), cx_Oracle.NATIVE_FLOAT)
390 self.assertEqual(self.cursor.bindvars[0].type,
391 cx_Oracle.DB_TYPE_BINARY_DOUBLE)
372392 value, = self.cursor.fetchone()
373393 self.assertEqual(value, 1.5)
374394 self.cursor.execute("select :1 from dual", (decimal.Decimal("NaN"),))
375 self.assertEqual(type(self.cursor.bindvars[0]), cx_Oracle.NATIVE_FLOAT)
395 self.assertEqual(self.cursor.bindvars[0].type,
396 cx_Oracle.DB_TYPE_BINARY_DOUBLE)
376397 value, = self.cursor.fetchone()
377398 self.assertEqual(str(value), str(float("NaN")))
378399
386407
387408 if __name__ == "__main__":
388409 TestEnv.RunTestCases()
389
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 #
33 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 #
4949
5050 def testBindNullIn(self):
5151 "test binding a null value (IN)"
52 var = self.cursor.var(cx_Oracle.OBJECT, typename = "UDT_OBJECT")
52 var = self.cursor.var(cx_Oracle.DB_TYPE_OBJECT,
53 typename = "UDT_OBJECT")
5354 result = self.cursor.callfunc("pkg_TestBindObject.GetStringRep", str,
5455 (var,))
5556 self.assertEqual(result, "null")
112113
113114 def testFetchData(self):
114115 "test fetching objects"
116 self.cursor.execute("alter session set time_zone = 'UTC'")
115117 self.cursor.execute("""
116118 select
117119 IntCol,
120122 from TestObjects
121123 order by IntCol""")
122124 self.assertEqual(self.cursor.description,
123 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
124 ('OBJECTCOL', cx_Oracle.OBJECT, None, None, None, None, 1),
125 ('ARRAYCOL', cx_Oracle.OBJECT, None, None, None, None, 1) ])
125 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
126 ('OBJECTCOL', cx_Oracle.DB_TYPE_OBJECT, None, None, None,
127 None, 1),
128 ('ARRAYCOL', cx_Oracle.DB_TYPE_OBJECT, None, None, None,
129 None, 1) ])
126130 self.__TestData(1, (1, 'First row', 'First ', 'N First Row',
127131 'N First ', b'Raw Data 1', 2, 5, 12.125, 0.5, 12.5, 25.25,
128132 50.125, cx_Oracle.Timestamp(2007, 3, 6, 0, 0, 0),
152156 self.assertEqual(typeObj.iscollection, False)
153157 self.assertEqual(typeObj.schema, self.connection.username.upper())
154158 self.assertEqual(typeObj.name, "UDT_OBJECT")
159 subObjectValueType = self.connection.gettype("UDT_SUBOBJECT")
160 subObjectArrayType = self.connection.gettype("UDT_OBJECTARRAY")
155161 expectedAttributeNames = ["NUMBERVALUE", "STRINGVALUE",
156162 "FIXEDCHARVALUE", "NSTRINGVALUE", "NFIXEDCHARVALUE",
157163 "RAWVALUE", "INTVALUE", "SMALLINTVALUE", "REALVALUE",
161167 "NCLOBVALUE", "BLOBVALUE", "SUBOBJECTVALUE", "SUBOBJECTARRAY"]
162168 actualAttributeNames = [a.name for a in typeObj.attributes]
163169 self.assertEqual(actualAttributeNames, expectedAttributeNames)
164 typeObj = self.connection.gettype("UDT_OBJECTARRAY")
165 self.assertEqual(typeObj.iscollection, True)
166 self.assertEqual(typeObj.attributes, [])
170 expectedAttributeTypes = [cx_Oracle.DB_TYPE_NUMBER,
171 cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.DB_TYPE_CHAR,
172 cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.DB_TYPE_NCHAR,
173 cx_Oracle.DB_TYPE_RAW, cx_Oracle.DB_TYPE_NUMBER,
174 cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.DB_TYPE_NUMBER,
175 cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.DB_TYPE_NUMBER,
176 cx_Oracle.DB_TYPE_BINARY_FLOAT,
177 cx_Oracle.DB_TYPE_BINARY_DOUBLE,
178 cx_Oracle.DB_TYPE_DATE, cx_Oracle.DB_TYPE_TIMESTAMP,
179 cx_Oracle.DB_TYPE_TIMESTAMP_TZ,
180 cx_Oracle.DB_TYPE_TIMESTAMP_LTZ, cx_Oracle.DB_TYPE_CLOB,
181 cx_Oracle.DB_TYPE_NCLOB, cx_Oracle.DB_TYPE_BLOB,
182 subObjectValueType, subObjectArrayType]
183 actualAttributeTypes = [a.type for a in typeObj.attributes]
184 self.assertEqual(actualAttributeTypes, expectedAttributeTypes)
185 self.assertEqual(subObjectArrayType.iscollection, True)
186 self.assertEqual(subObjectArrayType.attributes, [])
167187
168188 def testObjectType(self):
169189 "test object type data"
180200
181201 def testRoundTripObject(self):
182202 "test inserting and then querying object with all data types"
203 self.cursor.execute("alter session set time_zone = 'UTC'")
183204 self.cursor.execute("truncate table TestClobs")
184205 self.cursor.execute("truncate table TestNClobs")
185206 self.cursor.execute("truncate table TestBlobs")
237258 cx_Oracle.Timestamp(1999, 11, 12, 23, 5, 2),
238259 'A short CLOB', 'A short NCLOB', b'A short BLOB',
239260 (23, 'Substring value'), None), None)
261 obj.CLOBVALUE = "A short CLOB (modified)"
262 obj.NCLOBVALUE = "A short NCLOB (modified)"
263 obj.BLOBVALUE = "A short BLOB (modified)"
264 self.cursor.execute("insert into TestObjects (IntCol, ObjectCol) " \
265 "values (5, :obj)", obj = obj)
266 self.cursor.execute("""
267 select IntCol, ObjectCol, ArrayCol
268 from TestObjects
269 where IntCol = 5""")
270 self.__TestData(5, (5, 'A string', 'Fixed str ', 'A NCHAR string',
271 'Fixed N ', b'Raw Value', 27, 13, 184.875, 1.375, 23.75,
272 14.25, 29.1625, cx_Oracle.Timestamp(2017, 5, 9, 0, 0, 0),
273 cx_Oracle.Timestamp(2017, 5, 9, 9, 41, 13),
274 cx_Oracle.Timestamp(1986, 8, 2, 15, 27, 38),
275 cx_Oracle.Timestamp(1999, 11, 12, 23, 5, 2),
276 'A short CLOB (modified)', 'A short NCLOB (modified)',
277 b'A short BLOB (modified)',
278 (23, 'Substring value'), None), None)
240279 self.connection.rollback()
241280
242281 def testInvalidTypeObject(self):
295334 "test setting value of object variable to wrong object type"
296335 wrongObjType = self.connection.gettype("UDT_OBJECTARRAY")
297336 wrongObj = wrongObjType.newobject()
298 var = self.cursor.var(cx_Oracle.OBJECT, typename = "UDT_OBJECT")
337 var = self.cursor.var(cx_Oracle.DB_TYPE_OBJECT,
338 typename = "UDT_OBJECT")
299339 self.assertRaises(cx_Oracle.DatabaseError, var.setvalue, 0, wrongObj)
300340
301341 def testStringFormat(self):
9595 getmode=cx_Oracle.SPOOL_ATTRVAL_WAIT)
9696 self.assertEqual(pool.homogeneous, 1,
9797 "homogeneous should be 1 by default")
98 self.assertRaises(cx_Oracle.ProgrammingError, pool.acquire,
98 self.assertRaises(cx_Oracle.DatabaseError, pool.acquire,
9999 user = u"missing_proxyuser")
100100 pool = TestEnv.GetPool(min=2, max=8, increment=3,
101101 getmode=cx_Oracle.SPOOL_ATTRVAL_WAIT, homogeneous=False)
225225 TestEnv.GetMainPassword()), TestEnv.GetProxyUser(),
226226 TestEnv.GetMainUser())
227227
228 def testHeterogenousWithoutPassword(self):
229 """test heterogeneous pool without password"""
230 pool = TestEnv.GetPool(min=2, max=8, increment=3,
231 getmode=cx_Oracle.SPOOL_ATTRVAL_WAIT, homogeneous=False)
232 self.assertRaises(cx_Oracle.DatabaseError, pool.acquire,
233 TestEnv.GetMainUser())
234
235228 def testHeterogeneousWrongPassword(self):
236229 """test heterogeneous pool with wrong password specified"""
237230 pool = TestEnv.GetPool(min=2, max=8, increment=3,
239232 self.assertRaises(cx_Oracle.DatabaseError, pool.acquire,
240233 TestEnv.GetProxyUser(), "this is the wrong password")
241234
235 def testTaggingSession(self):
236 "test tagging a session"
237 pool = TestEnv.GetPool(min=2, max=8, increment=3,
238 getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT)
239
240 tagMST = "TIME_ZONE=MST"
241 tagUTC = "TIME_ZONE=UTC"
242
243 conn = pool.acquire()
244 self.assertEqual(conn.tag, None)
245 pool.release(conn, tag=tagMST)
246
247 conn = pool.acquire()
248 self.assertEqual(conn.tag, None)
249 conn.tag = tagUTC
250 conn.close()
251
252 conn = pool.acquire(tag=tagMST)
253 self.assertEqual(conn.tag, tagMST)
254 conn.close()
255
256 conn = pool.acquire(tag=tagUTC)
257 self.assertEqual(conn.tag, tagUTC)
258 conn.close()
259
260 def testPLSQLSessionCallbacks(self):
261 "test PL/SQL session callbacks"
262 clientVersion = cx_Oracle.clientversion()
263 if clientVersion < (12, 2):
264 self.skipTest("PL/SQL session callbacks not supported before 12.2")
265 pool = TestEnv.GetPool(min=2, max=8, increment=3,
266 getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT,
267 sessionCallback="pkg_SessionCallback.TheCallback")
268 tags = ["NLS_DATE_FORMAT=SIMPLE", "NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC",
269 "NLS_DATE_FORMAT=FULL;TIME_ZONE=MST"]
270 actualTags = [None, None, "NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC"]
271
272 # truncate PL/SQL session callback log
273 conn = pool.acquire()
274 cursor = conn.cursor()
275 cursor.execute("truncate table PLSQLSessionCallbacks")
276 conn.close()
277
278 # request sessions with each of the first two tags
279 for tag in tags[:2]:
280 conn = pool.acquire(tag=tag)
281 conn.close()
282
283 # for the last tag, use the matchanytag flag
284 conn = pool.acquire(tag=tags[2], matchanytag=True)
285 conn.close()
286
287 # verify the PL/SQL session callback log is accurate
288 conn = pool.acquire()
289 cursor = conn.cursor()
290 cursor.execute("""
291 select RequestedTag, ActualTag
292 from PLSQLSessionCallbacks
293 order by FixupTimestamp""")
294 results = cursor.fetchall()
295 expectedResults = list(zip(tags, actualTags))
296 self.assertEqual(results, expectedResults)
297
298 def testTaggingInvalidKey(self):
299 """testTagging with Invalid key"""
300 pool = TestEnv.GetPool(getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT)
301 conn = pool.acquire()
302 self.assertRaises(TypeError, pool.release, conn, tag=12345)
303 clientVersion = cx_Oracle.clientversion()
304 if clientVersion >= (12, 2):
305 self.assertRaises(cx_Oracle.DatabaseError, pool.release, conn,
306 tag="INVALID_TAG")
307
242308 if __name__ == "__main__":
243309 TestEnv.RunTestCases()
244310
88 # necessary for the cx_Oracle test suite.
99 #------------------------------------------------------------------------------
1010
11 from __future__ import print_function
12
1311 import cx_Oracle
1412
1513 import TestEnv
1614 import DropTest
1715
18 # connect as SYSDBA
19 conn = cx_Oracle.connect(TestEnv.GetSysdbaConnectString(),
20 mode = cx_Oracle.SYSDBA)
16 # connect as administrative user (usually SYSTEM or ADMIN)
17 conn = cx_Oracle.connect(TestEnv.GetAdminConnectString())
2118
2219 # drop existing users and editions, if applicable
2320 DropTest.DropTests(conn)
1818 def testInvalidJson(self):
1919 "test inserting invalid JSON value into SODA collection"
2020 invalidJson = "{testKey:testValue}"
21 sodaDatabase = self.connection.getSodaDatabase()
21 sodaDatabase = self.getSodaDatabase()
2222 coll = sodaDatabase.createCollection("cxoInvalidJSON")
2323 doc = sodaDatabase.createDocument(invalidJson)
2424 self.assertRaises(cx_Oracle.IntegrityError, coll.insertOne, doc)
2626
2727 def testInsertDocuments(self):
2828 "test inserting documents into a SODA collection"
29 sodaDatabase = self.connection.getSodaDatabase()
29 sodaDatabase = self.getSodaDatabase()
3030 coll = sodaDatabase.createCollection("cxoInsertDocs")
3131 coll.find().remove()
3232 valuesToInsert = [
4848
4949 def testSkipDocuments(self):
5050 "test skipping documents in a SODA collection"
51 sodaDatabase = self.connection.getSodaDatabase()
51 sodaDatabase = self.getSodaDatabase()
5252 coll = sodaDatabase.createCollection("cxoSkipDocs")
5353 coll.find().remove()
5454 valuesToInsert = [
6868
6969 def testReplaceDocument(self):
7070 "test replace documents in SODA collection"
71 sodaDatabase = self.connection.getSodaDatabase()
71 sodaDatabase = self.getSodaDatabase()
7272 coll = sodaDatabase.createCollection("cxoReplaceDoc")
7373 coll.find().remove()
7474 content = {'name': 'John', 'address': {'city': 'Sydney'}}
8282
8383 def testSearchDocumentsWithContent(self):
8484 "test search documents with content using $like and $regex"
85 sodaDatabase = self.connection.getSodaDatabase()
85 sodaDatabase = self.getSodaDatabase()
8686 coll = sodaDatabase.createCollection("cxoSearchDocContent")
8787 coll.find().remove()
8888 data = [
119119
120120 def testDocumentRemove(self):
121121 "test removing documents"
122 sodaDatabase = self.connection.getSodaDatabase()
122 sodaDatabase = self.getSodaDatabase()
123123 coll = sodaDatabase.createCollection("cxoRemoveDocs")
124124 coll.find().remove()
125125 data = [
155155 }
156156 ]
157157 }
158 sodaDatabase = self.connection.getSodaDatabase()
158 sodaDatabase = self.getSodaDatabase()
159159 coll = sodaDatabase.createCollection("cxoTestIndexes")
160160 coll.find().remove()
161161 self.connection.commit()
169169 def testGetDocuments(self):
170170 "test getting documents from Collection"
171171 self.connection.autocommit = True
172 sodaDatabase = self.connection.getSodaDatabase()
172 sodaDatabase = self.getSodaDatabase()
173173 coll = sodaDatabase.createCollection("cxoTestGetDocs")
174174 coll.find().remove()
175175 data = [
187187 def testCursor(self):
188188 "test fetching documents from a cursor"
189189 self.connection.autocommit = True
190 sodaDatabase = self.connection.getSodaDatabase()
190 sodaDatabase = self.getSodaDatabase()
191191 coll = sodaDatabase.createCollection("cxoFindViaCursor")
192192 coll.find().remove()
193193 data = [
202202
203203 def testMultipleDocumentRemove(self):
204204 "test removing multiple documents using multiple keys"
205 sodaDatabase = self.connection.getSodaDatabase()
205 sodaDatabase = self.getSodaDatabase()
206206 coll = sodaDatabase.createCollection("cxoRemoveMultipleDocs")
207207 coll.find().remove()
208208 data = [
223223
224224 def testDocumentVersion(self):
225225 "test using version to get documents and remove them"
226 sodaDatabase = self.connection.getSodaDatabase()
226 sodaDatabase = self.getSodaDatabase()
227227 coll = sodaDatabase.createCollection("cxoDocumentVersion")
228228 coll.find().remove()
229229 content = {'name': 'John', 'address': {'city': 'Bangalore'}}
247247
248248 def testGetCursor(self):
249249 "test keys with GetCursor"
250 sodaDatabase = self.connection.getSodaDatabase()
250 sodaDatabase = self.getSodaDatabase()
251251 coll = sodaDatabase.createCollection("cxoKeysWithGetCursor")
252252 coll.find().remove()
253253 data = [
267267
268268 def testCreatedOn(self):
269269 "test createdOn attribute of Document"
270 sodaDatabase = self.connection.getSodaDatabase()
270 sodaDatabase = self.getSodaDatabase()
271271 coll = sodaDatabase.createCollection("cxoCreatedOn")
272272 coll.find().remove()
273273 data = {'name': 'John', 'address': {'city': 'Bangalore'}}
274274 doc = coll.insertOneAndGet(data)
275275 self.assertEqual(doc.createdOn, doc.lastModified)
276276
277 def testSodaTruncate(self):
278 "test Soda truncate"
279 sodaDatabase = self.getSodaDatabase(minclient=(20,1))
280 coll = sodaDatabase.createCollection("cxoTruncateDocs")
281 coll.find().remove()
282 valuesToInsert = [
283 { "name" : "George", "age" : 47 },
284 { "name" : "Susan", "age" : 39 },
285 { "name" : "John", "age" : 50 },
286 { "name" : "Jill", "age" : 54 }
287 ]
288 for value in valuesToInsert:
289 coll.insertOne(value)
290 self.connection.commit()
291 self.assertEqual(coll.find().count(), len(valuesToInsert))
292 coll.truncate()
293 self.assertEqual(coll.find().count(), 0)
294 coll.drop()
295
277296 if __name__ == "__main__":
278297 TestEnv.RunTestCases()
279298
2626
2727 def testCreateDocumentWithJson(self):
2828 "test creating documents with JSON data"
29 sodaDatabase = self.connection.getSodaDatabase()
29 sodaDatabase = self.getSodaDatabase()
3030 val = {"testKey1" : "testValue1", "testKey2" : "testValue2" }
3131 strVal = json.dumps(val)
3232 bytesVal = strVal.encode("UTF-8")
4141
4242 def testCreateDocumentWithRaw(self):
4343 "test creating documents with raw data"
44 sodaDatabase = self.connection.getSodaDatabase()
44 sodaDatabase = self.getSodaDatabase()
4545 val = b"<html/>"
4646 key = "MyRawKey"
4747 mediaType = "text/html"
5454
5555 def testGetCollectionNames(self):
5656 "test getting collection names from the database"
57 sodaDatabase = self.connection.getSodaDatabase()
57 sodaDatabase = self.getSodaDatabase()
5858 self.__dropExistingCollections(sodaDatabase)
5959 self.assertEqual(sodaDatabase.getCollectionNames(), [])
6060 names = ["zCol", "dCol", "sCol", "aCol", "gCol"]
7373
7474 def testOpenCollection(self):
7575 "test opening a collection"
76 sodaDatabase = self.connection.getSodaDatabase()
76 sodaDatabase = self.getSodaDatabase()
7777 self.__dropExistingCollections(sodaDatabase)
7878 coll = sodaDatabase.openCollection("CollectionThatDoesNotExist")
7979 self.assertEqual(coll, None)
8686 "test SodaDatabase representation"
8787 con1 = self.connection
8888 con2 = TestEnv.GetConnection()
89 sodaDatabase1 = con1.getSodaDatabase()
89 sodaDatabase1 = self.getSodaDatabase()
9090 sodaDatabase2 = con1.getSodaDatabase()
9191 sodaDatabase3 = con2.getSodaDatabase()
9292 self.assertEqual(str(sodaDatabase1), str(sodaDatabase2))
9494
9595 def testNegative(self):
9696 "test negative cases for SODA database methods"
97 sodaDatabase = self.connection.getSodaDatabase()
97 sodaDatabase = self.getSodaDatabase()
9898 self.assertRaises(TypeError, sodaDatabase.createCollection)
9999 self.assertRaises(TypeError, sodaDatabase.createCollection, 1)
100100 self.assertRaises(cx_Oracle.DatabaseError,
103103
104104 if __name__ == "__main__":
105105 TestEnv.RunTestCases()
106
271271
272272 def testBindLongString(self):
273273 "test that binding a long string succeeds"
274 self.cursor.setinputsizes(bigString = cx_Oracle.LONG_STRING)
274 self.cursor.setinputsizes(bigString = cx_Oracle.DB_TYPE_LONG)
275275 self.cursor.execute("""
276276 declare
277277 t_Temp varchar2(20000);
294294 "test cursor description is accurate"
295295 self.cursor.execute("select * from TestStrings")
296296 self.assertEqual(self.cursor.description,
297 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
298 ('STRINGCOL', cx_Oracle.STRING, 20,
297 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
298 ('STRINGCOL', cx_Oracle.DB_TYPE_VARCHAR, 20,
299299 20 * TestEnv.GetCharSetRatio(), None,
300300 None, 0),
301 ('RAWCOL', cx_Oracle.BINARY, 30, 30, None, None, 0),
302 ('FIXEDCHARCOL', cx_Oracle.FIXED_CHAR, 40,
301 ('RAWCOL', cx_Oracle.DB_TYPE_RAW, 30, 30, None, None, 0),
302 ('FIXEDCHARCOL', cx_Oracle.DB_TYPE_CHAR, 40,
303303 40 * TestEnv.GetCharSetRatio(),
304304 None, None, 0),
305 ('NULLABLECOL', cx_Oracle.STRING, 50,
305 ('NULLABLECOL', cx_Oracle.DB_TYPE_VARCHAR, 50,
306306 50 * TestEnv.GetCharSetRatio(), None,
307307 None, 1) ])
308308
3737
3838 def testSubscription(self):
3939 "test Subscription for insert, update, delete and truncate"
40
41 # skip if running on the Oracle Cloud, which does not support
42 # subscriptions currently
43 if self.isOnOracleCloud():
44 self.skipTest("Oracle Cloud does not support subscriptions " \
45 "currently")
46
47 # truncate table in order to run test in known state
4048 self.cursor.execute("truncate table TestTempTable")
4149
4250 # expected values
1414 # You can set values in environment variables to bypass having the test suite
1515 # request the information it requires.
1616 #
17 # CX_ORACLE_TEST_MAIN_USER: user used for most samples
18 # CX_ORACLE_TEST_MAIN_PASSWORD: password of user used for most samples
19 # CX_ORACLE_TEST_PROXY_USER: user for testing proxy connections
20 # CX_ORACLE_TEST_PROXY_PASSWORD: password of user for proxying
21 # CX_ORACLE_TEST_CONNECT_STRING: connect string
22 # CX_ORACLE_TEST_SYSDBA_USER: SYSDBA user for setting up test suite
23 # CX_ORACLE_TEST_SYSDBA_PASSWORD: SYSDBA password for setting up test suite
17 # CX_ORACLE_TEST_MAIN_USER: user used for most test cases
18 # CX_ORACLE_TEST_MAIN_PASSWORD: password of user used for most test cases
19 # CX_ORACLE_TEST_PROXY_USER: user for testing proxying
20 # CX_ORACLE_TEST_PROXY_PASSWORD: password of user for testing proxying
21 # CX_ORACLE_TEST_CONNECT_STRING: connect string for test suite
22 # CX_ORACLE_TEST_ADMIN_USER: administrative user for test suite
23 # CX_ORACLE_TEST_ADMIN_PASSWORD: administrative password for test suite
2424 #
2525 # CX_ORACLE_TEST_CONNECT_STRING can be set to an Easy Connect string, or a
2626 # Net Service Name from a tnsnames.ora file or external naming service,
3232 # [//]host_name[:port][/service_name][:server_type][/instance_name]
3333 #
3434 # Commonly just the host_name and service_name are needed
35 # e.g. "localhost/orclpdb" or "localhost/XE"
35 # e.g. "localhost/orclpdb1" or "localhost/XEPDB1"
3636 #
3737 # If using a tnsnames.ora file, the file can be in a default
3838 # location such as $ORACLE_HOME/network/admin/tnsnames.ora or
3939 # /etc/tnsnames.ora. Alternatively set the TNS_ADMIN environment
4040 # variable and put the file in $TNS_ADMIN/tnsnames.ora.
41 #
42 # The administrative user for cloud databases is ADMIN and the administrative
43 # user for on premises databases is SYSTEM.
4144 #------------------------------------------------------------------------------
42
43 from __future__ import print_function
4445
4546 import cx_Oracle
4647 import getpass
5152 # default values
5253 DEFAULT_MAIN_USER = "pythontest"
5354 DEFAULT_PROXY_USER = "pythontestproxy"
54 DEFAULT_CONNECT_STRING = "localhost/orclpdb"
55 DEFAULT_CONNECT_STRING = "localhost/orclpdb1"
5556
5657 # dictionary containing all parameters; these are acquired as needed by the
5758 # methods below (which should be used instead of consulting this dictionary
103104 PARAMETERS["CS_RATIO"] = value
104105 return value
105106
106 def GetSysdbaConnectString():
107 sysdbaUser = GetValue("SYSDBA_USER", "SYSDBA user", "sys")
108 sysdbaPassword = GetValue("SYSDBA_PASSWORD",
109 "Password for %s" % sysdbaUser)
110 return "%s/%s@%s" % (sysdbaUser, sysdbaPassword, GetConnectString())
107 def GetAdminConnectString():
108 adminUser = GetValue("ADMIN_USER", "Administrative user", "admin")
109 adminPassword = GetValue("ADMIN_PASSWORD", "Password for %s" % adminUser)
110 return "%s/%s@%s" % (adminUser, adminPassword, GetConnectString())
111111
112112 def RunSqlScript(conn, scriptName, **kwargs):
113113 statementParts = []
122122 if statement:
123123 for searchValue, replaceValue in replaceValues:
124124 statement = statement.replace(searchValue, replaceValue)
125 cursor.execute(statement)
125 try:
126 cursor.execute(statement)
127 except:
128 print("Failed to execute SQL:", statement)
129 raise
126130 statementParts = []
127131 else:
128132 statementParts.append(line)
160164
161165 class BaseTestCase(unittest.TestCase):
162166
167 def getSodaDatabase(self, minclient=(18, 3), minserver=(18, 0),
168 message="not supported with this client/server combination"):
169 client = cx_Oracle.clientversion()[:2]
170 if client < minclient:
171 self.skipTest(message)
172 server = tuple(int(s) for s in self.connection.version.split("."))[:2]
173 if server < minserver:
174 self.skipTest(message)
175 if server > (20, 1) and client < (20, 1):
176 self.skipTest(message)
177 return self.connection.getSodaDatabase()
178
179 def isOnOracleCloud(self, connection=None):
180 if connection is None:
181 connection = self.connection
182 cursor = connection.cursor()
183 cursor.execute("""
184 select sys_context('userenv', 'service_name')
185 from dual""")
186 serviceName, = cursor.fetchone()
187 return serviceName.endswith("oraclecloud.com")
188
163189 def setUp(self):
164190 self.connection = GetConnection()
165191 self.cursor = self.connection.cursor()
4444
4545 def testBindTimestamp(self):
4646 "test binding in a timestamp"
47 self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
47 self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
4848 self.cursor.execute("""
4949 select * from TestTimestamps
5050 where TimestampCol = :value""",
5353
5454 def testBindNull(self):
5555 "test binding in a null"
56 self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
56 self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
5757 self.cursor.execute("""
5858 select * from TestTimestamps
5959 where TimestampCol = :value""",
6262
6363 def testBindOutSetInputSizes(self):
6464 "test binding out with set input sizes defined"
65 vars = self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
65 vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
6666 self.cursor.execute("""
6767 begin
6868 :value := to_timestamp('20021209', 'YYYYMMDD');
7272
7373 def testBindInOutSetInputSizes(self):
7474 "test binding in/out with set input sizes defined"
75 vars = self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
75 vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
7676 self.cursor.execute("""
7777 begin
7878 :value := :value + 5.25;
8383
8484 def testBindOutVar(self):
8585 "test binding out with cursor.var() method"
86 var = self.cursor.var(cx_Oracle.TIMESTAMP)
86 var = self.cursor.var(cx_Oracle.DB_TYPE_TIMESTAMP)
8787 self.cursor.execute("""
8888 begin
8989 :value := to_date('20021231 12:31:00',
9595
9696 def testBindInOutVarDirectSet(self):
9797 "test binding in/out with cursor.var() method"
98 var = self.cursor.var(cx_Oracle.TIMESTAMP)
98 var = self.cursor.var(cx_Oracle.DB_TYPE_TIMESTAMP)
9999 var.setvalue(0, cx_Oracle.Timestamp(2002, 12, 9, 6, 0, 0))
100100 self.cursor.execute("""
101101 begin
109109 "test cursor description is accurate"
110110 self.cursor.execute("select * from TestTimestamps")
111111 self.assertEqual(self.cursor.description,
112 [ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
113 ('TIMESTAMPCOL', cx_Oracle.TIMESTAMP, 23, None, 0, 6, 0),
114 ('NULLABLECOL', cx_Oracle.TIMESTAMP, 23, None, 0, 6, 1) ])
112 [ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
113 ('TIMESTAMPCOL', cx_Oracle.DB_TYPE_TIMESTAMP, 23, None, 0, 6,
114 0),
115 ('NULLABLECOL', cx_Oracle.DB_TYPE_TIMESTAMP, 23, None, 0, 6,
116 1) ])
115117
116118 def testFetchAll(self):
117119 "test that fetching all of the data returns the correct results"
2020 /
2121
2222 create user &main_user identified by &main_password
23 quota unlimited on users
24 default tablespace users
2523 /
2624
2725 create user &proxy_user identified by &proxy_password
3836 create procedure,
3937 create type,
4038 select any dictionary,
41 change notification
39 change notification,
40 unlimited tablespace
4241 to &main_user
4342 /
4443
178177 create table &main_user..TestLongs (
179178 IntCol number(9) not null,
180179 LongCol long not null
181 )
180 ) nocompress
182181 /
183182
184183 create table &main_user..TestLongRaws (
185184 IntCol number(9) not null,
186185 LongRawCol long raw not null
187 )
186 ) nocompress
188187 /
189188
190189 create table &main_user..TestTempTable (
245244 )
246245 /
247246
247 create table &main_user..PlsqlSessionCallbacks (
248 RequestedTag varchar2(250),
249 ActualTag varchar2(250),
250 FixupTimestamp timestamp
251 )
252 /
253
248254 -- create queue table and queues for testing advanced queuing
249255 begin
250 dbms_aqadm.create_queue_table('&main_user..BOOK_QUEUE',
256 dbms_aqadm.create_queue_table('&main_user..BOOK_QUEUE_TAB',
251257 '&main_user..UDT_BOOK');
252 dbms_aqadm.create_queue('&main_user..BOOKS', '&main_user..BOOK_QUEUE');
253 dbms_aqadm.start_queue('&main_user..BOOKS');
258 dbms_aqadm.create_queue('&main_user..TEST_BOOK_QUEUE',
259 '&main_user..BOOK_QUEUE_TAB');
260 dbms_aqadm.start_queue('&main_user..TEST_BOOK_QUEUE');
261
262 dbms_aqadm.create_queue_table('&main_user..RAW_QUEUE_TAB', 'RAW');
263 dbms_aqadm.create_queue('&main_user..TEST_RAW_QUEUE',
264 '&main_user..RAW_QUEUE_TAB');
265 dbms_aqadm.start_queue('&main_user..TEST_RAW_QUEUE');
254266 end;
255267 /
256268
917929 StringValue varchar2(30),
918930 DateValue date,
919931 TimestampValue timestamp,
920 BooleanValue boolean
932 BooleanValue boolean,
933 PlsIntegerValue pls_integer,
934 BinaryIntegerValue binary_integer
921935 );
922936
923937 type udt_RecordArray is table of udt_Record index by binary_integer;
957971 ''', ''YYYY-MM-DD HH24:MI:SS'')' end || ', ' ||
958972 case when a_Value.BooleanValue is null then 'null'
959973 when a_Value.BooleanValue then 'true'
960 else 'false' end || ')';
974 else 'false' end || ', ' ||
975 nvl(to_char(a_Value.PlsIntegerValue), 'null') || ', ' ||
976 nvl(to_char(a_Value.BinaryIntegerValue), 'null') || ')';
961977 end;
962978
963979 procedure TestOut (
970986 a_Value.TimestampValue := to_timestamp('20160216 18:23:55',
971987 'YYYYMMDD HH24:MI:SS');
972988 a_Value.BooleanValue := true;
989 a_Value.PlsIntegerValue := 45;
990 a_Value.BinaryIntegerValue := 10;
973991 end;
974992
975993 function TestInArrays (
9891007 end;
9901008 /
9911009
1010 create or replace package &main_user..pkg_SessionCallback as
1011
1012 procedure TheCallback (
1013 a_RequestedTag varchar2,
1014 a_ActualTag varchar2
1015 );
1016
1017 end;
1018 /
1019
1020 create or replace package body &main_user..pkg_SessionCallback as
1021
1022 type udt_Properties is table of varchar2(64) index by varchar2(64);
1023
1024 procedure LogCall (
1025 a_RequestedTag varchar2,
1026 a_ActualTag varchar2
1027 ) is
1028 pragma autonomous_transaction;
1029 begin
1030 insert into PlsqlSessionCallbacks
1031 values (a_RequestedTag, a_ActualTag, systimestamp);
1032 commit;
1033 end;
1034
1035 procedure ParseProperty (
1036 a_Property varchar2,
1037 a_Name out nocopy varchar2,
1038 a_Value out nocopy varchar2
1039 ) is
1040 t_Pos number;
1041 begin
1042 t_Pos := instr(a_Property, '=');
1043 if t_Pos = 0 then
1044 raise_application_error(-20000, 'Tag must contain key=value pairs');
1045 end if;
1046 a_Name := substr(a_Property, 1, t_Pos - 1);
1047 a_Value := substr(a_Property, t_Pos + 1);
1048 end;
1049
1050 procedure SetProperty (
1051 a_Name varchar2,
1052 a_Value varchar2
1053 ) is
1054 t_ValidValues udt_Properties;
1055 begin
1056 if a_Name = 'TIME_ZONE' then
1057 t_ValidValues('UTC') := 'UTC';
1058 t_ValidValues('MST') := '-07:00';
1059 elsif a_Name = 'NLS_DATE_FORMAT' then
1060 t_ValidValues('SIMPLE') := 'YYYY-MM-DD HH24:MI';
1061 t_ValidValues('FULL') := 'YYYY-MM-DD HH24:MI:SS';
1062 else
1063 raise_application_error(-20000, 'Unsupported session setting');
1064 end if;
1065 if not t_ValidValues.exists(a_Value) then
1066 raise_application_error(-20000, 'Unsupported session setting');
1067 end if;
1068 execute immediate
1069 'ALTER SESSION SET ' || a_Name || '=''' ||
1070 t_ValidValues(a_Value) || '''';
1071 end;
1072
1073 procedure ParseTag (
1074 a_Tag varchar2,
1075 a_Properties out nocopy udt_Properties
1076 ) is
1077 t_PropertyName varchar2(64);
1078 t_PropertyValue varchar2(64);
1079 t_StartPos number;
1080 t_EndPos number;
1081 begin
1082 t_StartPos := 1;
1083 while t_StartPos < length(a_Tag) loop
1084 t_EndPos := instr(a_Tag, ';', t_StartPos);
1085 if t_EndPos = 0 then
1086 t_EndPos := length(a_Tag) + 1;
1087 end if;
1088 ParseProperty(substr(a_Tag, t_StartPos, t_EndPos - t_StartPos),
1089 t_PropertyName, t_PropertyValue);
1090 a_Properties(t_PropertyName) := t_PropertyValue;
1091 t_StartPos := t_EndPos + 1;
1092 end loop;
1093 end;
1094
1095 procedure TheCallback (
1096 a_RequestedTag varchar2,
1097 a_ActualTag varchar2
1098 ) is
1099 t_RequestedProps udt_Properties;
1100 t_ActualProps udt_Properties;
1101 t_PropertyName varchar2(64);
1102 begin
1103 LogCall(a_RequestedTag, a_ActualTag);
1104 ParseTag(a_RequestedTag, t_RequestedProps);
1105 ParseTag(a_ActualTag, t_ActualProps);
1106 t_PropertyName := t_RequestedProps.first;
1107 while t_PropertyName is not null loop
1108 if not t_ActualProps.exists(t_PropertyName) or
1109 t_ActualProps(t_PropertyName) !=
1110 t_RequestedProps(t_PropertyName) then
1111 SetProperty(t_PropertyName, t_RequestedProps(t_PropertyName));
1112 end if;
1113 t_PropertyName := t_RequestedProps.next(t_PropertyName);
1114 end loop;
1115 end;
1116
1117 end;
1118 /
1119
00 #------------------------------------------------------------------------------
1 # Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
1 # Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
22 #
33 # Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
44 #
77 #------------------------------------------------------------------------------
88
99 """Runs all defined unit tests."""
10
11 from __future__ import print_function
1210
1311 import cx_Oracle
1412 import os
3533 "Cursor",
3634 "CursorVar",
3735 "DateTimeVar",
36 "DbTypes",
3837 "DMLReturning",
3938 "Error",
4039 "IntervalVar",
4746 "StringVar",
4847 "TimestampVar",
4948 "AQ",
49 "BulkAQ",
5050 "Rowid",
5151 "Subscription"
5252 ]
7474 for name in failures:
7575 print(" %s" % name)
7676 sys.exit(1)
77
88
99 """Driver specific portion of the DB API test suite provided by Stuart Bishop
1010 available at http://stuartbishop.net/Software/DBAPI20TestSuite/"""
11
12 from __future__ import print_function
1311
1412 import cx_Oracle
1513 import dbapi20