Comdb2 to Python Type Mappings
For all Comdb2 types, the same Python type is used for binding a parameter value as is returned for a SQL query result column of that type. SQL types are mapped to Python types according to the following table:
SQL type |
Python type |
|---|---|
NULL |
|
integer |
|
real |
|
blob |
|
text |
|
datetime |
|
datetimeus |
|
carray |
|
intervalym |
not supported |
intervalds |
not supported |
intervaldsus |
not supported |
decimal |
not supported |
NULL
A SQL NULL value is represented as a Python None.
Numeric Types
Integral SQL values are represented as Python int values. Floating point
SQL values are represented as Python float values. If a Python value is
given that’s too large to fit into the database column (for instance, 1000000
into a column of type short), an exception will be raised.
String and Blob Types
You may occasionally need to convert between byte strings and Unicode strings:
If you have a variable of type
bytesand you want to pass it to the database as a TEXT value, you need to convert it to astrusingdecode.When a TEXT column is read back from the database, it is decoded as UTF-8. If your database has non-UTF-8 text in a
cstringcolumn, you need to cast that column from a TEXT to a BLOB in SQL when reading it out, like this:cursor.execute("select cast(col as blob) from tbl")
That will result in you receiving a
bytesobject rather thanstrfor that result column.Note
ASCII is a subset of UTF-8, so this is not required for if the column contains plain ASCII text.
Likewise, when a
strobject is sent to the database, it is encoded as UTF-8. If you need to store non-UTF-8 text in acstringcolumn in your database, you need to bind a byte string in Python land, and then cast the value from BLOB to TEXT in SQL. For instance, to bind a latin1 string containing a copyright symbol, you could do:params = {'c': b'Copyright \xA9 2016'} # dbapi2 c.execute("select * from tbl where col=cast(%(c)s as text)", params) # cdb2 h.execute("select * from tbl where col=cast(@c as text)", params)
Date and Time Types
Comdb2 has two types for representing a specific point in time. The DATETIME
type supports millisecond precision and is mapped to Python’s
datetime.datetime. The DATETIMEUS type supports microsecond precision and is
mapped to a subclass of datetime.datetime that we expose, called
DatetimeUs. This subclass behaves identically to
datetime.datetime, differing only in type and in resulting in higher
precision values when bound as an input parameter or retrieved as a result
column.
Whenever either type of datetime is retrieved as a result column, the returned
datetime.datetime object will be aware, meaning it will be associated with
a timezone (namely, the current timezone of the Comdb2 connection). Whenever
either type of datetime is sent as a query parameter, it is permitted to be
naïve, in which case it is treated as UTC (and not as the system’s local
time, which is the more common interpretation in newer Python libraries).
Comdb2 additionally supports three types for representing time intervals. One represents an exact number of elapsed milliseconds between two times (INTERVALDS). One represents an exact number of elapsed microseconds between two times (INTERVALDSUS). The final one (INTERVALYM) represents a number of years and months between two events - unlike the other two, this represents a fuzzy time interval, as the length of a month varies. We do not currently support any of these types.
Decimal Type
Comdb2 supports a DECIMAL type. However, when retriving these columns through
libcdb2api, they are returned as TEXT, making them indistinguishable from
string columns. That currently makes it impossible to map them to Python’s
decimal.Decimal type as we would like to. If libcdb2api is ever changed
to properly distinguish between DECIMAL and TEXT columns this package will be
enhanced to properly expose DECIMAL columns.
C Array Types
Note
This only works with comdb2 R8. If you need to connect to a database that is still running comdb2 R7, the queries using this feature will fail.
Often in SQL queries, it is useful to bind an array of elements of the same
type, for example when using the IN operator. In this case, you can use a
(non-empty) list or tuple, as long as all elements of the sequence are of
the same type (and one of the above Python types). Note that nested sequences
are not allowed.
Note that when binding an element of that type, you want to use the CARRAY
function, like so:
params = {'arr': [1, 2, 3, 4]}
# dbapi2
c.execute("select 2 in CARRAY(%(arr)s)", params)
# cdb2
h.execute("select 2 in CARRAY(@arr)", params)