Rework to use the ODPI-C library instead of direct OCI calls.
This commit is contained in:
parent
856608e49c
commit
b28e04e901
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "odpi"]
|
||||
path = odpi
|
||||
url = ../odpi.git
|
||||
62
README.txt
62
README.txt
@ -1,54 +1,58 @@
|
||||
Open Source Python/Oracle Utility - cx_Oracle
|
||||
---------------------------------------------
|
||||
|
||||
cx_Oracle is a Python extension module that allows access to Oracle and
|
||||
conforms to the Python database API 2.0 specifications with a number of
|
||||
additions. The time data type is not supported by Oracle and is therefore not
|
||||
implemented. The method cursor.nextset() is not implemented either as the DB
|
||||
API specification assumes an implementation of cursors that does not fit well
|
||||
with Oracle's implementation of cursors and implicit results. See the method
|
||||
cx_Oracle is a Python extension module that enables access to Oracle databases
|
||||
and conforms to the Python database API 2.0 specifications with a considerable
|
||||
number of additions and a couple of exclusions. The time data type is not
|
||||
supported by Oracle and is therefore not implemented. The method
|
||||
cursor.nextset() is not implemented either as the DB API specification assumes
|
||||
an implementation of cursors that does not fit well with Oracle's
|
||||
implementation of cursors and implicit results. See the method
|
||||
cursor.getimplicitresults() for more information.
|
||||
|
||||
See http://www.python.org/topics/database/DatabaseAPI-2.0.html for more
|
||||
information on the Python database API specification. See the included
|
||||
documentation for additional information.
|
||||
information on the Python database API specification. See the documentation at
|
||||
http://cx-oracle.readthedocs.io for a complete description of the module's
|
||||
capabilities.
|
||||
|
||||
cx_Oracle is licensed under a BSD license which you can find at
|
||||
http://cx-oracle.readthedocs.io/en/latest/license.html.
|
||||
|
||||
Please note that an Oracle client (or server) installation is required in order
|
||||
to use cx_Oracle. If you do not require the tools that come with a full client
|
||||
installation, it is recommended to install the Instant Client
|
||||
(http://www.oracle.com/technetwork/database/features/instant-client/index.html)
|
||||
which is far easier to install.
|
||||
|
||||
For feedback or patches, contact Anthony Tuininga at
|
||||
anthony.tuininga@gmail.com. For help or to ask questions, please use the
|
||||
mailing list at http://lists.sourceforge.net/lists/listinfo/cx-oracle-users.
|
||||
|
||||
Please note that an Oracle client (or server) installation is required in order
|
||||
to use cx_Oracle. If you do not require the tools that come with a full client
|
||||
installation, it is recommended to install the Instant Client which is far
|
||||
easier to install.
|
||||
|
||||
|
||||
Binary Install
|
||||
--------------
|
||||
Place the file cx_Oracle.pyd or cx_Oracle.so anywhere on your Python path.
|
||||
|
||||
|
||||
Source Install
|
||||
--------------
|
||||
This module has been built with Oracle 11g and 12c on Linux, Windows and macOS.
|
||||
Others have reported success with other platforms.
|
||||
|
||||
For simplified installation use pip
|
||||
Installation
|
||||
------------
|
||||
Binaries for some platforms and Oracle versions are available at
|
||||
https://pypi.python.org/pypi/cx_Oracle. If you prefer to build your own you
|
||||
can use this command
|
||||
|
||||
pip install cx_Oracle
|
||||
|
||||
Otherwise, you can use the provided setup.py to build and install the module
|
||||
which will download the source package, build and install it. Otherwise, you
|
||||
can download the source package directly from PyPI, extract it and run these
|
||||
commands instead
|
||||
|
||||
python setup.py build
|
||||
python setup.py install
|
||||
|
||||
This module has been built with Oracle 10g, 11g and 12c on Linux and Windows.
|
||||
Others have reported success with other platforms such as Mac OS X.
|
||||
|
||||
See BUILD.txt for additional information.
|
||||
|
||||
|
||||
Usage Example
|
||||
-------------
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import print_function # needed for Python 2.x
|
||||
|
||||
import cx_Oracle
|
||||
|
||||
@ -74,7 +78,3 @@ samples in the samples directory. You can also look at the scripts in the
|
||||
cx_OracleTools (http://cx-oracletools.sourceforge.net) and the modules in the
|
||||
cx_PyOracleLib (http://cx-pyoraclelib.sourceforge.net) projects.
|
||||
|
||||
For further information see
|
||||
|
||||
http://cx-oracle.readthedocs.io
|
||||
|
||||
|
||||
@ -40,9 +40,9 @@ author = 'Oracle'
|
||||
# other places throughout the built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '5.3'
|
||||
version = '6.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '5.3'
|
||||
release = '6.0'
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
|
||||
@ -135,6 +135,17 @@ Connection Object
|
||||
Return a new :ref:`cursor object <cursorobj>` using the connection.
|
||||
|
||||
|
||||
.. attribute:: Connection.dbop
|
||||
|
||||
This write-only attribute sets the database operation that is to be
|
||||
monitored. This can be viewed in the DBOP_NAME column of the V$SQL_MONITOR
|
||||
table.
|
||||
|
||||
.. note::
|
||||
|
||||
This attribute is an extension to the DB API definition.
|
||||
|
||||
|
||||
.. method:: Connection.deq(name, options, msgproperties, payload)
|
||||
|
||||
Returns a message id after successfully dequeuing a message. The options
|
||||
@ -247,6 +258,17 @@ Connection Object
|
||||
This method is an extension to the DB API definition.
|
||||
|
||||
|
||||
.. attribute:: Connection.handle
|
||||
|
||||
This read-only attribute returns the OCI service context handle for the
|
||||
connection. It is primarily provided to facilitate testing the creation of a
|
||||
connection using the OCI service context handle.
|
||||
|
||||
.. note::
|
||||
|
||||
This attribute is an extension to the DB API definition.
|
||||
|
||||
|
||||
.. attribute:: Connection.inputtypehandler
|
||||
|
||||
This read-write attribute specifies a method called for each value that is
|
||||
@ -430,7 +452,7 @@ Connection Object
|
||||
This attribute is an extension to the DB API definition.
|
||||
|
||||
|
||||
.. method:: Connection.subscribe(namespace=cx_Oracle.SUBSCR_NAMESPACE_DBCHANGE, protocol=cx_Oracle.SUBSCR_PROTO_OCI, callback=None, timeout=0, operations=OPCODE_ALLOPS, rowids=False, port=0, qos=0, cqqos=0)
|
||||
.. 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)
|
||||
|
||||
Return a new :ref:`subscription object <subscrobj>` using the connection.
|
||||
Currently the namespace and protocol arguments cannot have any other
|
||||
@ -448,11 +470,6 @@ Connection Object
|
||||
(insert, update, delete). The default value will send notifications for all
|
||||
operations.
|
||||
|
||||
The rowids flag specifies whether the rowids of affected rows should be
|
||||
included in the messages that are sent. This argument is deprecated and
|
||||
will be removed in a future version of cx_Oracle. Use the value
|
||||
:data:`~cx_Oracle.SUBSCR_QOS_ROWIDS` for the qos argument instead.
|
||||
|
||||
The port specifies the listening port for callback notifications from the
|
||||
database server. If not specified, an unused port will be selected by the
|
||||
database.
|
||||
@ -465,9 +482,6 @@ Connection Object
|
||||
:data:`cx_Oracle.SUBSCR_QOS_QUERY`,
|
||||
:data:`cx_Oracle.SUBSCR_QOS_BEST_EFFORT`.
|
||||
|
||||
The cqqos argument is deprecated and will be removed in a future version of
|
||||
cx_Oracle. The qos argument should be used instead.
|
||||
|
||||
.. note::
|
||||
|
||||
This method is an extension to the DB API definition.
|
||||
|
||||
@ -337,24 +337,6 @@ Cursor Object
|
||||
mentioned in PEP 249 as an optional extension.
|
||||
|
||||
|
||||
.. attribute:: Cursor.numbersAsStrings
|
||||
|
||||
This integer attribute defines whether or not numbers should be returned as
|
||||
strings rather than integers or floating point numbers. This is useful to
|
||||
get around the fact that Oracle floating point numbers have considerably
|
||||
greater precision than C floating point numbers and not require a change to
|
||||
the SQL being executed.
|
||||
|
||||
.. deprecated:: 5.3
|
||||
|
||||
Use one of the attributes :attr:`Connection.outputtypehandler` or
|
||||
:attr:`~Cursor.outputtypehandler` instead.
|
||||
|
||||
.. note::
|
||||
|
||||
The DB API definition does not define this attribute.
|
||||
|
||||
|
||||
.. attribute:: Cursor.outputtypehandler
|
||||
|
||||
This read-write attribute specifies a method called for each column that is
|
||||
|
||||
@ -8,12 +8,12 @@ License
|
||||
|
||||
.. centered:: **LICENSE AGREEMENT FOR CX_ORACLE**
|
||||
|
||||
Copyright |copy| 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright |copy| 2016-2017, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Portions Copyright |copy| 2007-2015, Anthony Tuininga. All rights reserved.
|
||||
Copyright |copy| 2007-2015, Anthony Tuininga. All rights reserved.
|
||||
|
||||
Portions Copyright |copy| 2001-2007, Computronix (Canada) Ltd., Edmonton,
|
||||
Alberta, Canada. All rights reserved.
|
||||
Copyright |copy| 2001-2007, Computronix (Canada) Ltd., Edmonton, Alberta,
|
||||
Canada. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
@ -10,17 +10,6 @@ LOB Objects
|
||||
:data:`CLOB`, :data:`BLOB` and :data:`BFILE` columns are fetched.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Internally, Oracle uses LOB locators which are allocated based on the
|
||||
cursor array size. Thus, it is important that the data in the LOB object be
|
||||
manipulated before another internal fetch takes place. The safest way to do
|
||||
this is to use the cursor as an iterator. In particular, do not use the
|
||||
:meth:`Cursor.fetchall()` method. The exception "LOB variable no longer
|
||||
valid after subsequent fetch" will be raised if an attempt to access a LOB
|
||||
variable after a subsequent fetch is detected.
|
||||
|
||||
|
||||
.. method:: LOB.close()
|
||||
|
||||
Close the LOB. Call this when writing is completed so that the indexes
|
||||
|
||||
@ -22,18 +22,18 @@ Module Interface
|
||||
This method is an extension to the DB API definition.
|
||||
|
||||
|
||||
.. function:: Connection([user, password, dsn, mode, handle, pool, threaded, twophase, events, cclass, purity, newpassword, encoding, nencoding, module, action, clientinfo, edition, appcontext])
|
||||
connect([user, password, dsn, mode, handle, pool, threaded, twophase, events, cclass, purity, newpassword, encoding, nencoding, module, action, clientinfo, edition, appcontext])
|
||||
.. function:: Connection([user, password, dsn, mode, handle, pool, threaded, events, cclass, purity, newpassword, encoding, nencoding, edition, appcontext, tag, matchanytag])
|
||||
connect([user, password, dsn, mode, handle, pool, threaded, events, cclass, purity, newpassword, encoding, nencoding, edition, appcontext, tag, matchanytag])
|
||||
|
||||
Constructor for creating a connection to the database. Return a
|
||||
:ref:`connection object <connobj>`. All arguments are optional and can be
|
||||
specified as keyword parameters.
|
||||
|
||||
The dsn (data source name) is the TNS entry (from the Oracle names server or
|
||||
tnsnames.ora file) or is a string like the one returned from makedsn(). If
|
||||
only one parameter is passed, a connect string is assumed which is to be of
|
||||
the format ``user/password@dsn``, the same format accepted by Oracle
|
||||
applications such as SQL\*Plus.
|
||||
tnsnames.ora file) or is a string like the one returned from
|
||||
:meth:`~cx_Oracle.makedsn()`. If only one parameter is passed, a connect
|
||||
string is assumed which is to be of the format ``user/password@dsn``, the
|
||||
same format accepted by Oracle applications such as SQL\*Plus.
|
||||
|
||||
If the mode is specified, it must be one of :data:`~cx_Oracle.SYSDBA`,
|
||||
:data:`~cx_Oracle.SYSASM` or :data:`~cx_Oracle.SYSOPER` which are defined at
|
||||
@ -51,13 +51,6 @@ Module Interface
|
||||
mutex. Doing so in single threaded applications imposes a performance
|
||||
penalty of about 10-15% which is why the default is False.
|
||||
|
||||
The twophase argument is expected to be a boolean expression which
|
||||
indicates whether or not the external_name and internal_name attributes
|
||||
should be set on the connection object to allow for two phase commit. The
|
||||
default for this value is False. Use of this argument is deprecated and will
|
||||
be removed in a future release of cx_Oracle. Instead, the application should
|
||||
set these attributes itself to an appropriate value for the application.
|
||||
|
||||
The events argument is expected to be a boolean expression which indicates
|
||||
whether or not to initialize Oracle in events mode.
|
||||
|
||||
@ -77,13 +70,6 @@ Module Interface
|
||||
The nencoding argument is expected to be a string if specified and sets the
|
||||
national encoding to use for national character set database strings.
|
||||
|
||||
The module, action and clientinfo arguments are expected to be strings, if
|
||||
specified, and set the module, action and client_info attributes on the
|
||||
connection respectively. These arguments are deprecated and will be removed
|
||||
in a future version of cx_Oracle since Oracle does not support their use
|
||||
during the creation of a connection. Instead, application context (see
|
||||
below) should be used.
|
||||
|
||||
The edition argument is expected to be a string if specified and sets the
|
||||
edition to use for the session. It is only relevant if both the client and
|
||||
the server are at least Oracle Database 11.2.
|
||||
@ -95,6 +81,15 @@ Module Interface
|
||||
Each entry in the list is expected to contain three strings: the namespace,
|
||||
the name and the value.
|
||||
|
||||
The tag argument, if specified, is expected to be a string and will limit
|
||||
the sessions that can be returned from a session pool unless the matchanytag
|
||||
argument is set to True. In that case sessions with the specified tag will
|
||||
be preferred over others, but if no such sessions are available a session
|
||||
with a different tag may be returned instead. In any case, untagged sessions
|
||||
will always be returned if no sessions with the specified tag are available.
|
||||
Sessions are tagged when they are :meth:`released <SessionPool.release>`
|
||||
back to the pool.
|
||||
|
||||
|
||||
.. function:: Cursor(connection)
|
||||
|
||||
@ -118,21 +113,18 @@ Module Interface
|
||||
time module for details).
|
||||
|
||||
|
||||
.. function:: makedsn(host, port, sid, [service_name])
|
||||
.. function:: makedsn(host, port, sid=None, service_name=None, region=None, sharding_key=None, super_sharding_key=None)
|
||||
|
||||
Return a string suitable for use as the dsn argument for
|
||||
:meth:`~cx_Oracle.connect()`. This string is identical to the strings that
|
||||
are defined by the Oracle names server or defined in the tnsnames.ora file.
|
||||
If you wish to use the service name instead of the sid, do not include a
|
||||
value for the parameter sid and use the keyword parameter service_name
|
||||
instead.
|
||||
|
||||
.. note::
|
||||
|
||||
This method is an extension to the DB API definition.
|
||||
|
||||
|
||||
.. function:: SessionPool(user, password, database, min, max, increment, [connectiontype, threaded, getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT, homogeneous=True, externalauth=True, encoding=None, nencoding=None])
|
||||
.. function:: SessionPool(user, password, database, min, max, increment, [connectiontype, threaded, getmode=cx_Oracle.SPOOL_ATTRVAL_NOWAIT, homogeneous=True, externalauth=True, encoding=None, nencoding=None, edition=None])
|
||||
|
||||
Create and return a :ref:`session pool object <sesspool>`. This
|
||||
allows for very fast connections to the database and is of primary use in a
|
||||
@ -151,6 +143,10 @@ Module Interface
|
||||
The nencoding argument is expected to be a string if specified and sets the
|
||||
national encoding to use for national character set database strings.
|
||||
|
||||
The edition argument is expected to be a string, if specified, and sets the
|
||||
edition to use for the sessions in the pool. It is only relevant if both the
|
||||
client and the server are at least Oracle Database 11.2.
|
||||
|
||||
.. note::
|
||||
|
||||
This method is an extension to the DB API definition.
|
||||
|
||||
@ -1,12 +1,45 @@
|
||||
Release notes
|
||||
=============
|
||||
|
||||
5.x releases
|
||||
6.x releases
|
||||
############
|
||||
|
||||
|
||||
Version 5.next
|
||||
--------------
|
||||
Version 6.0 (TBD)
|
||||
-----------------
|
||||
|
||||
1) Added attribute :attr:`SessionPool.stmtcachesize` to support getting and
|
||||
setting the default statement cache size for connections in the pool.
|
||||
2) Added attribute :attr:`Connection.dbop` to support setting the database
|
||||
operation that is to be monitored.
|
||||
3) Added attribute :attr:`Connection.handle` to facilitate testing the
|
||||
creation of a connection using a OCI service context handle.
|
||||
4) Added parameters tag and matchanytag to the :meth:`cx_Oracle.connect`
|
||||
and :meth:`SessionPool.acquire` methods and added parameters tag and retag
|
||||
to the :meth:`SessionPool.release` method in order to support session
|
||||
tagging.
|
||||
5) Added parameter edition to the :meth:`cx_Oracle.SessionPool` method.
|
||||
6) Added support for universal rowids.
|
||||
7) Added support for DML returning of multiple rows.
|
||||
8) Added sharding parameters region, sharding_key and super_sharding_key to
|
||||
the :meth:`cx_Oracle.makedsn()` method.
|
||||
9) Removed restriction on fetching LOBs across round trips to the database
|
||||
(LOB variable no longer valid after subsequent fetch).
|
||||
10) Removed requirement for specifying a maximum size when fetching LONG or
|
||||
LONG raw columns. This also allows CLOB, NCLOB, BLOB and BFILE columns to
|
||||
be fetched without needing to specify a maximum size.
|
||||
11) Dropped deprecated parameters twophase, action, module and clientinfo from
|
||||
the :meth:`cx_Oracle.connect` method.
|
||||
12) Dropped deprecated attribute numbersAsString from
|
||||
:ref:`cursor objects <cursorobj>`. Use an output type handler instead.
|
||||
13) Dropped deprecated attributes cqqos and rowids from
|
||||
:ref:`subscription objects <subscrobj>`. Use the qos attribute instead.
|
||||
14) Dropped deprecated parameters cqqos and rowids from the
|
||||
:meth:`Connection.subscribe()` method.
|
||||
|
||||
|
||||
5.x releases
|
||||
############
|
||||
|
||||
|
||||
Version 5.3 (March 2017)
|
||||
|
||||
@ -9,11 +9,30 @@ SessionPool Object
|
||||
This object is an extension to the DB API.
|
||||
|
||||
|
||||
.. method:: SessionPool.acquire()
|
||||
.. method:: SessionPool.acquire(user=None, password=None, cclass=None, purity=cx_Oracle.ATTR_PURITY_DEFAULT, tag=None, matchanytag=False)
|
||||
|
||||
Acquire a connection from the session pool and return a
|
||||
:ref:`connection object <connobj>`.
|
||||
|
||||
The user and password arguments may not be specified if the pool is
|
||||
homogeneous. In that case an exception will be raised.
|
||||
|
||||
The cclass argument, if specified, should be a string corresponding to the
|
||||
connection class for database resident connection pooling (DRCP).
|
||||
|
||||
The purity argument is expected to be one of
|
||||
:data:`~cx_Oracle.ATTR_PURITY_NEW`, :data:`~cx_Oracle.ATTR_PURITY_SELF`, or
|
||||
:data:`~cx_Oracle.ATTR_PURITY_DEFAULT`.
|
||||
|
||||
The tag argument, if specified, is expected to be a string and will limit
|
||||
the sessions that can be returned from a session pool unless the matchanytag
|
||||
argument is set to True. In that case sessions with the specified tag will
|
||||
be preferred over others, but if no such sessions are available a session
|
||||
with a different tag may be returned instead. In any case, untagged sessions
|
||||
will always be returned if no sessions with the specified tag are available.
|
||||
Sessions are tagged when they are :meth:`released <SessionPool.release>`
|
||||
back to the pool.
|
||||
|
||||
|
||||
.. attribute:: SessionPool.busy
|
||||
|
||||
@ -81,11 +100,25 @@ SessionPool Object
|
||||
the session pool.
|
||||
|
||||
|
||||
.. method:: SessionPool.release(connection)
|
||||
.. method:: SessionPool.release(connection, tag=None)
|
||||
|
||||
Release the connection back to the pool. This will be done automatically as
|
||||
well if the connection object is garbage collected.
|
||||
|
||||
If a tag is specified, the session will be tagged (or retagged) with the
|
||||
specified value before being returned to the pool.
|
||||
|
||||
|
||||
.. attribute:: SessionPool.stmtcachesize
|
||||
|
||||
This read-write attribute specifies the size of the statement cache that
|
||||
will be used as the starting point for any connections that are created by
|
||||
the session pool. Once created, the connection's statement cache size can
|
||||
only be changed by setting the stmtcachesize attribute on the connection
|
||||
itself.
|
||||
|
||||
.. versionadded:: 6.0
|
||||
|
||||
|
||||
.. attribute:: SessionPool.timeout
|
||||
|
||||
|
||||
@ -21,15 +21,6 @@ Subscription Object
|
||||
the subscription when it was created.
|
||||
|
||||
|
||||
.. attribute:: Subscription.cqqos
|
||||
|
||||
This read-only attribute returns the quality of service flags used to
|
||||
register the subscription when it was created.
|
||||
|
||||
.. deprecated:: 5.3
|
||||
Use the qos attribute instead.
|
||||
|
||||
|
||||
.. attribute:: Subscription.id
|
||||
|
||||
This read-only attribute returns the registration ID returned by the
|
||||
@ -77,16 +68,6 @@ Subscription Object
|
||||
returned; otherwise, None is returned.
|
||||
|
||||
|
||||
.. attribute:: Subscription.rowids
|
||||
|
||||
This read-only attribute returns True or False specifying if rowids will be
|
||||
included in notifications sent using this subscription.
|
||||
|
||||
.. deprecated:: 5.3
|
||||
Use :data:`~cx_Oracle.SUBSCR_QOS_ROWIDS` masked with the qos attribute
|
||||
instead.
|
||||
|
||||
|
||||
.. attribute:: Subscription.timeout
|
||||
|
||||
This read-only attribute returns the timeout (in seconds) that was specified
|
||||
|
||||
1
odpi
Submodule
1
odpi
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 88f9cdc6508304ff02744b44f17f4088354f8677
|
||||
18
setup.py
18
setup.py
@ -38,7 +38,7 @@ except:
|
||||
from distutils.extension import Extension
|
||||
|
||||
# define build constants
|
||||
BUILD_VERSION = "5.3"
|
||||
BUILD_VERSION = "6.0"
|
||||
|
||||
# define the list of files to be included as documentation for Windows
|
||||
dataFiles = None
|
||||
@ -224,6 +224,10 @@ else:
|
||||
if not includeDirs:
|
||||
raise DistutilsSetupError("cannot locate Oracle include files")
|
||||
|
||||
# include the ODPI-C header and source file locations
|
||||
includeDirs.append("odpi/include")
|
||||
includeDirs.append("odpi/src")
|
||||
|
||||
# NOTE: on HP-UX Itanium with Oracle 10g you need to add the library "ttsh10"
|
||||
# to the list of libraries along with "clntsh"; since I am unable to test, I'll
|
||||
# leave this as a comment until someone can verify when this is required
|
||||
@ -361,13 +365,13 @@ extension = Extension(
|
||||
extra_compile_args = extraCompileArgs,
|
||||
extra_link_args = extraLinkArgs,
|
||||
sources = ["src/cx_Oracle.c"],
|
||||
depends = ["src/AQ.c", "src/Buffer.c", "src/Connection.c",
|
||||
depends = ["src/BooleanVar.c", "src/Buffer.c", "src/Connection.c",
|
||||
"src/Cursor.c", "src/CursorVar.c", "src/DateTimeVar.c",
|
||||
"src/Environment.c", "src/Error.c", "src/ExternalLobVar.c",
|
||||
"src/IntervalVar.c", "src/LobVar.c", "src/LongVar.c",
|
||||
"src/NumberVar.c", "src/Object.c", "src/ObjectType.c",
|
||||
"src/ObjectVar.c", "src/SessionPool.c", "src/StringVar.c",
|
||||
"src/Subscription.c", "src/TimestampVar.c", "src/Transforms.c",
|
||||
"src/DeqOptions.c", "src/EnqOptions.c", "src/Error.c",
|
||||
"src/IntervalVar.c", "src/LOB.c", "src/LobVar.c",
|
||||
"src/LongVar.c", "src/MsgProps.c", "src/NumberVar.c",
|
||||
"src/Object.c", "src/ObjectType.c", "src/ObjectVar.c",
|
||||
"src/SessionPool.c", "src/StringVar.c", "src/Subscription.c",
|
||||
"src/Variable.c"])
|
||||
|
||||
# perform the setup
|
||||
|
||||
771
src/AQ.c
771
src/AQ.c
@ -1,771 +0,0 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AQ.c
|
||||
// Implements the enqueue and dequeue options and message properties objects
|
||||
// used in Advanced Queuing.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// structures used for handling AQ options and message properties
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_Environment *environment;
|
||||
OCIAQEnqOptions *handle;
|
||||
} udt_EnqOptions;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_Environment *environment;
|
||||
OCIAQDeqOptions *handle;
|
||||
} udt_DeqOptions;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_Environment *environment;
|
||||
OCIAQMsgProperties *handle;
|
||||
} udt_MessageProperties;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of methods used for enqueue options
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_EnqOptions *EnqOptions_New(udt_Environment*);
|
||||
static void EnqOptions_Free(udt_EnqOptions*);
|
||||
static PyObject *EnqOptions_GetOCIAttr(udt_EnqOptions*, ub4*);
|
||||
static int EnqOptions_SetOCIAttr(udt_EnqOptions*, PyObject*, ub4*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of methods used for dequeue options
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_DeqOptions *DeqOptions_New(udt_Environment*);
|
||||
static void DeqOptions_Free(udt_DeqOptions*);
|
||||
static PyObject *DeqOptions_GetOCIAttr(udt_DeqOptions*, ub4*);
|
||||
static int DeqOptions_SetOCIAttr(udt_DeqOptions*, PyObject*, ub4*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of methods used for message properties
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_MessageProperties *MessageProperties_New(udt_Environment*);
|
||||
static void MessageProperties_Free(udt_MessageProperties*);
|
||||
static PyObject *MessageProperties_GetOCIAttr(udt_MessageProperties*, ub4*);
|
||||
static int MessageProperties_SetOCIAttr(udt_MessageProperties*, PyObject*,
|
||||
ub4*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constants for OCI attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static ub4 gc_AQAttempts = OCI_ATTR_ATTEMPTS;
|
||||
static ub4 gc_AQConsumerName = OCI_ATTR_CONSUMER_NAME;
|
||||
static ub4 gc_AQCorrelation = OCI_ATTR_CORRELATION;
|
||||
static ub4 gc_AQDelay = OCI_ATTR_DELAY;
|
||||
static ub4 gc_AQDeliveryMode = OCI_ATTR_MSG_DELIVERY_MODE;
|
||||
static ub4 gc_AQDeqCondition = OCI_ATTR_DEQCOND;
|
||||
static ub4 gc_AQDeqMode = OCI_ATTR_DEQ_MODE;
|
||||
static ub4 gc_AQDeqMsgId = OCI_ATTR_DEQ_MSGID;
|
||||
static ub4 gc_AQEnqTime = OCI_ATTR_ENQ_TIME;
|
||||
static ub4 gc_AQExceptionQ = OCI_ATTR_EXCEPTION_QUEUE;
|
||||
static ub4 gc_AQExpiration = OCI_ATTR_EXPIRATION;
|
||||
static ub4 gc_AQNavigation = OCI_ATTR_NAVIGATION;
|
||||
static ub4 gc_AQOriginalMsgId = OCI_ATTR_ORIGINAL_MSGID;
|
||||
static ub4 gc_AQPriority = OCI_ATTR_PRIORITY;
|
||||
static ub4 gc_AQState = OCI_ATTR_MSG_STATE;
|
||||
static ub4 gc_AQTransformation = OCI_ATTR_TRANSFORMATION;
|
||||
static ub4 gc_AQVisibility = OCI_ATTR_VISIBILITY;
|
||||
static ub4 gc_AQWait = OCI_ATTR_WAIT;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members for Python type "EnqOptions"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef g_EnqOptionsCalcMembers[] = {
|
||||
{ "deliverymode", 0, (setter) EnqOptions_SetOCIAttr, 0,
|
||||
&gc_AQDeliveryMode },
|
||||
{ "transformation", (getter) EnqOptions_GetOCIAttr,
|
||||
(setter) EnqOptions_SetOCIAttr, 0, &gc_AQTransformation },
|
||||
{ "visibility", (getter) EnqOptions_GetOCIAttr,
|
||||
(setter) EnqOptions_SetOCIAttr, 0, &gc_AQVisibility },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members for Python type "DeqOptions"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef g_DeqOptionsCalcMembers[] = {
|
||||
{ "condition", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQDeqCondition },
|
||||
{ "consumername", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQConsumerName },
|
||||
{ "correlation", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQCorrelation },
|
||||
{ "deliverymode", 0, (setter) EnqOptions_SetOCIAttr, 0,
|
||||
&gc_AQDeliveryMode },
|
||||
{ "mode", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQDeqMode },
|
||||
{ "msgid", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQDeqMsgId },
|
||||
{ "navigation", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQNavigation },
|
||||
{ "transformation", (getter) EnqOptions_GetOCIAttr,
|
||||
(setter) EnqOptions_SetOCIAttr, 0, &gc_AQTransformation },
|
||||
{ "visibility", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQVisibility },
|
||||
{ "wait", (getter) DeqOptions_GetOCIAttr,
|
||||
(setter) DeqOptions_SetOCIAttr, 0, &gc_AQWait },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members for Python type "MessageProperties"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef g_MessagePropertiesCalcMembers[] = {
|
||||
{ "attempts", (getter) MessageProperties_GetOCIAttr, 0, 0,
|
||||
&gc_AQAttempts },
|
||||
{ "correlation", (getter) MessageProperties_GetOCIAttr,
|
||||
(setter) MessageProperties_SetOCIAttr, 0, &gc_AQCorrelation },
|
||||
{ "delay", (getter) MessageProperties_GetOCIAttr,
|
||||
(setter) MessageProperties_SetOCIAttr, 0, &gc_AQDelay },
|
||||
{ "deliverymode", (getter) MessageProperties_GetOCIAttr, 0, 0,
|
||||
&gc_AQDeliveryMode },
|
||||
{ "enqtime", (getter) MessageProperties_GetOCIAttr, 0, 0, &gc_AQEnqTime },
|
||||
{ "exceptionq", (getter) MessageProperties_GetOCIAttr,
|
||||
(setter) MessageProperties_SetOCIAttr, 0, &gc_AQExceptionQ },
|
||||
{ "expiration", (getter) MessageProperties_GetOCIAttr,
|
||||
(setter) MessageProperties_SetOCIAttr, 0, &gc_AQExpiration },
|
||||
{ "msgid", (getter) MessageProperties_GetOCIAttr,
|
||||
(setter) MessageProperties_SetOCIAttr, 0, &gc_AQOriginalMsgId },
|
||||
{ "priority", (getter) MessageProperties_GetOCIAttr,
|
||||
(setter) MessageProperties_SetOCIAttr, 0, &gc_AQPriority },
|
||||
{ "state", (getter) MessageProperties_GetOCIAttr, 0, 0, &gc_AQState },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_EnqOptionsType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.EnqOptions", // tp_name
|
||||
sizeof(udt_EnqOptions), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) EnqOptions_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
g_EnqOptionsCalcMembers, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_DeqOptionsType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.DeqOptions", // tp_name
|
||||
sizeof(udt_DeqOptions), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) DeqOptions_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
g_DeqOptionsCalcMembers, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_MessagePropertiesType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.MessageProperties", // tp_name
|
||||
sizeof(udt_MessageProperties), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) MessageProperties_Free,// tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
g_MessagePropertiesCalcMembers, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_New()
|
||||
// Create a new enqueue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_EnqOptions *EnqOptions_New(
|
||||
udt_Environment *env) // environment in which to create
|
||||
{
|
||||
udt_EnqOptions *self;
|
||||
sword status;
|
||||
|
||||
self = (udt_EnqOptions*) g_EnqOptionsType.tp_alloc(&g_EnqOptionsType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
Py_INCREF(env);
|
||||
self->environment = env;
|
||||
status = OCIDescriptorAlloc(env->handle, (dvoid**) &self->handle,
|
||||
OCI_DTYPE_AQENQ_OPTIONS, 0, 0);
|
||||
if (Environment_CheckForError(env, status, "EnqOptions_New()") < 0) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_Free()
|
||||
// Free the memory associated with the enqueue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void EnqOptions_Free(
|
||||
udt_EnqOptions *self) // object to free
|
||||
{
|
||||
if (self->handle)
|
||||
OCIDescriptorFree(self->handle, OCI_DTYPE_AQENQ_OPTIONS);
|
||||
Py_CLEAR(self->environment);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_GetOCIAttr()
|
||||
// Get the value of the OCI attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *EnqOptions_GetOCIAttr(
|
||||
udt_EnqOptions *self, // options object
|
||||
ub4 *attribute) // OCI attribute type
|
||||
{
|
||||
ub4 valueLength, ub4Value;
|
||||
dvoid *ociValue = NULL;
|
||||
char *textValue;
|
||||
sword status;
|
||||
|
||||
// get the value from the OCI
|
||||
switch (*attribute) {
|
||||
case OCI_ATTR_VISIBILITY:
|
||||
ociValue = &ub4Value;
|
||||
break;
|
||||
case OCI_ATTR_TRANSFORMATION:
|
||||
ociValue = &textValue;
|
||||
break;
|
||||
};
|
||||
status = OCIAttrGet(self->handle, OCI_DTYPE_AQENQ_OPTIONS, ociValue,
|
||||
&valueLength, *attribute, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"EnqOptions_GetOCIAttr()") < 0)
|
||||
return NULL;
|
||||
if (*attribute == gc_AQTransformation) {
|
||||
if (!textValue)
|
||||
Py_RETURN_NONE;
|
||||
return cxString_FromEncodedString(textValue, valueLength,
|
||||
self->environment->encoding);
|
||||
}
|
||||
return PyInt_FromLong(ub4Value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_SetOCIAttr()
|
||||
// Set the value of the OCI attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int EnqOptions_SetOCIAttr(
|
||||
udt_EnqOptions *self, // options object
|
||||
PyObject *value, // value to set
|
||||
ub4 *attribute) // OCI attribute type
|
||||
{
|
||||
dvoid *ociValue = NULL;
|
||||
ub4 valueLength = 0;
|
||||
udt_Buffer buffer;
|
||||
ub4 ub4Value;
|
||||
ub2 ub2Value;
|
||||
sword status;
|
||||
|
||||
switch (*attribute) {
|
||||
case OCI_ATTR_MSG_DELIVERY_MODE:
|
||||
ub2Value = (ub2) PyInt_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
ociValue = &ub2Value;
|
||||
break;
|
||||
case OCI_ATTR_VISIBILITY:
|
||||
ub4Value = (ub4) PyInt_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
ociValue = &ub4Value;
|
||||
break;
|
||||
case OCI_ATTR_TRANSFORMATION:
|
||||
if (cxBuffer_FromObject(&buffer, value,
|
||||
self->environment->encoding) < 0)
|
||||
return -1;
|
||||
ociValue = (dvoid*) buffer.ptr;
|
||||
valueLength = (ub4) buffer.size;
|
||||
break;
|
||||
};
|
||||
status = OCIAttrSet(self->handle, OCI_DTYPE_AQENQ_OPTIONS,
|
||||
ociValue, valueLength, *attribute, self->environment->errorHandle);
|
||||
if (*attribute == gc_AQTransformation)
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"EnqOptions_SetOCIAttr()") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_New()
|
||||
// Create a new dequeue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_DeqOptions *DeqOptions_New(
|
||||
udt_Environment *env) // environment in which to create
|
||||
{
|
||||
udt_DeqOptions *self;
|
||||
sword status;
|
||||
|
||||
self = (udt_DeqOptions*) g_DeqOptionsType.tp_alloc(&g_DeqOptionsType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
Py_INCREF(env);
|
||||
self->environment = env;
|
||||
status = OCIDescriptorAlloc(env->handle, (dvoid**) &self->handle,
|
||||
OCI_DTYPE_AQDEQ_OPTIONS, 0, 0);
|
||||
if (Environment_CheckForError(env, status, "DeqOptions_New()") < 0) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_Free()
|
||||
// Free the memory associated with the dequeue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void DeqOptions_Free(
|
||||
udt_DeqOptions *self) // object to free
|
||||
{
|
||||
if (self->handle)
|
||||
OCIDescriptorFree(self->handle, OCI_DTYPE_AQDEQ_OPTIONS);
|
||||
Py_CLEAR(self->environment);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetOCIAttr()
|
||||
// Get the value of the OCI attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetOCIAttr(
|
||||
udt_DeqOptions *self, // options object
|
||||
ub4 *attribute) // OCI attribute type
|
||||
{
|
||||
ub4 valueLength, ub4Value;
|
||||
dvoid *ociValue = NULL;
|
||||
char *rawValuePtr;
|
||||
OCIRaw *rawValue;
|
||||
char *textValue;
|
||||
sword status;
|
||||
|
||||
// get the value from the OCI
|
||||
switch (*attribute) {
|
||||
case OCI_ATTR_DEQ_MODE:
|
||||
case OCI_ATTR_NAVIGATION:
|
||||
case OCI_ATTR_VISIBILITY:
|
||||
case OCI_ATTR_WAIT:
|
||||
ociValue = &ub4Value;
|
||||
break;
|
||||
case OCI_ATTR_CONSUMER_NAME:
|
||||
case OCI_ATTR_CORRELATION:
|
||||
case OCI_ATTR_DEQCOND:
|
||||
case OCI_ATTR_TRANSFORMATION:
|
||||
ociValue = &textValue;
|
||||
break;
|
||||
case OCI_ATTR_DEQ_MSGID:
|
||||
rawValue = NULL;
|
||||
ociValue = &rawValue;
|
||||
break;
|
||||
};
|
||||
status = OCIAttrGet(self->handle, OCI_DTYPE_AQDEQ_OPTIONS, ociValue,
|
||||
&valueLength, *attribute, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"DeqOptions_GetOCIAttr()") < 0)
|
||||
return NULL;
|
||||
if (ociValue == &textValue) {
|
||||
if (!textValue)
|
||||
Py_RETURN_NONE;
|
||||
return cxString_FromEncodedString(textValue, valueLength,
|
||||
self->environment->encoding);
|
||||
} else if (ociValue == &rawValue) {
|
||||
if (!rawValue)
|
||||
Py_RETURN_NONE;
|
||||
rawValuePtr = (char*) OCIRawPtr(self->environment->handle, rawValue);
|
||||
valueLength = OCIRawSize(self->environment->handle, rawValue);
|
||||
return PyBytes_FromStringAndSize(rawValuePtr, valueLength);
|
||||
}
|
||||
return PyInt_FromLong(ub4Value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetOCIAttr()
|
||||
// Set the value of the OCI attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetOCIAttr(
|
||||
udt_DeqOptions *self, // options object
|
||||
PyObject *value, // value to set
|
||||
ub4 *attribute) // OCI attribute type
|
||||
{
|
||||
Py_ssize_t rawValueLength;
|
||||
OCIRaw *rawValue = NULL;
|
||||
dvoid *ociValue = NULL;
|
||||
ub4 valueLength = 0;
|
||||
udt_Buffer buffer;
|
||||
char *rawValuePtr;
|
||||
ub4 ub4Value;
|
||||
ub2 ub2Value;
|
||||
sword status;
|
||||
|
||||
cxBuffer_Init(&buffer);
|
||||
switch (*attribute) {
|
||||
case OCI_ATTR_MSG_DELIVERY_MODE:
|
||||
ub2Value = (ub2) PyInt_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
ociValue = &ub2Value;
|
||||
break;
|
||||
case OCI_ATTR_DEQ_MODE:
|
||||
case OCI_ATTR_NAVIGATION:
|
||||
case OCI_ATTR_VISIBILITY:
|
||||
case OCI_ATTR_WAIT:
|
||||
ub4Value = (ub4) PyInt_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
ociValue = &ub4Value;
|
||||
break;
|
||||
case OCI_ATTR_CONSUMER_NAME:
|
||||
case OCI_ATTR_CORRELATION:
|
||||
case OCI_ATTR_DEQCOND:
|
||||
case OCI_ATTR_TRANSFORMATION:
|
||||
if (cxBuffer_FromObject(&buffer, value,
|
||||
self->environment->encoding) < 0)
|
||||
return -1;
|
||||
ociValue = (dvoid*) buffer.ptr;
|
||||
valueLength = (ub4) buffer.size;
|
||||
break;
|
||||
case OCI_ATTR_DEQ_MSGID:
|
||||
if (PyBytes_AsStringAndSize(value, &rawValuePtr,
|
||||
&rawValueLength) < 0)
|
||||
return -1;
|
||||
status = OCIRawAssignBytes(self->environment->handle,
|
||||
self->environment->errorHandle, (const ub1*) rawValuePtr,
|
||||
(ub4) rawValueLength, &rawValue);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"DeqOptions_SetOCIAttr(): assign raw value") < 0)
|
||||
return -1;
|
||||
ociValue = (dvoid*) &rawValue;
|
||||
valueLength = OCIRawSize(self->environment->handle, rawValue);
|
||||
break;
|
||||
};
|
||||
status = OCIAttrSet(self->handle, OCI_DTYPE_AQDEQ_OPTIONS,
|
||||
ociValue, valueLength, *attribute, self->environment->errorHandle);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (rawValue)
|
||||
OCIRawResize(self->environment->handle, self->environment->errorHandle,
|
||||
0, &rawValue);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"DeqOptions_SetOCIAttr(): set value") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MessageProperties_New()
|
||||
// Create a new dequeue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_MessageProperties *MessageProperties_New(
|
||||
udt_Environment *env) // environment in which to create
|
||||
{
|
||||
udt_MessageProperties *self;
|
||||
sword status;
|
||||
|
||||
self = (udt_MessageProperties*)
|
||||
g_MessagePropertiesType.tp_alloc(&g_MessagePropertiesType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
Py_INCREF(env);
|
||||
self->environment = env;
|
||||
status = OCIDescriptorAlloc(env->handle, (dvoid**) &self->handle,
|
||||
OCI_DTYPE_AQMSG_PROPERTIES, 0, 0);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageProperties_New()") < 0) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MessageProperties_Free()
|
||||
// Free the memory associated with the message properties object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void MessageProperties_Free(
|
||||
udt_MessageProperties *self) // object to free
|
||||
{
|
||||
if (self->handle)
|
||||
OCIDescriptorFree(self->handle, OCI_DTYPE_AQMSG_PROPERTIES);
|
||||
Py_CLEAR(self->environment);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MessageProperties_GetOCIAttr()
|
||||
// Get the value of the OCI attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MessageProperties_GetOCIAttr(
|
||||
udt_MessageProperties *self, // options object
|
||||
ub4 *attribute) // OCI attribute type
|
||||
{
|
||||
ub4 valueLength, ub4Value;
|
||||
dvoid *ociValue = NULL;
|
||||
char *rawValuePtr;
|
||||
OCIDate dateValue;
|
||||
OCIRaw *rawValue;
|
||||
char *textValue;
|
||||
sb4 sb4Value;
|
||||
ub2 ub2Value;
|
||||
sword status;
|
||||
|
||||
// get the value from the OCI
|
||||
switch (*attribute) {
|
||||
case OCI_ATTR_MSG_DELIVERY_MODE:
|
||||
ociValue = &ub2Value;
|
||||
break;
|
||||
case OCI_ATTR_ATTEMPTS:
|
||||
case OCI_ATTR_DELAY:
|
||||
case OCI_ATTR_EXPIRATION:
|
||||
case OCI_ATTR_PRIORITY:
|
||||
ociValue = &sb4Value;
|
||||
break;
|
||||
case OCI_ATTR_MSG_STATE:
|
||||
ociValue = &ub4Value;
|
||||
break;
|
||||
case OCI_ATTR_CORRELATION:
|
||||
case OCI_ATTR_EXCEPTION_QUEUE:
|
||||
ociValue = &textValue;
|
||||
break;
|
||||
case OCI_ATTR_ENQ_TIME:
|
||||
ociValue = &dateValue;
|
||||
break;
|
||||
case OCI_ATTR_ORIGINAL_MSGID:
|
||||
rawValue = NULL;
|
||||
ociValue = &rawValue;
|
||||
break;
|
||||
};
|
||||
status = OCIAttrGet(self->handle, OCI_DTYPE_AQMSG_PROPERTIES, ociValue,
|
||||
&valueLength, *attribute, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"MessageProperties_GetOCIAttr()") < 0)
|
||||
return NULL;
|
||||
if (ociValue == &textValue) {
|
||||
if (!textValue)
|
||||
Py_RETURN_NONE;
|
||||
return cxString_FromEncodedString(textValue, valueLength,
|
||||
self->environment->encoding);
|
||||
} else if (ociValue == &rawValue) {
|
||||
if (!rawValue)
|
||||
Py_RETURN_NONE;
|
||||
rawValuePtr = (char*) OCIRawPtr(self->environment->handle, rawValue);
|
||||
valueLength = OCIRawSize(self->environment->handle, rawValue);
|
||||
return PyBytes_FromStringAndSize(rawValuePtr, valueLength);
|
||||
} else if (ociValue == &dateValue)
|
||||
return OracleDateToPythonDate(&vt_DateTime, &dateValue);
|
||||
else if (ociValue == &ub2Value)
|
||||
return PyInt_FromLong(ub2Value);
|
||||
else if (ociValue == &sb4Value)
|
||||
return PyInt_FromLong(sb4Value);
|
||||
return PyInt_FromLong(ub4Value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MessageProperties_SetOCIAttr()
|
||||
// Set the value of the OCI attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MessageProperties_SetOCIAttr(
|
||||
udt_MessageProperties *self, // options object
|
||||
PyObject *value, // value to set
|
||||
ub4 *attribute) // OCI attribute type
|
||||
{
|
||||
Py_ssize_t rawValueLength;
|
||||
OCIRaw *rawValue = NULL;
|
||||
dvoid *ociValue = NULL;
|
||||
ub4 valueLength = 0;
|
||||
udt_Buffer buffer;
|
||||
char *rawValuePtr;
|
||||
ub4 ub4Value;
|
||||
ub2 ub2Value;
|
||||
sword status;
|
||||
|
||||
cxBuffer_Init(&buffer);
|
||||
switch (*attribute) {
|
||||
case OCI_ATTR_MSG_DELIVERY_MODE:
|
||||
ub2Value = (ub2) PyInt_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
ociValue = &ub2Value;
|
||||
break;
|
||||
case OCI_ATTR_DEQ_MODE:
|
||||
case OCI_ATTR_NAVIGATION:
|
||||
case OCI_ATTR_VISIBILITY:
|
||||
case OCI_ATTR_WAIT:
|
||||
ub4Value = (ub4) PyInt_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
ociValue = &ub4Value;
|
||||
break;
|
||||
case OCI_ATTR_CONSUMER_NAME:
|
||||
case OCI_ATTR_CORRELATION:
|
||||
case OCI_ATTR_DEQCOND:
|
||||
case OCI_ATTR_TRANSFORMATION:
|
||||
if (cxBuffer_FromObject(&buffer, value,
|
||||
self->environment->encoding) < 0)
|
||||
return -1;
|
||||
ociValue = (dvoid*) buffer.ptr;
|
||||
valueLength = (ub4) buffer.size;
|
||||
break;
|
||||
case OCI_ATTR_DEQ_MSGID:
|
||||
if (PyBytes_AsStringAndSize(value, &rawValuePtr,
|
||||
&rawValueLength) < 0)
|
||||
return -1;
|
||||
status = OCIRawAssignBytes(self->environment->handle,
|
||||
self->environment->errorHandle, (const ub1*) rawValuePtr,
|
||||
(ub4) rawValueLength, &rawValue);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"MessageProperties_SetOCIAttr(): assign raw value") < 0)
|
||||
return -1;
|
||||
ociValue = (dvoid*) &rawValue;
|
||||
valueLength = OCIRawSize(self->environment->handle, rawValue);
|
||||
break;
|
||||
};
|
||||
status = OCIAttrSet(self->handle, OCI_DTYPE_AQMSG_PROPERTIES,
|
||||
ociValue, valueLength, *attribute, self->environment->errorHandle);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (rawValue)
|
||||
OCIRawResize(self->environment->handle, self->environment->errorHandle,
|
||||
0, &rawValue);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"MessageProperties_SetOCIAttr(): set value") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -13,72 +13,29 @@
|
||||
// Oracle 12.1).
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Data types
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
boolean *data;
|
||||
} udt_BooleanVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int BooleanVar_SetValue(udt_BooleanVar*, unsigned, PyObject*);
|
||||
static PyObject *BooleanVar_GetValue(udt_BooleanVar*, unsigned);
|
||||
static int BooleanVar_SetValue(udt_Variable*, uint32_t, dpiData*, PyObject*);
|
||||
static PyObject *BooleanVar_GetValue(udt_Variable*, dpiData*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declaration
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_BooleanVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.BOOLEAN", // tp_name
|
||||
sizeof(udt_BooleanVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_BooleanVarType, BOOLEAN)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_Boolean = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) BooleanVar_SetValue,
|
||||
(GetValueProc) BooleanVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_BooleanVarType, // Python type
|
||||
SQLT_BOL, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(boolean), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_BOOLEAN, // Oracle type
|
||||
DPI_NATIVE_TYPE_BOOLEAN, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
@ -86,11 +43,11 @@ static udt_VariableType vt_Boolean = {
|
||||
// BooleanVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *BooleanVar_GetValue(
|
||||
udt_BooleanVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *BooleanVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
return OracleBooleanToPythonBoolean(&var->data[pos]);
|
||||
if (data->value.asBoolean)
|
||||
Py_RETURN_TRUE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -98,11 +55,10 @@ static PyObject *BooleanVar_GetValue(
|
||||
// BooleanVar_SetValue()
|
||||
// Set the value of the variable at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int BooleanVar_SetValue(
|
||||
udt_BooleanVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
static int BooleanVar_SetValue(udt_Variable *var, uint32_t pos, dpiData *data,
|
||||
PyObject *value)
|
||||
{
|
||||
return PythonBooleanToOracleBoolean(value, &var->data[pos]);
|
||||
data->value.asBoolean = (value == Py_True);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
38
src/Buffer.c
38
src/Buffer.c
@ -16,7 +16,7 @@
|
||||
|
||||
// define structure for abstracting string buffers
|
||||
typedef struct {
|
||||
const void *ptr;
|
||||
const char *ptr;
|
||||
Py_ssize_t numCharacters;
|
||||
Py_ssize_t size;
|
||||
PyObject *obj;
|
||||
@ -28,8 +28,7 @@ typedef struct {
|
||||
// Initialize the buffer with an empty string. Returns 0 as a convenience to
|
||||
// the caller.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int cxBuffer_Init(
|
||||
udt_Buffer *buf) // buffer to initialize
|
||||
static int cxBuffer_Init(udt_Buffer *buf)
|
||||
{
|
||||
buf->ptr = NULL;
|
||||
buf->size = 0;
|
||||
@ -39,41 +38,26 @@ static int cxBuffer_Init(
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// cxBuffer_Copy()
|
||||
// Copy the contents of the buffer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int cxBuffer_Copy(
|
||||
udt_Buffer *buf, // buffer to copy into
|
||||
udt_Buffer *copyFromBuf) // buffer to copy from
|
||||
{
|
||||
buf->ptr = copyFromBuf->ptr;
|
||||
buf->size = copyFromBuf->size;
|
||||
buf->numCharacters = copyFromBuf->numCharacters;
|
||||
Py_XINCREF(copyFromBuf->obj);
|
||||
buf->obj = copyFromBuf->obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// cxBuffer_FromObject()
|
||||
// Populate the string buffer from a unicode object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int cxBuffer_FromObject(
|
||||
udt_Buffer *buf, // buffer to fill
|
||||
PyObject *obj, // object (string or Unicode object)
|
||||
const char *encoding) // encoding to use, if applicable
|
||||
static int cxBuffer_FromObject(udt_Buffer *buf, PyObject *obj,
|
||||
const char *encoding)
|
||||
{
|
||||
if (!obj)
|
||||
return cxBuffer_Init(buf);
|
||||
if (encoding && PyUnicode_Check(obj)) {
|
||||
if (PyUnicode_Check(obj)) {
|
||||
buf->obj = PyUnicode_AsEncodedString(obj, encoding, NULL);
|
||||
if (!buf->obj)
|
||||
return -1;
|
||||
buf->ptr = PyBytes_AS_STRING(buf->obj);
|
||||
buf->size = PyBytes_GET_SIZE(buf->obj);
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
buf->numCharacters = PyUnicode_GET_SIZE(obj);
|
||||
#else
|
||||
buf->numCharacters = PyUnicode_GET_LENGTH(obj);
|
||||
#endif
|
||||
} else if (PyBytes_Check(obj)) {
|
||||
Py_INCREF(obj);
|
||||
buf->obj = obj;
|
||||
@ -81,7 +65,7 @@ static int cxBuffer_FromObject(
|
||||
buf->size = buf->numCharacters = PyBytes_GET_SIZE(buf->obj);
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
} else if (PyBuffer_Check(obj)) {
|
||||
if (PyObject_AsReadBuffer(obj, &buf->ptr, &buf->size) < 0)
|
||||
if (PyObject_AsReadBuffer(obj, (void*) &buf->ptr, &buf->size) < 0)
|
||||
return -1;
|
||||
Py_INCREF(obj);
|
||||
buf->obj = obj;
|
||||
@ -94,5 +78,5 @@ static int cxBuffer_FromObject(
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define cxBuffer_Clear(buf) Py_XDECREF((buf)->obj)
|
||||
#define cxBuffer_Clear(buf) Py_CLEAR((buf)->obj)
|
||||
|
||||
|
||||
1945
src/Connection.c
1945
src/Connection.c
File diff suppressed because it is too large
Load Diff
1776
src/Cursor.c
1776
src/Cursor.c
File diff suppressed because it is too large
Load Diff
149
src/CursorVar.c
149
src/CursorVar.c
@ -12,134 +12,38 @@
|
||||
// Defines the routines specific to the cursor type.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Cursor variable type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
OCIStmt **data;
|
||||
udt_Connection *connection;
|
||||
PyObject *cursors;
|
||||
} udt_CursorVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of cursor variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int CursorVar_Initialize(udt_CursorVar*, udt_Cursor*);
|
||||
static void CursorVar_Finalize(udt_CursorVar*);
|
||||
static int CursorVar_SetValue(udt_CursorVar*, unsigned, PyObject*);
|
||||
static PyObject *CursorVar_GetValue(udt_CursorVar*, unsigned);
|
||||
static int CursorVar_SetValue(udt_Variable*, uint32_t, dpiData*, PyObject*);
|
||||
static PyObject *CursorVar_GetValue(udt_Variable*, dpiData*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_CursorVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.CURSOR", // tp_name
|
||||
sizeof(udt_CursorVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_CursorVarType, CURSOR)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_Cursor = {
|
||||
(InitializeProc) CursorVar_Initialize,
|
||||
(FinalizeProc) CursorVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) CursorVar_SetValue,
|
||||
(GetValueProc) CursorVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_CursorVarType, // Python type
|
||||
SQLT_RSET, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCIStmt*), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
0, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_STMT, // Oracle type
|
||||
DPI_NATIVE_TYPE_STMT, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CursorVar_Initialize()
|
||||
// Initialize the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int CursorVar_Initialize(
|
||||
udt_CursorVar *var, // variable to initialize
|
||||
udt_Cursor *cursor) // cursor created by
|
||||
{
|
||||
udt_Cursor *tempCursor;
|
||||
ub4 i;
|
||||
|
||||
Py_INCREF(cursor->connection);
|
||||
var->connection = cursor->connection;
|
||||
var->cursors = PyList_New(var->allocatedElements);
|
||||
if (!var->cursors)
|
||||
return -1;
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
tempCursor = (udt_Cursor*) Connection_NewCursor(var->connection, NULL,
|
||||
NULL);
|
||||
if (!tempCursor) {
|
||||
Py_DECREF(var);
|
||||
return -1;
|
||||
}
|
||||
PyList_SET_ITEM(var->cursors, i, (PyObject*) tempCursor);
|
||||
if (Cursor_AllocateHandle(tempCursor) < 0) {
|
||||
Py_DECREF(var);
|
||||
return -1;
|
||||
}
|
||||
var->data[i] = tempCursor->handle;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CursorVar_Finalize()
|
||||
// Prepare for variable destruction.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CursorVar_Finalize(
|
||||
udt_CursorVar *var) // variable to free
|
||||
{
|
||||
Py_DECREF(var->connection);
|
||||
Py_XDECREF(var->cursors);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CursorVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int CursorVar_SetValue(
|
||||
udt_CursorVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
static int CursorVar_SetValue(udt_Variable *var, uint32_t pos, dpiData *data,
|
||||
PyObject *value)
|
||||
{
|
||||
udt_Cursor *cursor;
|
||||
|
||||
@ -147,20 +51,15 @@ static int CursorVar_SetValue(
|
||||
PyErr_SetString(PyExc_TypeError, "expecting cursor");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_XDECREF(PyList_GET_ITEM(var->cursors, pos));
|
||||
Py_INCREF(value);
|
||||
PyList_SET_ITEM(var->cursors, pos, value);
|
||||
cursor = (udt_Cursor *) value;
|
||||
if (!cursor->isOwned) {
|
||||
if (Cursor_FreeHandle(cursor, 1) < 0)
|
||||
return -1;
|
||||
cursor->isOwned = 1;
|
||||
if (Cursor_AllocateHandle(cursor) < 0)
|
||||
return -1;
|
||||
if (cursor->handle) {
|
||||
if (dpiVar_setFromStmt(var->handle, pos, cursor->handle) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
} else {
|
||||
cursor->handle = data->value.asStmt;
|
||||
dpiStmt_addRef(cursor->handle);
|
||||
}
|
||||
var->data[pos] = cursor->handle;
|
||||
cursor->statementType = -1;
|
||||
cursor->fixupRefCursor = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -169,15 +68,17 @@ static int CursorVar_SetValue(
|
||||
// CursorVar_GetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *CursorVar_GetValue(
|
||||
udt_CursorVar *var, // variable to set value for
|
||||
unsigned pos) // array position to set
|
||||
static PyObject *CursorVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
PyObject *cursor;
|
||||
udt_Cursor *cursor;
|
||||
|
||||
cursor = PyList_GET_ITEM(var->cursors, pos);
|
||||
((udt_Cursor*) cursor)->statementType = -1;
|
||||
Py_INCREF(cursor);
|
||||
return cursor;
|
||||
cursor = (udt_Cursor*) PyObject_CallMethod((PyObject*) var->connection,
|
||||
"cursor", NULL);
|
||||
if (!cursor)
|
||||
return NULL;
|
||||
cursor->handle = data->value.asStmt;
|
||||
dpiStmt_addRef(cursor->handle);
|
||||
cursor->fixupRefCursor = 1;
|
||||
return (PyObject*) cursor;
|
||||
}
|
||||
|
||||
|
||||
@ -12,94 +12,60 @@
|
||||
// Defines the routines for handling date (time) variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DateTime type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
OCIDate *data;
|
||||
} udt_DateTimeVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of date/time variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DateTimeVar_SetValue(udt_DateTimeVar*, unsigned, PyObject*);
|
||||
static PyObject *DateTimeVar_GetValue(udt_DateTimeVar*, unsigned);
|
||||
static int DateTimeVar_SetValue(udt_Variable*, uint32_t, dpiData*, PyObject*);
|
||||
static PyObject *DateTimeVar_GetValue(udt_Variable*, dpiData*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_DateTimeVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.DATETIME", // tp_name
|
||||
sizeof(udt_DateTimeVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_DateTimeVarType, DATETIME)
|
||||
DECLARE_VARIABLE_TYPE(g_TimestampVarType, TIMESTAMP)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_DateTime = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) DateTimeVar_SetValue,
|
||||
(GetValueProc) DateTimeVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_DateTimeVarType, // Python type
|
||||
SQLT_ODT, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCIDate), // element length (default)
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_DATE, // Oracle type
|
||||
DPI_NATIVE_TYPE_TIMESTAMP, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_Date = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) DateTimeVar_SetValue,
|
||||
(GetValueProc) DateTimeVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_DateTimeVarType, // Python type
|
||||
SQLT_ODT, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCIDate), // element length (default)
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_DATE, // Oracle type
|
||||
DPI_NATIVE_TYPE_TIMESTAMP, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_Timestamp = {
|
||||
(SetValueProc) DateTimeVar_SetValue,
|
||||
(GetValueProc) DateTimeVar_GetValue,
|
||||
&g_TimestampVarType, // Python type
|
||||
DPI_ORACLE_TYPE_TIMESTAMP, // Oracle type
|
||||
DPI_NATIVE_TYPE_TIMESTAMP, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_TimestampLTZ = {
|
||||
(SetValueProc) DateTimeVar_SetValue,
|
||||
(GetValueProc) DateTimeVar_GetValue,
|
||||
&g_TimestampVarType, // Python type
|
||||
DPI_ORACLE_TYPE_TIMESTAMP_LTZ, // Oracle type
|
||||
DPI_NATIVE_TYPE_TIMESTAMP, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
@ -107,12 +73,33 @@ static udt_VariableType vt_Date = {
|
||||
// DateTimeVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DateTimeVar_SetValue(
|
||||
udt_DateTimeVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
static int DateTimeVar_SetValue(udt_Variable *var, uint32_t pos, dpiData *data,
|
||||
PyObject *value)
|
||||
{
|
||||
return PythonDateToOracleDate(value, &var->data[pos]);
|
||||
dpiTimestamp *timestamp;
|
||||
|
||||
timestamp = &data->value.asTimestamp;
|
||||
if (PyDateTime_Check(value)) {
|
||||
timestamp->year = PyDateTime_GET_YEAR(value);
|
||||
timestamp->month = PyDateTime_GET_MONTH(value);
|
||||
timestamp->day = PyDateTime_GET_DAY(value);
|
||||
timestamp->hour = PyDateTime_DATE_GET_HOUR(value);
|
||||
timestamp->minute = PyDateTime_DATE_GET_MINUTE(value);
|
||||
timestamp->second = PyDateTime_DATE_GET_SECOND(value);
|
||||
timestamp->fsecond = PyDateTime_DATE_GET_MICROSECOND(value) * 1000;
|
||||
} else if (PyDate_Check(value)) {
|
||||
timestamp->year = PyDateTime_GET_YEAR(value);
|
||||
timestamp->month = PyDateTime_GET_MONTH(value);
|
||||
timestamp->day = PyDateTime_GET_DAY(value);
|
||||
timestamp->hour = 0;
|
||||
timestamp->minute = 0;
|
||||
timestamp->second = 0;
|
||||
timestamp->fsecond = 0;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting date data");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -120,10 +107,16 @@ static int DateTimeVar_SetValue(
|
||||
// DateTimeVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DateTimeVar_GetValue(
|
||||
udt_DateTimeVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *DateTimeVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
return OracleDateToPythonDate(var->type, &var->data[pos]);
|
||||
dpiTimestamp *timestamp;
|
||||
|
||||
timestamp = &data->value.asTimestamp;
|
||||
if (var->type == &vt_Date)
|
||||
return PyDate_FromDate(timestamp->year, timestamp->month,
|
||||
timestamp->day);
|
||||
return PyDateTime_FromDateAndTime(timestamp->year, timestamp->month,
|
||||
timestamp->day, timestamp->hour, timestamp->minute,
|
||||
timestamp->second, timestamp->fsecond / 1000);
|
||||
}
|
||||
|
||||
|
||||
466
src/DeqOptions.c
Normal file
466
src/DeqOptions.c
Normal file
@ -0,0 +1,466 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions.c
|
||||
// Implements the dequeue options objects used in Advanced Queuing.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// structure used for implementing dequeue options
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
dpiDeqOptions *handle;
|
||||
const char *encoding;
|
||||
} udt_DeqOptions;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of methods used for dequeue options
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_DeqOptions *DeqOptions_New(udt_Connection*);
|
||||
static void DeqOptions_Free(udt_DeqOptions*);
|
||||
static PyObject *DeqOptions_GetCondition(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetConsumerName(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetCorrelation(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetMode(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetMsgId(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetNavigation(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetTransformation(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetVisibility(udt_DeqOptions*, void*);
|
||||
static PyObject *DeqOptions_GetWait(udt_DeqOptions*, void*);
|
||||
static int DeqOptions_SetCondition(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetConsumerName(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetCorrelation(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetDeliveryMode(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetMode(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetMsgId(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetNavigation(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetTransformation(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetVisibility(udt_DeqOptions*, PyObject*, void*);
|
||||
static int DeqOptions_SetWait(udt_DeqOptions*, PyObject*, void*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members for Python type "DeqOptions"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef g_DeqOptionsCalcMembers[] = {
|
||||
{ "condition", (getter) DeqOptions_GetCondition,
|
||||
(setter) DeqOptions_SetCondition, 0, 0 },
|
||||
{ "consumername", (getter) DeqOptions_GetConsumerName,
|
||||
(setter) DeqOptions_SetConsumerName, 0, 0 },
|
||||
{ "correlation", (getter) DeqOptions_GetCorrelation,
|
||||
(setter) DeqOptions_SetCorrelation, 0, 0 },
|
||||
{ "deliverymode", 0, (setter) DeqOptions_SetDeliveryMode, 0, 0 },
|
||||
{ "mode", (getter) DeqOptions_GetMode, (setter) DeqOptions_SetMode, 0, 0 },
|
||||
{ "msgid", (getter) DeqOptions_GetMsgId,
|
||||
(setter) DeqOptions_SetMsgId, 0, 0 },
|
||||
{ "navigation", (getter) DeqOptions_GetNavigation,
|
||||
(setter) DeqOptions_SetNavigation, 0, 0 },
|
||||
{ "transformation", (getter) DeqOptions_GetTransformation,
|
||||
(setter) DeqOptions_SetTransformation, 0, 0 },
|
||||
{ "visibility", (getter) DeqOptions_GetVisibility,
|
||||
(setter) DeqOptions_SetVisibility, 0, 0 },
|
||||
{ "wait", (getter) DeqOptions_GetWait, (setter) DeqOptions_SetWait, 0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_DeqOptionsType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.DeqOptions", // tp_name
|
||||
sizeof(udt_DeqOptions), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) DeqOptions_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
g_DeqOptionsCalcMembers, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_New()
|
||||
// Create a new dequeue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_DeqOptions *DeqOptions_New(udt_Connection *connection)
|
||||
{
|
||||
udt_DeqOptions *self;
|
||||
|
||||
self = (udt_DeqOptions*) g_DeqOptionsType.tp_alloc(&g_DeqOptionsType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
if (dpiConn_newDeqOptions(connection->handle, &self->handle) < 0) {
|
||||
Py_DECREF(self);
|
||||
Error_RaiseAndReturnNull();
|
||||
return NULL;
|
||||
}
|
||||
self->encoding = connection->encodingInfo.encoding;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_Free()
|
||||
// Free the memory associated with the dequeue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void DeqOptions_Free(
|
||||
udt_DeqOptions *self) // object to free
|
||||
{
|
||||
if (self->handle) {
|
||||
dpiDeqOptions_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetAttrText()
|
||||
// Get the value of the attribute as text.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetAttrText(udt_DeqOptions *self,
|
||||
int (*func)(dpiDeqOptions*, const char**, uint32_t*))
|
||||
{
|
||||
uint32_t valueLength;
|
||||
const char *value;
|
||||
|
||||
if ((*func)(self->handle, &value, &valueLength) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (!value)
|
||||
Py_RETURN_NONE;
|
||||
return cxString_FromEncodedString(value, valueLength, self->encoding);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetAttrText()
|
||||
// Set the value of the attribute as text.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetAttrText(udt_DeqOptions *self, PyObject *value,
|
||||
int (*func)(dpiDeqOptions*, const char*, uint32_t))
|
||||
{
|
||||
udt_Buffer buffer;
|
||||
int status;
|
||||
|
||||
if (cxBuffer_FromObject(&buffer, value, self->encoding))
|
||||
return -1;
|
||||
status = (*func)(self->handle, buffer.ptr, buffer.size);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetCondition()
|
||||
// Get the value of the condition option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetCondition(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
return DeqOptions_GetAttrText(self, dpiDeqOptions_getCondition);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetConsumerName()
|
||||
// Get the value of the consumer name option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetConsumerName(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
return DeqOptions_GetAttrText(self, dpiDeqOptions_getConsumerName);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetCorrelation()
|
||||
// Get the value of the correlation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetCorrelation(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
return DeqOptions_GetAttrText(self, dpiDeqOptions_getCorrelation);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetMode()
|
||||
// Get the value of the mode option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetMode(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
dpiDeqMode value;
|
||||
|
||||
if (dpiDeqOptions_getMode(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetMsgId()
|
||||
// Get the value of the message id option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetMsgId(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
uint32_t valueLength;
|
||||
const char *value;
|
||||
|
||||
if (dpiDeqOptions_getMsgId(self->handle, &value, &valueLength) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (!value)
|
||||
Py_RETURN_NONE;
|
||||
return PyBytes_FromStringAndSize(value, valueLength);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetNavigation()
|
||||
// Get the value of the navigation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetNavigation(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
dpiDeqNavigation value;
|
||||
|
||||
if (dpiDeqOptions_getNavigation(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetTransformation()
|
||||
// Get the value of the transformation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetTransformation(udt_DeqOptions *self,
|
||||
void *unused)
|
||||
{
|
||||
return DeqOptions_GetAttrText(self, dpiDeqOptions_getTransformation);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetVisibility()
|
||||
// Get the value of the visibility option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetVisibility(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
dpiVisibility value;
|
||||
|
||||
if (dpiDeqOptions_getVisibility(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_GetWait()
|
||||
// Get the value of the wait option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *DeqOptions_GetWait(udt_DeqOptions *self, void *unused)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
if (dpiDeqOptions_getWait(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetCondition()
|
||||
// Set the value of the condition option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetCondition(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
return DeqOptions_SetAttrText(self, valueObj, dpiDeqOptions_setCondition);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetConsumerName()
|
||||
// Set the value of the consumer name option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetConsumerName(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
return DeqOptions_SetAttrText(self, valueObj,
|
||||
dpiDeqOptions_setConsumerName);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetCorrelation()
|
||||
// Set the value of the correlation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetCorrelation(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
return DeqOptions_SetAttrText(self, valueObj,
|
||||
dpiDeqOptions_setCorrelation);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetDeliveryMode()
|
||||
// Set the value of the delivery mode option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetDeliveryMode(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
dpiMessageDeliveryMode value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (dpiDeqOptions_setDeliveryMode(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetMode()
|
||||
// Set the value of the mode option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetMode(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
dpiDeqMode value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (dpiDeqOptions_setMode(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetMsgId()
|
||||
// Set the value of the message id option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetMsgId(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
Py_ssize_t valueLength;
|
||||
char *value;
|
||||
|
||||
if (PyBytes_AsStringAndSize(valueObj, &value, &valueLength) < 0)
|
||||
return -1;
|
||||
if (dpiDeqOptions_setMsgId(self->handle, value, valueLength) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetNavigation()
|
||||
// Set the value of the navigation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetNavigation(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
dpiDeqNavigation value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (dpiDeqOptions_setNavigation(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetTransformation()
|
||||
// Set the value of the correlation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetTransformation(udt_DeqOptions *self,
|
||||
PyObject *valueObj, void *unused)
|
||||
{
|
||||
return DeqOptions_SetAttrText(self, valueObj,
|
||||
dpiDeqOptions_setTransformation);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetVisibility()
|
||||
// Set the value of the visibility option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetVisibility(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
dpiVisibility value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (dpiDeqOptions_setVisibility(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DeqOptions_SetWait()
|
||||
// Set the value of the wait option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int DeqOptions_SetWait(udt_DeqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (dpiDeqOptions_setWait(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
222
src/EnqOptions.c
Normal file
222
src/EnqOptions.c
Normal file
@ -0,0 +1,222 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions.c
|
||||
// Implements the enqueue options objects used in Advanced Queuing.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// structure used for implementing enqueue options
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
dpiEnqOptions *handle;
|
||||
const char *encoding;
|
||||
} udt_EnqOptions;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of methods used for enqueue options
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_EnqOptions *EnqOptions_New(udt_Connection*);
|
||||
static void EnqOptions_Free(udt_EnqOptions*);
|
||||
static PyObject *EnqOptions_GetTransformation(udt_EnqOptions*, void*);
|
||||
static PyObject *EnqOptions_GetVisibility(udt_EnqOptions*, void*);
|
||||
static int EnqOptions_SetDeliveryMode(udt_EnqOptions*, PyObject*, void*);
|
||||
static int EnqOptions_SetTransformation(udt_EnqOptions*, PyObject*, void*);
|
||||
static int EnqOptions_SetVisibility(udt_EnqOptions*, PyObject*, void*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members for Python type "EnqOptions"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef g_EnqOptionsCalcMembers[] = {
|
||||
{ "deliverymode", 0, (setter) EnqOptions_SetDeliveryMode, 0, 0 },
|
||||
{ "transformation", (getter) EnqOptions_GetTransformation,
|
||||
(setter) EnqOptions_SetTransformation, 0, 0 },
|
||||
{ "visibility", (getter) EnqOptions_GetVisibility,
|
||||
(setter) EnqOptions_SetVisibility, 0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_EnqOptionsType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.EnqOptions", // tp_name
|
||||
sizeof(udt_EnqOptions), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) EnqOptions_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
g_EnqOptionsCalcMembers, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_New()
|
||||
// Create a new enqueue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_EnqOptions *EnqOptions_New(udt_Connection *connection)
|
||||
{
|
||||
udt_EnqOptions *self;
|
||||
|
||||
self = (udt_EnqOptions*) g_EnqOptionsType.tp_alloc(&g_EnqOptionsType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
if (dpiConn_newEnqOptions(connection->handle, &self->handle) < 0) {
|
||||
Py_DECREF(self);
|
||||
Error_RaiseAndReturnNull();
|
||||
return NULL;
|
||||
}
|
||||
self->encoding = connection->encodingInfo.encoding;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_Free()
|
||||
// Free the memory associated with the enqueue options object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void EnqOptions_Free(udt_EnqOptions *self)
|
||||
{
|
||||
if (self->handle) {
|
||||
dpiEnqOptions_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_GetTransformation()
|
||||
// Get the value of the transformation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *EnqOptions_GetTransformation(udt_EnqOptions *self,
|
||||
void *unused)
|
||||
{
|
||||
uint32_t valueLength;
|
||||
const char *value;
|
||||
|
||||
if (dpiEnqOptions_getTransformation(self->handle, &value,
|
||||
&valueLength) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (!value)
|
||||
Py_RETURN_NONE;
|
||||
return cxString_FromEncodedString(value, valueLength, self->encoding);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_GetVisibility()
|
||||
// Get the value of the visibility option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *EnqOptions_GetVisibility(udt_EnqOptions *self, void *unused)
|
||||
{
|
||||
dpiVisibility value;
|
||||
|
||||
if (dpiEnqOptions_getVisibility(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_SetDeliveryMode()
|
||||
// Set the value of the delivery mode option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int EnqOptions_SetDeliveryMode(udt_EnqOptions *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
dpiMessageDeliveryMode value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (dpiEnqOptions_setDeliveryMode(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_SetTransformation()
|
||||
// Set the value of the transformation option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int EnqOptions_SetTransformation(udt_EnqOptions *self,
|
||||
PyObject *valueObj, void *unused)
|
||||
{
|
||||
udt_Buffer buffer;
|
||||
int status;
|
||||
|
||||
if (cxBuffer_FromObject(&buffer, valueObj, self->encoding) < 0)
|
||||
return -1;
|
||||
status = dpiEnqOptions_setTransformation(self->handle, buffer.ptr,
|
||||
buffer.size);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// EnqOptions_SetVisibility()
|
||||
// Set the value of the visibility option.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int EnqOptions_SetVisibility(udt_EnqOptions *self,
|
||||
PyObject *valueObj, void *unused)
|
||||
{
|
||||
dpiVisibility value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if (dpiEnqOptions_setVisibility(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1,404 +0,0 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment.c
|
||||
// Environment handling.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// structure for the Python type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
OCIEnv *handle;
|
||||
OCIError *errorHandle;
|
||||
int maxBytesPerCharacter;
|
||||
int nmaxBytesPerCharacter;
|
||||
char *encoding;
|
||||
char *nencoding;
|
||||
ub2 charsetId;
|
||||
ub2 ncharsetId;
|
||||
PyObject *cloneEnv;
|
||||
udt_Buffer numberToStringFormatBuffer;
|
||||
udt_Buffer numberFromStringFormatBuffer;
|
||||
udt_Buffer nlsNumericCharactersBuffer;
|
||||
} udt_Environment;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static void Environment_Free(udt_Environment*);
|
||||
static int Environment_CheckForError(udt_Environment*, sword, const char*);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of Python type
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_EnvironmentType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"OracleEnvironment", // tp_name
|
||||
sizeof(udt_Environment), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) Environment_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
#include "Error.c"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_New()
|
||||
// Create a new environment object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_Environment *Environment_New(
|
||||
OCIEnv *handle) // handle to use
|
||||
{
|
||||
udt_Environment *env;
|
||||
udt_Error *errorObj;
|
||||
sword status;
|
||||
|
||||
// create a new object for the Oracle environment
|
||||
env = (udt_Environment*) g_EnvironmentType.tp_alloc(&g_EnvironmentType, 0);
|
||||
if (!env)
|
||||
return NULL;
|
||||
env->handle = handle;
|
||||
env->maxBytesPerCharacter = 1;
|
||||
env->nmaxBytesPerCharacter = 4;
|
||||
cxBuffer_Init(&env->numberToStringFormatBuffer);
|
||||
cxBuffer_Init(&env->numberFromStringFormatBuffer);
|
||||
cxBuffer_Init(&env->nlsNumericCharactersBuffer);
|
||||
|
||||
// create the error handle
|
||||
status = OCIHandleAlloc(handle, (dvoid**) &env->errorHandle,
|
||||
OCI_HTYPE_ERROR, 0, 0);
|
||||
if (status != OCI_SUCCESS) {
|
||||
errorObj = Error_InternalNew(env,
|
||||
"Environment_New(): create error handle", OCI_HTYPE_ENV,
|
||||
handle);
|
||||
if (!errorObj) {
|
||||
Py_DECREF(env);
|
||||
return NULL;
|
||||
}
|
||||
PyErr_SetObject(g_DatabaseErrorException, (PyObject*) errorObj);
|
||||
Py_DECREF(env);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_GetCharacterSetName()
|
||||
// Retrieve and store the IANA character set name for the attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Environment_GetCharacterSetName(
|
||||
udt_Environment *self, // environment object
|
||||
ub2 attribute, // attribute to fetch
|
||||
const char *overrideValue, // override value, if specified
|
||||
char **result, // place to store result
|
||||
ub2 *charsetId) // character set ID (OUT)
|
||||
{
|
||||
char charsetName[OCI_NLS_MAXBUFSZ], ianaCharsetName[OCI_NLS_MAXBUFSZ];
|
||||
sword status;
|
||||
|
||||
// get character set id
|
||||
status = OCIAttrGet(self->handle, OCI_HTYPE_ENV, charsetId, NULL,
|
||||
attribute, self->errorHandle);
|
||||
if (Environment_CheckForError(self, status,
|
||||
"Environment_GetCharacterSetName(): get charset id") < 0)
|
||||
return -1;
|
||||
|
||||
// if override value specified, use it
|
||||
if (overrideValue) {
|
||||
*result = PyMem_Malloc(strlen(overrideValue) + 1);
|
||||
if (!*result)
|
||||
return -1;
|
||||
strcpy(*result, overrideValue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get character set name
|
||||
status = OCINlsCharSetIdToName(self->handle, (text*) charsetName,
|
||||
OCI_NLS_MAXBUFSZ, *charsetId);
|
||||
if (Environment_CheckForError(self, status,
|
||||
"Environment_GetCharacterSetName(): get Oracle charset name") < 0)
|
||||
return -1;
|
||||
|
||||
// get IANA character set name
|
||||
status = OCINlsNameMap(self->handle, (oratext*) ianaCharsetName,
|
||||
OCI_NLS_MAXBUFSZ, (oratext*) charsetName, OCI_NLS_CS_ORA_TO_IANA);
|
||||
if (Environment_CheckForError(self, status,
|
||||
"Environment_GetCharacterSetName(): translate NLS charset") < 0)
|
||||
return -1;
|
||||
|
||||
// store results
|
||||
*result = PyMem_Malloc(strlen(ianaCharsetName) + 1);
|
||||
if (!*result)
|
||||
return -1;
|
||||
strcpy(*result, ianaCharsetName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_SetBuffer()
|
||||
// Set the buffer in the environment from the specified string.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Environment_SetBuffer(
|
||||
udt_Buffer *buf, // buffer to set
|
||||
const char *value, // ASCII value to use
|
||||
const char *encoding) // encoding to use
|
||||
{
|
||||
PyObject *obj;
|
||||
|
||||
obj = cxString_FromAscii(value);
|
||||
if (!obj)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(buf, obj, encoding) < 0) {
|
||||
Py_DECREF(obj);
|
||||
return -1;
|
||||
}
|
||||
Py_CLEAR(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_LookupCharSet()
|
||||
// Look up an Oracle character set given the name. This can be either the
|
||||
// Oracle character set name or the IANA encoding name. A pointer to an
|
||||
// environment handle is passed and an environment created if needed in
|
||||
// order to perform the lookup.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Environment_LookupCharSet(
|
||||
const char *name, // IANA or Oracle character set name
|
||||
OCIEnv **envHandle, // environment handle (IN/OUT)
|
||||
ub2 *charsetId) // Oracle character set id (OUT)
|
||||
{
|
||||
char oraCharsetName[OCI_NLS_MAXBUFSZ];
|
||||
sword status;
|
||||
|
||||
// if IANA name is null, use the charset 0 which tells Oracle to make use
|
||||
// of the NLS_LANG and NLS_NCHAR environment variables
|
||||
if (!name) {
|
||||
*charsetId = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create environment, if needed
|
||||
if (!*envHandle) {
|
||||
status = OCIEnvCreate(envHandle, OCI_DEFAULT, NULL, NULL, NULL, NULL,
|
||||
0, NULL);
|
||||
if (status != OCI_SUCCESS) {
|
||||
PyErr_SetString(g_InterfaceErrorException,
|
||||
"Unable to acquire Oracle environment handle");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// check for the Oracle character set name first
|
||||
// if that fails, lookup using the IANA character set name
|
||||
*charsetId = OCINlsCharSetNameToId(*envHandle, (oratext*) name);
|
||||
if (!*charsetId) {
|
||||
status = OCINlsNameMap(*envHandle, (oratext*) oraCharsetName,
|
||||
sizeof(oraCharsetName), (oratext*) name,
|
||||
OCI_NLS_CS_IANA_TO_ORA);
|
||||
if (status == OCI_ERROR) {
|
||||
PyErr_SetString(g_InterfaceErrorException,
|
||||
"Invalid character set name");
|
||||
return -1;
|
||||
}
|
||||
*charsetId = OCINlsCharSetNameToId(*envHandle,
|
||||
(oratext*) oraCharsetName);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_NewFromScratch()
|
||||
// Create a new environment object from scratch.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_Environment *Environment_NewFromScratch(
|
||||
int threaded, // use threaded mode?
|
||||
int events, // use events mode?
|
||||
char *encoding, // override value for encoding
|
||||
char *nencoding) // override value for nencoding
|
||||
{
|
||||
ub2 charsetId, ncharsetId;
|
||||
udt_Environment *env;
|
||||
OCIEnv *handle;
|
||||
sword status;
|
||||
ub4 mode;
|
||||
|
||||
// turn threading mode on, if desired
|
||||
mode = OCI_OBJECT;
|
||||
if (threaded)
|
||||
mode |= OCI_THREADED;
|
||||
if (events)
|
||||
mode |= OCI_EVENTS;
|
||||
|
||||
// perform lookup of character sets to use
|
||||
// keep track of any environment that needs to be created in order to
|
||||
// perform this lookup
|
||||
handle = NULL;
|
||||
status = Environment_LookupCharSet(encoding, &handle, &charsetId);
|
||||
if (status == 0)
|
||||
status = Environment_LookupCharSet(nencoding, &handle, &ncharsetId);
|
||||
if (handle) {
|
||||
OCIHandleFree(handle, OCI_HTYPE_ENV);
|
||||
handle = NULL;
|
||||
}
|
||||
if (status < 0)
|
||||
return NULL;
|
||||
|
||||
// create the new environment handle
|
||||
status = OCIEnvNlsCreate(&handle, mode, NULL, NULL, NULL, NULL, 0, NULL,
|
||||
charsetId, ncharsetId);
|
||||
if (!handle ||
|
||||
(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO)) {
|
||||
PyErr_SetString(g_InterfaceErrorException,
|
||||
"Unable to acquire Oracle environment handle");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// create the environment object
|
||||
env = Environment_New(handle);
|
||||
if (!env) {
|
||||
OCIHandleFree(handle, OCI_HTYPE_ENV);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// acquire max bytes per character
|
||||
status = OCINlsNumericInfoGet(env->handle, env->errorHandle,
|
||||
&env->maxBytesPerCharacter, OCI_NLS_CHARSET_MAXBYTESZ);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Environment_New(): get max bytes per character") < 0) {
|
||||
Py_DECREF(env);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// determine encodings to use for Unicode values
|
||||
if (Environment_GetCharacterSetName(env, OCI_ATTR_ENV_CHARSET_ID,
|
||||
encoding, &env->encoding, &env->charsetId) < 0)
|
||||
return NULL;
|
||||
if (Environment_GetCharacterSetName(env, OCI_ATTR_ENV_NCHARSET_ID,
|
||||
nencoding, &env->nencoding, &env->ncharsetId) < 0)
|
||||
return NULL;
|
||||
|
||||
// max bytes per character for NCHAR can be assigned only if it matches the
|
||||
// character set used for CHAR data; OCI does not provide a way of
|
||||
// determining it otherwise
|
||||
if (env->ncharsetId == env->charsetId)
|
||||
env->nmaxBytesPerCharacter = env->maxBytesPerCharacter;
|
||||
|
||||
// fill buffers for number formats
|
||||
if (Environment_SetBuffer(&env->numberToStringFormatBuffer, "TM9",
|
||||
env->encoding) < 0)
|
||||
return NULL;
|
||||
if (Environment_SetBuffer(&env->numberFromStringFormatBuffer,
|
||||
"999999999999999999999999999999999999999999999999999999999999999",
|
||||
env->encoding) < 0)
|
||||
return NULL;
|
||||
if (Environment_SetBuffer(&env->nlsNumericCharactersBuffer,
|
||||
"NLS_NUMERIC_CHARACTERS='.,'", env->encoding) < 0)
|
||||
return NULL;
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_Clone()
|
||||
// Clone an existing environment which is used when acquiring a connection
|
||||
// from a session pool, for example.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_Environment *Environment_Clone(
|
||||
udt_Environment *cloneEnv) // environment to clone
|
||||
{
|
||||
udt_Environment *env;
|
||||
|
||||
env = Environment_New(cloneEnv->handle);
|
||||
if (!env)
|
||||
return NULL;
|
||||
env->maxBytesPerCharacter = cloneEnv->maxBytesPerCharacter;
|
||||
Py_INCREF(cloneEnv);
|
||||
env->cloneEnv = (PyObject*) cloneEnv;
|
||||
env->encoding = cloneEnv->encoding;
|
||||
env->nencoding = cloneEnv->nencoding;
|
||||
env->charsetId = cloneEnv->charsetId;
|
||||
env->ncharsetId = cloneEnv->ncharsetId;
|
||||
cxBuffer_Copy(&env->numberToStringFormatBuffer,
|
||||
&cloneEnv->numberToStringFormatBuffer);
|
||||
cxBuffer_Copy(&env->numberFromStringFormatBuffer,
|
||||
&cloneEnv->numberFromStringFormatBuffer);
|
||||
cxBuffer_Copy(&env->nlsNumericCharactersBuffer,
|
||||
&cloneEnv->nlsNumericCharactersBuffer);
|
||||
return env;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_Free()
|
||||
// Deallocate the environment. Note that destroying the environment handle
|
||||
// will automatically destroy any child handles that were created.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void Environment_Free(
|
||||
udt_Environment *self) // environment object
|
||||
{
|
||||
if (self->errorHandle)
|
||||
OCIHandleFree(self->errorHandle, OCI_HTYPE_ERROR);
|
||||
if (self->handle && !self->cloneEnv)
|
||||
OCIHandleFree(self->handle, OCI_HTYPE_ENV);
|
||||
if (!self->cloneEnv) {
|
||||
if (self->encoding)
|
||||
PyMem_Free(self->encoding);
|
||||
if (self->nencoding)
|
||||
PyMem_Free(self->nencoding);
|
||||
}
|
||||
cxBuffer_Clear(&self->numberToStringFormatBuffer);
|
||||
cxBuffer_Clear(&self->numberFromStringFormatBuffer);
|
||||
cxBuffer_Clear(&self->nlsNumericCharactersBuffer);
|
||||
Py_CLEAR(self->cloneEnv);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Environment_CheckForError()
|
||||
// Check for an error in the last call and if an error has occurred, raise a
|
||||
// Python exception.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Environment_CheckForError(
|
||||
udt_Environment *environment, // environment to raise error in
|
||||
sword status, // status of last call
|
||||
const char *context) // context
|
||||
{
|
||||
return Error_Check(environment, status, context, environment->errorHandle);
|
||||
}
|
||||
|
||||
287
src/Error.c
287
src/Error.c
@ -17,24 +17,14 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
sb4 code;
|
||||
ub2 offset;
|
||||
long code;
|
||||
unsigned offset;
|
||||
PyObject *message;
|
||||
const char *context;
|
||||
boolean isRecoverable;
|
||||
PyObject *context;
|
||||
char isRecoverable;
|
||||
} udt_Error;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// maximum size of error message string in bytes
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef OCI_ERROR_MAXMSG_SIZE2
|
||||
#define ERROR_BUF_SIZE OCI_ERROR_MAXMSG_SIZE2
|
||||
#else
|
||||
#define ERROR_BUF_SIZE OCI_ERROR_MAXMSG_SIZE
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -57,10 +47,10 @@ static PyMethodDef g_ErrorMethods[] = {
|
||||
// declaration of members
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyMemberDef g_ErrorMembers[] = {
|
||||
{ "code", T_INT, offsetof(udt_Error, code), READONLY },
|
||||
{ "offset", T_INT, offsetof(udt_Error, offset), READONLY },
|
||||
{ "code", T_LONG, offsetof(udt_Error, code), READONLY },
|
||||
{ "offset", T_UINT, offsetof(udt_Error, offset), READONLY },
|
||||
{ "message", T_OBJECT, offsetof(udt_Error, message), READONLY },
|
||||
{ "context", T_STRING, offsetof(udt_Error, context), READONLY },
|
||||
{ "context", T_OBJECT, offsetof(udt_Error, context), READONLY },
|
||||
{ "isrecoverable", T_BOOL, offsetof(udt_Error, isRecoverable), READONLY },
|
||||
{ NULL }
|
||||
};
|
||||
@ -116,12 +106,12 @@ static PyTypeObject g_ErrorType = {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Error_Free()
|
||||
// Deallocate the environment, disconnecting from the database if necessary.
|
||||
// Deallocate the error.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void Error_Free(
|
||||
udt_Error *self) // error object
|
||||
static void Error_Free(udt_Error *self)
|
||||
{
|
||||
Py_CLEAR(self->message);
|
||||
Py_CLEAR(self->context);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
@ -131,32 +121,29 @@ static void Error_Free(
|
||||
// Create a new error object. This is intended to only be used by the
|
||||
// unpickling routine, and not by direct creation!
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Error_New(
|
||||
PyTypeObject *type, // type object
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
static PyObject *Error_New(PyTypeObject *type, PyObject *args,
|
||||
PyObject *keywordArgs)
|
||||
{
|
||||
boolean isRecoverable;
|
||||
PyObject *message;
|
||||
PyObject *message, *context;
|
||||
int isRecoverable, code;
|
||||
udt_Error *self;
|
||||
unsigned offset;
|
||||
char *context;
|
||||
int code;
|
||||
|
||||
isRecoverable = 0;
|
||||
if (!PyArg_ParseTuple(args, "OiIs|i", &message, &code, &offset, &context,
|
||||
if (!PyArg_ParseTuple(args, "OiIO|i", &message, &code, &offset, &context,
|
||||
&isRecoverable))
|
||||
return NULL;
|
||||
self = (udt_Error*) type->tp_alloc(type, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
self->context = context;
|
||||
self->code = code;
|
||||
self->offset = offset;
|
||||
self->isRecoverable = isRecoverable;
|
||||
self->isRecoverable = (char) isRecoverable;
|
||||
Py_INCREF(message);
|
||||
self->message = message;
|
||||
Py_INCREF(context);
|
||||
self->context = context;
|
||||
|
||||
return (PyObject*) self;
|
||||
}
|
||||
@ -166,8 +153,7 @@ static PyObject *Error_New(
|
||||
// Error_Str()
|
||||
// Return a string representation of the error variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Error_Str(
|
||||
udt_Error *self) // variable to return the string for
|
||||
static PyObject *Error_Str(udt_Error *self)
|
||||
{
|
||||
Py_INCREF(self->message);
|
||||
return self->message;
|
||||
@ -176,57 +162,61 @@ static PyObject *Error_Str(
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Error_InternalNew()
|
||||
// Internal method for creating an error object.
|
||||
// Internal method for creating an error object from the DPI error
|
||||
// information.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_Error *Error_InternalNew(
|
||||
udt_Environment *environment, // environment object
|
||||
const char *context, // context in which error occurred
|
||||
ub4 handleType, // handle type
|
||||
dvoid* handle) // handle
|
||||
static udt_Error *Error_InternalNew(dpiErrorInfo *errorInfo)
|
||||
{
|
||||
char errorText[ERROR_BUF_SIZE];
|
||||
PyObject *format, *args, *fnName, *action;
|
||||
udt_Error *self;
|
||||
sword status;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Py_ssize_t len;
|
||||
#endif
|
||||
|
||||
// create error object and initialize it
|
||||
self = (udt_Error*) g_ErrorType.tp_alloc(&g_ErrorType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
self->context = context;
|
||||
self->code = errorInfo->code;
|
||||
self->offset = errorInfo->offset;
|
||||
self->isRecoverable = (char) errorInfo->isRecoverable;
|
||||
|
||||
if (handle) {
|
||||
status = OCIErrorGet(handle, 1, 0, &self->code,
|
||||
(unsigned char*) errorText, sizeof(errorText), handleType);
|
||||
if (status != OCI_SUCCESS) {
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(g_InternalErrorException, "No Oracle error?");
|
||||
return NULL;
|
||||
}
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
self->message = PyBytes_FromString(errorText);
|
||||
#else
|
||||
len = strlen(errorText);
|
||||
self->message = PyUnicode_Decode(errorText, len, environment->encoding,
|
||||
NULL);
|
||||
#endif
|
||||
if (!self->message) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
// determine if error is recoverable (Transaction Guard)
|
||||
// if the attribute cannot be read properly, simply set it to false;
|
||||
// otherwise, that error will mask the one that we really want to see
|
||||
if (handleType == OCI_HTYPE_ERROR) {
|
||||
status = OCIAttrGet(handle, handleType,
|
||||
(dvoid*) &self->isRecoverable, 0,
|
||||
OCI_ATTR_ERROR_IS_RECOVERABLE, handle);
|
||||
if (status != OCI_SUCCESS)
|
||||
self->isRecoverable = 0;
|
||||
}
|
||||
#endif
|
||||
// create message
|
||||
self->message = cxString_FromEncodedString(errorInfo->message,
|
||||
errorInfo->messageLength, errorInfo->encoding);
|
||||
if (!self->message) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// create context composed of function name and action
|
||||
fnName = cxString_FromAscii(errorInfo->fnName);
|
||||
if (!fnName) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
action = cxString_FromAscii(errorInfo->action);
|
||||
if (!action) {
|
||||
Py_DECREF(fnName);
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
args = PyTuple_Pack(2, fnName, action);
|
||||
Py_DECREF(fnName);
|
||||
Py_DECREF(action);
|
||||
if (!args) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
format = cxString_FromAscii("%s: %s");
|
||||
if (!format) {
|
||||
Py_DECREF(self);
|
||||
Py_DECREF(args);
|
||||
return NULL;
|
||||
}
|
||||
self->context = cxString_Format(format, args);
|
||||
Py_DECREF(format);
|
||||
Py_DECREF(args);
|
||||
if (!self->context) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
@ -234,94 +224,84 @@ static udt_Error *Error_InternalNew(
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Error_Raise()
|
||||
// Reads the error that was caused by the last Oracle statement and raise an
|
||||
// exception for Python. Return -1 as a convenience to the caller.
|
||||
// Error_RaiseFromInfo()
|
||||
// Internal method for raising an exception given an error information
|
||||
// structure from DPI. Return -1 as a convenience to the caller.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Error_Raise(
|
||||
udt_Environment *environment, // environment object
|
||||
const char *context, // context in which error occurred
|
||||
OCIError* errorHandle) // handle
|
||||
static int Error_RaiseFromInfo(dpiErrorInfo *errorInfo)
|
||||
{
|
||||
PyObject *exceptionType;
|
||||
udt_Error *error;
|
||||
udt_Error *self;
|
||||
|
||||
error = Error_InternalNew(environment, context, OCI_HTYPE_ERROR,
|
||||
errorHandle);
|
||||
if (error) {
|
||||
switch (error->code) {
|
||||
case 1:
|
||||
case 1400:
|
||||
case 2290:
|
||||
case 2291:
|
||||
case 2292:
|
||||
exceptionType = g_IntegrityErrorException;
|
||||
break;
|
||||
case 22:
|
||||
case 378:
|
||||
case 602:
|
||||
case 603:
|
||||
case 604:
|
||||
case 609:
|
||||
case 1012:
|
||||
case 1013:
|
||||
case 1033:
|
||||
case 1034:
|
||||
case 1041:
|
||||
case 1043:
|
||||
case 1089:
|
||||
case 1090:
|
||||
case 1092:
|
||||
case 3113:
|
||||
case 3114:
|
||||
case 3122:
|
||||
case 3135:
|
||||
case 12153:
|
||||
case 12203:
|
||||
case 12500:
|
||||
case 12571:
|
||||
case 27146:
|
||||
case 28511:
|
||||
exceptionType = g_OperationalErrorException;
|
||||
break;
|
||||
default:
|
||||
exceptionType = g_DatabaseErrorException;
|
||||
break;
|
||||
}
|
||||
PyErr_SetObject(exceptionType, (PyObject*) error);
|
||||
Py_DECREF(error);
|
||||
self = Error_InternalNew(errorInfo);
|
||||
switch (errorInfo->code) {
|
||||
case 1:
|
||||
case 1400:
|
||||
case 2290:
|
||||
case 2291:
|
||||
case 2292:
|
||||
exceptionType = g_IntegrityErrorException;
|
||||
break;
|
||||
case 22:
|
||||
case 378:
|
||||
case 602:
|
||||
case 603:
|
||||
case 604:
|
||||
case 609:
|
||||
case 1012:
|
||||
case 1013:
|
||||
case 1033:
|
||||
case 1034:
|
||||
case 1041:
|
||||
case 1043:
|
||||
case 1089:
|
||||
case 1090:
|
||||
case 1092:
|
||||
case 3113:
|
||||
case 3114:
|
||||
case 3122:
|
||||
case 3135:
|
||||
case 12153:
|
||||
case 12203:
|
||||
case 12500:
|
||||
case 12571:
|
||||
case 27146:
|
||||
case 28511:
|
||||
exceptionType = g_OperationalErrorException;
|
||||
break;
|
||||
default:
|
||||
exceptionType = g_DatabaseErrorException;
|
||||
break;
|
||||
}
|
||||
PyErr_SetObject(exceptionType, (PyObject*) self);
|
||||
Py_DECREF(self);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Error_Check()
|
||||
// Check for an error in the last call and if an error has occurred, raise a
|
||||
// Python exception.
|
||||
// Error_RaiseAndReturnInt()
|
||||
// Internal method for raising an exception from an error generated from DPI.
|
||||
// Return -1 as a convenience to the caller.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Error_Check(
|
||||
udt_Environment *environment, // environment to raise error in
|
||||
sword status, // status of last call
|
||||
const char *context, // context
|
||||
OCIError *errorHandle) // error handle to use
|
||||
static int Error_RaiseAndReturnInt(void)
|
||||
{
|
||||
udt_Error *error;
|
||||
dpiErrorInfo errorInfo;
|
||||
|
||||
if (status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO) {
|
||||
if (status != OCI_INVALID_HANDLE)
|
||||
return Error_Raise(environment, context, errorHandle);
|
||||
error = Error_InternalNew(environment, context, 0, NULL);
|
||||
if (!error)
|
||||
return -1;
|
||||
error->code = 0;
|
||||
error->message = cxString_FromAscii("Invalid handle!");
|
||||
if (!error->message)
|
||||
Py_DECREF(error);
|
||||
else PyErr_SetObject(g_DatabaseErrorException, (PyObject*) error);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
dpiContext_getError(g_DpiContext, &errorInfo);
|
||||
return Error_RaiseFromInfo(&errorInfo);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Error_RaiseAndReturnNull()
|
||||
// Internal method for raising an exception from an error generated from DPI.
|
||||
// Return NULL as a convenience to the caller.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Error_RaiseAndReturnNull(void)
|
||||
{
|
||||
Error_RaiseAndReturnInt();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -329,10 +309,9 @@ static int Error_Check(
|
||||
// Error_Reduce()
|
||||
// Method provided for pickling/unpickling of Error objects.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Error_Reduce(
|
||||
udt_Error *self) // error object
|
||||
static PyObject *Error_Reduce(udt_Error *self)
|
||||
{
|
||||
return Py_BuildValue("(O(OiIs))", Py_TYPE(self), self->message,
|
||||
return Py_BuildValue("(O(OiIO))", Py_TYPE(self), self->message,
|
||||
self->code, self->offset, self->context);
|
||||
}
|
||||
|
||||
|
||||
@ -1,666 +0,0 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar.c
|
||||
// Defines the routines for handling LOB variables external to this module.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// external LOB type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_LobVar *lobVar;
|
||||
unsigned pos;
|
||||
unsigned internalFetchNum;
|
||||
} udt_ExternalLobVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of external LOB variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void ExternalLobVar_Free(udt_ExternalLobVar*);
|
||||
static PyObject *ExternalLobVar_Str(udt_ExternalLobVar*);
|
||||
static PyObject *ExternalLobVar_Size(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_Open(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_Close(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_Read(udt_ExternalLobVar*, PyObject*,
|
||||
PyObject*);
|
||||
static PyObject *ExternalLobVar_Write(udt_ExternalLobVar*, PyObject*,
|
||||
PyObject*);
|
||||
static PyObject *ExternalLobVar_Trim(udt_ExternalLobVar*, PyObject*,
|
||||
PyObject*);
|
||||
static PyObject *ExternalLobVar_GetChunkSize(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_IsOpen(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_GetFileName(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_SetFileName(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_FileExists(udt_ExternalLobVar*, PyObject*);
|
||||
static PyObject *ExternalLobVar_Reduce(udt_ExternalLobVar*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of methods for Python type "ExternalLOBVar"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyMethodDef g_ExternalLobVarMethods[] = {
|
||||
{ "size", (PyCFunction) ExternalLobVar_Size, METH_NOARGS },
|
||||
{ "open", (PyCFunction) ExternalLobVar_Open, METH_NOARGS },
|
||||
{ "close", (PyCFunction) ExternalLobVar_Close, METH_NOARGS },
|
||||
{ "read", (PyCFunction) ExternalLobVar_Read,
|
||||
METH_VARARGS | METH_KEYWORDS },
|
||||
{ "write", (PyCFunction) ExternalLobVar_Write,
|
||||
METH_VARARGS | METH_KEYWORDS },
|
||||
{ "trim", (PyCFunction) ExternalLobVar_Trim,
|
||||
METH_VARARGS | METH_KEYWORDS },
|
||||
{ "getchunksize", (PyCFunction) ExternalLobVar_GetChunkSize, METH_NOARGS },
|
||||
{ "isopen", (PyCFunction) ExternalLobVar_IsOpen, METH_NOARGS },
|
||||
{ "getfilename", (PyCFunction) ExternalLobVar_GetFileName, METH_NOARGS },
|
||||
{ "setfilename", (PyCFunction) ExternalLobVar_SetFileName, METH_VARARGS },
|
||||
{ "fileexists", (PyCFunction) ExternalLobVar_FileExists, METH_NOARGS },
|
||||
{ "__reduce__", (PyCFunction) ExternalLobVar_Reduce, METH_NOARGS },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declaration
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_ExternalLobVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.LOB", // tp_name
|
||||
sizeof(udt_ExternalLobVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) ExternalLobVar_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
(reprfunc) ExternalLobVar_Str, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
g_ExternalLobVarMethods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_New()
|
||||
// Create a new external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
PyObject *ExternalLobVar_New(
|
||||
udt_LobVar *var, // variable to encapsulate
|
||||
unsigned pos) // position in array to encapsulate
|
||||
{
|
||||
udt_ExternalLobVar *self;
|
||||
|
||||
self = (udt_ExternalLobVar*)
|
||||
g_ExternalLobVarType.tp_alloc(&g_ExternalLobVarType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
self->pos = pos;
|
||||
self->internalFetchNum = var->internalFetchNum;
|
||||
Py_INCREF(var);
|
||||
self->lobVar = var;
|
||||
|
||||
return (PyObject*) self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Free()
|
||||
// Free an external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void ExternalLobVar_Free(
|
||||
udt_ExternalLobVar *self) // variable to free
|
||||
{
|
||||
Py_CLEAR(self->lobVar);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Verify()
|
||||
// Verify that the external LOB var is still valid.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ExternalLobVar_Verify(
|
||||
udt_ExternalLobVar *var) // variable to verify
|
||||
{
|
||||
if (var->internalFetchNum != var->lobVar->internalFetchNum) {
|
||||
PyErr_SetString(g_ProgrammingErrorException,
|
||||
"LOB variable no longer valid after subsequent fetch");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_InternalRead()
|
||||
// Return the size of the LOB variable for internal comsumption.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ExternalLobVar_InternalRead(
|
||||
udt_ExternalLobVar *var, // variable to return the size of
|
||||
char *buffer, // buffer in which to put data
|
||||
oraub8 bufferSize, // size of buffer
|
||||
oraub8 *length, // length of data (IN/OUT)
|
||||
oraub8 offset) // offset
|
||||
{
|
||||
oraub8 lengthInBytes = 0, lengthInChars = 0;
|
||||
ub2 charsetId;
|
||||
sword status;
|
||||
|
||||
if (var->lobVar->type == &vt_NCLOB || var->lobVar->type == &vt_CLOB)
|
||||
lengthInChars = *length;
|
||||
else lengthInBytes = *length;
|
||||
|
||||
if (var->lobVar->isFile) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobFileOpen(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle,
|
||||
var->lobVar->data[var->pos], OCI_FILE_READONLY);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_FileOpen()") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
charsetId = (var->lobVar->type->charsetForm == SQLCS_NCHAR) ?
|
||||
var->lobVar->environment->ncharsetId :
|
||||
var->lobVar->environment->charsetId;
|
||||
status = OCILobRead2(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
|
||||
&lengthInBytes, &lengthInChars, offset, buffer, bufferSize,
|
||||
OCI_ONE_PIECE, NULL, NULL, charsetId,
|
||||
var->lobVar->type->charsetForm);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_LobRead()") < 0) {
|
||||
if (var->lobVar->isFile) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
OCILobFileClose(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle,
|
||||
var->lobVar->data[var->pos]);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
*length = lengthInBytes;
|
||||
|
||||
if (var->lobVar->isFile) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobFileClose(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle,
|
||||
var->lobVar->data[var->pos]);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_FileClose()") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_InternalSize()
|
||||
// Return the size of the LOB variable for internal comsumption.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ExternalLobVar_InternalSize(
|
||||
udt_ExternalLobVar *var, // variable to return the size of
|
||||
oraub8 *length) // length to return
|
||||
{
|
||||
sword status;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobGetLength2(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle,
|
||||
var->lobVar->data[var->pos], length);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_InternalSize()") < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Value()
|
||||
// Return a portion (or all) of the data in the external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Value(
|
||||
udt_ExternalLobVar *var, // variable to return the size of
|
||||
oraub8 offset, // offset into LOB
|
||||
oraub8 amount) // amount to read from LOB
|
||||
{
|
||||
oraub8 length, bufferSize;
|
||||
PyObject *result;
|
||||
char *buffer;
|
||||
|
||||
// modify the arguments
|
||||
if (amount == (oraub8)(-1)) {
|
||||
if (ExternalLobVar_InternalSize(var, &amount) < 0)
|
||||
return NULL;
|
||||
if (amount >= offset)
|
||||
amount = amount - offset + 1;
|
||||
else amount = 1;
|
||||
}
|
||||
length = amount;
|
||||
|
||||
if (var->lobVar->type == &vt_CLOB)
|
||||
bufferSize = amount * var->lobVar->environment->maxBytesPerCharacter;
|
||||
else if (var->lobVar->type == &vt_NCLOB)
|
||||
bufferSize = amount * var->lobVar->environment->nmaxBytesPerCharacter;
|
||||
else bufferSize = amount;
|
||||
|
||||
// create a string for retrieving the value
|
||||
buffer = (char*) PyMem_Malloc(bufferSize);
|
||||
if (!buffer)
|
||||
return PyErr_NoMemory();
|
||||
if (ExternalLobVar_InternalRead(var, buffer, bufferSize, &length,
|
||||
offset) < 0) {
|
||||
PyMem_Free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// return the result
|
||||
if (var->lobVar->type == &vt_CLOB) {
|
||||
result = cxString_FromEncodedString(buffer, length,
|
||||
var->lobVar->environment->encoding);
|
||||
} else if (var->lobVar->type == &vt_NCLOB) {
|
||||
result = PyUnicode_Decode(buffer, length,
|
||||
var->lobVar->environment->encoding, NULL);
|
||||
} else {
|
||||
result = PyBytes_FromStringAndSize(buffer, length);
|
||||
}
|
||||
PyMem_Free(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Size()
|
||||
// Return the size of the data in the LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Size(
|
||||
udt_ExternalLobVar *var, // variable to return the size of
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
oraub8 length;
|
||||
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
if (ExternalLobVar_InternalSize(var, &length) < 0)
|
||||
return NULL;
|
||||
return PyLong_FromUnsignedLong( (unsigned long) length);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Open()
|
||||
// Open the LOB to speed further accesses.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Open(
|
||||
udt_ExternalLobVar *var, // variable to return the size of
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
sword status;
|
||||
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobOpen(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle,
|
||||
var->lobVar->data[var->pos], OCI_LOB_READWRITE);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_Open()") < 0)
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Close()
|
||||
// Close the LOB.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Close(
|
||||
udt_ExternalLobVar *var, // variable to return the size of
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
sword status;
|
||||
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobClose(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle,
|
||||
var->lobVar->data[var->pos]);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_Close()") < 0)
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Read()
|
||||
// Return a portion (or all) of the data in the external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Read(
|
||||
udt_ExternalLobVar *var, // variable to return the size of
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
{
|
||||
static char *keywordList[] = { "offset", "amount", NULL };
|
||||
oraub8 offset, amount;
|
||||
|
||||
// offset and amount are expected, both optional
|
||||
offset = 1;
|
||||
amount = (oraub8)(-1);
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|KK", keywordList,
|
||||
&offset, &amount))
|
||||
return NULL;
|
||||
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
return ExternalLobVar_Value(var, offset, amount);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Str()
|
||||
// Return all of the data in the external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Str(
|
||||
udt_ExternalLobVar *var) // variable to return the string for
|
||||
{
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
return ExternalLobVar_Value(var, 1, (oraub8)(-1));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Write()
|
||||
// Write a value to the LOB at the specified offset.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Write(
|
||||
udt_ExternalLobVar *var, // variable to perform write against
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
{
|
||||
static char *keywordList[] = { "data", "offset", NULL };
|
||||
PyObject *dataObj;
|
||||
oraub8 offset;
|
||||
|
||||
// buffer is expected, offset is optional
|
||||
offset = 1;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|K", keywordList,
|
||||
&dataObj, &offset))
|
||||
return NULL;
|
||||
|
||||
// perform the write, if possible
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
if (LobVar_Write(var->lobVar, var->pos, dataObj, offset) < 0)
|
||||
return NULL;
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Trim()
|
||||
// Trim the LOB variable to the specified length.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Trim(
|
||||
udt_ExternalLobVar *var, // variable to perform write against
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
{
|
||||
static char *keywordList[] = { "newSize", NULL };
|
||||
oraub8 newSize;
|
||||
sword status;
|
||||
|
||||
// buffer and offset are expected, offset is optional
|
||||
newSize = 0;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|K", keywordList,
|
||||
&newSize))
|
||||
return NULL;
|
||||
|
||||
// create a string for retrieving the value
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobTrim2(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
|
||||
newSize);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_Trim()") < 0)
|
||||
return NULL;
|
||||
|
||||
// return the result
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_Reduce()
|
||||
// Method provided for pickling/unpickling of LOB variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_Reduce(
|
||||
udt_ExternalLobVar *self) // variable to dump
|
||||
{
|
||||
PyObject *result, *value;
|
||||
|
||||
value = ExternalLobVar_Str(self);
|
||||
if (!value)
|
||||
return NULL;
|
||||
result = Py_BuildValue("(O(O))", Py_TYPE(value), value);
|
||||
Py_DECREF(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_GetChunkSize()
|
||||
// Return the chunk size that should be used when reading/writing the LOB in
|
||||
// chunks.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_GetChunkSize(
|
||||
udt_ExternalLobVar *var, // variable to get chunk size for
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
ub4 chunkSize;
|
||||
sword status;
|
||||
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
status = OCILobGetChunkSize(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
|
||||
&chunkSize);
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_GetChunkSize()") < 0)
|
||||
return NULL;
|
||||
return PyInt_FromLong(chunkSize);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_IsOpen()
|
||||
// Return a boolean indicating if the lob is open or not.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_IsOpen(
|
||||
udt_ExternalLobVar *var, // variable to get chunk size for
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
boolean isOpen;
|
||||
sword status;
|
||||
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobIsOpen(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
|
||||
&isOpen);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_IsOpen()") < 0)
|
||||
return NULL;
|
||||
return PyBool_FromLong(isOpen);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_GetFileName()
|
||||
// Return the directory alias and file name for the BFILE lob.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_GetFileName(
|
||||
udt_ExternalLobVar *var, // variable to get file name for
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
char dirAlias[120], name[1020];
|
||||
ub2 dirAliasLength, nameLength;
|
||||
PyObject *result, *temp;
|
||||
sword status;
|
||||
|
||||
// determine the directory alias and name
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
nameLength = sizeof(name);
|
||||
dirAliasLength = sizeof(dirAlias);
|
||||
status = OCILobFileGetName(var->lobVar->environment->handle,
|
||||
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
|
||||
(text*) dirAlias, &dirAliasLength, (text*) name, &nameLength);
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_GetFileName()") < 0)
|
||||
return NULL;
|
||||
|
||||
// create the two-tuple for returning
|
||||
result = PyTuple_New(2);
|
||||
if (!result)
|
||||
return NULL;
|
||||
temp = cxString_FromEncodedString(dirAlias, dirAliasLength,
|
||||
var->lobVar->environment->encoding);
|
||||
if (!temp) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(result, 0, temp);
|
||||
temp = cxString_FromEncodedString(name, nameLength,
|
||||
var->lobVar->environment->encoding);
|
||||
if (!temp) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(result, 1, temp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_SetFileName()
|
||||
// Set the directory alias and file name for the BFILE lob.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_SetFileName(
|
||||
udt_ExternalLobVar *var, // variable to set file name for
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
int dirAliasLength, nameLength;
|
||||
char *dirAlias, *name;
|
||||
sword status;
|
||||
|
||||
// get the directory alias and name as strings
|
||||
if (!PyArg_ParseTuple(args, "s#s#", &dirAlias, &dirAliasLength, &name,
|
||||
&nameLength))
|
||||
return NULL;
|
||||
|
||||
// create a string for retrieving the value
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
status = OCILobFileSetName(var->lobVar->environment->handle,
|
||||
var->lobVar->environment->errorHandle,
|
||||
&var->lobVar->data[var->pos], (text*) dirAlias,
|
||||
(ub2) dirAliasLength, (text*) name, (ub2) nameLength);
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_SetFileName()") < 0)
|
||||
return NULL;
|
||||
|
||||
// return the result
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ExternalLobVar_FileExists()
|
||||
// Return a boolean indicating if the BFIILE lob exists.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ExternalLobVar_FileExists(
|
||||
udt_ExternalLobVar *var, // variable to perform write against
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
PyObject *result;
|
||||
sword status;
|
||||
boolean flag;
|
||||
|
||||
if (ExternalLobVar_Verify(var) < 0)
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobFileExists(var->lobVar->connection->handle,
|
||||
var->lobVar->environment->errorHandle, var->lobVar->data[var->pos],
|
||||
&flag);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->lobVar->environment, status,
|
||||
"ExternalLobVar_FileExists()") < 0)
|
||||
return NULL;
|
||||
|
||||
// return the result
|
||||
if (flag)
|
||||
result = Py_True;
|
||||
else result = Py_False;
|
||||
Py_INCREF(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -12,147 +12,54 @@
|
||||
// Defines the routines for handling interval variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Interval type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
OCIInterval **data;
|
||||
} udt_IntervalVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of interval variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int IntervalVar_Initialize(udt_IntervalVar*, udt_Cursor*);
|
||||
static void IntervalVar_Finalize(udt_IntervalVar*);
|
||||
static int IntervalVar_SetValue(udt_IntervalVar*, unsigned, PyObject*);
|
||||
static PyObject *IntervalVar_GetValue(udt_IntervalVar*, unsigned);
|
||||
static int IntervalVar_SetValue(udt_Variable*, uint32_t, dpiData*, PyObject*);
|
||||
static PyObject *IntervalVar_GetValue(udt_Variable*, dpiData*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_IntervalVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.INTERVAL", // tp_name
|
||||
sizeof(udt_IntervalVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_IntervalVarType, INTERVAL)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_Interval = {
|
||||
(InitializeProc) IntervalVar_Initialize,
|
||||
(FinalizeProc) IntervalVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) IntervalVar_SetValue,
|
||||
(GetValueProc) IntervalVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_IntervalVarType, // Python type
|
||||
SQLT_INTERVAL_DS, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCIInterval*), // element length (default)
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_INTERVAL_DS, // Oracle type
|
||||
DPI_NATIVE_TYPE_INTERVAL_DS, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IntervalVar_Initialize()
|
||||
// Initialize the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int IntervalVar_Initialize(
|
||||
udt_IntervalVar *var, // variable to initialize
|
||||
udt_Cursor *cursor) // cursor created by
|
||||
{
|
||||
sword status;
|
||||
ub4 i;
|
||||
|
||||
// initialize the interval locators
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
status = OCIDescriptorAlloc(var->environment->handle,
|
||||
(dvoid**) &var->data[i], OCI_DTYPE_INTERVAL_DS, 0, 0);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"IntervalVar_Initialize()") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IntervalVar_Finalize()
|
||||
// Prepare for variable destruction.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void IntervalVar_Finalize(
|
||||
udt_IntervalVar *var) // variable to free
|
||||
{
|
||||
ub4 i;
|
||||
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
if (var->data[i])
|
||||
OCIDescriptorFree(var->data[i], OCI_DTYPE_INTERVAL_DS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// IntervalVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int IntervalVar_SetValue(
|
||||
udt_IntervalVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
static int IntervalVar_SetValue(udt_Variable *var, uint32_t pos, dpiData *data,
|
||||
PyObject *value)
|
||||
{
|
||||
sb4 hours, minutes, seconds;
|
||||
dpiIntervalDS *interval;
|
||||
PyDateTime_Delta *delta;
|
||||
sword status;
|
||||
|
||||
if (!PyDelta_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting timedelta data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
delta = (PyDateTime_Delta*) value;
|
||||
hours = (sb4) delta->seconds / 3600;
|
||||
seconds = delta->seconds - hours * 3600;
|
||||
minutes = (sb4) seconds / 60;
|
||||
seconds -= minutes * 60;
|
||||
status = OCIIntervalSetDaySecond(var->environment->handle,
|
||||
var->environment->errorHandle, delta->days, hours, minutes,
|
||||
seconds, delta->microseconds*1000, var->data[pos]);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"IntervalVar_SetValue()") < 0)
|
||||
return -1;
|
||||
|
||||
interval = &data->value.asIntervalDS;
|
||||
interval->days = delta->days;
|
||||
interval->hours = (int32_t) delta->seconds / 3600;
|
||||
interval->seconds = delta->seconds - interval->hours * 3600;
|
||||
interval->minutes = (int32_t) interval->seconds / 60;
|
||||
interval->seconds -= interval->minutes * 60;
|
||||
interval->fseconds = delta->microseconds * 1000;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -161,10 +68,14 @@ static int IntervalVar_SetValue(
|
||||
// IntervalVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *IntervalVar_GetValue(
|
||||
udt_IntervalVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *IntervalVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
return OracleIntervalToPythonDelta(var->environment, var->data[pos]);
|
||||
dpiIntervalDS *interval;
|
||||
int32_t seconds;
|
||||
|
||||
interval = &data->value.asIntervalDS;
|
||||
seconds = interval->hours * 60 * 60 + interval->minutes * 60 +
|
||||
interval->seconds;
|
||||
return PyDelta_FromDSU(interval->days, seconds, interval->fseconds / 1000);
|
||||
}
|
||||
|
||||
|
||||
492
src/LOB.c
Normal file
492
src/LOB.c
Normal file
@ -0,0 +1,492 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB.c
|
||||
// Defines the routines for handling LOB values.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_Variable *var;
|
||||
dpiLob *handle;
|
||||
} udt_LOB;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of external LOB variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void LOB_Free(udt_LOB*);
|
||||
static PyObject *LOB_Str(udt_LOB*);
|
||||
static PyObject *LOB_Size(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_Open(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_Close(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_Read(udt_LOB*, PyObject*, PyObject*);
|
||||
static PyObject *LOB_Write(udt_LOB*, PyObject*, PyObject*);
|
||||
static PyObject *LOB_Trim(udt_LOB*, PyObject*, PyObject*);
|
||||
static PyObject *LOB_GetChunkSize(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_IsOpen(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_GetFileName(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_SetFileName(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_FileExists(udt_LOB*, PyObject*);
|
||||
static PyObject *LOB_Reduce(udt_LOB*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of methods for Python type "ExternalLOBVar"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyMethodDef g_LOBMethods[] = {
|
||||
{ "size", (PyCFunction) LOB_Size, METH_NOARGS },
|
||||
{ "open", (PyCFunction) LOB_Open, METH_NOARGS },
|
||||
{ "close", (PyCFunction) LOB_Close, METH_NOARGS },
|
||||
{ "read", (PyCFunction) LOB_Read, METH_VARARGS | METH_KEYWORDS },
|
||||
{ "write", (PyCFunction) LOB_Write, METH_VARARGS | METH_KEYWORDS },
|
||||
{ "trim", (PyCFunction) LOB_Trim, METH_VARARGS | METH_KEYWORDS },
|
||||
{ "getchunksize", (PyCFunction) LOB_GetChunkSize, METH_NOARGS },
|
||||
{ "isopen", (PyCFunction) LOB_IsOpen, METH_NOARGS },
|
||||
{ "getfilename", (PyCFunction) LOB_GetFileName, METH_NOARGS },
|
||||
{ "setfilename", (PyCFunction) LOB_SetFileName, METH_VARARGS },
|
||||
{ "fileexists", (PyCFunction) LOB_FileExists, METH_NOARGS },
|
||||
{ "__reduce__", (PyCFunction) LOB_Reduce, METH_NOARGS },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declaration
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_LOBType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.LOB", // tp_name
|
||||
sizeof(udt_LOB), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) LOB_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
(reprfunc) LOB_Str, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
g_LOBMethods, // tp_methods
|
||||
0, // tp_members
|
||||
0, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_New()
|
||||
// Create a new external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
PyObject *LOB_New(udt_Variable *var, dpiLob *handle)
|
||||
{
|
||||
udt_LOB *self;
|
||||
|
||||
self = (udt_LOB*) g_LOBType.tp_alloc(&g_LOBType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
if (dpiLob_addRef(handle) < 0) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
self->handle = handle;
|
||||
Py_INCREF(var);
|
||||
self->var = var;
|
||||
return (PyObject*) self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Free()
|
||||
// Free an external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void LOB_Free(udt_LOB *self)
|
||||
{
|
||||
if (self->handle) {
|
||||
dpiLob_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_CLEAR(self->var);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_InternalRead()
|
||||
// Return a portion (or all) of the data in the LOB.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_InternalRead(udt_LOB *self, uint64_t offset,
|
||||
uint64_t amount)
|
||||
{
|
||||
uint64_t bufferSize;
|
||||
PyObject *result;
|
||||
char *buffer;
|
||||
int status;
|
||||
|
||||
// modify the arguments
|
||||
if (amount == (uint64_t)(-1)) {
|
||||
if (dpiLob_getSize(self->handle, &amount) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (amount >= offset)
|
||||
amount = amount - offset + 1;
|
||||
else amount = 1;
|
||||
}
|
||||
|
||||
// create a buffer of the correct size
|
||||
if (dpiLob_getBufferSize(self->handle, amount, &bufferSize) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
buffer = (char*) PyMem_Malloc(bufferSize);
|
||||
if (!buffer)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
// read the LOB
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_readBytes(self->handle, offset, amount, buffer,
|
||||
&bufferSize);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (status < 0) {
|
||||
PyMem_Free(buffer);
|
||||
return Error_RaiseAndReturnNull();
|
||||
}
|
||||
|
||||
// return the result
|
||||
if (self->var->type == &vt_CLOB)
|
||||
result = PyUnicode_Decode(buffer, bufferSize,
|
||||
self->var->connection->encodingInfo.encoding, NULL);
|
||||
else if (self->var->type == &vt_NCLOB)
|
||||
result = cxString_FromEncodedString(buffer, bufferSize,
|
||||
self->var->connection->encodingInfo.nencoding);
|
||||
else result = PyBytes_FromStringAndSize(buffer, bufferSize);
|
||||
PyMem_Free(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_InternalWrite()
|
||||
// Write the data in the Python object to the LOB.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LOB_InternalWrite(udt_LOB *self, PyObject *dataObj, uint64_t offset)
|
||||
{
|
||||
const char *encoding;
|
||||
udt_Buffer buffer;
|
||||
int status;
|
||||
|
||||
if (self->var->type == &vt_NCLOB)
|
||||
encoding = self->var->connection->encodingInfo.nencoding;
|
||||
else encoding = self->var->connection->encodingInfo.encoding;
|
||||
if (cxBuffer_FromObject(&buffer, dataObj, encoding) < 0)
|
||||
return -1;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_writeBytes(self->handle, offset,
|
||||
(char*) buffer.ptr, buffer.size);
|
||||
Py_END_ALLOW_THREADS
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Size()
|
||||
// Return the size of the data in the LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Size(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
uint64_t length;
|
||||
|
||||
if (dpiLob_getSize(self->handle, &length) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyLong_FromUnsignedLongLong(length);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Open()
|
||||
// Open the LOB to speed further accesses.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Open(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
int status;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_openResource(self->handle);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Close()
|
||||
// Close the LOB.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Close(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
int status;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_closeResource(self->handle);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Read()
|
||||
// Return a portion (or all) of the data in the external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Read(udt_LOB *self, PyObject *args, PyObject *keywordArgs)
|
||||
{
|
||||
static char *keywordList[] = { "offset", "amount", NULL };
|
||||
unsigned PY_LONG_LONG offset, amount;
|
||||
|
||||
// offset and amount are expected, both optional
|
||||
offset = 1;
|
||||
amount = (unsigned PY_LONG_LONG)(-1);
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|KK", keywordList,
|
||||
&offset, &amount))
|
||||
return NULL;
|
||||
return LOB_InternalRead(self, (uint64_t) offset, (uint64_t) amount);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Str()
|
||||
// Return all of the data in the external LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Str(udt_LOB *self)
|
||||
{
|
||||
return LOB_InternalRead(self, 1, (uint64_t)(-1));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Write()
|
||||
// Write a value to the LOB variable; return the number of bytes written.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Write(udt_LOB *self, PyObject *args,
|
||||
PyObject *keywordArgs)
|
||||
{
|
||||
static char *keywordList[] = { "data", "offset", NULL };
|
||||
unsigned PY_LONG_LONG offset;
|
||||
PyObject *dataObj;
|
||||
|
||||
offset = 1;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O|K", keywordList,
|
||||
&dataObj, &offset))
|
||||
return NULL;
|
||||
if (LOB_InternalWrite(self, dataObj, (uint64_t) offset) < 0)
|
||||
return NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Trim()
|
||||
// Trim the LOB variable to the specified length.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Trim(udt_LOB *self, PyObject *args, PyObject *keywordArgs)
|
||||
{
|
||||
static char *keywordList[] = { "newSize", NULL };
|
||||
unsigned PY_LONG_LONG newSize;
|
||||
int status;
|
||||
|
||||
newSize = 0;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|K", keywordList,
|
||||
&newSize))
|
||||
return NULL;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_trim(self->handle, (uint64_t) newSize);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_Reduce()
|
||||
// Method provided for pickling/unpickling of LOB variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_Reduce(udt_LOB *self)
|
||||
{
|
||||
PyObject *result, *value;
|
||||
|
||||
value = LOB_Str(self);
|
||||
if (!value)
|
||||
return NULL;
|
||||
result = Py_BuildValue("(O(O))", Py_TYPE(value), value);
|
||||
Py_DECREF(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_GetChunkSize()
|
||||
// Return the chunk size that should be used when reading/writing the LOB in
|
||||
// chunks.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_GetChunkSize(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
uint32_t size;
|
||||
|
||||
if (dpiLob_getChunkSize(self->handle, &size) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(size);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_IsOpen()
|
||||
// Return a boolean indicating if the lob is open or not.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_IsOpen(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
int isOpen, status;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_getIsResourceOpen(self->handle, &isOpen);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyBool_FromLong(isOpen);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_GetFileName()
|
||||
// Return the directory alias and file name for the BFILE lob.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_GetFileName(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
uint32_t directoryAliasLength, fileNameLength;
|
||||
const char *directoryAlias, *fileName;
|
||||
PyObject *result, *temp;
|
||||
int status;
|
||||
|
||||
// get the information from the LOB
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_getDirectoryAndFileName(self->handle, &directoryAlias,
|
||||
&directoryAliasLength, &fileName, &fileNameLength);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
|
||||
// create the two-tuple for returning
|
||||
result = PyTuple_New(2);
|
||||
if (!result)
|
||||
return NULL;
|
||||
temp = cxString_FromEncodedString(directoryAlias, directoryAliasLength,
|
||||
self->var->connection->encodingInfo.encoding);
|
||||
if (!temp) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(result, 0, temp);
|
||||
temp = cxString_FromEncodedString(fileName, fileNameLength,
|
||||
self->var->connection->encodingInfo.encoding);
|
||||
if (!temp) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
PyTuple_SET_ITEM(result, 1, temp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_SetFileName()
|
||||
// Set the directory alias and file name for the BFILE lob.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_SetFileName(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
udt_Buffer directoryAliasBuffer, fileNameBuffer;
|
||||
PyObject *directoryAliasObj, *fileNameObj;
|
||||
int status;
|
||||
|
||||
// get the directory alias and file name
|
||||
if (!PyArg_ParseTuple(args, "OO", &directoryAliasObj, &fileNameObj))
|
||||
return NULL;
|
||||
if (cxBuffer_FromObject(&directoryAliasBuffer, directoryAliasObj,
|
||||
self->var->connection->encodingInfo.encoding) < 0)
|
||||
return NULL;
|
||||
if (cxBuffer_FromObject(&fileNameBuffer, fileNameObj,
|
||||
self->var->connection->encodingInfo.encoding) < 0) {
|
||||
cxBuffer_Clear(&directoryAliasBuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// perform the work
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_setDirectoryAndFileName(self->handle,
|
||||
(char*) directoryAliasBuffer.ptr, directoryAliasBuffer.size,
|
||||
(char*) fileNameBuffer.ptr, fileNameBuffer.size);
|
||||
Py_END_ALLOW_THREADS
|
||||
cxBuffer_Clear(&directoryAliasBuffer);
|
||||
cxBuffer_Clear(&fileNameBuffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB_FileExists()
|
||||
// Return a boolean indicating if the BFIILE lob exists.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LOB_FileExists(udt_LOB *self, PyObject *args)
|
||||
{
|
||||
int status, exists;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiLob_getFileExists(self->handle, &exists);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (exists)
|
||||
Py_RETURN_TRUE;
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
391
src/LobVar.c
391
src/LobVar.c
@ -12,364 +12,89 @@
|
||||
// Defines the routines for handling LOB variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LOB type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
OCILobLocator **data;
|
||||
udt_Connection *connection;
|
||||
int isFile;
|
||||
} udt_LobVar;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of LOB variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LobVar_Initialize(udt_LobVar*, udt_Cursor*);
|
||||
static int LobVar_PreFetch(udt_LobVar*);
|
||||
static void LobVar_Finalize(udt_LobVar*);
|
||||
static PyObject *LobVar_GetValue(udt_LobVar*, unsigned);
|
||||
static int LobVar_SetValue(udt_LobVar*, unsigned, PyObject*);
|
||||
static int LobVar_Write(udt_LobVar*, unsigned, PyObject*, oraub8);
|
||||
static int LobVar_SetValue(udt_Variable*, uint32_t, dpiData*, PyObject*);
|
||||
static PyObject *LobVar_GetValue(udt_Variable*, dpiData*);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_CLOBVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.CLOB", // tp_name
|
||||
sizeof(udt_LobVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_NCLOBVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.NCLOB", // tp_name
|
||||
sizeof(udt_LobVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_BLOBVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.BLOB", // tp_name
|
||||
sizeof(udt_LobVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_BFILEVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.BFILE", // tp_name
|
||||
sizeof(udt_LobVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_CLOBVarType, CLOB)
|
||||
DECLARE_VARIABLE_TYPE(g_NCLOBVarType, NCLOB)
|
||||
DECLARE_VARIABLE_TYPE(g_BLOBVarType, BLOB)
|
||||
DECLARE_VARIABLE_TYPE(g_BFILEVarType, BFILE)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_CLOB = {
|
||||
(InitializeProc) LobVar_Initialize,
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
(GetValueProc) LobVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_CLOBVarType, // Python type
|
||||
SQLT_CLOB, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCILobLocator*), // element length
|
||||
1, // is character data
|
||||
0, // is variable length
|
||||
0, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_CLOB, // Oracle type
|
||||
DPI_NATIVE_TYPE_LOB, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_NCLOB = {
|
||||
(InitializeProc) LobVar_Initialize,
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
(GetValueProc) LobVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_NCLOBVarType, // Python type
|
||||
SQLT_CLOB, // Oracle type
|
||||
SQLCS_NCHAR, // charset form
|
||||
sizeof(OCILobLocator*), // element length
|
||||
1, // is character data
|
||||
0, // is variable length
|
||||
0, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_NCLOB, // Oracle type
|
||||
DPI_NATIVE_TYPE_LOB, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_BLOB = {
|
||||
(InitializeProc) LobVar_Initialize,
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
(GetValueProc) LobVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_BLOBVarType, // Python type
|
||||
SQLT_BLOB, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCILobLocator*), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
0, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_BLOB, // Oracle type
|
||||
DPI_NATIVE_TYPE_LOB, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_BFILE = {
|
||||
(InitializeProc) LobVar_Initialize,
|
||||
(FinalizeProc) LobVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) LobVar_PreFetch,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LobVar_SetValue,
|
||||
(GetValueProc) LobVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_BFILEVarType, // Python type
|
||||
SQLT_BFILE, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCILobLocator*), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
0, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_BFILE, // Oracle type
|
||||
DPI_NATIVE_TYPE_LOB, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
#include "ExternalLobVar.c"
|
||||
#include "LOB.c"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LobVar_Initialize()
|
||||
// Initialize the variable.
|
||||
// LobVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LobVar_Initialize(
|
||||
udt_LobVar *var, // variable to initialize
|
||||
udt_Cursor *cursor) // cursor created by
|
||||
static int LobVar_SetValue(udt_Variable *var, uint32_t pos, dpiData *data,
|
||||
PyObject *value)
|
||||
{
|
||||
sword status;
|
||||
ub4 i;
|
||||
|
||||
// initialize members
|
||||
Py_INCREF(cursor->connection);
|
||||
var->connection = cursor->connection;
|
||||
var->isFile = (var->type == &vt_BFILE);
|
||||
|
||||
// initialize the LOB locators
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
status = OCIDescriptorAlloc(var->environment->handle,
|
||||
(dvoid**) &var->data[i], OCI_DTYPE_LOB, 0, 0);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"LobVar_Initialize()") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LobVar_PreFetch()
|
||||
// Free temporary LOBs prior to fetch.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LobVar_PreFetch(
|
||||
udt_LobVar *var) // variable to free
|
||||
{
|
||||
boolean isTemporary;
|
||||
sword status;
|
||||
ub4 i;
|
||||
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
if (var->data[i]) {
|
||||
status = OCILobIsTemporary(var->environment->handle,
|
||||
var->environment->errorHandle, var->data[i], &isTemporary);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"LobVar_PreFetch(): is temporary LOB?") < 0)
|
||||
return -1;
|
||||
if (isTemporary) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobFreeTemporary(var->connection->handle,
|
||||
var->environment->errorHandle, var->data[i]);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"LobVar_PreFetch(): free temporary LOB") < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LobVar_Finalize()
|
||||
// Prepare for variable destruction.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void LobVar_Finalize(
|
||||
udt_LobVar *var) // variable to free
|
||||
{
|
||||
boolean isTemporary;
|
||||
ub4 i;
|
||||
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
if (var->data[i]) {
|
||||
OCILobIsTemporary(var->environment->handle,
|
||||
var->environment->errorHandle, var->data[i], &isTemporary);
|
||||
if (isTemporary) {
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
OCILobFreeTemporary(var->connection->handle,
|
||||
var->environment->errorHandle, var->data[i]);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
OCIDescriptorFree(var->data[i], OCI_DTYPE_LOB);
|
||||
}
|
||||
}
|
||||
Py_DECREF(var->connection);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LobVar_Write()
|
||||
// Write data to the LOB variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LobVar_Write(
|
||||
udt_LobVar *var, // variable to perform write against
|
||||
unsigned position, // position to perform write against
|
||||
PyObject *dataObj, // data object to write into LOB
|
||||
oraub8 offset) // offset into variable
|
||||
{
|
||||
oraub8 lengthInBytes, lengthInChars = 0;
|
||||
const char *encoding;
|
||||
udt_Buffer buffer;
|
||||
ub2 charsetId;
|
||||
sword status;
|
||||
int status;
|
||||
|
||||
// verify the data type
|
||||
if (var->type == &vt_BFILE) {
|
||||
PyErr_SetString(PyExc_TypeError, "BFILEs are read only");
|
||||
if (var->type == &vt_NCLOB)
|
||||
encoding = var->connection->encodingInfo.nencoding;
|
||||
else encoding = var->connection->encodingInfo.encoding;
|
||||
if (cxBuffer_FromObject(&buffer, value, encoding) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// determine the buffer to write
|
||||
if (var->type->charsetForm == SQLCS_NCHAR) {
|
||||
charsetId = var->environment->ncharsetId;
|
||||
encoding = var->environment->nencoding;
|
||||
} else {
|
||||
charsetId = var->environment->charsetId;
|
||||
encoding = var->environment->encoding;
|
||||
}
|
||||
if (cxBuffer_FromObject(&buffer, dataObj, encoding) < 0)
|
||||
return -1;
|
||||
lengthInBytes = buffer.size;
|
||||
|
||||
// nothing to do if no data to write
|
||||
if (lengthInBytes == 0) {
|
||||
cxBuffer_Clear(&buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// write the data with the correct character set
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobWrite2(var->connection->handle,
|
||||
var->environment->errorHandle, var->data[position], &lengthInBytes,
|
||||
&lengthInChars, offset, (void*) buffer.ptr, buffer.size,
|
||||
OCI_ONE_PIECE, NULL, NULL, charsetId, var->type->charsetForm);
|
||||
status = dpiLob_setFromBytes(data->value.asLOB, buffer.ptr, buffer.size);
|
||||
Py_END_ALLOW_THREADS
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"LobVar_Write()") < 0)
|
||||
return -1;
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -379,58 +104,8 @@ static int LobVar_Write(
|
||||
// LobVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LobVar_GetValue(
|
||||
udt_LobVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *LobVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
return ExternalLobVar_New(var, pos);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LobVar_SetValue()
|
||||
// Sets the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LobVar_SetValue(
|
||||
udt_LobVar *var, // variable to determine value for
|
||||
unsigned position, // array position
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
boolean isTemporary;
|
||||
sword status;
|
||||
ub1 lobType;
|
||||
|
||||
// make sure have temporary LOBs set up
|
||||
status = OCILobIsTemporary(var->environment->handle,
|
||||
var->environment->errorHandle, var->data[position], &isTemporary);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"LobVar_SetValue(): is temporary?") < 0)
|
||||
return -1;
|
||||
if (!isTemporary) {
|
||||
if (var->type->oracleType == SQLT_BLOB)
|
||||
lobType = OCI_TEMP_BLOB;
|
||||
else lobType = OCI_TEMP_CLOB;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobCreateTemporary(var->connection->handle,
|
||||
var->environment->errorHandle, var->data[position],
|
||||
OCI_DEFAULT, var->type->charsetForm, lobType, FALSE,
|
||||
OCI_DURATION_SESSION);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"LobVar_SetValue(): create temporary") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// trim the current value
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCILobTrim(var->connection->handle,
|
||||
var->environment->errorHandle, var->data[position], 0);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"LobVar_SetValue(): trim") < 0)
|
||||
return -1;
|
||||
|
||||
// set the current value
|
||||
return LobVar_Write(var, position, value, 1);
|
||||
return LOB_New(var, data->value.asLOB);
|
||||
}
|
||||
|
||||
|
||||
215
src/LongVar.c
215
src/LongVar.c
@ -12,235 +12,54 @@
|
||||
// Defines the routines specific to the long type.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// long type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
char *data;
|
||||
} udt_LongVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of long variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LongVar_SetValue(udt_LongVar*, unsigned, PyObject*);
|
||||
static PyObject *LongVar_GetValue(udt_LongVar*, unsigned);
|
||||
static ub4 LongVar_GetBufferSize(udt_LongVar*);
|
||||
static PyObject *LongVar_GetValue(udt_Variable*, dpiData*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_LongStringVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.LONG_STRING", // tp_name
|
||||
sizeof(udt_LongVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_LongNCharVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.LONG_NCHAR", // tp_name
|
||||
sizeof(udt_LongVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_LongBinaryVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.LONG_BINARY", // tp_name
|
||||
sizeof(udt_LongVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_LongStringVarType, LONG_STRING)
|
||||
DECLARE_VARIABLE_TYPE(g_LongBinaryVarType, LONG_BINARY)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_LongString = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LongVar_SetValue,
|
||||
(SetValueProc) Variable_SetValueBytes,
|
||||
(GetValueProc) LongVar_GetValue,
|
||||
(GetBufferSizeProc) LongVar_GetBufferSize,
|
||||
&g_LongStringVarType, // Python type
|
||||
SQLT_LVC, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
128 * 1024, // element length (default)
|
||||
1, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
0 // can be in array
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_LongNationalCharString = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LongVar_SetValue,
|
||||
(GetValueProc) LongVar_GetValue,
|
||||
(GetBufferSizeProc) LongVar_GetBufferSize,
|
||||
&g_LongNCharVarType, // Python type
|
||||
SQLT_LVC, // Oracle type
|
||||
SQLCS_NCHAR, // charset form
|
||||
128 * 1024, // element length (default)
|
||||
1, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_LONG_VARCHAR, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
128 * 1024 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_LongBinary = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) LongVar_SetValue,
|
||||
(SetValueProc) Variable_SetValueBytes,
|
||||
(GetValueProc) LongVar_GetValue,
|
||||
(GetBufferSizeProc) LongVar_GetBufferSize,
|
||||
&g_LongBinaryVarType, // Python type
|
||||
SQLT_LVB, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
128 * 1024, // element length (default)
|
||||
0, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_LONG_RAW, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
128 * 1024 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LongVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int LongVar_SetValue(
|
||||
udt_LongVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
udt_Buffer buffer;
|
||||
char *ptr;
|
||||
|
||||
// get the buffer data and size for binding
|
||||
if (cxBuffer_FromObject(&buffer, value, var->environment->encoding) < 0)
|
||||
return -1;
|
||||
|
||||
// verify there is enough space to store the value
|
||||
if (buffer.numCharacters > var->size) {
|
||||
if (Variable_Resize((udt_Variable*) var,
|
||||
(unsigned) buffer.numCharacters) < 0) {
|
||||
cxBuffer_Clear(&buffer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// copy the string to the Oracle buffer
|
||||
ptr = var->data + var->bufferSize * pos;
|
||||
*((ub4 *) ptr) = (ub4) buffer.size;
|
||||
if (buffer.size)
|
||||
memcpy(ptr + sizeof(ub4), buffer.ptr, buffer.size);
|
||||
cxBuffer_Clear(&buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LongVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *LongVar_GetValue(
|
||||
udt_LongVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *LongVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
char *ptr;
|
||||
ub4 size;
|
||||
dpiBytes *bytes;
|
||||
|
||||
ptr = var->data + var->bufferSize * pos;
|
||||
size = *((ub4 *) ptr);
|
||||
ptr += sizeof(ub4);
|
||||
bytes = &data->value.asBytes;
|
||||
if (var->type == &vt_LongBinary)
|
||||
return PyBytes_FromStringAndSize(ptr, size);
|
||||
return cxString_FromEncodedString(ptr, size, var->environment->encoding);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LongVar_GetBufferSize()
|
||||
// Returns the size of the buffer to use for data of the given size.
|
||||
//-----------------------------------------------------------------------------
|
||||
static ub4 LongVar_GetBufferSize(
|
||||
udt_LongVar *self) // variable to get buffer size
|
||||
{
|
||||
if (!self->type->isCharacterData)
|
||||
return self->size + sizeof(ub4);
|
||||
return sizeof(ub4) + self->size * self->environment->maxBytesPerCharacter;
|
||||
return PyBytes_FromStringAndSize(bytes->ptr, bytes->length);
|
||||
return cxString_FromEncodedString(bytes->ptr, bytes->length,
|
||||
bytes->encoding);
|
||||
}
|
||||
|
||||
|
||||
412
src/MsgProps.c
Normal file
412
src/MsgProps.c
Normal file
@ -0,0 +1,412 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps.c
|
||||
// Implements the message properties object used in Advanced Queuing.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// structures used for handling AQ options and message properties
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
dpiMsgProps *handle;
|
||||
const char *encoding;
|
||||
} udt_MsgProps;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of methods used for message properties
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_MsgProps *MsgProps_New(udt_Connection*);
|
||||
static void MsgProps_Free(udt_MsgProps*);
|
||||
static PyObject *MsgProps_GetNumAttempts(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetCorrelation(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetDelay(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetDeliveryMode(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetEnqTime(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetExceptionQ(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetExpiration(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetOriginalMsgId(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetPriority(udt_MsgProps*, void*);
|
||||
static PyObject *MsgProps_GetState(udt_MsgProps*, void*);
|
||||
static int MsgProps_SetCorrelation(udt_MsgProps*, PyObject*, void*);
|
||||
static int MsgProps_SetDelay(udt_MsgProps*, PyObject*, void*);
|
||||
static int MsgProps_SetExceptionQ(udt_MsgProps*, PyObject*, void*);
|
||||
static int MsgProps_SetExpiration(udt_MsgProps*, PyObject*, void*);
|
||||
static int MsgProps_SetOriginalMsgId(udt_MsgProps*, PyObject*, void*);
|
||||
static int MsgProps_SetPriority(udt_MsgProps*, PyObject*, void*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members for Python type "MessageProperties"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef g_MessagePropertiesCalcMembers[] = {
|
||||
{ "attempts", (getter) MsgProps_GetNumAttempts, 0, 0, 0 },
|
||||
{ "correlation", (getter) MsgProps_GetCorrelation,
|
||||
(setter) MsgProps_SetCorrelation, 0, 0 },
|
||||
{ "delay", (getter) MsgProps_GetDelay, (setter) MsgProps_SetDelay, 0, 0 },
|
||||
{ "deliverymode", (getter) MsgProps_GetDeliveryMode, 0, 0, 0 },
|
||||
{ "enqtime", (getter) MsgProps_GetEnqTime, 0, 0, 0 },
|
||||
{ "exceptionq", (getter) MsgProps_GetExceptionQ,
|
||||
(setter) MsgProps_SetExceptionQ, 0, 0 },
|
||||
{ "expiration", (getter) MsgProps_GetExpiration,
|
||||
(setter) MsgProps_SetExpiration, 0, 0 },
|
||||
{ "msgid", (getter) MsgProps_GetOriginalMsgId,
|
||||
(setter) MsgProps_SetOriginalMsgId, 0, 0 },
|
||||
{ "priority", (getter) MsgProps_GetPriority,
|
||||
(setter) MsgProps_SetPriority, 0, 0 },
|
||||
{ "state", (getter) MsgProps_GetState, 0, 0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_MessagePropertiesType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.MessageProperties", // tp_name
|
||||
sizeof(udt_MsgProps), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
(destructor) MsgProps_Free, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
0, // tp_members
|
||||
g_MessagePropertiesCalcMembers, // tp_getset
|
||||
0, // tp_base
|
||||
0, // tp_dict
|
||||
0, // tp_descr_get
|
||||
0, // tp_descr_set
|
||||
0, // tp_dictoffset
|
||||
0, // tp_init
|
||||
0, // tp_alloc
|
||||
0, // tp_new
|
||||
0, // tp_free
|
||||
0, // tp_is_gc
|
||||
0 // tp_bases
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_New()
|
||||
// Create a new message properties object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_MsgProps *MsgProps_New(udt_Connection *connection)
|
||||
{
|
||||
udt_MsgProps *self;
|
||||
|
||||
self = (udt_MsgProps*)
|
||||
g_MessagePropertiesType.tp_alloc(&g_MessagePropertiesType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
if (dpiConn_newMsgProps(connection->handle, &self->handle) < 0) {
|
||||
Py_DECREF(self);
|
||||
Error_RaiseAndReturnNull();
|
||||
return NULL;
|
||||
}
|
||||
self->encoding = connection->encodingInfo.encoding;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_Free()
|
||||
// Free the memory associated with the message properties object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void MsgProps_Free(udt_MsgProps *self)
|
||||
{
|
||||
if (self->handle) {
|
||||
dpiMsgProps_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetAttrInt32()
|
||||
// Get the value of the attribute as a 32-bit integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetAttrInt32(udt_MsgProps *self,
|
||||
int (*func)(dpiMsgProps *props, int32_t *value))
|
||||
{
|
||||
int32_t value;
|
||||
|
||||
if ((*func)(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_SetAttrInt32()
|
||||
// Set the value of the attribute as a 32-bit integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MsgProps_SetAttrInt32(udt_MsgProps *self, PyObject *valueObj,
|
||||
int (*func)(dpiMsgProps *props, int32_t value))
|
||||
{
|
||||
int32_t value;
|
||||
|
||||
value = PyInt_AsLong(valueObj);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if ((*func)(self->handle, value) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetNumAttempts()
|
||||
// Get the value of the attempts property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetNumAttempts(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
return MsgProps_GetAttrInt32(self, dpiMsgProps_getNumAttempts);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetCorrelation()
|
||||
// Get the value of the correlation property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetCorrelation(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
uint32_t valueLength;
|
||||
const char *value;
|
||||
|
||||
if (dpiMsgProps_getCorrelation(self->handle, &value, &valueLength) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (!value)
|
||||
Py_RETURN_NONE;
|
||||
return cxString_FromEncodedString(value, valueLength, self->encoding);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetDelay()
|
||||
// Get the value of the delay property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetDelay(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
return MsgProps_GetAttrInt32(self, dpiMsgProps_getDelay);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetDeliveryMode()
|
||||
// Get the value of the delivery mode property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetDeliveryMode(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
dpiMessageDeliveryMode value;
|
||||
|
||||
if (dpiMsgProps_getDeliveryMode(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetEnqTime()
|
||||
// Get the value of the enqueue time property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetEnqTime(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
dpiTimestamp value;
|
||||
|
||||
if (dpiMsgProps_getEnqTime(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyDateTime_FromDateAndTime(value.year, value.month, value.day,
|
||||
value.hour, value.minute, value.second, 0);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetExceptionQ()
|
||||
// Get the value of the exception queue property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetExceptionQ(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
uint32_t valueLength;
|
||||
const char *value;
|
||||
|
||||
if (dpiMsgProps_getExceptionQ(self->handle, &value, &valueLength) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (!value)
|
||||
Py_RETURN_NONE;
|
||||
return cxString_FromEncodedString(value, valueLength, self->encoding);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetExpiration()
|
||||
// Get the value of the expiration property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetExpiration(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
return MsgProps_GetAttrInt32(self, dpiMsgProps_getExpiration);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetOriginalMsgId()
|
||||
// Get the value of the expiration property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetOriginalMsgId(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
uint32_t valueLength;
|
||||
const char *value;
|
||||
|
||||
if (dpiMsgProps_getOriginalMsgId(self->handle, &value, &valueLength) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
if (!value)
|
||||
Py_RETURN_NONE;
|
||||
return PyBytes_FromStringAndSize(value, valueLength);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetPriority()
|
||||
// Get the value of the priority property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetPriority(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
return MsgProps_GetAttrInt32(self, dpiMsgProps_getPriority);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_GetState()
|
||||
// Get the value of the state property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *MsgProps_GetState(udt_MsgProps *self, void *unused)
|
||||
{
|
||||
dpiMessageState value;
|
||||
|
||||
if (dpiMsgProps_getState(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_SetCorrelation()
|
||||
// Set the value of the correlation property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MsgProps_SetCorrelation(udt_MsgProps *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
udt_Buffer buffer;
|
||||
int status;
|
||||
|
||||
if (cxBuffer_FromObject(&buffer, valueObj, self->encoding))
|
||||
return -1;
|
||||
status = dpiMsgProps_setCorrelation(self->handle, buffer.ptr, buffer.size);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_SetDelay()
|
||||
// Set the value of the delay property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MsgProps_SetDelay(udt_MsgProps *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
return MsgProps_SetAttrInt32(self, valueObj, dpiMsgProps_setDelay);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_SetExceptionQ()
|
||||
// Set the value of the exception queue property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MsgProps_SetExceptionQ(udt_MsgProps *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
udt_Buffer buffer;
|
||||
int status;
|
||||
|
||||
if (cxBuffer_FromObject(&buffer, valueObj, self->encoding))
|
||||
return -1;
|
||||
status = dpiMsgProps_setExceptionQ(self->handle, buffer.ptr, buffer.size);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_SetExpiration()
|
||||
// Set the value of the expiration property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MsgProps_SetExpiration(udt_MsgProps *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
return MsgProps_SetAttrInt32(self, valueObj, dpiMsgProps_setExpiration);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_SetOriginalMsgId()
|
||||
// Set the value of the original message id property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MsgProps_SetOriginalMsgId(udt_MsgProps *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
Py_ssize_t valueLength;
|
||||
char *value;
|
||||
|
||||
if (PyBytes_AsStringAndSize(valueObj, &value, &valueLength) < 0)
|
||||
return -1;
|
||||
if (dpiMsgProps_setOriginalMsgId(self->handle, value, valueLength) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MsgProps_SetPriority()
|
||||
// Set the value of the expiration property.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MsgProps_SetPriority(udt_MsgProps *self, PyObject *valueObj,
|
||||
void *unused)
|
||||
{
|
||||
return MsgProps_SetAttrInt32(self, valueObj, dpiMsgProps_setPriority);
|
||||
}
|
||||
|
||||
561
src/NumberVar.c
561
src/NumberVar.c
@ -12,449 +12,242 @@
|
||||
// Defines the routines for handling numeric variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Number types
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
OCINumber *data;
|
||||
} udt_NumberVar;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
double *data;
|
||||
} udt_NativeFloatVar;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
long *data;
|
||||
} udt_NativeIntVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of number variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_PreDefine(udt_NumberVar*, OCIParam*);
|
||||
static int NumberVar_SetValue(udt_NumberVar*, unsigned, PyObject*);
|
||||
static PyObject *NumberVar_GetValue(udt_NumberVar*, unsigned);
|
||||
static int NativeFloatVar_SetValue(udt_NativeFloatVar*, unsigned, PyObject*);
|
||||
static PyObject *NativeFloatVar_GetValue(udt_NativeFloatVar*, unsigned);
|
||||
static int NativeIntVar_SetValue(udt_NativeIntVar*, unsigned, PyObject*);
|
||||
static PyObject *NativeIntVar_GetValue(udt_NativeIntVar*, unsigned);
|
||||
static PyObject *NumberVar_GetValueDecimal(udt_Variable*, dpiData*);
|
||||
static PyObject *NumberVar_GetValueFloat(udt_Variable*, dpiData*);
|
||||
static PyObject *NumberVar_GetValueInteger(udt_Variable*, dpiData*);
|
||||
static PyObject *NumberVar_GetValueLongInteger(udt_Variable*, dpiData*);
|
||||
|
||||
static int NumberVar_SetValueDecimal(udt_Variable*, uint32_t, dpiData*,
|
||||
PyObject*);
|
||||
static int NumberVar_SetValueFloat(udt_Variable*, uint32_t, dpiData*,
|
||||
PyObject*);
|
||||
static int NumberVar_SetValueInteger(udt_Variable*, uint32_t, dpiData*,
|
||||
PyObject*);
|
||||
static int NumberVar_SetValueLongInteger(udt_Variable*, uint32_t, dpiData*,
|
||||
PyObject*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declaration
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_NumberVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.NUMBER", // tp_name
|
||||
sizeof(udt_NumberVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_NativeFloatVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.NATIVE_FLOAT", // tp_name
|
||||
sizeof(udt_NativeFloatVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_NativeIntVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.NATIVE_INT", // tp_name
|
||||
sizeof(udt_NativeIntVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_NumberVarType, NUMBER)
|
||||
DECLARE_VARIABLE_TYPE(g_NativeFloatVarType, NATIVE_FLOAT)
|
||||
DECLARE_VARIABLE_TYPE(g_NativeIntVarType, NATIVE_INT)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_Float = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
(GetValueProc) NumberVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
static udt_VariableType vt_NumberAsDecimal = {
|
||||
(SetValueProc) NumberVar_SetValueDecimal,
|
||||
(GetValueProc) NumberVar_GetValueDecimal,
|
||||
&g_NumberVarType, // Python type
|
||||
SQLT_VNU, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCINumber), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_NUMBER, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
1000 // element length
|
||||
};
|
||||
|
||||
static udt_VariableType vt_NumberAsFloat = {
|
||||
(SetValueProc) NumberVar_SetValueFloat,
|
||||
(GetValueProc) NumberVar_GetValueFloat,
|
||||
&g_NumberVarType, // Python type
|
||||
DPI_ORACLE_TYPE_NUMBER, // Oracle type
|
||||
DPI_NATIVE_TYPE_DOUBLE, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_NumberAsInteger = {
|
||||
(SetValueProc) NumberVar_SetValueInteger,
|
||||
(GetValueProc) NumberVar_GetValueInteger,
|
||||
&g_NumberVarType, // Python type
|
||||
DPI_ORACLE_TYPE_NUMBER, // Oracle type
|
||||
DPI_NATIVE_TYPE_INT64, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_NumberAsLongInteger = {
|
||||
(SetValueProc) NumberVar_SetValueLongInteger,
|
||||
(GetValueProc) NumberVar_GetValueLongInteger,
|
||||
&g_NumberVarType, // Python type
|
||||
DPI_ORACLE_TYPE_NUMBER, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
40 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_NativeFloat = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NativeFloatVar_SetValue,
|
||||
(GetValueProc) NativeFloatVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValueFloat,
|
||||
(GetValueProc) NumberVar_GetValueFloat,
|
||||
&g_NativeFloatVarType, // Python type
|
||||
SQLT_BDOUBLE, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(double), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_NATIVE_DOUBLE, // Oracle type
|
||||
DPI_NATIVE_TYPE_DOUBLE, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
|
||||
static udt_VariableType vt_NativeInteger = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NativeIntVar_SetValue,
|
||||
(GetValueProc) NativeIntVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValueInteger,
|
||||
(GetValueProc) NumberVar_GetValueInteger,
|
||||
&g_NativeIntVarType, // Python type
|
||||
SQLT_INT, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(long), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_NATIVE_INT, // Oracle type
|
||||
DPI_NATIVE_TYPE_INT64, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_Integer = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
(GetValueProc) NumberVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_NumberVarType, // Python type
|
||||
SQLT_VNU, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCINumber), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_LongInteger = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
(GetValueProc) NumberVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_NumberVarType, // Python type
|
||||
SQLT_VNU, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCINumber), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_NumberAsString = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
(GetValueProc) NumberVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_NumberVarType, // Python type
|
||||
SQLT_VNU, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCINumber), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
};
|
||||
|
||||
|
||||
#if ORACLE_VERSION_HEX < ORACLE_VERSION(12, 1)
|
||||
static udt_VariableType vt_Boolean = {
|
||||
(InitializeProc) NULL,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NumberVar_PreDefine,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) NumberVar_SetValue,
|
||||
(GetValueProc) NumberVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_NumberVarType, // Python type
|
||||
SQLT_VNU, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCINumber), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_PreDefine()
|
||||
// Set the type of value (integer, float or string) that will be returned
|
||||
// when values are fetched from this variable.
|
||||
// NumberVar_GetValueDecimal()
|
||||
// Returns the value of the variable as a decimal object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_PreDefine(
|
||||
udt_NumberVar *var, // variable to initialize
|
||||
OCIParam *param) // parameter handle
|
||||
static PyObject *NumberVar_GetValueDecimal(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
static int maxLongSafeDigits = sizeof(long) >= 8 ? 18 : 9;
|
||||
sb2 precision;
|
||||
sword status;
|
||||
sb1 scale;
|
||||
PyObject *stringObj, *result;
|
||||
dpiBytes *bytes;
|
||||
|
||||
// if the return type has not already been specified, check to see if the
|
||||
// number can fit inside an integer by looking at the precision and scale
|
||||
if (var->type == &vt_Float) {
|
||||
scale = 0;
|
||||
precision = 0;
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &scale, 0,
|
||||
OCI_ATTR_SCALE, var->environment->errorHandle);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_PreDefine(): scale") < 0)
|
||||
return -1;
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &precision, 0,
|
||||
OCI_ATTR_PRECISION, var->environment->errorHandle);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_PreDefine(): precision") < 0)
|
||||
return -1;
|
||||
if (scale == 0 || (scale == -127 && precision == 0)) {
|
||||
var->type = &vt_LongInteger;
|
||||
if (precision > 0 && precision <= maxLongSafeDigits)
|
||||
var->type = &vt_Integer;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
bytes = &data->value.asBytes;
|
||||
stringObj = cxString_FromEncodedString(bytes->ptr, bytes->length,
|
||||
bytes->encoding);
|
||||
if (!stringObj)
|
||||
return NULL;
|
||||
result = PyObject_CallFunctionObjArgs( (PyObject*) g_DecimalType,
|
||||
stringObj, NULL);
|
||||
Py_DECREF(stringObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
// NumberVar_GetValueFloat()
|
||||
// Returns the value of the variable as a float.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValue(
|
||||
udt_NumberVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
static PyObject *NumberVar_GetValueFloat(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
return PythonNumberToOracleNumber(var->environment, value,
|
||||
&var->data[pos]);
|
||||
return PyFloat_FromDouble(data->value.asDouble);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
// NumberVar_GetValueInteger()
|
||||
// Returns the value of the variable as an integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *NumberVar_GetValue(
|
||||
udt_NumberVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *NumberVar_GetValueInteger(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
PyObject *result, *stringObj;
|
||||
char stringValue[200];
|
||||
long integerValue;
|
||||
ub4 stringLength;
|
||||
sword status;
|
||||
|
||||
if (var->type == &vt_Boolean || var->type == &vt_Integer) {
|
||||
status = OCINumberToInt(var->environment->errorHandle, &var->data[pos],
|
||||
sizeof(long), OCI_NUMBER_SIGNED, (dvoid*) &integerValue);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_GetValue(): as integer") < 0)
|
||||
return NULL;
|
||||
|
||||
if (var->type == &vt_Boolean)
|
||||
return PyBool_FromLong(integerValue);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyLong_FromLong(integerValue);
|
||||
#else
|
||||
return PyInt_FromLong(integerValue);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (var->type == &vt_NumberAsString || var->type == &vt_LongInteger) {
|
||||
stringLength = sizeof(stringValue);
|
||||
status = OCINumberToText(var->environment->errorHandle,
|
||||
&var->data[pos],
|
||||
(text*) var->environment->numberToStringFormatBuffer.ptr,
|
||||
(ub4) var->environment->numberToStringFormatBuffer.size, NULL,
|
||||
0, &stringLength, (unsigned char*) stringValue);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"NumberVar_GetValue(): as string") < 0)
|
||||
return NULL;
|
||||
stringObj = cxString_FromEncodedString(stringValue, stringLength,
|
||||
var->environment->encoding);
|
||||
if (!stringObj)
|
||||
return NULL;
|
||||
if (var->type == &vt_NumberAsString)
|
||||
return stringObj;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
result = PyNumber_Long(stringObj);
|
||||
#else
|
||||
result = PyNumber_Int(stringObj);
|
||||
#endif
|
||||
Py_DECREF(stringObj);
|
||||
if (result || !PyErr_ExceptionMatches(PyExc_ValueError))
|
||||
return result;
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
return OracleNumberToPythonFloat(var->environment, &var->data[pos]);
|
||||
return PyInt_FromLong(data->value.asInt64);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NativeFloatVar_GetValue()
|
||||
// Returns the value stored at the given array position as a float.
|
||||
// NumberVar_GetValueLongInteger()
|
||||
// Returns the value of the variable as a long integer (one that may not fit
|
||||
// in a native integer).
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *NativeFloatVar_GetValue(
|
||||
udt_NativeFloatVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *NumberVar_GetValueLongInteger(udt_Variable *var,
|
||||
dpiData *data)
|
||||
{
|
||||
return PyFloat_FromDouble(var->data[pos]);
|
||||
PyObject *stringObj, *result;
|
||||
dpiBytes *bytes;
|
||||
|
||||
bytes = &data->value.asBytes;
|
||||
stringObj = cxString_FromEncodedString(bytes->ptr, bytes->length,
|
||||
bytes->encoding);
|
||||
if (!stringObj)
|
||||
return NULL;
|
||||
result = PyNumber_Int(stringObj);
|
||||
Py_DECREF(stringObj);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NativeFloatVar_SetValue()
|
||||
// Set the value of the variable which should be a native double.
|
||||
// NumberVar_SetValueDecimal()
|
||||
// Sets the value of the variable from a decimal object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NativeFloatVar_SetValue(
|
||||
udt_NativeFloatVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
static int NumberVar_SetValueDecimal(udt_Variable *var, uint32_t pos,
|
||||
dpiData *data, PyObject *value)
|
||||
{
|
||||
if (!PyFloat_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting float");
|
||||
PyObject *textValue;
|
||||
int status;
|
||||
|
||||
if (Py_TYPE(value) != g_DecimalType) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting decimal");
|
||||
return -1;
|
||||
}
|
||||
var->data[pos] = PyFloat_AS_DOUBLE(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NativeIntVar_GetValue()
|
||||
// Returns the value stored at the given array position as an integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *NativeIntVar_GetValue(
|
||||
udt_NativeIntVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
{
|
||||
return PyInt_FromLong(var->data[pos]);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NativeIntVar_SetValue()
|
||||
// Set the value of the variable which should be a native integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NativeIntVar_SetValue(
|
||||
udt_NativeIntVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
if (!PyInt_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting integer");
|
||||
textValue = PyObject_Str(value);
|
||||
if (!textValue)
|
||||
return -1;
|
||||
}
|
||||
var->data[pos] = PyInt_AsLong(value);
|
||||
status = Variable_SetValueBytes(var, pos, data, textValue);
|
||||
Py_DECREF(textValue);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueFloat()
|
||||
// Sets the value of the variable from a float.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueFloat(udt_Variable *var, uint32_t pos,
|
||||
dpiData *data, PyObject *value)
|
||||
{
|
||||
data->value.asDouble = PyFloat_AsDouble(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueInteger()
|
||||
// Sets the value of the variable from an integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueInteger(udt_Variable *var, uint32_t pos,
|
||||
dpiData *data, PyObject *value)
|
||||
{
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyInt_Check(value)) {
|
||||
data->value.asInt64 = PyInt_AS_LONG(value);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (!PyLong_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting integer");
|
||||
return -1;
|
||||
}
|
||||
data->value.asInt64 = PyLong_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// NumberVar_SetValueLongInteger()
|
||||
// Sets the value of the variable from a long integer.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int NumberVar_SetValueLongInteger(udt_Variable *var, uint32_t pos,
|
||||
dpiData *data, PyObject *value)
|
||||
{
|
||||
PyObject *textValue;
|
||||
int status;
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (!PyInt_Check(value) && !PyLong_Check(value)) {
|
||||
#else
|
||||
if (!PyLong_Check(value)) {
|
||||
#endif
|
||||
PyErr_SetString(PyExc_TypeError, "expecting integer");
|
||||
return -1;
|
||||
}
|
||||
textValue = PyObject_Str(value);
|
||||
if (!textValue)
|
||||
return -1;
|
||||
status = Variable_SetValueBytes(var, pos, data, textValue);
|
||||
Py_DECREF(textValue);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
917
src/Object.c
917
src/Object.c
File diff suppressed because it is too large
Load Diff
442
src/ObjectType.c
442
src/ObjectType.c
@ -17,34 +17,34 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_Connection *connection;
|
||||
OCIType *tdo;
|
||||
dpiObjectType *handle;
|
||||
PyObject *schema;
|
||||
PyObject *name;
|
||||
PyObject *attributes;
|
||||
PyObject *attributesByName;
|
||||
OCITypeCode typeCode;
|
||||
OCITypeCode collectionTypeCode;
|
||||
OCITypeCode elementTypeCode;
|
||||
const char *encoding;
|
||||
dpiNativeTypeNum elementNativeTypeNum;
|
||||
PyObject *elementType;
|
||||
boolean isCollection;
|
||||
char isCollection;
|
||||
} udt_ObjectType;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *name;
|
||||
OCITypeCode typeCode;
|
||||
udt_ObjectType *subType;
|
||||
dpiObjectAttr *handle;
|
||||
dpiNativeTypeNum nativeTypeNum;
|
||||
udt_ObjectType *type;
|
||||
} udt_ObjectAttribute;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of type variable functions.
|
||||
// Declaration of functions
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_ObjectType *ObjectType_New(udt_Connection*, OCIParam*, ub4);
|
||||
static udt_ObjectType *ObjectType_New(udt_Connection*, dpiObjectType*);
|
||||
static void ObjectType_Free(udt_ObjectType*);
|
||||
static PyObject *ObjectType_Repr(udt_ObjectType*);
|
||||
static PyObject *ObjectType_NewObject(udt_ObjectType*, PyObject*, PyObject*);
|
||||
static udt_ObjectAttribute *ObjectAttribute_New(udt_Connection*, OCIParam*);
|
||||
static udt_ObjectAttribute *ObjectAttribute_New(udt_Connection*,
|
||||
dpiObjectAttr*);
|
||||
static void ObjectAttribute_Free(udt_ObjectAttribute*);
|
||||
static PyObject *ObjectAttribute_Repr(udt_ObjectAttribute*);
|
||||
|
||||
@ -178,194 +178,71 @@ static PyTypeObject g_ObjectAttributeType = {
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectType_Describe()
|
||||
// Describe the type and store information about it as needed.
|
||||
// ObjectType_Initialize()
|
||||
// Initialize the object type with the information that is required.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectType_Describe(
|
||||
udt_ObjectType *self, // type to populate
|
||||
OCIDescribe *describeHandle) // describe handle
|
||||
static int ObjectType_Initialize(udt_ObjectType *self,
|
||||
udt_Connection *connection)
|
||||
{
|
||||
OCIParam *topLevelParam, *attributeListParam, *attributeParam;
|
||||
udt_ObjectAttribute *attribute;
|
||||
OCIParam *collectionParam;
|
||||
ub2 numAttributes;
|
||||
sword status;
|
||||
int i;
|
||||
dpiObjectAttr **attributes;
|
||||
udt_ObjectAttribute *attr;
|
||||
dpiObjectTypeInfo info;
|
||||
uint16_t i;
|
||||
|
||||
// describe the type
|
||||
status = OCIDescribeAny(self->connection->handle,
|
||||
self->connection->environment->errorHandle, (dvoid*) self->tdo, 0,
|
||||
OCI_OTYPE_PTR, OCI_DEFAULT, OCI_PTYPE_TYPE, describeHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): describe type") < 0)
|
||||
// get object type information
|
||||
self->encoding = connection->encodingInfo.encoding;
|
||||
if (dpiObjectType_getInfo(self->handle, &info) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
self->schema = cxString_FromEncodedString(info.schema, info.schemaLength,
|
||||
self->encoding);
|
||||
if (!self->schema)
|
||||
return -1;
|
||||
|
||||
// get top level parameter descriptor
|
||||
status = OCIAttrGet(describeHandle, OCI_HTYPE_DESCRIBE, &topLevelParam, 0,
|
||||
OCI_ATTR_PARAM, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get top level parameter descriptor") < 0)
|
||||
self->name = cxString_FromEncodedString(info.name, info.nameLength,
|
||||
self->encoding);
|
||||
if (!self->name)
|
||||
return -1;
|
||||
|
||||
// determine type of type
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM, &self->typeCode, 0,
|
||||
OCI_ATTR_TYPECODE, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get type code") < 0)
|
||||
return -1;
|
||||
|
||||
// if a collection, need to determine the sub type
|
||||
if (self->typeCode == OCI_TYPECODE_NAMEDCOLLECTION) {
|
||||
self->isCollection = 1;
|
||||
|
||||
// determine type of collection
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
|
||||
&self->collectionTypeCode, 0, OCI_ATTR_COLLECTION_TYPECODE,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get collection type code") < 0)
|
||||
self->isCollection = info.isCollection;
|
||||
self->elementNativeTypeNum = info.elementDefaultNativeTypeNum;
|
||||
if (info.elementObjectType) {
|
||||
self->elementType = (PyObject*) ObjectType_New(connection,
|
||||
info.elementObjectType);
|
||||
if (!self->elementType)
|
||||
return -1;
|
||||
|
||||
// acquire collection parameter descriptor
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM, &collectionParam,
|
||||
0, OCI_ATTR_COLLECTION_ELEMENT,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get collection descriptor") < 0)
|
||||
return -1;
|
||||
|
||||
// determine type of element
|
||||
status = OCIAttrGet(collectionParam, OCI_DTYPE_PARAM,
|
||||
&self->elementTypeCode, 0, OCI_ATTR_TYPECODE,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get element type code") < 0)
|
||||
return -1;
|
||||
|
||||
// if element type is an object type get its type
|
||||
if (self->elementTypeCode == OCI_TYPECODE_OBJECT) {
|
||||
self->elementType = (PyObject*)
|
||||
ObjectType_New(self->connection, collectionParam,
|
||||
OCI_ATTR_TYPE_NAME);
|
||||
if (!self->elementType)
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// determine the number of attributes
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
|
||||
(dvoid*) &numAttributes, 0, OCI_ATTR_NUM_TYPE_ATTRS,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get number of attributes") < 0)
|
||||
return -1;
|
||||
|
||||
// allocate the attribute list and dictionary
|
||||
self->attributes = PyList_New(numAttributes);
|
||||
// allocate the attribute list (temporary and permanent) and dictionary
|
||||
self->attributes = PyList_New(info.numAttributes);
|
||||
if (!self->attributes)
|
||||
return -1;
|
||||
self->attributesByName = PyDict_New();
|
||||
if (!self->attributesByName)
|
||||
return -1;
|
||||
|
||||
// acquire the list parameter descriptor
|
||||
status = OCIAttrGet(topLevelParam, OCI_DTYPE_PARAM,
|
||||
(dvoid*) &attributeListParam, 0, OCI_ATTR_LIST_TYPE_ATTRS,
|
||||
self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get list parameter descriptor") < 0)
|
||||
// get the list of attributes from DPI
|
||||
attributes = PyMem_Malloc(sizeof(dpiObjectAttr*) * info.numAttributes);
|
||||
if (!attributes) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
|
||||
// create attribute information for each attribute
|
||||
for (i = 0; i < numAttributes; i++) {
|
||||
status = OCIParamGet(attributeListParam, OCI_DTYPE_PARAM,
|
||||
self->connection->environment->errorHandle,
|
||||
(dvoid**) &attributeParam, (ub4) i + 1);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Describe(): get attribute param descriptor") < 0)
|
||||
return -1;
|
||||
attribute = ObjectAttribute_New(self->connection, attributeParam);
|
||||
if (!attribute)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->attributes, i, (PyObject*) attribute);
|
||||
if (PyDict_SetItem(self->attributesByName, attribute->name,
|
||||
(PyObject*) attribute) < 0)
|
||||
return -1;
|
||||
}
|
||||
if (dpiObjectType_getAttributes(self->handle, info.numAttributes,
|
||||
attributes) < 0) {
|
||||
PyMem_Free(attributes);
|
||||
return Error_RaiseAndReturnInt();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectType_Initialize()
|
||||
// Initialize the object type with the information that is required.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectType_Initialize(
|
||||
udt_ObjectType *self, // type to initialize
|
||||
OCIParam *param, // parameter descriptor
|
||||
ub4 nameAttribute) // value for the name attribute
|
||||
{
|
||||
OCIDescribe *describeHandle;
|
||||
OCIRef *tdoReference;
|
||||
sword status;
|
||||
char *name;
|
||||
ub4 size;
|
||||
|
||||
// determine the schema of the type
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &name, &size,
|
||||
OCI_ATTR_SCHEMA_NAME, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): get schema name") < 0)
|
||||
return -1;
|
||||
self->schema = cxString_FromEncodedString(name, size,
|
||||
self->connection->environment->encoding);
|
||||
if (!self->schema)
|
||||
return -1;
|
||||
|
||||
// determine the name of the type
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &name, &size,
|
||||
nameAttribute, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): get name") < 0)
|
||||
return -1;
|
||||
self->name = cxString_FromEncodedString(name, size,
|
||||
self->connection->environment->encoding);
|
||||
if (!self->name)
|
||||
return -1;
|
||||
|
||||
// retrieve TDO of the parameter
|
||||
status = OCIAttrGet(param, OCI_HTYPE_DESCRIBE, (dvoid*) &tdoReference, 0,
|
||||
OCI_ATTR_REF_TDO, self->connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): get TDO reference") < 0)
|
||||
return -1;
|
||||
status = OCIObjectPin(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, tdoReference, NULL,
|
||||
OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE,
|
||||
(dvoid**) &self->tdo);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): pin TDO reference") < 0)
|
||||
return -1;
|
||||
|
||||
// acquire a describe handle
|
||||
status = OCIHandleAlloc(self->connection->environment->handle,
|
||||
(dvoid**) &describeHandle, OCI_HTYPE_DESCRIBE, 0, 0);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): allocate describe handle") < 0)
|
||||
return -1;
|
||||
|
||||
// describe the type
|
||||
if (ObjectType_Describe(self, describeHandle) < 0)
|
||||
return -1;
|
||||
|
||||
// free the describe handle
|
||||
status = OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectType_Initialize(): free describe handle") < 0)
|
||||
return -1;
|
||||
|
||||
// create attribute information for each attribute
|
||||
for (i = 0; i < info.numAttributes; i++) {
|
||||
attr = ObjectAttribute_New(connection, attributes[i]);
|
||||
if (!attr) {
|
||||
PyMem_Free(attributes);
|
||||
return -1;
|
||||
}
|
||||
PyList_SET_ITEM(self->attributes, i, (PyObject*) attr);
|
||||
if (PyDict_SetItem(self->attributesByName, attr->name,
|
||||
(PyObject*) attr) < 0)
|
||||
return -1;
|
||||
}
|
||||
PyMem_Free(attributes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -374,19 +251,21 @@ static int ObjectType_Initialize(
|
||||
// ObjectType_New()
|
||||
// Allocate a new object type.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_ObjectType *ObjectType_New(
|
||||
udt_Connection *connection, // connection for type information
|
||||
OCIParam *param, // parameter descriptor
|
||||
ub4 nameAttribute) // value for the name attribute
|
||||
static udt_ObjectType *ObjectType_New(udt_Connection *connection,
|
||||
dpiObjectType *handle)
|
||||
{
|
||||
udt_ObjectType *self;
|
||||
|
||||
self = (udt_ObjectType*) g_ObjectTypeType.tp_alloc(&g_ObjectTypeType, 0);
|
||||
if (!self)
|
||||
return NULL;
|
||||
Py_INCREF(connection);
|
||||
self->connection = connection;
|
||||
if (ObjectType_Initialize(self, param, nameAttribute) < 0) {
|
||||
if (dpiObjectType_addRef(handle) < 0) {
|
||||
Py_DECREF(self);
|
||||
Error_RaiseAndReturnNull();
|
||||
return NULL;
|
||||
}
|
||||
self->handle = handle;
|
||||
if (ObjectType_Initialize(self, connection) < 0) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
@ -399,87 +278,25 @@ static udt_ObjectType *ObjectType_New(
|
||||
// ObjectType_NewByName()
|
||||
// Create a new object type given its name.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_ObjectType *ObjectType_NewByName(
|
||||
udt_Connection *connection, // connection for type information
|
||||
PyObject *name) // name of object type to describe
|
||||
static udt_ObjectType *ObjectType_NewByName(udt_Connection *connection,
|
||||
PyObject *name)
|
||||
{
|
||||
OCIDescribe *describeHandle;
|
||||
udt_ObjectType *result;
|
||||
udt_ObjectType *objType;
|
||||
dpiObjectType *handle;
|
||||
udt_Buffer buffer;
|
||||
OCIParam *param;
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
OCIType *tdo;
|
||||
#endif
|
||||
sword status;
|
||||
int status;
|
||||
|
||||
// allocate describe handle
|
||||
status = OCIHandleAlloc(connection->environment->handle,
|
||||
(dvoid**) &describeHandle, OCI_HTYPE_DESCRIBE, 0, 0);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectType_NewByName(): allocate describe handle") < 0)
|
||||
return NULL;
|
||||
|
||||
// describe the object
|
||||
if (cxBuffer_FromObject(&buffer, name,
|
||||
connection->environment->encoding) < 0) {
|
||||
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
connection->encodingInfo.encoding) < 0)
|
||||
return NULL;
|
||||
}
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
status = OCITypeByFullName(connection->environment->handle,
|
||||
connection->environment->errorHandle, connection->handle,
|
||||
buffer.ptr, (ub4) buffer.size, NULL, 0, OCI_DURATION_SESSION,
|
||||
OCI_TYPEGET_ALL, &tdo);
|
||||
status = dpiConn_getObjectType(connection->handle, buffer.ptr,
|
||||
buffer.size, &handle);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectType_NewByName(): get type by full name") < 0) {
|
||||
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
return NULL;
|
||||
}
|
||||
status = OCIDescribeAny(connection->handle,
|
||||
connection->environment->errorHandle, (dvoid*) tdo, 0,
|
||||
OCI_OTYPE_PTR, 0, OCI_PTYPE_TYPE, describeHandle);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectType_NewByName(): describe type") < 0) {
|
||||
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
status = OCIDescribeAny(connection->handle,
|
||||
connection->environment->errorHandle, (dvoid*) buffer.ptr,
|
||||
(ub4) buffer.size, OCI_OTYPE_NAME, 0, OCI_PTYPE_TYPE,
|
||||
describeHandle);
|
||||
cxBuffer_Clear(&buffer);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectType_NewByName(): describe type") < 0) {
|
||||
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// get the parameter handle
|
||||
status = OCIAttrGet(describeHandle, OCI_HTYPE_DESCRIBE, ¶m, 0,
|
||||
OCI_ATTR_PARAM, connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectType_NewByName(): get parameter handle") < 0) {
|
||||
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get object type
|
||||
result = ObjectType_New(connection, param, OCI_ATTR_NAME);
|
||||
if (!result) {
|
||||
OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// free the describe handle
|
||||
status = OCIHandleFree(describeHandle, OCI_HTYPE_DESCRIBE);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectType_NewByName(): free describe handle") < 0)
|
||||
return NULL;
|
||||
|
||||
return result;
|
||||
if (status < 0)
|
||||
return (udt_ObjectType*) Error_RaiseAndReturnNull();
|
||||
objType = ObjectType_New(connection, handle);
|
||||
dpiObjectType_release(handle);
|
||||
return objType;
|
||||
}
|
||||
|
||||
|
||||
@ -487,13 +304,12 @@ static udt_ObjectType *ObjectType_NewByName(
|
||||
// ObjectType_Free()
|
||||
// Free the memory associated with an object type.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void ObjectType_Free(
|
||||
udt_ObjectType *self) // object type to free
|
||||
static void ObjectType_Free(udt_ObjectType *self)
|
||||
{
|
||||
if (self->tdo)
|
||||
OCIObjectUnpin(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, self->tdo);
|
||||
Py_CLEAR(self->connection);
|
||||
if (self->handle) {
|
||||
dpiObjectType_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_CLEAR(self->schema);
|
||||
Py_CLEAR(self->name);
|
||||
Py_CLEAR(self->attributes);
|
||||
@ -507,8 +323,7 @@ static void ObjectType_Free(
|
||||
// ObjectType_Repr()
|
||||
// Return a string representation of the object type.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ObjectType_Repr(
|
||||
udt_ObjectType *self) // object type to return the string for
|
||||
static PyObject *ObjectType_Repr(udt_ObjectType *self)
|
||||
{
|
||||
PyObject *module, *name, *result, *format, *formatArgs;
|
||||
|
||||
@ -538,13 +353,12 @@ static PyObject *ObjectType_Repr(
|
||||
// ObjectType_NewObject()
|
||||
// Factory function for creating objects of the type which can be bound.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ObjectType_NewObject(
|
||||
udt_ObjectType *self, // object type to return the string for
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
static PyObject *ObjectType_NewObject(udt_ObjectType *self, PyObject *args,
|
||||
PyObject *keywordArgs)
|
||||
{
|
||||
static char *keywordList[] = { "value", NULL };
|
||||
PyObject *initialValue;
|
||||
dpiObject *handle;
|
||||
udt_Object *obj;
|
||||
|
||||
// parse arguments
|
||||
@ -553,8 +367,12 @@ static PyObject *ObjectType_NewObject(
|
||||
&initialValue))
|
||||
return NULL;
|
||||
|
||||
// get handle to newly created object
|
||||
if (dpiObjectType_createObject(self->handle, &handle) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
|
||||
// create the object
|
||||
obj = Object_Create(self);
|
||||
obj = (udt_Object*) Object_New(self, handle, 0);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
@ -574,43 +392,23 @@ static PyObject *ObjectType_NewObject(
|
||||
// ObjectAttribute_Initialize()
|
||||
// Initialize the new object attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectAttribute_Initialize(
|
||||
udt_ObjectAttribute *self, // object attribute to initialize
|
||||
udt_Connection *connection, // connection in use
|
||||
OCIParam *param) // parameter descriptor
|
||||
static int ObjectAttribute_Initialize(udt_ObjectAttribute *self,
|
||||
udt_Connection *connection)
|
||||
{
|
||||
sword status;
|
||||
char *name;
|
||||
ub4 size;
|
||||
dpiObjectAttrInfo info;
|
||||
|
||||
// determine the name of the attribute
|
||||
status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid*) &name, &size,
|
||||
OCI_ATTR_NAME, connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectAttribute_Initialize(): get name") < 0)
|
||||
return -1;
|
||||
self->name = cxString_FromEncodedString(name, size,
|
||||
connection->environment->encoding);
|
||||
if (dpiObjectAttr_getInfo(self->handle, &info) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
self->nativeTypeNum = info.defaultNativeTypeNum;
|
||||
self->name = cxString_FromEncodedString(info.name, info.nameLength,
|
||||
connection->encodingInfo.encoding);
|
||||
if (!self->name)
|
||||
return -1;
|
||||
|
||||
// determine the type of the attribute
|
||||
status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid*) &self->typeCode, 0,
|
||||
OCI_ATTR_TYPECODE, connection->environment->errorHandle);
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"ObjectAttribute_Initialize(): get type code") < 0)
|
||||
return -1;
|
||||
|
||||
// if the type of the attribute is object, recurse
|
||||
switch (self->typeCode) {
|
||||
case OCI_TYPECODE_NAMEDCOLLECTION:
|
||||
case OCI_TYPECODE_OBJECT:
|
||||
self->subType = ObjectType_New(connection, param,
|
||||
OCI_ATTR_TYPE_NAME);
|
||||
if (!self->subType)
|
||||
return -1;
|
||||
break;
|
||||
};
|
||||
if (info.objectType) {
|
||||
self->type = ObjectType_New(connection, info.objectType);
|
||||
if (!self->type)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -620,17 +418,19 @@ static int ObjectAttribute_Initialize(
|
||||
// ObjectAttribute_New()
|
||||
// Allocate a new object attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_ObjectAttribute *ObjectAttribute_New(
|
||||
udt_Connection *connection, // connection information
|
||||
OCIParam *param) // parameter descriptor
|
||||
static udt_ObjectAttribute *ObjectAttribute_New(udt_Connection *connection,
|
||||
dpiObjectAttr *handle)
|
||||
{
|
||||
udt_ObjectAttribute *self;
|
||||
|
||||
self = (udt_ObjectAttribute*)
|
||||
g_ObjectAttributeType.tp_alloc(&g_ObjectAttributeType, 0);
|
||||
if (!self)
|
||||
if (!self) {
|
||||
dpiObjectAttr_release(handle);
|
||||
return NULL;
|
||||
if (ObjectAttribute_Initialize(self, connection, param) < 0) {
|
||||
}
|
||||
self->handle = handle;
|
||||
if (ObjectAttribute_Initialize(self, connection) < 0) {
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
@ -643,11 +443,14 @@ static udt_ObjectAttribute *ObjectAttribute_New(
|
||||
// ObjectAttribute_Free()
|
||||
// Free the memory associated with an object attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void ObjectAttribute_Free(
|
||||
udt_ObjectAttribute *self) // object attribute to free
|
||||
static void ObjectAttribute_Free(udt_ObjectAttribute *self)
|
||||
{
|
||||
if (self->handle) {
|
||||
dpiObjectAttr_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_CLEAR(self->name);
|
||||
Py_CLEAR(self->subType);
|
||||
Py_CLEAR(self->type);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
@ -656,8 +459,7 @@ static void ObjectAttribute_Free(
|
||||
// ObjectAttribute_Repr()
|
||||
// Return a string representation of the object attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ObjectAttribute_Repr(
|
||||
udt_ObjectAttribute *self) // attribute to return the string for
|
||||
static PyObject *ObjectAttribute_Repr(udt_ObjectAttribute *self)
|
||||
{
|
||||
PyObject *module, *name, *result, *format, *formatArgs;
|
||||
|
||||
|
||||
338
src/ObjectVar.c
338
src/ObjectVar.c
@ -12,364 +12,58 @@
|
||||
// Defines the routines for handling Oracle object variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "ObjectType.c"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Object type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
dvoid **data;
|
||||
dvoid **objectIndicator;
|
||||
PyObject **objects;
|
||||
udt_Connection *connection;
|
||||
udt_ObjectType *objectType;
|
||||
} udt_ObjectVar;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of object variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_Initialize(udt_ObjectVar*, udt_Cursor*);
|
||||
static void ObjectVar_Finalize(udt_ObjectVar*);
|
||||
static int ObjectVar_SetValue(udt_ObjectVar*, unsigned, PyObject*);
|
||||
static PyObject *ObjectVar_GetValue(udt_ObjectVar*, unsigned);
|
||||
static int ObjectVar_PreDefine(udt_ObjectVar*, OCIParam*);
|
||||
static int ObjectVar_PostDefine(udt_ObjectVar*);
|
||||
static int ObjectVar_PostBind(udt_ObjectVar*);
|
||||
static int ObjectVar_PreFetch(udt_ObjectVar*);
|
||||
static int ObjectVar_IsNull(udt_ObjectVar*, unsigned);
|
||||
static int ObjectVar_SetType(udt_ObjectVar*, PyObject*);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of members for Oracle objects
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyMemberDef g_ObjectVarMembers[] = {
|
||||
{ "type", T_OBJECT, offsetof(udt_ObjectVar, objectType), READONLY },
|
||||
{ NULL }
|
||||
};
|
||||
static int ObjectVar_SetValue(udt_Variable*, uint32_t, dpiData*, PyObject*);
|
||||
static PyObject *ObjectVar_GetValue(udt_Variable*, dpiData*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_ObjectVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.OBJECT", // tp_name
|
||||
sizeof(udt_ObjectVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0, // tp_doc
|
||||
0, // tp_traverse
|
||||
0, // tp_clear
|
||||
0, // tp_richcompare
|
||||
0, // tp_weaklistoffset
|
||||
0, // tp_iter
|
||||
0, // tp_iternext
|
||||
0, // tp_methods
|
||||
g_ObjectVarMembers // tp_members
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_ObjectVarType, OBJECT)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_Object = {
|
||||
(InitializeProc) ObjectVar_Initialize,
|
||||
(FinalizeProc) ObjectVar_Finalize,
|
||||
(PreDefineProc) ObjectVar_PreDefine,
|
||||
(PostDefineProc) ObjectVar_PostDefine,
|
||||
(PostBindProc) ObjectVar_PostBind,
|
||||
(PreFetchProc) ObjectVar_PreFetch,
|
||||
(IsNullProc) ObjectVar_IsNull,
|
||||
(SetValueProc) ObjectVar_SetValue,
|
||||
(GetValueProc) ObjectVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_ObjectVarType, // Python type
|
||||
SQLT_NTY, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(dvoid*), // element length
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
0, // can be copied
|
||||
0 // can be in array
|
||||
DPI_ORACLE_TYPE_OBJECT, // Oracle type
|
||||
DPI_NATIVE_TYPE_OBJECT, // native type
|
||||
0 // element length
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_Initialize()
|
||||
// Initialize the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_Initialize(
|
||||
udt_ObjectVar *self, // variable to initialize
|
||||
udt_Cursor *cursor) // cursor to use
|
||||
{
|
||||
ub4 i;
|
||||
|
||||
Py_INCREF(cursor->connection);
|
||||
self->connection = cursor->connection;
|
||||
self->objectType = NULL;
|
||||
self->objectIndicator =
|
||||
PyMem_Malloc(self->allocatedElements * sizeof(dvoid*));
|
||||
if (!self->objectIndicator) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
self->objects = PyMem_Malloc(self->allocatedElements * sizeof(PyObject*));
|
||||
if (!self->objects) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < self->allocatedElements; i++) {
|
||||
self->data[i] = NULL;
|
||||
self->objectIndicator[i] = NULL;
|
||||
self->objects[i] = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_Finalize()
|
||||
// Prepare for variable destruction.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void ObjectVar_Finalize(
|
||||
udt_ObjectVar *self) // variable to free
|
||||
{
|
||||
ub4 i;
|
||||
|
||||
for (i = 0; i < self->allocatedElements; i++) {
|
||||
if (self->objects[i])
|
||||
Py_CLEAR(self->objects[i]);
|
||||
else if (self->data[i])
|
||||
OCIObjectFree(self->environment->handle,
|
||||
self->environment->errorHandle, self->data[i],
|
||||
OCI_DEFAULT);
|
||||
}
|
||||
Py_CLEAR(self->connection);
|
||||
Py_CLEAR(self->objectType);
|
||||
if (self->objectIndicator)
|
||||
PyMem_Free(self->objectIndicator);
|
||||
if (self->objects)
|
||||
PyMem_Free(self->objects);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_PreDefine()
|
||||
// Performs additional steps required for defining objects.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_PreDefine(
|
||||
udt_ObjectVar *self, // variable to set up
|
||||
OCIParam *param) // parameter being defined
|
||||
{
|
||||
self->objectType = ObjectType_New(self->connection, param,
|
||||
OCI_ATTR_TYPE_NAME);
|
||||
if (!self->objectType)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_PostDefine()
|
||||
// Performs additional steps required for defining objects.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_PostDefine(
|
||||
udt_ObjectVar *self) // variable to set up
|
||||
{
|
||||
sword status;
|
||||
|
||||
status = OCIDefineObject(self->defineHandle,
|
||||
self->environment->errorHandle, self->objectType->tdo, self->data,
|
||||
0, self->objectIndicator, 0);
|
||||
return Environment_CheckForError(self->environment, status,
|
||||
"ObjectVar_PostDefine(): define object");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_PostBind()
|
||||
// Performs additional steps required for binding objects.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_PostBind(
|
||||
udt_ObjectVar *self) // variable to set up
|
||||
{
|
||||
sword status;
|
||||
|
||||
if (!self->objectType) {
|
||||
PyErr_SetString(g_InterfaceErrorException,
|
||||
"object type not associated with bind variable");
|
||||
return -1;
|
||||
}
|
||||
status = OCIBindObject(self->bindHandle, self->environment->errorHandle,
|
||||
self->objectType->tdo, self->data, 0, self->objectIndicator, 0);
|
||||
return Environment_CheckForError(self->environment, status,
|
||||
"ObjectVar_PostBind(): bind object");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_PreFetch()
|
||||
// Free objects prior to next fetch.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_PreFetch(
|
||||
udt_ObjectVar *var) // variable to free
|
||||
{
|
||||
ub4 i;
|
||||
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
if (var->objects[i])
|
||||
Py_CLEAR(var->objects[i]);
|
||||
else if (var->data[i])
|
||||
OCIObjectFree(var->environment->handle,
|
||||
var->environment->errorHandle, var->data[i], OCI_DEFAULT);
|
||||
var->data[i] = NULL;
|
||||
var->objectIndicator[i] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_IsNull()
|
||||
// Returns a boolean indicating if the variable is null or not.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_IsNull(
|
||||
udt_ObjectVar *self, // variable to set up
|
||||
unsigned pos) // position to check
|
||||
{
|
||||
if (!self->objectIndicator[pos])
|
||||
return 1;
|
||||
return (*((OCIInd*) self->objectIndicator[pos]) == OCI_IND_NULL);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
// Set the value of the variable. Only cx_Oracle.Object values are permitted.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_SetValue(
|
||||
udt_ObjectVar *self, // variable to determine value for
|
||||
unsigned pos, // array position
|
||||
PyObject *value) // value to set
|
||||
static int ObjectVar_SetValue(udt_Variable *self, uint32_t pos, dpiData *data,
|
||||
PyObject *value)
|
||||
{
|
||||
udt_Object *object;
|
||||
udt_Object *obj;
|
||||
|
||||
// only cx_Oracle.Object values are permitted and the types must match
|
||||
// if the variable doesn't have a type yet, assign it
|
||||
if (Py_TYPE(value) != &g_ObjectType) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting cx_Oracle.Object");
|
||||
return -1;
|
||||
}
|
||||
object = (udt_Object*) value;
|
||||
if (!self->objectType) {
|
||||
Py_INCREF(object->objectType);
|
||||
self->objectType = object->objectType;
|
||||
} else if (object->objectType->tdo != self->objectType->tdo) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"expecting same type as the variable itself");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// eliminate prior value, if needed
|
||||
if (self->objects[pos])
|
||||
Py_CLEAR(self->objects[pos]);
|
||||
else OCIObjectFree(self->environment->handle,
|
||||
self->environment->errorHandle, self->data[pos], OCI_DEFAULT);
|
||||
|
||||
// set new value
|
||||
Py_INCREF(value);
|
||||
self->objects[pos] = value;
|
||||
self->data[pos] = object->instance;
|
||||
self->objectIndicator[pos] = object->indicator;
|
||||
obj = (udt_Object*) value;
|
||||
if (dpiVar_setFromObject(self->handle, pos, obj->handle) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *ObjectVar_GetValue(
|
||||
udt_ObjectVar *self, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *ObjectVar_GetValue(udt_Variable *self, dpiData *data)
|
||||
{
|
||||
PyObject *obj;
|
||||
|
||||
// create the object, if needed; for collections, return a list, not the
|
||||
// object itself
|
||||
if (!self->objects[pos]) {
|
||||
obj = Object_New(self->objectType, self->data[pos],
|
||||
self->objectIndicator[pos], 1);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
self->objects[pos] = obj;
|
||||
}
|
||||
|
||||
Py_INCREF(self->objects[pos]);
|
||||
return self->objects[pos];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ObjectVar_SetType()
|
||||
// Internal method used to set the type when creating an object variable.
|
||||
// This will also create the object instances.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ObjectVar_SetType(
|
||||
udt_ObjectVar *self, // variable to initialize the type
|
||||
PyObject *typeNameObj) // value to set
|
||||
{
|
||||
dvoid *instance, *indicator;
|
||||
sword status;
|
||||
ub4 i;
|
||||
|
||||
// get the object type from the name
|
||||
self->objectType = ObjectType_NewByName(self->connection, typeNameObj);
|
||||
if (!self->objectType)
|
||||
return -1;
|
||||
|
||||
// initialize the object instances
|
||||
for (i = 0; i < self->allocatedElements; i++) {
|
||||
|
||||
// create the object instance
|
||||
status = OCIObjectNew(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle,
|
||||
self->connection->handle, self->objectType->typeCode,
|
||||
self->objectType->tdo, NULL, OCI_DURATION_SESSION, TRUE,
|
||||
&instance);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectVar_SetType(): create object instance") < 0)
|
||||
return -1;
|
||||
self->data[i] = instance;
|
||||
|
||||
// get the null indicator structure
|
||||
status = OCIObjectGetInd(self->connection->environment->handle,
|
||||
self->connection->environment->errorHandle, instance,
|
||||
&indicator);
|
||||
if (Environment_CheckForError(self->connection->environment, status,
|
||||
"ObjectVar_SetType(): get indicator structure") < 0)
|
||||
return -1;
|
||||
*((OCIInd*) indicator) = OCI_IND_NULL;
|
||||
self->objectIndicator[i] = indicator;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return Object_New(self->objectType, data->value.asObject, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -17,31 +17,20 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
OCISPool *handle;
|
||||
ub4 minSessions;
|
||||
ub4 maxSessions;
|
||||
ub4 sessionIncrement;
|
||||
ub4 cacheSize;
|
||||
dpiPool *handle;
|
||||
uint32_t minSessions;
|
||||
uint32_t maxSessions;
|
||||
uint32_t sessionIncrement;
|
||||
uint32_t cacheSize;
|
||||
dpiEncodingInfo encodingInfo;
|
||||
int homogeneous;
|
||||
int externalAuth;
|
||||
PyObject *name;
|
||||
PyObject *username;
|
||||
PyObject *dsn;
|
||||
udt_Environment *environment;
|
||||
PyObject *name;
|
||||
PyTypeObject *connectionType;
|
||||
} udt_SessionPool;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constants for the OCI attributes
|
||||
//-----------------------------------------------------------------------------
|
||||
static ub4 gc_OpenAttribute = OCI_ATTR_SPOOL_OPEN_COUNT;
|
||||
static ub4 gc_BusyAttribute = OCI_ATTR_SPOOL_BUSY_COUNT;
|
||||
static ub4 gc_TimeoutAttribute = OCI_ATTR_SPOOL_TIMEOUT;
|
||||
static ub4 gc_GetModeAttribute = OCI_ATTR_SPOOL_GETMODE;
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
static ub4 gc_MaxLifetimeAttribute = OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// functions for the Python type "SessionPool"
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -50,9 +39,18 @@ static int SessionPool_Init(udt_SessionPool*, PyObject*, PyObject*);
|
||||
static void SessionPool_Free(udt_SessionPool*);
|
||||
static PyObject *SessionPool_Acquire(udt_SessionPool*, PyObject*, PyObject*);
|
||||
static PyObject *SessionPool_Drop(udt_SessionPool*, PyObject*);
|
||||
static PyObject *SessionPool_Release(udt_SessionPool*, PyObject*);
|
||||
static PyObject *SessionPool_GetOCIAttr(udt_SessionPool*, ub4*);
|
||||
static int SessionPool_SetOCIAttr(udt_SessionPool*, PyObject*, ub4*);
|
||||
static PyObject *SessionPool_Release(udt_SessionPool*, PyObject*, PyObject*);
|
||||
static PyObject *SessionPool_GetBusyCount(udt_SessionPool*, void*);
|
||||
static PyObject *SessionPool_GetGetMode(udt_SessionPool*, void*);
|
||||
static PyObject *SessionPool_GetMaxLifetimeSession(udt_SessionPool*, void*);
|
||||
static PyObject *SessionPool_GetOpenCount(udt_SessionPool*, void*);
|
||||
static PyObject *SessionPool_GetStmtCacheSize(udt_SessionPool*, void*);
|
||||
static PyObject *SessionPool_GetTimeout(udt_SessionPool*, void*);
|
||||
static int SessionPool_SetGetMode(udt_SessionPool*, PyObject*, void*);
|
||||
static int SessionPool_SetMaxLifetimeSession(udt_SessionPool*, PyObject*,
|
||||
void*);
|
||||
static int SessionPool_SetStmtCacheSize(udt_SessionPool*, PyObject*, void*);
|
||||
static int SessionPool_SetTimeout(udt_SessionPool*, PyObject*, void*);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -62,7 +60,8 @@ static PyMethodDef g_SessionPoolMethods[] = {
|
||||
{ "acquire", (PyCFunction) SessionPool_Acquire,
|
||||
METH_VARARGS | METH_KEYWORDS },
|
||||
{ "drop", (PyCFunction) SessionPool_Drop, METH_VARARGS },
|
||||
{ "release", (PyCFunction) SessionPool_Release, METH_VARARGS },
|
||||
{ "release", (PyCFunction) SessionPool_Release,
|
||||
METH_VARARGS | METH_KEYWORDS },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -88,16 +87,16 @@ static PyMemberDef g_SessionPoolMembers[] = {
|
||||
// declaration of calculated members for Python type "SessionPool"
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef g_SessionPoolCalcMembers[] = {
|
||||
{ "opened", (getter) SessionPool_GetOCIAttr, 0, 0, &gc_OpenAttribute },
|
||||
{ "busy", (getter) SessionPool_GetOCIAttr, 0, 0, &gc_BusyAttribute },
|
||||
{ "timeout", (getter) SessionPool_GetOCIAttr,
|
||||
(setter) SessionPool_SetOCIAttr, 0, &gc_TimeoutAttribute },
|
||||
{ "getmode", (getter) SessionPool_GetOCIAttr,
|
||||
(setter) SessionPool_SetOCIAttr, 0, &gc_GetModeAttribute },
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
{ "max_lifetime_session", (getter) SessionPool_GetOCIAttr,
|
||||
(setter) SessionPool_SetOCIAttr, 0, &gc_MaxLifetimeAttribute },
|
||||
#endif
|
||||
{ "opened", (getter) SessionPool_GetOpenCount, 0, 0, 0 },
|
||||
{ "busy", (getter) SessionPool_GetBusyCount, 0, 0, 0 },
|
||||
{ "timeout", (getter) SessionPool_GetTimeout,
|
||||
(setter) SessionPool_SetTimeout, 0, 0 },
|
||||
{ "getmode", (getter) SessionPool_GetGetMode,
|
||||
(setter) SessionPool_SetGetMode, 0, 0 },
|
||||
{ "max_lifetime_session", (getter) SessionPool_GetMaxLifetimeSession,
|
||||
(setter) SessionPool_SetMaxLifetimeSession, 0, 0 },
|
||||
{ "stmtcachesize", (getter) SessionPool_GetStmtCacheSize,
|
||||
(setter) SessionPool_SetStmtCacheSize, 0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -158,10 +157,8 @@ static PyTypeObject g_SessionPoolType = {
|
||||
// SessionPool_New()
|
||||
// Create a new session pool object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_New(
|
||||
PyTypeObject *type, // type object
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
static PyObject *SessionPool_New(PyTypeObject *type, PyObject *args,
|
||||
PyObject *keywordArgs)
|
||||
{
|
||||
udt_SessionPool *newObject;
|
||||
|
||||
@ -178,43 +175,42 @@ static PyObject *SessionPool_New(
|
||||
// SessionPool_Init()
|
||||
// Initialize the session pool object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_Init(
|
||||
udt_SessionPool *self, // session pool object
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
static int SessionPool_Init(udt_SessionPool *self, PyObject *args,
|
||||
PyObject *keywordArgs)
|
||||
{
|
||||
udt_Buffer userNameBuffer, passwordBuffer, dsnBuffer, editionBuffer;
|
||||
PyObject *threadedObj, *eventsObj, *homogeneousObj, *passwordObj;
|
||||
unsigned minSessions, maxSessions, sessionIncrement;
|
||||
int threaded, events, homogeneous, externalAuth;
|
||||
udt_Buffer username, password, dsn;
|
||||
uint32_t minSessions, maxSessions, sessionIncrement;
|
||||
PyObject *externalAuthObj, *editionObj;
|
||||
dpiCommonCreateParams dpiCommonParams;
|
||||
dpiPoolCreateParams dpiCreateParams;
|
||||
PyTypeObject *connectionType;
|
||||
char *encoding, *nencoding;
|
||||
PyObject *externalAuthObj;
|
||||
unsigned poolNameLength;
|
||||
const char *poolName;
|
||||
sword status;
|
||||
ub4 poolMode;
|
||||
ub1 getMode;
|
||||
const char *encoding;
|
||||
int status, temp;
|
||||
|
||||
// define keyword arguments
|
||||
static char *keywordList[] = { "user", "password", "dsn", "min", "max",
|
||||
"increment", "connectiontype", "threaded", "getmode", "events",
|
||||
"homogeneous", "externalauth", "encoding", "nencoding", NULL };
|
||||
"homogeneous", "externalauth", "encoding", "nencoding", "edition",
|
||||
NULL };
|
||||
|
||||
// parse arguments and keywords
|
||||
homogeneous = 1;
|
||||
externalAuthObj = NULL;
|
||||
encoding = nencoding = NULL;
|
||||
threaded = events = externalAuth = 0;
|
||||
externalAuthObj = editionObj = NULL;
|
||||
threadedObj = eventsObj = homogeneousObj = passwordObj = NULL;
|
||||
connectionType = &g_ConnectionType;
|
||||
getMode = OCI_SPOOL_ATTRVAL_NOWAIT;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!O!O!iii|OObOOOss",
|
||||
if (dpiContext_initCommonCreateParams(g_DpiContext, &dpiCommonParams) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
dpiCommonParams.driverName = DRIVER_NAME;
|
||||
dpiCommonParams.driverNameLength = strlen(dpiCommonParams.driverName);
|
||||
if (dpiContext_initPoolCreateParams(g_DpiContext, &dpiCreateParams) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!O!O!iii|OObOOOssO",
|
||||
keywordList, cxString_Type, &self->username,
|
||||
cxString_Type, &passwordObj, cxString_Type, &self->dsn,
|
||||
&minSessions, &maxSessions, &sessionIncrement, &connectionType,
|
||||
&threadedObj, &getMode, &eventsObj, &homogeneousObj,
|
||||
&externalAuthObj, &encoding, &nencoding))
|
||||
&threadedObj, &dpiCreateParams.getMode, &eventsObj,
|
||||
&homogeneousObj, &externalAuthObj, &dpiCommonParams.encoding,
|
||||
&dpiCommonParams.nencoding, &editionObj))
|
||||
return -1;
|
||||
if (!PyType_Check(connectionType)) {
|
||||
PyErr_SetString(g_ProgrammingErrorException,
|
||||
@ -226,27 +222,18 @@ static int SessionPool_Init(
|
||||
"connectiontype must be a subclass of Connection");
|
||||
return -1;
|
||||
}
|
||||
if (threadedObj) {
|
||||
threaded = PyObject_IsTrue(threadedObj);
|
||||
if (threaded < 0)
|
||||
return -1;
|
||||
}
|
||||
if (eventsObj) {
|
||||
events = PyObject_IsTrue(eventsObj);
|
||||
if (events < 0)
|
||||
return -1;
|
||||
}
|
||||
if (externalAuthObj) {
|
||||
externalAuth = PyObject_IsTrue(externalAuthObj);
|
||||
if (externalAuth < 0)
|
||||
return -1;
|
||||
homogeneous = 0;
|
||||
}
|
||||
if (homogeneousObj) {
|
||||
homogeneous = PyObject_IsTrue(homogeneousObj);
|
||||
if (homogeneous < 0)
|
||||
return -1;
|
||||
}
|
||||
if (GetBooleanValue(threadedObj, 0, &temp) < 0)
|
||||
return -1;
|
||||
if (temp)
|
||||
dpiCommonParams.createMode |= DPI_MODE_CREATE_THREADED;
|
||||
if (GetBooleanValue(eventsObj, 0, &temp) < 0)
|
||||
return -1;
|
||||
if (temp)
|
||||
dpiCommonParams.createMode |= DPI_MODE_CREATE_EVENTS;
|
||||
if (GetBooleanValue(externalAuthObj, 0, &dpiCreateParams.externalAuth) < 0)
|
||||
return -1;
|
||||
if (GetBooleanValue(homogeneousObj, 1, &dpiCreateParams.homogeneous) < 0)
|
||||
return -1;
|
||||
|
||||
// initialize the object's members
|
||||
Py_INCREF(connectionType);
|
||||
@ -256,70 +243,58 @@ static int SessionPool_Init(
|
||||
self->minSessions = minSessions;
|
||||
self->maxSessions = maxSessions;
|
||||
self->sessionIncrement = sessionIncrement;
|
||||
self->homogeneous = homogeneous;
|
||||
self->externalAuth = externalAuth;
|
||||
self->homogeneous = dpiCreateParams.homogeneous;
|
||||
self->externalAuth = dpiCreateParams.externalAuth;
|
||||
|
||||
// set up the environment
|
||||
self->environment = Environment_NewFromScratch(threaded, events, encoding,
|
||||
nencoding);
|
||||
if (!self->environment)
|
||||
// populate parameters
|
||||
encoding = GetAdjustedEncoding(dpiCommonParams.encoding);
|
||||
if (cxBuffer_FromObject(&userNameBuffer, self->username, encoding) < 0)
|
||||
return -1;
|
||||
|
||||
// create the session pool handle
|
||||
status = OCIHandleAlloc(self->environment->handle, (dvoid**) &self->handle,
|
||||
OCI_HTYPE_SPOOL, 0, 0);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"SessionPool_New(): allocate handle") < 0)
|
||||
return -1;
|
||||
|
||||
// prepare pool mode
|
||||
poolMode = OCI_SPC_STMTCACHE;
|
||||
if (self->homogeneous)
|
||||
poolMode |= OCI_SPC_HOMOGENEOUS;
|
||||
|
||||
// create the session pool
|
||||
if (cxBuffer_FromObject(&username, self->username,
|
||||
self->environment->encoding) < 0)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(&password, passwordObj,
|
||||
self->environment->encoding) < 0) {
|
||||
cxBuffer_Clear(&username);
|
||||
if (cxBuffer_FromObject(&passwordBuffer, passwordObj, encoding) < 0) {
|
||||
cxBuffer_Clear(&userNameBuffer);
|
||||
return -1;
|
||||
}
|
||||
if (cxBuffer_FromObject(&dsn, self->dsn,
|
||||
self->environment->encoding) < 0) {
|
||||
cxBuffer_Clear(&username);
|
||||
cxBuffer_Clear(&password);
|
||||
if (cxBuffer_FromObject(&dsnBuffer, self->dsn, encoding) < 0) {
|
||||
cxBuffer_Clear(&userNameBuffer);
|
||||
cxBuffer_Clear(&passwordBuffer);
|
||||
return -1;
|
||||
}
|
||||
if (cxBuffer_FromObject(&editionBuffer, editionObj, encoding) < 0) {
|
||||
cxBuffer_Clear(&userNameBuffer);
|
||||
cxBuffer_Clear(&passwordBuffer);
|
||||
cxBuffer_Clear(&dsnBuffer);
|
||||
return -1;
|
||||
}
|
||||
dpiCreateParams.minSessions = minSessions;
|
||||
dpiCreateParams.maxSessions = maxSessions;
|
||||
dpiCreateParams.sessionIncrement = sessionIncrement;
|
||||
|
||||
// create pool
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCISessionPoolCreate(self->environment->handle,
|
||||
self->environment->errorHandle, self->handle,
|
||||
(OraText**) &poolName, &poolNameLength, (OraText*) dsn.ptr,
|
||||
(ub4) dsn.size, minSessions, maxSessions, sessionIncrement,
|
||||
(OraText*) username.ptr, (ub4) username.size,
|
||||
(OraText*) password.ptr, (ub4) password.size, poolMode);
|
||||
status = dpiPool_create(g_DpiContext, userNameBuffer.ptr,
|
||||
userNameBuffer.size, passwordBuffer.ptr, passwordBuffer.size,
|
||||
dsnBuffer.ptr, dsnBuffer.size, &dpiCommonParams, &dpiCreateParams,
|
||||
&self->handle);
|
||||
Py_END_ALLOW_THREADS
|
||||
cxBuffer_Clear(&username);
|
||||
cxBuffer_Clear(&password);
|
||||
cxBuffer_Clear(&dsn);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"SessionPool_New(): create pool") < 0)
|
||||
return -1;
|
||||
cxBuffer_Clear(&userNameBuffer);
|
||||
cxBuffer_Clear(&passwordBuffer);
|
||||
cxBuffer_Clear(&dsnBuffer);
|
||||
cxBuffer_Clear(&editionBuffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
|
||||
// create the string for the pool name
|
||||
self->name = cxString_FromEncodedString(poolName, poolNameLength,
|
||||
self->environment->encoding);
|
||||
// get encodings and name
|
||||
if (dpiPool_getEncodingInfo(self->handle, &self->encodingInfo) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
self->encodingInfo.encoding =
|
||||
GetAdjustedEncoding(self->encodingInfo.encoding);
|
||||
self->encodingInfo.nencoding =
|
||||
GetAdjustedEncoding(self->encodingInfo.nencoding);
|
||||
self->name = cxString_FromEncodedString(dpiCreateParams.outPoolName,
|
||||
dpiCreateParams.outPoolNameLength, self->encodingInfo.encoding);
|
||||
if (!self->name)
|
||||
return -1;
|
||||
|
||||
// set the mode on the pool
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SPOOL, (dvoid*) &getMode, 0,
|
||||
OCI_ATTR_SPOOL_GETMODE, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"SessionPool_New(): set wait mode") < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -328,70 +303,45 @@ static int SessionPool_Init(
|
||||
// SessionPool_Free()
|
||||
// Deallocate the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void SessionPool_Free(
|
||||
udt_SessionPool *self) // session pool
|
||||
static void SessionPool_Free(udt_SessionPool *self)
|
||||
{
|
||||
if (self->handle) {
|
||||
OCISessionPoolDestroy(self->handle, self->environment->errorHandle,
|
||||
OCI_SPD_FORCE);
|
||||
OCIHandleFree(self->handle, OCI_HTYPE_SPOOL);
|
||||
dpiPool_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_XDECREF(self->name);
|
||||
Py_XDECREF(self->environment);
|
||||
Py_XDECREF(self->username);
|
||||
Py_XDECREF(self->dsn);
|
||||
Py_CLEAR(self->username);
|
||||
Py_CLEAR(self->dsn);
|
||||
Py_CLEAR(self->name);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_IsConnected()
|
||||
// Determines if the session pool object is connected to the database. If
|
||||
// not, a Python exception is raised.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_IsConnected(
|
||||
udt_SessionPool *self) // session pool
|
||||
{
|
||||
if (!self->handle) {
|
||||
PyErr_SetString(g_InterfaceErrorException, "not connected");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_Acquire()
|
||||
// Create a new connection within the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_Acquire(
|
||||
udt_SessionPool *self, // session pool
|
||||
PyObject *args, // arguments
|
||||
PyObject *keywordArgs) // keyword arguments
|
||||
static PyObject *SessionPool_Acquire(udt_SessionPool *self, PyObject *args,
|
||||
PyObject *keywordArgs)
|
||||
{
|
||||
static char *keywordList[] = { "user", "password", "cclass", "purity",
|
||||
NULL };
|
||||
PyObject *createKeywordArgs, *result, *cclassObj, *purityObj;
|
||||
"tag", "matchanytag", NULL };
|
||||
PyObject *createKeywordArgs, *result, *cclassObj, *purityObj, *tagObj;
|
||||
unsigned usernameLength, passwordLength;
|
||||
char *username, *password;
|
||||
PyObject *matchAnyTagObj;
|
||||
|
||||
// parse arguments
|
||||
username = NULL;
|
||||
password = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|s#s#OO", keywordList,
|
||||
&username, &usernameLength, &password, &passwordLength, &cclassObj,
|
||||
&purityObj))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "|s#s#OOOO",
|
||||
keywordList, &username, &usernameLength, &password,
|
||||
&passwordLength, &cclassObj, &purityObj, &tagObj, &matchAnyTagObj))
|
||||
return NULL;
|
||||
if (self->homogeneous && (username || password)) {
|
||||
if (self->homogeneous && username) {
|
||||
PyErr_SetString(g_ProgrammingErrorException,
|
||||
"pool is homogeneous. Proxy authentication is not possible.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// make sure session pool is connected
|
||||
if (SessionPool_IsConnected(self) < 0)
|
||||
return NULL;
|
||||
|
||||
// create arguments
|
||||
if (keywordArgs)
|
||||
createKeywordArgs = PyDict_Copy(keywordArgs);
|
||||
@ -414,74 +364,32 @@ static PyObject *SessionPool_Acquire(
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_InternalRelease()
|
||||
// Internal method used to release a connection back to the pool in order to
|
||||
// allow for the possibility of dropping the connection.
|
||||
// SessionPool_Drop()
|
||||
// Release a connection back to the session pool, dropping it so that a new
|
||||
// connection will be created if needed.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_InternalRelease(
|
||||
udt_SessionPool *self, // session pool
|
||||
PyObject *args, // arguments
|
||||
ub4 mode) // OCI mode to use
|
||||
static PyObject *SessionPool_Drop(udt_SessionPool *self, PyObject *args)
|
||||
{
|
||||
udt_Connection *connection;
|
||||
sword status;
|
||||
int status;
|
||||
|
||||
// connection is expected
|
||||
if (!PyArg_ParseTuple(args, "O!", &g_ConnectionType, &connection))
|
||||
return NULL;
|
||||
|
||||
// make sure session pool is connected
|
||||
if (SessionPool_IsConnected(self) < 0)
|
||||
return NULL;
|
||||
if (connection->sessionPool != self) {
|
||||
PyErr_SetString(g_ProgrammingErrorException,
|
||||
"connection not acquired with this session pool");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// attempt a rollback but if dropping the connection from the pool
|
||||
// ignore the error
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCITransRollback(connection->handle,
|
||||
connection->environment->errorHandle, OCI_DEFAULT);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"SessionPool_Release(): rollback") < 0) {
|
||||
if (mode != OCI_SESSRLS_DROPSESS)
|
||||
return NULL;
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
// release the connection
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCISessionRelease(connection->handle,
|
||||
connection->environment->errorHandle, NULL, 0, mode);
|
||||
status = dpiConn_close(connection->handle, DPI_MODE_CONN_CLOSE_DROP, NULL,
|
||||
0);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(connection->environment, status,
|
||||
"SessionPool_Release(): release session") < 0)
|
||||
return NULL;
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
|
||||
// ensure that the connection behaves as closed
|
||||
Py_DECREF(connection->sessionPool);
|
||||
connection->sessionPool = NULL;
|
||||
// mark connection as closed
|
||||
Py_CLEAR(connection->sessionPool);
|
||||
dpiConn_release(connection->handle);
|
||||
connection->handle = NULL;
|
||||
connection->release = 0;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_Drop()
|
||||
// Release a connection back to the session pool, dropping it so that a new
|
||||
// connection will be created if needed.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_Drop(
|
||||
udt_SessionPool *self, // session pool
|
||||
PyObject *args) // arguments
|
||||
{
|
||||
return SessionPool_InternalRelease(self, args, OCI_SESSRLS_DROPSESS);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -489,70 +397,205 @@ static PyObject *SessionPool_Drop(
|
||||
// SessionPool_Release()
|
||||
// Release a connection back to the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_Release(
|
||||
udt_SessionPool *self, // session pool
|
||||
PyObject *args) // arguments
|
||||
static PyObject *SessionPool_Release(udt_SessionPool *self, PyObject *args,
|
||||
PyObject *keywordArgs)
|
||||
{
|
||||
return SessionPool_InternalRelease(self, args, OCI_DEFAULT);
|
||||
static char *keywordList[] = { "connection", "tag", NULL };
|
||||
udt_Connection *connection;
|
||||
dpiConnCloseMode mode;
|
||||
udt_Buffer tagBuffer;
|
||||
PyObject *tagObj;
|
||||
int status;
|
||||
|
||||
// parse arguments
|
||||
tagObj = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "O!|O",
|
||||
keywordList, &g_ConnectionType, &connection, &tagObj))
|
||||
return NULL;
|
||||
if (cxBuffer_FromObject(&tagBuffer, tagObj,
|
||||
self->encodingInfo.encoding) < 0)
|
||||
return NULL;
|
||||
mode = (tagBuffer.size > 0) ? DPI_MODE_CONN_CLOSE_RETAG :
|
||||
DPI_MODE_CONN_CLOSE_DEFAULT;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = dpiConn_close(connection->handle, mode, (char*) tagBuffer.ptr,
|
||||
tagBuffer.size);
|
||||
Py_END_ALLOW_THREADS
|
||||
cxBuffer_Clear(&tagBuffer);
|
||||
if (status < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
|
||||
// mark connection as closed
|
||||
Py_CLEAR(connection->sessionPool);
|
||||
dpiConn_release(connection->handle);
|
||||
connection->handle = NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_GetOCIAttr()
|
||||
// Return the value for the OCI attribute.
|
||||
// SessionPool_GetAttribute()
|
||||
// Return the value for the attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_GetOCIAttr(
|
||||
udt_SessionPool *self, // session pool
|
||||
ub4 *attribute) // OCI attribute type
|
||||
static PyObject *SessionPool_GetAttribute(udt_SessionPool *self,
|
||||
int (*func)(dpiPool *pool, uint32_t *value))
|
||||
{
|
||||
sword status;
|
||||
ub4 value;
|
||||
uint32_t value;
|
||||
|
||||
// make sure session pool is connected
|
||||
if (SessionPool_IsConnected(self) < 0)
|
||||
return NULL;
|
||||
if ((*func)(self->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyInt_FromUnsignedLong(value);
|
||||
#else
|
||||
return PyInt_FromLong(value);
|
||||
#endif
|
||||
}
|
||||
|
||||
// get the value from the OCI
|
||||
status = OCIAttrGet(self->handle, OCI_HTYPE_SPOOL, &value, 0, *attribute,
|
||||
self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"SessionPool_GetOCIAttr()") < 0)
|
||||
return NULL;
|
||||
if (*attribute == OCI_ATTR_SPOOL_GETMODE)
|
||||
return PyInt_FromLong((ub1) value);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_SetAttribute()
|
||||
// Set the value of the OCI attribute.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_SetAttribute(udt_SessionPool *self, PyObject *value,
|
||||
int (*func)(dpiPool *pool, uint32_t value))
|
||||
{
|
||||
uint32_t cValue;
|
||||
|
||||
if (!PyInt_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "value must be an integer");
|
||||
return -1;
|
||||
}
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
cValue = PyInt_AsUnsignedLong(value);
|
||||
#else
|
||||
cValue = PyInt_AsLong(value);
|
||||
#endif
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
if ((*func)(self->handle, cValue) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_GetBusyCount()
|
||||
// Return the number of busy connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_GetBusyCount(udt_SessionPool *pool, void *unused)
|
||||
{
|
||||
return SessionPool_GetAttribute(pool, dpiPool_getBusyCount);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_GetGetMode()
|
||||
// Return the "get" mode for connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_GetGetMode(udt_SessionPool *pool, void *unused)
|
||||
{
|
||||
dpiPoolGetMode value;
|
||||
|
||||
if (dpiPool_getGetMode(pool->handle, &value) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_SetOCIAttr()
|
||||
// Set the value of the OCI attribute.
|
||||
// SessionPool_GetMaxLifetimeSession()
|
||||
// Return the maximum lifetime session of connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_SetOCIAttr(
|
||||
udt_SessionPool *self, // session pool
|
||||
PyObject *value, // value to set
|
||||
ub4 *attribute) // OCI attribute type
|
||||
static PyObject *SessionPool_GetMaxLifetimeSession(udt_SessionPool *pool,
|
||||
void *unused)
|
||||
{
|
||||
ub4 ociValue;
|
||||
sword status;
|
||||
return SessionPool_GetAttribute(pool, dpiPool_getMaxLifetimeSession);
|
||||
}
|
||||
|
||||
// make sure session pool is connected
|
||||
if (SessionPool_IsConnected(self) < 0)
|
||||
return -1;
|
||||
|
||||
// set the value in the OCI
|
||||
if (!PyInt_Check(value)) {
|
||||
PyErr_SetString(PyExc_TypeError, "value must be an integer");
|
||||
return -1;
|
||||
}
|
||||
ociValue = PyInt_AsLong(value);
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_GetOpenCount()
|
||||
// Return the number of open connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_GetOpenCount(udt_SessionPool *pool, void *unused)
|
||||
{
|
||||
return SessionPool_GetAttribute(pool, dpiPool_getOpenCount);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_GetStmtCacheSize()
|
||||
// Return the size of the statement cache to use in connections that are
|
||||
// acquired from the pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_GetStmtCacheSize(udt_SessionPool *pool,
|
||||
void *unused)
|
||||
{
|
||||
return SessionPool_GetAttribute(pool, dpiPool_getStmtCacheSize);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_GetTimeout()
|
||||
// Return the timeout for connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *SessionPool_GetTimeout(udt_SessionPool *pool, void *unused)
|
||||
{
|
||||
return SessionPool_GetAttribute(pool, dpiPool_getTimeout);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_SetGetMode()
|
||||
// Set the "get" mode for connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_SetGetMode(udt_SessionPool *pool, PyObject *value,
|
||||
void *unused)
|
||||
{
|
||||
dpiPoolGetMode cValue;
|
||||
|
||||
cValue = PyInt_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SPOOL, &ociValue, 0,
|
||||
*attribute, self->environment->errorHandle);
|
||||
if (Environment_CheckForError(self->environment, status,
|
||||
"SessionPool_SetOCIAttr()") < 0)
|
||||
return -1;
|
||||
if (dpiPool_setGetMode(pool->handle, cValue) < 0)
|
||||
return Error_RaiseAndReturnInt();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_SetMaxLifetimeSession()
|
||||
// Set the maximum lifetime for connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_SetMaxLifetimeSession(udt_SessionPool *pool,
|
||||
PyObject *value, void *unused)
|
||||
{
|
||||
return SessionPool_SetAttribute(pool, value,
|
||||
dpiPool_setMaxLifetimeSession);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_SetStmtCacheSize()
|
||||
// Set the default size of the statement cache used for connections that are
|
||||
// acquired from the pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_SetStmtCacheSize(udt_SessionPool *pool,
|
||||
PyObject *value, void *unused)
|
||||
{
|
||||
return SessionPool_SetAttribute(pool, value, dpiPool_setStmtCacheSize);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SessionPool_SetTimeout()
|
||||
// Set the timeout for connections in the session pool.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SessionPool_SetTimeout(udt_SessionPool *pool, PyObject *value,
|
||||
void *unused)
|
||||
{
|
||||
return SessionPool_SetAttribute(pool, value, dpiPool_setTimeout);
|
||||
}
|
||||
|
||||
|
||||
416
src/StringVar.c
416
src/StringVar.c
@ -12,373 +12,113 @@
|
||||
// Defines the routines specific to the string type.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// String type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
char *data;
|
||||
} udt_StringVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of string variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int StringVar_Initialize(udt_StringVar*, udt_Cursor*);
|
||||
static int StringVar_SetValue(udt_StringVar*, unsigned, PyObject*);
|
||||
static PyObject *StringVar_GetValue(udt_StringVar*, unsigned);
|
||||
static int StringVar_PostDefine(udt_StringVar*);
|
||||
static ub4 StringVar_GetBufferSize(udt_StringVar*);
|
||||
static PyObject *RowidVar_GetValue(udt_Variable*, dpiData*);
|
||||
static PyObject *StringVar_GetValue(udt_Variable*, dpiData*);
|
||||
static int RowidVar_SetValue(udt_Variable*, uint32_t, dpiData*, PyObject*);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_StringVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.STRING", // tp_name
|
||||
sizeof(udt_StringVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_NCharVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.NCHAR", // tp_name
|
||||
sizeof(udt_StringVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_FixedCharVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.FIXED_CHAR", // tp_name
|
||||
sizeof(udt_StringVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_FixedNCharVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.FIXED_NCHAR", // tp_name
|
||||
sizeof(udt_StringVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_RowidVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.ROWID", // tp_name
|
||||
sizeof(udt_StringVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
static PyTypeObject g_BinaryVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.BINARY", // tp_name
|
||||
sizeof(udt_StringVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
DECLARE_VARIABLE_TYPE(g_StringVarType, STRING)
|
||||
DECLARE_VARIABLE_TYPE(g_NCharVarType, NCHAR)
|
||||
DECLARE_VARIABLE_TYPE(g_FixedCharVarType, FIXED_CHAR)
|
||||
DECLARE_VARIABLE_TYPE(g_FixedNCharVarType, FIXED_NCHAR)
|
||||
DECLARE_VARIABLE_TYPE(g_RowidVarType, ROWID)
|
||||
DECLARE_VARIABLE_TYPE(g_BinaryVarType, BINARY)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_String = {
|
||||
(InitializeProc) StringVar_Initialize,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
(SetValueProc) Variable_SetValueBytes,
|
||||
(GetValueProc) StringVar_GetValue,
|
||||
(GetBufferSizeProc) StringVar_GetBufferSize,
|
||||
&g_StringVarType, // Python type
|
||||
SQLT_CHR, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
4000, // element length (default)
|
||||
1, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_VARCHAR, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
4000 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_NationalCharString = {
|
||||
(InitializeProc) StringVar_Initialize,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) StringVar_PostDefine,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
(SetValueProc) Variable_SetValueBytes,
|
||||
(GetValueProc) StringVar_GetValue,
|
||||
(GetBufferSizeProc) StringVar_GetBufferSize,
|
||||
&g_NCharVarType, // Python type
|
||||
SQLT_CHR, // Oracle type
|
||||
SQLCS_NCHAR, // charset form
|
||||
4000, // element length (default)
|
||||
1, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_NVARCHAR, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
4000 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_FixedChar = {
|
||||
(InitializeProc) StringVar_Initialize,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
(SetValueProc) Variable_SetValueBytes,
|
||||
(GetValueProc) StringVar_GetValue,
|
||||
(GetBufferSizeProc) StringVar_GetBufferSize,
|
||||
&g_FixedCharVarType, // Python type
|
||||
SQLT_AFC, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
2000, // element length (default)
|
||||
1, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_CHAR, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
2000 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_FixedNationalChar = {
|
||||
(InitializeProc) StringVar_Initialize,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) StringVar_PostDefine,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
(SetValueProc) Variable_SetValueBytes,
|
||||
(GetValueProc) StringVar_GetValue,
|
||||
(GetBufferSizeProc) StringVar_GetBufferSize,
|
||||
&g_FixedNCharVarType, // Python type
|
||||
SQLT_AFC, // Oracle type
|
||||
SQLCS_NCHAR, // charset form
|
||||
2000, // element length (default)
|
||||
1, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_NCHAR, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
2000 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_Rowid = {
|
||||
(InitializeProc) StringVar_Initialize,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
(GetValueProc) StringVar_GetValue,
|
||||
(GetBufferSizeProc) StringVar_GetBufferSize,
|
||||
(SetValueProc) RowidVar_SetValue,
|
||||
(GetValueProc) RowidVar_GetValue,
|
||||
&g_RowidVarType, // Python type
|
||||
SQLT_CHR, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
18, // element length (default)
|
||||
1, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_ROWID, // Oracle type
|
||||
DPI_NATIVE_TYPE_ROWID, // native type
|
||||
18 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
static udt_VariableType vt_Binary = {
|
||||
(InitializeProc) StringVar_Initialize,
|
||||
(FinalizeProc) NULL,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) StringVar_SetValue,
|
||||
(SetValueProc) Variable_SetValueBytes,
|
||||
(GetValueProc) StringVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_BinaryVarType, // Python type
|
||||
SQLT_BIN, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
4000, // element length (default)
|
||||
0, // is character data
|
||||
1, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
DPI_ORACLE_TYPE_RAW, // Oracle type
|
||||
DPI_NATIVE_TYPE_BYTES, // native type
|
||||
4000 // element length (default)
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StringVar_Initialize()
|
||||
// Initialize the variable.
|
||||
// RowidVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int StringVar_Initialize(
|
||||
udt_StringVar *var, // variable to initialize
|
||||
udt_Cursor *cursor) // cursor to use
|
||||
static PyObject *RowidVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
ub4 i;
|
||||
uint32_t rowidLength;
|
||||
const char *rowid;
|
||||
|
||||
var->actualLength = (ACTUAL_LENGTH_TYPE *)
|
||||
PyMem_Malloc(var->allocatedElements * sizeof(ACTUAL_LENGTH_TYPE));
|
||||
if (!var->actualLength) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < var->allocatedElements; i++)
|
||||
var->actualLength[i] = 0;
|
||||
|
||||
return 0;
|
||||
if (dpiRowid_getStringValue(data->value.asRowid, &rowid, &rowidLength) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return cxString_FromEncodedString(rowid, rowidLength,
|
||||
var->connection->encodingInfo.encoding);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StringVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
// RowidVar_SetValue()
|
||||
// Rowid values cannot be set.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int StringVar_SetValue(
|
||||
udt_StringVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
static int RowidVar_SetValue(udt_Variable *var, uint32_t pos, dpiData *data,
|
||||
PyObject *value)
|
||||
{
|
||||
udt_Buffer buffer;
|
||||
char *encoding;
|
||||
|
||||
// determine which encoding should be used
|
||||
if (var->type->charsetForm == SQLCS_NCHAR)
|
||||
encoding = var->environment->nencoding;
|
||||
else encoding = var->environment->encoding;
|
||||
|
||||
// populate the buffer and confirm the maximum size is not exceeded
|
||||
if (cxBuffer_FromObject(&buffer, value, encoding) < 0)
|
||||
return -1;
|
||||
|
||||
// ensure that the buffer is large enough
|
||||
if (buffer.size > var->bufferSize) {
|
||||
if (Variable_Resize( (udt_Variable*) var,
|
||||
(unsigned) buffer.numCharacters) < 0) {
|
||||
cxBuffer_Clear(&buffer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// keep a copy of the string
|
||||
var->actualLength[pos] = (ACTUAL_LENGTH_TYPE) buffer.size;
|
||||
if (buffer.size)
|
||||
memcpy(var->data + var->bufferSize * pos, buffer.ptr, buffer.size);
|
||||
cxBuffer_Clear(&buffer);
|
||||
|
||||
return 0;
|
||||
PyErr_SetString(g_NotSupportedErrorException,
|
||||
"setting rowid variables, use a string variable instead");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -386,54 +126,18 @@ static int StringVar_SetValue(
|
||||
// StringVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *StringVar_GetValue(
|
||||
udt_StringVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
static PyObject *StringVar_GetValue(udt_Variable *var, dpiData *data)
|
||||
{
|
||||
char *data;
|
||||
dpiBytes *bytes;
|
||||
|
||||
data = var->data + pos * var->bufferSize;
|
||||
bytes = &data->value.asBytes;
|
||||
if (var->type == &vt_Binary)
|
||||
return PyBytes_FromStringAndSize(data, var->actualLength[pos]);
|
||||
if (var->type == &vt_FixedNationalChar
|
||||
|| var->type == &vt_NationalCharString)
|
||||
return PyUnicode_Decode(data, var->actualLength[pos],
|
||||
var->environment->nencoding, NULL);
|
||||
return cxString_FromEncodedString(data, var->actualLength[pos],
|
||||
var->environment->encoding);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StringVar_PostDefine()
|
||||
// Set the character set information when values are fetched from this
|
||||
// variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int StringVar_PostDefine(
|
||||
udt_StringVar *var) // variable to initialize
|
||||
{
|
||||
sword status;
|
||||
|
||||
status = OCIAttrSet(var->defineHandle, OCI_HTYPE_DEFINE,
|
||||
&var->type->charsetForm, 0, OCI_ATTR_CHARSET_FORM,
|
||||
var->environment->errorHandle);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"StringVar_PostDefine(): setting charset form") < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// StringVar_GetBufferSize()
|
||||
// Returns the buffer size to use for the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static ub4 StringVar_GetBufferSize(
|
||||
udt_StringVar* self) // variable to get buffer size for
|
||||
{
|
||||
if (self->type->isCharacterData)
|
||||
return self->size * self->environment->maxBytesPerCharacter;
|
||||
return self->size;
|
||||
return PyBytes_FromStringAndSize(bytes->ptr, bytes->length);
|
||||
else if (var->type == &vt_FixedNationalChar ||
|
||||
var->type == &vt_NationalCharString)
|
||||
return PyUnicode_Decode(bytes->ptr, bytes->length, bytes->encoding,
|
||||
NULL);
|
||||
return cxString_FromEncodedString(bytes->ptr, bytes->length,
|
||||
bytes->encoding);
|
||||
}
|
||||
|
||||
|
||||
@ -17,24 +17,22 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
OCISubscription *handle;
|
||||
dpiSubscr *handle;
|
||||
udt_Connection *connection;
|
||||
PyObject *callback;
|
||||
ub4 namespace;
|
||||
ub4 protocol;
|
||||
ub4 port;
|
||||
ub4 timeout;
|
||||
ub4 operations;
|
||||
ub4 qos;
|
||||
ub4 cqqos;
|
||||
ub4 rowids;
|
||||
ub4 id;
|
||||
uint32_t namespace;
|
||||
uint32_t protocol;
|
||||
uint32_t port;
|
||||
uint32_t timeout;
|
||||
uint32_t operations;
|
||||
uint32_t qos;
|
||||
uint32_t id;
|
||||
} udt_Subscription;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
udt_Subscription *subscription;
|
||||
ub4 type;
|
||||
dpiEventType type;
|
||||
PyObject *dbname;
|
||||
PyObject *tables;
|
||||
PyObject *queries;
|
||||
@ -44,19 +42,19 @@ typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *name;
|
||||
PyObject *rows;
|
||||
ub4 operation;
|
||||
dpiOpCode operation;
|
||||
} udt_MessageTable;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *rowid;
|
||||
ub4 operation;
|
||||
dpiOpCode operation;
|
||||
} udt_MessageRow;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
ub8 id;
|
||||
ub4 operation;
|
||||
uint64_t id;
|
||||
dpiOpCode operation;
|
||||
PyObject *tables;
|
||||
} udt_MessageQuery;
|
||||
|
||||
@ -85,8 +83,6 @@ static PyMemberDef g_SubscriptionTypeMembers[] = {
|
||||
{ "timeout", T_INT, offsetof(udt_Subscription, timeout), READONLY },
|
||||
{ "operations", T_INT, offsetof(udt_Subscription, operations), READONLY },
|
||||
{ "qos", T_INT, offsetof(udt_Subscription, qos), READONLY },
|
||||
{ "cqqos", T_INT, offsetof(udt_Subscription, cqqos), READONLY },
|
||||
{ "rowids", T_BOOL, offsetof(udt_Subscription, rowids), READONLY },
|
||||
{ "id", T_INT, offsetof(udt_Subscription, id), READONLY },
|
||||
{ NULL }
|
||||
};
|
||||
@ -362,30 +358,12 @@ static PyTypeObject g_MessageQueryType = {
|
||||
// MessageRow_Initialize()
|
||||
// Initialize a new message row with the information from the descriptor.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MessageRow_Initialize(
|
||||
udt_MessageRow *self, // object to initialize
|
||||
udt_Environment *env, // environment to use
|
||||
dvoid *descriptor) // descriptor to get information from
|
||||
static int MessageRow_Initialize(udt_MessageRow *self, const char *encoding,
|
||||
dpiSubscrMessageRow *row)
|
||||
{
|
||||
ub4 rowidLength;
|
||||
sword status;
|
||||
char *rowid;
|
||||
|
||||
// determine operation
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_ROW_CHDES, &self->operation,
|
||||
NULL, OCI_ATTR_CHDES_ROW_OPFLAGS, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageRow_Initialize(): get operation") < 0)
|
||||
return -1;
|
||||
|
||||
// determine table name
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_ROW_CHDES, &rowid, &rowidLength,
|
||||
OCI_ATTR_CHDES_ROW_ROWID, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageRow_Initialize(): get rowid") < 0)
|
||||
return -1;
|
||||
self->rowid = cxString_FromEncodedString(rowid, rowidLength,
|
||||
env->encoding);
|
||||
self->operation = row->operation;
|
||||
self->rowid = cxString_FromEncodedString(row->rowid, row->rowidLength,
|
||||
encoding);
|
||||
if (!self->rowid)
|
||||
return -1;
|
||||
|
||||
@ -397,70 +375,25 @@ static int MessageRow_Initialize(
|
||||
// MessageTable_Initialize()
|
||||
// Initialize a new message table with the information from the descriptor.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MessageTable_Initialize(
|
||||
udt_MessageTable *self, // object to initialize
|
||||
udt_Environment *env, // environment to use
|
||||
dvoid *descriptor) // descriptor to get information from
|
||||
static int MessageTable_Initialize(udt_MessageTable *self,
|
||||
const char *encoding, dpiSubscrMessageTable *table)
|
||||
{
|
||||
dvoid **rowDescriptor, *indicator;
|
||||
udt_MessageRow *row;
|
||||
ub4 nameLength;
|
||||
boolean exists;
|
||||
sb4 numRows, i;
|
||||
OCIColl *rows;
|
||||
sword status;
|
||||
char *name;
|
||||
uint32_t i;
|
||||
|
||||
// determine operation
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_TABLE_CHDES, &self->operation,
|
||||
NULL, OCI_ATTR_CHDES_TABLE_OPFLAGS, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageTable_Initialize(): get operation") < 0)
|
||||
return -1;
|
||||
|
||||
// determine table name
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_TABLE_CHDES, &name, &nameLength,
|
||||
OCI_ATTR_CHDES_TABLE_NAME, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageTable_Initialize(): get table name") < 0)
|
||||
return -1;
|
||||
self->name = cxString_FromEncodedString(name, nameLength, env->encoding);
|
||||
if (!self->name)
|
||||
return -1;
|
||||
|
||||
// if change invalidated all rows, nothing to do
|
||||
if (self->operation & OCI_OPCODE_ALLROWS)
|
||||
return 0;
|
||||
|
||||
// determine rows collection
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_TABLE_CHDES, &rows, NULL,
|
||||
OCI_ATTR_CHDES_TABLE_ROW_CHANGES, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageTable_Initialize(): get rows collection") < 0)
|
||||
return -1;
|
||||
|
||||
// determine number of rows in collection
|
||||
status = OCICollSize(env->handle, env->errorHandle, rows, &numRows);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageTable_Initialize(): get size of rows collection") < 0)
|
||||
return -1;
|
||||
|
||||
// populate the rows attribute
|
||||
self->rows = PyList_New(numRows);
|
||||
self->operation = table->operation;
|
||||
self->name = cxString_FromEncodedString(table->name, table->nameLength,
|
||||
encoding);
|
||||
self->rows = PyList_New(table->numRows);
|
||||
if (!self->rows)
|
||||
return -1;
|
||||
for (i = 0; i < numRows; i++) {
|
||||
status = OCICollGetElem(env->handle, env->errorHandle, rows, i,
|
||||
&exists, (dvoid*) &rowDescriptor, &indicator);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageTable_Initialize(): get element from collection") < 0)
|
||||
return -1;
|
||||
for (i = 0; i < table->numRows; i++) {
|
||||
row = (udt_MessageRow*)
|
||||
g_MessageRowType.tp_alloc(&g_MessageRowType, 0);
|
||||
if (!row)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->rows, i, (PyObject*) row);
|
||||
if (MessageRow_Initialize(row, env, *rowDescriptor) < 0)
|
||||
if (MessageRow_Initialize(row, encoding, &table->rows[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -472,68 +405,24 @@ static int MessageTable_Initialize(
|
||||
// MessageQuery_Initialize()
|
||||
// Initialize a new message query with the information from the descriptor.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int MessageQuery_Initialize(
|
||||
udt_MessageQuery *self, // object to initialize
|
||||
udt_Environment *env, // environment to use
|
||||
dvoid *descriptor) // descriptor to get information from
|
||||
static int MessageQuery_Initialize(udt_MessageQuery *self,
|
||||
const char *encoding, dpiSubscrMessageQuery *query)
|
||||
{
|
||||
dvoid **tableDescriptor, *indicator;
|
||||
udt_MessageTable *table;
|
||||
sb4 numTables, i;
|
||||
OCIColl *tables;
|
||||
boolean exists;
|
||||
sword status;
|
||||
uint32_t i;
|
||||
|
||||
// determine query id
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_CQDES, &self->id,
|
||||
NULL, OCI_ATTR_CQDES_QUERYID, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageQuery_Initialize(): get query id") < 0)
|
||||
return -1;
|
||||
|
||||
// determine operation
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_CQDES, &self->operation,
|
||||
NULL, OCI_ATTR_CQDES_OPERATION, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageQuery_Initialize(): get operation") < 0)
|
||||
return -1;
|
||||
|
||||
// determine table collection
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_CQDES, &tables, NULL,
|
||||
OCI_ATTR_CQDES_TABLE_CHANGES, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageQuery_Initialize(): get tables collection") < 0)
|
||||
return -1;
|
||||
|
||||
// determine number of tables
|
||||
if (!tables)
|
||||
numTables = 0;
|
||||
else {
|
||||
status = OCICollSize(env->handle, env->errorHandle, tables,
|
||||
&numTables);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageQuery_Initialize(): get size of collection") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create list to hold results
|
||||
self->tables = PyList_New(numTables);
|
||||
self->id = query->id;
|
||||
self->operation = query->operation;
|
||||
self->tables = PyList_New(query->numTables);
|
||||
if (!self->tables)
|
||||
return -1;
|
||||
|
||||
// populate each entry with a message table instance
|
||||
for (i = 0; i < numTables; i++) {
|
||||
status = OCICollGetElem(env->handle, env->errorHandle, tables, i,
|
||||
&exists, (dvoid*) &tableDescriptor, &indicator);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"MessageQuery_Initialize(): get element from collection") < 0)
|
||||
return -1;
|
||||
for (i = 0; i < query->numTables; i++) {
|
||||
table = (udt_MessageTable*)
|
||||
g_MessageTableType.tp_alloc(&g_MessageTableType, 0);
|
||||
if (!table)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->tables, i, (PyObject*) table);
|
||||
if (MessageTable_Initialize(table, env, *tableDescriptor) < 0)
|
||||
if (MessageTable_Initialize(table, encoding, &query->tables[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -545,124 +434,55 @@ static int MessageQuery_Initialize(
|
||||
// Message_Initialize()
|
||||
// Initialize a new message with the information from the descriptor.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Message_Initialize(
|
||||
udt_Message *self, // object to initialize
|
||||
udt_Environment *env, // environment to use
|
||||
udt_Subscription *subscription, // associated subscription for message
|
||||
dvoid *descriptor) // descriptor to get information from
|
||||
static int Message_Initialize(udt_Message *self,
|
||||
udt_Subscription *subscription, dpiSubscrMessage *message)
|
||||
{
|
||||
dvoid **tableDescriptor, *indicator, **queryDescriptor;
|
||||
sb4 numTables, numQueries, i;
|
||||
OCIColl *tables, *queries;
|
||||
udt_MessageTable *table;
|
||||
udt_MessageQuery *query;
|
||||
ub4 dbnameLength;
|
||||
boolean exists;
|
||||
char *dbname;
|
||||
sword status;
|
||||
const char *encoding;
|
||||
uint32_t i;
|
||||
|
||||
// assign reference to associated subscription
|
||||
Py_INCREF(subscription);
|
||||
self->subscription = subscription;
|
||||
|
||||
// determine type
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_CHDES, &self->type, NULL,
|
||||
OCI_ATTR_CHDES_NFYTYPE, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get type") < 0)
|
||||
return -1;
|
||||
|
||||
// determine database name
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_CHDES, &dbname, &dbnameLength,
|
||||
OCI_ATTR_CHDES_DBNAME, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get database name") < 0)
|
||||
return -1;
|
||||
self->dbname = cxString_FromEncodedString(dbname, dbnameLength,
|
||||
env->encoding);
|
||||
encoding = subscription->connection->encodingInfo.encoding;
|
||||
self->type = message->eventType;
|
||||
self->dbname = cxString_FromEncodedString(message->dbName,
|
||||
message->dbNameLength, encoding);
|
||||
if (!self->dbname)
|
||||
return -1;
|
||||
|
||||
if (self->type == OCI_EVENT_OBJCHANGE) {
|
||||
// determine table collection
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_CHDES, &tables, NULL,
|
||||
OCI_ATTR_CHDES_TABLE_CHANGES, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get tables collection") < 0)
|
||||
return -1;
|
||||
|
||||
// determine number of tables
|
||||
if (!tables)
|
||||
numTables = 0;
|
||||
else {
|
||||
status = OCICollSize(env->handle, env->errorHandle, tables,
|
||||
&numTables);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get size of collection") < 0)
|
||||
switch (message->eventType) {
|
||||
case DPI_EVENT_OBJCHANGE:
|
||||
self->tables = PyList_New(message->numTables);
|
||||
if (!self->tables)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create list to hold results
|
||||
self->tables = PyList_New(numTables);
|
||||
if (!self->tables)
|
||||
return -1;
|
||||
|
||||
// populate each entry with a message table instance
|
||||
for (i = 0; i < numTables; i++) {
|
||||
status = OCICollGetElem(env->handle, env->errorHandle, tables, i,
|
||||
&exists, (dvoid*) &tableDescriptor, &indicator);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get element from collection") < 0)
|
||||
for (i = 0; i < message->numTables; i++) {
|
||||
table = (udt_MessageTable*)
|
||||
g_MessageTableType.tp_alloc(&g_MessageTableType, 0);
|
||||
if (!table)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->tables, i, (PyObject*) table);
|
||||
if (MessageTable_Initialize(table, encoding,
|
||||
&message->tables[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case DPI_EVENT_QUERYCHANGE:
|
||||
self->queries = PyList_New(message->numQueries);
|
||||
if (!self->queries)
|
||||
return -1;
|
||||
table = (udt_MessageTable*)
|
||||
g_MessageTableType.tp_alloc(&g_MessageTableType, 0);
|
||||
if (!table)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->tables, i, (PyObject*) table);
|
||||
if (MessageTable_Initialize(table, env, *tableDescriptor) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->type == OCI_EVENT_QUERYCHANGE) {
|
||||
// determine query collection
|
||||
status = OCIAttrGet(descriptor, OCI_DTYPE_CHDES, &queries, NULL,
|
||||
OCI_ATTR_CHDES_QUERIES, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get queries collection") < 0)
|
||||
return -1;
|
||||
|
||||
// determine number of queries
|
||||
if (!queries)
|
||||
numQueries = 0;
|
||||
else {
|
||||
status = OCICollSize(env->handle, env->errorHandle, queries,
|
||||
&numQueries);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get size of collection") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create list to hold results
|
||||
self->queries = PyList_New(numQueries);
|
||||
if (!self->queries)
|
||||
return -1;
|
||||
|
||||
// populate each entry with a message query instance
|
||||
for (i = 0; i < numQueries; i++) {
|
||||
status = OCICollGetElem(env->handle, env->errorHandle, queries, i,
|
||||
&exists, (dvoid*) &queryDescriptor, &indicator);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Message_Initialize(): get element from collection") < 0)
|
||||
return -1;
|
||||
query = (udt_MessageQuery*)
|
||||
g_MessageQueryType.tp_alloc(&g_MessageQueryType, 0);
|
||||
if (!query)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->queries, i, (PyObject*) query);
|
||||
if (MessageQuery_Initialize(query, env, *queryDescriptor) < 0)
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < message->numQueries; i++) {
|
||||
query = (udt_MessageQuery*)
|
||||
g_MessageQueryType.tp_alloc(&g_MessageQueryType, 0);
|
||||
if (!query)
|
||||
return -1;
|
||||
PyList_SET_ITEM(self->queries, i, (PyObject*) query);
|
||||
if (MessageQuery_Initialize(query, encoding,
|
||||
&message->queries[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -673,26 +493,24 @@ static int Message_Initialize(
|
||||
// Subscription_CallbackHandler()
|
||||
// Routine that performs the actual call.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Subscription_CallbackHandler(
|
||||
udt_Subscription *self, // subscription object
|
||||
udt_Environment *env, // environment to use
|
||||
dvoid *descriptor) // descriptor to get information from
|
||||
static int Subscription_CallbackHandler(udt_Subscription *self,
|
||||
dpiSubscrMessage *message)
|
||||
{
|
||||
PyObject *result, *args;
|
||||
udt_Message *message;
|
||||
udt_Message *messageObj;
|
||||
|
||||
// create the message
|
||||
message = (udt_Message*) g_MessageType.tp_alloc(&g_MessageType, 0);
|
||||
if (!message)
|
||||
messageObj = (udt_Message*) g_MessageType.tp_alloc(&g_MessageType, 0);
|
||||
if (!messageObj)
|
||||
return -1;
|
||||
if (Message_Initialize(message, env, self, descriptor) < 0) {
|
||||
Py_DECREF(message);
|
||||
if (Message_Initialize(messageObj, self, message) < 0) {
|
||||
Py_DECREF(messageObj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create the arguments for the call
|
||||
args = PyTuple_Pack(1, message);
|
||||
Py_DECREF(message);
|
||||
args = PyTuple_Pack(1, messageObj);
|
||||
Py_DECREF(messageObj);
|
||||
if (!args)
|
||||
return -1;
|
||||
|
||||
@ -711,192 +529,35 @@ static int Subscription_CallbackHandler(
|
||||
// Subscription_Callback()
|
||||
// Routine that is called when a callback needs to be invoked.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void Subscription_Callback(
|
||||
udt_Subscription *self, // subscription object
|
||||
OCISubscription *handle, // subscription handle
|
||||
dvoid *payload, // payload
|
||||
ub4 *payloadLength, // payload length
|
||||
dvoid *descriptor, // descriptor
|
||||
ub4 mode) // mode used
|
||||
static void Subscription_Callback(udt_Subscription *self,
|
||||
dpiSubscrMessage *message)
|
||||
{
|
||||
#ifdef WITH_THREAD
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
#endif
|
||||
udt_Environment *env;
|
||||
|
||||
// perform the call
|
||||
env = Environment_NewFromScratch(0, 0, NULL, NULL);
|
||||
if (!env)
|
||||
if (message->errorInfo) {
|
||||
Error_RaiseFromInfo(message->errorInfo);
|
||||
PyErr_Print();
|
||||
} else if (Subscription_CallbackHandler(self, message) < 0)
|
||||
PyErr_Print();
|
||||
else {
|
||||
if (Subscription_CallbackHandler(self, env, descriptor) < 0)
|
||||
PyErr_Print();
|
||||
Py_DECREF(env);
|
||||
}
|
||||
|
||||
// restore thread state, if necessary
|
||||
#ifdef WITH_THREAD
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Subscription_Register()
|
||||
// Register the subscription.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int Subscription_Register(
|
||||
udt_Subscription *self) // subscription to register
|
||||
{
|
||||
udt_Environment *env;
|
||||
ub4 qosFlags;
|
||||
sword status;
|
||||
|
||||
// create the subscription handle
|
||||
env = self->connection->environment;
|
||||
status = OCIHandleAlloc(env->handle, (dvoid**) &self->handle,
|
||||
OCI_HTYPE_SUBSCRIPTION, 0, 0);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): allocate handle") < 0)
|
||||
return -1;
|
||||
|
||||
// set the namespace
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) &self->namespace, sizeof(ub4), OCI_ATTR_SUBSCR_NAMESPACE,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set namespace") < 0)
|
||||
return -1;
|
||||
|
||||
// set the protocol
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) &self->protocol, sizeof(ub4), OCI_ATTR_SUBSCR_RECPTPROTO,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set protocol") < 0)
|
||||
return -1;
|
||||
|
||||
// set the timeout
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) &self->timeout, sizeof(ub4), OCI_ATTR_SUBSCR_TIMEOUT,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set timeout") < 0)
|
||||
return -1;
|
||||
|
||||
// set the TCP port used on client to listen for callback from DB server
|
||||
if (self->port > 0) {
|
||||
status = OCIAttrSet(env->handle, OCI_HTYPE_ENV,
|
||||
(dvoid*) &(self->port), (ub4) 0, OCI_ATTR_SUBSCR_PORTNO,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set port") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set the context for the callback
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) self, 0, OCI_ATTR_SUBSCR_CTX, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set context") < 0)
|
||||
return -1;
|
||||
|
||||
// set the callback, if applicable
|
||||
if (self->callback) {
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) Subscription_Callback, 0, OCI_ATTR_SUBSCR_CALLBACK,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set callback") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set suscription QOS
|
||||
qosFlags = 0;
|
||||
if (self->qos & CX_SUBSCR_QOS_RELIABLE)
|
||||
qosFlags |= OCI_SUBSCR_QOS_RELIABLE;
|
||||
if (self->qos & CX_SUBSCR_QOS_DEREG_NFY)
|
||||
qosFlags |= OCI_SUBSCR_QOS_PURGE_ON_NTFN;
|
||||
if (qosFlags) {
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) &qosFlags, sizeof(ub4), OCI_ATTR_SUBSCR_QOSFLAGS,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set qos flags") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set subscription change notification QOS flags
|
||||
qosFlags = 0;
|
||||
if (self->qos & CX_SUBSCR_QOS_QUERY)
|
||||
qosFlags |= OCI_SUBSCR_CQ_QOS_QUERY;
|
||||
if (self->qos & CX_SUBSCR_QOS_BEST_EFFORT)
|
||||
qosFlags |= OCI_SUBSCR_CQ_QOS_BEST_EFFORT;
|
||||
if (qosFlags) {
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) &qosFlags, sizeof(ub4), OCI_ATTR_SUBSCR_CQ_QOSFLAGS,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set cq qos flags") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set whether or not rowids are desired
|
||||
if (self->qos & CX_SUBSCR_QOS_ROWIDS) {
|
||||
self->rowids = 1;
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) &self->rowids, sizeof(ub4), OCI_ATTR_CHNF_ROWIDS,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set rowids") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set which operations are desired
|
||||
status = OCIAttrSet(self->handle, OCI_HTYPE_SUBSCRIPTION,
|
||||
(dvoid*) &self->operations, sizeof(ub4), OCI_ATTR_CHNF_OPERATIONS,
|
||||
env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): set operations") < 0)
|
||||
return -1;
|
||||
|
||||
// register the subscription
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCISubscriptionRegister(self->connection->handle,
|
||||
&self->handle, 1, env->errorHandle, OCI_DEFAULT);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): register") < 0)
|
||||
return -1;
|
||||
|
||||
// get the registration id
|
||||
status = OCIAttrGet(self->handle, OCI_HTYPE_SUBSCRIPTION, &self->id,
|
||||
NULL, OCI_ATTR_SUBSCR_CQ_REGID, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_Register(): get registration id") < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Subscription_New()
|
||||
// Allocate a new subscription object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_Subscription *Subscription_New(
|
||||
udt_Connection *connection, // connection object
|
||||
ub4 namespace, // namespace to use
|
||||
ub4 protocol, // protocol to use
|
||||
ub4 port, // client port for callbacks
|
||||
PyObject *callback, // callback routine
|
||||
ub4 timeout, // timeout (in seconds)
|
||||
ub4 operations, // operations to notify
|
||||
ub4 qos, // QOS flags
|
||||
ub4 cqqos, // change notification QOS flags
|
||||
int rowids) // retrieve rowids?
|
||||
static udt_Subscription *Subscription_New(udt_Connection *connection,
|
||||
uint32_t namespace, uint32_t protocol, uint32_t port,
|
||||
PyObject *callback, uint32_t timeout, uint32_t operations,
|
||||
uint32_t qos)
|
||||
{
|
||||
dpiSubscrCreateParams params;
|
||||
udt_Subscription *self;
|
||||
|
||||
self = (udt_Subscription*)
|
||||
@ -911,15 +572,26 @@ static udt_Subscription *Subscription_New(
|
||||
self->protocol = protocol;
|
||||
self->port = port;
|
||||
self->timeout = timeout;
|
||||
self->rowids = rowids;
|
||||
self->operations = operations;
|
||||
self->qos = qos | cqqos;
|
||||
if (rowids)
|
||||
self->qos |= CX_SUBSCR_QOS_ROWIDS;
|
||||
else if (qos & CX_SUBSCR_QOS_ROWIDS)
|
||||
self->rowids = 1;
|
||||
self->cqqos = cqqos;
|
||||
if (Subscription_Register(self) < 0) {
|
||||
self->qos = qos;
|
||||
|
||||
if (dpiContext_initSubscrCreateParams(g_DpiContext, ¶ms) < 0) {
|
||||
Error_RaiseAndReturnNull();
|
||||
return NULL;
|
||||
}
|
||||
params.subscrNamespace = namespace;
|
||||
params.protocol = protocol;
|
||||
params.portNumber = port;
|
||||
if (callback) {
|
||||
params.callback = (dpiSubscrCallback) Subscription_Callback;
|
||||
params.callbackContext = self;
|
||||
}
|
||||
params.timeout = timeout;
|
||||
params.operations = operations;
|
||||
params.qos = qos;
|
||||
if (dpiConn_newSubscription(connection->handle, ¶ms, &self->handle,
|
||||
&self->id) < 0) {
|
||||
Error_RaiseAndReturnNull();
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
@ -932,13 +604,12 @@ static udt_Subscription *Subscription_New(
|
||||
// Subscription_Free()
|
||||
// Free the memory associated with a subscription.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void Subscription_Free(
|
||||
udt_Subscription *self) // subscription to free
|
||||
static void Subscription_Free(udt_Subscription *self)
|
||||
{
|
||||
if (self->handle)
|
||||
OCISubscriptionUnRegister(self->connection->handle,
|
||||
self->handle, self->connection->environment->errorHandle,
|
||||
OCI_DEFAULT);
|
||||
if (self->handle) {
|
||||
dpiSubscr_release(self->handle);
|
||||
self->handle = NULL;
|
||||
}
|
||||
Py_CLEAR(self->connection);
|
||||
Py_CLEAR(self->callback);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
@ -949,8 +620,7 @@ static void Subscription_Free(
|
||||
// Subscription_Repr()
|
||||
// Return a string representation of the subscription.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Subscription_Repr(
|
||||
udt_Subscription *subscription) // subscription to repr
|
||||
static PyObject *Subscription_Repr(udt_Subscription *subscription)
|
||||
{
|
||||
PyObject *connectionRepr, *module, *name, *result, *format, *formatArgs;
|
||||
|
||||
@ -986,16 +656,15 @@ static PyObject *Subscription_Repr(
|
||||
// Subscription_RegisterQuery()
|
||||
// Register a query for database change notification.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Subscription_RegisterQuery(
|
||||
udt_Subscription *self, // subscription to use
|
||||
PyObject *args) // arguments
|
||||
static PyObject *Subscription_RegisterQuery(udt_Subscription *self,
|
||||
PyObject *args)
|
||||
{
|
||||
PyObject *statement, *executeArgs;
|
||||
udt_Buffer statementBuffer;
|
||||
udt_Environment *env;
|
||||
uint32_t numQueryColumns;
|
||||
udt_Cursor *cursor;
|
||||
sword status;
|
||||
ub8 queryid;
|
||||
uint64_t queryId;
|
||||
int status;
|
||||
|
||||
// parse arguments
|
||||
executeArgs = NULL;
|
||||
@ -1011,29 +680,22 @@ static PyObject *Subscription_RegisterQuery(
|
||||
}
|
||||
|
||||
// create cursor to perform query
|
||||
env = self->connection->environment;
|
||||
cursor = (udt_Cursor*) Connection_NewCursor(self->connection, NULL, NULL);
|
||||
cursor = (udt_Cursor*) PyObject_CallMethod((PyObject*) self->connection,
|
||||
"cursor", NULL);
|
||||
if (!cursor)
|
||||
return NULL;
|
||||
|
||||
// allocate the handle so the subscription handle can be set
|
||||
if (Cursor_AllocateHandle(cursor) < 0) {
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// prepare the statement for execution
|
||||
if (cxBuffer_FromObject(&statementBuffer, statement,
|
||||
env->encoding) < 0) {
|
||||
self->connection->encodingInfo.encoding) < 0) {
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
status = OCIStmtPrepare(cursor->handle, env->errorHandle,
|
||||
(text*) statementBuffer.ptr, (ub4) statementBuffer.size,
|
||||
OCI_NTV_SYNTAX, OCI_DEFAULT);
|
||||
status = dpiSubscr_prepareStmt(self->handle, statementBuffer.ptr,
|
||||
statementBuffer.size, &cursor->handle);
|
||||
cxBuffer_Clear(&statementBuffer);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_RegisterQuery(): prepare statement") < 0) {
|
||||
if (status < 0) {
|
||||
Error_RaiseAndReturnNull();
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
@ -1049,56 +711,30 @@ static PyObject *Subscription_RegisterQuery(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// parse the query in order to get the defined variables
|
||||
// perform the execute (which registers the query)
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
status = OCIStmtExecute(self->connection->handle, cursor->handle,
|
||||
env->errorHandle, 0, 0, 0, 0, OCI_DESCRIBE_ONLY);
|
||||
status = dpiStmt_execute(cursor->handle, DPI_MODE_EXEC_DEFAULT,
|
||||
&numQueryColumns);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_RegisterQuery(): parse statement") < 0) {
|
||||
if (status < 0) {
|
||||
Error_RaiseAndReturnNull();
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// perform define as needed
|
||||
if (Cursor_PerformDefine(cursor) < 0) {
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set the subscription handle
|
||||
status = OCIAttrSet(cursor->handle, OCI_HTYPE_STMT, self->handle, 0,
|
||||
OCI_ATTR_CHNF_REGHANDLE, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_RegisterQuery(): set subscription handle") < 0) {
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// execute the query which registers it
|
||||
if (Cursor_InternalExecute(cursor, 0, 0) < 0) {
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (self->cqqos & OCI_SUBSCR_CQ_QOS_QUERY) {
|
||||
// get the query id
|
||||
status = OCIAttrGet(cursor->handle, OCI_HTYPE_STMT, &queryid, NULL,
|
||||
OCI_ATTR_CQ_QUERYID, env->errorHandle);
|
||||
if (Environment_CheckForError(env, status,
|
||||
"Subscription_RegisterQuery(): get query id") < 0) {
|
||||
// return the query id, if applicable
|
||||
if (self->qos & DPI_SUBSCR_QOS_QUERY) {
|
||||
if (dpiStmt_getSubscrQueryId(cursor->handle, &queryId) < 0) {
|
||||
Error_RaiseAndReturnNull();
|
||||
Py_DECREF(cursor);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(cursor);
|
||||
return PyInt_FromLong(queryId);
|
||||
}
|
||||
|
||||
Py_DECREF(cursor);
|
||||
|
||||
if (self->cqqos & OCI_SUBSCR_CQ_QOS_QUERY)
|
||||
return PyInt_FromLong( (long) queryid);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -1106,8 +742,7 @@ static PyObject *Subscription_RegisterQuery(
|
||||
// Message_Free()
|
||||
// Free the memory associated with a message.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void Message_Free(
|
||||
udt_Message *self) // object to free
|
||||
static void Message_Free(udt_Message *self)
|
||||
{
|
||||
Py_CLEAR(self->subscription);
|
||||
Py_CLEAR(self->dbname);
|
||||
@ -1121,8 +756,7 @@ static void Message_Free(
|
||||
// MessageTable_Free()
|
||||
// Free the memory associated with a table in a message.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void MessageTable_Free(
|
||||
udt_MessageTable *self) // object to free
|
||||
static void MessageTable_Free(udt_MessageTable *self)
|
||||
{
|
||||
Py_CLEAR(self->name);
|
||||
Py_CLEAR(self->rows);
|
||||
@ -1134,8 +768,7 @@ static void MessageTable_Free(
|
||||
// MessageRow_Free()
|
||||
// Free the memory associated with a row in a message.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void MessageRow_Free(
|
||||
udt_MessageRow *self) // object to free
|
||||
static void MessageRow_Free(udt_MessageRow *self)
|
||||
{
|
||||
Py_CLEAR(self->rowid);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
@ -1146,8 +779,7 @@ static void MessageRow_Free(
|
||||
// MessageQuery_Free()
|
||||
// Free the memory associated with a query in a message.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void MessageQuery_Free(
|
||||
udt_MessageQuery *self) // object to free
|
||||
static void MessageQuery_Free(udt_MessageQuery *self)
|
||||
{
|
||||
Py_CLEAR(self->tables);
|
||||
Py_TYPE(self)->tp_free((PyObject*) self);
|
||||
|
||||
@ -1,150 +0,0 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TimestampVar.c
|
||||
// Defines the routines for handling timestamp variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Timestamp type
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct {
|
||||
Variable_HEAD
|
||||
OCIDateTime **data;
|
||||
} udt_TimestampVar;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of date/time variable functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int TimestampVar_Initialize(udt_TimestampVar*, udt_Cursor*);
|
||||
static void TimestampVar_Finalize(udt_TimestampVar*);
|
||||
static int TimestampVar_SetValue(udt_TimestampVar*, unsigned, PyObject*);
|
||||
static PyObject *TimestampVar_GetValue(udt_TimestampVar*, unsigned);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyTypeObject g_TimestampVarType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"cx_Oracle.TIMESTAMP", // tp_name
|
||||
sizeof(udt_TimestampVar), // tp_basicsize
|
||||
0, // tp_itemsize
|
||||
0, // tp_dealloc
|
||||
0, // tp_print
|
||||
0, // tp_getattr
|
||||
0, // tp_setattr
|
||||
0, // tp_compare
|
||||
0, // tp_repr
|
||||
0, // tp_as_number
|
||||
0, // tp_as_sequence
|
||||
0, // tp_as_mapping
|
||||
0, // tp_hash
|
||||
0, // tp_call
|
||||
0, // tp_str
|
||||
0, // tp_getattro
|
||||
0, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT, // tp_flags
|
||||
0 // tp_doc
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// variable type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
static udt_VariableType vt_Timestamp = {
|
||||
(InitializeProc) TimestampVar_Initialize,
|
||||
(FinalizeProc) TimestampVar_Finalize,
|
||||
(PreDefineProc) NULL,
|
||||
(PostDefineProc) NULL,
|
||||
(PostBindProc) NULL,
|
||||
(PreFetchProc) NULL,
|
||||
(IsNullProc) NULL,
|
||||
(SetValueProc) TimestampVar_SetValue,
|
||||
(GetValueProc) TimestampVar_GetValue,
|
||||
(GetBufferSizeProc) NULL,
|
||||
&g_TimestampVarType, // Python type
|
||||
SQLT_TIMESTAMP, // Oracle type
|
||||
SQLCS_IMPLICIT, // charset form
|
||||
sizeof(OCIDateTime*), // element length (default)
|
||||
0, // is character data
|
||||
0, // is variable length
|
||||
1, // can be copied
|
||||
1 // can be in array
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TimestampVar_Initialize()
|
||||
// Initialize the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int TimestampVar_Initialize(
|
||||
udt_TimestampVar *var, // variable to initialize
|
||||
udt_Cursor *cursor) // cursor variable associated with
|
||||
{
|
||||
sword status;
|
||||
ub4 i;
|
||||
|
||||
// initialize the LOB locators
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
status = OCIDescriptorAlloc(var->environment->handle,
|
||||
(dvoid**) &var->data[i], OCI_DTYPE_TIMESTAMP, 0, 0);
|
||||
if (Environment_CheckForError(var->environment, status,
|
||||
"TimestampVar_Initialize()") < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TimestampVar_Finalize()
|
||||
// Prepare for variable destruction.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void TimestampVar_Finalize(
|
||||
udt_TimestampVar *var) // variable to free
|
||||
{
|
||||
ub4 i;
|
||||
|
||||
for (i = 0; i < var->allocatedElements; i++) {
|
||||
if (var->data[i])
|
||||
OCIDescriptorFree(var->data[i], OCI_DTYPE_TIMESTAMP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TimestampVar_SetValue()
|
||||
// Set the value of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int TimestampVar_SetValue(
|
||||
udt_TimestampVar *var, // variable to set value for
|
||||
unsigned pos, // array position to set
|
||||
PyObject *value) // value to set
|
||||
{
|
||||
return PythonDateToOracleTimestamp(var->environment, value,
|
||||
var->data[pos]);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TimestampVar_GetValue()
|
||||
// Returns the value stored at the given array position.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *TimestampVar_GetValue(
|
||||
udt_TimestampVar *var, // variable to determine value for
|
||||
unsigned pos) // array position
|
||||
{
|
||||
return OracleTimestampToPythonDate(var->environment, var->data[pos]);
|
||||
}
|
||||
|
||||
492
src/Transforms.c
492
src/Transforms.c
@ -1,492 +0,0 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright 2016, 2017, 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Transforms.c
|
||||
// Provides methods for transforming Oracle data to Python objects or for
|
||||
// setting Oracle data from Python objects.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static udt_VariableType vt_Date;
|
||||
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
//-----------------------------------------------------------------------------
|
||||
// OracleBooleanToPythonBoolean()
|
||||
// Return a Python boolean object given an Oracle boolean.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *OracleBooleanToPythonBoolean(
|
||||
boolean *value) // value to convert
|
||||
{
|
||||
PyObject *pythonValue;
|
||||
|
||||
pythonValue = (*value) ? Py_True : Py_False;
|
||||
Py_INCREF(pythonValue);
|
||||
return pythonValue;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OracleDateToPythonDate()
|
||||
// Return a Python date object given an Oracle date.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *OracleDateToPythonDate(
|
||||
udt_VariableType *varType, // variable type
|
||||
OCIDate* value) // value to convert
|
||||
{
|
||||
ub1 hour, minute, second, month, day;
|
||||
sb2 year;
|
||||
|
||||
OCIDateGetDate(value, &year, &month, &day);
|
||||
OCIDateGetTime(value, &hour, &minute, &second);
|
||||
|
||||
if (varType == &vt_Date)
|
||||
return PyDate_FromDate(year, month, day);
|
||||
return PyDateTime_FromDateAndTime(year, month, day, hour, minute, second,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OracleIntervalToPythonDelta()
|
||||
// Return a Python delta object given an Oracle interval.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *OracleIntervalToPythonDelta(
|
||||
udt_Environment *environment, // environment
|
||||
OCIInterval *value) // value to convert
|
||||
{
|
||||
sb4 days, hours, minutes, seconds, fseconds;
|
||||
sword status;
|
||||
|
||||
status = OCIIntervalGetDaySecond(environment->handle,
|
||||
environment->errorHandle, &days, &hours, &minutes, &seconds,
|
||||
&fseconds, value);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"OracleIntervalToPythonDelta()") < 0)
|
||||
return NULL;
|
||||
seconds = hours * 60 * 60 + minutes * 60 + seconds;
|
||||
return PyDelta_FromDSU(days, seconds, fseconds / 1000);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OracleTimestampToPythonDate()
|
||||
// Return a Python date object given an Oracle timestamp.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *OracleTimestampToPythonDate(
|
||||
udt_Environment *environment, // environment
|
||||
OCIDateTime* value) // value to convert
|
||||
{
|
||||
ub1 hour, minute, second, month, day;
|
||||
sword status;
|
||||
ub4 fsecond;
|
||||
sb2 year;
|
||||
|
||||
status = OCIDateTimeGetDate(environment->handle, environment->errorHandle,
|
||||
value, &year, &month, &day);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"OracleTimestampToPythonDate(): date portion") < 0)
|
||||
return NULL;
|
||||
status = OCIDateTimeGetTime(environment->handle, environment->errorHandle,
|
||||
value, &hour, &minute, &second, &fsecond);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"OracleTimestampToPythonDate(): time portion") < 0)
|
||||
return NULL;
|
||||
return PyDateTime_FromDateAndTime(year, month, day, hour, minute, second,
|
||||
fsecond / 1000);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OracleNumberToPythonFloat()
|
||||
// Return a Python float given an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *OracleNumberToPythonFloat(
|
||||
udt_Environment *environment, // environment
|
||||
OCINumber* value) // value to convert
|
||||
{
|
||||
double doubleValue;
|
||||
sword status;
|
||||
|
||||
status = OCINumberToReal(environment->errorHandle,
|
||||
value, sizeof(double), (dvoid*) &doubleValue);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"OracleNumberToPythonFloat()") < 0)
|
||||
return NULL;
|
||||
return PyFloat_FromDouble(doubleValue);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OracleNumberToPythonInteger()
|
||||
// Return a Python integer given an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *OracleNumberToPythonInteger(
|
||||
udt_Environment *environment, // environment
|
||||
OCINumber* value) // value to convert
|
||||
{
|
||||
long integerValue;
|
||||
sword status;
|
||||
|
||||
status = OCINumberToInt(environment->errorHandle, value,
|
||||
sizeof(long), OCI_NUMBER_SIGNED, (dvoid*) &integerValue);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"OracleNumberToPythonInteger()") < 0)
|
||||
return NULL;
|
||||
return PyInt_FromLong(integerValue);
|
||||
}
|
||||
|
||||
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonBooleanToOracleBoolean()
|
||||
// Transform a Python boolean into an Oracle boolean.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonBooleanToOracleBoolean(
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
boolean *oracleValue) // value to convert
|
||||
{
|
||||
*oracleValue = (pythonValue == Py_True);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonBooleanToOracleNumber()
|
||||
// Transform a Python boolean into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonBooleanToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
long integerValue;
|
||||
sword status;
|
||||
|
||||
integerValue = (pythonValue == Py_True);
|
||||
status = OCINumberFromInt(environment->errorHandle, &integerValue,
|
||||
sizeof(long), OCI_NUMBER_SIGNED, oracleValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonBooleanToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonDateToOracleDate()
|
||||
// Transform a Python date into an Oracle date.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonDateToOracleDate(
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCIDate *oracleValue) // Oracle value to set
|
||||
{
|
||||
ub1 month, day, hour, minute, second;
|
||||
sb2 year;
|
||||
|
||||
if (PyDateTime_Check(pythonValue)) {
|
||||
year = (short) PyDateTime_GET_YEAR(pythonValue);
|
||||
month = PyDateTime_GET_MONTH(pythonValue);
|
||||
day = PyDateTime_GET_DAY(pythonValue);
|
||||
hour = PyDateTime_DATE_GET_HOUR(pythonValue);
|
||||
minute = PyDateTime_DATE_GET_MINUTE(pythonValue);
|
||||
second = PyDateTime_DATE_GET_SECOND(pythonValue);
|
||||
} else if (PyDate_Check(pythonValue)) {
|
||||
year = (short) PyDateTime_GET_YEAR(pythonValue);
|
||||
month = PyDateTime_GET_MONTH(pythonValue);
|
||||
day = PyDateTime_GET_DAY(pythonValue);
|
||||
hour = minute = second = 0;
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting date data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
OCIDateSetDate(oracleValue, year, month, day);
|
||||
OCIDateSetTime(oracleValue, hour, minute, second);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonIntegerToOracleNumber()
|
||||
// Transform a Python integer into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonIntegerToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
long integerValue;
|
||||
sword status;
|
||||
|
||||
integerValue = PyInt_AS_LONG(pythonValue);
|
||||
status = OCINumberFromInt(environment->errorHandle, &integerValue,
|
||||
sizeof(long), OCI_NUMBER_SIGNED, oracleValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonIntegerToOracleNumber()");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonFloatToOracleNumber()
|
||||
// Transform a Python float into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonFloatToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
double doubleValue;
|
||||
sword status;
|
||||
|
||||
doubleValue = PyFloat_AS_DOUBLE(pythonValue);
|
||||
status = OCINumberFromReal(environment->errorHandle, &doubleValue,
|
||||
sizeof(double), oracleValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonFloatToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonLongToOracleNumber()
|
||||
// Set the value of the variable from a Python long.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonLongToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
udt_Buffer textBuffer;
|
||||
PyObject *textValue;
|
||||
sword status;
|
||||
|
||||
textValue = PyObject_Str(pythonValue);
|
||||
if (!textValue)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(&textBuffer, textValue, environment->encoding) < 0)
|
||||
return -1;
|
||||
status = OCINumberFromText(environment->errorHandle,
|
||||
(text*) textBuffer.ptr, (ub4) textBuffer.size,
|
||||
(text*) environment->numberFromStringFormatBuffer.ptr,
|
||||
(ub4) environment->numberFromStringFormatBuffer.size, NULL, 0,
|
||||
oracleValue);
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
Py_DECREF(textValue);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonLongToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GetFormatAndTextFromPythonDecimal()
|
||||
// Return the number format and text to use for the Decimal object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int GetFormatAndTextFromPythonDecimal(
|
||||
PyObject *tupleValue, // decimal as_tuple() value
|
||||
PyObject **textObj, // text string for conversion
|
||||
PyObject **formatObj) // format for conversion
|
||||
{
|
||||
Py_ssize_t numDigits, scale, i, sign, length, digit;
|
||||
char *textValue, *format, *textPtr, *formatPtr;
|
||||
PyObject *digits;
|
||||
|
||||
// acquire basic information from the value tuple
|
||||
sign = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 0));
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
digits = PyTuple_GET_ITEM(tupleValue, 1);
|
||||
scale = PyInt_AsLong(PyTuple_GET_ITEM(tupleValue, 2));
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
numDigits = PyTuple_GET_SIZE(digits);
|
||||
|
||||
// allocate memory for the string and format to use in conversion
|
||||
length = numDigits + abs( (long) scale) + 3;
|
||||
textValue = textPtr = PyMem_Malloc(length);
|
||||
if (!textValue) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
format = formatPtr = PyMem_Malloc(length);
|
||||
if (!format) {
|
||||
PyMem_Free(textValue);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// populate the string and format
|
||||
if (sign)
|
||||
*textPtr++ = '-';
|
||||
for (i = 0; i < numDigits + scale; i++) {
|
||||
*formatPtr++ = '9';
|
||||
if (i < numDigits) {
|
||||
digit = PyInt_AsLong(PyTuple_GetItem(digits, i));
|
||||
if (PyErr_Occurred()) {
|
||||
PyMem_Free(textValue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else digit = 0;
|
||||
*textPtr++ = '0' + (char) digit;
|
||||
}
|
||||
if (scale < 0) {
|
||||
*formatPtr++ = 'D';
|
||||
*textPtr++ = '.';
|
||||
for (i = scale; i < 0; i++) {
|
||||
*formatPtr++ = '9';
|
||||
if (numDigits + i < 0)
|
||||
digit = 0;
|
||||
else {
|
||||
digit = PyInt_AsLong(PyTuple_GetItem(digits, numDigits + i));
|
||||
if (PyErr_Occurred()) {
|
||||
PyMem_Free(textValue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*textPtr++ = '0' + (char) digit;
|
||||
}
|
||||
}
|
||||
*formatPtr = '\0';
|
||||
*textPtr = '\0';
|
||||
*textObj = cxString_FromAscii(textValue);
|
||||
PyMem_Free(textValue);
|
||||
if (!*textObj) {
|
||||
PyMem_Free(format);
|
||||
return -1;
|
||||
}
|
||||
*formatObj = cxString_FromAscii(format);
|
||||
PyMem_Free(format);
|
||||
if (!*formatObj) {
|
||||
Py_DECREF(*textObj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonDecimalToOracleNumber()
|
||||
// Transform a Python decimal object into an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonDecimalToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value to convert
|
||||
OCINumber *oracleValue) // Oracle value to set
|
||||
{
|
||||
PyObject *textValue, *format, *tupleValue;
|
||||
udt_Buffer textBuffer, formatBuffer;
|
||||
sword status;
|
||||
|
||||
tupleValue = PyObject_CallMethod(pythonValue, "as_tuple", NULL);
|
||||
if (!tupleValue)
|
||||
return -1;
|
||||
if (GetFormatAndTextFromPythonDecimal(tupleValue, &textValue,
|
||||
&format) < 0) {
|
||||
Py_DECREF(tupleValue);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(tupleValue);
|
||||
if (cxBuffer_FromObject(&textBuffer, textValue, environment->encoding) < 0)
|
||||
return -1;
|
||||
if (cxBuffer_FromObject(&formatBuffer, format,
|
||||
environment->encoding) < 0) {
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
return -1;
|
||||
}
|
||||
status = OCINumberFromText(environment->errorHandle,
|
||||
(text*) textBuffer.ptr, (ub4) textBuffer.size,
|
||||
(text*) formatBuffer.ptr, (ub4) formatBuffer.size,
|
||||
environment->nlsNumericCharactersBuffer.ptr,
|
||||
(ub4) environment->nlsNumericCharactersBuffer.size, oracleValue);
|
||||
cxBuffer_Clear(&textBuffer);
|
||||
cxBuffer_Clear(&formatBuffer);
|
||||
Py_DECREF(textValue);
|
||||
Py_DECREF(format);
|
||||
return Environment_CheckForError(environment, status,
|
||||
"PythonDecimalToOracleNumber()");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonNumberToOracleNumber()
|
||||
// Convert a Python number to an Oracle number.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonNumberToOracleNumber(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value
|
||||
OCINumber* oracleValue) // Oracle value
|
||||
{
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (PyInt_Check(pythonValue))
|
||||
return PythonIntegerToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
#endif
|
||||
if (PyBool_Check(pythonValue))
|
||||
return PythonBooleanToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
if (PyLong_Check(pythonValue))
|
||||
return PythonLongToOracleNumber(environment, pythonValue, oracleValue);
|
||||
if (PyFloat_Check(pythonValue))
|
||||
return PythonFloatToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
if (Py_TYPE(pythonValue) == g_DecimalType)
|
||||
return PythonDecimalToOracleNumber(environment, pythonValue,
|
||||
oracleValue);
|
||||
PyErr_SetString(PyExc_TypeError, "expecting numeric data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PythonDateToOracleTimestamp()
|
||||
// Convert a Python date to an Oracle timestamp.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int PythonDateToOracleTimestamp(
|
||||
udt_Environment *environment, // environment
|
||||
PyObject *pythonValue, // Python value
|
||||
OCIDateTime* oracleValue) // Oracle value
|
||||
{
|
||||
sword status;
|
||||
uword valid;
|
||||
|
||||
// make sure a timestamp is being bound
|
||||
if (!PyDateTime_Check(pythonValue)) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting timestamp data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// store a copy of the value
|
||||
status = OCIDateTimeConstruct(environment->handle,
|
||||
environment->errorHandle, oracleValue,
|
||||
(sb2) PyDateTime_GET_YEAR(pythonValue),
|
||||
PyDateTime_GET_MONTH(pythonValue),
|
||||
PyDateTime_GET_DAY(pythonValue),
|
||||
PyDateTime_DATE_GET_HOUR(pythonValue),
|
||||
PyDateTime_DATE_GET_MINUTE(pythonValue),
|
||||
PyDateTime_DATE_GET_SECOND(pythonValue),
|
||||
PyDateTime_DATE_GET_MICROSECOND(pythonValue) * 1000, NULL, 0);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"PythonDateToOracleTimestamp(): create structure") < 0)
|
||||
return -1;
|
||||
status = OCIDateTimeCheck(environment->handle, environment->errorHandle,
|
||||
oracleValue, &valid);
|
||||
if (Environment_CheckForError(environment, status,
|
||||
"PythonDateToOracleTimestamp(): check validity") < 0)
|
||||
return -1;
|
||||
if (valid != 0) {
|
||||
PyErr_SetString(g_DataErrorException, "invalid date");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
1209
src/Variable.c
1209
src/Variable.c
File diff suppressed because it is too large
Load Diff
460
src/cx_Oracle.c
460
src/cx_Oracle.c
@ -18,28 +18,17 @@
|
||||
#include <datetime.h>
|
||||
#include <structmember.h>
|
||||
#include <time.h>
|
||||
#include <oci.h>
|
||||
#include <orid.h>
|
||||
#include <xa.h>
|
||||
#include <dpi.h>
|
||||
|
||||
// validate OCI library
|
||||
#if !defined(OCI_MAJOR_VERSION) || (OCI_MAJOR_VERSION < 11) || \
|
||||
((OCI_MAJOR_VERSION == 11) && (OCI_MINOR_VERSION < 2))
|
||||
#error Oracle 11.2 or later client libraries are required for building
|
||||
#endif
|
||||
|
||||
// define simple way to respresent Oracle version
|
||||
#define ORACLE_VERSION(major, minor) \
|
||||
((major << 8) | minor)
|
||||
#define ORACLE_VERSION_HEX \
|
||||
ORACLE_VERSION(OCI_MAJOR_VERSION, OCI_MINOR_VERSION)
|
||||
|
||||
// define PyInt_* macros for Python 3.x
|
||||
// define integer macros/methods for Python 3.x
|
||||
#ifndef PyInt_Check
|
||||
#define PyInt_Check PyLong_Check
|
||||
#define PyInt_FromLong PyLong_FromLong
|
||||
#define PyInt_FromUnsignedLong PyLong_FromUnsignedLong
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyInt_AsUnsignedLong PyLong_AsUnsignedLong
|
||||
#define PyInt_Type PyLong_Type
|
||||
#define PyNumber_Int PyNumber_Long
|
||||
#endif
|
||||
|
||||
// use the bytes methods in cx_Oracle and define them as the equivalent string
|
||||
@ -61,7 +50,7 @@
|
||||
#define cxString_Type &PyUnicode_Type
|
||||
#define cxString_Format PyUnicode_Format
|
||||
#define cxString_Check PyUnicode_Check
|
||||
#define cxString_GetSize PyUnicode_GET_SIZE
|
||||
#define cxString_GetSize PyUnicode_GET_LENGTH
|
||||
#else
|
||||
#define cxBinary_Type PyBuffer_Type
|
||||
#define cxBinary_Check PyBuffer_Check
|
||||
@ -104,13 +93,43 @@
|
||||
if (PyModule_AddObject(module, name, (PyObject*) type) < 0) \
|
||||
return NULL;
|
||||
|
||||
// define macros for making types ready
|
||||
// define macros for defining and making variable types ready
|
||||
#define DECLARE_VARIABLE_TYPE(INTERNAL_NAME, EXTERNAL_NAME) \
|
||||
static PyTypeObject INTERNAL_NAME = { \
|
||||
PyVarObject_HEAD_INIT(NULL, 0) \
|
||||
"cx_Oracle." #EXTERNAL_NAME, /* tp_name */ \
|
||||
sizeof(udt_Variable), /* tp_basicsize */ \
|
||||
0, /* tp_itemsize */ \
|
||||
(destructor) Variable_Free, /* tp_dealloc */ \
|
||||
0, /* tp_print */ \
|
||||
0, /* tp_getattr */ \
|
||||
0, /* tp_setattr */ \
|
||||
0, /* tp_compare */ \
|
||||
(reprfunc) Variable_Repr, /* tp_repr */ \
|
||||
0, /* tp_as_number */ \
|
||||
0, /* tp_as_sequence */ \
|
||||
0, /* tp_as_mapping */ \
|
||||
0, /* tp_hash */ \
|
||||
0, /* tp_call */ \
|
||||
0, /* tp_str */ \
|
||||
0, /* tp_getattro */ \
|
||||
0, /* tp_setattro */ \
|
||||
0, /* tp_as_buffer */ \
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */ \
|
||||
0, /* tp_doc */ \
|
||||
0, /* tp_traverse */ \
|
||||
0, /* tp_clear */ \
|
||||
0, /* tp_richcompare */ \
|
||||
0, /* tp_weaklistoffset */ \
|
||||
0, /* tp_iter */ \
|
||||
0, /* tp_iternext */ \
|
||||
g_VariableMethods, /* tp_methods */ \
|
||||
g_VariableMembers /* tp_members */ \
|
||||
};
|
||||
|
||||
#define MAKE_TYPE_READY(type) \
|
||||
if (PyType_Ready(type) < 0) \
|
||||
return NULL;
|
||||
#define MAKE_VARIABLE_TYPE_READY(type) \
|
||||
(type)->tp_base = &g_BaseVarType; \
|
||||
MAKE_TYPE_READY(type)
|
||||
|
||||
// define macros to get the build version as a string and the driver name
|
||||
#define xstr(s) str(s)
|
||||
@ -118,15 +137,6 @@
|
||||
#define BUILD_VERSION_STRING xstr(BUILD_VERSION)
|
||||
#define DRIVER_NAME "cx_Oracle : "BUILD_VERSION_STRING
|
||||
|
||||
// define constants used for subscription quality of service
|
||||
// these are intended to more closely follow the PL/SQL implementation and
|
||||
// merge the SUBSCR_QOS and SUBSCR_CQ_QOS constants
|
||||
#define CX_SUBSCR_QOS_RELIABLE 0x01
|
||||
#define CX_SUBSCR_QOS_DEREG_NFY 0x02
|
||||
#define CX_SUBSCR_QOS_ROWIDS 0x04
|
||||
#define CX_SUBSCR_QOS_QUERY 0x08
|
||||
#define CX_SUBSCR_QOS_BEST_EFFORT 0x10
|
||||
|
||||
#include "Buffer.c"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -144,17 +154,15 @@ static PyObject *g_ProgrammingErrorException = NULL;
|
||||
static PyObject *g_NotSupportedErrorException = NULL;
|
||||
static PyTypeObject *g_DateTimeType = NULL;
|
||||
static PyTypeObject *g_DecimalType = NULL;
|
||||
static dpiContext *g_DpiContext = NULL;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SetException()
|
||||
// Create an exception and set it in the provided dictionary.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int SetException(
|
||||
PyObject *module, // module object
|
||||
PyObject **exception, // exception to create
|
||||
char *name, // name of the exception
|
||||
PyObject *baseException) // exception to base exception on
|
||||
static int SetException(PyObject *module, PyObject **exception, char *name,
|
||||
PyObject *baseException)
|
||||
{
|
||||
char buffer[100];
|
||||
|
||||
@ -170,10 +178,8 @@ static int SetException(
|
||||
// GetModuleAndName()
|
||||
// Return the module and name for the type.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int GetModuleAndName(
|
||||
PyTypeObject *type, // type to get module/name for
|
||||
PyObject **module, // name of module
|
||||
PyObject **name) // name of type
|
||||
static int GetModuleAndName(PyTypeObject *type, PyObject **module,
|
||||
PyObject **name)
|
||||
{
|
||||
*module = PyObject_GetAttrString( (PyObject*) type, "__module__");
|
||||
if (!*module)
|
||||
@ -187,7 +193,47 @@ static int GetModuleAndName(
|
||||
}
|
||||
|
||||
|
||||
#include "Environment.c"
|
||||
//-----------------------------------------------------------------------------
|
||||
// GetBooleanValue()
|
||||
// Get a boolean value from a Python object.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int GetBooleanValue(PyObject *obj, int defaultValue, int *value)
|
||||
{
|
||||
if (!obj)
|
||||
*value = defaultValue;
|
||||
else {
|
||||
*value = PyObject_IsTrue(obj);
|
||||
if (*value < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GetAdjustedEncoding()
|
||||
// Return the adjusted encoding to use when encoding and decoding strings
|
||||
// that are passed to and from the Oracle database. The Oracle client interface
|
||||
// does not support the inclusion of a BOM in the encoded string but assumes
|
||||
// native endian order for UTF-16. Python generates a BOM at the beginning of
|
||||
// the encoded string if plain UTF-16 is specified. For this reason, the
|
||||
// correct byte order must be determined and used inside Python so that the
|
||||
// Oracle client receives the data it expects.
|
||||
//-----------------------------------------------------------------------------
|
||||
static const char *GetAdjustedEncoding(const char *encoding)
|
||||
{
|
||||
static const union {
|
||||
unsigned char bytes[4];
|
||||
uint32_t value;
|
||||
} hostOrder = { { 0, 1, 2, 3 } };
|
||||
|
||||
if (!encoding || strcmp(encoding, "UTF-16") != 0)
|
||||
return encoding;
|
||||
return (hostOrder.value == 0x03020100) ? "UTF-16LE" : "UTF-16BE";
|
||||
}
|
||||
|
||||
|
||||
#include "Error.c"
|
||||
#include "SessionPool.c"
|
||||
|
||||
|
||||
@ -195,34 +241,78 @@ static int GetModuleAndName(
|
||||
// MakeDSN()
|
||||
// Make a data source name given the host port and SID.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject* MakeDSN(
|
||||
PyObject* self, // passthrough argument
|
||||
PyObject* args, // arguments to function
|
||||
PyObject* keywordArgs) // keyword arguments
|
||||
static PyObject* MakeDSN(PyObject* self, PyObject* args, PyObject* keywordArgs)
|
||||
{
|
||||
static unsigned int numConnectDataArgs = 5;
|
||||
static char *keywordList[] = { "host", "port", "sid", "service_name",
|
||||
NULL };
|
||||
PyObject *hostObj, *portObj, *sidObj, *serviceNameObj, *connectDataObj;
|
||||
PyObject *format, *result, *formatArgs;
|
||||
"region", "sharding_key", "super_sharding_key", NULL };
|
||||
PyObject *format, *formatArgs, *result, *connectData, *hostObj, *portObj;
|
||||
char connectDataFormat[72], *sourcePtr, *targetPtr;
|
||||
PyObject *connectDataArgs[5], *formatArgsArray;
|
||||
unsigned int i;
|
||||
|
||||
// parse arguments
|
||||
sidObj = serviceNameObj = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "OO|OO", keywordList,
|
||||
&hostObj, &portObj, &sidObj, &serviceNameObj))
|
||||
for (i = 0; i < numConnectDataArgs; i++)
|
||||
connectDataArgs[i] = NULL;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywordArgs, "OO|OOOO0",
|
||||
keywordList, &hostObj, &portObj, &connectDataArgs[0],
|
||||
&connectDataArgs[1], &connectDataArgs[2], &connectDataArgs[3],
|
||||
&connectDataArgs[4]))
|
||||
return NULL;
|
||||
if (sidObj) {
|
||||
connectDataObj = sidObj;
|
||||
format = cxString_FromAscii("(DESCRIPTION=(ADDRESS="
|
||||
"(PROTOCOL=TCP)(HOST=%s)(PORT=%s))(CONNECT_DATA=(SID=%s)))");
|
||||
} else {
|
||||
connectDataObj = serviceNameObj;
|
||||
format = cxString_FromAscii("(DESCRIPTION=(ADDRESS="
|
||||
"(PROTOCOL=TCP)(HOST=%s)(PORT=%s))(CONNECT_DATA="
|
||||
"(SERVICE_NAME=%s)))");
|
||||
|
||||
// create list for connect data format arguments
|
||||
formatArgsArray = PyList_New(0);
|
||||
if (!formatArgsArray)
|
||||
return NULL;
|
||||
|
||||
// process each of the connect data arguments
|
||||
// build up a format string and a list of format arguments
|
||||
targetPtr = connectDataFormat;
|
||||
*targetPtr = '\0';
|
||||
for (i = 0; i < numConnectDataArgs; i++) {
|
||||
if (connectDataArgs[i]) {
|
||||
if (PyList_Append(formatArgsArray, connectDataArgs[i]) < 0) {
|
||||
Py_DECREF(formatArgsArray);
|
||||
return NULL;
|
||||
}
|
||||
sourcePtr = keywordList[i + 2];
|
||||
*targetPtr++ = '(';
|
||||
while (*sourcePtr)
|
||||
*targetPtr++ = toupper(*sourcePtr++);
|
||||
*targetPtr++ = '=';
|
||||
*targetPtr++ = '%';
|
||||
*targetPtr++ = 's';
|
||||
*targetPtr++ = ')';
|
||||
*targetPtr = '\0';
|
||||
}
|
||||
}
|
||||
if (!format)
|
||||
formatArgs = PyList_AsTuple(formatArgsArray);
|
||||
Py_DECREF(formatArgsArray);
|
||||
if (!formatArgs)
|
||||
return NULL;
|
||||
formatArgs = PyTuple_Pack(3, hostObj, portObj, connectDataObj);
|
||||
|
||||
// determine connect data
|
||||
format = cxString_FromAscii(connectDataFormat);
|
||||
if (!format) {
|
||||
Py_DECREF(formatArgs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
connectData = cxString_Format(format, formatArgs);
|
||||
Py_DECREF(format);
|
||||
Py_DECREF(formatArgs);
|
||||
if (!connectData)
|
||||
return NULL;
|
||||
|
||||
// perform overall format
|
||||
format = cxString_FromAscii("(DESCRIPTION=(ADDRESS="
|
||||
"(PROTOCOL=TCP)(HOST=%s)(PORT=%s))(CONNECT_DATA=%s))");
|
||||
if (!format) {
|
||||
Py_DECREF(connectData);
|
||||
return NULL;
|
||||
}
|
||||
formatArgs = PyTuple_Pack(3, hostObj, portObj, connectData);
|
||||
Py_DECREF(connectData);
|
||||
if (!formatArgs) {
|
||||
Py_DECREF(format);
|
||||
return NULL;
|
||||
@ -238,16 +328,15 @@ static PyObject* MakeDSN(
|
||||
// ClientVersion()
|
||||
// Return the version of the Oracle client being used as a 5-tuple.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject* ClientVersion(
|
||||
PyObject* self, // passthrough argument
|
||||
PyObject* args) // arguments to function
|
||||
static PyObject* ClientVersion(PyObject* self, PyObject* args)
|
||||
{
|
||||
sword majorVersion, minorVersion, updateNum, patchNum, portUpdateNum;
|
||||
int versionNum, releaseNum, updateNum, portReleaseNum, portUpdateNum;
|
||||
|
||||
OCIClientVersion(&majorVersion, &minorVersion, &updateNum,
|
||||
&patchNum, &portUpdateNum);
|
||||
return Py_BuildValue("(iiiii)", majorVersion, minorVersion, updateNum,
|
||||
patchNum, portUpdateNum);
|
||||
if (dpiContext_getClientVersion(g_DpiContext, &versionNum, &releaseNum,
|
||||
&updateNum, &portReleaseNum, &portUpdateNum) < 0)
|
||||
return Error_RaiseAndReturnNull();
|
||||
return Py_BuildValue("(iiiii)", versionNum, releaseNum, updateNum,
|
||||
portReleaseNum, portUpdateNum);
|
||||
}
|
||||
|
||||
|
||||
@ -255,9 +344,7 @@ static PyObject* ClientVersion(
|
||||
// Time()
|
||||
// Returns a time value suitable for binding.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject* Time(
|
||||
PyObject* self, // passthrough argument
|
||||
PyObject* args) // arguments to function
|
||||
static PyObject* Time(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyErr_SetString(g_NotSupportedErrorException,
|
||||
"Oracle does not support time only variables");
|
||||
@ -269,9 +356,7 @@ static PyObject* Time(
|
||||
// TimeFromTicks()
|
||||
// Returns a time value suitable for binding.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject* TimeFromTicks(
|
||||
PyObject* self, // passthrough argument
|
||||
PyObject* args) // arguments to function
|
||||
static PyObject* TimeFromTicks(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyErr_SetString(g_NotSupportedErrorException,
|
||||
"Oracle does not support time only variables");
|
||||
@ -283,9 +368,7 @@ static PyObject* TimeFromTicks(
|
||||
// DateFromTicks()
|
||||
// Returns a date value suitable for binding.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject* DateFromTicks(
|
||||
PyObject* self, // passthrough argument
|
||||
PyObject* args) // arguments to function
|
||||
static PyObject* DateFromTicks(PyObject* self, PyObject* args)
|
||||
{
|
||||
return PyDate_FromTimestamp(args);
|
||||
}
|
||||
@ -295,9 +378,7 @@ static PyObject* DateFromTicks(
|
||||
// TimestampFromTicks()
|
||||
// Returns a date value suitable for binding.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject* TimestampFromTicks(
|
||||
PyObject* self, // passthrough argument
|
||||
PyObject* args) // arguments to function
|
||||
static PyObject* TimestampFromTicks(PyObject* self, PyObject* args)
|
||||
{
|
||||
return PyDateTime_FromTimestamp(args);
|
||||
}
|
||||
@ -341,6 +422,7 @@ static struct PyModuleDef g_ModuleDef = {
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *Module_Initialize(void)
|
||||
{
|
||||
dpiErrorInfo errorInfo;
|
||||
PyObject *module;
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
@ -365,10 +447,9 @@ static PyObject *Module_Initialize(void)
|
||||
MAKE_TYPE_READY(&g_CursorType);
|
||||
MAKE_TYPE_READY(&g_ErrorType);
|
||||
MAKE_TYPE_READY(&g_SessionPoolType);
|
||||
MAKE_TYPE_READY(&g_EnvironmentType);
|
||||
MAKE_TYPE_READY(&g_ObjectTypeType);
|
||||
MAKE_TYPE_READY(&g_ObjectAttributeType);
|
||||
MAKE_TYPE_READY(&g_ExternalLobVarType);
|
||||
MAKE_TYPE_READY(&g_LOBType);
|
||||
MAKE_TYPE_READY(&g_ObjectType);
|
||||
MAKE_TYPE_READY(&g_EnqOptionsType);
|
||||
MAKE_TYPE_READY(&g_DeqOptionsType);
|
||||
@ -378,30 +459,27 @@ static PyObject *Module_Initialize(void)
|
||||
MAKE_TYPE_READY(&g_MessageTableType);
|
||||
MAKE_TYPE_READY(&g_MessageRowType);
|
||||
MAKE_TYPE_READY(&g_MessageQueryType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_StringVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_FixedCharVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_RowidVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_BinaryVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_LongStringVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_LongBinaryVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_NumberVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_DateTimeVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_TimestampVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_CLOBVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_BLOBVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_BFILEVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_CursorVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_ObjectVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_NCharVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_FixedNCharVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_LongNCharVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_NCLOBVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_NativeFloatVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_NativeIntVarType);
|
||||
MAKE_VARIABLE_TYPE_READY(&g_IntervalVarType);
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
MAKE_VARIABLE_TYPE_READY(&g_BooleanVarType);
|
||||
#endif
|
||||
MAKE_TYPE_READY(&g_StringVarType);
|
||||
MAKE_TYPE_READY(&g_FixedCharVarType);
|
||||
MAKE_TYPE_READY(&g_RowidVarType);
|
||||
MAKE_TYPE_READY(&g_BinaryVarType);
|
||||
MAKE_TYPE_READY(&g_LongStringVarType);
|
||||
MAKE_TYPE_READY(&g_LongBinaryVarType);
|
||||
MAKE_TYPE_READY(&g_NumberVarType);
|
||||
MAKE_TYPE_READY(&g_DateTimeVarType);
|
||||
MAKE_TYPE_READY(&g_TimestampVarType);
|
||||
MAKE_TYPE_READY(&g_CLOBVarType);
|
||||
MAKE_TYPE_READY(&g_BLOBVarType);
|
||||
MAKE_TYPE_READY(&g_BFILEVarType);
|
||||
MAKE_TYPE_READY(&g_CursorVarType);
|
||||
MAKE_TYPE_READY(&g_ObjectVarType);
|
||||
MAKE_TYPE_READY(&g_NCharVarType);
|
||||
MAKE_TYPE_READY(&g_FixedNCharVarType);
|
||||
MAKE_TYPE_READY(&g_NCLOBVarType);
|
||||
MAKE_TYPE_READY(&g_NativeFloatVarType);
|
||||
MAKE_TYPE_READY(&g_NativeIntVarType);
|
||||
MAKE_TYPE_READY(&g_IntervalVarType);
|
||||
MAKE_TYPE_READY(&g_BooleanVarType);
|
||||
|
||||
// initialize module and retrieve the dictionary
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
@ -444,6 +522,13 @@ static PyObject *Module_Initialize(void)
|
||||
"NotSupportedError", g_DatabaseErrorException) < 0)
|
||||
return NULL;
|
||||
|
||||
// initialize DPI library and create DPI context
|
||||
if (dpiContext_create(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, &g_DpiContext,
|
||||
&errorInfo) < 0) {
|
||||
Error_RaiseFromInfo(&errorInfo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set up the types that are available
|
||||
ADD_TYPE_OBJECT("Binary", &cxBinary_Type)
|
||||
ADD_TYPE_OBJECT("Connection", &g_ConnectionType)
|
||||
@ -472,9 +557,8 @@ static PyObject *Module_Initialize(void)
|
||||
ADD_TYPE_OBJECT("FIXED_CHAR", &g_FixedCharVarType)
|
||||
ADD_TYPE_OBJECT("FIXED_NCHAR", &g_FixedNCharVarType)
|
||||
ADD_TYPE_OBJECT("NCHAR", &g_NCharVarType)
|
||||
ADD_TYPE_OBJECT("LONG_NCHAR", &g_LongNCharVarType)
|
||||
ADD_TYPE_OBJECT("INTERVAL", &g_IntervalVarType)
|
||||
ADD_TYPE_OBJECT("LOB", &g_ExternalLobVarType)
|
||||
ADD_TYPE_OBJECT("LOB", &g_LOBType)
|
||||
ADD_TYPE_OBJECT("LONG_BINARY", &g_LongBinaryVarType)
|
||||
ADD_TYPE_OBJECT("LONG_STRING", &g_LongStringVarType)
|
||||
ADD_TYPE_OBJECT("NCLOB", &g_NCLOBVarType)
|
||||
@ -484,9 +568,7 @@ static PyObject *Module_Initialize(void)
|
||||
ADD_TYPE_OBJECT("TIMESTAMP", &g_TimestampVarType)
|
||||
ADD_TYPE_OBJECT("NATIVE_INT", &g_NativeIntVarType)
|
||||
ADD_TYPE_OBJECT("NATIVE_FLOAT", &g_NativeFloatVarType)
|
||||
#if ORACLE_VERSION_HEX >= ORACLE_VERSION(12, 1)
|
||||
ADD_TYPE_OBJECT("BOOLEAN", &g_BooleanVarType)
|
||||
#endif
|
||||
|
||||
// create constants required by Python DB API 2.0
|
||||
if (PyModule_AddStringConstant(module, "apilevel", "2.0") < 0)
|
||||
@ -508,108 +590,103 @@ static PyObject *Module_Initialize(void)
|
||||
return NULL;
|
||||
|
||||
// add constants for authorization modes
|
||||
ADD_INT_CONSTANT("SYSASM", OCI_SYSASM)
|
||||
ADD_INT_CONSTANT("SYSDBA", OCI_SYSDBA)
|
||||
ADD_INT_CONSTANT("SYSOPER", OCI_SYSOPER)
|
||||
ADD_INT_CONSTANT("PRELIM_AUTH", OCI_PRELIM_AUTH)
|
||||
ADD_INT_CONSTANT("SYSASM", DPI_MODE_AUTH_SYSASM)
|
||||
ADD_INT_CONSTANT("SYSDBA", DPI_MODE_AUTH_SYSDBA)
|
||||
ADD_INT_CONSTANT("SYSOPER", DPI_MODE_AUTH_SYSOPER)
|
||||
ADD_INT_CONSTANT("PRELIM_AUTH", DPI_MODE_AUTH_PRELIM)
|
||||
|
||||
// add constants for session pool get modes
|
||||
ADD_INT_CONSTANT("SPOOL_ATTRVAL_WAIT", OCI_SPOOL_ATTRVAL_WAIT)
|
||||
ADD_INT_CONSTANT("SPOOL_ATTRVAL_NOWAIT", OCI_SPOOL_ATTRVAL_NOWAIT)
|
||||
ADD_INT_CONSTANT("SPOOL_ATTRVAL_FORCEGET", OCI_SPOOL_ATTRVAL_FORCEGET)
|
||||
ADD_INT_CONSTANT("SPOOL_ATTRVAL_WAIT", DPI_MODE_POOL_GET_WAIT)
|
||||
ADD_INT_CONSTANT("SPOOL_ATTRVAL_NOWAIT", DPI_MODE_POOL_GET_NOWAIT)
|
||||
ADD_INT_CONSTANT("SPOOL_ATTRVAL_FORCEGET", DPI_MODE_POOL_GET_FORCEGET)
|
||||
|
||||
// add constants for database shutdown modes
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_ABORT", OCI_DBSHUTDOWN_ABORT)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_FINAL", OCI_DBSHUTDOWN_FINAL)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_IMMEDIATE", OCI_DBSHUTDOWN_IMMEDIATE)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_TRANSACTIONAL", OCI_DBSHUTDOWN_TRANSACTIONAL)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_ABORT", DPI_MODE_SHUTDOWN_ABORT)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_FINAL", DPI_MODE_SHUTDOWN_FINAL)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_IMMEDIATE", DPI_MODE_SHUTDOWN_IMMEDIATE)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_TRANSACTIONAL",
|
||||
DPI_MODE_SHUTDOWN_TRANSACTIONAL)
|
||||
ADD_INT_CONSTANT("DBSHUTDOWN_TRANSACTIONAL_LOCAL",
|
||||
OCI_DBSHUTDOWN_TRANSACTIONAL_LOCAL)
|
||||
DPI_MODE_SHUTDOWN_TRANSACTIONAL_LOCAL)
|
||||
|
||||
// add constants for purity
|
||||
ADD_INT_CONSTANT("ATTR_PURITY_DEFAULT", OCI_ATTR_PURITY_DEFAULT)
|
||||
ADD_INT_CONSTANT("ATTR_PURITY_NEW", OCI_ATTR_PURITY_NEW)
|
||||
ADD_INT_CONSTANT("ATTR_PURITY_SELF", OCI_ATTR_PURITY_SELF)
|
||||
ADD_INT_CONSTANT("ATTR_PURITY_DEFAULT", DPI_PURITY_DEFAULT)
|
||||
ADD_INT_CONSTANT("ATTR_PURITY_NEW", DPI_PURITY_NEW)
|
||||
ADD_INT_CONSTANT("ATTR_PURITY_SELF", DPI_PURITY_SELF)
|
||||
|
||||
// add constants for subscription protocols
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_OCI", OCI_SUBSCR_PROTO_OCI)
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_MAIL", OCI_SUBSCR_PROTO_MAIL)
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_SERVER", OCI_SUBSCR_PROTO_SERVER)
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_HTTP", OCI_SUBSCR_PROTO_HTTP)
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_OCI", DPI_SUBSCR_PROTO_CALLBACK)
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_MAIL", DPI_SUBSCR_PROTO_MAIL)
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_SERVER", DPI_SUBSCR_PROTO_PLSQL)
|
||||
ADD_INT_CONSTANT("SUBSCR_PROTO_HTTP", DPI_SUBSCR_PROTO_HTTP)
|
||||
|
||||
// add constants for subscription quality of service
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_RELIABLE", CX_SUBSCR_QOS_RELIABLE)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_DEREG_NFY", CX_SUBSCR_QOS_DEREG_NFY)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_ROWIDS", CX_SUBSCR_QOS_ROWIDS)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_QUERY", CX_SUBSCR_QOS_QUERY)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_BEST_EFFORT", CX_SUBSCR_QOS_BEST_EFFORT)
|
||||
|
||||
// add constants for deprecated subscription quality of service
|
||||
ADD_INT_CONSTANT("SUBSCR_CQ_QOS_PURGE_ON_NTFN", CX_SUBSCR_QOS_DEREG_NFY)
|
||||
ADD_INT_CONSTANT("SUBSCR_CQ_QOS_QUERY", CX_SUBSCR_QOS_QUERY)
|
||||
ADD_INT_CONSTANT("SUBSCR_CQ_QOS_BEST_EFFORT",
|
||||
OCI_SUBSCR_CQ_QOS_BEST_EFFORT)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_RELIABLE", DPI_SUBSCR_QOS_RELIABLE)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_DEREG_NFY", DPI_SUBSCR_QOS_DEREG_NFY)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_ROWIDS", DPI_SUBSCR_QOS_ROWIDS)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_QUERY", DPI_SUBSCR_QOS_QUERY)
|
||||
ADD_INT_CONSTANT("SUBSCR_QOS_BEST_EFFORT", DPI_SUBSCR_QOS_BEST_EFFORT)
|
||||
|
||||
// add constants for subscription namespaces
|
||||
ADD_INT_CONSTANT("SUBSCR_NAMESPACE_DBCHANGE",
|
||||
OCI_SUBSCR_NAMESPACE_DBCHANGE)
|
||||
DPI_SUBSCR_NAMESPACE_DBCHANGE)
|
||||
|
||||
// add constants for event types
|
||||
ADD_INT_CONSTANT("EVENT_NONE", OCI_EVENT_NONE)
|
||||
ADD_INT_CONSTANT("EVENT_STARTUP", OCI_EVENT_STARTUP)
|
||||
ADD_INT_CONSTANT("EVENT_SHUTDOWN", OCI_EVENT_SHUTDOWN)
|
||||
ADD_INT_CONSTANT("EVENT_SHUTDOWN_ANY", OCI_EVENT_SHUTDOWN_ANY)
|
||||
ADD_INT_CONSTANT("EVENT_DEREG", OCI_EVENT_DEREG)
|
||||
ADD_INT_CONSTANT("EVENT_OBJCHANGE", OCI_EVENT_OBJCHANGE)
|
||||
ADD_INT_CONSTANT("EVENT_QUERYCHANGE", OCI_EVENT_QUERYCHANGE)
|
||||
ADD_INT_CONSTANT("EVENT_NONE", DPI_EVENT_NONE)
|
||||
ADD_INT_CONSTANT("EVENT_STARTUP", DPI_EVENT_STARTUP)
|
||||
ADD_INT_CONSTANT("EVENT_SHUTDOWN", DPI_EVENT_SHUTDOWN)
|
||||
ADD_INT_CONSTANT("EVENT_SHUTDOWN_ANY", DPI_EVENT_SHUTDOWN_ANY)
|
||||
ADD_INT_CONSTANT("EVENT_DEREG", DPI_EVENT_DEREG)
|
||||
ADD_INT_CONSTANT("EVENT_OBJCHANGE", DPI_EVENT_OBJCHANGE)
|
||||
ADD_INT_CONSTANT("EVENT_QUERYCHANGE", DPI_EVENT_QUERYCHANGE)
|
||||
|
||||
// add constants for opcodes
|
||||
ADD_INT_CONSTANT("OPCODE_ALLOPS", OCI_OPCODE_ALLOPS)
|
||||
ADD_INT_CONSTANT("OPCODE_ALLROWS", OCI_OPCODE_ALLROWS)
|
||||
ADD_INT_CONSTANT("OPCODE_INSERT", OCI_OPCODE_INSERT)
|
||||
ADD_INT_CONSTANT("OPCODE_UPDATE", OCI_OPCODE_UPDATE)
|
||||
ADD_INT_CONSTANT("OPCODE_DELETE", OCI_OPCODE_DELETE)
|
||||
ADD_INT_CONSTANT("OPCODE_ALTER", OCI_OPCODE_ALTER)
|
||||
ADD_INT_CONSTANT("OPCODE_DROP", OCI_OPCODE_DROP)
|
||||
ADD_INT_CONSTANT("OPCODE_ALLOPS", DPI_OPCODE_ALL_OPS)
|
||||
ADD_INT_CONSTANT("OPCODE_ALLROWS", DPI_OPCODE_ALL_ROWS)
|
||||
ADD_INT_CONSTANT("OPCODE_INSERT", DPI_OPCODE_INSERT)
|
||||
ADD_INT_CONSTANT("OPCODE_UPDATE", DPI_OPCODE_UPDATE)
|
||||
ADD_INT_CONSTANT("OPCODE_DELETE", DPI_OPCODE_DELETE)
|
||||
ADD_INT_CONSTANT("OPCODE_ALTER", DPI_OPCODE_ALTER)
|
||||
ADD_INT_CONSTANT("OPCODE_DROP", DPI_OPCODE_DROP)
|
||||
|
||||
// add constants for AQ dequeue modes
|
||||
ADD_INT_CONSTANT("DEQ_BROWSE", OCI_DEQ_BROWSE)
|
||||
ADD_INT_CONSTANT("DEQ_LOCKED", OCI_DEQ_LOCKED)
|
||||
ADD_INT_CONSTANT("DEQ_REMOVE", OCI_DEQ_REMOVE)
|
||||
ADD_INT_CONSTANT("DEQ_REMOVE_NODATA", OCI_DEQ_REMOVE_NODATA)
|
||||
ADD_INT_CONSTANT("DEQ_BROWSE", DPI_MODE_DEQ_BROWSE)
|
||||
ADD_INT_CONSTANT("DEQ_LOCKED", DPI_MODE_DEQ_LOCKED)
|
||||
ADD_INT_CONSTANT("DEQ_REMOVE", DPI_MODE_DEQ_REMOVE)
|
||||
ADD_INT_CONSTANT("DEQ_REMOVE_NODATA", DPI_MODE_DEQ_REMOVE_NO_DATA)
|
||||
|
||||
// add constants for AQ dequeue navigation
|
||||
ADD_INT_CONSTANT("DEQ_FIRST_MSG", OCI_DEQ_FIRST_MSG)
|
||||
ADD_INT_CONSTANT("DEQ_NEXT_TRANSACTION", OCI_DEQ_NEXT_TRANSACTION)
|
||||
ADD_INT_CONSTANT("DEQ_NEXT_MSG", OCI_DEQ_NEXT_MSG)
|
||||
ADD_INT_CONSTANT("DEQ_FIRST_MSG", DPI_DEQ_NAV_FIRST_MSG)
|
||||
ADD_INT_CONSTANT("DEQ_NEXT_TRANSACTION", DPI_DEQ_NAV_NEXT_TRANSACTION)
|
||||
ADD_INT_CONSTANT("DEQ_NEXT_MSG", DPI_DEQ_NAV_NEXT_MSG)
|
||||
|
||||
// add constants for AQ dequeue visibility
|
||||
ADD_INT_CONSTANT("DEQ_IMMEDIATE", OCI_DEQ_IMMEDIATE)
|
||||
ADD_INT_CONSTANT("DEQ_ON_COMMIT", OCI_DEQ_ON_COMMIT)
|
||||
ADD_INT_CONSTANT("DEQ_IMMEDIATE", DPI_VISIBILITY_IMMEDIATE)
|
||||
ADD_INT_CONSTANT("DEQ_ON_COMMIT", DPI_VISIBILITY_ON_COMMIT)
|
||||
|
||||
// add constants for AQ dequeue wait
|
||||
ADD_INT_CONSTANT("DEQ_NO_WAIT", OCI_DEQ_NO_WAIT)
|
||||
ADD_INT_CONSTANT("DEQ_WAIT_FOREVER", OCI_DEQ_WAIT_FOREVER)
|
||||
ADD_INT_CONSTANT("DEQ_NO_WAIT", DPI_DEQ_WAIT_NO_WAIT)
|
||||
ADD_INT_CONSTANT("DEQ_WAIT_FOREVER", DPI_DEQ_WAIT_FOREVER)
|
||||
|
||||
// add constants for AQ enqueue visibility
|
||||
ADD_INT_CONSTANT("ENQ_IMMEDIATE", OCI_ENQ_IMMEDIATE)
|
||||
ADD_INT_CONSTANT("ENQ_ON_COMMIT", OCI_ENQ_ON_COMMIT)
|
||||
ADD_INT_CONSTANT("ENQ_IMMEDIATE", DPI_VISIBILITY_IMMEDIATE)
|
||||
ADD_INT_CONSTANT("ENQ_ON_COMMIT", DPI_VISIBILITY_ON_COMMIT)
|
||||
|
||||
// add constants for AQ table purge mode (message)
|
||||
ADD_INT_CONSTANT("MSG_PERSISTENT", OCI_MSG_PERSISTENT)
|
||||
ADD_INT_CONSTANT("MSG_BUFFERED", OCI_MSG_BUFFERED)
|
||||
ADD_INT_CONSTANT("MSG_PERSISTENT", DPI_MODE_MSG_PERSISTENT)
|
||||
ADD_INT_CONSTANT("MSG_BUFFERED", DPI_MODE_MSG_BUFFERED)
|
||||
ADD_INT_CONSTANT("MSG_PERSISTENT_OR_BUFFERED",
|
||||
OCI_MSG_PERSISTENT_OR_BUFFERED)
|
||||
DPI_MODE_MSG_PERSISTENT_OR_BUFFERED)
|
||||
|
||||
// add constants for AQ message state
|
||||
ADD_INT_CONSTANT("MSG_EXPIRED", OCI_MSG_EXPIRED)
|
||||
ADD_INT_CONSTANT("MSG_READY", OCI_MSG_READY)
|
||||
ADD_INT_CONSTANT("MSG_PROCESSED", OCI_MSG_PROCESSED)
|
||||
ADD_INT_CONSTANT("MSG_WAITING", OCI_MSG_WAITING)
|
||||
ADD_INT_CONSTANT("MSG_EXPIRED", DPI_MSG_STATE_EXPIRED)
|
||||
ADD_INT_CONSTANT("MSG_READY", DPI_MSG_STATE_READY)
|
||||
ADD_INT_CONSTANT("MSG_PROCESSED", DPI_MSG_STATE_PROCESSED)
|
||||
ADD_INT_CONSTANT("MSG_WAITING", DPI_MSG_STATE_WAITING)
|
||||
|
||||
// add special constants for AQ delay/expiration
|
||||
ADD_INT_CONSTANT("MSG_NO_DELAY", OCI_MSG_NO_DELAY)
|
||||
ADD_INT_CONSTANT("MSG_NO_EXPIRATION", OCI_MSG_NO_EXPIRATION)
|
||||
ADD_INT_CONSTANT("MSG_NO_DELAY", 0)
|
||||
ADD_INT_CONSTANT("MSG_NO_EXPIRATION", -1)
|
||||
|
||||
return module;
|
||||
}
|
||||
@ -630,3 +707,30 @@ void initcx_Oracle(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// include all DPI files
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dpiConn.c"
|
||||
#include "dpiContext.c"
|
||||
#include "dpiData.c"
|
||||
#include "dpiDeqOptions.c"
|
||||
#include "dpiEnqOptions.c"
|
||||
#include "dpiEnv.c"
|
||||
#include "dpiError.c"
|
||||
#include "dpiGen.c"
|
||||
#include "dpiGlobal.c"
|
||||
#include "dpiLob.c"
|
||||
#include "dpiMsgProps.c"
|
||||
#include "dpiObject.c"
|
||||
#include "dpiObjectAttr.c"
|
||||
#include "dpiObjectType.c"
|
||||
#include "dpiOracleType.c"
|
||||
#include "dpiPool.c"
|
||||
#include "dpiRowid.c"
|
||||
#include "dpiStmt.c"
|
||||
#include "dpiSubscr.c"
|
||||
#include "dpiUtils.c"
|
||||
#include "dpiVar.c"
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ class TestConnection(TestCase):
|
||||
connection = cx_Oracle.connect(self.username, self.password,
|
||||
self.tnsentry)
|
||||
connection.close()
|
||||
self.assertRaises(cx_Oracle.InterfaceError, connection.rollback)
|
||||
self.assertRaises(cx_Oracle.DatabaseError, connection.rollback)
|
||||
|
||||
def testMakeDSN(self):
|
||||
"test making a data source name from host, port and sid"
|
||||
|
||||
@ -19,7 +19,6 @@ class TestError(BaseTestCase):
|
||||
self.assertTrue("Test!" in errorObj.message)
|
||||
self.assertEqual(errorObj.code, 20101)
|
||||
self.assertEqual(errorObj.offset, 0)
|
||||
self.assertEqual(errorObj.context, "Cursor_InternalExecute()")
|
||||
self.assertTrue(isinstance(errorObj.isrecoverable, bool))
|
||||
pickledData = pickle.dumps(errorObj)
|
||||
newErrorObj = pickle.loads(pickledData)
|
||||
|
||||
@ -120,6 +120,35 @@ class TestFeatures12_1(BaseTestCase):
|
||||
self.cursor.callproc("pkg_TestNumberArrays.TestOutArrays", (3, obj))
|
||||
self.assertEqual(obj.aslist(), [100, 200, 300])
|
||||
|
||||
def testBindPLSQLRecordArray(self):
|
||||
"test binding an array of PL/SQL records (in)"
|
||||
recType = self.connection.gettype("PKG_TESTRECORDS.UDT_RECORD")
|
||||
arrayType = self.connection.gettype("PKG_TESTRECORDS.UDT_RECORDARRAY")
|
||||
arrayObj = arrayType.newobject()
|
||||
for i in range(3):
|
||||
obj = recType.newobject()
|
||||
obj.NUMBERVALUE = i + 1
|
||||
obj.STRINGVALUE = "String in record #%d" % (i + 1)
|
||||
obj.DATEVALUE = datetime.datetime(2017, i + 1, 1)
|
||||
obj.TIMESTAMPVALUE = datetime.datetime(2017, 1, i + 1)
|
||||
obj.BOOLEANVALUE = (i % 2) == 1
|
||||
arrayObj.append(obj)
|
||||
result = self.cursor.callfunc("pkg_TestRecords.TestInArrays", str,
|
||||
(arrayObj,))
|
||||
self.assertEqual(result,
|
||||
"udt_Record(1, 'String in record #1', " \
|
||||
"to_date('2017-01-01', 'YYYY-MM-DD'), " \
|
||||
"to_timestamp('2017-01-01 00:00:00', " \
|
||||
"'YYYY-MM-DD HH24:MI:SS'), false); " \
|
||||
"udt_Record(2, 'String in record #2', " \
|
||||
"to_date('2017-02-01', 'YYYY-MM-DD'), " \
|
||||
"to_timestamp('2017-01-02 00:00:00', " \
|
||||
"'YYYY-MM-DD HH24:MI:SS'), true); " \
|
||||
"udt_Record(3, 'String in record #3', " \
|
||||
"to_date('2017-03-01', 'YYYY-MM-DD'), " \
|
||||
"to_timestamp('2017-01-03 00:00:00', " \
|
||||
"'YYYY-MM-DD HH24:MI:SS'), false)")
|
||||
|
||||
def testBindPLSQLRecordIn(self):
|
||||
"test binding a PL/SQL record (in)"
|
||||
typeObj = self.connection.gettype("PKG_TESTRECORDS.UDT_RECORD")
|
||||
@ -312,9 +341,9 @@ class TestFeatures12_1(BaseTestCase):
|
||||
arraydmlrowcounts = True)
|
||||
expectedErrors = [
|
||||
( 4, 1438, "ORA-01438: value larger than specified " \
|
||||
"precision allowed for this column\n" ),
|
||||
"precision allowed for this column" ),
|
||||
( 2, 1, "ORA-00001: unique constraint " \
|
||||
"(CX_ORACLE.TESTARRAYDML_PK) violated\n")
|
||||
"(CX_ORACLE.TESTARRAYDML_PK) violated")
|
||||
]
|
||||
actualErrors = [(e.offset, e.code, e.message) \
|
||||
for e in self.cursor.getbatcherrors()]
|
||||
@ -349,7 +378,7 @@ class TestFeatures12_1(BaseTestCase):
|
||||
self.cursor.executemany(sql, rows, batcherrors = True)
|
||||
expectedErrors = [
|
||||
( 6, 1, "ORA-00001: unique constraint " \
|
||||
"(CX_ORACLE.TESTARRAYDML_PK) violated\n")
|
||||
"(CX_ORACLE.TESTARRAYDML_PK) violated")
|
||||
]
|
||||
actualErrors = [(e.offset, e.code, e.message) \
|
||||
for e in self.cursor.getbatcherrors()]
|
||||
@ -364,7 +393,7 @@ class TestFeatures12_1(BaseTestCase):
|
||||
batcherrors = True)
|
||||
expectedErrors = [
|
||||
( 2, 1438, "ORA-01438: value larger than specified " \
|
||||
"precision allowed for this column\n" )
|
||||
"precision allowed for this column" )
|
||||
]
|
||||
actualErrors = [(e.offset, e.code, e.message) \
|
||||
for e in self.cursor.getbatcherrors()]
|
||||
|
||||
@ -76,7 +76,7 @@ class TestLobVar(BaseTestCase):
|
||||
|
||||
def __ValidateQuery(self, rows, lobType):
|
||||
longString = ""
|
||||
for row in self.cursor:
|
||||
for row in rows:
|
||||
integerValue, lob = row
|
||||
if integerValue == 0:
|
||||
self.assertEqual(lob.size(), 0)
|
||||
|
||||
@ -26,7 +26,6 @@ class TestLongVar(BaseTestCase):
|
||||
integerValue = i,
|
||||
longString = bindValue)
|
||||
self.connection.commit()
|
||||
self.cursor.setoutputsize(250000, 2)
|
||||
self.cursor.execute("""
|
||||
select *
|
||||
from Test%ss
|
||||
@ -76,7 +75,6 @@ class TestLongVar(BaseTestCase):
|
||||
self.cursor.execute("select * from TestLongRaws")
|
||||
longVar = self.cursor.fetchvars[1]
|
||||
self.assertEqual(longVar.size, 25000)
|
||||
self.assertEqual(longVar.bufferSize, 25004)
|
||||
|
||||
def testSetOutputSizesWrongColumn(self):
|
||||
"test setoutputsizes is valid (wrong column)"
|
||||
@ -84,8 +82,6 @@ class TestLongVar(BaseTestCase):
|
||||
self.cursor.execute("select * from TestLongs")
|
||||
longVar = self.cursor.fetchvars[1]
|
||||
self.assertEqual(longVar.size, 131072)
|
||||
self.assertEqual(longVar.bufferSize,
|
||||
131072 * self.connection.maxBytesPerCharacter + 4)
|
||||
|
||||
def testSetOutputSizesRightColumn(self):
|
||||
"test setoutputsizes is valid (right column)"
|
||||
@ -93,11 +89,10 @@ class TestLongVar(BaseTestCase):
|
||||
self.cursor.execute("select * from TestLongRaws")
|
||||
longVar = self.cursor.fetchvars[1]
|
||||
self.assertEqual(longVar.size, 35000)
|
||||
self.assertEqual(longVar.bufferSize, 35004)
|
||||
|
||||
def testArraySizeTooLarge(self):
|
||||
"test array size too large generates an exception"
|
||||
self.cursor.arraysize = 65536
|
||||
self.assertRaises(ValueError, self.cursor.execute,
|
||||
self.cursor.arraysize = 268435456
|
||||
self.assertRaises(cx_Oracle.DatabaseError, self.cursor.execute,
|
||||
"select * from TestLongRaws")
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ class TestConnection(TestCase):
|
||||
connection = cx_Oracle.connect(self.username, self.password,
|
||||
self.tnsentry)
|
||||
connection.close()
|
||||
self.assertRaises(cx_Oracle.InterfaceError, connection.rollback)
|
||||
self.assertRaises(cx_Oracle.DatabaseError, connection.rollback)
|
||||
|
||||
def testMakeDSN(self):
|
||||
"test making a data source name from host, port and sid"
|
||||
|
||||
@ -103,9 +103,9 @@ class TestArrayDMLBatchError(BaseTestCase):
|
||||
arraydmlrowcounts = True)
|
||||
expectedErrors = [
|
||||
( 4, 1438, u"ORA-01438: value larger than specified " \
|
||||
u"precision allowed for this column\n" ),
|
||||
u"precision allowed for this column" ),
|
||||
( 2, 1, u"ORA-00001: unique constraint " \
|
||||
u"(CX_ORACLE.TESTARRAYDML_PK) violated\n")
|
||||
u"(CX_ORACLE.TESTARRAYDML_PK) violated")
|
||||
]
|
||||
actualErrors = [(e.offset, e.code, e.message) \
|
||||
for e in self.cursor.getbatcherrors()]
|
||||
@ -140,7 +140,7 @@ class TestArrayDMLBatchError(BaseTestCase):
|
||||
self.cursor.executemany(sql, rows, batcherrors = True)
|
||||
expectedErrors = [
|
||||
( 6, 1, u"ORA-00001: unique constraint " \
|
||||
u"(CX_ORACLE.TESTARRAYDML_PK) violated\n")
|
||||
u"(CX_ORACLE.TESTARRAYDML_PK) violated")
|
||||
]
|
||||
actualErrors = [(e.offset, e.code, e.message) \
|
||||
for e in self.cursor.getbatcherrors()]
|
||||
@ -155,7 +155,7 @@ class TestArrayDMLBatchError(BaseTestCase):
|
||||
batcherrors = True)
|
||||
expectedErrors = [
|
||||
( 2, 1438, u"ORA-01438: value larger than specified " \
|
||||
u"precision allowed for this column\n" )
|
||||
u"precision allowed for this column" )
|
||||
]
|
||||
actualErrors = [(e.offset, e.code, e.message) \
|
||||
for e in self.cursor.getbatcherrors()]
|
||||
|
||||
@ -124,13 +124,6 @@ class TestLobVar(BaseTestCase):
|
||||
"test trimming a CLOB"
|
||||
self.__TestTrim("CLOB")
|
||||
|
||||
def testMultipleFetch(self):
|
||||
"test retrieving data from a CLOB after multiple fetches"
|
||||
self.cursor.arraysize = 1
|
||||
self.cursor.execute(u"select CLOBCol from TestCLOBS")
|
||||
rows = self.cursor.fetchall()
|
||||
self.assertRaises(cx_Oracle.ProgrammingError, rows[1][0].read)
|
||||
|
||||
def testNCLOBCursorDescription(self):
|
||||
"test cursor description is accurate for NCLOBs"
|
||||
self.cursor.execute(u"select * from TestNCLOBs")
|
||||
|
||||
@ -72,7 +72,6 @@ class TestLongVar(BaseTestCase):
|
||||
self.cursor.execute(u"select * from TestLongRaws")
|
||||
longVar = self.cursor.fetchvars[1]
|
||||
self.assertEqual(longVar.size, 25000)
|
||||
self.assertEqual(longVar.bufferSize, 25004)
|
||||
|
||||
def testSetOutputSizesWrongColumn(self):
|
||||
"test setoutputsizes is valid (wrong column)"
|
||||
@ -80,11 +79,10 @@ class TestLongVar(BaseTestCase):
|
||||
self.cursor.execute(u"select * from TestLongRaws")
|
||||
longVar = self.cursor.fetchvars[1]
|
||||
self.assertEqual(longVar.size, 131072)
|
||||
self.assertEqual(longVar.bufferSize, 131076)
|
||||
|
||||
def testArraySizeTooLarge(self):
|
||||
"test array size too large generates an exception"
|
||||
self.cursor.arraysize = 65536
|
||||
self.assertRaises(ValueError, self.cursor.execute,
|
||||
self.cursor.arraysize = 268435456
|
||||
self.assertRaises(cx_Oracle.DatabaseError, self.cursor.execute,
|
||||
u"select * from TestLongRaws")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user