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
|
||||
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)
|
||||
|
@ -554,10 +555,34 @@ Cursor Object
|
|||
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 variable. This should be one of the types defined at the module level
|
||||
(such as :data:`cx_Oracle.STRING`) or a Python type that cx_Oracle knows
|
||||
how to process (such as str) or an object type returned from the method
|
||||
:meth:`Connection.gettype()`.
|
||||
the variable. This should be one of the
|
||||
:ref:`database type constants <dbtypes>`, :ref:`DB API constants <types>`,
|
||||
an object type returned from the method :meth:`Connection.gettype()` or one
|
||||
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
|
||||
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.
|
||||
|
||||
The encodingErrors parameter specifies what should happen when decoding
|
||||
byte strings fetched from the database into strings (Python 3) or unicode
|
||||
objects (Python 2). It should be one of the values noted in the builtin
|
||||
byte strings fetched from the database into strings. It should be one of
|
||||
the values noted in the builtin
|
||||
`decode <https://docs.python.org/3/library/stdtypes.html#bytes.decode>`__
|
||||
function.
|
||||
|
||||
|
|
|
@ -79,6 +79,14 @@ See :ref:`lobdata` for more information about using LOBs.
|
|||
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])
|
||||
|
||||
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
|
||||
=====
|
||||
DB API Types
|
||||
------------
|
||||
|
||||
.. data:: BINARY
|
||||
|
||||
This type object is used to describe columns in a database that contain
|
||||
binary data. In Oracle this is RAW columns.
|
||||
|
||||
|
||||
.. data:: BFILE
|
||||
|
||||
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.
|
||||
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
|
||||
type, the database type :data:`DB_TYPE_RAW` will be used.
|
||||
|
||||
|
||||
.. data:: DATETIME
|
||||
|
||||
This type object is used to describe columns in a database that are dates.
|
||||
|
||||
|
||||
.. data:: FIXED_CHAR
|
||||
|
||||
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.
|
||||
The database types :data:`DB_TYPE_DATE`, :data:`DB_TYPE_TIMESTAMP`,
|
||||
:data:`DB_TYPE_TIMESTAMP_LTZ` and :data:`DB_TYPE_TIMESTAMP_TZ` will all
|
||||
compare equal to this value. If a variable is created with this
|
||||
type, the database type :data:`DB_TYPE_DATE` will be used.
|
||||
|
||||
|
||||
.. data:: NUMBER
|
||||
|
||||
This type object is used to describe columns in a database that are
|
||||
numbers.
|
||||
|
||||
|
||||
.. data:: OBJECT
|
||||
|
||||
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.
|
||||
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
|
||||
is created with this type, the database type :data:`DB_TYPE_NUMBER` will be
|
||||
used.
|
||||
|
||||
|
||||
.. 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
|
||||
|
||||
This type object is used to describe columns in a database that are strings
|
||||
(in Oracle this is VARCHAR2 columns).
|
||||
This type object is used to describe columns in a database that are
|
||||
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
|
||||
|
||||
This type object is used to describe columns in a database that are
|
||||
timestamps.
|
||||
A synonym for :data:`DB_TYPE_TIMESTAMP`.
|
||||
|
||||
.. 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:
|
||||
|
|
|
@ -19,8 +19,8 @@ Object Type Objects
|
|||
|
||||
.. attribute:: ObjectType.attributes
|
||||
|
||||
This read-only attribute returns a list of the attributes that make up the
|
||||
object type. Each attribute has a name attribute on it.
|
||||
This read-only attribute returns a list of the :ref:`attributes
|
||||
<objectattr>` that make up the object type.
|
||||
|
||||
|
||||
.. attribute:: ObjectType.iscollection
|
||||
|
@ -34,6 +34,17 @@ Object Type Objects
|
|||
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])
|
||||
|
||||
Return a new Oracle object of the given type. This object can then be
|
||||
|
@ -151,3 +162,29 @@ Object Objects
|
|||
.. method:: Object.trim(num)
|
||||
|
||||
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
|
||||
|
||||
This read-only attribute returns the type of the variable for those
|
||||
variables that bind Oracle objects (it is not present for any other type of
|
||||
variable).
|
||||
This read-only attribute returns the type of the variable. 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>`.
|
||||
|
||||
.. versionchanged:: 8.0
|
||||
Database type constants are now used when the variable is not used for
|
||||
binding Oracle objects.
|
||||
|
||||
|
||||
.. 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
|
||||
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
|
||||
and 3.8.
|
||||
against Oracle Client 19c, 18c, 12c, and 11.2, and Python 3.5, 3.6, 3.7 and
|
||||
3.8.
|
||||
|
||||
**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
|
||||
|
|
|
@ -9,9 +9,48 @@ Version 8.0 (TBD)
|
|||
-----------------
|
||||
|
||||
#) 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),
|
||||
as requested
|
||||
(`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)
|
||||
|
|
|
@ -214,9 +214,10 @@ LOB Bind Variables
|
|||
==================
|
||||
|
||||
Database CLOBs, NCLOBS, BLOBs and BFILEs can be bound with types
|
||||
:attr:`cx_Oracle.CLOB`, :attr:`cx_Oracle.NCLOB`, :attr:`cx_Oracle.BLOB`
|
||||
and :attr:`cx_Oracle.BFILE` respectively. LOBs fetched from the database or
|
||||
created with :meth:`Connection.createlob()` can also be bound.
|
||||
:attr:`cx_Oracle.DB_TYPE_CLOB`, :attr:`cx_Oracle.DB_TYPE_NCLOB`,
|
||||
:attr:`cx_Oracle.DB_TYPE_BLOB` and :attr:`cx_Oracle.DB_TYPE_BFILE`
|
||||
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
|
||||
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')
|
||||
(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()`:
|
||||
|
||||
.. 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:
|
||||
print(row)
|
||||
|
||||
|
@ -659,7 +660,7 @@ objects seamlessly:
|
|||
|
||||
def InputTypeHandler(cursor, value, numElements):
|
||||
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)
|
||||
|
||||
|
||||
|
|
|
@ -637,6 +637,25 @@ Upgrading from Older Versions
|
|||
Review the :ref:`release notes <releasenotes>` for deprecations and modify any
|
||||
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:
|
||||
|
||||
- When using Oracle Instant Client, you should not set ``ORACLE_HOME``.
|
||||
|
@ -684,9 +703,8 @@ If installation fails:
|
|||
or venv?
|
||||
|
||||
- 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
|
||||
venv module (builtin to Python 3.x) or virtualenv module (Python 2.x)
|
||||
instead.
|
||||
to Python but is sometimes removed by the OS. Use the venv module
|
||||
(builtin to Python 3.x) or virtualenv module instead.
|
||||
|
||||
- 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
|
||||
|
@ -723,6 +741,5 @@ If using cx_Oracle fails:
|
|||
supported on Windows 7. Similar steps shown above for ``DPI-1047`` may
|
||||
help.
|
||||
|
||||
- If you have both Python 2 and 3 installed, make sure you are
|
||||
using the correct python and pip (or python3 and pip3)
|
||||
executables.
|
||||
- If you have multiple versions of Python installed, make sure you are
|
||||
using the correct python and pip (or python3 and pip3) executables.
|
||||
|
|
|
@ -47,7 +47,7 @@ Features
|
|||
The cx_Oracle feature highlights are:
|
||||
|
||||
* 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
|
||||
* Extensive Oracle data type support, including large objects (CLOB and
|
||||
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):
|
||||
|
||||
* 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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
|
@ -76,10 +77,10 @@ to be used as shown in this example:
|
|||
.. code-block:: python
|
||||
|
||||
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
|
||||
if defaultType == cx_Oracle.CLOB:
|
||||
return cursor.var(cx_Oracle.LONG_STRING, arraysize=cursor.arraysize)
|
||||
if defaultType == cx_Oracle.BLOB:
|
||||
return cursor.var(cx_Oracle.LONG_BINARY, arraysize=cursor.arraysize)
|
||||
if defaultType == cx_Oracle.DB_TYPE_CLOB:
|
||||
return cursor.var(cx_Oracle.DB_TYPE_LONG, arraysize=cursor.arraysize)
|
||||
if defaultType == cx_Oracle.DB_TYPE_BLOB:
|
||||
return cursor.var(cx_Oracle.DB_TYPE_LONG_RAW, arraysize=cursor.arraysize)
|
||||
|
||||
idVal = 1
|
||||
textData = "The quick brown fox jumps over the lazy dog"
|
||||
|
@ -161,7 +162,7 @@ in the following code:
|
|||
.. code-block:: python
|
||||
|
||||
idVal = 9
|
||||
lobVar = cursor.var(cx_Oracle.BLOB)
|
||||
lobVar = cursor.var(cx_Oracle.DB_TYPE_BLOB)
|
||||
cursor.execute("""
|
||||
insert into lob_tbl (id, b)
|
||||
values (:1, empty_blob())
|
||||
|
|
|
@ -225,8 +225,8 @@ can be obtained using :attr:`Cursor.description`:
|
|||
|
||||
This could result in metadata like::
|
||||
|
||||
('ID', <class 'cx_Oracle.NUMBER'>, 39, None, 38, 0, 0)
|
||||
('NAME', <class 'cx_Oracle.STRING'>, 20, 20, None, None, 1)
|
||||
('ID', <class 'cx_Oracle.DB_TYPE_NUMBER'>, 39, None, 38, 0, 0)
|
||||
('NAME', <class 'cx_Oracle.DB_TYPE_VARCHAR'>, 20, 20, None, None, 1)
|
||||
|
||||
|
||||
.. _defaultfetchtypes:
|
||||
|
@ -236,8 +236,8 @@ Fetch Data Types
|
|||
|
||||
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
|
||||
:ref:`query metadata <querymetadata>`. The last column gives the type of Python
|
||||
object that is returned by default. Python types can be changed with
|
||||
:ref:`query metadata <querymetadata>`. The last column gives the type of
|
||||
Python object that is returned by default. Python types can be changed with
|
||||
:ref:`Output Type Handlers <outputtypehandlers>`.
|
||||
|
||||
.. list-table::
|
||||
|
@ -246,91 +246,87 @@ object that is returned by default. Python types can be changed with
|
|||
:align: left
|
||||
|
||||
* - Oracle Database Type
|
||||
- cx_Oracle Type
|
||||
- cx_Oracle Database Type
|
||||
- Default Python type
|
||||
* - BFILE
|
||||
- :attr:`cx_Oracle.BFILE`
|
||||
- :attr:`cx_Oracle.DB_TYPE_BFILE`
|
||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||
* - BINARY_DOUBLE
|
||||
- :attr:`cx_Oracle.NATIVE_FLOAT`
|
||||
- :attr:`cx_Oracle.DB_TYPE_BINARY_DOUBLE`
|
||||
- float
|
||||
* - BINARY_FLOAT
|
||||
- :attr:`cx_Oracle.NATIVE_FLOAT`
|
||||
- :attr:`cx_Oracle.DB_TYPE_BINARY_FLOAT`
|
||||
- float
|
||||
* - BLOB
|
||||
- :attr:`cx_Oracle.BLOB`
|
||||
- :attr:`cx_Oracle.DB_TYPE_BLOB`
|
||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||
* - CHAR
|
||||
- :attr:`cx_Oracle.FIXED_CHAR`
|
||||
- :attr:`cx_Oracle.DB_TYPE_CHAR`
|
||||
- str
|
||||
* - CLOB
|
||||
- :attr:`cx_Oracle.CLOB`
|
||||
- :attr:`cx_Oracle.DB_TYPE_CLOB`
|
||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||
* - CURSOR
|
||||
- :attr:`cx_Oracle.CURSOR`
|
||||
- :attr:`cx_Oracle.DB_TYPE_CURSOR`
|
||||
- :ref:`cx_Oracle.Cursor <cursorobj>`
|
||||
* - DATE
|
||||
- :attr:`cx_Oracle.DATETIME`
|
||||
- :attr:`cx_Oracle.DB_TYPE_DATE`
|
||||
- datetime.datetime
|
||||
* - INTERVAL DAY TO SECOND
|
||||
- :attr:`cx_Oracle.INTERVAL`
|
||||
- :attr:`cx_Oracle.DB_TYPE_INTERVAL_DS`
|
||||
- datetime.timedelta
|
||||
* - LONG
|
||||
- :attr:`cx_Oracle.LONG_STRING`
|
||||
- :attr:`cx_Oracle.DB_TYPE_LONG`
|
||||
- str
|
||||
* - LONG RAW
|
||||
- :attr:`cx_Oracle.LONG_BINARY`
|
||||
- bytes [4]_
|
||||
- :attr:`cx_Oracle.DB_TYPE_LONG_RAW`
|
||||
- bytes
|
||||
* - NCHAR
|
||||
- :attr:`cx_Oracle.FIXED_NCHAR`
|
||||
- str [1]_
|
||||
- :attr:`cx_Oracle.DB_TYPE_NCHAR`
|
||||
- str
|
||||
* - NCLOB
|
||||
- :attr:`cx_Oracle.NCLOB`
|
||||
- :attr:`cx_Oracle.DB_TYPE_NCLOB`
|
||||
- :ref:`cx_Oracle.LOB <lobobj>`
|
||||
* - NUMBER
|
||||
- :attr:`cx_Oracle.NUMBER`
|
||||
- float or int [2]_
|
||||
- :attr:`cx_Oracle.DB_TYPE_NUMBER`
|
||||
- float or int [1]_
|
||||
* - NVARCHAR2
|
||||
- :attr:`cx_Oracle.NCHAR`
|
||||
- str [1]_
|
||||
* - OBJECT [5]_
|
||||
- :attr:`cx_Oracle.OBJECT`
|
||||
- :attr:`cx_Oracle.DB_TYPE_NVARCHAR`
|
||||
- str
|
||||
* - OBJECT [3]_
|
||||
- :attr:`cx_Oracle.DB_TYPE_OBJECT`
|
||||
- :ref:`cx_Oracle.Object <objecttype>`
|
||||
* - RAW
|
||||
- :attr:`cx_Oracle.BINARY`
|
||||
- bytes [4]_
|
||||
- :attr:`cx_Oracle.DB_TYPE_RAW`
|
||||
- bytes
|
||||
* - ROWID
|
||||
- :attr:`cx_Oracle.ROWID`
|
||||
- :attr:`cx_Oracle.DB_TYPE_ROWID`
|
||||
- str
|
||||
* - TIMESTAMP
|
||||
- :attr:`cx_Oracle.TIMESTAMP`
|
||||
- :attr:`cx_Oracle.DB_TYPE_TIMESTAMP`
|
||||
- datetime.datetime
|
||||
* - TIMESTAMP WITH LOCAL TIME ZONE
|
||||
- :attr:`cx_Oracle.TIMESTAMP`
|
||||
- datetime.datetime [3]_
|
||||
- :attr:`cx_Oracle.DB_TYPE_TIMESTAMP_LTZ`
|
||||
- datetime.datetime [2]_
|
||||
* - TIMESTAMP WITH TIME ZONE
|
||||
- :attr:`cx_Oracle.TIMESTAMP`
|
||||
- datetime.datetime [3]_
|
||||
- :attr:`cx_Oracle.DB_TYPE_TIMESTAMP_TZ`
|
||||
- datetime.datetime [2]_
|
||||
* - UROWID
|
||||
- :attr:`cx_Oracle.ROWID`
|
||||
- :attr:`cx_Oracle.DB_TYPE_ROWID`
|
||||
- str
|
||||
* - VARCHAR2
|
||||
- :attr:`cx_Oracle.STRING`
|
||||
- :attr:`cx_Oracle.DB_TYPE_VARCHAR`
|
||||
- str
|
||||
|
||||
.. [1] In Python 2 these are fetched as unicode objects.
|
||||
.. [2] If the precision and scale obtained from query column metadata indicate
|
||||
.. [1] If the precision and scale obtained from query column metadata indicate
|
||||
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
|
||||
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
|
||||
the value is returned as a float. Note that in Python 2, values returned
|
||||
as integers will be int or long depending on the size of the integer.
|
||||
.. [3] The timestamps returned are naive timestamps without any time zone
|
||||
the value is returned as a float.
|
||||
.. [2] The timestamps returned are naive timestamps without any time zone
|
||||
information present.
|
||||
.. [4] In Python 2 these are identical to str objects since Python 2 doesn't
|
||||
have a native bytes object.
|
||||
.. [5] These include all user-defined types such as VARRAY, NESTED TABLE, etc.
|
||||
.. [3] These include all user-defined types such as VARRAY, NESTED TABLE, etc.
|
||||
|
||||
|
||||
.. _outputtypehandlers:
|
||||
|
@ -399,7 +395,7 @@ Using Python decimal objects, however, there is no loss of precision:
|
|||
import decimal
|
||||
|
||||
def NumberToDecimal(cursor, name, defaultType, size, precision, scale):
|
||||
if defaultType == cx_Oracle.NUMBER:
|
||||
if defaultType == cx_Oracle.DB_TYPE_NUMBER:
|
||||
return cursor.var(decimal.Decimal, arraysize=cursor.arraysize)
|
||||
|
||||
cur = connection.cursor()
|
||||
|
@ -432,7 +428,7 @@ For example, to make queries return empty strings instead of NULLs:
|
|||
return value
|
||||
|
||||
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)
|
||||
|
||||
connection.outputtypehandler = OutputTypeHandler
|
||||
|
|
|
@ -38,7 +38,7 @@ as shown:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
clob = connection.createlob(cx_Oracle.CLOB)
|
||||
clob = connection.createlob(cx_Oracle.DB_TYPE_CLOB)
|
||||
clob.write(xmlData)
|
||||
cursor.execute("insert into xml_table values (:id, sys.xmltype(:xml))",
|
||||
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;
|
||||
cxoTransformNum transformNum;
|
||||
|
||||
transformNum = cxoTransform_getNumFromValue(value, 0);
|
||||
transformNum = cxoTransform_getNumFromPythonValue(value, 0);
|
||||
if (cxoTransform_fromPython(transformNum, &nativeTypeNum, value,
|
||||
&column->value, buffer, params->encoding, params->nencoding, NULL,
|
||||
0) < 0)
|
||||
|
@ -1011,7 +1011,7 @@ static PyObject *cxoConnection_getType(cxoConnection *conn, PyObject *nameObj)
|
|||
static PyObject *cxoConnection_createLob(cxoConnection *conn,
|
||||
PyObject *lobType)
|
||||
{
|
||||
dpiOracleTypeNum oracleTypeNum;
|
||||
cxoDbType *dbType;
|
||||
dpiLob *handle;
|
||||
PyObject *lob;
|
||||
|
||||
|
@ -1020,23 +1020,20 @@ static PyObject *cxoConnection_createLob(cxoConnection *conn,
|
|||
return NULL;
|
||||
|
||||
// verify the LOB type
|
||||
if (lobType == (PyObject*) &cxoPyTypeClobVar)
|
||||
oracleTypeNum = DPI_ORACLE_TYPE_CLOB;
|
||||
else if (lobType == (PyObject*) &cxoPyTypeBlobVar)
|
||||
oracleTypeNum = DPI_ORACLE_TYPE_BLOB;
|
||||
else if (lobType == (PyObject*) &cxoPyTypeNclobVar)
|
||||
oracleTypeNum = DPI_ORACLE_TYPE_NCLOB;
|
||||
else {
|
||||
if (lobType != (PyObject*) cxoDbTypeClob &&
|
||||
lobType != (PyObject*) cxoDbTypeBlob &&
|
||||
lobType != (PyObject*) cxoDbTypeNclob) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"parameter should be one of cx_Oracle.CLOB, cx_Oracle.BLOB "
|
||||
"or cx_Oracle.NCLOB");
|
||||
"parameter should be one of cx_Oracle.DB_TYPE_CLOB, "
|
||||
"cx_Oracle.DB_TYPE_BLOB or cx_Oracle.DB_TYPE_NCLOB");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 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();
|
||||
lob = cxoLob_new(conn, oracleTypeNum, handle);
|
||||
lob = cxoLob_new(conn, dbType, handle);
|
||||
if (!lob)
|
||||
dpiLob_release(handle);
|
||||
return lob;
|
||||
|
|
|
@ -329,10 +329,12 @@ static int cxoCursor_fetchRow(cxoCursor *cursor, int *found,
|
|||
static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
||||
{
|
||||
PyObject *outputTypeHandler, *result;
|
||||
cxoTransformNum transformNum;
|
||||
cxoObjectType *objectType;
|
||||
cxoVarType *varType;
|
||||
dpiQueryInfo queryInfo;
|
||||
uint32_t pos, size;
|
||||
cxoDbType *dbType;
|
||||
char message[120];
|
||||
cxoVar *var;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// determine the default type
|
||||
varType = cxoVarType_fromDataTypeInfo(&queryInfo.typeInfo);
|
||||
if (!varType)
|
||||
// determine the default types to use
|
||||
transformNum =
|
||||
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;
|
||||
|
||||
// see if an output type handler should be used
|
||||
|
@ -390,7 +400,7 @@ static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
|||
if (outputTypeHandler) {
|
||||
result = PyObject_CallFunction(outputTypeHandler, "Os#Oiii",
|
||||
cursor, queryInfo.name, (Py_ssize_t) queryInfo.nameLength,
|
||||
varType->pythonType, size, queryInfo.typeInfo.precision,
|
||||
dbType, size, queryInfo.typeInfo.precision,
|
||||
queryInfo.typeInfo.scale);
|
||||
if (!result) {
|
||||
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 (!var) {
|
||||
var = cxoVar_new(cursor, cursor->fetchArraySize, varType, size, 0,
|
||||
objectType);
|
||||
var = cxoVar_new(cursor, cursor->fetchArraySize, transformNum,
|
||||
size, 0, objectType);
|
||||
if (!var) {
|
||||
Py_XDECREF(objectType);
|
||||
return -1;
|
||||
|
@ -444,16 +454,16 @@ static int cxoCursor_performDefine(cxoCursor *cursor, uint32_t numQueryColumns)
|
|||
//-----------------------------------------------------------------------------
|
||||
static PyObject *cxoCursor_itemDescription(cxoCursor *cursor, uint32_t pos)
|
||||
{
|
||||
cxoVarType *varType;
|
||||
int displaySize, index;
|
||||
dpiQueryInfo queryInfo;
|
||||
PyObject *tuple, *temp;
|
||||
cxoDbType *dbType;
|
||||
|
||||
// get information about the column position
|
||||
if (dpiStmt_getQueryInfo(cursor->handle, pos, &queryInfo) < 0)
|
||||
return NULL;
|
||||
varType = cxoVarType_fromDataTypeInfo(&queryInfo.typeInfo);
|
||||
if (!varType)
|
||||
dbType = cxoDbType_fromDataTypeInfo(&queryInfo.typeInfo);
|
||||
if (!dbType)
|
||||
return NULL;
|
||||
|
||||
// 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,
|
||||
queryInfo.nameLength, cursor->connection->encodingInfo.encoding,
|
||||
NULL));
|
||||
Py_INCREF(varType->pythonType);
|
||||
PyTuple_SET_ITEM(tuple, 1, (PyObject*) varType->pythonType);
|
||||
Py_INCREF(dbType);
|
||||
PyTuple_SET_ITEM(tuple, 1, (PyObject*) dbType);
|
||||
if (displaySize)
|
||||
PyTuple_SET_ITEM(tuple, 2, PyLong_FromLong(displaySize));
|
||||
else {
|
||||
|
@ -673,7 +683,7 @@ static int cxoCursor_setBindVariableHelper(cxoCursor *cursor,
|
|||
// can happen if all of the values in a previous invocation of
|
||||
// executemany() were None) and there is now a value; in this case,
|
||||
// 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) {
|
||||
origVar = NULL;
|
||||
varToSet = NULL;
|
||||
|
@ -682,8 +692,9 @@ static int cxoCursor_setBindVariableHelper(cxoCursor *cursor,
|
|||
// variable this is only necessary for executemany() since
|
||||
// execute() always passes a value of 1 for the number of elements
|
||||
} else if (numElements > origVar->allocatedElements) {
|
||||
*newVar = cxoVar_new(cursor, numElements, origVar->type,
|
||||
origVar->size, origVar->isArray, origVar->objectType);
|
||||
*newVar = cxoVar_new(cursor, numElements,
|
||||
origVar->transformNum, origVar->size, origVar->isArray,
|
||||
origVar->objectType);
|
||||
if (!*newVar)
|
||||
return -1;
|
||||
varToSet = *newVar;
|
||||
|
@ -1826,9 +1837,9 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
|||
"inconverter", "outconverter", "typename", "encodingErrors",
|
||||
NULL };
|
||||
PyObject *inConverter, *outConverter, *typeNameObj;
|
||||
cxoTransformNum transformNum;
|
||||
const char *encodingErrors;
|
||||
cxoObjectType *objType;
|
||||
cxoVarType *varType;
|
||||
int size, arraySize;
|
||||
PyObject *type;
|
||||
cxoVar *var;
|
||||
|
@ -1844,12 +1855,9 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
|||
return NULL;
|
||||
|
||||
// determine the type of variable
|
||||
varType = cxoVarType_fromPythonType(type, &objType);
|
||||
if (!varType)
|
||||
if (cxoTransform_getNumFromType(type, &transformNum, &objType) < 0)
|
||||
return NULL;
|
||||
Py_XINCREF(objType);
|
||||
if (size == 0)
|
||||
size = varType->size;
|
||||
if (typeNameObj && typeNameObj != Py_None && !objType) {
|
||||
objType = cxoObjectType_newByName(cursor->connection, typeNameObj);
|
||||
if (!objType)
|
||||
|
@ -1857,7 +1865,7 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
|||
}
|
||||
|
||||
// create the variable
|
||||
var = cxoVar_new(cursor, arraySize, varType, size, 0, objType);
|
||||
var = cxoVar_new(cursor, arraySize, transformNum, size, 0, objType);
|
||||
Py_XDECREF(objType);
|
||||
if (!var)
|
||||
return NULL;
|
||||
|
@ -1886,23 +1894,20 @@ static PyObject *cxoCursor_var(cxoCursor *cursor, PyObject *args,
|
|||
//-----------------------------------------------------------------------------
|
||||
static PyObject *cxoCursor_arrayVar(cxoCursor *cursor, PyObject *args)
|
||||
{
|
||||
cxoTransformNum transformNum;
|
||||
uint32_t size, numElements;
|
||||
PyObject *type, *value;
|
||||
cxoObjectType *objType;
|
||||
cxoVarType *varType;
|
||||
cxoVar *var;
|
||||
|
||||
// parse arguments
|
||||
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;
|
||||
|
||||
// determine the type of variable
|
||||
varType = cxoVarType_fromPythonType(type, &objType);
|
||||
if (!varType)
|
||||
// determine the transform to use for the variable
|
||||
if (cxoTransform_getNumFromType(type, &transformNum, &objType) < 0)
|
||||
return NULL;
|
||||
if (size == 0)
|
||||
size = varType->size;
|
||||
|
||||
// determine the number of elements to create
|
||||
if (PyList_Check(value))
|
||||
|
@ -1918,7 +1923,7 @@ static PyObject *cxoCursor_arrayVar(cxoCursor *cursor, PyObject *args)
|
|||
}
|
||||
|
||||
// create the variable
|
||||
var = cxoVar_new(cursor, numElements, varType, size, 1, objType);
|
||||
var = cxoVar_new(cursor, numElements, transformNum, size, 1, objType);
|
||||
if (!var)
|
||||
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[] = {
|
||||
{ "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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -63,7 +72,8 @@ PyTypeObject cxoPyTypeLob = {
|
|||
.tp_dealloc = (destructor) cxoLob_free,
|
||||
.tp_str = (reprfunc) cxoLob_str,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||
.tp_methods = cxoLobMethods
|
||||
.tp_methods = cxoLobMethods,
|
||||
.tp_members = cxoMembers
|
||||
};
|
||||
|
||||
|
||||
|
@ -71,7 +81,7 @@ PyTypeObject cxoPyTypeLob = {
|
|||
// cxoLob_new()
|
||||
// Create a new LOB.
|
||||
//-----------------------------------------------------------------------------
|
||||
PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
|
||||
PyObject *cxoLob_new(cxoConnection *connection, cxoDbType *dbType,
|
||||
dpiLob *handle)
|
||||
{
|
||||
cxoLob *lob;
|
||||
|
@ -80,9 +90,10 @@ PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
|
|||
if (!lob)
|
||||
return NULL;
|
||||
lob->handle = handle;
|
||||
lob->oracleTypeNum = oracleTypeNum;
|
||||
Py_INCREF(connection);
|
||||
lob->connection = connection;
|
||||
Py_INCREF(dbType);
|
||||
lob->dbType = dbType;
|
||||
return (PyObject*) lob;
|
||||
}
|
||||
|
||||
|
@ -97,6 +108,7 @@ static void cxoLob_free(cxoLob *lob)
|
|||
dpiLob_release(lob->handle);
|
||||
lob->handle = NULL;
|
||||
}
|
||||
Py_CLEAR(lob->dbType);
|
||||
Py_CLEAR(lob->connection);
|
||||
Py_TYPE(lob)->tp_free((PyObject*) lob);
|
||||
}
|
||||
|
@ -141,13 +153,15 @@ static PyObject *cxoLob_internalRead(cxoLob *lob, uint64_t offset,
|
|||
}
|
||||
|
||||
// return the result
|
||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
|
||||
if (lob->dbType == cxoDbTypeNclob) {
|
||||
result = PyUnicode_Decode(buffer, (Py_ssize_t) bufferSize,
|
||||
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,
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
@ -164,7 +178,7 @@ static int cxoLob_internalWrite(cxoLob *lob, PyObject *dataObj,
|
|||
cxoBuffer buffer;
|
||||
int status;
|
||||
|
||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB)
|
||||
if (lob->dbType == cxoDbTypeNclob)
|
||||
encoding = lob->connection->encodingInfo.nencoding;
|
||||
else encoding = lob->connection->encodingInfo.encoding;
|
||||
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) \
|
||||
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 CXO_ADD_TYPE_OBJECT(name, type) \
|
||||
Py_INCREF(type); \
|
||||
|
@ -48,10 +63,98 @@ PyObject *cxoProgrammingErrorException = NULL;
|
|||
PyObject *cxoNotSupportedErrorException = NULL;
|
||||
PyObject *cxoJsonDumpFunction = 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;
|
||||
dpiContext *cxoDpiContext = NULL;
|
||||
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()
|
||||
// Create an exception and set it in the provided dictionary.
|
||||
|
@ -242,50 +345,32 @@ static PyObject *cxoModule_initialize(void)
|
|||
return NULL;
|
||||
|
||||
// prepare the types for use by the module
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBfileVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBinaryVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBlobVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeBooleanVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeClobVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeApiType);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeConnection);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeCursor);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeCursorVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeDateTimeVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeDbType);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeDeqOptions);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeEnqOptions);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeError);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeFixedCharVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeFixedNcharVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeFuture);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeIntervalVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeLob);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeLongBinaryVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeLongStringVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMsgProps);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMessage);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageQuery);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeMessageRow);
|
||||
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(&cxoPyTypeObject);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeObjectType);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeObjectVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeQueue);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeRowidVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSessionPool);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaCollection);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDatabase);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDoc);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaDocCursor);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSodaOperation);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeStringVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeSubscr);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeTimestampVar);
|
||||
CXO_MAKE_TYPE_READY(&cxoPyTypeVar);
|
||||
|
||||
// initialize module and retrieve the dictionary
|
||||
module = PyModule_Create(&cxoModuleDef);
|
||||
|
@ -325,50 +410,129 @@ static PyObject *cxoModule_initialize(void)
|
|||
return NULL;
|
||||
|
||||
// set up the types that are available
|
||||
CXO_ADD_TYPE_OBJECT("ApiType", &cxoPyTypeApiType)
|
||||
CXO_ADD_TYPE_OBJECT("Binary", &PyBytes_Type)
|
||||
CXO_ADD_TYPE_OBJECT("Connection", &cxoPyTypeConnection)
|
||||
CXO_ADD_TYPE_OBJECT("Cursor", &cxoPyTypeCursor)
|
||||
CXO_ADD_TYPE_OBJECT("Timestamp", cxoPyTypeDateTime)
|
||||
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("LOB", &cxoPyTypeLob)
|
||||
CXO_ADD_TYPE_OBJECT("MessageProperties", &cxoPyTypeMsgProps)
|
||||
CXO_ADD_TYPE_OBJECT("Object", &cxoPyTypeObject)
|
||||
CXO_ADD_TYPE_OBJECT("ObjectType", &cxoPyTypeObjectType)
|
||||
CXO_ADD_TYPE_OBJECT("EnqOptions", &cxoPyTypeEnqOptions)
|
||||
CXO_ADD_TYPE_OBJECT("DeqOptions", &cxoPyTypeDeqOptions)
|
||||
CXO_ADD_TYPE_OBJECT("MessageProperties", &cxoPyTypeMsgProps)
|
||||
CXO_ADD_TYPE_OBJECT("SessionPool", &cxoPyTypeSessionPool)
|
||||
CXO_ADD_TYPE_OBJECT("SodaCollection", &cxoPyTypeSodaCollection)
|
||||
CXO_ADD_TYPE_OBJECT("SodaDatabase", &cxoPyTypeSodaDatabase)
|
||||
CXO_ADD_TYPE_OBJECT("SodaDoc", &cxoPyTypeSodaDoc)
|
||||
CXO_ADD_TYPE_OBJECT("SodaDocCursor", &cxoPyTypeSodaDocCursor)
|
||||
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
|
||||
CXO_ADD_TYPE_OBJECT("connect", &cxoPyTypeConnection)
|
||||
|
||||
// create the basic data types for setting input sizes
|
||||
CXO_ADD_TYPE_OBJECT("BINARY", &cxoPyTypeBinaryVar)
|
||||
CXO_ADD_TYPE_OBJECT("BFILE", &cxoPyTypeBfileVar)
|
||||
CXO_ADD_TYPE_OBJECT("BLOB", &cxoPyTypeBlobVar)
|
||||
CXO_ADD_TYPE_OBJECT("CLOB", &cxoPyTypeClobVar)
|
||||
CXO_ADD_TYPE_OBJECT("CURSOR", &cxoPyTypeCursorVar)
|
||||
CXO_ADD_TYPE_OBJECT("OBJECT", &cxoPyTypeObjectVar)
|
||||
CXO_ADD_TYPE_OBJECT("DATETIME", &cxoPyTypeDateTimeVar)
|
||||
CXO_ADD_TYPE_OBJECT("FIXED_CHAR", &cxoPyTypeFixedCharVar)
|
||||
CXO_ADD_TYPE_OBJECT("FIXED_NCHAR", &cxoPyTypeFixedNcharVar)
|
||||
CXO_ADD_TYPE_OBJECT("NCHAR", &cxoPyTypeNcharVar)
|
||||
CXO_ADD_TYPE_OBJECT("INTERVAL", &cxoPyTypeIntervalVar)
|
||||
CXO_ADD_TYPE_OBJECT("LOB", &cxoPyTypeLob)
|
||||
CXO_ADD_TYPE_OBJECT("LONG_BINARY", &cxoPyTypeLongBinaryVar)
|
||||
CXO_ADD_TYPE_OBJECT("LONG_STRING", &cxoPyTypeLongStringVar)
|
||||
CXO_ADD_TYPE_OBJECT("NCLOB", &cxoPyTypeNclobVar)
|
||||
CXO_ADD_TYPE_OBJECT("NUMBER", &cxoPyTypeNumberVar)
|
||||
CXO_ADD_TYPE_OBJECT("ROWID", &cxoPyTypeRowidVar)
|
||||
CXO_ADD_TYPE_OBJECT("STRING", &cxoPyTypeStringVar)
|
||||
CXO_ADD_TYPE_OBJECT("TIMESTAMP", &cxoPyTypeTimestampVar)
|
||||
CXO_ADD_TYPE_OBJECT("NATIVE_INT", &cxoPyTypeNativeIntVar)
|
||||
CXO_ADD_TYPE_OBJECT("NATIVE_FLOAT", &cxoPyTypeNativeFloatVar)
|
||||
CXO_ADD_TYPE_OBJECT("BOOLEAN", &cxoPyTypeBooleanVar)
|
||||
// create the database types (preferred names)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BFILE, "DB_TYPE_BFILE",
|
||||
CXO_TRANSFORM_BFILE, &cxoDbTypeBfile)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_DOUBLE, "DB_TYPE_BINARY_DOUBLE",
|
||||
CXO_TRANSFORM_NATIVE_DOUBLE, &cxoDbTypeBinaryDouble)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_FLOAT, "DB_TYPE_BINARY_FLOAT",
|
||||
CXO_TRANSFORM_NATIVE_FLOAT, &cxoDbTypeBinaryFloat)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_NATIVE_INT, "DB_TYPE_BINARY_INTEGER",
|
||||
CXO_TRANSFORM_NATIVE_INT, &cxoDbTypeBinaryInteger)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BLOB, "DB_TYPE_BLOB",
|
||||
CXO_TRANSFORM_BLOB, &cxoDbTypeBlob)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_BOOLEAN, "DB_TYPE_BOOLEAN",
|
||||
CXO_TRANSFORM_BOOLEAN, &cxoDbTypeBoolean)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_CHAR, "DB_TYPE_CHAR",
|
||||
CXO_TRANSFORM_FIXED_CHAR, &cxoDbTypeChar)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_CLOB, "DB_TYPE_CLOB",
|
||||
CXO_TRANSFORM_CLOB, &cxoDbTypeClob)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_STMT, "DB_TYPE_CURSOR",
|
||||
CXO_TRANSFORM_CURSOR, &cxoDbTypeCursor)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_DATE, "DB_TYPE_DATE",
|
||||
CXO_TRANSFORM_DATETIME, &cxoDbTypeDate)
|
||||
CXO_ADD_DB_TYPE(DPI_ORACLE_TYPE_INTERVAL_DS, "DB_TYPE_INTERVAL_DS",
|
||||
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
|
||||
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).
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -29,12 +29,14 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Forward Declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef struct cxoApiType cxoApiType;
|
||||
typedef struct cxoBuffer cxoBuffer;
|
||||
typedef struct cxoError cxoError;
|
||||
typedef struct cxoConnection cxoConnection;
|
||||
typedef struct cxoCursor cxoCursor;
|
||||
typedef struct cxoDbType cxoDbType;
|
||||
typedef struct cxoDeqOptions cxoDeqOptions;
|
||||
typedef struct cxoEnqOptions cxoEnqOptions;
|
||||
typedef struct cxoError cxoError;
|
||||
typedef struct cxoFuture cxoFuture;
|
||||
typedef struct cxoLob cxoLob;
|
||||
typedef struct cxoMessage cxoMessage;
|
||||
|
@ -54,7 +56,6 @@ typedef struct cxoSodaDocCursor cxoSodaDocCursor;
|
|||
typedef struct cxoSodaOperation cxoSodaOperation;
|
||||
typedef struct cxoSubscr cxoSubscr;
|
||||
typedef struct cxoVar cxoVar;
|
||||
typedef struct cxoVarType cxoVarType;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -74,55 +75,71 @@ extern PyObject *cxoProgrammingErrorException;
|
|||
extern PyObject *cxoNotSupportedErrorException;
|
||||
|
||||
// type objects
|
||||
extern PyTypeObject cxoPyTypeBfileVar;
|
||||
extern PyTypeObject cxoPyTypeBinaryVar;
|
||||
extern PyTypeObject cxoPyTypeBlobVar;
|
||||
extern PyTypeObject cxoPyTypeBooleanVar;
|
||||
extern PyTypeObject cxoPyTypeClobVar;
|
||||
extern PyTypeObject cxoPyTypeApiType;
|
||||
extern PyTypeObject cxoPyTypeConnection;
|
||||
extern PyTypeObject cxoPyTypeCursor;
|
||||
extern PyTypeObject cxoPyTypeCursorVar;
|
||||
extern PyTypeObject cxoPyTypeDateTimeVar;
|
||||
extern PyTypeObject cxoPyTypeDbType;
|
||||
extern PyTypeObject cxoPyTypeDeqOptions;
|
||||
extern PyTypeObject cxoPyTypeEnqOptions;
|
||||
extern PyTypeObject cxoPyTypeError;
|
||||
extern PyTypeObject cxoPyTypeFixedCharVar;
|
||||
extern PyTypeObject cxoPyTypeFixedNcharVar;
|
||||
extern PyTypeObject cxoPyTypeFuture;
|
||||
extern PyTypeObject cxoPyTypeIntervalVar;
|
||||
extern PyTypeObject cxoPyTypeLob;
|
||||
extern PyTypeObject cxoPyTypeLongBinaryVar;
|
||||
extern PyTypeObject cxoPyTypeLongStringVar;
|
||||
extern PyTypeObject cxoPyTypeMsgProps;
|
||||
extern PyTypeObject cxoPyTypeMessage;
|
||||
extern PyTypeObject cxoPyTypeMessageQuery;
|
||||
extern PyTypeObject cxoPyTypeMessageRow;
|
||||
extern PyTypeObject cxoPyTypeMessageTable;
|
||||
extern PyTypeObject cxoPyTypeNativeFloatVar;
|
||||
extern PyTypeObject cxoPyTypeNativeIntVar;
|
||||
extern PyTypeObject cxoPyTypeNcharVar;
|
||||
extern PyTypeObject cxoPyTypeNclobVar;
|
||||
extern PyTypeObject cxoPyTypeNumberVar;
|
||||
extern PyTypeObject cxoPyTypeObject;
|
||||
extern PyTypeObject cxoPyTypeObjectAttr;
|
||||
extern PyTypeObject cxoPyTypeObjectType;
|
||||
extern PyTypeObject cxoPyTypeObjectVar;
|
||||
extern PyTypeObject cxoPyTypeQueue;
|
||||
extern PyTypeObject cxoPyTypeRowidVar;
|
||||
extern PyTypeObject cxoPyTypeSessionPool;
|
||||
extern PyTypeObject cxoPyTypeSodaCollection;
|
||||
extern PyTypeObject cxoPyTypeSodaDatabase;
|
||||
extern PyTypeObject cxoPyTypeSodaDoc;
|
||||
extern PyTypeObject cxoPyTypeSodaDocCursor;
|
||||
extern PyTypeObject cxoPyTypeSodaOperation;
|
||||
extern PyTypeObject cxoPyTypeStringVar;
|
||||
extern PyTypeObject cxoPyTypeSubscr;
|
||||
extern PyTypeObject cxoPyTypeTimestampVar;
|
||||
extern PyTypeObject cxoPyTypeVar;
|
||||
|
||||
// datetime types
|
||||
extern PyTypeObject *cxoPyTypeDate;
|
||||
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
|
||||
extern PyObject *cxoJsonDumpFunction;
|
||||
extern PyObject *cxoJsonLoadFunction;
|
||||
|
@ -166,6 +183,7 @@ typedef enum {
|
|||
CXO_TRANSFORM_TIMEDELTA,
|
||||
CXO_TRANSFORM_TIMESTAMP,
|
||||
CXO_TRANSFORM_TIMESTAMP_LTZ,
|
||||
CXO_TRANSFORM_TIMESTAMP_TZ,
|
||||
CXO_TRANSFORM_UNSUPPORTED
|
||||
} cxoTransformNum;
|
||||
|
||||
|
@ -173,6 +191,13 @@ typedef enum {
|
|||
//-----------------------------------------------------------------------------
|
||||
// Structures
|
||||
//-----------------------------------------------------------------------------
|
||||
struct cxoApiType {
|
||||
PyObject_HEAD
|
||||
const char *name;
|
||||
PyObject *dbTypes;
|
||||
cxoTransformNum defaultTransformNum;
|
||||
};
|
||||
|
||||
struct cxoBuffer {
|
||||
const char *ptr;
|
||||
uint32_t numCharacters;
|
||||
|
@ -228,6 +253,13 @@ struct cxoCursor {
|
|||
int isOpen;
|
||||
};
|
||||
|
||||
struct cxoDbType {
|
||||
PyObject_HEAD
|
||||
uint32_t num;
|
||||
const char *name;
|
||||
cxoTransformNum defaultTransformNum;
|
||||
};
|
||||
|
||||
struct cxoDeqOptions {
|
||||
PyObject_HEAD
|
||||
dpiDeqOptions *handle;
|
||||
|
@ -247,7 +279,7 @@ struct cxoFuture {
|
|||
struct cxoLob {
|
||||
PyObject_HEAD
|
||||
cxoConnection *connection;
|
||||
dpiOracleTypeNum oracleTypeNum;
|
||||
cxoDbType *dbType;
|
||||
dpiLob *handle;
|
||||
};
|
||||
|
||||
|
@ -303,7 +335,8 @@ struct cxoObjectAttr {
|
|||
dpiObjectAttr *handle;
|
||||
dpiOracleTypeNum oracleTypeNum;
|
||||
cxoTransformNum transformNum;
|
||||
cxoObjectType *type;
|
||||
cxoObjectType *objectType;
|
||||
cxoDbType *dbType;
|
||||
};
|
||||
|
||||
struct cxoObjectType {
|
||||
|
@ -316,7 +349,8 @@ struct cxoObjectType {
|
|||
cxoConnection *connection;
|
||||
dpiOracleTypeNum elementOracleTypeNum;
|
||||
cxoTransformNum elementTransformNum;
|
||||
PyObject *elementType;
|
||||
cxoObjectType *elementObjectType;
|
||||
cxoDbType *elementDbType;
|
||||
char isCollection;
|
||||
};
|
||||
|
||||
|
@ -418,13 +452,9 @@ struct cxoVar {
|
|||
int isArray;
|
||||
int isValueSet;
|
||||
int getReturnedData;
|
||||
cxoVarType *type;
|
||||
};
|
||||
|
||||
struct cxoVarType {
|
||||
cxoTransformNum transformNum;
|
||||
PyTypeObject *pythonType;
|
||||
uint32_t size;
|
||||
dpiNativeTypeNum nativeTypeNum;
|
||||
cxoDbType *dbType;
|
||||
};
|
||||
|
||||
|
||||
|
@ -441,6 +471,9 @@ int cxoCursor_performBind(cxoCursor *cursor);
|
|||
int cxoCursor_setBindVariables(cxoCursor *cursor, PyObject *parameters,
|
||||
unsigned numElements, unsigned arrayPos, int deferTypeAssignment);
|
||||
|
||||
cxoDbType *cxoDbType_fromDataTypeInfo(dpiDataTypeInfo *info);
|
||||
cxoDbType *cxoDbType_fromTransformNum(cxoTransformNum transformNum);
|
||||
|
||||
cxoDeqOptions *cxoDeqOptions_new(cxoConnection *connection,
|
||||
dpiDeqOptions *handle);
|
||||
|
||||
|
@ -454,7 +487,7 @@ int cxoError_raiseFromInfo(dpiErrorInfo *errorInfo);
|
|||
PyObject *cxoError_raiseFromString(PyObject *exceptionType,
|
||||
const char *message);
|
||||
|
||||
PyObject *cxoLob_new(cxoConnection *connection, dpiOracleTypeNum oracleTypeNum,
|
||||
PyObject *cxoLob_new(cxoConnection *connection, cxoDbType *dbType,
|
||||
dpiLob *handle);
|
||||
|
||||
cxoMsgProps *cxoMsgProps_new(cxoConnection*, dpiMsgProps *handle);
|
||||
|
@ -491,9 +524,15 @@ int cxoTransform_fromPython(cxoTransformNum transformNum,
|
|||
dpiNativeTypeNum *nativeTypeNum, PyObject *pyValue,
|
||||
dpiDataBuffer *dbValue, cxoBuffer *buffer, const char *encoding,
|
||||
const char *nencoding, cxoVar *var, uint32_t arrayPos);
|
||||
uint32_t cxoTransform_getDefaultSize(cxoTransformNum transformNum);
|
||||
cxoTransformNum cxoTransform_getNumFromDataTypeInfo(dpiDataTypeInfo *info);
|
||||
cxoTransformNum cxoTransform_getNumFromType(PyTypeObject *type);
|
||||
cxoTransformNum cxoTransform_getNumFromValue(PyObject *value, int plsql);
|
||||
cxoTransformNum cxoTransform_getNumFromPythonValue(PyObject *value,
|
||||
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,
|
||||
dpiOracleTypeNum *oracleTypeNum, dpiNativeTypeNum *nativeTypeNum);
|
||||
int cxoTransform_init(void);
|
||||
|
@ -512,20 +551,15 @@ int cxoUtils_processJsonArg(PyObject *arg, cxoBuffer *buffer);
|
|||
int cxoUtils_processSodaDocArg(cxoSodaDatabase *db, PyObject *arg,
|
||||
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_check(PyObject *object);
|
||||
PyObject *cxoVar_getSingleValue(cxoVar *var, dpiData *data, uint32_t arrayPos);
|
||||
PyObject *cxoVar_getValue(cxoVar *var, uint32_t arrayPos);
|
||||
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
|
||||
Py_ssize_t size, int isArray, cxoObjectType *objType);
|
||||
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements,
|
||||
cxoTransformNum transformNum, Py_ssize_t size, int isArray,
|
||||
cxoObjectType *objType);
|
||||
cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
||||
uint32_t numElements);
|
||||
cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
|
||||
Py_ssize_t numElements);
|
||||
int cxoVar_setValue(cxoVar *var, uint32_t arrayPos, PyObject *value);
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ static PyObject *cxoObject_getAttributeValue(cxoObject *obj,
|
|||
nativeTypeNum, &data) < 0)
|
||||
return cxoError_raiseAndReturnNull();
|
||||
return cxoObject_convertToPython(obj, attribute->transformNum, &data,
|
||||
attribute->type);
|
||||
attribute->objectType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -367,7 +367,7 @@ static PyObject *cxoObject_internalGetElementByIndex(cxoObject *obj,
|
|||
&data) < 0)
|
||||
return cxoError_raiseAndReturnNull();
|
||||
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 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 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef cxoCalcMembers[] = {
|
||||
{ "type", (getter) cxoObjectAttr_getType, 0, 0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declaration
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -35,7 +45,8 @@ PyTypeObject cxoPyTypeObjectAttr = {
|
|||
.tp_dealloc = (destructor) cxoObjectAttr_free,
|
||||
.tp_repr = (reprfunc) cxoObjectAttr_repr,
|
||||
.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)
|
||||
return cxoError_raiseAndReturnInt();
|
||||
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->name = PyUnicode_Decode(info.name, info.nameLength,
|
||||
connection->encodingInfo.encoding, NULL);
|
||||
if (!attr->name)
|
||||
return -1;
|
||||
if (info.typeInfo.objectType) {
|
||||
attr->type = cxoObjectType_new(connection,
|
||||
attr->objectType = cxoObjectType_new(connection,
|
||||
info.typeInfo.objectType);
|
||||
if (!attr->type)
|
||||
if (!attr->objectType)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -103,11 +118,29 @@ static void cxoObjectAttr_free(cxoObjectAttr *attr)
|
|||
attr->handle = NULL;
|
||||
}
|
||||
Py_CLEAR(attr->name);
|
||||
Py_CLEAR(attr->type);
|
||||
Py_CLEAR(attr->objectType);
|
||||
Py_CLEAR(attr->dbType);
|
||||
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()
|
||||
// Return a string representation of the object attribute.
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
static void cxoObjectType_free(cxoObjectType*);
|
||||
static PyObject *cxoObjectType_repr(cxoObjectType*);
|
||||
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,
|
||||
METH_VARARGS | METH_KEYWORDS },
|
||||
{ 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 },
|
||||
{ "name", T_OBJECT, offsetof(cxoObjectType, name), READONLY },
|
||||
{ "attributes", T_OBJECT, offsetof(cxoObjectType, attributes), READONLY },
|
||||
{ "elementType", T_OBJECT, offsetof(cxoObjectType, elementType),
|
||||
READONLY },
|
||||
{ "iscollection", T_BOOL, offsetof(cxoObjectType, isCollection),
|
||||
READONLY },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef cxoCalcMembers[] = {
|
||||
{ "element_type", (getter) cxoObjectType_getElementType, 0, 0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Python type declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -58,8 +67,10 @@ PyTypeObject cxoPyTypeObjectType = {
|
|||
.tp_repr = (reprfunc) cxoObjectType_repr,
|
||||
.tp_call = (ternaryfunc) cxoObjectType_newObject,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||
.tp_methods = cxoObjectTypeMethods,
|
||||
.tp_members = cxoObjectTypeMembers,
|
||||
.tp_methods = cxoMethods,
|
||||
.tp_members = cxoMembers,
|
||||
.tp_getset = cxoCalcMembers,
|
||||
.tp_richcompare = (richcmpfunc) cxoObjectType_richCompare
|
||||
};
|
||||
|
||||
|
||||
|
@ -89,14 +100,21 @@ static int cxoObjectType_initialize(cxoObjectType *objType,
|
|||
if (!objType->name)
|
||||
return -1;
|
||||
objType->isCollection = info.isCollection;
|
||||
objType->elementOracleTypeNum = info.elementTypeInfo.oracleTypeNum;
|
||||
objType->elementTransformNum =
|
||||
cxoTransform_getNumFromDataTypeInfo(&info.elementTypeInfo);
|
||||
if (info.elementTypeInfo.objectType) {
|
||||
objType->elementType = (PyObject*) cxoObjectType_new(connection,
|
||||
info.elementTypeInfo.objectType);
|
||||
if (!objType->elementType)
|
||||
if (info.isCollection) {
|
||||
objType->elementOracleTypeNum = info.elementTypeInfo.oracleTypeNum;
|
||||
objType->elementTransformNum =
|
||||
cxoTransform_getNumFromDataTypeInfo(&info.elementTypeInfo);
|
||||
objType->elementDbType =
|
||||
cxoDbType_fromTransformNum(objType->elementTransformNum);
|
||||
if (!objType->elementDbType)
|
||||
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
|
||||
|
@ -205,11 +223,34 @@ static void cxoObjectType_free(cxoObjectType *objType)
|
|||
Py_CLEAR(objType->name);
|
||||
Py_CLEAR(objType->attributes);
|
||||
Py_CLEAR(objType->attributesByName);
|
||||
Py_CLEAR(objType->elementType);
|
||||
Py_CLEAR(objType->elementObjectType);
|
||||
Py_CLEAR(objType->elementDbType);
|
||||
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()
|
||||
// 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()
|
||||
// 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)
|
||||
#endif
|
||||
|
||||
// forward declarations
|
||||
static Py_ssize_t cxoTransform_calculateSize(PyObject *value,
|
||||
cxoTransformNum transformNum);
|
||||
static cxoTransformNum cxoTransform_getNumFromPythonType(PyTypeObject *type);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -175,10 +181,39 @@ static const cxoTransform cxoAllTransforms[] = {
|
|||
CXO_TRANSFORM_TIMESTAMP_LTZ,
|
||||
DPI_ORACLE_TYPE_TIMESTAMP_LTZ,
|
||||
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()
|
||||
// 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_TIMESTAMP:
|
||||
case CXO_TRANSFORM_TIMESTAMP_LTZ:
|
||||
case CXO_TRANSFORM_TIMESTAMP_TZ:
|
||||
if (PyDateTime_Check(pyValue)) {
|
||||
memset(&dbValue->asTimestamp, 0, sizeof(dbValue->asTimestamp));
|
||||
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()
|
||||
// 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:
|
||||
return CXO_TRANSFORM_TIMESTAMP;
|
||||
case DPI_ORACLE_TYPE_TIMESTAMP_TZ:
|
||||
return CXO_TRANSFORM_TIMESTAMP_TZ;
|
||||
case DPI_ORACLE_TYPE_TIMESTAMP_LTZ:
|
||||
return CXO_TRANSFORM_TIMESTAMP_LTZ;
|
||||
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.
|
||||
//-----------------------------------------------------------------------------
|
||||
cxoTransformNum cxoTransform_getNumFromType(PyTypeObject *type)
|
||||
static cxoTransformNum cxoTransform_getNumFromPythonType(PyTypeObject *type)
|
||||
{
|
||||
if (type == &PyUnicode_Type)
|
||||
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)
|
||||
return CXO_TRANSFORM_BINARY;
|
||||
if (type == &cxoPyTypeBinaryVar)
|
||||
return CXO_TRANSFORM_BINARY;
|
||||
if (type == &PyFloat_Type)
|
||||
return CXO_TRANSFORM_FLOAT;
|
||||
if (type == &PyLong_Type)
|
||||
return CXO_TRANSFORM_INT;
|
||||
if (type == cxoPyTypeDecimal)
|
||||
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)
|
||||
return CXO_TRANSFORM_BOOLEAN;
|
||||
if (type == &cxoPyTypeBooleanVar)
|
||||
return CXO_TRANSFORM_BOOLEAN;
|
||||
if (type == PyDateTimeAPI->DateType)
|
||||
return CXO_TRANSFORM_DATE;
|
||||
if (type == PyDateTimeAPI->DateTimeType)
|
||||
return CXO_TRANSFORM_DATETIME;
|
||||
if (type == &cxoPyTypeDateTimeVar)
|
||||
return CXO_TRANSFORM_DATETIME;
|
||||
if (type == &cxoPyTypeTimestampVar)
|
||||
return CXO_TRANSFORM_TIMESTAMP;
|
||||
if (type == PyDateTimeAPI->DeltaType)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// cxoTransform_getNumFromValue()
|
||||
// Get the appropriate transformation to use for the specified Python object.
|
||||
// cxoTransform_getNumFromPythonValue()
|
||||
// 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;
|
||||
|
||||
|
@ -542,19 +566,144 @@ cxoTransformNum cxoTransform_getNumFromValue(PyObject *value, int plsql)
|
|||
return CXO_TRANSFORM_OBJECT;
|
||||
if (PyObject_TypeCheck(value, &cxoPyTypeLob)) {
|
||||
lob = (cxoLob*) value;
|
||||
if (lob->oracleTypeNum == DPI_ORACLE_TYPE_CLOB)
|
||||
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 lob->dbType->defaultTransformNum;
|
||||
}
|
||||
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()
|
||||
// Get type information for the specified transform. The transform number is
|
||||
|
@ -618,17 +767,16 @@ PyObject *cxoTransform_toPython(cxoTransformNum transformNum,
|
|||
cxoConnection *connection, cxoObjectType *objType,
|
||||
dpiDataBuffer *dbValue, const char *encodingErrors)
|
||||
{
|
||||
const cxoTransform *transform;
|
||||
PyObject *stringObj, *result;
|
||||
dpiIntervalDS *intervalDS;
|
||||
dpiTimestamp *timestamp;
|
||||
uint32_t rowidLength;
|
||||
cxoDbType *dbType;
|
||||
const char *rowid;
|
||||
cxoCursor *cursor;
|
||||
dpiBytes *bytes;
|
||||
int32_t seconds;
|
||||
|
||||
transform = &cxoAllTransforms[transformNum];
|
||||
switch (transformNum) {
|
||||
case CXO_TRANSFORM_BINARY:
|
||||
case CXO_TRANSFORM_LONG_BINARY:
|
||||
|
@ -638,8 +786,8 @@ PyObject *cxoTransform_toPython(cxoTransformNum transformNum,
|
|||
case CXO_TRANSFORM_BLOB:
|
||||
case CXO_TRANSFORM_CLOB:
|
||||
case CXO_TRANSFORM_NCLOB:
|
||||
return cxoLob_new(connection, transform->oracleTypeNum,
|
||||
dbValue->asLOB);
|
||||
dbType = cxoDbType_fromTransformNum(transformNum);
|
||||
return cxoLob_new(connection, dbType, dbValue->asLOB);
|
||||
case CXO_TRANSFORM_BOOLEAN:
|
||||
if (dbValue->asBoolean)
|
||||
Py_RETURN_TRUE;
|
||||
|
@ -660,6 +808,7 @@ PyObject *cxoTransform_toPython(cxoTransformNum transformNum,
|
|||
case CXO_TRANSFORM_DATETIME:
|
||||
case CXO_TRANSFORM_TIMESTAMP:
|
||||
case CXO_TRANSFORM_TIMESTAMP_LTZ:
|
||||
case CXO_TRANSFORM_TIMESTAMP_TZ:
|
||||
timestamp = &dbValue->asTimestamp;
|
||||
return PyDateTime_FromDateAndTime(timestamp->year,
|
||||
timestamp->month, timestamp->day, timestamp->hour,
|
||||
|
|
199
src/cxoVar.c
199
src/cxoVar.c
|
@ -15,7 +15,7 @@
|
|||
#include "cxoModule.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of common variable functions.
|
||||
// forward declaration of functions
|
||||
//-----------------------------------------------------------------------------
|
||||
static void cxoVar_free(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_externalGetActualElements(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 },
|
||||
{ "inconverter", T_OBJECT, offsetof(cxoVar, inConverter), 0 },
|
||||
{ "numElements", T_INT, offsetof(cxoVar, allocatedElements),
|
||||
READONLY },
|
||||
{ "outconverter", T_OBJECT, offsetof(cxoVar, outConverter), 0 },
|
||||
{ "size", T_INT, offsetof(cxoVar, size), READONLY },
|
||||
{ "type", T_OBJECT, offsetof(cxoVar, objectType), READONLY },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of calculated members for variables
|
||||
// declaration of calculated members
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyGetSetDef cxoVarCalcMembers[] = {
|
||||
static PyGetSetDef cxoCalcMembers[] = {
|
||||
{ "actualElements", (getter) cxoVar_externalGetActualElements, 0, 0, 0 },
|
||||
{ "type", (getter) cxoVar_getType, 0, 0, 0 },
|
||||
{ "values", (getter) cxoVar_externalGetValues, 0, 0, 0 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// declaration of methods for variables
|
||||
// declaration of methods
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyMethodDef cxoVarMethods[] = {
|
||||
{ "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 INTERNAL_NAME = { \
|
||||
PyVarObject_HEAD_INIT(NULL, 0) \
|
||||
.tp_name = "cx_Oracle." #EXTERNAL_NAME, \
|
||||
.tp_basicsize = sizeof(cxoVar), \
|
||||
.tp_dealloc = (destructor) cxoVar_free, \
|
||||
.tp_repr = (reprfunc) cxoVar_repr, \
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT, \
|
||||
.tp_methods = cxoVarMethods, \
|
||||
.tp_members = cxoVarMembers, \
|
||||
.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)
|
||||
PyTypeObject cxoPyTypeVar = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
.tp_name = "cx_Oracle.Var",
|
||||
.tp_basicsize = sizeof(cxoVar),
|
||||
.tp_dealloc = (destructor) cxoVar_free,
|
||||
.tp_repr = (reprfunc) cxoVar_repr,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||
.tp_methods = cxoVarMethods,
|
||||
.tp_members = cxoMembers,
|
||||
.tp_getset = cxoCalcMembers
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// cxoVar_new()
|
||||
// Allocate a new variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
|
||||
Py_ssize_t size, int isArray, cxoObjectType *objType)
|
||||
cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements,
|
||||
cxoTransformNum transformNum, Py_ssize_t size, int isArray,
|
||||
cxoObjectType *objType)
|
||||
{
|
||||
dpiObjectType *typeHandle = NULL;
|
||||
dpiOracleTypeNum oracleTypeNum;
|
||||
dpiNativeTypeNum nativeTypeNum;
|
||||
cxoVar *var;
|
||||
|
||||
// attempt to allocate the object
|
||||
var = (cxoVar*) type->pythonType->tp_alloc(type->pythonType, 0);
|
||||
var = (cxoVar*) cxoPyTypeVar.tp_alloc(&cxoPyTypeVar, 0);
|
||||
if (!var)
|
||||
return NULL;
|
||||
|
||||
|
@ -130,15 +108,25 @@ cxoVar *cxoVar_new(cxoCursor *cursor, Py_ssize_t numElements, cxoVarType *type,
|
|||
if (numElements == 0)
|
||||
numElements = 1;
|
||||
var->allocatedElements = (uint32_t) numElements;
|
||||
var->type = type;
|
||||
var->size = (size == 0) ? type->size : (uint32_t) size;
|
||||
var->transformNum = transformNum;
|
||||
var->size = (uint32_t) size;
|
||||
if (var->size == 0)
|
||||
var->size = cxoTransform_getDefaultSize(transformNum);
|
||||
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
|
||||
cxoTransform_getTypeInfo(type->transformNum, &oracleTypeNum,
|
||||
&nativeTypeNum);
|
||||
cxoTransform_getTypeInfo(transformNum, &oracleTypeNum,
|
||||
&var->nativeTypeNum);
|
||||
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) {
|
||||
cxoError_raiseAndReturnNull();
|
||||
Py_DECREF(var);
|
||||
|
@ -174,6 +162,7 @@ static void cxoVar_free(cxoVar *var)
|
|||
Py_CLEAR(var->inConverter);
|
||||
Py_CLEAR(var->outConverter);
|
||||
Py_CLEAR(var->objectType);
|
||||
Py_CLEAR(var->dbType);
|
||||
Py_TYPE(var)->tp_free((PyObject*) var);
|
||||
}
|
||||
|
||||
|
@ -184,29 +173,7 @@ static void cxoVar_free(cxoVar *var)
|
|||
//-----------------------------------------------------------------------------
|
||||
int cxoVar_check(PyObject *object)
|
||||
{
|
||||
PyTypeObject *objectType = Py_TYPE(object);
|
||||
|
||||
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);
|
||||
return (Py_TYPE(object) == &cxoPyTypeVar);
|
||||
}
|
||||
|
||||
|
||||
|
@ -219,7 +186,7 @@ cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
|
|||
{
|
||||
PyObject *result, *inputTypeHandler = NULL;
|
||||
cxoObjectType *objType = NULL;
|
||||
cxoVarType *varType;
|
||||
cxoTransformNum transformNum;
|
||||
Py_ssize_t size;
|
||||
cxoObject *obj;
|
||||
int isArray;
|
||||
|
@ -253,15 +220,15 @@ cxoVar *cxoVar_newByValue(cxoCursor *cursor, PyObject *value,
|
|||
}
|
||||
|
||||
// default processing
|
||||
varType = cxoVarType_fromPythonValue(value,
|
||||
&isArray, &size, &numElements, cursor->stmtInfo.isPLSQL);
|
||||
if (!varType)
|
||||
if (cxoTransform_getNumFromValue(value, &isArray, &size, &numElements,
|
||||
cursor->stmtInfo.isPLSQL, &transformNum) < 0)
|
||||
return NULL;
|
||||
if (varType->transformNum == CXO_TRANSFORM_OBJECT) {
|
||||
if (transformNum == CXO_TRANSFORM_OBJECT) {
|
||||
obj = (cxoObject*) value;
|
||||
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 *typeObj, *numElementsObj;
|
||||
cxoTransformNum transformNum;
|
||||
cxoObjectType *objType;
|
||||
cxoVarType *varType;
|
||||
uint32_t numElements;
|
||||
int ok;
|
||||
|
||||
|
@ -282,9 +249,6 @@ static cxoVar *cxoVar_newArrayByType(cxoCursor *cursor,
|
|||
ok = (PyList_GET_SIZE(value) == 2);
|
||||
if (ok) {
|
||||
typeObj = PyList_GET_ITEM(value, 0);
|
||||
ok = PyType_Check(typeObj);
|
||||
}
|
||||
if (ok) {
|
||||
numElementsObj = PyList_GET_ITEM(value, 1);
|
||||
ok = PyLong_Check(numElementsObj);
|
||||
}
|
||||
|
@ -295,13 +259,12 @@ static cxoVar *cxoVar_newArrayByType(cxoCursor *cursor,
|
|||
}
|
||||
|
||||
// create variable
|
||||
varType = cxoVarType_fromPythonType(typeObj, &objType);
|
||||
if (!varType)
|
||||
if (cxoTransform_getNumFromType(typeObj, &transformNum, &objType) < 0)
|
||||
return NULL;
|
||||
numElements = PyLong_AsLong(numElementsObj);
|
||||
if (PyErr_Occurred())
|
||||
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,
|
||||
uint32_t numElements)
|
||||
{
|
||||
cxoTransformNum transformNum;
|
||||
cxoObjectType *objType;
|
||||
cxoVarType *varType;
|
||||
long size;
|
||||
|
||||
// passing an integer is assumed to be a string
|
||||
|
@ -321,9 +284,8 @@ cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
|||
size = PyLong_AsLong(value);
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
varType = cxoVarType_fromPythonType((PyObject*) &PyUnicode_Type,
|
||||
&objType);
|
||||
return cxoVar_new(cursor, numElements, varType, size, 0, objType);
|
||||
return cxoVar_new(cursor, numElements, CXO_TRANSFORM_STRING, size, 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
// passing an array of two elements to define an array
|
||||
|
@ -336,11 +298,11 @@ cxoVar *cxoVar_newByType(cxoCursor *cursor, PyObject *value,
|
|||
return (cxoVar*) value;
|
||||
}
|
||||
|
||||
// everything else ought to be a Python type or object type
|
||||
varType = cxoVarType_fromPythonType(value, &objType);
|
||||
if (!varType)
|
||||
// everything else ought to be a Python type, database type constant or
|
||||
// object type
|
||||
if (cxoTransform_getNumFromType(value, &transformNum, &objType) < 0)
|
||||
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];
|
||||
if (data->isNull)
|
||||
Py_RETURN_NONE;
|
||||
value = cxoTransform_toPython(var->type->transformNum, var->connection,
|
||||
value = cxoTransform_toPython(var->transformNum, var->connection,
|
||||
var->objectType, &data->value, var->encodingErrors);
|
||||
if (value) {
|
||||
switch (var->type->transformNum) {
|
||||
switch (var->transformNum) {
|
||||
case CXO_TRANSFORM_BFILE:
|
||||
case CXO_TRANSFORM_BLOB:
|
||||
case CXO_TRANSFORM_CLOB:
|
||||
|
@ -491,7 +453,7 @@ static int cxoVar_setValueBytes(cxoVar *var, uint32_t pos, dpiData *data,
|
|||
int status;
|
||||
|
||||
if (buffer->size > var->bufferSize) {
|
||||
cxoTransform_getTypeInfo(var->type->transformNum, &oracleTypeNum,
|
||||
cxoTransform_getTypeInfo(var->transformNum, &oracleTypeNum,
|
||||
&nativeTypeNum);
|
||||
if (dpiConn_newVar(var->connection->handle, oracleTypeNum,
|
||||
nativeTypeNum, var->allocatedElements, buffer->size, 0,
|
||||
|
@ -605,18 +567,18 @@ static int cxoVar_setSingleValue(cxoVar *var, uint32_t arrayPos,
|
|||
data = &var->data[arrayPos];
|
||||
data->isNull = (value == Py_None);
|
||||
if (!data->isNull) {
|
||||
if (var->type->transformNum == CXO_TRANSFORM_CURSOR)
|
||||
if (var->transformNum == CXO_TRANSFORM_CURSOR)
|
||||
result = cxoVar_setValueCursor(var, arrayPos, data, value);
|
||||
else {
|
||||
cxoBuffer_init(&buffer);
|
||||
if (var->type->size > 0)
|
||||
if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES)
|
||||
dbValue = &tempDbValue;
|
||||
else dbValue = &data->value;
|
||||
result = cxoTransform_fromPython(var->type->transformNum,
|
||||
result = cxoTransform_fromPython(var->transformNum,
|
||||
&nativeTypeNum, value, dbValue, &buffer,
|
||||
var->connection->encodingInfo.encoding,
|
||||
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);
|
||||
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()
|
||||
// Return a string representation of the variable.
|
||||
//-----------------------------------------------------------------------------
|
||||
static PyObject *cxoVar_repr(cxoVar *var)
|
||||
{
|
||||
PyObject *value, *module, *name, *result;
|
||||
PyObject *value, *module, *name, *result, *typeName;
|
||||
uint32_t numElements;
|
||||
|
||||
if (var->isArray) {
|
||||
|
@ -780,14 +759,22 @@ static PyObject *cxoVar_repr(cxoVar *var)
|
|||
else value = cxoVar_getArrayValue(var, var->allocatedElements, NULL);
|
||||
if (!value)
|
||||
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);
|
||||
return NULL;
|
||||
}
|
||||
result = cxoUtils_formatString("<%s.%s with value %r>",
|
||||
PyTuple_Pack(3, module, name, value));
|
||||
if (cxoUtils_getModuleAndName(Py_TYPE(var), &module, &name) < 0) {
|
||||
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(name);
|
||||
Py_DECREF(value);
|
||||
Py_DECREF(typeName);
|
||||
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):
|
||||
"test binding out a boolean value (False)"
|
||||
result = self.cursor.callfunc("pkg_TestBooleans.IsLessThan10",
|
||||
cx_Oracle.BOOLEAN, (15,))
|
||||
cx_Oracle.DB_TYPE_BOOLEAN, (15,))
|
||||
self.assertEqual(result, False)
|
||||
|
||||
def testBindOutTrue(self):
|
||||
|
|
|
@ -191,7 +191,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
encoding="UTF-8", nencoding="UTF-16")
|
||||
value = u"\u03b4\u4e2a"
|
||||
cursor = connection.cursor()
|
||||
ncharVar = cursor.var(cx_Oracle.NCHAR, 100)
|
||||
ncharVar = cursor.var(cx_Oracle.DB_TYPE_NVARCHAR, 100)
|
||||
ncharVar.setvalue(0, value)
|
||||
cursor.execute("select :value from dual", value = ncharVar)
|
||||
result, = cursor.fetchone()
|
||||
|
|
|
@ -613,7 +613,8 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
self.cursor.parse(sql)
|
||||
self.assertEqual(self.cursor.statement, sql)
|
||||
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):
|
||||
"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.
|
||||
#
|
||||
|
@ -26,7 +26,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
end;""",
|
||||
cursor = cursor)
|
||||
self.assertEqual(cursor.description,
|
||||
[ ('STRINGVALUE', cx_Oracle.FIXED_CHAR, 1,
|
||||
[ ('STRINGVALUE', cx_Oracle.DB_TYPE_CHAR, 1,
|
||||
TestEnv.GetCharSetRatio(), None, None, 1) ])
|
||||
self.assertEqual(cursor.fetchall(), [('X',)])
|
||||
|
||||
|
@ -36,8 +36,8 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
self.assertEqual(cursor.description, None)
|
||||
self.cursor.callproc("pkg_TestRefCursors.TestOutCursor", (2, cursor))
|
||||
self.assertEqual(cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('STRINGCOL', cx_Oracle.STRING, 20, 20 *
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('STRINGCOL', cx_Oracle.DB_TYPE_VARCHAR, 20, 20 *
|
||||
TestEnv.GetCharSetRatio(), None, None, 0) ])
|
||||
self.assertEqual(cursor.fetchall(),
|
||||
[ (1, 'String 1'), (2, 'String 2') ])
|
||||
|
@ -80,9 +80,9 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
from TestNumbers
|
||||
order by IntCol""")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('CURSORVALUE', cx_Oracle.CURSOR, None, None, None, None,
|
||||
1) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('CURSORVALUE', cx_Oracle.DB_TYPE_CURSOR, None, None, None,
|
||||
None, 1) ])
|
||||
for i in range(1, 11):
|
||||
number, cursor = self.cursor.fetchone()
|
||||
self.assertEqual(number, i)
|
||||
|
@ -90,4 +90,3 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
if __name__ == "__main__":
|
||||
TestEnv.RunTestCases()
|
||||
|
||||
|
|
|
@ -174,7 +174,8 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
stringValue = "The string that will be verified"
|
||||
obj = typeObj.newobject()
|
||||
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("""
|
||||
insert into TestObjects (IntCol, ObjectCol)
|
||||
values (4, :obj)
|
||||
|
|
|
@ -215,9 +215,9 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate"
|
||||
self.cursor.execute("select * from TestDates")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('DATECOL', cx_Oracle.DATETIME, 23, None, None, None, 0),
|
||||
('NULLABLECOL', cx_Oracle.DATETIME, 23, None, None, None,
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('DATECOL', cx_Oracle.DB_TYPE_DATE, 23, None, None, None, 0),
|
||||
('NULLABLECOL', cx_Oracle.DB_TYPE_DATE, 23, None, None, None,
|
||||
1) ])
|
||||
|
||||
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):
|
||||
"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("""
|
||||
select * from TestIntervals
|
||||
where IntervalCol = :value""",
|
||||
|
@ -44,7 +44,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindNull(self):
|
||||
"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("""
|
||||
select * from TestIntervals
|
||||
where IntervalCol = :value""",
|
||||
|
@ -53,7 +53,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindOutSetInputSizes(self):
|
||||
"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("""
|
||||
begin
|
||||
:value := to_dsinterval('8 09:24:18.123789');
|
||||
|
@ -64,7 +64,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutSetInputSizes(self):
|
||||
"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("""
|
||||
begin
|
||||
:value := :value + to_dsinterval('5 08:30:00');
|
||||
|
@ -75,7 +75,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutFractionalSecond(self):
|
||||
"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("""
|
||||
begin
|
||||
:value := :value + to_dsinterval('5 08:30:00');
|
||||
|
@ -87,7 +87,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindOutVar(self):
|
||||
"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("""
|
||||
begin
|
||||
:value := to_dsinterval('15 18:35:45.586');
|
||||
|
@ -99,7 +99,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutVarDirectSet(self):
|
||||
"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))
|
||||
self.cursor.execute("""
|
||||
begin
|
||||
|
@ -113,9 +113,11 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate"
|
||||
self.cursor.execute("select * from TestIntervals")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('INTERVALCOL', cx_Oracle.INTERVAL, None, None, 2, 6, 0),
|
||||
('NULLABLECOL', cx_Oracle.INTERVAL, None, None, 2, 6, 1) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('INTERVALCOL', cx_Oracle.DB_TYPE_INTERVAL_DS, None, None, 2,
|
||||
6, 0),
|
||||
('NULLABLECOL', cx_Oracle.DB_TYPE_INTERVAL_DS, None, None, 2,
|
||||
6, 1) ])
|
||||
|
||||
def testFetchAll(self):
|
||||
"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.
|
||||
#
|
||||
|
@ -117,8 +117,10 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def __ValidateQuery(self, rows, lobType):
|
||||
longString = ""
|
||||
dbType = getattr(cx_Oracle, "DB_TYPE_" + lobType)
|
||||
for row in rows:
|
||||
integerValue, lob = row
|
||||
self.assertEqual(lob.type, dbType)
|
||||
if integerValue == 0:
|
||||
self.assertEqual(lob.size(), 0)
|
||||
expectedValue = ""
|
||||
|
@ -158,16 +160,17 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate for BLOBs"
|
||||
self.cursor.execute("select * from TestBLOBs")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('BLOBCOL', cx_Oracle.BLOB, None, None, None, None, 0) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('BLOBCOL', cx_Oracle.DB_TYPE_BLOB, None, None, None, None,
|
||||
0) ])
|
||||
|
||||
def testBLOBsDirect(self):
|
||||
"test binding and fetching BLOB data (directly)"
|
||||
self.__PerformTest("BLOB", cx_Oracle.BLOB)
|
||||
self.__PerformTest("BLOB", cx_Oracle.DB_TYPE_BLOB)
|
||||
|
||||
def testBLOBsIndirect(self):
|
||||
"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):
|
||||
"test operations on BLOBs"
|
||||
|
@ -177,16 +180,17 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate for CLOBs"
|
||||
self.cursor.execute("select * from TestCLOBs")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('CLOBCOL', cx_Oracle.CLOB, None, None, None, None, 0) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('CLOBCOL', cx_Oracle.DB_TYPE_CLOB, None, None, None, None,
|
||||
0) ])
|
||||
|
||||
def testCLOBsDirect(self):
|
||||
"test binding and fetching CLOB data (directly)"
|
||||
self.__PerformTest("CLOB", cx_Oracle.CLOB)
|
||||
self.__PerformTest("CLOB", cx_Oracle.DB_TYPE_CLOB)
|
||||
|
||||
def testCLOBsIndirect(self):
|
||||
"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):
|
||||
"test operations on CLOBs"
|
||||
|
@ -215,12 +219,13 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate for NCLOBs"
|
||||
self.cursor.execute("select * from TestNCLOBs")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('NCLOBCOL', cx_Oracle.NCLOB, None, None, None, None, 0) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('NCLOBCOL', cx_Oracle.DB_TYPE_NCLOB, None, None, None, None,
|
||||
0) ])
|
||||
|
||||
def testNCLOBsDirect(self):
|
||||
"test binding and fetching NCLOB data (directly)"
|
||||
self.__PerformTest("NCLOB", cx_Oracle.NCLOB)
|
||||
self.__PerformTest("NCLOB", cx_Oracle.DB_TYPE_NCLOB)
|
||||
|
||||
def testNCLOBDifferentEncodings(self):
|
||||
"test binding and fetching NCLOB data (different encodings)"
|
||||
|
@ -230,11 +235,11 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
value = u"\u03b4\u4e2a"
|
||||
cursor = connection.cursor()
|
||||
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("select NCLOBCol from TestNCLOBs")
|
||||
nclob, = cursor.fetchone()
|
||||
cursor.setinputsizes(val = cx_Oracle.NCHAR)
|
||||
cursor.setinputsizes(val = cx_Oracle.DB_TYPE_NVARCHAR)
|
||||
cursor.execute("update TestNCLOBs set NCLOBCol = :val",
|
||||
val = nclob.read() + value)
|
||||
cursor.execute("select NCLOBCol from TestNCLOBs")
|
||||
|
@ -243,7 +248,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testNCLOBsIndirect(self):
|
||||
"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):
|
||||
"test operations on NCLOBs"
|
||||
|
@ -271,7 +276,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testAssignStringBeyondArraySize(self):
|
||||
"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")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -59,7 +59,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testLongs(self):
|
||||
"test binding and fetching long data"
|
||||
self.__PerformTest("Long", cx_Oracle.LONG_STRING)
|
||||
self.__PerformTest("Long", cx_Oracle.DB_TYPE_LONG)
|
||||
|
||||
def testLongWithExecuteMany(self):
|
||||
"test binding long data with executemany()"
|
||||
|
@ -77,23 +77,23 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testLongRaws(self):
|
||||
"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):
|
||||
"test cursor description is accurate for longs"
|
||||
self.cursor.execute("select * from TestLongs")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('LONGCOL', cx_Oracle.LONG_STRING, None, None, None, None,
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('LONGCOL', cx_Oracle.DB_TYPE_LONG, None, None, None, None,
|
||||
0) ])
|
||||
|
||||
def testLongRawCursorDescription(self):
|
||||
"test cursor description is accurate for long raws"
|
||||
self.cursor.execute("select * from TestLongRaws")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('LONGRAWCOL', cx_Oracle.LONG_BINARY, None, None, None, None,
|
||||
0) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('LONGRAWCOL', cx_Oracle.DB_TYPE_LONG_RAW, None, None, None,
|
||||
None, 0) ])
|
||||
|
||||
def testArraySizeTooLarge(self):
|
||||
"test array size too large generates an exception"
|
||||
|
|
|
@ -43,7 +43,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindUnicode(self):
|
||||
"test binding in a unicode"
|
||||
self.cursor.setinputsizes(value = cx_Oracle.NCHAR)
|
||||
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_NVARCHAR)
|
||||
self.cursor.execute("""
|
||||
select * from TestUnicodes
|
||||
where UnicodeCol = :value""",
|
||||
|
@ -52,8 +52,8 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindDifferentVar(self):
|
||||
"test binding a different variable on second execution"
|
||||
retval_1 = self.cursor.var(cx_Oracle.NCHAR, 30)
|
||||
retval_2 = 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.DB_TYPE_NVARCHAR, 30)
|
||||
self.cursor.execute(r"begin :retval := unistr('Called \3042'); end;",
|
||||
retval = retval_1)
|
||||
self.assertEqual(retval_1.getvalue(), u"Called \u3042")
|
||||
|
@ -63,7 +63,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindUnicodeAfterNumber(self):
|
||||
"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")
|
||||
self.cursor.setinputsizes(value = cx_Oracle.NUMBER)
|
||||
self.cursor.execute("""
|
||||
|
@ -76,7 +76,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test binding in a unicode array"
|
||||
returnValue = self.cursor.var(cx_Oracle.NUMBER)
|
||||
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 = """
|
||||
begin
|
||||
:retval := pkg_TestUnicodeArrays.TestInArrays(
|
||||
|
@ -88,7 +88,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
array = arrayVar)
|
||||
self.assertEqual(returnValue.getvalue(), 116)
|
||||
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,
|
||||
integerValue = 8,
|
||||
array = arrayVar)
|
||||
|
@ -97,7 +97,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
def testBindUnicodeArrayBySizes(self):
|
||||
"test binding in a unicode array (with setinputsizes)"
|
||||
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]
|
||||
self.cursor.execute("""
|
||||
begin
|
||||
|
@ -112,7 +112,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
def testBindUnicodeArrayByVar(self):
|
||||
"test binding in a unicode array (with arrayvar)"
|
||||
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])
|
||||
self.cursor.execute("""
|
||||
begin
|
||||
|
@ -126,7 +126,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutUnicodeArrayByVar(self):
|
||||
"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]
|
||||
format = u"Converted element \u3042 # %d originally had length %d"
|
||||
expectedData = [format % (i, len(originalData[i - 1])) \
|
||||
|
@ -142,7 +142,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindOutUnicodeArrayByVar(self):
|
||||
"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"
|
||||
expectedData = [format % i for i in range(1, 7)]
|
||||
self.cursor.execute("""
|
||||
|
@ -163,7 +163,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindOutSetInputSizesByType(self):
|
||||
"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"""
|
||||
begin
|
||||
:value := unistr('TSI \3042');
|
||||
|
@ -172,7 +172,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutSetInputSizesByType(self):
|
||||
"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"""
|
||||
begin
|
||||
:value := :value || unistr(' TSI \3042');
|
||||
|
@ -183,7 +183,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindOutVar(self):
|
||||
"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"""
|
||||
begin
|
||||
:value := unistr('TSI (VAR) \3042');
|
||||
|
@ -193,7 +193,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutVarDirectSet(self):
|
||||
"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")
|
||||
self.cursor.execute(r"""
|
||||
begin
|
||||
|
@ -206,11 +206,13 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate"
|
||||
self.cursor.execute("select * from TestUnicodes")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('UNICODECOL', cx_Oracle.NCHAR, 20, 80, None, None, 0),
|
||||
('FIXEDUNICODECOL', cx_Oracle.FIXED_NCHAR, 40, 160, None,
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('UNICODECOL', cx_Oracle.DB_TYPE_NVARCHAR, 20, 80, None,
|
||||
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):
|
||||
"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.
|
||||
#
|
||||
|
@ -19,7 +19,8 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def outputTypeHandlerNativeInt(self, cursor, name, defaultType, size,
|
||||
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,
|
||||
precision, scale):
|
||||
|
@ -272,12 +273,15 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate"
|
||||
self.cursor.execute("select * from TestNumbers")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('LONGINTCOL', cx_Oracle.NUMBER, 17, None, 16, 0, 0),
|
||||
('NUMBERCOL', cx_Oracle.NUMBER, 13, None, 9, 2, 0),
|
||||
('FLOATCOL', cx_Oracle.NUMBER, 127, None, 126, -127, 0),
|
||||
('UNCONSTRAINEDCOL', cx_Oracle.NUMBER, 127, None, 0, -127, 0),
|
||||
('NULLABLECOL', cx_Oracle.NUMBER, 39, None, 38, 0, 1) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('LONGINTCOL', cx_Oracle.DB_TYPE_NUMBER, 17, None, 16, 0, 0),
|
||||
('NUMBERCOL', cx_Oracle.DB_TYPE_NUMBER, 13, None, 9, 2, 0),
|
||||
('FLOATCOL', cx_Oracle.DB_TYPE_NUMBER, 127, None, 126, -127,
|
||||
0),
|
||||
('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):
|
||||
"test that fetching all of the data returns the correct results"
|
||||
|
@ -369,23 +373,28 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
def testStringFormat(self):
|
||||
"test that string format is returned properly"
|
||||
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)
|
||||
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):
|
||||
"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.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()
|
||||
self.assertEqual(value, 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()
|
||||
self.assertEqual(value, 1.5)
|
||||
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()
|
||||
self.assertEqual(str(value), str(float("NaN")))
|
||||
|
||||
|
@ -399,4 +408,3 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
if __name__ == "__main__":
|
||||
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.
|
||||
#
|
||||
|
@ -50,7 +50,8 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindNullIn(self):
|
||||
"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,
|
||||
(var,))
|
||||
self.assertEqual(result, "null")
|
||||
|
@ -122,9 +123,11 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
from TestObjects
|
||||
order by IntCol""")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('OBJECTCOL', cx_Oracle.OBJECT, None, None, None, None, 1),
|
||||
('ARRAYCOL', cx_Oracle.OBJECT, None, None, None, None, 1) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('OBJECTCOL', cx_Oracle.DB_TYPE_OBJECT, None, None, None,
|
||||
None, 1),
|
||||
('ARRAYCOL', cx_Oracle.DB_TYPE_OBJECT, None, None, None,
|
||||
None, 1) ])
|
||||
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,
|
||||
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.schema, self.connection.username.upper())
|
||||
self.assertEqual(typeObj.name, "UDT_OBJECT")
|
||||
subObjectValueType = self.connection.gettype("UDT_SUBOBJECT")
|
||||
subObjectArrayType = self.connection.gettype("UDT_OBJECTARRAY")
|
||||
expectedAttributeNames = ["NUMBERVALUE", "STRINGVALUE",
|
||||
"FIXEDCHARVALUE", "NSTRINGVALUE", "NFIXEDCHARVALUE",
|
||||
"RAWVALUE", "INTVALUE", "SMALLINTVALUE", "REALVALUE",
|
||||
|
@ -163,9 +168,23 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"NCLOBVALUE", "BLOBVALUE", "SUBOBJECTVALUE", "SUBOBJECTARRAY"]
|
||||
actualAttributeNames = [a.name for a in typeObj.attributes]
|
||||
self.assertEqual(actualAttributeNames, expectedAttributeNames)
|
||||
typeObj = self.connection.gettype("UDT_OBJECTARRAY")
|
||||
self.assertEqual(typeObj.iscollection, True)
|
||||
self.assertEqual(typeObj.attributes, [])
|
||||
expectedAttributeTypes = [cx_Oracle.DB_TYPE_NUMBER,
|
||||
cx_Oracle.DB_TYPE_VARCHAR, cx_Oracle.DB_TYPE_CHAR,
|
||||
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):
|
||||
"test object type data"
|
||||
|
@ -316,7 +335,8 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test setting value of object variable to wrong object type"
|
||||
wrongObjType = self.connection.gettype("UDT_OBJECTARRAY")
|
||||
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)
|
||||
|
||||
def testStringFormat(self):
|
||||
|
|
|
@ -272,7 +272,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindLongString(self):
|
||||
"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("""
|
||||
declare
|
||||
t_Temp varchar2(20000);
|
||||
|
@ -295,15 +295,15 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate"
|
||||
self.cursor.execute("select * from TestStrings")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('STRINGCOL', cx_Oracle.STRING, 20,
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('STRINGCOL', cx_Oracle.DB_TYPE_VARCHAR, 20,
|
||||
20 * TestEnv.GetCharSetRatio(), None,
|
||||
None, 0),
|
||||
('RAWCOL', cx_Oracle.BINARY, 30, 30, None, None, 0),
|
||||
('FIXEDCHARCOL', cx_Oracle.FIXED_CHAR, 40,
|
||||
('RAWCOL', cx_Oracle.DB_TYPE_RAW, 30, 30, None, None, 0),
|
||||
('FIXEDCHARCOL', cx_Oracle.DB_TYPE_CHAR, 40,
|
||||
40 * TestEnv.GetCharSetRatio(),
|
||||
None, None, 0),
|
||||
('NULLABLECOL', cx_Oracle.STRING, 50,
|
||||
('NULLABLECOL', cx_Oracle.DB_TYPE_VARCHAR, 50,
|
||||
50 * TestEnv.GetCharSetRatio(), None,
|
||||
None, 1) ])
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindTimestamp(self):
|
||||
"test binding in a timestamp"
|
||||
self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
|
||||
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||
self.cursor.execute("""
|
||||
select * from TestTimestamps
|
||||
where TimestampCol = :value""",
|
||||
|
@ -54,7 +54,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindNull(self):
|
||||
"test binding in a null"
|
||||
self.cursor.setinputsizes(value = cx_Oracle.TIMESTAMP)
|
||||
self.cursor.setinputsizes(value = cx_Oracle.DB_TYPE_TIMESTAMP)
|
||||
self.cursor.execute("""
|
||||
select * from TestTimestamps
|
||||
where TimestampCol = :value""",
|
||||
|
@ -63,7 +63,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindOutSetInputSizes(self):
|
||||
"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("""
|
||||
begin
|
||||
:value := to_timestamp('20021209', 'YYYYMMDD');
|
||||
|
@ -73,7 +73,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutSetInputSizes(self):
|
||||
"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("""
|
||||
begin
|
||||
:value := :value + 5.25;
|
||||
|
@ -84,7 +84,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindOutVar(self):
|
||||
"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("""
|
||||
begin
|
||||
:value := to_date('20021231 12:31:00',
|
||||
|
@ -96,7 +96,7 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
|
||||
def testBindInOutVarDirectSet(self):
|
||||
"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))
|
||||
self.cursor.execute("""
|
||||
begin
|
||||
|
@ -110,9 +110,11 @@ class TestCase(TestEnv.BaseTestCase):
|
|||
"test cursor description is accurate"
|
||||
self.cursor.execute("select * from TestTimestamps")
|
||||
self.assertEqual(self.cursor.description,
|
||||
[ ('INTCOL', cx_Oracle.NUMBER, 10, None, 9, 0, 0),
|
||||
('TIMESTAMPCOL', cx_Oracle.TIMESTAMP, 23, None, 0, 6, 0),
|
||||
('NULLABLECOL', cx_Oracle.TIMESTAMP, 23, None, 0, 6, 1) ])
|
||||
[ ('INTCOL', cx_Oracle.DB_TYPE_NUMBER, 10, None, 9, 0, 0),
|
||||
('TIMESTAMPCOL', cx_Oracle.DB_TYPE_TIMESTAMP, 23, None, 0, 6,
|
||||
0),
|
||||
('NULLABLECOL', cx_Oracle.DB_TYPE_TIMESTAMP, 23, None, 0, 6,
|
||||
1) ])
|
||||
|
||||
def testFetchAll(self):
|
||||
"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.
|
||||
#
|
||||
|
@ -36,6 +36,7 @@ moduleNames = [
|
|||
"Cursor",
|
||||
"CursorVar",
|
||||
"DateTimeVar",
|
||||
"DbTypes",
|
||||
"DMLReturning",
|
||||
"Error",
|
||||
"IntervalVar",
|
||||
|
|
Loading…
Reference in New Issue