Reworked type management to clarify and simplify code (see release notes for
details).
This commit is contained in:
parent
08346005a7
commit
f7b7785e82
|
@ -157,7 +157,8 @@ Cursor Object
|
||||||
will be None for operations that do not return rows or if the cursor has
|
will be None for operations that do not return rows or if the cursor has
|
||||||
not had an operation invoked via the :meth:`~Cursor.execute()` method yet.
|
not had an operation invoked via the :meth:`~Cursor.execute()` method yet.
|
||||||
|
|
||||||
The type will be one of the type objects defined at the module level.
|
The type will be one of the :ref:`database type constants <dbtypes>`
|
||||||
|
defined at the module level.
|
||||||
|
|
||||||
|
|
||||||
.. method:: Cursor.execute(statement, [parameters], \*\*keywordParameters)
|
.. method:: Cursor.execute(statement, [parameters], \*\*keywordParameters)
|
||||||
|
@ -554,10 +555,34 @@ Cursor Object
|
||||||
use in input and output type handlers defined on cursors or connections.
|
use in input and output type handlers defined on cursors or connections.
|
||||||
|
|
||||||
The dataType parameter specifies the type of data that should be stored in
|
The dataType parameter specifies the type of data that should be stored in
|
||||||
the variable. This should be one of the types defined at the module level
|
the variable. This should be one of the
|
||||||
(such as :data:`cx_Oracle.STRING`) or a Python type that cx_Oracle knows
|
:ref:`database type constants <dbtypes>`, :ref:`DB API constants <types>`,
|
||||||
how to process (such as str) or an object type returned from the method
|
an object type returned from the method :meth:`Connection.gettype()` or one
|
||||||
:meth:`Connection.gettype()`.
|
of the following Python types:
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - Python Type
|
||||||
|
- Database Type
|
||||||
|
* - bool
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_BOOLEAN`
|
||||||
|
* - bytes
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_RAW`
|
||||||
|
* - datetime.date
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_DATE`
|
||||||
|
* - datetime.datetime
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_DATE`
|
||||||
|
* - datetime.timedelta
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_INTERVAL_DS`
|
||||||
|
* - decimal.Decimal
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_NUMBER`
|
||||||
|
* - float
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_NUMBER`
|
||||||
|
* - int
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_NUMBER`
|
||||||
|
* - str
|
||||||
|
- :attr:`cx_Oracle.DB_TYPE_VARCHAR`
|
||||||
|
|
||||||
The size parameter specifies the length of string and raw variables and is
|
The size parameter specifies the length of string and raw variables and is
|
||||||
ignored in all other cases. If not specified for string and raw variables,
|
ignored in all other cases. If not specified for string and raw variables,
|
||||||
|
@ -577,8 +602,8 @@ Cursor Object
|
||||||
was passed directly as the first parameter.
|
was passed directly as the first parameter.
|
||||||
|
|
||||||
The encodingErrors parameter specifies what should happen when decoding
|
The encodingErrors parameter specifies what should happen when decoding
|
||||||
byte strings fetched from the database into strings (Python 3) or unicode
|
byte strings fetched from the database into strings. It should be one of
|
||||||
objects (Python 2). It should be one of the values noted in the builtin
|
the values noted in the builtin
|
||||||
`decode <https://docs.python.org/3/library/stdtypes.html#bytes.decode>`__
|
`decode <https://docs.python.org/3/library/stdtypes.html#bytes.decode>`__
|
||||||
function.
|
function.
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,14 @@ See :ref:`lobdata` for more information about using LOBs.
|
||||||
Trim the LOB to the new size.
|
Trim the LOB to the new size.
|
||||||
|
|
||||||
|
|
||||||
|
.. attribute:: LOB.type
|
||||||
|
|
||||||
|
This read-only attribute returns the type of the LOB as one of the
|
||||||
|
:ref:`database type constants <dbtypes>`.
|
||||||
|
|
||||||
|
.. versionadded:: 8.0
|
||||||
|
|
||||||
|
|
||||||
.. method:: LOB.write(data, [offset=1])
|
.. method:: LOB.write(data, [offset=1])
|
||||||
|
|
||||||
Write the data to the LOB object at the given offset. The offset is in
|
Write the data to the LOB object at the given offset. The offset is in
|
||||||
|
|
|
@ -972,210 +972,369 @@ or more of these values can be OR'ed together.
|
||||||
|
|
||||||
.. _types:
|
.. _types:
|
||||||
|
|
||||||
Types
|
DB API Types
|
||||||
=====
|
------------
|
||||||
|
|
||||||
.. data:: BINARY
|
.. data:: BINARY
|
||||||
|
|
||||||
This type object is used to describe columns in a database that contain
|
This type object is used to describe columns in a database that contain
|
||||||
binary data. In Oracle this is RAW columns.
|
binary data. The database types :data:`DB_TYPE_RAW`,
|
||||||
|
:data:`DB_TYPE_LONG_RAW`, :data:`DB_TYPE_BLOB` and :data:`DB_TYPE_BFILE`.
|
||||||
|
will all compare equal to this value. If a variable is created with this
|
||||||
.. data:: BFILE
|
type, the database type :data:`DB_TYPE_RAW` will be used.
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are BFILEs.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: BLOB
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are BLOBs.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: BOOLEAN
|
|
||||||
|
|
||||||
This type object is used to represent PL/SQL booleans.
|
|
||||||
|
|
||||||
.. versionadded:: 5.2.1
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition. It is only
|
|
||||||
available in Oracle 12.1 and higher and only within PL/SQL. It cannot
|
|
||||||
be used in columns.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: CLOB
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are CLOBs.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: CURSOR
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are cursors
|
|
||||||
(in PL/SQL these are known as ref cursors).
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: DATETIME
|
.. data:: DATETIME
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are dates.
|
This type object is used to describe columns in a database that are dates.
|
||||||
|
The database types :data:`DB_TYPE_DATE`, :data:`DB_TYPE_TIMESTAMP`,
|
||||||
|
:data:`DB_TYPE_TIMESTAMP_LTZ` and :data:`DB_TYPE_TIMESTAMP_TZ` will all
|
||||||
.. data:: FIXED_CHAR
|
compare equal to this value. If a variable is created with this
|
||||||
|
type, the database type :data:`DB_TYPE_DATE` will be used.
|
||||||
This type object is used to describe columns in a database that are fixed
|
|
||||||
length strings (in Oracle these is CHAR columns); these behave differently
|
|
||||||
in Oracle than varchar2 so they are differentiated here even though the DB
|
|
||||||
API does not differentiate them.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This attribute is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: FIXED_NCHAR
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are NCHAR
|
|
||||||
columns in Oracle; these behave differently in Oracle than nvarchar2 so
|
|
||||||
they are differentiated here even though the DB API does not differentiate
|
|
||||||
them.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: INTERVAL
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are of type
|
|
||||||
interval day to second.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: LOB
|
|
||||||
|
|
||||||
This type object is the Python type of :data:`BLOB` and :data:`CLOB` data
|
|
||||||
that is returned from cursors.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: LONG_BINARY
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are long
|
|
||||||
binary (in Oracle these are LONG RAW columns).
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: LONG_STRING
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are long
|
|
||||||
strings (in Oracle these are LONG columns).
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: NATIVE_FLOAT
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are of type
|
|
||||||
binary_double or binary_float.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: NATIVE_INT
|
|
||||||
|
|
||||||
This type object is used to bind integers using Oracle's native integer
|
|
||||||
support, rather than the standard number support.
|
|
||||||
|
|
||||||
.. versionadded:: 5.3
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: NCHAR
|
|
||||||
|
|
||||||
This type object is used to describe national character strings (NVARCHAR2)
|
|
||||||
in Oracle.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: NCLOB
|
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are NCLOBs.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: NUMBER
|
.. data:: NUMBER
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are
|
This type object is used to describe columns in a database that are
|
||||||
numbers.
|
numbers. The database types :data:`DB_TYPE_BINARY_DOUBLE`,
|
||||||
|
:data:`DB_TYPE_BINARY_FLOAT`, :data:`DB_TYPE_BINARY_INTEGER` and
|
||||||
|
:data:`DB_TYPE_NUMBER` will all compare equal to this value. If a variable
|
||||||
.. data:: OBJECT
|
is created with this type, the database type :data:`DB_TYPE_NUMBER` will be
|
||||||
|
used.
|
||||||
This type object is used to describe columns in a database that are
|
|
||||||
objects.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This type is an extension to the DB API definition.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: ROWID
|
.. data:: ROWID
|
||||||
|
|
||||||
This type object is used to describe the pseudo column "rowid".
|
This type object is used to describe the pseudo column "rowid". The
|
||||||
|
database type :data:`DB_TYPE_ROWID` will compare equal to this value. If a
|
||||||
|
variable is created with this type, the database type
|
||||||
|
:data:`DB_TYPE_VARCHAR` will be used.
|
||||||
|
|
||||||
|
|
||||||
.. data:: STRING
|
.. data:: STRING
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are strings
|
This type object is used to describe columns in a database that are
|
||||||
(in Oracle this is VARCHAR2 columns).
|
strings. The database types :data:`DB_TYPE_CHAR`, :data:`DB_TYPE_CLOB`,
|
||||||
|
:data:`DB_TYPE_LONG`, :data:`DB_TYPE_NCHAR`, :data:`DB_TYPE_NCLOB`,
|
||||||
|
:data:`DB_TYPE_NVARCHAR` and :data:`DB_TYPE_VARCHAR` will all compare equal
|
||||||
|
to this value. If a variable is created with this type, the database type
|
||||||
|
:data:`DB_TYPE_VARCHAR` will be used.
|
||||||
|
|
||||||
|
|
||||||
|
.. _dbtypes:
|
||||||
|
|
||||||
|
Database Types
|
||||||
|
--------------
|
||||||
|
|
||||||
|
All of these types are extensions to the DB API definition. They are found in
|
||||||
|
query and object metadata. They can also be used to specify the database type
|
||||||
|
when binding data.
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_BFILE
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type BFILE. It will compare equal to the DB API type :data:`BINARY`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_BINARY_DOUBLE
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type BINARY_DOUBLE. It will compare equal to the DB API type
|
||||||
|
:data:`NUMBER`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_BINARY_FLOAT
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are
|
||||||
|
of type BINARY_FLOAT. It will compare equal to the DB API type
|
||||||
|
:data:`NUMBER`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_BINARY_INTEGER
|
||||||
|
|
||||||
|
Describes attributes or array elements in a database that are of type
|
||||||
|
BINARY_INTEGER. It will compare equal to the DB API type :data:`NUMBER`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_BLOB
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type BLOB. It will compare equal to the DB API type :data:`BINARY`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_BOOLEAN
|
||||||
|
|
||||||
|
Describes attributes or array elements in a database that are of type
|
||||||
|
BOOLEAN. It is only available in Oracle 12.1 and higher and only within
|
||||||
|
PL/SQL.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_CHAR
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type CHAR. It will compare equal to the DB API type :data:`STRING`.
|
||||||
|
|
||||||
|
Note that these are fixed length string values and behave differently from
|
||||||
|
VARCHAR2.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_CLOB
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type CLOB. It will compare equal to the DB API type :data:`STRING`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_CURSOR
|
||||||
|
|
||||||
|
Describes columns in a database that are of type CURSOR. In PL/SQL these
|
||||||
|
are knoown as REF CURSOR.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_DATE
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type DATE. It will compare equal to the DB API type :data:`DATETIME`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_INTERVAL_DS
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type INTERVAL DAY TO SECOND.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_INTERVAL_YM
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type INTERVAL YEAR TO MONTH. This database type is not currently supported
|
||||||
|
by cx_Oracle.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_LONG
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type LONG. It will compare equal to the DB API type :data:`STRING`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_LONG_RAW
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type LONG RAW. It will compare equal to the DB API type :data:`BINARY`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_NCHAR
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type NCHAR. It will compare equal to the DB API type :data:`STRING`.
|
||||||
|
|
||||||
|
Note that these are fixed length string values and behave differently from
|
||||||
|
NVARCHAR2.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_NCLOB
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type NCLOB. It will compare equal to the DB API type :data:`STRING`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_NUMBER
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type NUMBER. It will compare equal to the DB API type :data:`NUMBER`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_NVARCHAR
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type NVARCHAR2. It will compare equal to the DB API type :data:`STRING`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_OBJECT
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are an
|
||||||
|
instance of a named SQL or PL/SQL type.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_RAW
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type RAW. It will compare equal to the DB API type :data:`BINARY`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_ROWID
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type ROWID or UROWID. It will compare equal to the DB API type
|
||||||
|
:data:`ROWID`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_TIMESTAMP
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type TIMESTAMP. It will compare equal to the DB API type :data:`DATETIME`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_TIMESTAMP_LTZ
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type TIMESTAMP WITH LOCAL TIME ZONE. It will compare equal to the DB API
|
||||||
|
type :data:`DATETIME`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_TIMESTAMP_TZ
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type TIMESTAMP WITH TIME ZONE. It will compare equal to the DB API type
|
||||||
|
:data:`DATETIME`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DB_TYPE_VARCHAR
|
||||||
|
|
||||||
|
Describes columns, attributes or array elements in a database that are of
|
||||||
|
type VARCHAR2. It will compare equal to the DB API type :data:`STRING`.
|
||||||
|
|
||||||
|
|
||||||
|
.. _dbtypesynonyms:
|
||||||
|
|
||||||
|
Database Type Synonyms
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
All of the following constants are deprecated and will be removed in a future
|
||||||
|
version of cx_Oracle.
|
||||||
|
|
||||||
|
.. data:: BFILE
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_BFILE`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: BLOB
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_BLOB`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: BOOLEAN
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_BOOLEAN`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: CLOB
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_CLOB`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
.. data:: CURSOR
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_CURSOR`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: FIXED_CHAR
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_CHAR`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: FIXED_NCHAR
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_NCHAR`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: INTERVAL
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_INTERVAL_DS`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: LONG_BINARY
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_LONG_RAW`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: LONG_STRING
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_LONG`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: NATIVE_FLOAT
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_BINARY_DOUBLE`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: NATIVE_INT
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_BINARY_INTEGER`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: NCHAR
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_NVARCHAR`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: NCLOB
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_NCLOB`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: OBJECT
|
||||||
|
|
||||||
|
A synonym for :data:`DB_TYPE_OBJECT`.
|
||||||
|
|
||||||
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
|
|
||||||
.. data:: TIMESTAMP
|
.. data:: TIMESTAMP
|
||||||
|
|
||||||
This type object is used to describe columns in a database that are
|
A synonym for :data:`DB_TYPE_TIMESTAMP`.
|
||||||
timestamps.
|
|
||||||
|
|
||||||
.. note::
|
.. deprecated:: 8.0
|
||||||
|
|
||||||
This attribute is an extension to the DB API definition.
|
|
||||||
|
Other Types
|
||||||
|
-----------
|
||||||
|
|
||||||
|
All of these types are extensions to the DB API definition.
|
||||||
|
|
||||||
|
.. data:: ApiType
|
||||||
|
|
||||||
|
This type object is the Python type of the database API type constants
|
||||||
|
:data:`BINARY`, :data:`DATETIME`, :data:`NUMBER`, :data:`ROWID` and
|
||||||
|
:data:`STRING`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: DbType
|
||||||
|
|
||||||
|
This type object is the Python type of the
|
||||||
|
:ref:`database type constants <dbtypes>`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: LOB
|
||||||
|
|
||||||
|
This type object is the Python type of :data:`DB_TYPE_BLOB`,
|
||||||
|
:data:`DB_TYPE_BFILE`, :data:`DB_TYPE_CLOB` and :data:`DB_TYPE_NCLOB` data
|
||||||
|
that is returned from cursors.
|
||||||
|
|
||||||
|
|
||||||
.. _exceptions:
|
.. _exceptions:
|
||||||
|
|
|
@ -19,8 +19,8 @@ Object Type Objects
|
||||||
|
|
||||||
.. attribute:: ObjectType.attributes
|
.. attribute:: ObjectType.attributes
|
||||||
|
|
||||||
This read-only attribute returns a list of the attributes that make up the
|
This read-only attribute returns a list of the :ref:`attributes
|
||||||
object type. Each attribute has a name attribute on it.
|
<objectattr>` that make up the object type.
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: ObjectType.iscollection
|
.. attribute:: ObjectType.iscollection
|
||||||
|
@ -34,6 +34,17 @@ Object Type Objects
|
||||||
This read-only attribute returns the name of the type.
|
This read-only attribute returns the name of the type.
|
||||||
|
|
||||||
|
|
||||||
|
.. attribute:: ObjectType.element_type
|
||||||
|
|
||||||
|
This read-only attribute returns the type of elements found in collections
|
||||||
|
of this type, if :attr:`~ObjectType.iscollection` is ``True``; otherwise,
|
||||||
|
it returns ``None``. If the collection contains objects, this will be
|
||||||
|
another object type; otherwise, it will be one of the
|
||||||
|
:ref:`database type constants <dbtypes>`.
|
||||||
|
|
||||||
|
.. versionadded:: 8.0
|
||||||
|
|
||||||
|
|
||||||
.. method:: ObjectType.newobject([sequence])
|
.. method:: ObjectType.newobject([sequence])
|
||||||
|
|
||||||
Return a new Oracle object of the given type. This object can then be
|
Return a new Oracle object of the given type. This object can then be
|
||||||
|
@ -151,3 +162,29 @@ Object Objects
|
||||||
.. method:: Object.trim(num)
|
.. method:: Object.trim(num)
|
||||||
|
|
||||||
Remove the specified number of elements from the end of the collection.
|
Remove the specified number of elements from the end of the collection.
|
||||||
|
|
||||||
|
|
||||||
|
.. _objectattr:
|
||||||
|
|
||||||
|
Object Attribute Objects
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This object is an extension to the DB API. The elements of
|
||||||
|
:attr:`ObjectType.attributes` are instances of this type.
|
||||||
|
|
||||||
|
|
||||||
|
.. attribute:: ObjectAttribute.name
|
||||||
|
|
||||||
|
This read-only attribute returns the name of the attribute.
|
||||||
|
|
||||||
|
|
||||||
|
.. attribute:: ObjectAttribute.type
|
||||||
|
|
||||||
|
This read-only attribute returns the type of the attribute. This will be an
|
||||||
|
:ref:`Oracle Object Type <objecttype>` if the variable binds
|
||||||
|
Oracle objects; otherwise, it will be one of the
|
||||||
|
:ref:`database type constants <dbtypes>`.
|
||||||
|
|
||||||
|
.. versionadded:: 8.0
|
||||||
|
|
|
@ -70,9 +70,14 @@ Variable Objects
|
||||||
|
|
||||||
.. attribute:: Variable.type
|
.. attribute:: Variable.type
|
||||||
|
|
||||||
This read-only attribute returns the type of the variable for those
|
This read-only attribute returns the type of the variable. This will be an
|
||||||
variables that bind Oracle objects (it is not present for any other type of
|
:ref:`Oracle Object Type <objecttype>` if the variable binds
|
||||||
variable).
|
Oracle objects; otherwise, it will be one of the
|
||||||
|
:ref:`database type constants <dbtypes>`.
|
||||||
|
|
||||||
|
.. versionchanged:: 8.0
|
||||||
|
Database type constants are now used when the variable is not used for
|
||||||
|
binding Oracle objects.
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: Variable.values
|
.. attribute:: Variable.values
|
||||||
|
|
|
@ -4,8 +4,8 @@ Welcome to cx_Oracle's documentation!
|
||||||
|
|
||||||
**cx_Oracle** is a module that enables access to Oracle Database and conforms
|
**cx_Oracle** is a module that enables access to Oracle Database and conforms
|
||||||
to the Python database API specification. This module is currently tested
|
to the Python database API specification. This module is currently tested
|
||||||
against Oracle Client 19c, 18c, 12c, and 11.2, and Python 2.7, 3.5, 3.6, 3.7
|
against Oracle Client 19c, 18c, 12c, and 11.2, and Python 3.5, 3.6, 3.7 and
|
||||||
and 3.8.
|
3.8.
|
||||||
|
|
||||||
**cx_Oracle** is distributed under an open-source :ref:`license <license>`
|
**cx_Oracle** is distributed under an open-source :ref:`license <license>`
|
||||||
(the BSD license). A detailed description of cx_Oracle changes can be found in
|
(the BSD license). A detailed description of cx_Oracle changes can be found in
|
||||||
|
|
|
@ -9,9 +9,48 @@ Version 8.0 (TBD)
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
#) Dropped support for Python 2.7.
|
#) Dropped support for Python 2.7.
|
||||||
|
#) Updated embedded ODPI-C to `version 3.4
|
||||||
|
<https://oracle.github.io/odpi/doc/releasenotes.html#version-3-4-tbd>`__.
|
||||||
|
#) Reworked type management to clarify and simplify code
|
||||||
|
|
||||||
|
- Added :ref:`constants <dbtypes>` for all database types. The database
|
||||||
|
types :data:`cx_Oracle.DB_TYPE_BINARY_FLOAT`,
|
||||||
|
:data:`cx_Oracle.DB_TYPE_INTERVAL_YM`,
|
||||||
|
:data:`cx_Oracle.DB_TYPE_TIMESTAMP_LTZ` and
|
||||||
|
:data:`cx_Oracle.DB_TYPE_TIMESTAMP_TZ` are completely new. The other
|
||||||
|
types were found in earlier releases under a different name. These types
|
||||||
|
will be found in :data:`Cursor.description` and passed as the defaultType
|
||||||
|
parameter to the :data:`Connection.outputtypehandler` and
|
||||||
|
:data:`Cursor.outputtypehandler` functions.
|
||||||
|
- Added :ref:`synonyms <dbtypesynonyms>` from the old type names to the new
|
||||||
|
type names for backwards compatibility. They are deprecated and will be
|
||||||
|
removed in a future version of cx_Oracle.
|
||||||
|
- The DB API :ref:`constants <types>` are now a specialized constant that
|
||||||
|
matches to the corresponding database types, as recommended by the DB
|
||||||
|
API.
|
||||||
|
- The variable attribute :data:`~Variable.type` now refers to one of the
|
||||||
|
new database type constants if the variable does not contain objects
|
||||||
|
(previously it was None in that case).
|
||||||
|
- The attribute :data:`~LOB.type` was added to LOB values.
|
||||||
|
- The attribute :data:`~ObjectAttribute.type` was added to attributes of
|
||||||
|
object types.
|
||||||
|
- The attribute :data:`~ObjectType.element_type` was added to object types.
|
||||||
|
- :ref:`Object types <objecttype>` now compare equal if they were created
|
||||||
|
by the same connection or session pool and their schemas and names match.
|
||||||
|
- All variables are now instances of the same class (previously each type
|
||||||
|
was an instance of a separate variable type). The attribute
|
||||||
|
:data:`~Variable.type` can be examined to determine the database type it
|
||||||
|
is associated with.
|
||||||
|
- The string representation of variables has changed to include the type
|
||||||
|
in addition to the value.
|
||||||
|
|
||||||
#) Added support for starting up a database using a parameter file (PFILE),
|
#) Added support for starting up a database using a parameter file (PFILE),
|
||||||
as requested
|
as requested
|
||||||
(`issue 295 <https://github.com/oracle/python-cx_Oracle/issues/295>`__).
|
(`issue 295 <https://github.com/oracle/python-cx_Oracle/issues/295>`__).
|
||||||
|
#) Fixed overflow issue when calling :meth:`Cursor.getbatcherrors()` with
|
||||||
|
row offsets exceeding 65536.
|
||||||
|
#) Eliminated spurious error when accessing :attr:`Cursor.lastrowid` after
|
||||||
|
executing an INSERT ALL statement.
|
||||||
|
|
||||||
|
|
||||||
Version 7.3 (December 2019)
|
Version 7.3 (December 2019)
|
||||||
|
|
|
@ -214,9 +214,10 @@ LOB Bind Variables
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Database CLOBs, NCLOBS, BLOBs and BFILEs can be bound with types
|
Database CLOBs, NCLOBS, BLOBs and BFILEs can be bound with types
|
||||||
:attr:`cx_Oracle.CLOB`, :attr:`cx_Oracle.NCLOB`, :attr:`cx_Oracle.BLOB`
|
:attr:`cx_Oracle.DB_TYPE_CLOB`, :attr:`cx_Oracle.DB_TYPE_NCLOB`,
|
||||||
and :attr:`cx_Oracle.BFILE` respectively. LOBs fetched from the database or
|
:attr:`cx_Oracle.DB_TYPE_BLOB` and :attr:`cx_Oracle.DB_TYPE_BFILE`
|
||||||
created with :meth:`Connection.createlob()` can also be bound.
|
respectively. LOBs fetched from the database or created with
|
||||||
|
:meth:`Connection.createlob()` can also be bound.
|
||||||
|
|
||||||
LOBs may represent Oracle Database persistent LOBs (those stored in tables) or
|
LOBs may represent Oracle Database persistent LOBs (those stored in tables) or
|
||||||
temporary LOBs (such as those created with :meth:`Connection.createlob()` or
|
temporary LOBs (such as those created with :meth:`Connection.createlob()` or
|
||||||
|
@ -268,12 +269,12 @@ employees with the last name 'Smith' so the result is::
|
||||||
(159, 'Lindsey', 'Smith')
|
(159, 'Lindsey', 'Smith')
|
||||||
(171, 'William', 'Smith')
|
(171, 'William', 'Smith')
|
||||||
|
|
||||||
To return a REF CURSOR from a PL/SQL function, use ``cx_Oracle.CURSOR`` for the
|
To return a REF CURSOR from a PL/SQL function, use ``cx_Oracle.DB_TYPE_CURSOR`` for the
|
||||||
return type of :meth:`Cursor.callfunc()`:
|
return type of :meth:`Cursor.callfunc()`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
refCursor = cursor.callfunc('example_package.f_get_cursor', cx_Oracle.CURSOR)
|
refCursor = cursor.callfunc('example_package.f_get_cursor', cx_Oracle.DB_TYPE_CURSOR)
|
||||||
for row in refCursor:
|
for row in refCursor:
|
||||||
print(row)
|
print(row)
|
||||||
|
|
||||||
|
@ -659,7 +660,7 @@ objects seamlessly:
|
||||||
|
|
||||||
def InputTypeHandler(cursor, value, numElements):
|
def InputTypeHandler(cursor, value, numElements):
|
||||||
if isinstance(value, Building):
|
if isinstance(value, Building):
|
||||||
return cursor.var(cx_Oracle.OBJECT, arraysize = numElements,
|
return cursor.var(cx_Oracle.DB_TYPE_OBJECT, arraysize = numElements,
|
||||||
inconverter = BuildingInConverter, typename = objType.name)
|
inconverter = BuildingInConverter, typename = objType.name)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -637,6 +637,25 @@ Upgrading from Older Versions
|
||||||
Review the :ref:`release notes <releasenotes>` for deprecations and modify any
|
Review the :ref:`release notes <releasenotes>` for deprecations and modify any
|
||||||
affected code.
|
affected code.
|
||||||
|
|
||||||
|
If you are upgrading from cx_Oracle 7 note these changes:
|
||||||
|
|
||||||
|
- Any uses of ``type(var)`` need to be changed to ``var.type``.
|
||||||
|
|
||||||
|
- Any uses of ``var.type is not None`` need to be changed to
|
||||||
|
``isinstance(var.type, cx_Oracle.ObjectType)``
|
||||||
|
|
||||||
|
- Note that ``TIMESTAMP WITH TIME ZONE`` columns will now be reported as
|
||||||
|
:data:`cx_Oracle.DB_TYPE_TIMESTAMP_TZ` instead of
|
||||||
|
:data:`cx_Oracle.TIMESTAMP` in :data:`Cursor.description`.
|
||||||
|
|
||||||
|
- Note that ``TIMESTAMP WITH LOCAL TIME ZONE`` columns will now be reported
|
||||||
|
as :data:`cx_Oracle.DB_TYPE_TIMESTAMP_LTZ` instead of
|
||||||
|
:data:`cx_Oracle.TIMESTAMP` in :data:`Cursor.description`.
|
||||||
|
|
||||||
|
- Note that ``BINARY_FLOAT`` columns will now be reported as
|
||||||
|
:data:`cx_Oracle.DB_TYPE_BINARY_FLOAT` instead of
|
||||||
|
:data:`cx_Oracle.NATIVE_DOUBLE` in :data:`Cursor.description`.
|
||||||
|
|
||||||
If you are upgrading from cx_Oracle 5 note these installation changes:
|
If you are upgrading from cx_Oracle 5 note these installation changes:
|
||||||
|
|
||||||
- When using Oracle Instant Client, you should not set ``ORACLE_HOME``.
|
- When using Oracle Instant Client, you should not set ``ORACLE_HOME``.
|
||||||
|
@ -684,9 +703,8 @@ If installation fails:
|
||||||
or venv?
|
or venv?
|
||||||
|
|
||||||
- Do you get the error "``No module named pip``"? The pip module is builtin
|
- Do you get the error "``No module named pip``"? The pip module is builtin
|
||||||
to Python from version 2.7.9 but is sometimes removed by the OS. Use the
|
to Python but is sometimes removed by the OS. Use the venv module
|
||||||
venv module (builtin to Python 3.x) or virtualenv module (Python 2.x)
|
(builtin to Python 3.x) or virtualenv module instead.
|
||||||
instead.
|
|
||||||
|
|
||||||
- Do you get the error "``fatal error: dpi.h: No such file or directory``"
|
- Do you get the error "``fatal error: dpi.h: No such file or directory``"
|
||||||
when building from source code? Ensure that your source installation has
|
when building from source code? Ensure that your source installation has
|
||||||
|
@ -723,6 +741,5 @@ If using cx_Oracle fails:
|
||||||
supported on Windows 7. Similar steps shown above for ``DPI-1047`` may
|
supported on Windows 7. Similar steps shown above for ``DPI-1047`` may
|
||||||
help.
|
help.
|
||||||
|
|
||||||
- If you have both Python 2 and 3 installed, make sure you are
|
- If you have multiple versions of Python installed, make sure you are
|
||||||
using the correct python and pip (or python3 and pip3)
|
using the correct python and pip (or python3 and pip3) executables.
|
||||||
executables.
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ Features
|
||||||
The cx_Oracle feature highlights are:
|
The cx_Oracle feature highlights are:
|
||||||
|
|
||||||
* Easily installed from PyPI
|
* Easily installed from PyPI
|
||||||
* Support for Python 2 and 3, and for multiple Oracle Database versions
|
* Support for multiple Oracle Client and Database versions
|
||||||
* Execution of SQL and PL/SQL statements
|
* Execution of SQL and PL/SQL statements
|
||||||
* Extensive Oracle data type support, including large objects (CLOB and
|
* Extensive Oracle data type support, including large objects (CLOB and
|
||||||
BLOB) and binding of SQL objects
|
BLOB) and binding of SQL objects
|
||||||
|
|
|
@ -11,15 +11,16 @@ the size of the tablespace storing it.
|
||||||
There are four types of LOB (large object):
|
There are four types of LOB (large object):
|
||||||
|
|
||||||
* BLOB - Binary Large Object, used for storing binary data. cx_Oracle uses
|
* BLOB - Binary Large Object, used for storing binary data. cx_Oracle uses
|
||||||
the type :attr:`cx_Oracle.BLOB`.
|
the type :attr:`cx_Oracle.DB_TYPE_BLOB`.
|
||||||
* CLOB - Character Large Object, used for string strings in the database
|
* CLOB - Character Large Object, used for string strings in the database
|
||||||
character set format. cx_Oracle uses the type :attr:`cx_Oracle.CLOB`.
|
character set format. cx_Oracle uses the type
|
||||||
|
:attr:`cx_Oracle.DB_TYPE_CLOB`.
|
||||||
* NCLOB - National Character Large Object, used for string strings in the
|
* NCLOB - National Character Large Object, used for string strings in the
|
||||||
national character set format. cx_Oracle uses the type
|
national character set format. cx_Oracle uses the type
|
||||||
:attr:`cx_Oracle.NCLOB`.
|
:attr:`cx_Oracle.DB_TYPE_NCLOB`.
|
||||||
* BFILE - External Binary File, used for referencing a file stored on the
|
* BFILE - External Binary File, used for referencing a file stored on the
|
||||||
host operating system outside of the database. cx_Oracle uses the type
|
host operating system outside of the database. cx_Oracle uses the type
|
||||||
:attr:`cx_Oracle.BFILE`.
|
:attr:`cx_Oracle.DB_TYPE_BFILE`.
|
||||||
|
|
||||||
LOBs can be streamed to, and from, Oracle Database.
|
LOBs can be streamed to, and from, Oracle Database.
|
||||||
|
|
||||||
|
@ -76,10 +77,10 @@ to be used as shown in this example:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
|
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
|
||||||
if defaultType == cx_Oracle.CLOB:
|
if defaultType == cx_Oracle.DB_TYPE_CLOB:
|
||||||
return cursor.var(cx_Oracle.LONG_STRING, arraysize=cursor.arraysize)
|
return cursor.var(cx_Oracle.DB_TYPE_LONG, arraysize=cursor.arraysize)
|
||||||
if defaultType == cx_Oracle.BLOB:
|
if defaultType == cx_Oracle.DB_TYPE_BLOB:
|
||||||
return cursor.var(cx_Oracle.LONG_BINARY, arraysize=cursor.arraysize)
|
return cursor.var(cx_Oracle.DB_TYPE_LONG_RAW, arraysize=cursor.arraysize)
|
||||||
|
|
||||||
idVal = 1
|
idVal = 1
|
||||||
textData = "The quick brown fox jumps over the lazy dog"
|
textData = "The quick brown fox jumps over the lazy dog"
|
||||||
|
@ -161,7 +162,7 @@ in the following code:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
idVal = 9
|
idVal = 9
|
||||||
lobVar = cursor.var(cx_Oracle.BLOB)
|
lobVar = cursor.var(cx_Oracle.DB_TYPE_BLOB)
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
insert into lob_tbl (id, b)
|
insert into lob_tbl (id, b)
|
||||||
values (:1, empty_blob())
|
values (:1, empty_blob())
|
||||||
|
|
|
@ -225,8 +225,8 @@ can be obtained using :attr:`Cursor.description`:
|
||||||
|
|
||||||
This could result in metadata like::
|
This could result in metadata like::
|
||||||
|
|
||||||
('ID', <class 'cx_Oracle.NUMBER'>, 39, None, 38, 0, 0)
|
('ID', <class 'cx_Oracle.DB_TYPE_NUMBER'>, 39, None, 38, 0, 0)
|
||||||
('NAME', <class 'cx_Oracle.STRING'>, 20, 20, None, None, 1)
|
('NAME', <class 'cx_Oracle.DB_TYPE_VARCHAR'>, 20, 20, None, None, 1)
|
||||||
|
|
||||||
|
|
||||||
.. _defaultfetchtypes:
|
.. _defaultfetchtypes:
|
||||||
|
@ -236,8 +236,8 @@ Fetch Data Types
|
||||||
|
|
||||||
The following table provides a list of all of the data types that cx_Oracle
|
The following table provides a list of all of the data types that cx_Oracle
|
||||||
knows how to fetch. The middle column gives the type that is returned in the
|
knows how to fetch. The middle column gives the type that is returned in the
|
||||||
:ref:`query metadata <querymetadata>`. The last column gives the type of Python
|
:ref:`query metadata <querymetadata>`. The last column gives the type of
|
||||||
object that is returned by default. Python types can be changed with
|
Python object that is returned by default. Python types can be changed with
|
||||||
:ref:`Output Type Handlers <outputtypehandlers>`.
|
:ref:`Output Type Handlers <outputtypehandlers>`.
|
||||||
|
|
||||||
.. list-table::
|
.. list-table::
|
||||||
|
@ -246,91 +246,87 @@ object that is returned by default. Python types can be changed with
|
||||||
:align: left
|
:align: left
|
||||||
|
|
||||||
* - Oracle Database Type
|
* - Oracle Database Type
|
||||||
- cx_Oracle Type
|
- cx_Oracle Database Type
|
||||||
- Default Python type
|
- Default Python type
|
||||||
* - BFILE
|
* - BFILE
|
||||||
- :attr:`cx_Oracle.BFILE`
|
- :attr:`cx_Oracle.DB_TYPE_BFILE`
|
||||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||||
* - BINARY_DOUBLE
|
* - BINARY_DOUBLE
|
||||||
- :attr:`cx_Oracle.NATIVE_FLOAT`
|
- :attr:`cx_Oracle.DB_TYPE_BINARY_DOUBLE`
|
||||||
- float
|
- float
|
||||||
* - BINARY_FLOAT
|
* - BINARY_FLOAT
|
||||||
- :attr:`cx_Oracle.NATIVE_FLOAT`
|
- :attr:`cx_Oracle.DB_TYPE_BINARY_FLOAT`
|
||||||
- float
|
- float
|
||||||
* - BLOB
|
* - BLOB
|
||||||
- :attr:`cx_Oracle.BLOB`
|
- :attr:`cx_Oracle.DB_TYPE_BLOB`
|
||||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||||
* - CHAR
|
* - CHAR
|
||||||
- :attr:`cx_Oracle.FIXED_CHAR`
|
- :attr:`cx_Oracle.DB_TYPE_CHAR`
|
||||||
- str
|
- str
|
||||||
* - CLOB
|
* - CLOB
|
||||||
- :attr:`cx_Oracle.CLOB`
|
- :attr:`cx_Oracle.DB_TYPE_CLOB`
|
||||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||||
* - CURSOR
|
* - CURSOR
|
||||||
- :attr:`cx_Oracle.CURSOR`
|
- :attr:`cx_Oracle.DB_TYPE_CURSOR`
|
||||||
- :ref:`cx_Oracle.Cursor <cursorobj>`
|
- :ref:`cx_Oracle.Cursor <cursorobj>`
|
||||||
* - DATE
|
* - DATE
|
||||||
- :attr:`cx_Oracle.DATETIME`
|
- :attr:`cx_Oracle.DB_TYPE_DATE`
|
||||||
- datetime.datetime
|
- datetime.datetime
|
||||||
* - INTERVAL DAY TO SECOND
|
* - INTERVAL DAY TO SECOND
|
||||||
- :attr:`cx_Oracle.INTERVAL`
|
- :attr:`cx_Oracle.DB_TYPE_INTERVAL_DS`
|
||||||
- datetime.timedelta
|
- datetime.timedelta
|
||||||
* - LONG
|
* - LONG
|
||||||
- :attr:`cx_Oracle.LONG_STRING`
|
- :attr:`cx_Oracle.DB_TYPE_LONG`
|
||||||
- str
|
- str
|
||||||
* - LONG RAW
|
* - LONG RAW
|
||||||
- :attr:`cx_Oracle.LONG_BINARY`
|
- :attr:`cx_Oracle.DB_TYPE_LONG_RAW`
|
||||||
- bytes [4]_
|
- bytes
|
||||||
* - NCHAR
|
* - NCHAR
|
||||||
- :attr:`cx_Oracle.FIXED_NCHAR`
|
- :attr:`cx_Oracle.DB_TYPE_NCHAR`
|
||||||
- str [1]_
|
- str
|
||||||
* - NCLOB
|
* - NCLOB
|
||||||
- :attr:`cx_Oracle.NCLOB`
|
- :attr:`cx_Oracle.DB_TYPE_NCLOB`
|
||||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||||
* - NUMBER
|
* - NUMBER
|
||||||
- :attr:`cx_Oracle.NUMBER`
|
- :attr:`cx_Oracle.DB_TYPE_NUMBER`
|
||||||
- float or int [2]_
|
- float or int [1]_
|
||||||
* - NVARCHAR2
|
* - NVARCHAR2
|
||||||
- :attr:`cx_Oracle.NCHAR`
|
- :attr:`cx_Oracle.DB_TYPE_NVARCHAR`
|
||||||
- str [1]_
|
- str
|
||||||
* - OBJECT [5]_
|
* - OBJECT [3]_
|
||||||
- :attr:`cx_Oracle.OBJECT`
|
- :attr:`cx_Oracle.DB_TYPE_OBJECT`
|
||||||
- :ref:`cx_Oracle.Object <objecttype>`
|
- :ref:`cx_Oracle.Object <objecttype>`
|
||||||
* - RAW
|
* - RAW
|
||||||
- :attr:`cx_Oracle.BINARY`
|
- :attr:`cx_Oracle.DB_TYPE_RAW`
|
||||||
- bytes [4]_
|
- bytes
|
||||||
* - ROWID
|
* - ROWID
|
||||||
- :attr:`cx_Oracle.ROWID`
|
- :attr:`cx_Oracle.DB_TYPE_ROWID`
|
||||||
- str
|
- str
|
||||||
* - TIMESTAMP
|
* - TIMESTAMP
|
||||||
- :attr:`cx_Oracle.TIMESTAMP`
|
- :attr:`cx_Oracle.DB_TYPE_TIMESTAMP`
|
||||||
- datetime.datetime
|
- datetime.datetime
|
||||||
* - TIMESTAMP WITH LOCAL TIME ZONE
|
* - TIMESTAMP WITH LOCAL TIME ZONE
|
||||||
- :attr:`cx_Oracle.TIMESTAMP`
|
- :attr:`cx_Oracle.DB_TYPE_TIMESTAMP_LTZ`
|
||||||
- datetime.datetime [3]_
|
- datetime.datetime [2]_
|
||||||
* - TIMESTAMP WITH TIME ZONE
|
* - TIMESTAMP WITH TIME ZONE
|
||||||
- :attr:`cx_Oracle.TIMESTAMP`
|
- :attr:`cx_Oracle.DB_TYPE_TIMESTAMP_TZ`
|
||||||
- datetime.datetime [3]_
|
- datetime.datetime [2]_
|
||||||
* - UROWID
|
* - UROWID
|
||||||
- :attr:`cx_Oracle.ROWID`
|
- :attr:`cx_Oracle.DB_TYPE_ROWID`
|
||||||
- str
|
- str
|
||||||
* - VARCHAR2
|
* - VARCHAR2
|
||||||
- :attr:`cx_Oracle.STRING`
|
- :attr:`cx_Oracle.DB_TYPE_VARCHAR`
|
||||||
- str
|
- str
|
||||||
|
|
||||||
.. [1] In Python 2 these are fetched as unicode objects.
|
.. [1] If the precision and scale obtained from query column metadata indicate
|
||||||
.. [2] If the precision and scale obtained from query column metadata indicate
|
|
||||||
that the value can be expressed as an integer, the value will be
|
that the value can be expressed as an integer, the value will be
|
||||||
returned as an int. If the column is unconstrained (no precision and
|
returned as an int. If the column is unconstrained (no precision and
|
||||||
scale specified), the value will be returned as a float or an int
|
scale specified), the value will be returned as a float or an int
|
||||||
depending on whether the value itself is an integer. In all other cases
|
depending on whether the value itself is an integer. In all other cases
|
||||||
the value is returned as a float. Note that in Python 2, values returned
|
the value is returned as a float.
|
||||||
as integers will be int or long depending on the size of the integer.
|
.. [2] The timestamps returned are naive timestamps without any time zone
|
||||||
.. [3] The timestamps returned are naive timestamps without any time zone
|
|
||||||
information present.
|
information present.
|
||||||
.. [4] In Python 2 these are identical to str objects since Python 2 doesn't
|
.. [3] These include all user-defined types such as VARRAY, NESTED TABLE, etc.
|
||||||
have a native bytes object.
|
|
||||||
.. [5] These include all user-defined types such as VARRAY, NESTED TABLE, etc.
|
|
||||||
|
|
||||||
|
|
||||||
.. _outputtypehandlers:
|
.. _outputtypehandlers:
|
||||||
|
@ -399,7 +395,7 @@ Using Python decimal objects, however, there is no loss of precision:
|
||||||
import decimal
|
import decimal
|
||||||
|
|
||||||
def NumberToDecimal(cursor, name, defaultType, size, precision, scale):
|
def NumberToDecimal(cursor, name, defaultType, size, precision, scale):
|
||||||
if defaultType == cx_Oracle.NUMBER:
|
if defaultType == cx_Oracle.DB_TYPE_NUMBER:
|
||||||
return cursor.var(decimal.Decimal, arraysize=cursor.arraysize)
|
return cursor.var(decimal.Decimal, arraysize=cursor.arraysize)
|
||||||
|
|
||||||
cur = connection.cursor()
|
cur = connection.cursor()
|
||||||
|
@ -432,7 +428,7 @@ For example, to make queries return empty strings instead of NULLs:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
|
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
|
||||||
if defaultType in (cx_Oracle.STRING, cx_Oracle.FIXED_CHAR):
|
if defaultType in (cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.DB_TYPE_CHAR):
|
||||||
return cursor.var(str, size, cur.arraysize, outconverter=OutConverter)
|
return cursor.var(str, size, cur.arraysize, outconverter=OutConverter)
|
||||||
|
|
||||||
connection.outputtypehandler = OutputTypeHandler
|
connection.outputtypehandler = OutputTypeHandler
|
||||||
|
|
|
@ -38,7 +38,7 @@ as shown:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
clob = connection.createlob(cx_Oracle.CLOB)
|
clob = connection.createlob(cx_Oracle.DB_TYPE_CLOB)
|
||||||
clob.write(xmlData)
|
clob.write(xmlData)
|
||||||
cursor.execute("insert into xml_table values (:id, sys.xmltype(:xml))",
|
cursor.execute("insert into xml_table values (:id, sys.xmltype(:xml))",
|
||||||
id=2, xml=clob)
|
id=2, xml=clob)
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoApiType.c
|
||||||
|
// Defines the objects used for identifying types defined by the Python
|
||||||
|
// Database API.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cxoModule.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// declaration of functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static void cxoApiType_free(cxoApiType*);
|
||||||
|
static PyObject *cxoApiType_repr(cxoApiType*);
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// declaration of members
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyMemberDef cxoMembers[] = {
|
||||||
|
{ "name", T_STRING, offsetof(cxoApiType, name), READONLY },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Python type declaration
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
PyTypeObject cxoPyTypeApiType = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
.tp_name = "cx_Oracle.ApiType",
|
||||||
|
.tp_basicsize = sizeof(cxoApiType),
|
||||||
|
.tp_dealloc = (destructor) cxoApiType_free,
|
||||||
|
.tp_repr = (reprfunc) cxoApiType_repr,
|
||||||
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
|
.tp_members = cxoMembers
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoApiType_free()
|
||||||
|
// Free the API type object.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static void cxoApiType_free(cxoApiType *apiType)
|
||||||
|
{
|
||||||
|
Py_CLEAR(apiType->dbTypes);
|
||||||
|
Py_TYPE(apiType)->tp_free((PyObject*) apiType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoApiType_repr()
|
||||||
|
// Return a string representation of a queue.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyObject *cxoApiType_repr(cxoApiType *apiType)
|
||||||
|
{
|
||||||
|
PyObject *module, *name, *apiTypeName, *result;
|
||||||
|
|
||||||
|
apiTypeName = PyUnicode_DecodeASCII(apiType->name, strlen(apiType->name),
|
||||||
|
NULL);
|
||||||
|
if (!apiTypeName)
|
||||||
|
return NULL;
|
||||||
|
if (cxoUtils_getModuleAndName(Py_TYPE(apiType), &module, &name) < 0) {
|
||||||
|
Py_DECREF(apiTypeName);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = cxoUtils_formatString("<%s.%s %s>",
|
||||||
|
PyTuple_Pack(3, module, name, apiTypeName));
|
||||||
|
Py_DECREF(module);
|
||||||
|
Py_DECREF(name);
|
||||||
|
Py_DECREF(apiTypeName);
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -347,7 +347,7 @@ static int cxoConnectionParams_processShardingKeyValue(
|
||||||
dpiNativeTypeNum nativeTypeNum;
|
dpiNativeTypeNum nativeTypeNum;
|
||||||
cxoTransformNum transformNum;
|
cxoTransformNum transformNum;
|
||||||
|
|
||||||
transformNum = cxoTransform_getNumFromValue(value, 0);
|
transformNum = cxoTransform_getNumFromPythonValue(value, 0);
|
||||||
if (cxoTransform_fromPython(transformNum, &nativeTypeNum, value,
|
if (cxoTransform_fromPython(transformNum, &nativeTypeNum, value,
|
||||||
&column->value, buffer, params->encoding, params->nencoding, NULL,
|
&column->value, buffer, params->encoding, params->nencoding, NULL,
|
||||||
0) < 0)
|
0) < 0)
|
||||||
|
@ -1011,7 +1011,7 @@ static PyObject *cxoConnection_getType(cxoConnection *conn, PyObject *nameObj)
|
||||||
static PyObject *cxoConnection_createLob(cxoConnection *conn,
|
static PyObject *cxoConnection_createLob(cxoConnection *conn,
|
||||||
PyObject *lobType)
|
PyObject *lobType)
|
||||||
{
|
{
|
||||||
dpiOracleTypeNum oracleTypeNum;
|
cxoDbType *dbType;
|
||||||
dpiLob *handle;
|
dpiLob *handle;
|
||||||
PyObject *lob;
|
PyObject *lob;
|
||||||
|
|
||||||
|
@ -1020,23 +1020,20 @@ static PyObject *cxoConnection_createLob(cxoConnection *conn,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// verify the LOB type
|
// verify the LOB type
|
||||||
if (lobType == (PyObject*) &cxoPyTypeClobVar)
|
if (lobType != (PyObject*) cxoDbTypeClob &&
|
||||||
oracleTypeNum = DPI_ORACLE_TYPE_CLOB;
|
lobType != (PyObject*) cxoDbTypeBlob &&
|
||||||
else if (lobType == (PyObject*) &cxoPyTypeBlobVar)
|
lobType != (PyObject*) cxoDbTypeNclob) {
|
||||||
oracleTypeNum = DPI_ORACLE_TYPE_BLOB;
|
|
||||||
else if (lobType == (PyObject*) &cxoPyTypeNclobVar)
|
|
||||||
oracleTypeNum = DPI_ORACLE_TYPE_NCLOB;
|
|
||||||
else {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"parameter should be one of cx_Oracle.CLOB, cx_Oracle.BLOB "
|
"parameter should be one of cx_Oracle.DB_TYPE_CLOB, "
|
||||||
"or cx_Oracle.NCLOB");
|
"cx_Oracle.DB_TYPE_BLOB or cx_Oracle.DB_TYPE_NCLOB");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a temporary LOB
|
// create a temporary LOB
|
||||||
if (dpiConn_newTempLob(conn->handle, oracleTypeNum, &handle) < 0)
|
dbType = (cxoDbType*) lobType;
|
||||||
|
if (dpiConn_newTempLob(conn->handle, dbType->num, &handle) < 0)
|
||||||
return cxoError_raiseAndReturnNull();
|
return cxoError_raiseAndReturnNull();
|
||||||
lob = cxoLob_new(conn, oracleTypeNum, handle);
|
lob = cxoLob_new(conn, dbType, handle);
|
||||||
if (!lob)
|
if (!lob)
|
||||||
dpiLob_release(handle);
|
dpiLob_release(handle);
|
||||||
return lob;
|
return lob;
|
||||||
|
|
|
@ -329,10 +329,12 @@ static int cxoCursor_fetchRow(cxoCursor *cursor, int *found,
|
||||||
static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
||||||
{
|
{
|
||||||
PyObject *outputTypeHandler, *result;
|
PyObject *outputTypeHandler, *result;
|
||||||
|
cxoTransformNum transformNum;
|
||||||
cxoObjectType *objectType;
|
cxoObjectType *objectType;
|
||||||
cxoVarType *varType;
|
|
||||||
dpiQueryInfo queryInfo;
|
dpiQueryInfo queryInfo;
|
||||||
uint32_t pos, size;
|
uint32_t pos, size;
|
||||||
|
cxoDbType *dbType;
|
||||||
|
char message[120];
|
||||||
cxoVar *var;
|
cxoVar *var;
|
||||||
|
|
||||||
// initialize fetching variables; these are used to reduce the number of
|
// initialize fetching variables; these are used to reduce the number of
|
||||||
|
@ -372,9 +374,17 @@ static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the default type
|
// determine the default types to use
|
||||||
varType = cxoVarType_fromDataTypeInfo(&queryInfo.typeInfo);
|
transformNum =
|
||||||
if (!varType)
|
cxoTransform_getNumFromDataTypeInfo(&queryInfo.typeInfo);
|
||||||
|
if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
|
||||||
|
snprintf(message, sizeof(message), "Oracle type %d not supported.",
|
||||||
|
queryInfo.typeInfo.oracleTypeNum);
|
||||||
|
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dbType = cxoDbType_fromTransformNum(transformNum);
|
||||||
|
if (!dbType)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// see if an output type handler should be used
|
// see if an output type handler should be used
|
||||||
|
@ -390,7 +400,7 @@ static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
||||||
if (outputTypeHandler) {
|
if (outputTypeHandler) {
|
||||||
result = PyObject_CallFunction(outputTypeHandler, "Os#Oiii",
|
result = PyObject_CallFunction(outputTypeHandler, "Os#Oiii",
|
||||||
cursor, queryInfo.name, (Py_ssize_t) queryInfo.nameLength,
|
cursor, queryInfo.name, (Py_ssize_t) queryInfo.nameLength,
|
||||||
varType->pythonType, size, queryInfo.typeInfo.precision,
|
dbType, size, queryInfo.typeInfo.precision,
|
||||||
queryInfo.typeInfo.scale);
|
queryInfo.typeInfo.scale);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
Py_XDECREF(objectType);
|
Py_XDECREF(objectType);
|
||||||
|
@ -418,8 +428,8 @@ static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
||||||
|
|
||||||
// if no variable created yet, use the database metadata
|
// if no variable created yet, use the database metadata
|
||||||
if (!var) {
|
if (!var) {
|
||||||
var = cxoVar_new(cursor, cursor->fetchArraySize, varType, size, 0,
|
var = cxoVar_new(cursor, cursor->fetchArraySize, transformNum,
|
||||||
objectType);
|
size, 0, objectType);
|
||||||
if (!var) {
|
if (!var) {
|
||||||
Py_XDECREF(objectType);
|
Py_XDECREF(objectType);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -444,16 +454,16 @@ static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyObject *cxoCursor_itemDescription(cxoCursor *cursor, uint32_t pos)
|
static PyObject *cxoCursor_itemDescription(cxoCursor *cursor, uint32_t pos)
|
||||||
{
|
{
|
||||||
cxoVarType *varType;
|
|
||||||
int displaySize, index;
|
int displaySize, index;
|
||||||
dpiQueryInfo queryInfo;
|
dpiQueryInfo queryInfo;
|
||||||
PyObject *tuple, *temp;
|
PyObject *tuple, *temp;
|
||||||
|
cxoDbType *dbType;
|
||||||
|
|
||||||
// get information about the column position
|
// get information about the column position
|
||||||
if (dpiStmt_getQueryInfo(cursor->handle, pos, &queryInfo) < 0)
|
if (dpiStmt_getQueryInfo(cursor->handle, pos, &queryInfo) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
varType = cxoVarType_fromDataTypeInfo(&queryInfo.typeInfo);
|
dbType = cxoDbType_fromDataTypeInfo(&queryInfo.typeInfo);
|
||||||
if (!varType)
|
if (!dbType)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// set display size based on data type
|
// set display size based on data type
|
||||||
|
@ -496,8 +506,8 @@ static PyObject *cxoCursor_itemDescription(cxoCursor *cursor, uint32_t pos)
|
||||||
PyTuple_SET_ITEM(tuple, 0, PyUnicode_Decode(queryInfo.name,
|
PyTuple_SET_ITEM(tuple, 0, PyUnicode_Decode(queryInfo.name,
|
||||||
queryInfo.nameLength, cursor->connection->encodingInfo.encoding,
|
queryInfo.nameLength, cursor->connection->encodingInfo.encoding,
|
||||||
NULL));
|
NULL));
|
||||||
Py_INCREF(varType->pythonType);
|
Py_INCREF(dbType);
|
||||||
PyTuple_SET_ITEM(tuple, 1, (PyObject*) varType->pythonType);
|
PyTuple_SET_ITEM(tuple, 1, (PyObject*) dbType);
|
||||||
if (displaySize)
|
if (displaySize)
|
||||||
PyTuple_SET_ITEM(tuple, 2, PyLong_FromLong(displaySize));
|
PyTuple_SET_ITEM(tuple, 2, PyLong_FromLong(displaySize));
|
||||||
else {
|
else {
|
||||||
|
@ -673,7 +683,7 @@ static int cxoCursor_setBindVariableHelper(cxoCursor *cursor,
|
||||||
// can happen if all of the values in a previous invocation of
|
// can happen if all of the values in a previous invocation of
|
||||||
// executemany() were None) and there is now a value; in this case,
|
// executemany() were None) and there is now a value; in this case,
|
||||||
// discard the original variable and have a new one created
|
// discard the original variable and have a new one created
|
||||||
if (origVar->type->transformNum == CXO_TRANSFORM_NONE &&
|
if (origVar->transformNum == CXO_TRANSFORM_NONE &&
|
||||||
value != Py_None) {
|
value != Py_None) {
|
||||||
origVar = NULL;
|
origVar = NULL;
|
||||||
varToSet = NULL;
|
varToSet = NULL;
|
||||||
|
@ -682,8 +692,9 @@ static int cxoCursor_setBindVariableHelper(cxoCursor *cursor,
|
||||||
// variable this is only necessary for executemany() since
|
// variable this is only necessary for executemany() since
|
||||||
// execute() always passes a value of 1 for the number of elements
|
// execute() always passes a value of 1 for the number of elements
|
||||||
} else if (numElements > origVar->allocatedElements) {
|
} else if (numElements > origVar->allocatedElements) {
|
||||||
*newVar = cxoVar_new(cursor, numElements, origVar->type,
|
*newVar = cxoVar_new(cursor, numElements,
|
||||||
origVar->size, origVar->isArray, origVar->objectType);
|
origVar->transformNum, origVar->size, origVar->isArray,
|
||||||
|
origVar->objectType);
|
||||||
if (!*newVar)
|
if (!*newVar)
|
||||||
return -1;
|
return -1;
|
||||||
varToSet = *newVar;
|
varToSet = *newVar;
|
||||||
|
@ -1826,9 +1837,9 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
||||||
"inconverter", "outconverter", "typename", "encodingErrors",
|
"inconverter", "outconverter", "typename", "encodingErrors",
|
||||||
NULL };
|
NULL };
|
||||||
PyObject *inConverter, *outConverter, *typeNameObj;
|
PyObject *inConverter, *outConverter, *typeNameObj;
|
||||||
|
cxoTransformNum transformNum;
|
||||||
const char *encodingErrors;
|
const char *encodingErrors;
|
||||||
cxoObjectType *objType;
|
cxoObjectType *objType;
|
||||||
cxoVarType *varType;
|
|
||||||
int size, arraySize;
|
int size, arraySize;
|
||||||
PyObject *type;
|
PyObject *type;
|
||||||
cxoVar *var;
|
cxoVar *var;
|
||||||
|
@ -1844,12 +1855,9 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// determine the type of variable
|
// determine the type of variable
|
||||||
varType = cxoVarType_fromPythonType(type, &objType);
|
if (cxoTransform_getNumFromType(type, &transformNum, &objType) < 0)
|
||||||
if (!varType)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
Py_XINCREF(objType);
|
Py_XINCREF(objType);
|
||||||
if (size == 0)
|
|
||||||
size = varType->size;
|
|
||||||
if (typeNameObj && typeNameObj != Py_None && !objType) {
|
if (typeNameObj && typeNameObj != Py_None && !objType) {
|
||||||
objType = cxoObjectType_newByName(cursor->connection, typeNameObj);
|
objType = cxoObjectType_newByName(cursor->connection, typeNameObj);
|
||||||
if (!objType)
|
if (!objType)
|
||||||
|
@ -1857,7 +1865,7 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the variable
|
// create the variable
|
||||||
var = cxoVar_new(cursor, arraySize, varType, size, 0, objType);
|
var = cxoVar_new(cursor, arraySize, transformNum, size, 0, objType);
|
||||||
Py_XDECREF(objType);
|
Py_XDECREF(objType);
|
||||||
if (!var)
|
if (!var)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1886,23 +1894,20 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyObject *cxoCursor_arrayVar(cxoCursor *cursor, PyObject *args)
|
static PyObject *cxoCursor_arrayVar(cxoCursor *cursor, PyObject *args)
|
||||||
{
|
{
|
||||||
|
cxoTransformNum transformNum;
|
||||||
uint32_t size, numElements;
|
uint32_t size, numElements;
|
||||||
PyObject *type, *value;
|
PyObject *type, *value;
|
||||||
cxoObjectType *objType;
|
cxoObjectType *objType;
|
||||||
cxoVarType *varType;
|
|
||||||
cxoVar *var;
|
cxoVar *var;
|
||||||
|
|
||||||
// parse arguments
|
// parse arguments
|
||||||
size = 0;
|
size = 0;
|
||||||
if (!PyArg_ParseTuple(args, "O!O|i", &PyType_Type, &type, &value, &size))
|
if (!PyArg_ParseTuple(args, "OO|i", &type, &value, &size))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// determine the type of variable
|
// determine the transform to use for the variable
|
||||||
varType = cxoVarType_fromPythonType(type, &objType);
|
if (cxoTransform_getNumFromType(type, &transformNum, &objType) < 0)
|
||||||
if (!varType)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
if (size == 0)
|
|
||||||
size = varType->size;
|
|
||||||
|
|
||||||
// determine the number of elements to create
|
// determine the number of elements to create
|
||||||
if (PyList_Check(value))
|
if (PyList_Check(value))
|
||||||
|
@ -1918,7 +1923,7 @@ static PyObject *cxoCursor_arrayVar(cxoCursor *cursor, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the variable
|
// create the variable
|
||||||
var = cxoVar_new(cursor, numElements, varType, size, 1, objType);
|
var = cxoVar_new(cursor, numElements, transformNum, size, 1, objType);
|
||||||
if (!var)
|
if (!var)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoDbType.c
|
||||||
|
// Defines the objects used for identifying all types used by the database.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "cxoModule.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// declaration of functions
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static void cxoDbType_free(cxoDbType*);
|
||||||
|
static PyObject *cxoDbType_repr(cxoDbType*);
|
||||||
|
static PyObject *cxoDbType_richCompare(cxoDbType*, PyObject*, int);
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// declaration of members
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyMemberDef cxoMembers[] = {
|
||||||
|
{ "name", T_STRING, offsetof(cxoDbType, name), READONLY },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Python type declaration
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
PyTypeObject cxoPyTypeDbType = {
|
||||||
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
.tp_name = "cx_Oracle.DbType",
|
||||||
|
.tp_basicsize = sizeof(cxoDbType),
|
||||||
|
.tp_dealloc = (destructor) cxoDbType_free,
|
||||||
|
.tp_repr = (reprfunc) cxoDbType_repr,
|
||||||
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
|
.tp_members = cxoMembers,
|
||||||
|
.tp_richcompare = (richcmpfunc) cxoDbType_richCompare
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoDbType_free()
|
||||||
|
// Free the database type object.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static void cxoDbType_free(cxoDbType *dbType)
|
||||||
|
{
|
||||||
|
Py_TYPE(dbType)->tp_free((PyObject*) dbType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoDbType_repr()
|
||||||
|
// Return a string representation of a queue.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyObject *cxoDbType_repr(cxoDbType *dbType)
|
||||||
|
{
|
||||||
|
PyObject *module, *name, *dbTypeName, *result;
|
||||||
|
|
||||||
|
dbTypeName = PyUnicode_DecodeASCII(dbType->name, strlen(dbType->name),
|
||||||
|
NULL);
|
||||||
|
if (!dbTypeName)
|
||||||
|
return NULL;
|
||||||
|
if (cxoUtils_getModuleAndName(Py_TYPE(dbType), &module, &name) < 0) {
|
||||||
|
Py_DECREF(dbTypeName);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = cxoUtils_formatString("<%s.%s %s>",
|
||||||
|
PyTuple_Pack(3, module, name, dbTypeName));
|
||||||
|
Py_DECREF(module);
|
||||||
|
Py_DECREF(name);
|
||||||
|
Py_DECREF(dbTypeName);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoDbType_richCompare()
|
||||||
|
// Peforms a comparison between the database type and another Python object.
|
||||||
|
// Equality (and inequality) are used to match database API types with their
|
||||||
|
// associated database types.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyObject *cxoDbType_richCompare(cxoDbType* dbType, PyObject* obj,
|
||||||
|
int op)
|
||||||
|
{
|
||||||
|
cxoApiType *apiType;
|
||||||
|
int status, equal;
|
||||||
|
|
||||||
|
// only equality and inequality can be checked
|
||||||
|
if (op != Py_EQ && op != Py_NE) {
|
||||||
|
Py_INCREF(Py_NotImplemented);
|
||||||
|
return Py_NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for exact object
|
||||||
|
equal = 0;
|
||||||
|
if (obj == (PyObject*) dbType) {
|
||||||
|
equal = 1;
|
||||||
|
|
||||||
|
// check for API type
|
||||||
|
} else {
|
||||||
|
status = PyObject_IsInstance(obj, (PyObject*) &cxoPyTypeApiType);
|
||||||
|
if (status < 0)
|
||||||
|
return NULL;
|
||||||
|
if (status == 1) {
|
||||||
|
apiType = (cxoApiType*) obj;
|
||||||
|
status = PySequence_Contains(apiType->dbTypes, (PyObject*) dbType);
|
||||||
|
if (status < 0)
|
||||||
|
return NULL;
|
||||||
|
equal = (status == 1) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine return value
|
||||||
|
if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoDbType_fromDataTypeInfo()
|
||||||
|
// Return the database type given the data type info available from ODPI-C.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
cxoDbType *cxoDbType_fromDataTypeInfo(dpiDataTypeInfo *info)
|
||||||
|
{
|
||||||
|
char message[120];
|
||||||
|
|
||||||
|
switch (info->oracleTypeNum) {
|
||||||
|
case DPI_ORACLE_TYPE_VARCHAR:
|
||||||
|
return cxoDbTypeVarchar;
|
||||||
|
case DPI_ORACLE_TYPE_NVARCHAR:
|
||||||
|
return cxoDbTypeNvarchar;
|
||||||
|
case DPI_ORACLE_TYPE_CHAR:
|
||||||
|
return cxoDbTypeChar;
|
||||||
|
case DPI_ORACLE_TYPE_NCHAR:
|
||||||
|
return cxoDbTypeNchar;
|
||||||
|
case DPI_ORACLE_TYPE_ROWID:
|
||||||
|
return cxoDbTypeRowid;
|
||||||
|
case DPI_ORACLE_TYPE_RAW:
|
||||||
|
return cxoDbTypeRaw;
|
||||||
|
case DPI_ORACLE_TYPE_NATIVE_DOUBLE:
|
||||||
|
return cxoDbTypeBinaryDouble;
|
||||||
|
case DPI_ORACLE_TYPE_NATIVE_FLOAT:
|
||||||
|
return cxoDbTypeBinaryFloat;
|
||||||
|
case DPI_ORACLE_TYPE_NATIVE_INT:
|
||||||
|
return cxoDbTypeBinaryInteger;
|
||||||
|
case DPI_ORACLE_TYPE_NUMBER:
|
||||||
|
return cxoDbTypeNumber;
|
||||||
|
case DPI_ORACLE_TYPE_DATE:
|
||||||
|
return cxoDbTypeDate;
|
||||||
|
case DPI_ORACLE_TYPE_TIMESTAMP:
|
||||||
|
return cxoDbTypeTimestamp;
|
||||||
|
case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
|
||||||
|
return cxoDbTypeTimestampTZ;
|
||||||
|
case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
|
||||||
|
return cxoDbTypeTimestampLTZ;
|
||||||
|
case DPI_ORACLE_TYPE_INTERVAL_DS:
|
||||||
|
return cxoDbTypeIntervalDS;
|
||||||
|
case DPI_ORACLE_TYPE_INTERVAL_YM:
|
||||||
|
return cxoDbTypeIntervalYM;
|
||||||
|
case DPI_ORACLE_TYPE_CLOB:
|
||||||
|
return cxoDbTypeClob;
|
||||||
|
case DPI_ORACLE_TYPE_NCLOB:
|
||||||
|
return cxoDbTypeNclob;
|
||||||
|
case DPI_ORACLE_TYPE_BLOB:
|
||||||
|
return cxoDbTypeBlob;
|
||||||
|
case DPI_ORACLE_TYPE_BFILE:
|
||||||
|
return cxoDbTypeBfile;
|
||||||
|
case DPI_ORACLE_TYPE_STMT:
|
||||||
|
return cxoDbTypeCursor;
|
||||||
|
case DPI_ORACLE_TYPE_OBJECT:
|
||||||
|
return cxoDbTypeObject;
|
||||||
|
case DPI_ORACLE_TYPE_LONG_VARCHAR:
|
||||||
|
return cxoDbTypeLong;
|
||||||
|
case DPI_ORACLE_TYPE_LONG_RAW:
|
||||||
|
return cxoDbTypeLongRaw;
|
||||||
|
case DPI_ORACLE_TYPE_BOOLEAN:
|
||||||
|
return cxoDbTypeBoolean;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(message, sizeof(message), "Oracle type %d not supported.",
|
||||||
|
info->oracleTypeNum);
|
||||||
|
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoDbType_fromTransformNum()
|
||||||
|
// Return the database type given the transformation number.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
cxoDbType *cxoDbType_fromTransformNum(cxoTransformNum transformNum)
|
||||||
|
{
|
||||||
|
char message[120];
|
||||||
|
|
||||||
|
switch (transformNum) {
|
||||||
|
case CXO_TRANSFORM_BINARY:
|
||||||
|
return cxoDbTypeRaw;
|
||||||
|
case CXO_TRANSFORM_BFILE:
|
||||||
|
return cxoDbTypeBfile;
|
||||||
|
case CXO_TRANSFORM_BLOB:
|
||||||
|
return cxoDbTypeBlob;
|
||||||
|
case CXO_TRANSFORM_BOOLEAN:
|
||||||
|
return cxoDbTypeBoolean;
|
||||||
|
case CXO_TRANSFORM_CLOB:
|
||||||
|
return cxoDbTypeClob;
|
||||||
|
case CXO_TRANSFORM_CURSOR:
|
||||||
|
return cxoDbTypeCursor;
|
||||||
|
case CXO_TRANSFORM_DATE:
|
||||||
|
case CXO_TRANSFORM_DATETIME:
|
||||||
|
return cxoDbTypeDate;
|
||||||
|
case CXO_TRANSFORM_DECIMAL:
|
||||||
|
case CXO_TRANSFORM_FLOAT:
|
||||||
|
case CXO_TRANSFORM_INT:
|
||||||
|
return cxoDbTypeNumber;
|
||||||
|
case CXO_TRANSFORM_FIXED_CHAR:
|
||||||
|
return cxoDbTypeChar;
|
||||||
|
case CXO_TRANSFORM_FIXED_NCHAR:
|
||||||
|
return cxoDbTypeNchar;
|
||||||
|
case CXO_TRANSFORM_LONG_BINARY:
|
||||||
|
return cxoDbTypeLongRaw;
|
||||||
|
case CXO_TRANSFORM_LONG_STRING:
|
||||||
|
return cxoDbTypeLong;
|
||||||
|
case CXO_TRANSFORM_NATIVE_DOUBLE:
|
||||||
|
return cxoDbTypeBinaryDouble;
|
||||||
|
case CXO_TRANSFORM_NATIVE_FLOAT:
|
||||||
|
return cxoDbTypeBinaryFloat;
|
||||||
|
case CXO_TRANSFORM_NATIVE_INT:
|
||||||
|
return cxoDbTypeBinaryInteger;
|
||||||
|
case CXO_TRANSFORM_NCLOB:
|
||||||
|
return cxoDbTypeNclob;
|
||||||
|
case CXO_TRANSFORM_NSTRING:
|
||||||
|
return cxoDbTypeNvarchar;
|
||||||
|
case CXO_TRANSFORM_OBJECT:
|
||||||
|
return cxoDbTypeObject;
|
||||||
|
case CXO_TRANSFORM_ROWID:
|
||||||
|
return cxoDbTypeRowid;
|
||||||
|
case CXO_TRANSFORM_NONE:
|
||||||
|
case CXO_TRANSFORM_STRING:
|
||||||
|
return cxoDbTypeVarchar;
|
||||||
|
case CXO_TRANSFORM_TIMEDELTA:
|
||||||
|
return cxoDbTypeIntervalDS;
|
||||||
|
case CXO_TRANSFORM_TIMESTAMP:
|
||||||
|
return cxoDbTypeTimestamp;
|
||||||
|
case CXO_TRANSFORM_TIMESTAMP_LTZ:
|
||||||
|
return cxoDbTypeTimestampLTZ;
|
||||||
|
case CXO_TRANSFORM_TIMESTAMP_TZ:
|
||||||
|
return cxoDbTypeTimestampTZ;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(message, sizeof(message), "transform %d not supported.",
|
||||||
|
transformNum);
|
||||||
|
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
||||||
|
return NULL;
|
||||||
|
}
|
30
src/cxoLob.c
30
src/cxoLob.c
|
@ -34,7 +34,7 @@ static PyObject *cxoLob_reduce(cxoLob*);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of methods for Python type "LOB"
|
// declaration of methods
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyMethodDef cxoLobMethods[] = {
|
static PyMethodDef cxoLobMethods[] = {
|
||||||
{ "size", (PyCFunction) cxoLob_size, METH_NOARGS },
|
{ "size", (PyCFunction) cxoLob_size, METH_NOARGS },
|
||||||
|
@ -53,6 +53,15 @@ static PyMethodDef cxoLobMethods[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// declaration of members
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyMemberDef cxoMembers[] = {
|
||||||
|
{ "type", T_OBJECT, offsetof(cxoLob, dbType), READONLY },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Python type declaration
|
// Python type declaration
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -63,7 +72,8 @@ PyTypeObject cxoPyTypeLob = {
|
||||||
.tp_dealloc = (destructor) cxoLob_free,
|
.tp_dealloc = (destructor) cxoLob_free,
|
||||||
.tp_str = (reprfunc) cxoLob_str,
|
.tp_str = (reprfunc) cxoLob_str,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_methods = cxoLobMethods
|
.tp_methods = cxoLobMethods,
|
||||||
|
.tp_members = cxoMembers
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +81,7 @@ PyTypeObject cxoPyTypeLob = {
|
||||||
// cxoLob_new()
|
// cxoLob_new()
|
||||||
// Create a new LOB.
|
// Create a new LOB.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
|
PyObject *cxoLob_new(cxoConnection *connection, cxoDbType *dbType,
|
||||||
dpiLob *handle)
|
dpiLob *handle)
|
||||||
{
|
{
|
||||||
cxoLob *lob;
|
cxoLob *lob;
|
||||||
|
@ -80,9 +90,10 @@ PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
|
||||||
if (!lob)
|
if (!lob)
|
||||||
return NULL;
|
return NULL;
|
||||||
lob->handle = handle;
|
lob->handle = handle;
|
||||||
lob->oracleTypeNum = oracleTypeNum;
|
|
||||||
Py_INCREF(connection);
|
Py_INCREF(connection);
|
||||||
lob->connection = connection;
|
lob->connection = connection;
|
||||||
|
Py_INCREF(dbType);
|
||||||
|
lob->dbType = dbType;
|
||||||
return (PyObject*) lob;
|
return (PyObject*) lob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +108,7 @@ static void cxoLob_free(cxoLob *lob)
|
||||||
dpiLob_release(lob->handle);
|
dpiLob_release(lob->handle);
|
||||||
lob->handle = NULL;
|
lob->handle = NULL;
|
||||||
}
|
}
|
||||||
|
Py_CLEAR(lob->dbType);
|
||||||
Py_CLEAR(lob->connection);
|
Py_CLEAR(lob->connection);
|
||||||
Py_TYPE(lob)->tp_free((PyObject*) lob);
|
Py_TYPE(lob)->tp_free((PyObject*) lob);
|
||||||
}
|
}
|
||||||
|
@ -141,13 +153,15 @@ static PyObject *cxoLob_internalRead(cxoLob *lob, uint64_t offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the result
|
// return the result
|
||||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
|
if (lob->dbType == cxoDbTypeNclob) {
|
||||||
result = PyUnicode_Decode(buffer, (Py_ssize_t) bufferSize,
|
result = PyUnicode_Decode(buffer, (Py_ssize_t) bufferSize,
|
||||||
lob->connection->encodingInfo.nencoding, NULL);
|
lob->connection->encodingInfo.nencoding, NULL);
|
||||||
else if (lob->oracleTypeNum == DPI_ORACLE_TYPE_CLOB)
|
} else if (lob->dbType == cxoDbTypeClob) {
|
||||||
result = PyUnicode_Decode(buffer, (Py_ssize_t) bufferSize,
|
result = PyUnicode_Decode(buffer, (Py_ssize_t) bufferSize,
|
||||||
lob->connection->encodingInfo.encoding, NULL);
|
lob->connection->encodingInfo.encoding, NULL);
|
||||||
else result = PyBytes_FromStringAndSize(buffer, (Py_ssize_t) bufferSize);
|
} else {
|
||||||
|
result = PyBytes_FromStringAndSize(buffer, (Py_ssize_t) bufferSize);
|
||||||
|
}
|
||||||
PyMem_Free(buffer);
|
PyMem_Free(buffer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +178,7 @@ static int cxoLob_internalWrite(cxoLob *lob, PyObject *dataObj,
|
||||||
cxoBuffer buffer;
|
cxoBuffer buffer;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
|
if (lob->dbType == cxoDbTypeNclob)
|
||||||
encoding = lob->connection->encodingInfo.nencoding;
|
encoding = lob->connection->encodingInfo.nencoding;
|
||||||
else encoding = lob->connection->encodingInfo.encoding;
|
else encoding = lob->connection->encodingInfo.encoding;
|
||||||
if (cxoBuffer_fromObject(&buffer, dataObj, encoding) < 0)
|
if (cxoBuffer_fromObject(&buffer, dataObj, encoding) < 0)
|
||||||
|
|
262
src/cxoModule.c
262
src/cxoModule.c
|
@ -21,6 +21,21 @@
|
||||||
if (PyModule_AddIntConstant(module, name, value) < 0) \
|
if (PyModule_AddIntConstant(module, name, value) < 0) \
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
// define macro for adding Python Database API types
|
||||||
|
#define CXO_ADD_API_TYPE(name, transformNum, typeObj) \
|
||||||
|
if (cxoModule_addApiType(module, name, transformNum, typeObj) < 0) \
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// define macro for adding database types
|
||||||
|
#define CXO_ADD_DB_TYPE(num, name, transformNum, typeObj) \
|
||||||
|
if (cxoModule_addDbType(module, num, name, transformNum, typeObj) < 0) \
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// define macro for associating database types with Database API types
|
||||||
|
#define CXO_ASSOCIATE_DB_TYPE(apiType, dbType) \
|
||||||
|
if (PyList_Append(apiType->dbTypes, (PyObject*) dbType) < 0) \
|
||||||
|
return NULL;
|
||||||
|
|
||||||
// define macro for adding type objects
|
// define macro for adding type objects
|
||||||
#define CXO_ADD_TYPE_OBJECT(name, type) \
|
#define CXO_ADD_TYPE_OBJECT(name, type) \
|
||||||
Py_INCREF(type); \
|
Py_INCREF(type); \
|
||||||
|
@ -48,10 +63,98 @@ PyObject *cxoProgrammingErrorException = NULL;
|
||||||
PyObject *cxoNotSupportedErrorException = NULL;
|
PyObject *cxoNotSupportedErrorException = NULL;
|
||||||
PyObject *cxoJsonDumpFunction = NULL;
|
PyObject *cxoJsonDumpFunction = NULL;
|
||||||
PyObject *cxoJsonLoadFunction = NULL;
|
PyObject *cxoJsonLoadFunction = NULL;
|
||||||
|
|
||||||
|
cxoDbType *cxoDbTypeBfile = NULL;
|
||||||
|
cxoDbType *cxoDbTypeBinaryDouble = NULL;
|
||||||
|
cxoDbType *cxoDbTypeBinaryFloat = NULL;
|
||||||
|
cxoDbType *cxoDbTypeBinaryInteger = NULL;
|
||||||
|
cxoDbType *cxoDbTypeBlob = NULL;
|
||||||
|
cxoDbType *cxoDbTypeBoolean = NULL;
|
||||||
|
cxoDbType *cxoDbTypeChar = NULL;
|
||||||
|
cxoDbType *cxoDbTypeClob = NULL;
|
||||||
|
cxoDbType *cxoDbTypeCursor = NULL;
|
||||||
|
cxoDbType *cxoDbTypeDate = NULL;
|
||||||
|
cxoDbType *cxoDbTypeIntervalDS = NULL;
|
||||||
|
cxoDbType *cxoDbTypeIntervalYM = NULL;
|
||||||
|
cxoDbType *cxoDbTypeLong = NULL;
|
||||||
|
cxoDbType *cxoDbTypeLongRaw = NULL;
|
||||||
|
cxoDbType *cxoDbTypeNchar = NULL;
|
||||||
|
cxoDbType *cxoDbTypeNclob = NULL;
|
||||||
|
cxoDbType *cxoDbTypeNumber = NULL;
|
||||||
|
cxoDbType *cxoDbTypeNvarchar = NULL;
|
||||||
|
cxoDbType *cxoDbTypeObject = NULL;
|
||||||
|
cxoDbType *cxoDbTypeRaw = NULL;
|
||||||
|
cxoDbType *cxoDbTypeRowid = NULL;
|
||||||
|
cxoDbType *cxoDbTypeTimestamp = NULL;
|
||||||
|
cxoDbType *cxoDbTypeTimestampLTZ = NULL;
|
||||||
|
cxoDbType *cxoDbTypeTimestampTZ = NULL;
|
||||||
|
cxoDbType *cxoDbTypeVarchar = NULL;
|
||||||
|
|
||||||
|
cxoApiType *cxoApiTypeBinary = NULL;
|
||||||
|
cxoApiType *cxoApiTypeDatetime = NULL;
|
||||||
|
cxoApiType *cxoApiTypeNumber = NULL;
|
||||||
|
cxoApiType *cxoApiTypeRowid = NULL;
|
||||||
|
cxoApiType *cxoApiTypeString = NULL;
|
||||||
|
|
||||||
cxoFuture *cxoFutureObj = NULL;
|
cxoFuture *cxoFutureObj = NULL;
|
||||||
dpiContext *cxoDpiContext = NULL;
|
dpiContext *cxoDpiContext = NULL;
|
||||||
dpiVersionInfo cxoClientVersionInfo;
|
dpiVersionInfo cxoClientVersionInfo;
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoModule_addApiType()
|
||||||
|
// Create a Python Database API type and add it to the module.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static int cxoModule_addApiType(PyObject *module, const char *name,
|
||||||
|
cxoTransformNum defaultTransformNum, cxoApiType **apiType)
|
||||||
|
{
|
||||||
|
cxoApiType *tempApiType;
|
||||||
|
|
||||||
|
tempApiType =
|
||||||
|
(cxoApiType*) cxoPyTypeApiType.tp_alloc(&cxoPyTypeApiType, 0);
|
||||||
|
if (!tempApiType)
|
||||||
|
return -1;
|
||||||
|
tempApiType->name = name;
|
||||||
|
tempApiType->defaultTransformNum = defaultTransformNum;
|
||||||
|
tempApiType->dbTypes = PyList_New(0);
|
||||||
|
if (!tempApiType->dbTypes) {
|
||||||
|
Py_DECREF(tempApiType);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (PyModule_AddObject(module, name, (PyObject*) tempApiType) < 0) {
|
||||||
|
Py_DECREF(tempApiType);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*apiType = tempApiType;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoModule_addDbType()
|
||||||
|
// Create a database type and add it to the module.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static int cxoModule_addDbType(PyObject *module, uint32_t num,
|
||||||
|
const char *name, cxoTransformNum defaultTransformNum,
|
||||||
|
cxoDbType **dbType)
|
||||||
|
{
|
||||||
|
cxoDbType *tempDbType;
|
||||||
|
|
||||||
|
tempDbType = (cxoDbType*) cxoPyTypeDbType.tp_alloc(&cxoPyTypeDbType, 0);
|
||||||
|
if (!tempDbType)
|
||||||
|
return -1;
|
||||||
|
tempDbType->num = num;
|
||||||
|
tempDbType->name = name;
|
||||||
|
tempDbType->defaultTransformNum = defaultTransformNum;
|
||||||
|
if (PyModule_AddObject(module, name, (PyObject*) tempDbType) < 0) {
|
||||||
|
Py_DECREF(tempDbType);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*dbType = tempDbType;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoModule_setException()
|
// cxoModule_setException()
|
||||||
// Create an exception and set it in the provided dictionary.
|
// Create an exception and set it in the provided dictionary.
|
||||||
|
@ -242,50 +345,32 @@ static PyObject *cxoModule_initialize(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// prepare the types for use by the module
|
// prepare the types for use by the module
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBfileVar);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeApiType);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBinaryVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBlobVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBooleanVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeClobVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeConnection);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeConnection);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeCursor);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeCursor);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeCursorVar);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeDbType);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeDateTimeVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeDeqOptions);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeDeqOptions);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeEnqOptions);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeEnqOptions);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeError);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeError);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeFixedCharVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeFixedNcharVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeFuture);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeFuture);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeIntervalVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeLob);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeLob);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeLongBinaryVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeLongStringVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMsgProps);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeMsgProps);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMessage);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeMessage);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageQuery);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageQuery);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageRow);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageRow);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageTable);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageTable);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeNativeFloatVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeNativeIntVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeNcharVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeNclobVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeNumberVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeObjectAttr);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeObjectAttr);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeObject);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeObject);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeObjectType);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeObjectType);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeObjectVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeQueue);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeQueue);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeRowidVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSessionPool);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeSessionPool);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaCollection);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaCollection);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDatabase);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDatabase);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDoc);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDoc);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDocCursor);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDocCursor);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaOperation);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaOperation);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeStringVar);
|
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSubscr);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeSubscr);
|
||||||
CXO_MAKE_TYPE_READY(&cxoPyTypeTimestampVar);
|
CXO_MAKE_TYPE_READY(&cxoPyTypeVar);
|
||||||
|
|
||||||
// initialize module and retrieve the dictionary
|
// initialize module and retrieve the dictionary
|
||||||
module = PyModule_Create(&cxoModuleDef);
|
module = PyModule_Create(&cxoModuleDef);
|
||||||
|
@ -325,50 +410,129 @@ static PyObject *cxoModule_initialize(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// set up the types that are available
|
// set up the types that are available
|
||||||
|
CXO_ADD_TYPE_OBJECT("ApiType", &cxoPyTypeApiType)
|
||||||
CXO_ADD_TYPE_OBJECT("Binary", &PyBytes_Type)
|
CXO_ADD_TYPE_OBJECT("Binary", &PyBytes_Type)
|
||||||
CXO_ADD_TYPE_OBJECT("Connection", &cxoPyTypeConnection)
|
CXO_ADD_TYPE_OBJECT("Connection", &cxoPyTypeConnection)
|
||||||
CXO_ADD_TYPE_OBJECT("Cursor", &cxoPyTypeCursor)
|
CXO_ADD_TYPE_OBJECT("Cursor", &cxoPyTypeCursor)
|
||||||
CXO_ADD_TYPE_OBJECT("Timestamp", cxoPyTypeDateTime)
|
|
||||||
CXO_ADD_TYPE_OBJECT("Date", cxoPyTypeDate)
|
CXO_ADD_TYPE_OBJECT("Date", cxoPyTypeDate)
|
||||||
CXO_ADD_TYPE_OBJECT("SessionPool", &cxoPyTypeSessionPool)
|
CXO_ADD_TYPE_OBJECT("DbType", &cxoPyTypeDbType)
|
||||||
|
CXO_ADD_TYPE_OBJECT("DeqOptions", &cxoPyTypeDeqOptions)
|
||||||
|
CXO_ADD_TYPE_OBJECT("EnqOptions", &cxoPyTypeEnqOptions)
|
||||||
CXO_ADD_TYPE_OBJECT("_Error", &cxoPyTypeError)
|
CXO_ADD_TYPE_OBJECT("_Error", &cxoPyTypeError)
|
||||||
|
CXO_ADD_TYPE_OBJECT("LOB", &cxoPyTypeLob)
|
||||||
|
CXO_ADD_TYPE_OBJECT("MessageProperties", &cxoPyTypeMsgProps)
|
||||||
CXO_ADD_TYPE_OBJECT("Object", &cxoPyTypeObject)
|
CXO_ADD_TYPE_OBJECT("Object", &cxoPyTypeObject)
|
||||||
CXO_ADD_TYPE_OBJECT("ObjectType", &cxoPyTypeObjectType)
|
CXO_ADD_TYPE_OBJECT("ObjectType", &cxoPyTypeObjectType)
|
||||||
CXO_ADD_TYPE_OBJECT("EnqOptions", &cxoPyTypeEnqOptions)
|
CXO_ADD_TYPE_OBJECT("SessionPool", &cxoPyTypeSessionPool)
|
||||||
CXO_ADD_TYPE_OBJECT("DeqOptions", &cxoPyTypeDeqOptions)
|
|
||||||
CXO_ADD_TYPE_OBJECT("MessageProperties", &cxoPyTypeMsgProps)
|
|
||||||
CXO_ADD_TYPE_OBJECT("SodaCollection", &cxoPyTypeSodaCollection)
|
CXO_ADD_TYPE_OBJECT("SodaCollection", &cxoPyTypeSodaCollection)
|
||||||
CXO_ADD_TYPE_OBJECT("SodaDatabase", &cxoPyTypeSodaDatabase)
|
CXO_ADD_TYPE_OBJECT("SodaDatabase", &cxoPyTypeSodaDatabase)
|
||||||
CXO_ADD_TYPE_OBJECT("SodaDoc", &cxoPyTypeSodaDoc)
|
CXO_ADD_TYPE_OBJECT("SodaDoc", &cxoPyTypeSodaDoc)
|
||||||
CXO_ADD_TYPE_OBJECT("SodaDocCursor", &cxoPyTypeSodaDocCursor)
|
CXO_ADD_TYPE_OBJECT("SodaDocCursor", &cxoPyTypeSodaDocCursor)
|
||||||
CXO_ADD_TYPE_OBJECT("SodaOperation", &cxoPyTypeSodaOperation)
|
CXO_ADD_TYPE_OBJECT("SodaOperation", &cxoPyTypeSodaOperation)
|
||||||
|
CXO_ADD_TYPE_OBJECT("Timestamp", cxoPyTypeDateTime)
|
||||||
|
CXO_ADD_TYPE_OBJECT("Var", &cxoPyTypeVar)
|
||||||
|
|
||||||
// the name "connect" is required by the DB API
|
// the name "connect" is required by the DB API
|
||||||
CXO_ADD_TYPE_OBJECT("connect", &cxoPyTypeConnection)
|
CXO_ADD_TYPE_OBJECT("connect", &cxoPyTypeConnection)
|
||||||
|
|
||||||
// create the basic data types for setting input sizes
|
// create the database types (preferred names)
|
||||||
CXO_ADD_TYPE_OBJECT("BINARY", &cxoPyTypeBinaryVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BFILE, "DB_TYPE_BFILE",
|
||||||
CXO_ADD_TYPE_OBJECT("BFILE", &cxoPyTypeBfileVar)
|
CXO_TRANSFORM_BFILE, &cxoDbTypeBfile)
|
||||||
CXO_ADD_TYPE_OBJECT("BLOB", &cxoPyTypeBlobVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_DOUBLE, "DB_TYPE_BINARY_DOUBLE",
|
||||||
CXO_ADD_TYPE_OBJECT("CLOB", &cxoPyTypeClobVar)
|
CXO_TRANSFORM_NATIVE_DOUBLE, &cxoDbTypeBinaryDouble)
|
||||||
CXO_ADD_TYPE_OBJECT("CURSOR", &cxoPyTypeCursorVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_FLOAT, "DB_TYPE_BINARY_FLOAT",
|
||||||
CXO_ADD_TYPE_OBJECT("OBJECT", &cxoPyTypeObjectVar)
|
CXO_TRANSFORM_NATIVE_FLOAT, &cxoDbTypeBinaryFloat)
|
||||||
CXO_ADD_TYPE_OBJECT("DATETIME", &cxoPyTypeDateTimeVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_INT, "DB_TYPE_BINARY_INTEGER",
|
||||||
CXO_ADD_TYPE_OBJECT("FIXED_CHAR", &cxoPyTypeFixedCharVar)
|
CXO_TRANSFORM_NATIVE_INT, &cxoDbTypeBinaryInteger)
|
||||||
CXO_ADD_TYPE_OBJECT("FIXED_NCHAR", &cxoPyTypeFixedNcharVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BLOB, "DB_TYPE_BLOB",
|
||||||
CXO_ADD_TYPE_OBJECT("NCHAR", &cxoPyTypeNcharVar)
|
CXO_TRANSFORM_BLOB, &cxoDbTypeBlob)
|
||||||
CXO_ADD_TYPE_OBJECT("INTERVAL", &cxoPyTypeIntervalVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BOOLEAN, "DB_TYPE_BOOLEAN",
|
||||||
CXO_ADD_TYPE_OBJECT("LOB", &cxoPyTypeLob)
|
CXO_TRANSFORM_BOOLEAN, &cxoDbTypeBoolean)
|
||||||
CXO_ADD_TYPE_OBJECT("LONG_BINARY", &cxoPyTypeLongBinaryVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_CHAR, "DB_TYPE_CHAR",
|
||||||
CXO_ADD_TYPE_OBJECT("LONG_STRING", &cxoPyTypeLongStringVar)
|
CXO_TRANSFORM_FIXED_CHAR, &cxoDbTypeChar)
|
||||||
CXO_ADD_TYPE_OBJECT("NCLOB", &cxoPyTypeNclobVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_CLOB, "DB_TYPE_CLOB",
|
||||||
CXO_ADD_TYPE_OBJECT("NUMBER", &cxoPyTypeNumberVar)
|
CXO_TRANSFORM_CLOB, &cxoDbTypeClob)
|
||||||
CXO_ADD_TYPE_OBJECT("ROWID", &cxoPyTypeRowidVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_STMT, "DB_TYPE_CURSOR",
|
||||||
CXO_ADD_TYPE_OBJECT("STRING", &cxoPyTypeStringVar)
|
CXO_TRANSFORM_CURSOR, &cxoDbTypeCursor)
|
||||||
CXO_ADD_TYPE_OBJECT("TIMESTAMP", &cxoPyTypeTimestampVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_DATE, "DB_TYPE_DATE",
|
||||||
CXO_ADD_TYPE_OBJECT("NATIVE_INT", &cxoPyTypeNativeIntVar)
|
CXO_TRANSFORM_DATETIME, &cxoDbTypeDate)
|
||||||
CXO_ADD_TYPE_OBJECT("NATIVE_FLOAT", &cxoPyTypeNativeFloatVar)
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_INTERVAL_DS, "DB_TYPE_INTERVAL_DS",
|
||||||
CXO_ADD_TYPE_OBJECT("BOOLEAN", &cxoPyTypeBooleanVar)
|
CXO_TRANSFORM_TIMEDELTA, &cxoDbTypeIntervalDS)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_INTERVAL_YM, "DB_TYPE_INTERVAL_YM",
|
||||||
|
CXO_TRANSFORM_UNSUPPORTED, &cxoDbTypeIntervalYM)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_LONG_VARCHAR, "DB_TYPE_LONG",
|
||||||
|
CXO_TRANSFORM_LONG_STRING, &cxoDbTypeLong)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_LONG_RAW, "DB_TYPE_LONG_RAW",
|
||||||
|
CXO_TRANSFORM_LONG_BINARY, &cxoDbTypeLongRaw)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NCHAR, "DB_TYPE_NCHAR",
|
||||||
|
CXO_TRANSFORM_FIXED_NCHAR, &cxoDbTypeNchar)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NCLOB, "DB_TYPE_NCLOB",
|
||||||
|
CXO_TRANSFORM_NCLOB, &cxoDbTypeNclob)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NUMBER, "DB_TYPE_NUMBER",
|
||||||
|
CXO_TRANSFORM_FLOAT, &cxoDbTypeNumber)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NVARCHAR, "DB_TYPE_NVARCHAR",
|
||||||
|
CXO_TRANSFORM_NSTRING, &cxoDbTypeNvarchar)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_OBJECT, "DB_TYPE_OBJECT",
|
||||||
|
CXO_TRANSFORM_OBJECT, &cxoDbTypeObject)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_RAW, "DB_TYPE_RAW",
|
||||||
|
CXO_TRANSFORM_BINARY, &cxoDbTypeRaw)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_ROWID, "DB_TYPE_ROWID",
|
||||||
|
CXO_TRANSFORM_ROWID, &cxoDbTypeRowid)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_TIMESTAMP, "DB_TYPE_TIMESTAMP",
|
||||||
|
CXO_TRANSFORM_TIMESTAMP, &cxoDbTypeTimestamp)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_TIMESTAMP_LTZ, "DB_TYPE_TIMESTAMP_LTZ",
|
||||||
|
CXO_TRANSFORM_TIMESTAMP_LTZ, &cxoDbTypeTimestampLTZ)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_TIMESTAMP_TZ, "DB_TYPE_TIMESTAMP_TZ",
|
||||||
|
CXO_TRANSFORM_TIMESTAMP_TZ, &cxoDbTypeTimestampTZ)
|
||||||
|
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_VARCHAR, "DB_TYPE_VARCHAR",
|
||||||
|
CXO_TRANSFORM_STRING, &cxoDbTypeVarchar)
|
||||||
|
|
||||||
|
// create the synonyms for database types (deprecated names)
|
||||||
|
CXO_ADD_TYPE_OBJECT("BFILE", cxoDbTypeBfile)
|
||||||
|
CXO_ADD_TYPE_OBJECT("BLOB", cxoDbTypeBlob)
|
||||||
|
CXO_ADD_TYPE_OBJECT("CLOB", cxoDbTypeClob)
|
||||||
|
CXO_ADD_TYPE_OBJECT("CURSOR", cxoDbTypeCursor)
|
||||||
|
CXO_ADD_TYPE_OBJECT("OBJECT", cxoDbTypeObject)
|
||||||
|
CXO_ADD_TYPE_OBJECT("FIXED_CHAR", cxoDbTypeChar)
|
||||||
|
CXO_ADD_TYPE_OBJECT("FIXED_NCHAR", cxoDbTypeNchar)
|
||||||
|
CXO_ADD_TYPE_OBJECT("NCHAR", cxoDbTypeNvarchar)
|
||||||
|
CXO_ADD_TYPE_OBJECT("INTERVAL", cxoDbTypeIntervalDS)
|
||||||
|
CXO_ADD_TYPE_OBJECT("LONG_BINARY", cxoDbTypeLongRaw)
|
||||||
|
CXO_ADD_TYPE_OBJECT("LONG_STRING", cxoDbTypeLong)
|
||||||
|
CXO_ADD_TYPE_OBJECT("NCLOB", cxoDbTypeNclob)
|
||||||
|
CXO_ADD_TYPE_OBJECT("TIMESTAMP", cxoDbTypeTimestamp)
|
||||||
|
CXO_ADD_TYPE_OBJECT("NATIVE_INT", cxoDbTypeBinaryInteger)
|
||||||
|
CXO_ADD_TYPE_OBJECT("NATIVE_FLOAT", cxoDbTypeBinaryDouble)
|
||||||
|
CXO_ADD_TYPE_OBJECT("BOOLEAN", cxoDbTypeBoolean)
|
||||||
|
|
||||||
|
// create the Python Database API types
|
||||||
|
CXO_ADD_API_TYPE("BINARY", CXO_TRANSFORM_BINARY, &cxoApiTypeBinary)
|
||||||
|
CXO_ADD_API_TYPE("DATETIME", CXO_TRANSFORM_DATETIME, &cxoApiTypeDatetime)
|
||||||
|
CXO_ADD_API_TYPE("NUMBER", CXO_TRANSFORM_FLOAT, &cxoApiTypeNumber)
|
||||||
|
CXO_ADD_API_TYPE("ROWID", CXO_TRANSFORM_ROWID, &cxoApiTypeRowid)
|
||||||
|
CXO_ADD_API_TYPE("STRING", CXO_TRANSFORM_STRING, &cxoApiTypeString)
|
||||||
|
|
||||||
|
// associate the Python Database API types with the database types
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeBinary, cxoDbTypeBfile)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeBinary, cxoDbTypeBlob)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeBinary, cxoDbTypeLongRaw)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeBinary, cxoDbTypeRaw)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeDate)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeTimestamp)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeTimestampLTZ)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeDatetime, cxoDbTypeTimestampTZ)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeBinaryDouble)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeBinaryFloat)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeBinaryInteger)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeNumber, cxoDbTypeNumber)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeRowid, cxoDbTypeRowid)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeChar)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeClob)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeLong)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeNchar)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeNclob)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeNvarchar)
|
||||||
|
CXO_ASSOCIATE_DB_TYPE(cxoApiTypeString, cxoDbTypeVarchar)
|
||||||
|
|
||||||
// create constants required by Python DB API 2.0
|
// create constants required by Python DB API 2.0
|
||||||
if (PyModule_AddStringConstant(module, "apilevel", "2.0") < 0)
|
if (PyModule_AddStringConstant(module, "apilevel", "2.0") < 0)
|
||||||
|
|
122
src/cxoModule.h
122
src/cxoModule.h
|
@ -1,5 +1,5 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
// Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under BSD license (see LICENSE.txt).
|
// Licensed under BSD license (see LICENSE.txt).
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -29,12 +29,14 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Forward Declarations
|
// Forward Declarations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
typedef struct cxoApiType cxoApiType;
|
||||||
typedef struct cxoBuffer cxoBuffer;
|
typedef struct cxoBuffer cxoBuffer;
|
||||||
typedef struct cxoError cxoError;
|
|
||||||
typedef struct cxoConnection cxoConnection;
|
typedef struct cxoConnection cxoConnection;
|
||||||
typedef struct cxoCursor cxoCursor;
|
typedef struct cxoCursor cxoCursor;
|
||||||
|
typedef struct cxoDbType cxoDbType;
|
||||||
typedef struct cxoDeqOptions cxoDeqOptions;
|
typedef struct cxoDeqOptions cxoDeqOptions;
|
||||||
typedef struct cxoEnqOptions cxoEnqOptions;
|
typedef struct cxoEnqOptions cxoEnqOptions;
|
||||||
|
typedef struct cxoError cxoError;
|
||||||
typedef struct cxoFuture cxoFuture;
|
typedef struct cxoFuture cxoFuture;
|
||||||
typedef struct cxoLob cxoLob;
|
typedef struct cxoLob cxoLob;
|
||||||
typedef struct cxoMessage cxoMessage;
|
typedef struct cxoMessage cxoMessage;
|
||||||
|
@ -54,7 +56,6 @@ typedef struct cxoSodaDocCursor cxoSodaDocCursor;
|
||||||
typedef struct cxoSodaOperation cxoSodaOperation;
|
typedef struct cxoSodaOperation cxoSodaOperation;
|
||||||
typedef struct cxoSubscr cxoSubscr;
|
typedef struct cxoSubscr cxoSubscr;
|
||||||
typedef struct cxoVar cxoVar;
|
typedef struct cxoVar cxoVar;
|
||||||
typedef struct cxoVarType cxoVarType;
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -74,55 +75,71 @@ extern PyObject *cxoProgrammingErrorException;
|
||||||
extern PyObject *cxoNotSupportedErrorException;
|
extern PyObject *cxoNotSupportedErrorException;
|
||||||
|
|
||||||
// type objects
|
// type objects
|
||||||
extern PyTypeObject cxoPyTypeBfileVar;
|
extern PyTypeObject cxoPyTypeApiType;
|
||||||
extern PyTypeObject cxoPyTypeBinaryVar;
|
|
||||||
extern PyTypeObject cxoPyTypeBlobVar;
|
|
||||||
extern PyTypeObject cxoPyTypeBooleanVar;
|
|
||||||
extern PyTypeObject cxoPyTypeClobVar;
|
|
||||||
extern PyTypeObject cxoPyTypeConnection;
|
extern PyTypeObject cxoPyTypeConnection;
|
||||||
extern PyTypeObject cxoPyTypeCursor;
|
extern PyTypeObject cxoPyTypeCursor;
|
||||||
extern PyTypeObject cxoPyTypeCursorVar;
|
extern PyTypeObject cxoPyTypeDbType;
|
||||||
extern PyTypeObject cxoPyTypeDateTimeVar;
|
|
||||||
extern PyTypeObject cxoPyTypeDeqOptions;
|
extern PyTypeObject cxoPyTypeDeqOptions;
|
||||||
extern PyTypeObject cxoPyTypeEnqOptions;
|
extern PyTypeObject cxoPyTypeEnqOptions;
|
||||||
extern PyTypeObject cxoPyTypeError;
|
extern PyTypeObject cxoPyTypeError;
|
||||||
extern PyTypeObject cxoPyTypeFixedCharVar;
|
|
||||||
extern PyTypeObject cxoPyTypeFixedNcharVar;
|
|
||||||
extern PyTypeObject cxoPyTypeFuture;
|
extern PyTypeObject cxoPyTypeFuture;
|
||||||
extern PyTypeObject cxoPyTypeIntervalVar;
|
|
||||||
extern PyTypeObject cxoPyTypeLob;
|
extern PyTypeObject cxoPyTypeLob;
|
||||||
extern PyTypeObject cxoPyTypeLongBinaryVar;
|
|
||||||
extern PyTypeObject cxoPyTypeLongStringVar;
|
|
||||||
extern PyTypeObject cxoPyTypeMsgProps;
|
extern PyTypeObject cxoPyTypeMsgProps;
|
||||||
extern PyTypeObject cxoPyTypeMessage;
|
extern PyTypeObject cxoPyTypeMessage;
|
||||||
extern PyTypeObject cxoPyTypeMessageQuery;
|
extern PyTypeObject cxoPyTypeMessageQuery;
|
||||||
extern PyTypeObject cxoPyTypeMessageRow;
|
extern PyTypeObject cxoPyTypeMessageRow;
|
||||||
extern PyTypeObject cxoPyTypeMessageTable;
|
extern PyTypeObject cxoPyTypeMessageTable;
|
||||||
extern PyTypeObject cxoPyTypeNativeFloatVar;
|
|
||||||
extern PyTypeObject cxoPyTypeNativeIntVar;
|
|
||||||
extern PyTypeObject cxoPyTypeNcharVar;
|
|
||||||
extern PyTypeObject cxoPyTypeNclobVar;
|
|
||||||
extern PyTypeObject cxoPyTypeNumberVar;
|
|
||||||
extern PyTypeObject cxoPyTypeObject;
|
extern PyTypeObject cxoPyTypeObject;
|
||||||
extern PyTypeObject cxoPyTypeObjectAttr;
|
extern PyTypeObject cxoPyTypeObjectAttr;
|
||||||
extern PyTypeObject cxoPyTypeObjectType;
|
extern PyTypeObject cxoPyTypeObjectType;
|
||||||
extern PyTypeObject cxoPyTypeObjectVar;
|
|
||||||
extern PyTypeObject cxoPyTypeQueue;
|
extern PyTypeObject cxoPyTypeQueue;
|
||||||
extern PyTypeObject cxoPyTypeRowidVar;
|
|
||||||
extern PyTypeObject cxoPyTypeSessionPool;
|
extern PyTypeObject cxoPyTypeSessionPool;
|
||||||
extern PyTypeObject cxoPyTypeSodaCollection;
|
extern PyTypeObject cxoPyTypeSodaCollection;
|
||||||
extern PyTypeObject cxoPyTypeSodaDatabase;
|
extern PyTypeObject cxoPyTypeSodaDatabase;
|
||||||
extern PyTypeObject cxoPyTypeSodaDoc;
|
extern PyTypeObject cxoPyTypeSodaDoc;
|
||||||
extern PyTypeObject cxoPyTypeSodaDocCursor;
|
extern PyTypeObject cxoPyTypeSodaDocCursor;
|
||||||
extern PyTypeObject cxoPyTypeSodaOperation;
|
extern PyTypeObject cxoPyTypeSodaOperation;
|
||||||
extern PyTypeObject cxoPyTypeStringVar;
|
|
||||||
extern PyTypeObject cxoPyTypeSubscr;
|
extern PyTypeObject cxoPyTypeSubscr;
|
||||||
extern PyTypeObject cxoPyTypeTimestampVar;
|
extern PyTypeObject cxoPyTypeVar;
|
||||||
|
|
||||||
// datetime types
|
// datetime types
|
||||||
extern PyTypeObject *cxoPyTypeDate;
|
extern PyTypeObject *cxoPyTypeDate;
|
||||||
extern PyTypeObject *cxoPyTypeDateTime;
|
extern PyTypeObject *cxoPyTypeDateTime;
|
||||||
|
|
||||||
|
// database types
|
||||||
|
extern cxoDbType *cxoDbTypeBfile;
|
||||||
|
extern cxoDbType *cxoDbTypeBinaryDouble;
|
||||||
|
extern cxoDbType *cxoDbTypeBinaryFloat;
|
||||||
|
extern cxoDbType *cxoDbTypeBinaryInteger;
|
||||||
|
extern cxoDbType *cxoDbTypeBlob;
|
||||||
|
extern cxoDbType *cxoDbTypeBoolean;
|
||||||
|
extern cxoDbType *cxoDbTypeChar;
|
||||||
|
extern cxoDbType *cxoDbTypeClob;
|
||||||
|
extern cxoDbType *cxoDbTypeCursor;
|
||||||
|
extern cxoDbType *cxoDbTypeDate;
|
||||||
|
extern cxoDbType *cxoDbTypeIntervalDS;
|
||||||
|
extern cxoDbType *cxoDbTypeIntervalYM;
|
||||||
|
extern cxoDbType *cxoDbTypeLong;
|
||||||
|
extern cxoDbType *cxoDbTypeLongRaw;
|
||||||
|
extern cxoDbType *cxoDbTypeNchar;
|
||||||
|
extern cxoDbType *cxoDbTypeNclob;
|
||||||
|
extern cxoDbType *cxoDbTypeNumber;
|
||||||
|
extern cxoDbType *cxoDbTypeNvarchar;
|
||||||
|
extern cxoDbType *cxoDbTypeObject;
|
||||||
|
extern cxoDbType *cxoDbTypeRaw;
|
||||||
|
extern cxoDbType *cxoDbTypeRowid;
|
||||||
|
extern cxoDbType *cxoDbTypeTimestamp;
|
||||||
|
extern cxoDbType *cxoDbTypeTimestampLTZ;
|
||||||
|
extern cxoDbType *cxoDbTypeTimestampTZ;
|
||||||
|
extern cxoDbType *cxoDbTypeVarchar;
|
||||||
|
|
||||||
|
// database API types
|
||||||
|
extern cxoApiType *cxoApiTypeBinary;
|
||||||
|
extern cxoApiType *cxoApiTypeDatetime;
|
||||||
|
extern cxoApiType *cxoApiTypeNumber;
|
||||||
|
extern cxoApiType *cxoApiTypeRowid;
|
||||||
|
extern cxoApiType *cxoApiTypeString;
|
||||||
|
|
||||||
// JSON dump and load functions for use with SODA
|
// JSON dump and load functions for use with SODA
|
||||||
extern PyObject *cxoJsonDumpFunction;
|
extern PyObject *cxoJsonDumpFunction;
|
||||||
extern PyObject *cxoJsonLoadFunction;
|
extern PyObject *cxoJsonLoadFunction;
|
||||||
|
@ -166,6 +183,7 @@ typedef enum {
|
||||||
CXO_TRANSFORM_TIMEDELTA,
|
CXO_TRANSFORM_TIMEDELTA,
|
||||||
CXO_TRANSFORM_TIMESTAMP,
|
CXO_TRANSFORM_TIMESTAMP,
|
||||||
CXO_TRANSFORM_TIMESTAMP_LTZ,
|
CXO_TRANSFORM_TIMESTAMP_LTZ,
|
||||||
|
CXO_TRANSFORM_TIMESTAMP_TZ,
|
||||||
CXO_TRANSFORM_UNSUPPORTED
|
CXO_TRANSFORM_UNSUPPORTED
|
||||||
} cxoTransformNum;
|
} cxoTransformNum;
|
||||||
|
|
||||||
|
@ -173,6 +191,13 @@ typedef enum {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Structures
|
// Structures
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
struct cxoApiType {
|
||||||
|
PyObject_HEAD
|
||||||
|
const char *name;
|
||||||
|
PyObject *dbTypes;
|
||||||
|
cxoTransformNum defaultTransformNum;
|
||||||
|
};
|
||||||
|
|
||||||
struct cxoBuffer {
|
struct cxoBuffer {
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
uint32_t numCharacters;
|
uint32_t numCharacters;
|
||||||
|
@ -228,6 +253,13 @@ struct cxoCursor {
|
||||||
int isOpen;
|
int isOpen;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cxoDbType {
|
||||||
|
PyObject_HEAD
|
||||||
|
uint32_t num;
|
||||||
|
const char *name;
|
||||||
|
cxoTransformNum defaultTransformNum;
|
||||||
|
};
|
||||||
|
|
||||||
struct cxoDeqOptions {
|
struct cxoDeqOptions {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
dpiDeqOptions *handle;
|
dpiDeqOptions *handle;
|
||||||
|
@ -247,7 +279,7 @@ struct cxoFuture {
|
||||||
struct cxoLob {
|
struct cxoLob {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
cxoConnection *connection;
|
cxoConnection *connection;
|
||||||
dpiOracleTypeNum oracleTypeNum;
|
cxoDbType *dbType;
|
||||||
dpiLob *handle;
|
dpiLob *handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -303,7 +335,8 @@ struct cxoObjectAttr {
|
||||||
dpiObjectAttr *handle;
|
dpiObjectAttr *handle;
|
||||||
dpiOracleTypeNum oracleTypeNum;
|
dpiOracleTypeNum oracleTypeNum;
|
||||||
cxoTransformNum transformNum;
|
cxoTransformNum transformNum;
|
||||||
cxoObjectType *type;
|
cxoObjectType *objectType;
|
||||||
|
cxoDbType *dbType;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cxoObjectType {
|
struct cxoObjectType {
|
||||||
|
@ -316,7 +349,8 @@ struct cxoObjectType {
|
||||||
cxoConnection *connection;
|
cxoConnection *connection;
|
||||||
dpiOracleTypeNum elementOracleTypeNum;
|
dpiOracleTypeNum elementOracleTypeNum;
|
||||||
cxoTransformNum elementTransformNum;
|
cxoTransformNum elementTransformNum;
|
||||||
PyObject *elementType;
|
cxoObjectType *elementObjectType;
|
||||||
|
cxoDbType *elementDbType;
|
||||||
char isCollection;
|
char isCollection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -418,13 +452,9 @@ struct cxoVar {
|
||||||
int isArray;
|
int isArray;
|
||||||
int isValueSet;
|
int isValueSet;
|
||||||
int getReturnedData;
|
int getReturnedData;
|
||||||
cxoVarType *type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cxoVarType {
|
|
||||||
cxoTransformNum transformNum;
|
cxoTransformNum transformNum;
|
||||||
PyTypeObject *pythonType;
|
dpiNativeTypeNum nativeTypeNum;
|
||||||
uint32_t size;
|
cxoDbType *dbType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -441,6 +471,9 @@ int cxoCursor_performBind(cxoCursor *cursor);
|
||||||
int cxoCursor_setBindVariables(cxoCursor *cursor, PyObject *parameters,
|
int cxoCursor_setBindVariables(cxoCursor *cursor, PyObject *parameters,
|
||||||
unsigned numElements, unsigned arrayPos, int deferTypeAssignment);
|
unsigned numElements, unsigned arrayPos, int deferTypeAssignment);
|
||||||
|
|
||||||
|
cxoDbType *cxoDbType_fromDataTypeInfo(dpiDataTypeInfo *info);
|
||||||
|
cxoDbType *cxoDbType_fromTransformNum(cxoTransformNum transformNum);
|
||||||
|
|
||||||
cxoDeqOptions *cxoDeqOptions_new(cxoConnection *connection,
|
cxoDeqOptions *cxoDeqOptions_new(cxoConnection *connection,
|
||||||
dpiDeqOptions *handle);
|
dpiDeqOptions *handle);
|
||||||
|
|
||||||
|
@ -454,7 +487,7 @@ int cxoError_raiseFromInfo(dpiErrorInfo *errorInfo);
|
||||||
PyObject *cxoError_raiseFromString(PyObject *exceptionType,
|
PyObject *cxoError_raiseFromString(PyObject *exceptionType,
|
||||||
const char *message);
|
const char *message);
|
||||||
|
|
||||||
PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
|
PyObject *cxoLob_new(cxoConnection *connection, cxoDbType *dbType,
|
||||||
dpiLob *handle);
|
dpiLob *handle);
|
||||||
|
|
||||||
cxoMsgProps *cxoMsgProps_new(cxoConnection*, dpiMsgProps *handle);
|
cxoMsgProps *cxoMsgProps_new(cxoConnection*, dpiMsgProps *handle);
|
||||||
|
@ -491,9 +524,15 @@ int cxoTransform_fromPython(cxoTransformNum transformNum,
|
||||||
dpiNativeTypeNum *nativeTypeNum, PyObject *pyValue,
|
dpiNativeTypeNum *nativeTypeNum, PyObject *pyValue,
|
||||||
dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding,
|
dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding,
|
||||||
const char *nencoding, cxoVar *var, uint32_t arrayPos);
|
const char *nencoding, cxoVar *var, uint32_t arrayPos);
|
||||||
|
uint32_t cxoTransform_getDefaultSize(cxoTransformNum transformNum);
|
||||||
cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info);
|
cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info);
|
||||||
cxoTransformNum cxoTransform_getNumFromType(PyTypeObject *type);
|
cxoTransformNum cxoTransform_getNumFromPythonValue(PyObject *value,
|
||||||
cxoTransformNum cxoTransform_getNumFromValue(PyObject *value, int plsql);
|
int plsql);
|
||||||
|
int cxoTransform_getNumFromType(PyObject *type, cxoTransformNum *transformNum,
|
||||||
|
cxoObjectType **objType);
|
||||||
|
int cxoTransform_getNumFromValue(PyObject *value, int *isArray,
|
||||||
|
Py_ssize_t *size, Py_ssize_t *numElements, int plsql,
|
||||||
|
cxoTransformNum *transformNum);
|
||||||
void cxoTransform_getTypeInfo(cxoTransformNum transformNum,
|
void cxoTransform_getTypeInfo(cxoTransformNum transformNum,
|
||||||
dpiOracleTypeNum *oracleTypeNum, dpiNativeTypeNum *nativeTypeNum);
|
dpiOracleTypeNum *oracleTypeNum, dpiNativeTypeNum *nativeTypeNum);
|
||||||
int cxoTransform_init(void);
|
int cxoTransform_init(void);
|
||||||
|
@ -512,20 +551,15 @@ int cxoUtils_processJsonArg(PyObject *arg, cxoBuffer *buffer);
|
||||||
int cxoUtils_processSodaDocArg(cxoSodaDatabase *db, PyObject *arg,
|
int cxoUtils_processSodaDocArg(cxoSodaDatabase *db, PyObject *arg,
|
||||||
dpiSodaDoc **handle);
|
dpiSodaDoc **handle);
|
||||||
|
|
||||||
cxoVarType *cxoVarType_fromDataTypeInfo(dpiDataTypeInfo *info);
|
|
||||||
cxoVarType *cxoVarType_fromPythonType(PyObject *type, cxoObjectType **objType);
|
|
||||||
cxoVarType *cxoVarType_fromPythonValue(PyObject *value, int *isArray,
|
|
||||||
Py_ssize_t *size, Py_ssize_t *numElements, int plsql);
|
|
||||||
|
|
||||||
int cxoVar_bind(cxoVar *var, cxoCursor *cursor, PyObject *name, uint32_t pos);
|
int cxoVar_bind(cxoVar *var, cxoCursor *cursor, PyObject *name, uint32_t pos);
|
||||||
int cxoVar_check(PyObject *object);
|
int cxoVar_check(PyObject *object);
|
||||||
PyObject *cxoVar_getSingleValue(cxoVar *var, dpiData *data, uint32_t arrayPos);
|
PyObject *cxoVar_getSingleValue(cxoVar *var, dpiData *data, uint32_t arrayPos);
|
||||||
PyObject *cxoVar_getValue(cxoVar *var, uint32_t arrayPos);
|
PyObject *cxoVar_getValue(cxoVar *var, uint32_t arrayPos);
|
||||||
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
|
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements,
|
||||||
Py_ssize_t size, int isArray, cxoObjectType *objType);
|
cxoTransformNum transformNum, Py_ssize_t size, int isArray,
|
||||||
|
cxoObjectType *objType);
|
||||||
cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
||||||
uint32_t numElements);
|
uint32_t numElements);
|
||||||
cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
|
cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
|
||||||
Py_ssize_t numElements);
|
Py_ssize_t numElements);
|
||||||
int cxoVar_setValue(cxoVar *var, uint32_t arrayPos, PyObject *value);
|
int cxoVar_setValue(cxoVar *var, uint32_t arrayPos, PyObject *value);
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ static PyObject *cxoObject_getAttributeValue(cxoObject *obj,
|
||||||
nativeTypeNum, &data) < 0)
|
nativeTypeNum, &data) < 0)
|
||||||
return cxoError_raiseAndReturnNull();
|
return cxoError_raiseAndReturnNull();
|
||||||
return cxoObject_convertToPython(obj, attribute->transformNum, &data,
|
return cxoObject_convertToPython(obj, attribute->transformNum, &data,
|
||||||
attribute->type);
|
attribute->objectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,7 +367,7 @@ static PyObject *cxoObject_internalGetElementByIndex(cxoObject *obj,
|
||||||
&data) < 0)
|
&data) < 0)
|
||||||
return cxoError_raiseAndReturnNull();
|
return cxoError_raiseAndReturnNull();
|
||||||
return cxoObject_convertToPython(obj, obj->objectType->elementTransformNum,
|
return cxoObject_convertToPython(obj, obj->objectType->elementTransformNum,
|
||||||
&data, (cxoObjectType*) obj->objectType->elementType);
|
&data, obj->objectType->elementObjectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,27 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static void cxoObjectAttr_free(cxoObjectAttr*);
|
static void cxoObjectAttr_free(cxoObjectAttr*);
|
||||||
static PyObject *cxoObjectAttr_repr(cxoObjectAttr*);
|
static PyObject *cxoObjectAttr_repr(cxoObjectAttr*);
|
||||||
|
static PyObject *cxoObjectAttr_getType(cxoObjectAttr*, void*);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of members for Python type "ObjectAttribute"
|
// declaration of members
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyMemberDef cxoObjectAttrMembers[] = {
|
static PyMemberDef cxoMembers[] = {
|
||||||
{ "name", T_OBJECT, offsetof(cxoObjectAttr, name), READONLY },
|
{ "name", T_OBJECT, offsetof(cxoObjectAttr, name), READONLY },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// declaration of calculated members
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyGetSetDef cxoCalcMembers[] = {
|
||||||
|
{ "type", (getter) cxoObjectAttr_getType, 0, 0, 0 },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Python type declaration
|
// Python type declaration
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -35,7 +45,8 @@ PyTypeObject cxoPyTypeObjectAttr = {
|
||||||
.tp_dealloc = (destructor) cxoObjectAttr_free,
|
.tp_dealloc = (destructor) cxoObjectAttr_free,
|
||||||
.tp_repr = (reprfunc) cxoObjectAttr_repr,
|
.tp_repr = (reprfunc) cxoObjectAttr_repr,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_members = cxoObjectAttrMembers
|
.tp_members = cxoMembers,
|
||||||
|
.tp_getset = cxoCalcMembers
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,15 +62,19 @@ static int cxoObjectAttr_initialize(cxoObjectAttr *attr,
|
||||||
if (dpiObjectAttr_getInfo(attr->handle, &info) < 0)
|
if (dpiObjectAttr_getInfo(attr->handle, &info) < 0)
|
||||||
return cxoError_raiseAndReturnInt();
|
return cxoError_raiseAndReturnInt();
|
||||||
attr->transformNum = cxoTransform_getNumFromDataTypeInfo(&info.typeInfo);
|
attr->transformNum = cxoTransform_getNumFromDataTypeInfo(&info.typeInfo);
|
||||||
|
attr->dbType = cxoDbType_fromTransformNum(attr->transformNum);
|
||||||
|
if (!attr->dbType)
|
||||||
|
return -1;
|
||||||
|
Py_INCREF(attr->dbType);
|
||||||
attr->oracleTypeNum = info.typeInfo.oracleTypeNum;
|
attr->oracleTypeNum = info.typeInfo.oracleTypeNum;
|
||||||
attr->name = PyUnicode_Decode(info.name, info.nameLength,
|
attr->name = PyUnicode_Decode(info.name, info.nameLength,
|
||||||
connection->encodingInfo.encoding, NULL);
|
connection->encodingInfo.encoding, NULL);
|
||||||
if (!attr->name)
|
if (!attr->name)
|
||||||
return -1;
|
return -1;
|
||||||
if (info.typeInfo.objectType) {
|
if (info.typeInfo.objectType) {
|
||||||
attr->type = cxoObjectType_new(connection,
|
attr->objectType = cxoObjectType_new(connection,
|
||||||
info.typeInfo.objectType);
|
info.typeInfo.objectType);
|
||||||
if (!attr->type)
|
if (!attr->objectType)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,11 +118,29 @@ static void cxoObjectAttr_free(cxoObjectAttr *attr)
|
||||||
attr->handle = NULL;
|
attr->handle = NULL;
|
||||||
}
|
}
|
||||||
Py_CLEAR(attr->name);
|
Py_CLEAR(attr->name);
|
||||||
Py_CLEAR(attr->type);
|
Py_CLEAR(attr->objectType);
|
||||||
|
Py_CLEAR(attr->dbType);
|
||||||
Py_TYPE(attr)->tp_free((PyObject*) attr);
|
Py_TYPE(attr)->tp_free((PyObject*) attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoObjectAttr_getType()
|
||||||
|
// Return the type associated with the attribute. This is either an object
|
||||||
|
// type or one of the database type constants.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyObject *cxoObjectAttr_getType(cxoObjectAttr *attr, void *unused)
|
||||||
|
{
|
||||||
|
if (attr->objectType) {
|
||||||
|
Py_INCREF(attr->objectType);
|
||||||
|
return (PyObject*) attr->objectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_INCREF(attr->dbType);
|
||||||
|
return (PyObject*) attr->dbType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoObjectAttr_repr()
|
// cxoObjectAttr_repr()
|
||||||
// Return a string representation of the object attribute.
|
// Return a string representation of the object attribute.
|
||||||
|
|
|
@ -20,12 +20,14 @@
|
||||||
static void cxoObjectType_free(cxoObjectType*);
|
static void cxoObjectType_free(cxoObjectType*);
|
||||||
static PyObject *cxoObjectType_repr(cxoObjectType*);
|
static PyObject *cxoObjectType_repr(cxoObjectType*);
|
||||||
static PyObject *cxoObjectType_newObject(cxoObjectType*, PyObject*, PyObject*);
|
static PyObject *cxoObjectType_newObject(cxoObjectType*, PyObject*, PyObject*);
|
||||||
|
static PyObject *cxoObjectType_richCompare(cxoObjectType*, PyObject*, int);
|
||||||
|
static PyObject *cxoObjectType_getElementType(cxoObjectType*, void*);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of methods for Python type "ObjectType"
|
// declaration of methods
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyMethodDef cxoObjectTypeMethods[] = {
|
static PyMethodDef cxoMethods[] = {
|
||||||
{ "newobject", (PyCFunction) cxoObjectType_newObject,
|
{ "newobject", (PyCFunction) cxoObjectType_newObject,
|
||||||
METH_VARARGS | METH_KEYWORDS },
|
METH_VARARGS | METH_KEYWORDS },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
|
@ -33,20 +35,27 @@ static PyMethodDef cxoObjectTypeMethods[] = {
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of members for Python type "ObjectType"
|
// declaration of members
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyMemberDef cxoObjectTypeMembers[] = {
|
static PyMemberDef cxoMembers[] = {
|
||||||
{ "schema", T_OBJECT, offsetof(cxoObjectType, schema), READONLY },
|
{ "schema", T_OBJECT, offsetof(cxoObjectType, schema), READONLY },
|
||||||
{ "name", T_OBJECT, offsetof(cxoObjectType, name), READONLY },
|
{ "name", T_OBJECT, offsetof(cxoObjectType, name), READONLY },
|
||||||
{ "attributes", T_OBJECT, offsetof(cxoObjectType, attributes), READONLY },
|
{ "attributes", T_OBJECT, offsetof(cxoObjectType, attributes), READONLY },
|
||||||
{ "elementType", T_OBJECT, offsetof(cxoObjectType, elementType),
|
|
||||||
READONLY },
|
|
||||||
{ "iscollection", T_BOOL, offsetof(cxoObjectType, isCollection),
|
{ "iscollection", T_BOOL, offsetof(cxoObjectType, isCollection),
|
||||||
READONLY },
|
READONLY },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// declaration of calculated members
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyGetSetDef cxoCalcMembers[] = {
|
||||||
|
{ "element_type", (getter) cxoObjectType_getElementType, 0, 0, 0 },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Python type declarations
|
// Python type declarations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -58,8 +67,10 @@ PyTypeObject cxoPyTypeObjectType = {
|
||||||
.tp_repr = (reprfunc) cxoObjectType_repr,
|
.tp_repr = (reprfunc) cxoObjectType_repr,
|
||||||
.tp_call = (ternaryfunc) cxoObjectType_newObject,
|
.tp_call = (ternaryfunc) cxoObjectType_newObject,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_methods = cxoObjectTypeMethods,
|
.tp_methods = cxoMethods,
|
||||||
.tp_members = cxoObjectTypeMembers,
|
.tp_members = cxoMembers,
|
||||||
|
.tp_getset = cxoCalcMembers,
|
||||||
|
.tp_richcompare = (richcmpfunc) cxoObjectType_richCompare
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,14 +100,21 @@ static int cxoObjectType_initialize(cxoObjectType *objType,
|
||||||
if (!objType->name)
|
if (!objType->name)
|
||||||
return -1;
|
return -1;
|
||||||
objType->isCollection = info.isCollection;
|
objType->isCollection = info.isCollection;
|
||||||
objType->elementOracleTypeNum = info.elementTypeInfo.oracleTypeNum;
|
if (info.isCollection) {
|
||||||
objType->elementTransformNum =
|
objType->elementOracleTypeNum = info.elementTypeInfo.oracleTypeNum;
|
||||||
cxoTransform_getNumFromDataTypeInfo(&info.elementTypeInfo);
|
objType->elementTransformNum =
|
||||||
if (info.elementTypeInfo.objectType) {
|
cxoTransform_getNumFromDataTypeInfo(&info.elementTypeInfo);
|
||||||
objType->elementType = (PyObject*) cxoObjectType_new(connection,
|
objType->elementDbType =
|
||||||
info.elementTypeInfo.objectType);
|
cxoDbType_fromTransformNum(objType->elementTransformNum);
|
||||||
if (!objType->elementType)
|
if (!objType->elementDbType)
|
||||||
return -1;
|
return -1;
|
||||||
|
Py_INCREF(objType->elementDbType);
|
||||||
|
if (info.elementTypeInfo.objectType) {
|
||||||
|
objType->elementObjectType = cxoObjectType_new(connection,
|
||||||
|
info.elementTypeInfo.objectType);
|
||||||
|
if (!objType->elementObjectType)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate the attribute list (temporary and permanent) and dictionary
|
// allocate the attribute list (temporary and permanent) and dictionary
|
||||||
|
@ -205,11 +223,34 @@ static void cxoObjectType_free(cxoObjectType *objType)
|
||||||
Py_CLEAR(objType->name);
|
Py_CLEAR(objType->name);
|
||||||
Py_CLEAR(objType->attributes);
|
Py_CLEAR(objType->attributes);
|
||||||
Py_CLEAR(objType->attributesByName);
|
Py_CLEAR(objType->attributesByName);
|
||||||
Py_CLEAR(objType->elementType);
|
Py_CLEAR(objType->elementObjectType);
|
||||||
|
Py_CLEAR(objType->elementDbType);
|
||||||
Py_TYPE(objType)->tp_free((PyObject*) objType);
|
Py_TYPE(objType)->tp_free((PyObject*) objType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoObjectType_getElementType()
|
||||||
|
// Return the element type associated with a collection. This is either an
|
||||||
|
// object type or one of the database type constants. If the object type is not
|
||||||
|
// a collection, None is returned.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyObject *cxoObjectType_getElementType(cxoObjectType *type,
|
||||||
|
void *unused)
|
||||||
|
{
|
||||||
|
if (type->elementObjectType) {
|
||||||
|
Py_INCREF(type->elementObjectType);
|
||||||
|
return (PyObject*) type->elementObjectType;
|
||||||
|
}
|
||||||
|
if (type->elementDbType) {
|
||||||
|
Py_INCREF(type->elementDbType);
|
||||||
|
return (PyObject*) type->elementDbType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoObjectType_repr()
|
// cxoObjectType_repr()
|
||||||
// Return a string representation of the object type.
|
// Return a string representation of the object type.
|
||||||
|
@ -228,6 +269,54 @@ static PyObject *cxoObjectType_repr(cxoObjectType *objType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoObjectType_richCompare()
|
||||||
|
// Peforms a comparison between the object type and another Python object.
|
||||||
|
// Equality (and inequality) are suppported to match object types; no other
|
||||||
|
// operations are supported.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyObject *cxoObjectType_richCompare(cxoObjectType* objType,
|
||||||
|
PyObject* otherObj, int op)
|
||||||
|
{
|
||||||
|
cxoObjectType *otherObjType;
|
||||||
|
int status, equal = 0;
|
||||||
|
|
||||||
|
// only equality and inequality can be checked
|
||||||
|
if (op != Py_EQ && op != Py_NE) {
|
||||||
|
Py_INCREF(Py_NotImplemented);
|
||||||
|
return Py_NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if the other object is an object type, too
|
||||||
|
status = PyObject_IsInstance(otherObj, (PyObject*) &cxoPyTypeObjectType);
|
||||||
|
if (status < 0)
|
||||||
|
return NULL;
|
||||||
|
if (status == 1) {
|
||||||
|
otherObjType = (cxoObjectType*) otherObj;
|
||||||
|
if (otherObjType->connection == objType->connection ||
|
||||||
|
otherObjType->connection->sessionPool ==
|
||||||
|
objType->connection->sessionPool) {
|
||||||
|
equal = PyObject_RichCompareBool(otherObjType->schema,
|
||||||
|
objType->schema, Py_EQ);
|
||||||
|
if (equal < 0)
|
||||||
|
return NULL;
|
||||||
|
if (equal) {
|
||||||
|
equal = PyObject_RichCompareBool(otherObjType->name,
|
||||||
|
objType->name, Py_EQ);
|
||||||
|
if (equal < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine return value
|
||||||
|
if ((equal && op == Py_EQ) || (!equal && op == Py_NE)) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoObjectType_newObject()
|
// cxoObjectType_newObject()
|
||||||
// Factory function for creating objects of the type which can be bound.
|
// Factory function for creating objects of the type which can be bound.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
// Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -24,6 +24,12 @@
|
||||||
#define PyDateTime_DELTA_GET_MICROSECONDS(x) ((x)->microseconds)
|
#define PyDateTime_DELTA_GET_MICROSECONDS(x) ((x)->microseconds)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
static Py_ssize_t cxoTransform_calculateSize(PyObject *value,
|
||||||
|
cxoTransformNum transformNum);
|
||||||
|
static cxoTransformNum cxoTransform_getNumFromPythonType(PyTypeObject *type);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Types
|
// Types
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -175,10 +181,39 @@ static const cxoTransform cxoAllTransforms[] = {
|
||||||
CXO_TRANSFORM_TIMESTAMP_LTZ,
|
CXO_TRANSFORM_TIMESTAMP_LTZ,
|
||||||
DPI_ORACLE_TYPE_TIMESTAMP_LTZ,
|
DPI_ORACLE_TYPE_TIMESTAMP_LTZ,
|
||||||
DPI_NATIVE_TYPE_TIMESTAMP
|
DPI_NATIVE_TYPE_TIMESTAMP
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CXO_TRANSFORM_TIMESTAMP_TZ,
|
||||||
|
DPI_ORACLE_TYPE_TIMESTAMP_TZ,
|
||||||
|
DPI_NATIVE_TYPE_TIMESTAMP
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoTransform_calculateSize()
|
||||||
|
// Calculate the size to use with the specified transform and Python value.
|
||||||
|
// This function is only called by cxoTransform_getNumFromValue() and no
|
||||||
|
// attempt is made to verify the value further.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static Py_ssize_t cxoTransform_calculateSize(PyObject *value,
|
||||||
|
cxoTransformNum transformNum)
|
||||||
|
{
|
||||||
|
switch (transformNum) {
|
||||||
|
case CXO_TRANSFORM_NONE:
|
||||||
|
return 1;
|
||||||
|
case CXO_TRANSFORM_BINARY:
|
||||||
|
return PyBytes_GET_SIZE(value);
|
||||||
|
case CXO_TRANSFORM_NSTRING:
|
||||||
|
case CXO_TRANSFORM_STRING:
|
||||||
|
return PyUnicode_GET_SIZE(value);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoTransform_dateFromTicks()
|
// cxoTransform_dateFromTicks()
|
||||||
// Creates a date from ticks (number of seconds since Unix epoch).
|
// Creates a date from ticks (number of seconds since Unix epoch).
|
||||||
|
@ -320,6 +355,7 @@ int cxoTransform_fromPython(cxoTransformNum transformNum,
|
||||||
case CXO_TRANSFORM_DATETIME:
|
case CXO_TRANSFORM_DATETIME:
|
||||||
case CXO_TRANSFORM_TIMESTAMP:
|
case CXO_TRANSFORM_TIMESTAMP:
|
||||||
case CXO_TRANSFORM_TIMESTAMP_LTZ:
|
case CXO_TRANSFORM_TIMESTAMP_LTZ:
|
||||||
|
case CXO_TRANSFORM_TIMESTAMP_TZ:
|
||||||
if (PyDateTime_Check(pyValue)) {
|
if (PyDateTime_Check(pyValue)) {
|
||||||
memset(&dbValue->asTimestamp, 0, sizeof(dbValue->asTimestamp));
|
memset(&dbValue->asTimestamp, 0, sizeof(dbValue->asTimestamp));
|
||||||
dbValue->asTimestamp.year = PyDateTime_GET_YEAR(pyValue);
|
dbValue->asTimestamp.year = PyDateTime_GET_YEAR(pyValue);
|
||||||
|
@ -368,6 +404,37 @@ int cxoTransform_fromPython(cxoTransformNum transformNum,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoTransform_getDefaultSize()
|
||||||
|
// Return the default size for the specified transform.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
uint32_t cxoTransform_getDefaultSize(cxoTransformNum transformNum)
|
||||||
|
{
|
||||||
|
switch (transformNum) {
|
||||||
|
case CXO_TRANSFORM_NONE:
|
||||||
|
return 1;
|
||||||
|
case CXO_TRANSFORM_BINARY:
|
||||||
|
case CXO_TRANSFORM_NSTRING:
|
||||||
|
case CXO_TRANSFORM_STRING:
|
||||||
|
return 4000;
|
||||||
|
case CXO_TRANSFORM_DECIMAL:
|
||||||
|
case CXO_TRANSFORM_FLOAT:
|
||||||
|
case CXO_TRANSFORM_INT:
|
||||||
|
return 1000;
|
||||||
|
case CXO_TRANSFORM_FIXED_CHAR:
|
||||||
|
case CXO_TRANSFORM_FIXED_NCHAR:
|
||||||
|
return 2000;
|
||||||
|
case CXO_TRANSFORM_LONG_BINARY:
|
||||||
|
case CXO_TRANSFORM_LONG_STRING:
|
||||||
|
return 128 * 1024;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoTransform_getNumFromDataTypeInfo()
|
// cxoTransform_getNumFromDataTypeInfo()
|
||||||
// Get the default transformation to use for the specified data type.
|
// Get the default transformation to use for the specified data type.
|
||||||
|
@ -403,6 +470,7 @@ cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info)
|
||||||
case DPI_ORACLE_TYPE_TIMESTAMP:
|
case DPI_ORACLE_TYPE_TIMESTAMP:
|
||||||
return CXO_TRANSFORM_TIMESTAMP;
|
return CXO_TRANSFORM_TIMESTAMP;
|
||||||
case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
|
case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
|
||||||
|
return CXO_TRANSFORM_TIMESTAMP_TZ;
|
||||||
case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
|
case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
|
||||||
return CXO_TRANSFORM_TIMESTAMP_LTZ;
|
return CXO_TRANSFORM_TIMESTAMP_LTZ;
|
||||||
case DPI_ORACLE_TYPE_INTERVAL_DS:
|
case DPI_ORACLE_TYPE_INTERVAL_DS:
|
||||||
|
@ -433,83 +501,39 @@ cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info)
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoTransform_getNumFromType()
|
// cxoTransform_getNumFromPythonType()
|
||||||
// Get the appropriate transformation to use for the specified Python type.
|
// Get the appropriate transformation to use for the specified Python type.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
cxoTransformNum cxoTransform_getNumFromType(PyTypeObject *type)
|
static cxoTransformNum cxoTransform_getNumFromPythonType(PyTypeObject *type)
|
||||||
{
|
{
|
||||||
if (type == &PyUnicode_Type)
|
if (type == &PyUnicode_Type)
|
||||||
return CXO_TRANSFORM_STRING;
|
return CXO_TRANSFORM_STRING;
|
||||||
if (type == &cxoPyTypeStringVar)
|
|
||||||
return CXO_TRANSFORM_STRING;
|
|
||||||
if (type == &cxoPyTypeFixedCharVar)
|
|
||||||
return CXO_TRANSFORM_FIXED_CHAR;
|
|
||||||
if (type == &cxoPyTypeNcharVar)
|
|
||||||
return CXO_TRANSFORM_NSTRING;
|
|
||||||
if (type == &cxoPyTypeFixedNcharVar)
|
|
||||||
return CXO_TRANSFORM_FIXED_NCHAR;
|
|
||||||
if (type == &cxoPyTypeRowidVar)
|
|
||||||
return CXO_TRANSFORM_ROWID;
|
|
||||||
if (type == &PyBytes_Type)
|
if (type == &PyBytes_Type)
|
||||||
return CXO_TRANSFORM_BINARY;
|
return CXO_TRANSFORM_BINARY;
|
||||||
if (type == &cxoPyTypeBinaryVar)
|
|
||||||
return CXO_TRANSFORM_BINARY;
|
|
||||||
if (type == &PyFloat_Type)
|
if (type == &PyFloat_Type)
|
||||||
return CXO_TRANSFORM_FLOAT;
|
return CXO_TRANSFORM_FLOAT;
|
||||||
if (type == &PyLong_Type)
|
if (type == &PyLong_Type)
|
||||||
return CXO_TRANSFORM_INT;
|
return CXO_TRANSFORM_INT;
|
||||||
if (type == cxoPyTypeDecimal)
|
if (type == cxoPyTypeDecimal)
|
||||||
return CXO_TRANSFORM_DECIMAL;
|
return CXO_TRANSFORM_DECIMAL;
|
||||||
if (type == &cxoPyTypeNumberVar)
|
|
||||||
return CXO_TRANSFORM_FLOAT;
|
|
||||||
if (type == &cxoPyTypeNativeFloatVar)
|
|
||||||
return CXO_TRANSFORM_NATIVE_DOUBLE;
|
|
||||||
if (type == &cxoPyTypeNativeIntVar)
|
|
||||||
return CXO_TRANSFORM_NATIVE_INT;
|
|
||||||
if (type == &PyBool_Type)
|
if (type == &PyBool_Type)
|
||||||
return CXO_TRANSFORM_BOOLEAN;
|
return CXO_TRANSFORM_BOOLEAN;
|
||||||
if (type == &cxoPyTypeBooleanVar)
|
|
||||||
return CXO_TRANSFORM_BOOLEAN;
|
|
||||||
if (type == PyDateTimeAPI->DateType)
|
if (type == PyDateTimeAPI->DateType)
|
||||||
return CXO_TRANSFORM_DATE;
|
return CXO_TRANSFORM_DATE;
|
||||||
if (type == PyDateTimeAPI->DateTimeType)
|
if (type == PyDateTimeAPI->DateTimeType)
|
||||||
return CXO_TRANSFORM_DATETIME;
|
return CXO_TRANSFORM_DATETIME;
|
||||||
if (type == &cxoPyTypeDateTimeVar)
|
|
||||||
return CXO_TRANSFORM_DATETIME;
|
|
||||||
if (type == &cxoPyTypeTimestampVar)
|
|
||||||
return CXO_TRANSFORM_TIMESTAMP;
|
|
||||||
if (type == PyDateTimeAPI->DeltaType)
|
if (type == PyDateTimeAPI->DeltaType)
|
||||||
return CXO_TRANSFORM_TIMEDELTA;
|
return CXO_TRANSFORM_TIMEDELTA;
|
||||||
if (type == &cxoPyTypeIntervalVar)
|
|
||||||
return CXO_TRANSFORM_TIMEDELTA;
|
|
||||||
if (type == &cxoPyTypeObject)
|
|
||||||
return CXO_TRANSFORM_OBJECT;
|
|
||||||
if (type == &cxoPyTypeObjectVar)
|
|
||||||
return CXO_TRANSFORM_OBJECT;
|
|
||||||
if (type == &cxoPyTypeClobVar)
|
|
||||||
return CXO_TRANSFORM_CLOB;
|
|
||||||
if (type == &cxoPyTypeNclobVar)
|
|
||||||
return CXO_TRANSFORM_NCLOB;
|
|
||||||
if (type == &cxoPyTypeBlobVar)
|
|
||||||
return CXO_TRANSFORM_BLOB;
|
|
||||||
if (type == &cxoPyTypeBfileVar)
|
|
||||||
return CXO_TRANSFORM_BFILE;
|
|
||||||
if (type == &cxoPyTypeCursorVar)
|
|
||||||
return CXO_TRANSFORM_CURSOR;
|
|
||||||
if (type == &cxoPyTypeLongStringVar)
|
|
||||||
return CXO_TRANSFORM_LONG_STRING;
|
|
||||||
if (type == &cxoPyTypeLongBinaryVar)
|
|
||||||
return CXO_TRANSFORM_LONG_BINARY;
|
|
||||||
|
|
||||||
return CXO_TRANSFORM_UNSUPPORTED;
|
return CXO_TRANSFORM_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoTransform_getNumFromValue()
|
// cxoTransform_getNumFromPythonValue()
|
||||||
// Get the appropriate transformation to use for the specified Python object.
|
// Get the appropriate transformation to use for the specified Python value.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
cxoTransformNum cxoTransform_getNumFromValue(PyObject *value, int plsql)
|
cxoTransformNum cxoTransform_getNumFromPythonValue(PyObject *value, int plsql)
|
||||||
{
|
{
|
||||||
cxoLob *lob;
|
cxoLob *lob;
|
||||||
|
|
||||||
|
@ -542,19 +566,144 @@ cxoTransformNum cxoTransform_getNumFromValue(PyObject *value, int plsql)
|
||||||
return CXO_TRANSFORM_OBJECT;
|
return CXO_TRANSFORM_OBJECT;
|
||||||
if (PyObject_TypeCheck(value, &cxoPyTypeLob)) {
|
if (PyObject_TypeCheck(value, &cxoPyTypeLob)) {
|
||||||
lob = (cxoLob*) value;
|
lob = (cxoLob*) value;
|
||||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_CLOB)
|
return lob->dbType->defaultTransformNum;
|
||||||
return CXO_TRANSFORM_CLOB;
|
|
||||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
|
|
||||||
return CXO_TRANSFORM_NCLOB;
|
|
||||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_BLOB)
|
|
||||||
return CXO_TRANSFORM_BLOB;
|
|
||||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_BFILE)
|
|
||||||
return CXO_TRANSFORM_BFILE;
|
|
||||||
}
|
}
|
||||||
return CXO_TRANSFORM_UNSUPPORTED;
|
return CXO_TRANSFORM_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoTransform_getNumFromType()
|
||||||
|
// Get the appropriate transformation to use for the specified type. This
|
||||||
|
// can be either a database type constant defined at the module level or a
|
||||||
|
// Python type.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int cxoTransform_getNumFromType(PyObject *type, cxoTransformNum *transformNum,
|
||||||
|
cxoObjectType **objType)
|
||||||
|
{
|
||||||
|
PyTypeObject *pyType;
|
||||||
|
cxoApiType *apiType;
|
||||||
|
cxoDbType *dbType;
|
||||||
|
char message[250];
|
||||||
|
int status;
|
||||||
|
|
||||||
|
// check to see if a database type constant has been specified
|
||||||
|
status = PyObject_IsInstance(type, (PyObject*) &cxoPyTypeDbType);
|
||||||
|
if (status < 0)
|
||||||
|
return -1;
|
||||||
|
if (status == 1) {
|
||||||
|
dbType = (cxoDbType*) type;
|
||||||
|
*transformNum = dbType->defaultTransformNum;
|
||||||
|
*objType = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if a DB API type constant has been specified
|
||||||
|
status = PyObject_IsInstance(type, (PyObject*) &cxoPyTypeApiType);
|
||||||
|
if (status < 0)
|
||||||
|
return -1;
|
||||||
|
if (status == 1) {
|
||||||
|
apiType = (cxoApiType*) type;
|
||||||
|
*transformNum = apiType->defaultTransformNum;
|
||||||
|
*objType = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if an object type has been specified
|
||||||
|
if (Py_TYPE(type) == &cxoPyTypeObjectType) {
|
||||||
|
*transformNum = CXO_TRANSFORM_OBJECT;
|
||||||
|
*objType = (cxoObjectType*) type;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if a Python type has been specified
|
||||||
|
if (Py_TYPE(type) != &PyType_Type) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expecting type");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check to see if the Python type is a supported type
|
||||||
|
pyType = (PyTypeObject*) type;
|
||||||
|
*objType = NULL;
|
||||||
|
*transformNum = cxoTransform_getNumFromPythonType(pyType);
|
||||||
|
if (*transformNum != CXO_TRANSFORM_UNSUPPORTED)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// no valid type specified
|
||||||
|
snprintf(message, sizeof(message), "Python type %s not supported.",
|
||||||
|
pyType->tp_name);
|
||||||
|
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoTransform_getNumFromValue()
|
||||||
|
// Get the appropriate transformation to use for the specified value. If the
|
||||||
|
// value is an array, determine the transformation that can be used for all of
|
||||||
|
// the elements in that array.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int cxoTransform_getNumFromValue(PyObject *value, int *isArray,
|
||||||
|
Py_ssize_t *size, Py_ssize_t *numElements, int plsql,
|
||||||
|
cxoTransformNum *transformNum)
|
||||||
|
{
|
||||||
|
cxoTransformNum tempTransformNum;
|
||||||
|
PyObject *elementValue;
|
||||||
|
Py_ssize_t i, tempSize;
|
||||||
|
char message[250];
|
||||||
|
|
||||||
|
// initialization (except numElements which always has a valid value and is
|
||||||
|
// only overridden when a an array is encountered)
|
||||||
|
*size = 0;
|
||||||
|
*isArray = 0;
|
||||||
|
|
||||||
|
// handle arrays
|
||||||
|
if (PyList_Check(value)) {
|
||||||
|
*transformNum = CXO_TRANSFORM_NONE;
|
||||||
|
for (i = 0; i < PyList_GET_SIZE(value); i++) {
|
||||||
|
elementValue = PyList_GET_ITEM(value, i);
|
||||||
|
tempTransformNum = cxoTransform_getNumFromPythonValue(elementValue,
|
||||||
|
1);
|
||||||
|
if (tempTransformNum == CXO_TRANSFORM_UNSUPPORTED) {
|
||||||
|
snprintf(message, sizeof(message),
|
||||||
|
"element %u value of type %s is not supported",
|
||||||
|
(unsigned) i, Py_TYPE(value)->tp_name);
|
||||||
|
cxoError_raiseFromString(cxoNotSupportedErrorException,
|
||||||
|
message);
|
||||||
|
return -1;
|
||||||
|
} else if (*transformNum == CXO_TRANSFORM_NONE) {
|
||||||
|
*transformNum = tempTransformNum;
|
||||||
|
} else if (*transformNum != tempTransformNum) {
|
||||||
|
snprintf(message, sizeof(message),
|
||||||
|
"element %u value is not the same type as previous "
|
||||||
|
"elements", (unsigned) i);
|
||||||
|
cxoError_raiseFromString(cxoNotSupportedErrorException,
|
||||||
|
message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tempSize = cxoTransform_calculateSize(elementValue, *transformNum);
|
||||||
|
if (tempSize > *size)
|
||||||
|
*size = tempSize;
|
||||||
|
}
|
||||||
|
*isArray = 1;
|
||||||
|
*numElements = PyList_GET_SIZE(value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle scalar values
|
||||||
|
*transformNum = cxoTransform_getNumFromPythonValue(value, plsql);
|
||||||
|
if (*transformNum == CXO_TRANSFORM_UNSUPPORTED) {
|
||||||
|
snprintf(message, sizeof(message),
|
||||||
|
"Python value of type %s not supported.",
|
||||||
|
Py_TYPE(value)->tp_name);
|
||||||
|
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*size = cxoTransform_calculateSize(value, *transformNum);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoTransform_getTypeInfo()
|
// cxoTransform_getTypeInfo()
|
||||||
// Get type information for the specified transform. The transform number is
|
// Get type information for the specified transform. The transform number is
|
||||||
|
@ -618,17 +767,16 @@ PyObject *cxoTransform_toPython(cxoTransformNum transformNum,
|
||||||
cxoConnection *connection, cxoObjectType *objType,
|
cxoConnection *connection, cxoObjectType *objType,
|
||||||
dpiDataBuffer *dbValue, const char *encodingErrors)
|
dpiDataBuffer *dbValue, const char *encodingErrors)
|
||||||
{
|
{
|
||||||
const cxoTransform *transform;
|
|
||||||
PyObject *stringObj, *result;
|
PyObject *stringObj, *result;
|
||||||
dpiIntervalDS *intervalDS;
|
dpiIntervalDS *intervalDS;
|
||||||
dpiTimestamp *timestamp;
|
dpiTimestamp *timestamp;
|
||||||
uint32_t rowidLength;
|
uint32_t rowidLength;
|
||||||
|
cxoDbType *dbType;
|
||||||
const char *rowid;
|
const char *rowid;
|
||||||
cxoCursor *cursor;
|
cxoCursor *cursor;
|
||||||
dpiBytes *bytes;
|
dpiBytes *bytes;
|
||||||
int32_t seconds;
|
int32_t seconds;
|
||||||
|
|
||||||
transform = &cxoAllTransforms[transformNum];
|
|
||||||
switch (transformNum) {
|
switch (transformNum) {
|
||||||
case CXO_TRANSFORM_BINARY:
|
case CXO_TRANSFORM_BINARY:
|
||||||
case CXO_TRANSFORM_LONG_BINARY:
|
case CXO_TRANSFORM_LONG_BINARY:
|
||||||
|
@ -638,8 +786,8 @@ PyObject *cxoTransform_toPython(cxoTransformNum transformNum,
|
||||||
case CXO_TRANSFORM_BLOB:
|
case CXO_TRANSFORM_BLOB:
|
||||||
case CXO_TRANSFORM_CLOB:
|
case CXO_TRANSFORM_CLOB:
|
||||||
case CXO_TRANSFORM_NCLOB:
|
case CXO_TRANSFORM_NCLOB:
|
||||||
return cxoLob_new(connection, transform->oracleTypeNum,
|
dbType = cxoDbType_fromTransformNum(transformNum);
|
||||||
dbValue->asLOB);
|
return cxoLob_new(connection, dbType, dbValue->asLOB);
|
||||||
case CXO_TRANSFORM_BOOLEAN:
|
case CXO_TRANSFORM_BOOLEAN:
|
||||||
if (dbValue->asBoolean)
|
if (dbValue->asBoolean)
|
||||||
Py_RETURN_TRUE;
|
Py_RETURN_TRUE;
|
||||||
|
@ -660,6 +808,7 @@ PyObject *cxoTransform_toPython(cxoTransformNum transformNum,
|
||||||
case CXO_TRANSFORM_DATETIME:
|
case CXO_TRANSFORM_DATETIME:
|
||||||
case CXO_TRANSFORM_TIMESTAMP:
|
case CXO_TRANSFORM_TIMESTAMP:
|
||||||
case CXO_TRANSFORM_TIMESTAMP_LTZ:
|
case CXO_TRANSFORM_TIMESTAMP_LTZ:
|
||||||
|
case CXO_TRANSFORM_TIMESTAMP_TZ:
|
||||||
timestamp = &dbValue->asTimestamp;
|
timestamp = &dbValue->asTimestamp;
|
||||||
return PyDateTime_FromDateAndTime(timestamp->year,
|
return PyDateTime_FromDateAndTime(timestamp->year,
|
||||||
timestamp->month, timestamp->day, timestamp->hour,
|
timestamp->month, timestamp->day, timestamp->hour,
|
||||||
|
|
199
src/cxoVar.c
199
src/cxoVar.c
|
@ -15,7 +15,7 @@
|
||||||
#include "cxoModule.h"
|
#include "cxoModule.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Declaration of common variable functions.
|
// forward declaration of functions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static void cxoVar_free(cxoVar*);
|
static void cxoVar_free(cxoVar*);
|
||||||
static PyObject *cxoVar_repr(cxoVar*);
|
static PyObject *cxoVar_repr(cxoVar*);
|
||||||
|
@ -24,35 +24,36 @@ static PyObject *cxoVar_externalSetValue(cxoVar*, PyObject*);
|
||||||
static PyObject *cxoVar_externalGetValue(cxoVar*, PyObject*, PyObject*);
|
static PyObject *cxoVar_externalGetValue(cxoVar*, PyObject*, PyObject*);
|
||||||
static PyObject *cxoVar_externalGetActualElements(cxoVar*, void*);
|
static PyObject *cxoVar_externalGetActualElements(cxoVar*, void*);
|
||||||
static PyObject *cxoVar_externalGetValues(cxoVar*, void*);
|
static PyObject *cxoVar_externalGetValues(cxoVar*, void*);
|
||||||
|
static PyObject *cxoVar_getType(cxoVar*, void*);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of members for variables
|
// declaration of members
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyMemberDef cxoVarMembers[] = {
|
static PyMemberDef cxoMembers[] = {
|
||||||
{ "bufferSize", T_INT, offsetof(cxoVar, bufferSize), READONLY },
|
{ "bufferSize", T_INT, offsetof(cxoVar, bufferSize), READONLY },
|
||||||
{ "inconverter", T_OBJECT, offsetof(cxoVar, inConverter), 0 },
|
{ "inconverter", T_OBJECT, offsetof(cxoVar, inConverter), 0 },
|
||||||
{ "numElements", T_INT, offsetof(cxoVar, allocatedElements),
|
{ "numElements", T_INT, offsetof(cxoVar, allocatedElements),
|
||||||
READONLY },
|
READONLY },
|
||||||
{ "outconverter", T_OBJECT, offsetof(cxoVar, outConverter), 0 },
|
{ "outconverter", T_OBJECT, offsetof(cxoVar, outConverter), 0 },
|
||||||
{ "size", T_INT, offsetof(cxoVar, size), READONLY },
|
{ "size", T_INT, offsetof(cxoVar, size), READONLY },
|
||||||
{ "type", T_OBJECT, offsetof(cxoVar, objectType), READONLY },
|
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of calculated members for variables
|
// declaration of calculated members
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyGetSetDef cxoVarCalcMembers[] = {
|
static PyGetSetDef cxoCalcMembers[] = {
|
||||||
{ "actualElements", (getter) cxoVar_externalGetActualElements, 0, 0, 0 },
|
{ "actualElements", (getter) cxoVar_externalGetActualElements, 0, 0, 0 },
|
||||||
|
{ "type", (getter) cxoVar_getType, 0, 0, 0 },
|
||||||
{ "values", (getter) cxoVar_externalGetValues, 0, 0, 0 },
|
{ "values", (getter) cxoVar_externalGetValues, 0, 0, 0 },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of methods for variables
|
// declaration of methods
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyMethodDef cxoVarMethods[] = {
|
static PyMethodDef cxoVarMethods[] = {
|
||||||
{ "copy", (PyCFunction) cxoVar_externalCopy, METH_VARARGS },
|
{ "copy", (PyCFunction) cxoVar_externalCopy, METH_VARARGS },
|
||||||
|
@ -64,58 +65,35 @@ static PyMethodDef cxoVarMethods[] = {
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// declaration of all variable types
|
// declaration of Python type
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define DECLARE_VARIABLE_TYPE(INTERNAL_NAME, EXTERNAL_NAME) \
|
PyTypeObject cxoPyTypeVar = {
|
||||||
PyTypeObject INTERNAL_NAME = { \
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
PyVarObject_HEAD_INIT(NULL, 0) \
|
.tp_name = "cx_Oracle.Var",
|
||||||
.tp_name = "cx_Oracle." #EXTERNAL_NAME, \
|
.tp_basicsize = sizeof(cxoVar),
|
||||||
.tp_basicsize = sizeof(cxoVar), \
|
.tp_dealloc = (destructor) cxoVar_free,
|
||||||
.tp_dealloc = (destructor) cxoVar_free, \
|
.tp_repr = (reprfunc) cxoVar_repr,
|
||||||
.tp_repr = (reprfunc) cxoVar_repr, \
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
.tp_flags = Py_TPFLAGS_DEFAULT, \
|
.tp_methods = cxoVarMethods,
|
||||||
.tp_methods = cxoVarMethods, \
|
.tp_members = cxoMembers,
|
||||||
.tp_members = cxoVarMembers, \
|
.tp_getset = cxoCalcMembers
|
||||||
.tp_getset = cxoVarCalcMembers \
|
};
|
||||||
};
|
|
||||||
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeBfileVar, BFILE)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeBinaryVar, BINARY)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeBlobVar, BLOB)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeBooleanVar, BOOLEAN)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeClobVar, CLOB)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeCursorVar, CURSOR)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeDateTimeVar, DATETIME)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeFixedCharVar, FIXED_CHAR)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeFixedNcharVar, FIXED_NCHAR)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeIntervalVar, INTERVAL)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeLongBinaryVar, LONG_BINARY)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeLongStringVar, LONG_STRING)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeNativeFloatVar, NATIVE_FLOAT)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeNativeIntVar, NATIVE_INT)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeNcharVar, NCHAR)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeNclobVar, NCLOB)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeNumberVar, NUMBER)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeObjectVar, OBJECT)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeRowidVar, ROWID)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeStringVar, STRING)
|
|
||||||
DECLARE_VARIABLE_TYPE(cxoPyTypeTimestampVar, TIMESTAMP)
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoVar_new()
|
// cxoVar_new()
|
||||||
// Allocate a new variable.
|
// Allocate a new variable.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
|
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements,
|
||||||
Py_ssize_t size, int isArray, cxoObjectType *objType)
|
cxoTransformNum transformNum, Py_ssize_t size, int isArray,
|
||||||
|
cxoObjectType *objType)
|
||||||
{
|
{
|
||||||
dpiObjectType *typeHandle = NULL;
|
dpiObjectType *typeHandle = NULL;
|
||||||
dpiOracleTypeNum oracleTypeNum;
|
dpiOracleTypeNum oracleTypeNum;
|
||||||
dpiNativeTypeNum nativeTypeNum;
|
|
||||||
cxoVar *var;
|
cxoVar *var;
|
||||||
|
|
||||||
// attempt to allocate the object
|
// attempt to allocate the object
|
||||||
var = (cxoVar*) type->pythonType->tp_alloc(type->pythonType, 0);
|
var = (cxoVar*) cxoPyTypeVar.tp_alloc(&cxoPyTypeVar, 0);
|
||||||
if (!var)
|
if (!var)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -130,15 +108,25 @@ cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
|
||||||
if (numElements == 0)
|
if (numElements == 0)
|
||||||
numElements = 1;
|
numElements = 1;
|
||||||
var->allocatedElements = (uint32_t) numElements;
|
var->allocatedElements = (uint32_t) numElements;
|
||||||
var->type = type;
|
var->transformNum = transformNum;
|
||||||
var->size = (size == 0) ? type->size : (uint32_t) size;
|
var->size = (uint32_t) size;
|
||||||
|
if (var->size == 0)
|
||||||
|
var->size = cxoTransform_getDefaultSize(transformNum);
|
||||||
var->isArray = isArray;
|
var->isArray = isArray;
|
||||||
|
|
||||||
|
// determine database type
|
||||||
|
var->dbType = cxoDbType_fromTransformNum(var->transformNum);
|
||||||
|
if (!var->dbType) {
|
||||||
|
Py_DECREF(var);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_INCREF(var->dbType);
|
||||||
|
|
||||||
// acquire and initialize DPI variable
|
// acquire and initialize DPI variable
|
||||||
cxoTransform_getTypeInfo(type->transformNum, &oracleTypeNum,
|
cxoTransform_getTypeInfo(transformNum, &oracleTypeNum,
|
||||||
&nativeTypeNum);
|
&var->nativeTypeNum);
|
||||||
if (dpiConn_newVar(cursor->connection->handle, oracleTypeNum,
|
if (dpiConn_newVar(cursor->connection->handle, oracleTypeNum,
|
||||||
nativeTypeNum, var->allocatedElements, var->size, 0, isArray,
|
var->nativeTypeNum, var->allocatedElements, var->size, 0, isArray,
|
||||||
typeHandle, &var->handle, &var->data) < 0) {
|
typeHandle, &var->handle, &var->data) < 0) {
|
||||||
cxoError_raiseAndReturnNull();
|
cxoError_raiseAndReturnNull();
|
||||||
Py_DECREF(var);
|
Py_DECREF(var);
|
||||||
|
@ -174,6 +162,7 @@ static void cxoVar_free(cxoVar *var)
|
||||||
Py_CLEAR(var->inConverter);
|
Py_CLEAR(var->inConverter);
|
||||||
Py_CLEAR(var->outConverter);
|
Py_CLEAR(var->outConverter);
|
||||||
Py_CLEAR(var->objectType);
|
Py_CLEAR(var->objectType);
|
||||||
|
Py_CLEAR(var->dbType);
|
||||||
Py_TYPE(var)->tp_free((PyObject*) var);
|
Py_TYPE(var)->tp_free((PyObject*) var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,29 +173,7 @@ static void cxoVar_free(cxoVar *var)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int cxoVar_check(PyObject *object)
|
int cxoVar_check(PyObject *object)
|
||||||
{
|
{
|
||||||
PyTypeObject *objectType = Py_TYPE(object);
|
return (Py_TYPE(object) == &cxoPyTypeVar);
|
||||||
|
|
||||||
return (objectType == &cxoPyTypeBfileVar ||
|
|
||||||
objectType == &cxoPyTypeBinaryVar ||
|
|
||||||
objectType == &cxoPyTypeBlobVar ||
|
|
||||||
objectType == &cxoPyTypeBooleanVar ||
|
|
||||||
objectType == &cxoPyTypeClobVar ||
|
|
||||||
objectType == &cxoPyTypeCursorVar ||
|
|
||||||
objectType == &cxoPyTypeDateTimeVar ||
|
|
||||||
objectType == &cxoPyTypeFixedCharVar ||
|
|
||||||
objectType == &cxoPyTypeFixedNcharVar ||
|
|
||||||
objectType == &cxoPyTypeIntervalVar ||
|
|
||||||
objectType == &cxoPyTypeLongBinaryVar ||
|
|
||||||
objectType == &cxoPyTypeLongStringVar ||
|
|
||||||
objectType == &cxoPyTypeNativeFloatVar ||
|
|
||||||
objectType == &cxoPyTypeNativeIntVar ||
|
|
||||||
objectType == &cxoPyTypeNcharVar ||
|
|
||||||
objectType == &cxoPyTypeNclobVar ||
|
|
||||||
objectType == &cxoPyTypeNumberVar ||
|
|
||||||
objectType == &cxoPyTypeObjectVar ||
|
|
||||||
objectType == &cxoPyTypeRowidVar ||
|
|
||||||
objectType == &cxoPyTypeStringVar ||
|
|
||||||
objectType == &cxoPyTypeTimestampVar);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +186,7 @@ cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
|
||||||
{
|
{
|
||||||
PyObject *result, *inputTypeHandler = NULL;
|
PyObject *result, *inputTypeHandler = NULL;
|
||||||
cxoObjectType *objType = NULL;
|
cxoObjectType *objType = NULL;
|
||||||
cxoVarType *varType;
|
cxoTransformNum transformNum;
|
||||||
Py_ssize_t size;
|
Py_ssize_t size;
|
||||||
cxoObject *obj;
|
cxoObject *obj;
|
||||||
int isArray;
|
int isArray;
|
||||||
|
@ -253,15 +220,15 @@ cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
|
||||||
}
|
}
|
||||||
|
|
||||||
// default processing
|
// default processing
|
||||||
varType = cxoVarType_fromPythonValue(value,
|
if (cxoTransform_getNumFromValue(value, &isArray, &size, &numElements,
|
||||||
&isArray, &size, &numElements, cursor->stmtInfo.isPLSQL);
|
cursor->stmtInfo.isPLSQL, &transformNum) < 0)
|
||||||
if (!varType)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
if (varType->transformNum == CXO_TRANSFORM_OBJECT) {
|
if (transformNum == CXO_TRANSFORM_OBJECT) {
|
||||||
obj = (cxoObject*) value;
|
obj = (cxoObject*) value;
|
||||||
objType = obj->objectType;
|
objType = obj->objectType;
|
||||||
}
|
}
|
||||||
return cxoVar_new(cursor, numElements, varType, size, isArray, objType);
|
return cxoVar_new(cursor, numElements, transformNum, size, isArray,
|
||||||
|
objType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,8 +240,8 @@ static cxoVar *cxoVar_newArrayByType(cxoCursor *cursor,
|
||||||
PyObject *value)
|
PyObject *value)
|
||||||
{
|
{
|
||||||
PyObject *typeObj, *numElementsObj;
|
PyObject *typeObj, *numElementsObj;
|
||||||
|
cxoTransformNum transformNum;
|
||||||
cxoObjectType *objType;
|
cxoObjectType *objType;
|
||||||
cxoVarType *varType;
|
|
||||||
uint32_t numElements;
|
uint32_t numElements;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
|
@ -282,9 +249,6 @@ static cxoVar *cxoVar_newArrayByType(cxoCursor *cursor,
|
||||||
ok = (PyList_GET_SIZE(value) == 2);
|
ok = (PyList_GET_SIZE(value) == 2);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
typeObj = PyList_GET_ITEM(value, 0);
|
typeObj = PyList_GET_ITEM(value, 0);
|
||||||
ok = PyType_Check(typeObj);
|
|
||||||
}
|
|
||||||
if (ok) {
|
|
||||||
numElementsObj = PyList_GET_ITEM(value, 1);
|
numElementsObj = PyList_GET_ITEM(value, 1);
|
||||||
ok = PyLong_Check(numElementsObj);
|
ok = PyLong_Check(numElementsObj);
|
||||||
}
|
}
|
||||||
|
@ -295,13 +259,12 @@ static cxoVar *cxoVar_newArrayByType(cxoCursor *cursor,
|
||||||
}
|
}
|
||||||
|
|
||||||
// create variable
|
// create variable
|
||||||
varType = cxoVarType_fromPythonType(typeObj, &objType);
|
if (cxoTransform_getNumFromType(typeObj, &transformNum, &objType) < 0)
|
||||||
if (!varType)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
numElements = PyLong_AsLong(numElementsObj);
|
numElements = PyLong_AsLong(numElementsObj);
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
return cxoVar_new(cursor, numElements, varType, varType->size, 1, objType);
|
return cxoVar_new(cursor, numElements, transformNum, 0, 1, objType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -312,8 +275,8 @@ static cxoVar *cxoVar_newArrayByType(cxoCursor *cursor,
|
||||||
cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
||||||
uint32_t numElements)
|
uint32_t numElements)
|
||||||
{
|
{
|
||||||
|
cxoTransformNum transformNum;
|
||||||
cxoObjectType *objType;
|
cxoObjectType *objType;
|
||||||
cxoVarType *varType;
|
|
||||||
long size;
|
long size;
|
||||||
|
|
||||||
// passing an integer is assumed to be a string
|
// passing an integer is assumed to be a string
|
||||||
|
@ -321,9 +284,8 @@ cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
||||||
size = PyLong_AsLong(value);
|
size = PyLong_AsLong(value);
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return NULL;
|
return NULL;
|
||||||
varType = cxoVarType_fromPythonType((PyObject*) &PyUnicode_Type,
|
return cxoVar_new(cursor, numElements, CXO_TRANSFORM_STRING, size, 0,
|
||||||
&objType);
|
NULL);
|
||||||
return cxoVar_new(cursor, numElements, varType, size, 0, objType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// passing an array of two elements to define an array
|
// passing an array of two elements to define an array
|
||||||
|
@ -336,11 +298,11 @@ cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
||||||
return (cxoVar*) value;
|
return (cxoVar*) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// everything else ought to be a Python type or object type
|
// everything else ought to be a Python type, database type constant or
|
||||||
varType = cxoVarType_fromPythonType(value, &objType);
|
// object type
|
||||||
if (!varType)
|
if (cxoTransform_getNumFromType(value, &transformNum, &objType) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
return cxoVar_new(cursor, numElements, varType, varType->size, 0, objType);
|
return cxoVar_new(cursor, numElements, transformNum, 0, 0, objType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -426,10 +388,10 @@ PyObject *cxoVar_getSingleValue(cxoVar *var, dpiData *data, uint32_t arrayPos)
|
||||||
else data = &var->data[arrayPos];
|
else data = &var->data[arrayPos];
|
||||||
if (data->isNull)
|
if (data->isNull)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
value = cxoTransform_toPython(var->type->transformNum, var->connection,
|
value = cxoTransform_toPython(var->transformNum, var->connection,
|
||||||
var->objectType, &data->value, var->encodingErrors);
|
var->objectType, &data->value, var->encodingErrors);
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (var->type->transformNum) {
|
switch (var->transformNum) {
|
||||||
case CXO_TRANSFORM_BFILE:
|
case CXO_TRANSFORM_BFILE:
|
||||||
case CXO_TRANSFORM_BLOB:
|
case CXO_TRANSFORM_BLOB:
|
||||||
case CXO_TRANSFORM_CLOB:
|
case CXO_TRANSFORM_CLOB:
|
||||||
|
@ -491,7 +453,7 @@ static int cxoVar_setValueBytes(cxoVar *var, uint32_t pos, dpiData *data,
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (buffer->size > var->bufferSize) {
|
if (buffer->size > var->bufferSize) {
|
||||||
cxoTransform_getTypeInfo(var->type->transformNum, &oracleTypeNum,
|
cxoTransform_getTypeInfo(var->transformNum, &oracleTypeNum,
|
||||||
&nativeTypeNum);
|
&nativeTypeNum);
|
||||||
if (dpiConn_newVar(var->connection->handle, oracleTypeNum,
|
if (dpiConn_newVar(var->connection->handle, oracleTypeNum,
|
||||||
nativeTypeNum, var->allocatedElements, buffer->size, 0,
|
nativeTypeNum, var->allocatedElements, buffer->size, 0,
|
||||||
|
@ -605,18 +567,18 @@ static int cxoVar_setSingleValue(cxoVar *var, uint32_t arrayPos,
|
||||||
data = &var->data[arrayPos];
|
data = &var->data[arrayPos];
|
||||||
data->isNull = (value == Py_None);
|
data->isNull = (value == Py_None);
|
||||||
if (!data->isNull) {
|
if (!data->isNull) {
|
||||||
if (var->type->transformNum == CXO_TRANSFORM_CURSOR)
|
if (var->transformNum == CXO_TRANSFORM_CURSOR)
|
||||||
result = cxoVar_setValueCursor(var, arrayPos, data, value);
|
result = cxoVar_setValueCursor(var, arrayPos, data, value);
|
||||||
else {
|
else {
|
||||||
cxoBuffer_init(&buffer);
|
cxoBuffer_init(&buffer);
|
||||||
if (var->type->size > 0)
|
if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES)
|
||||||
dbValue = &tempDbValue;
|
dbValue = &tempDbValue;
|
||||||
else dbValue = &data->value;
|
else dbValue = &data->value;
|
||||||
result = cxoTransform_fromPython(var->type->transformNum,
|
result = cxoTransform_fromPython(var->transformNum,
|
||||||
&nativeTypeNum, value, dbValue, &buffer,
|
&nativeTypeNum, value, dbValue, &buffer,
|
||||||
var->connection->encodingInfo.encoding,
|
var->connection->encodingInfo.encoding,
|
||||||
var->connection->encodingInfo.nencoding, var, arrayPos);
|
var->connection->encodingInfo.nencoding, var, arrayPos);
|
||||||
if (result == 0 && var->type->size > 0)
|
if (result == 0 && var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES)
|
||||||
result = cxoVar_setValueBytes(var, arrayPos, data, &buffer);
|
result = cxoVar_setValueBytes(var, arrayPos, data, &buffer);
|
||||||
cxoBuffer_clear(&buffer);
|
cxoBuffer_clear(&buffer);
|
||||||
}
|
}
|
||||||
|
@ -762,13 +724,30 @@ static PyObject *cxoVar_externalGetValues(cxoVar *var, void *unused)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// cxoVar_getType()
|
||||||
|
// Return the type associated with the variable. This is either an object
|
||||||
|
// type or one of the database type constants.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static PyObject *cxoVar_getType(cxoVar *var, void *unused)
|
||||||
|
{
|
||||||
|
if (var->objectType) {
|
||||||
|
Py_INCREF(var->objectType);
|
||||||
|
return (PyObject*) var->objectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_INCREF(var->dbType);
|
||||||
|
return (PyObject*) var->dbType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// cxoVar_repr()
|
// cxoVar_repr()
|
||||||
// Return a string representation of the variable.
|
// Return a string representation of the variable.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static PyObject *cxoVar_repr(cxoVar *var)
|
static PyObject *cxoVar_repr(cxoVar *var)
|
||||||
{
|
{
|
||||||
PyObject *value, *module, *name, *result;
|
PyObject *value, *module, *name, *result, *typeName;
|
||||||
uint32_t numElements;
|
uint32_t numElements;
|
||||||
|
|
||||||
if (var->isArray) {
|
if (var->isArray) {
|
||||||
|
@ -780,14 +759,22 @@ static PyObject *cxoVar_repr(cxoVar *var)
|
||||||
else value = cxoVar_getArrayValue(var, var->allocatedElements, NULL);
|
else value = cxoVar_getArrayValue(var, var->allocatedElements, NULL);
|
||||||
if (!value)
|
if (!value)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (cxoUtils_getModuleAndName(Py_TYPE(var), &module, &name) < 0) {
|
typeName = PyUnicode_DecodeASCII(var->dbType->name,
|
||||||
|
strlen(var->dbType->name), NULL);
|
||||||
|
if (!typeName) {
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
result = cxoUtils_formatString("<%s.%s with value %r>",
|
if (cxoUtils_getModuleAndName(Py_TYPE(var), &module, &name) < 0) {
|
||||||
PyTuple_Pack(3, module, name, value));
|
Py_DECREF(typeName);
|
||||||
|
Py_DECREF(value);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result = cxoUtils_formatString("<%s.%s of type %s with value %r>",
|
||||||
|
PyTuple_Pack(4, module, name, typeName, value));
|
||||||
Py_DECREF(module);
|
Py_DECREF(module);
|
||||||
Py_DECREF(name);
|
Py_DECREF(name);
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
|
Py_DECREF(typeName);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
296
src/cxoVarType.c
296
src/cxoVarType.c
|
@ -1,296 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// cxoVarType.c
|
|
||||||
// Defines variable types for various transformations.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include "cxoModule.h"
|
|
||||||
|
|
||||||
// define variable types for each of the supported transforms
|
|
||||||
static cxoVarType cxoAllVarTypes[] = {
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_NONE,
|
|
||||||
&cxoPyTypeStringVar,
|
|
||||||
1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_BINARY,
|
|
||||||
&cxoPyTypeBinaryVar,
|
|
||||||
4000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_BFILE,
|
|
||||||
&cxoPyTypeBfileVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_BLOB,
|
|
||||||
&cxoPyTypeBlobVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_BOOLEAN,
|
|
||||||
&cxoPyTypeBooleanVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_CLOB,
|
|
||||||
&cxoPyTypeClobVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_CURSOR,
|
|
||||||
&cxoPyTypeCursorVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_DATE,
|
|
||||||
&cxoPyTypeDateTimeVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_DATETIME,
|
|
||||||
&cxoPyTypeDateTimeVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_DECIMAL,
|
|
||||||
&cxoPyTypeNumberVar,
|
|
||||||
1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_FIXED_CHAR,
|
|
||||||
&cxoPyTypeFixedCharVar,
|
|
||||||
2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_FIXED_NCHAR,
|
|
||||||
&cxoPyTypeFixedNcharVar,
|
|
||||||
2000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_FLOAT,
|
|
||||||
&cxoPyTypeNumberVar,
|
|
||||||
1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_INT,
|
|
||||||
&cxoPyTypeNumberVar,
|
|
||||||
1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_LONG_BINARY,
|
|
||||||
&cxoPyTypeLongBinaryVar,
|
|
||||||
128 * 1024
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_LONG_STRING,
|
|
||||||
&cxoPyTypeLongStringVar,
|
|
||||||
128 * 1024
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_NATIVE_DOUBLE,
|
|
||||||
&cxoPyTypeNativeFloatVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_NATIVE_FLOAT,
|
|
||||||
&cxoPyTypeNativeFloatVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_NATIVE_INT,
|
|
||||||
&cxoPyTypeNativeIntVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_NCLOB,
|
|
||||||
&cxoPyTypeNclobVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_NSTRING,
|
|
||||||
&cxoPyTypeNcharVar,
|
|
||||||
4000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_OBJECT,
|
|
||||||
&cxoPyTypeObjectVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_ROWID,
|
|
||||||
&cxoPyTypeRowidVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_STRING,
|
|
||||||
&cxoPyTypeStringVar,
|
|
||||||
4000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_TIMEDELTA,
|
|
||||||
&cxoPyTypeIntervalVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_TIMESTAMP,
|
|
||||||
&cxoPyTypeTimestampVar,
|
|
||||||
0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CXO_TRANSFORM_TIMESTAMP_LTZ,
|
|
||||||
&cxoPyTypeTimestampVar,
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// cxoVarType_fromDataTypeInfo()
|
|
||||||
// Return a variable type given query metadata, or NULL indicating that the
|
|
||||||
// data indicated by the query metadata is not supported.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
cxoVarType *cxoVarType_fromDataTypeInfo(dpiDataTypeInfo *info)
|
|
||||||
{
|
|
||||||
cxoTransformNum transformNum;
|
|
||||||
char message[120];
|
|
||||||
|
|
||||||
transformNum = cxoTransform_getNumFromDataTypeInfo(info);
|
|
||||||
if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
|
|
||||||
snprintf(message, sizeof(message), "Oracle type %d not supported.",
|
|
||||||
info->oracleTypeNum);
|
|
||||||
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return &cxoAllVarTypes[transformNum];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// cxoVarType_fromPythonType()
|
|
||||||
// Return a variable type given a Python type object or NULL if the Python
|
|
||||||
// type does not have a corresponding variable type. If the type provided is an
|
|
||||||
// object type, return that as well.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
cxoVarType *cxoVarType_fromPythonType(PyObject *type, cxoObjectType **objType)
|
|
||||||
{
|
|
||||||
cxoTransformNum transformNum;
|
|
||||||
PyTypeObject *pyType;
|
|
||||||
char message[250];
|
|
||||||
|
|
||||||
if (Py_TYPE(type) == &cxoPyTypeObjectType) {
|
|
||||||
transformNum = CXO_TRANSFORM_OBJECT;
|
|
||||||
*objType = (cxoObjectType*) type;
|
|
||||||
} else if (Py_TYPE(type) != &PyType_Type) {
|
|
||||||
PyErr_SetString(PyExc_TypeError, "expecting type");
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
*objType = NULL;
|
|
||||||
pyType = (PyTypeObject*) type;
|
|
||||||
transformNum = cxoTransform_getNumFromType(pyType);
|
|
||||||
if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
|
|
||||||
snprintf(message, sizeof(message), "Python type %s not supported.",
|
|
||||||
pyType->tp_name);
|
|
||||||
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &cxoAllVarTypes[transformNum];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// cxoVarType_calculateSize()
|
|
||||||
// Calculate the size to use with the specified transform and Python value.
|
|
||||||
// This function is only called by cxoVarType_fromPythonValue() and no attempt
|
|
||||||
// is made to verify the value further.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
static Py_ssize_t cxoVarType_calculateSize(PyObject *value,
|
|
||||||
cxoTransformNum transformNum)
|
|
||||||
{
|
|
||||||
Py_ssize_t size = 0;
|
|
||||||
|
|
||||||
switch (transformNum) {
|
|
||||||
case CXO_TRANSFORM_NONE:
|
|
||||||
return 1;
|
|
||||||
case CXO_TRANSFORM_BINARY:
|
|
||||||
return PyBytes_GET_SIZE(value);
|
|
||||||
case CXO_TRANSFORM_NSTRING:
|
|
||||||
size = PyUnicode_GET_SIZE(value);
|
|
||||||
return (size == 0) ? 1 : size;
|
|
||||||
case CXO_TRANSFORM_STRING:
|
|
||||||
size = PyUnicode_GET_SIZE(value);
|
|
||||||
return (size == 0) ? 1 : size;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// cxoVarType_fromPythonValue()
|
|
||||||
// Return a variable type given a Python object or NULL if the Python object
|
|
||||||
// does not have a corresponding variable type.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
cxoVarType *cxoVarType_fromPythonValue(PyObject *value, int *isArray,
|
|
||||||
Py_ssize_t *size, Py_ssize_t *numElements, int plsql)
|
|
||||||
{
|
|
||||||
cxoTransformNum transformNum, tempTransformNum;
|
|
||||||
PyObject *elementValue;
|
|
||||||
Py_ssize_t i, tempSize;
|
|
||||||
char message[250];
|
|
||||||
|
|
||||||
// initialization (except numElements which always has a valid value and is
|
|
||||||
// only overridden when a an array is encountered)
|
|
||||||
*size = 0;
|
|
||||||
*isArray = 0;
|
|
||||||
|
|
||||||
// handle arrays
|
|
||||||
if (PyList_Check(value)) {
|
|
||||||
transformNum = CXO_TRANSFORM_NONE;
|
|
||||||
for (i = 0; i < PyList_GET_SIZE(value); i++) {
|
|
||||||
elementValue = PyList_GET_ITEM(value, i);
|
|
||||||
tempTransformNum = cxoTransform_getNumFromValue(elementValue, 1);
|
|
||||||
if (tempTransformNum == CXO_TRANSFORM_UNSUPPORTED) {
|
|
||||||
snprintf(message, sizeof(message),
|
|
||||||
"element %u value is unsupported", (unsigned) i);
|
|
||||||
cxoError_raiseFromString(cxoNotSupportedErrorException,
|
|
||||||
message);
|
|
||||||
return NULL;
|
|
||||||
} else if (transformNum == CXO_TRANSFORM_NONE) {
|
|
||||||
transformNum = tempTransformNum;
|
|
||||||
} else if (transformNum != tempTransformNum) {
|
|
||||||
snprintf(message, sizeof(message),
|
|
||||||
"element %u value is not the same type as previous "
|
|
||||||
"elements", (unsigned) i);
|
|
||||||
cxoError_raiseFromString(cxoNotSupportedErrorException,
|
|
||||||
message);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
tempSize = cxoVarType_calculateSize(elementValue,
|
|
||||||
tempTransformNum);
|
|
||||||
if (tempSize > *size)
|
|
||||||
*size = tempSize;
|
|
||||||
}
|
|
||||||
*isArray = 1;
|
|
||||||
*numElements = PyList_GET_SIZE(value);
|
|
||||||
return &cxoAllVarTypes[transformNum];
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle scalar values
|
|
||||||
transformNum = cxoTransform_getNumFromValue(value, plsql);
|
|
||||||
if (transformNum == CXO_TRANSFORM_UNSUPPORTED) {
|
|
||||||
snprintf(message, sizeof(message),
|
|
||||||
"Python value of type %s not supported.",
|
|
||||||
Py_TYPE(value)->tp_name);
|
|
||||||
cxoError_raiseFromString(cxoNotSupportedErrorException, message);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*size = cxoVarType_calculateSize(value, transformNum);
|
|
||||||
return &cxoAllVarTypes[transformNum];
|
|
||||||
}
|
|
|
@ -31,7 +31,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
def testBindOutFalse(self):
|
def testBindOutFalse(self):
|
||||||
"test binding out a boolean value (False)"
|
"test binding out a boolean value (False)"
|
||||||
result = self.cursor.callfunc("pkg_TestBooleans.IsLessThan10",
|
result = self.cursor.callfunc("pkg_TestBooleans.IsLessThan10",
|
||||||
cx_Oracle.BOOLEAN, (15,))
|
cx_Oracle.DB_TYPE_BOOLEAN, (15,))
|
||||||
self.assertEqual(result, False)
|
self.assertEqual(result, False)
|
||||||
|
|
||||||
def testBindOutTrue(self):
|
def testBindOutTrue(self):
|
||||||
|
|
|
@ -191,7 +191,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
encoding="UTF-8", nencoding="UTF-16")
|
encoding="UTF-8", nencoding="UTF-16")
|
||||||
value = u"\u03b4\u4e2a"
|
value = u"\u03b4\u4e2a"
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
ncharVar = cursor.var(cx_Oracle.NCHAR, 100)
|
ncharVar = cursor.var(cx_Oracle.DB_TYPE_NVARCHAR, 100)
|
||||||
ncharVar.setvalue(0, value)
|
ncharVar.setvalue(0, value)
|
||||||
cursor.execute("select :value from dual", value = ncharVar)
|
cursor.execute("select :value from dual", value = ncharVar)
|
||||||
result, = cursor.fetchone()
|
result, = cursor.fetchone()
|
||||||
|
|
|
@ -613,7 +613,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
self.cursor.parse(sql)
|
self.cursor.parse(sql)
|
||||||
self.assertEqual(self.cursor.statement, sql)
|
self.assertEqual(self.cursor.statement, sql)
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('LONGINTCOL', cx_Oracle.NUMBER, 17, None, 16, 0, 0) ])
|
[ ('LONGINTCOL', cx_Oracle.DB_TYPE_NUMBER, 17, None, 16, 0,
|
||||||
|
0) ])
|
||||||
|
|
||||||
def testSetOutputSize(self):
|
def testSetOutputSize(self):
|
||||||
"test cursor.setoutputsize() does not fail (but does nothing)"
|
"test cursor.setoutputsize() does not fail (but does nothing)"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
#
|
#
|
||||||
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -26,7 +26,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
end;""",
|
end;""",
|
||||||
cursor = cursor)
|
cursor = cursor)
|
||||||
self.assertEqual(cursor.description,
|
self.assertEqual(cursor.description,
|
||||||
[ ('STRINGVALUE', cx_Oracle.FIXED_CHAR, 1,
|
[ ('STRINGVALUE', cx_Oracle.DB_TYPE_CHAR, 1,
|
||||||
TestEnv.GetCharSetRatio(), None, None, 1) ])
|
TestEnv.GetCharSetRatio(), None, None, 1) ])
|
||||||
self.assertEqual(cursor.fetchall(), [('X',)])
|
self.assertEqual(cursor.fetchall(), [('X',)])
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
self.assertEqual(cursor.description, None)
|
self.assertEqual(cursor.description, None)
|
||||||
self.cursor.callproc("pkg_TestRefCursors.TestOutCursor", (2, cursor))
|
self.cursor.callproc("pkg_TestRefCursors.TestOutCursor", (2, cursor))
|
||||||
self.assertEqual(cursor.description,
|
self.assertEqual(cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('STRINGCOL', cx_Oracle.STRING, 20, 20 *
|
('STRINGCOL', cx_Oracle.DB_TYPE_VARCHAR, 20, 20 *
|
||||||
TestEnv.GetCharSetRatio(), None, None, 0) ])
|
TestEnv.GetCharSetRatio(), None, None, 0) ])
|
||||||
self.assertEqual(cursor.fetchall(),
|
self.assertEqual(cursor.fetchall(),
|
||||||
[ (1, 'String 1'), (2, 'String 2') ])
|
[ (1, 'String 1'), (2, 'String 2') ])
|
||||||
|
@ -80,9 +80,9 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
from TestNumbers
|
from TestNumbers
|
||||||
order by IntCol""")
|
order by IntCol""")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('CURSORVALUE', cx_Oracle.CURSOR, None, None, None, None,
|
('CURSORVALUE', cx_Oracle.DB_TYPE_CURSOR, None, None, None,
|
||||||
1) ])
|
None, 1) ])
|
||||||
for i in range(1, 11):
|
for i in range(1, 11):
|
||||||
number, cursor = self.cursor.fetchone()
|
number, cursor = self.cursor.fetchone()
|
||||||
self.assertEqual(number, i)
|
self.assertEqual(number, i)
|
||||||
|
@ -90,4 +90,3 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
TestEnv.RunTestCases()
|
TestEnv.RunTestCases()
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
stringValue = "The string that will be verified"
|
stringValue = "The string that will be verified"
|
||||||
obj = typeObj.newobject()
|
obj = typeObj.newobject()
|
||||||
obj.STRINGVALUE = stringValue
|
obj.STRINGVALUE = stringValue
|
||||||
outVar = self.cursor.var(cx_Oracle.OBJECT, typename = "UDT_OBJECT")
|
outVar = self.cursor.var(cx_Oracle.DB_TYPE_OBJECT,
|
||||||
|
typename = "UDT_OBJECT")
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
insert into TestObjects (IntCol, ObjectCol)
|
insert into TestObjects (IntCol, ObjectCol)
|
||||||
values (4, :obj)
|
values (4, :obj)
|
||||||
|
|
|
@ -215,9 +215,9 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate"
|
"test cursor description is accurate"
|
||||||
self.cursor.execute("select * from TestDates")
|
self.cursor.execute("select * from TestDates")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('DATECOL', cx_Oracle.DATETIME, 23, None, None, None, 0),
|
('DATECOL', cx_Oracle.DB_TYPE_DATE, 23, None, None, None, 0),
|
||||||
('NULLABLECOL', cx_Oracle.DATETIME, 23, None, None, None,
|
('NULLABLECOL', cx_Oracle.DB_TYPE_DATE, 23, None, None, None,
|
||||||
1) ])
|
1) ])
|
||||||
|
|
||||||
def testFetchAll(self):
|
def testFetchAll(self):
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
"""
|
||||||
|
Module for testing comparisons with database types and API types. This also
|
||||||
|
contains tests for comparisons with database types and variable types, for
|
||||||
|
backwards compatibility.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import TestEnv
|
||||||
|
|
||||||
|
import cx_Oracle
|
||||||
|
|
||||||
|
class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
|
def __testCompare(self, dbType, apiType):
|
||||||
|
self.assertEqual(dbType, dbType)
|
||||||
|
self.assertEqual(dbType, apiType)
|
||||||
|
self.assertEqual(apiType, dbType)
|
||||||
|
self.assertNotEqual(dbType, 5)
|
||||||
|
self.assertNotEqual(dbType, cx_Oracle.DB_TYPE_OBJECT)
|
||||||
|
|
||||||
|
def testBfile(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_BFILE comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_BFILE, cx_Oracle.BINARY)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_BFILE, cx_Oracle.BFILE)
|
||||||
|
|
||||||
|
def testBinaryDouble(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_BINARY_DOUBLE comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_BINARY_DOUBLE, cx_Oracle.NUMBER)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_BINARY_DOUBLE,
|
||||||
|
cx_Oracle.NATIVE_FLOAT)
|
||||||
|
|
||||||
|
def testBinaryFloat(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_BINARY_FLOAT comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_BINARY_FLOAT, cx_Oracle.NUMBER)
|
||||||
|
|
||||||
|
def testBinaryInteger(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_BINARY_INTEGER comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_BINARY_INTEGER, cx_Oracle.NUMBER)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_BINARY_INTEGER,
|
||||||
|
cx_Oracle.NATIVE_INT)
|
||||||
|
|
||||||
|
def testBlob(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_BLOB comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_BLOB, cx_Oracle.BINARY)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_BLOB, cx_Oracle.BLOB)
|
||||||
|
|
||||||
|
def testBoolean(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_BOOLEAN comparisons"
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_BOOLEAN, cx_Oracle.BOOLEAN)
|
||||||
|
|
||||||
|
def testChar(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_CHAR comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.STRING)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_CHAR, cx_Oracle.FIXED_CHAR)
|
||||||
|
|
||||||
|
def testClob(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_CLOB comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_CLOB, cx_Oracle.STRING)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_CLOB, cx_Oracle.CLOB)
|
||||||
|
|
||||||
|
def testCursor(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_CURSOR comparisons"
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_CURSOR, cx_Oracle.CURSOR)
|
||||||
|
|
||||||
|
def testDate(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_DATE comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_DATE, cx_Oracle.DATETIME)
|
||||||
|
|
||||||
|
def testIntervalDS(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_INTERVAL_DS comparisons"
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_INTERVAL_DS, cx_Oracle.INTERVAL)
|
||||||
|
|
||||||
|
def testLong(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_LONG comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_LONG, cx_Oracle.STRING)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_LONG, cx_Oracle.LONG_STRING)
|
||||||
|
|
||||||
|
def testLongRaw(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_LONG_RAW comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.BINARY)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_LONG_RAW, cx_Oracle.LONG_BINARY)
|
||||||
|
|
||||||
|
def testNchar(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_NCHAR comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.STRING)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_NCHAR, cx_Oracle.FIXED_NCHAR)
|
||||||
|
|
||||||
|
def testNclob(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_NCLOB comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_NCLOB, cx_Oracle.STRING)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_NCLOB, cx_Oracle.NCLOB)
|
||||||
|
|
||||||
|
def testNumber(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_NUMBER comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.NUMBER)
|
||||||
|
|
||||||
|
def testNvarchar(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_NVARCHAR comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.STRING)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.NCHAR)
|
||||||
|
|
||||||
|
def testObject(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_OBJECT comparisons"
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_OBJECT, cx_Oracle.OBJECT)
|
||||||
|
|
||||||
|
def testRaw(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_RAW comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_RAW, cx_Oracle.BINARY)
|
||||||
|
|
||||||
|
def testRowid(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_ROWID comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_ROWID, cx_Oracle.ROWID)
|
||||||
|
|
||||||
|
def testTimestamp(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_TIMESTAMP comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.DATETIME)
|
||||||
|
self.assertEqual(cx_Oracle.DB_TYPE_TIMESTAMP, cx_Oracle.TIMESTAMP)
|
||||||
|
|
||||||
|
def testTimestampLTZ(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_TIMESTAMP_LTZ comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_LTZ, cx_Oracle.DATETIME)
|
||||||
|
|
||||||
|
def testTimestampTZ(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_TIMESTAMP_TZ comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_TIMESTAMP_TZ, cx_Oracle.DATETIME)
|
||||||
|
|
||||||
|
def testVarchar(self):
|
||||||
|
"test cx_Oracle.DB_TYPE_VARCHAR comparisons"
|
||||||
|
self.__testCompare(cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.STRING)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
TestEnv.RunTestCases()
|
|
@ -34,7 +34,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInterval(self):
|
def testBindInterval(self):
|
||||||
"test binding in an interval"
|
"test binding in an interval"
|
||||||
self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
|
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
select * from TestIntervals
|
select * from TestIntervals
|
||||||
where IntervalCol = :value""",
|
where IntervalCol = :value""",
|
||||||
|
@ -44,7 +44,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindNull(self):
|
def testBindNull(self):
|
||||||
"test binding in a null"
|
"test binding in a null"
|
||||||
self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
|
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
select * from TestIntervals
|
select * from TestIntervals
|
||||||
where IntervalCol = :value""",
|
where IntervalCol = :value""",
|
||||||
|
@ -53,7 +53,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindOutSetInputSizes(self):
|
def testBindOutSetInputSizes(self):
|
||||||
"test binding out with set input sizes defined"
|
"test binding out with set input sizes defined"
|
||||||
vars = self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
|
vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
:value := to_dsinterval('8 09:24:18.123789');
|
:value := to_dsinterval('8 09:24:18.123789');
|
||||||
|
@ -64,7 +64,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutSetInputSizes(self):
|
def testBindInOutSetInputSizes(self):
|
||||||
"test binding in/out with set input sizes defined"
|
"test binding in/out with set input sizes defined"
|
||||||
vars = self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
|
vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
:value := :value + to_dsinterval('5 08:30:00');
|
:value := :value + to_dsinterval('5 08:30:00');
|
||||||
|
@ -75,7 +75,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutFractionalSecond(self):
|
def testBindInOutFractionalSecond(self):
|
||||||
"test binding in/out with set input sizes defined"
|
"test binding in/out with set input sizes defined"
|
||||||
vars = self.cursor.setinputsizes(value = cx_Oracle.INTERVAL)
|
vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_INTERVAL_DS)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
:value := :value + to_dsinterval('5 08:30:00');
|
:value := :value + to_dsinterval('5 08:30:00');
|
||||||
|
@ -87,7 +87,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindOutVar(self):
|
def testBindOutVar(self):
|
||||||
"test binding out with cursor.var() method"
|
"test binding out with cursor.var() method"
|
||||||
var = self.cursor.var(cx_Oracle.INTERVAL)
|
var = self.cursor.var(cx_Oracle.DB_TYPE_INTERVAL_DS)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
:value := to_dsinterval('15 18:35:45.586');
|
:value := to_dsinterval('15 18:35:45.586');
|
||||||
|
@ -99,7 +99,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutVarDirectSet(self):
|
def testBindInOutVarDirectSet(self):
|
||||||
"test binding in/out with cursor.var() method"
|
"test binding in/out with cursor.var() method"
|
||||||
var = self.cursor.var(cx_Oracle.INTERVAL)
|
var = self.cursor.var(cx_Oracle.DB_TYPE_INTERVAL_DS)
|
||||||
var.setvalue(0, datetime.timedelta(days = 1, minutes = 50))
|
var.setvalue(0, datetime.timedelta(days = 1, minutes = 50))
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
|
@ -113,9 +113,11 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate"
|
"test cursor description is accurate"
|
||||||
self.cursor.execute("select * from TestIntervals")
|
self.cursor.execute("select * from TestIntervals")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('INTERVALCOL', cx_Oracle.INTERVAL, None, None, 2, 6, 0),
|
('INTERVALCOL', cx_Oracle.DB_TYPE_INTERVAL_DS, None, None, 2,
|
||||||
('NULLABLECOL', cx_Oracle.INTERVAL, None, None, 2, 6, 1) ])
|
6, 0),
|
||||||
|
('NULLABLECOL', cx_Oracle.DB_TYPE_INTERVAL_DS, None, None, 2,
|
||||||
|
6, 1) ])
|
||||||
|
|
||||||
def testFetchAll(self):
|
def testFetchAll(self):
|
||||||
"test that fetching all of the data returns the correct results"
|
"test that fetching all of the data returns the correct results"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
#
|
#
|
||||||
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -117,8 +117,10 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def __ValidateQuery(self, rows, lobType):
|
def __ValidateQuery(self, rows, lobType):
|
||||||
longString = ""
|
longString = ""
|
||||||
|
dbType = getattr(cx_Oracle, "DB_TYPE_" + lobType)
|
||||||
for row in rows:
|
for row in rows:
|
||||||
integerValue, lob = row
|
integerValue, lob = row
|
||||||
|
self.assertEqual(lob.type, dbType)
|
||||||
if integerValue == 0:
|
if integerValue == 0:
|
||||||
self.assertEqual(lob.size(), 0)
|
self.assertEqual(lob.size(), 0)
|
||||||
expectedValue = ""
|
expectedValue = ""
|
||||||
|
@ -158,16 +160,17 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate for BLOBs"
|
"test cursor description is accurate for BLOBs"
|
||||||
self.cursor.execute("select * from TestBLOBs")
|
self.cursor.execute("select * from TestBLOBs")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('BLOBCOL', cx_Oracle.BLOB, None, None, None, None, 0) ])
|
('BLOBCOL', cx_Oracle.DB_TYPE_BLOB, None, None, None, None,
|
||||||
|
0) ])
|
||||||
|
|
||||||
def testBLOBsDirect(self):
|
def testBLOBsDirect(self):
|
||||||
"test binding and fetching BLOB data (directly)"
|
"test binding and fetching BLOB data (directly)"
|
||||||
self.__PerformTest("BLOB", cx_Oracle.BLOB)
|
self.__PerformTest("BLOB", cx_Oracle.DB_TYPE_BLOB)
|
||||||
|
|
||||||
def testBLOBsIndirect(self):
|
def testBLOBsIndirect(self):
|
||||||
"test binding and fetching BLOB data (indirectly)"
|
"test binding and fetching BLOB data (indirectly)"
|
||||||
self.__PerformTest("BLOB", cx_Oracle.LONG_BINARY)
|
self.__PerformTest("BLOB", cx_Oracle.DB_TYPE_LONG_RAW)
|
||||||
|
|
||||||
def testBLOBOperations(self):
|
def testBLOBOperations(self):
|
||||||
"test operations on BLOBs"
|
"test operations on BLOBs"
|
||||||
|
@ -177,16 +180,17 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate for CLOBs"
|
"test cursor description is accurate for CLOBs"
|
||||||
self.cursor.execute("select * from TestCLOBs")
|
self.cursor.execute("select * from TestCLOBs")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('CLOBCOL', cx_Oracle.CLOB, None, None, None, None, 0) ])
|
('CLOBCOL', cx_Oracle.DB_TYPE_CLOB, None, None, None, None,
|
||||||
|
0) ])
|
||||||
|
|
||||||
def testCLOBsDirect(self):
|
def testCLOBsDirect(self):
|
||||||
"test binding and fetching CLOB data (directly)"
|
"test binding and fetching CLOB data (directly)"
|
||||||
self.__PerformTest("CLOB", cx_Oracle.CLOB)
|
self.__PerformTest("CLOB", cx_Oracle.DB_TYPE_CLOB)
|
||||||
|
|
||||||
def testCLOBsIndirect(self):
|
def testCLOBsIndirect(self):
|
||||||
"test binding and fetching CLOB data (indirectly)"
|
"test binding and fetching CLOB data (indirectly)"
|
||||||
self.__PerformTest("CLOB", cx_Oracle.LONG_STRING)
|
self.__PerformTest("CLOB", cx_Oracle.DB_TYPE_LONG)
|
||||||
|
|
||||||
def testCLOBOperations(self):
|
def testCLOBOperations(self):
|
||||||
"test operations on CLOBs"
|
"test operations on CLOBs"
|
||||||
|
@ -215,12 +219,13 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate for NCLOBs"
|
"test cursor description is accurate for NCLOBs"
|
||||||
self.cursor.execute("select * from TestNCLOBs")
|
self.cursor.execute("select * from TestNCLOBs")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('NCLOBCOL', cx_Oracle.NCLOB, None, None, None, None, 0) ])
|
('NCLOBCOL', cx_Oracle.DB_TYPE_NCLOB, None, None, None, None,
|
||||||
|
0) ])
|
||||||
|
|
||||||
def testNCLOBsDirect(self):
|
def testNCLOBsDirect(self):
|
||||||
"test binding and fetching NCLOB data (directly)"
|
"test binding and fetching NCLOB data (directly)"
|
||||||
self.__PerformTest("NCLOB", cx_Oracle.NCLOB)
|
self.__PerformTest("NCLOB", cx_Oracle.DB_TYPE_NCLOB)
|
||||||
|
|
||||||
def testNCLOBDifferentEncodings(self):
|
def testNCLOBDifferentEncodings(self):
|
||||||
"test binding and fetching NCLOB data (different encodings)"
|
"test binding and fetching NCLOB data (different encodings)"
|
||||||
|
@ -230,11 +235,11 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
value = u"\u03b4\u4e2a"
|
value = u"\u03b4\u4e2a"
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("truncate table TestNCLOBs")
|
cursor.execute("truncate table TestNCLOBs")
|
||||||
cursor.setinputsizes(val = cx_Oracle.NCHAR)
|
cursor.setinputsizes(val = cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
cursor.execute("insert into TestNCLOBs values (1, :val)", val = value)
|
cursor.execute("insert into TestNCLOBs values (1, :val)", val = value)
|
||||||
cursor.execute("select NCLOBCol from TestNCLOBs")
|
cursor.execute("select NCLOBCol from TestNCLOBs")
|
||||||
nclob, = cursor.fetchone()
|
nclob, = cursor.fetchone()
|
||||||
cursor.setinputsizes(val = cx_Oracle.NCHAR)
|
cursor.setinputsizes(val = cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
cursor.execute("update TestNCLOBs set NCLOBCol = :val",
|
cursor.execute("update TestNCLOBs set NCLOBCol = :val",
|
||||||
val = nclob.read() + value)
|
val = nclob.read() + value)
|
||||||
cursor.execute("select NCLOBCol from TestNCLOBs")
|
cursor.execute("select NCLOBCol from TestNCLOBs")
|
||||||
|
@ -243,7 +248,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testNCLOBsIndirect(self):
|
def testNCLOBsIndirect(self):
|
||||||
"test binding and fetching NCLOB data (indirectly)"
|
"test binding and fetching NCLOB data (indirectly)"
|
||||||
self.__PerformTest("NCLOB", cx_Oracle.LONG_STRING)
|
self.__PerformTest("NCLOB", cx_Oracle.DB_TYPE_LONG)
|
||||||
|
|
||||||
def testNCLOBOperations(self):
|
def testNCLOBOperations(self):
|
||||||
"test operations on NCLOBs"
|
"test operations on NCLOBs"
|
||||||
|
@ -271,7 +276,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testAssignStringBeyondArraySize(self):
|
def testAssignStringBeyondArraySize(self):
|
||||||
"test assign string to NCLOB beyond array size"
|
"test assign string to NCLOB beyond array size"
|
||||||
nclobVar = self.cursor.var(cx_Oracle.NCLOB)
|
nclobVar = self.cursor.var(cx_Oracle.DB_TYPE_NCLOB)
|
||||||
self.assertRaises(IndexError, nclobVar.setvalue, 1, "test char")
|
self.assertRaises(IndexError, nclobVar.setvalue, 1, "test char")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -59,7 +59,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testLongs(self):
|
def testLongs(self):
|
||||||
"test binding and fetching long data"
|
"test binding and fetching long data"
|
||||||
self.__PerformTest("Long", cx_Oracle.LONG_STRING)
|
self.__PerformTest("Long", cx_Oracle.DB_TYPE_LONG)
|
||||||
|
|
||||||
def testLongWithExecuteMany(self):
|
def testLongWithExecuteMany(self):
|
||||||
"test binding long data with executemany()"
|
"test binding long data with executemany()"
|
||||||
|
@ -77,23 +77,23 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testLongRaws(self):
|
def testLongRaws(self):
|
||||||
"test binding and fetching long raw data"
|
"test binding and fetching long raw data"
|
||||||
self.__PerformTest("LongRaw", cx_Oracle.LONG_BINARY)
|
self.__PerformTest("LongRaw", cx_Oracle.DB_TYPE_LONG_RAW)
|
||||||
|
|
||||||
def testLongCursorDescription(self):
|
def testLongCursorDescription(self):
|
||||||
"test cursor description is accurate for longs"
|
"test cursor description is accurate for longs"
|
||||||
self.cursor.execute("select * from TestLongs")
|
self.cursor.execute("select * from TestLongs")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('LONGCOL', cx_Oracle.LONG_STRING, None, None, None, None,
|
('LONGCOL', cx_Oracle.DB_TYPE_LONG, None, None, None, None,
|
||||||
0) ])
|
0) ])
|
||||||
|
|
||||||
def testLongRawCursorDescription(self):
|
def testLongRawCursorDescription(self):
|
||||||
"test cursor description is accurate for long raws"
|
"test cursor description is accurate for long raws"
|
||||||
self.cursor.execute("select * from TestLongRaws")
|
self.cursor.execute("select * from TestLongRaws")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('LONGRAWCOL', cx_Oracle.LONG_BINARY, None, None, None, None,
|
('LONGRAWCOL', cx_Oracle.DB_TYPE_LONG_RAW, None, None, None,
|
||||||
0) ])
|
None, 0) ])
|
||||||
|
|
||||||
def testArraySizeTooLarge(self):
|
def testArraySizeTooLarge(self):
|
||||||
"test array size too large generates an exception"
|
"test array size too large generates an exception"
|
||||||
|
|
|
@ -43,7 +43,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindUnicode(self):
|
def testBindUnicode(self):
|
||||||
"test binding in a unicode"
|
"test binding in a unicode"
|
||||||
self.cursor.setinputsizes(value = cx_Oracle.NCHAR)
|
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
select * from TestUnicodes
|
select * from TestUnicodes
|
||||||
where UnicodeCol = :value""",
|
where UnicodeCol = :value""",
|
||||||
|
@ -52,8 +52,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindDifferentVar(self):
|
def testBindDifferentVar(self):
|
||||||
"test binding a different variable on second execution"
|
"test binding a different variable on second execution"
|
||||||
retval_1 = self.cursor.var(cx_Oracle.NCHAR, 30)
|
retval_1 = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR, 30)
|
||||||
retval_2 = self.cursor.var(cx_Oracle.NCHAR, 30)
|
retval_2 = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR, 30)
|
||||||
self.cursor.execute(r"begin :retval := unistr('Called \3042'); end;",
|
self.cursor.execute(r"begin :retval := unistr('Called \3042'); end;",
|
||||||
retval = retval_1)
|
retval = retval_1)
|
||||||
self.assertEqual(retval_1.getvalue(), u"Called \u3042")
|
self.assertEqual(retval_1.getvalue(), u"Called \u3042")
|
||||||
|
@ -63,7 +63,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindUnicodeAfterNumber(self):
|
def testBindUnicodeAfterNumber(self):
|
||||||
"test binding in a unicode after setting input sizes to a number"
|
"test binding in a unicode after setting input sizes to a number"
|
||||||
unicodeVal = self.cursor.var(cx_Oracle.NCHAR)
|
unicodeVal = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
unicodeVal.setvalue(0, u"Unicode \u3042 6")
|
unicodeVal.setvalue(0, u"Unicode \u3042 6")
|
||||||
self.cursor.setinputsizes(value = cx_Oracle.NUMBER)
|
self.cursor.setinputsizes(value = cx_Oracle.NUMBER)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
|
@ -76,7 +76,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test binding in a unicode array"
|
"test binding in a unicode array"
|
||||||
returnValue = self.cursor.var(cx_Oracle.NUMBER)
|
returnValue = self.cursor.var(cx_Oracle.NUMBER)
|
||||||
array = [r[1] for r in self.rawData]
|
array = [r[1] for r in self.rawData]
|
||||||
arrayVar = self.cursor.arrayvar(cx_Oracle.NCHAR, array)
|
arrayVar = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, array)
|
||||||
statement = """
|
statement = """
|
||||||
begin
|
begin
|
||||||
:retval := pkg_TestUnicodeArrays.TestInArrays(
|
:retval := pkg_TestUnicodeArrays.TestInArrays(
|
||||||
|
@ -88,7 +88,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
array = arrayVar)
|
array = arrayVar)
|
||||||
self.assertEqual(returnValue.getvalue(), 116)
|
self.assertEqual(returnValue.getvalue(), 116)
|
||||||
array = [ u"Unicode - \u3042 %d" % i for i in range(15) ]
|
array = [ u"Unicode - \u3042 %d" % i for i in range(15) ]
|
||||||
arrayVar = self.cursor.arrayvar(cx_Oracle.NCHAR, array)
|
arrayVar = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, array)
|
||||||
self.cursor.execute(statement,
|
self.cursor.execute(statement,
|
||||||
integerValue = 8,
|
integerValue = 8,
|
||||||
array = arrayVar)
|
array = arrayVar)
|
||||||
|
@ -97,7 +97,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
def testBindUnicodeArrayBySizes(self):
|
def testBindUnicodeArrayBySizes(self):
|
||||||
"test binding in a unicode array (with setinputsizes)"
|
"test binding in a unicode array (with setinputsizes)"
|
||||||
returnValue = self.cursor.var(cx_Oracle.NUMBER)
|
returnValue = self.cursor.var(cx_Oracle.NUMBER)
|
||||||
self.cursor.setinputsizes(array = [cx_Oracle.NCHAR, 10])
|
self.cursor.setinputsizes(array = [cx_Oracle.DB_TYPE_NVARCHAR, 10])
|
||||||
array = [r[1] for r in self.rawData]
|
array = [r[1] for r in self.rawData]
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
|
@ -112,7 +112,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
def testBindUnicodeArrayByVar(self):
|
def testBindUnicodeArrayByVar(self):
|
||||||
"test binding in a unicode array (with arrayvar)"
|
"test binding in a unicode array (with arrayvar)"
|
||||||
returnValue = self.cursor.var(cx_Oracle.NUMBER)
|
returnValue = self.cursor.var(cx_Oracle.NUMBER)
|
||||||
array = self.cursor.arrayvar(cx_Oracle.NCHAR, 10, 20)
|
array = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, 10, 20)
|
||||||
array.setvalue(0, [r[1] for r in self.rawData])
|
array.setvalue(0, [r[1] for r in self.rawData])
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
|
@ -126,7 +126,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutUnicodeArrayByVar(self):
|
def testBindInOutUnicodeArrayByVar(self):
|
||||||
"test binding in/out a unicode array (with arrayvar)"
|
"test binding in/out a unicode array (with arrayvar)"
|
||||||
array = self.cursor.arrayvar(cx_Oracle.NCHAR, 10, 100)
|
array = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, 10, 100)
|
||||||
originalData = [r[1] for r in self.rawData]
|
originalData = [r[1] for r in self.rawData]
|
||||||
format = u"Converted element \u3042 # %d originally had length %d"
|
format = u"Converted element \u3042 # %d originally had length %d"
|
||||||
expectedData = [format % (i, len(originalData[i - 1])) \
|
expectedData = [format % (i, len(originalData[i - 1])) \
|
||||||
|
@ -142,7 +142,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindOutUnicodeArrayByVar(self):
|
def testBindOutUnicodeArrayByVar(self):
|
||||||
"test binding out a unicode array (with arrayvar)"
|
"test binding out a unicode array (with arrayvar)"
|
||||||
array = self.cursor.arrayvar(cx_Oracle.NCHAR, 6, 100)
|
array = self.cursor.arrayvar(cx_Oracle.DB_TYPE_NVARCHAR, 6, 100)
|
||||||
format = u"Test out element \u3042 # %d"
|
format = u"Test out element \u3042 # %d"
|
||||||
expectedData = [format % i for i in range(1, 7)]
|
expectedData = [format % i for i in range(1, 7)]
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
|
@ -163,7 +163,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindOutSetInputSizesByType(self):
|
def testBindOutSetInputSizesByType(self):
|
||||||
"test binding out with set input sizes defined (by type)"
|
"test binding out with set input sizes defined (by type)"
|
||||||
vars = self.cursor.setinputsizes(value = cx_Oracle.NCHAR)
|
vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
self.cursor.execute(r"""
|
self.cursor.execute(r"""
|
||||||
begin
|
begin
|
||||||
:value := unistr('TSI \3042');
|
:value := unistr('TSI \3042');
|
||||||
|
@ -172,7 +172,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutSetInputSizesByType(self):
|
def testBindInOutSetInputSizesByType(self):
|
||||||
"test binding in/out with set input sizes defined (by type)"
|
"test binding in/out with set input sizes defined (by type)"
|
||||||
vars = self.cursor.setinputsizes(value = cx_Oracle.NCHAR)
|
vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
self.cursor.execute(r"""
|
self.cursor.execute(r"""
|
||||||
begin
|
begin
|
||||||
:value := :value || unistr(' TSI \3042');
|
:value := :value || unistr(' TSI \3042');
|
||||||
|
@ -183,7 +183,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindOutVar(self):
|
def testBindOutVar(self):
|
||||||
"test binding out with cursor.var() method"
|
"test binding out with cursor.var() method"
|
||||||
var = self.cursor.var(cx_Oracle.NCHAR)
|
var = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
self.cursor.execute(r"""
|
self.cursor.execute(r"""
|
||||||
begin
|
begin
|
||||||
:value := unistr('TSI (VAR) \3042');
|
:value := unistr('TSI (VAR) \3042');
|
||||||
|
@ -193,7 +193,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutVarDirectSet(self):
|
def testBindInOutVarDirectSet(self):
|
||||||
"test binding in/out with cursor.var() method"
|
"test binding in/out with cursor.var() method"
|
||||||
var = self.cursor.var(cx_Oracle.NCHAR)
|
var = self.cursor.var(cx_Oracle.DB_TYPE_NVARCHAR)
|
||||||
var.setvalue(0, u"InVal \u3041")
|
var.setvalue(0, u"InVal \u3041")
|
||||||
self.cursor.execute(r"""
|
self.cursor.execute(r"""
|
||||||
begin
|
begin
|
||||||
|
@ -206,11 +206,13 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate"
|
"test cursor description is accurate"
|
||||||
self.cursor.execute("select * from TestUnicodes")
|
self.cursor.execute("select * from TestUnicodes")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('UNICODECOL', cx_Oracle.NCHAR, 20, 80, None, None, 0),
|
('UNICODECOL', cx_Oracle.DB_TYPE_NVARCHAR, 20, 80, None,
|
||||||
('FIXEDUNICODECOL', cx_Oracle.FIXED_NCHAR, 40, 160, None,
|
|
||||||
None, 0),
|
None, 0),
|
||||||
('NULLABLECOL', cx_Oracle.NCHAR, 50, 200, None, None, 1) ])
|
('FIXEDUNICODECOL', cx_Oracle.DB_TYPE_NCHAR, 40, 160, None,
|
||||||
|
None, 0),
|
||||||
|
('NULLABLECOL', cx_Oracle.DB_TYPE_NVARCHAR, 50, 200, None,
|
||||||
|
None, 1) ])
|
||||||
|
|
||||||
def testFetchAll(self):
|
def testFetchAll(self):
|
||||||
"test that fetching all of the data returns the correct results"
|
"test that fetching all of the data returns the correct results"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
#
|
#
|
||||||
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -19,7 +19,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def outputTypeHandlerNativeInt(self, cursor, name, defaultType, size,
|
def outputTypeHandlerNativeInt(self, cursor, name, defaultType, size,
|
||||||
precision, scale):
|
precision, scale):
|
||||||
return cursor.var(cx_Oracle.NATIVE_INT, arraysize=cursor.arraysize)
|
return cursor.var(cx_Oracle.DB_TYPE_BINARY_INTEGER,
|
||||||
|
arraysize=cursor.arraysize)
|
||||||
|
|
||||||
def outputTypeHandlerDecimal(self, cursor, name, defaultType, size,
|
def outputTypeHandlerDecimal(self, cursor, name, defaultType, size,
|
||||||
precision, scale):
|
precision, scale):
|
||||||
|
@ -272,12 +273,15 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate"
|
"test cursor description is accurate"
|
||||||
self.cursor.execute("select * from TestNumbers")
|
self.cursor.execute("select * from TestNumbers")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('LONGINTCOL', cx_Oracle.NUMBER, 17, None, 16, 0, 0),
|
('LONGINTCOL', cx_Oracle.DB_TYPE_NUMBER, 17, None, 16, 0, 0),
|
||||||
('NUMBERCOL', cx_Oracle.NUMBER, 13, None, 9, 2, 0),
|
('NUMBERCOL', cx_Oracle.DB_TYPE_NUMBER, 13, None, 9, 2, 0),
|
||||||
('FLOATCOL', cx_Oracle.NUMBER, 127, None, 126, -127, 0),
|
('FLOATCOL', cx_Oracle.DB_TYPE_NUMBER, 127, None, 126, -127,
|
||||||
('UNCONSTRAINEDCOL', cx_Oracle.NUMBER, 127, None, 0, -127, 0),
|
0),
|
||||||
('NULLABLECOL', cx_Oracle.NUMBER, 39, None, 38, 0, 1) ])
|
('UNCONSTRAINEDCOL', cx_Oracle.DB_TYPE_NUMBER, 127, None, 0,
|
||||||
|
-127, 0),
|
||||||
|
('NULLABLECOL', cx_Oracle.DB_TYPE_NUMBER, 39, None, 38, 0,
|
||||||
|
1) ])
|
||||||
|
|
||||||
def testFetchAll(self):
|
def testFetchAll(self):
|
||||||
"test that fetching all of the data returns the correct results"
|
"test that fetching all of the data returns the correct results"
|
||||||
|
@ -369,23 +373,28 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
def testStringFormat(self):
|
def testStringFormat(self):
|
||||||
"test that string format is returned properly"
|
"test that string format is returned properly"
|
||||||
var = self.cursor.var(cx_Oracle.NUMBER)
|
var = self.cursor.var(cx_Oracle.NUMBER)
|
||||||
self.assertEqual(str(var), "<cx_Oracle.NUMBER with value None>")
|
self.assertEqual(str(var),
|
||||||
|
"<cx_Oracle.Var of type DB_TYPE_NUMBER with value None>")
|
||||||
var.setvalue(0, 4)
|
var.setvalue(0, 4)
|
||||||
self.assertEqual(str(var), "<cx_Oracle.NUMBER with value 4.0>")
|
self.assertEqual(str(var),
|
||||||
|
"<cx_Oracle.Var of type DB_TYPE_NUMBER with value 4.0>")
|
||||||
|
|
||||||
def testBindNativeFloat(self):
|
def testBindNativeFloat(self):
|
||||||
"test that binding native float is possible"
|
"test that binding native float is possible"
|
||||||
self.cursor.setinputsizes(cx_Oracle.NATIVE_FLOAT)
|
self.cursor.setinputsizes(cx_Oracle.DB_TYPE_BINARY_DOUBLE)
|
||||||
self.cursor.execute("select :1 from dual", (5,))
|
self.cursor.execute("select :1 from dual", (5,))
|
||||||
self.assertEqual(type(self.cursor.bindvars[0]), cx_Oracle.NATIVE_FLOAT)
|
self.assertEqual(self.cursor.bindvars[0].type,
|
||||||
|
cx_Oracle.DB_TYPE_BINARY_DOUBLE)
|
||||||
value, = self.cursor.fetchone()
|
value, = self.cursor.fetchone()
|
||||||
self.assertEqual(value, 5)
|
self.assertEqual(value, 5)
|
||||||
self.cursor.execute("select :1 from dual", (1.5,))
|
self.cursor.execute("select :1 from dual", (1.5,))
|
||||||
self.assertEqual(type(self.cursor.bindvars[0]), cx_Oracle.NATIVE_FLOAT)
|
self.assertEqual(self.cursor.bindvars[0].type,
|
||||||
|
cx_Oracle.DB_TYPE_BINARY_DOUBLE)
|
||||||
value, = self.cursor.fetchone()
|
value, = self.cursor.fetchone()
|
||||||
self.assertEqual(value, 1.5)
|
self.assertEqual(value, 1.5)
|
||||||
self.cursor.execute("select :1 from dual", (decimal.Decimal("NaN"),))
|
self.cursor.execute("select :1 from dual", (decimal.Decimal("NaN"),))
|
||||||
self.assertEqual(type(self.cursor.bindvars[0]), cx_Oracle.NATIVE_FLOAT)
|
self.assertEqual(self.cursor.bindvars[0].type,
|
||||||
|
cx_Oracle.DB_TYPE_BINARY_DOUBLE)
|
||||||
value, = self.cursor.fetchone()
|
value, = self.cursor.fetchone()
|
||||||
self.assertEqual(str(value), str(float("NaN")))
|
self.assertEqual(str(value), str(float("NaN")))
|
||||||
|
|
||||||
|
@ -399,4 +408,3 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
TestEnv.RunTestCases()
|
TestEnv.RunTestCases()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
#
|
#
|
||||||
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -50,7 +50,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindNullIn(self):
|
def testBindNullIn(self):
|
||||||
"test binding a null value (IN)"
|
"test binding a null value (IN)"
|
||||||
var = self.cursor.var(cx_Oracle.OBJECT, typename = "UDT_OBJECT")
|
var = self.cursor.var(cx_Oracle.DB_TYPE_OBJECT,
|
||||||
|
typename = "UDT_OBJECT")
|
||||||
result = self.cursor.callfunc("pkg_TestBindObject.GetStringRep", str,
|
result = self.cursor.callfunc("pkg_TestBindObject.GetStringRep", str,
|
||||||
(var,))
|
(var,))
|
||||||
self.assertEqual(result, "null")
|
self.assertEqual(result, "null")
|
||||||
|
@ -122,9 +123,11 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
from TestObjects
|
from TestObjects
|
||||||
order by IntCol""")
|
order by IntCol""")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('OBJECTCOL', cx_Oracle.OBJECT, None, None, None, None, 1),
|
('OBJECTCOL', cx_Oracle.DB_TYPE_OBJECT, None, None, None,
|
||||||
('ARRAYCOL', cx_Oracle.OBJECT, None, None, None, None, 1) ])
|
None, 1),
|
||||||
|
('ARRAYCOL', cx_Oracle.DB_TYPE_OBJECT, None, None, None,
|
||||||
|
None, 1) ])
|
||||||
self.__TestData(1, (1, 'First row', 'First ', 'N First Row',
|
self.__TestData(1, (1, 'First row', 'First ', 'N First Row',
|
||||||
'N First ', b'Raw Data 1', 2, 5, 12.125, 0.5, 12.5, 25.25,
|
'N First ', b'Raw Data 1', 2, 5, 12.125, 0.5, 12.5, 25.25,
|
||||||
50.125, cx_Oracle.Timestamp(2007, 3, 6, 0, 0, 0),
|
50.125, cx_Oracle.Timestamp(2007, 3, 6, 0, 0, 0),
|
||||||
|
@ -154,6 +157,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
self.assertEqual(typeObj.iscollection, False)
|
self.assertEqual(typeObj.iscollection, False)
|
||||||
self.assertEqual(typeObj.schema, self.connection.username.upper())
|
self.assertEqual(typeObj.schema, self.connection.username.upper())
|
||||||
self.assertEqual(typeObj.name, "UDT_OBJECT")
|
self.assertEqual(typeObj.name, "UDT_OBJECT")
|
||||||
|
subObjectValueType = self.connection.gettype("UDT_SUBOBJECT")
|
||||||
|
subObjectArrayType = self.connection.gettype("UDT_OBJECTARRAY")
|
||||||
expectedAttributeNames = ["NUMBERVALUE", "STRINGVALUE",
|
expectedAttributeNames = ["NUMBERVALUE", "STRINGVALUE",
|
||||||
"FIXEDCHARVALUE", "NSTRINGVALUE", "NFIXEDCHARVALUE",
|
"FIXEDCHARVALUE", "NSTRINGVALUE", "NFIXEDCHARVALUE",
|
||||||
"RAWVALUE", "INTVALUE", "SMALLINTVALUE", "REALVALUE",
|
"RAWVALUE", "INTVALUE", "SMALLINTVALUE", "REALVALUE",
|
||||||
|
@ -163,9 +168,23 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"NCLOBVALUE", "BLOBVALUE", "SUBOBJECTVALUE", "SUBOBJECTARRAY"]
|
"NCLOBVALUE", "BLOBVALUE", "SUBOBJECTVALUE", "SUBOBJECTARRAY"]
|
||||||
actualAttributeNames = [a.name for a in typeObj.attributes]
|
actualAttributeNames = [a.name for a in typeObj.attributes]
|
||||||
self.assertEqual(actualAttributeNames, expectedAttributeNames)
|
self.assertEqual(actualAttributeNames, expectedAttributeNames)
|
||||||
typeObj = self.connection.gettype("UDT_OBJECTARRAY")
|
expectedAttributeTypes = [cx_Oracle.DB_TYPE_NUMBER,
|
||||||
self.assertEqual(typeObj.iscollection, True)
|
cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.DB_TYPE_CHAR,
|
||||||
self.assertEqual(typeObj.attributes, [])
|
cx_Oracle.DB_TYPE_NVARCHAR, cx_Oracle.DB_TYPE_NCHAR,
|
||||||
|
cx_Oracle.DB_TYPE_RAW, cx_Oracle.DB_TYPE_NUMBER,
|
||||||
|
cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.DB_TYPE_NUMBER,
|
||||||
|
cx_Oracle.DB_TYPE_NUMBER, cx_Oracle.DB_TYPE_NUMBER,
|
||||||
|
cx_Oracle.DB_TYPE_BINARY_FLOAT,
|
||||||
|
cx_Oracle.DB_TYPE_BINARY_DOUBLE,
|
||||||
|
cx_Oracle.DB_TYPE_DATE, cx_Oracle.DB_TYPE_TIMESTAMP,
|
||||||
|
cx_Oracle.DB_TYPE_TIMESTAMP_TZ,
|
||||||
|
cx_Oracle.DB_TYPE_TIMESTAMP_LTZ, cx_Oracle.DB_TYPE_CLOB,
|
||||||
|
cx_Oracle.DB_TYPE_NCLOB, cx_Oracle.DB_TYPE_BLOB,
|
||||||
|
subObjectValueType, subObjectArrayType]
|
||||||
|
actualAttributeTypes = [a.type for a in typeObj.attributes]
|
||||||
|
self.assertEqual(actualAttributeTypes, expectedAttributeTypes)
|
||||||
|
self.assertEqual(subObjectArrayType.iscollection, True)
|
||||||
|
self.assertEqual(subObjectArrayType.attributes, [])
|
||||||
|
|
||||||
def testObjectType(self):
|
def testObjectType(self):
|
||||||
"test object type data"
|
"test object type data"
|
||||||
|
@ -316,7 +335,8 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test setting value of object variable to wrong object type"
|
"test setting value of object variable to wrong object type"
|
||||||
wrongObjType = self.connection.gettype("UDT_OBJECTARRAY")
|
wrongObjType = self.connection.gettype("UDT_OBJECTARRAY")
|
||||||
wrongObj = wrongObjType.newobject()
|
wrongObj = wrongObjType.newobject()
|
||||||
var = self.cursor.var(cx_Oracle.OBJECT, typename = "UDT_OBJECT")
|
var = self.cursor.var(cx_Oracle.DB_TYPE_OBJECT,
|
||||||
|
typename = "UDT_OBJECT")
|
||||||
self.assertRaises(cx_Oracle.DatabaseError, var.setvalue, 0, wrongObj)
|
self.assertRaises(cx_Oracle.DatabaseError, var.setvalue, 0, wrongObj)
|
||||||
|
|
||||||
def testStringFormat(self):
|
def testStringFormat(self):
|
||||||
|
|
|
@ -272,7 +272,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindLongString(self):
|
def testBindLongString(self):
|
||||||
"test that binding a long string succeeds"
|
"test that binding a long string succeeds"
|
||||||
self.cursor.setinputsizes(bigString = cx_Oracle.LONG_STRING)
|
self.cursor.setinputsizes(bigString = cx_Oracle.DB_TYPE_LONG)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
declare
|
declare
|
||||||
t_Temp varchar2(20000);
|
t_Temp varchar2(20000);
|
||||||
|
@ -295,15 +295,15 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate"
|
"test cursor description is accurate"
|
||||||
self.cursor.execute("select * from TestStrings")
|
self.cursor.execute("select * from TestStrings")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('STRINGCOL', cx_Oracle.STRING, 20,
|
('STRINGCOL', cx_Oracle.DB_TYPE_VARCHAR, 20,
|
||||||
20 * TestEnv.GetCharSetRatio(), None,
|
20 * TestEnv.GetCharSetRatio(), None,
|
||||||
None, 0),
|
None, 0),
|
||||||
('RAWCOL', cx_Oracle.BINARY, 30, 30, None, None, 0),
|
('RAWCOL', cx_Oracle.DB_TYPE_RAW, 30, 30, None, None, 0),
|
||||||
('FIXEDCHARCOL', cx_Oracle.FIXED_CHAR, 40,
|
('FIXEDCHARCOL', cx_Oracle.DB_TYPE_CHAR, 40,
|
||||||
40 * TestEnv.GetCharSetRatio(),
|
40 * TestEnv.GetCharSetRatio(),
|
||||||
None, None, 0),
|
None, None, 0),
|
||||||
('NULLABLECOL', cx_Oracle.STRING, 50,
|
('NULLABLECOL', cx_Oracle.DB_TYPE_VARCHAR, 50,
|
||||||
50 * TestEnv.GetCharSetRatio(), None,
|
50 * TestEnv.GetCharSetRatio(), None,
|
||||||
None, 1) ])
|
None, 1) ])
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindTimestamp(self):
|
def testBindTimestamp(self):
|
||||||
"test binding in a timestamp"
|
"test binding in a timestamp"
|
||||||
self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
|
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
select * from TestTimestamps
|
select * from TestTimestamps
|
||||||
where TimestampCol = :value""",
|
where TimestampCol = :value""",
|
||||||
|
@ -54,7 +54,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindNull(self):
|
def testBindNull(self):
|
||||||
"test binding in a null"
|
"test binding in a null"
|
||||||
self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
|
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
select * from TestTimestamps
|
select * from TestTimestamps
|
||||||
where TimestampCol = :value""",
|
where TimestampCol = :value""",
|
||||||
|
@ -63,7 +63,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindOutSetInputSizes(self):
|
def testBindOutSetInputSizes(self):
|
||||||
"test binding out with set input sizes defined"
|
"test binding out with set input sizes defined"
|
||||||
vars = self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
|
vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
:value := to_timestamp('20021209', 'YYYYMMDD');
|
:value := to_timestamp('20021209', 'YYYYMMDD');
|
||||||
|
@ -73,7 +73,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutSetInputSizes(self):
|
def testBindInOutSetInputSizes(self):
|
||||||
"test binding in/out with set input sizes defined"
|
"test binding in/out with set input sizes defined"
|
||||||
vars = self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
|
vars = self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
:value := :value + 5.25;
|
:value := :value + 5.25;
|
||||||
|
@ -84,7 +84,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindOutVar(self):
|
def testBindOutVar(self):
|
||||||
"test binding out with cursor.var() method"
|
"test binding out with cursor.var() method"
|
||||||
var = self.cursor.var(cx_Oracle.TIMESTAMP)
|
var = self.cursor.var(cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
:value := to_date('20021231 12:31:00',
|
:value := to_date('20021231 12:31:00',
|
||||||
|
@ -96,7 +96,7 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
|
|
||||||
def testBindInOutVarDirectSet(self):
|
def testBindInOutVarDirectSet(self):
|
||||||
"test binding in/out with cursor.var() method"
|
"test binding in/out with cursor.var() method"
|
||||||
var = self.cursor.var(cx_Oracle.TIMESTAMP)
|
var = self.cursor.var(cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||||
var.setvalue(0, cx_Oracle.Timestamp(2002, 12, 9, 6, 0, 0))
|
var.setvalue(0, cx_Oracle.Timestamp(2002, 12, 9, 6, 0, 0))
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
begin
|
begin
|
||||||
|
@ -110,9 +110,11 @@ class TestCase(TestEnv.BaseTestCase):
|
||||||
"test cursor description is accurate"
|
"test cursor description is accurate"
|
||||||
self.cursor.execute("select * from TestTimestamps")
|
self.cursor.execute("select * from TestTimestamps")
|
||||||
self.assertEqual(self.cursor.description,
|
self.assertEqual(self.cursor.description,
|
||||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||||
('TIMESTAMPCOL', cx_Oracle.TIMESTAMP, 23, None, 0, 6, 0),
|
('TIMESTAMPCOL', cx_Oracle.DB_TYPE_TIMESTAMP, 23, None, 0, 6,
|
||||||
('NULLABLECOL', cx_Oracle.TIMESTAMP, 23, None, 0, 6, 1) ])
|
0),
|
||||||
|
('NULLABLECOL', cx_Oracle.DB_TYPE_TIMESTAMP, 23, None, 0, 6,
|
||||||
|
1) ])
|
||||||
|
|
||||||
def testFetchAll(self):
|
def testFetchAll(self):
|
||||||
"test that fetching all of the data returns the correct results"
|
"test that fetching all of the data returns the correct results"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||||
#
|
#
|
||||||
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
# Portions Copyright 2007-2015, Anthony Tuininga. All rights reserved.
|
||||||
#
|
#
|
||||||
|
@ -36,6 +36,7 @@ moduleNames = [
|
||||||
"Cursor",
|
"Cursor",
|
||||||
"CursorVar",
|
"CursorVar",
|
||||||
"DateTimeVar",
|
"DateTimeVar",
|
||||||
|
"DbTypes",
|
||||||
"DMLReturning",
|
"DMLReturning",
|
||||||
"Error",
|
"Error",
|
||||||
"IntervalVar",
|
"IntervalVar",
|
||||||
|
|
Loading…
Reference in New Issue