Skip to content

API surface

The top-level surface of informix_db and informix_db.aio. For full PEP 249 details, see the standard’s DB-API 2.0 spec.

import informix_db
informix_db.connect(...) -> Connection
informix_db.create_pool(...) -> Pool
informix_db.apilevel # "2.0"
informix_db.threadsafety # 1
informix_db.paramstyle # "numeric"
from informix_db import aio
await aio.connect(...) -> aio.Connection
await aio.create_pool(...) -> aio.Pool
informix_db.connect(
*,
host: str,
port: int = 9088,
user: str,
password: str,
database: str | None,
server: str, # DBSERVERNAME (not hostname)
autocommit: bool = False,
connect_timeout: float | None = None,
read_timeout: float | None = None,
keepalive: bool = False,
client_locale: str = "en_US.8859-1",
env: dict[str, str] | None = None,
tls: bool | ssl.SSLContext = False,
) -> Connection
Method / propertyDescription
cursor(scrollable=False)Returns a new Cursor. Only one scrollable cursor may be open per connection; see below.
commit()Commits the current transaction.
rollback()Rolls back the current transaction.
close()Closes the connection. Idempotent.
fast_path_call(routine, *args)Direct UDF/SPL invocation, bypassing PREPARE/EXECUTE/FETCH.
encodingResolved Python codec for client_locale.
closedTrue after close().
server_versionServer release, e.g. '…Version 12.10.FC6'. Costs one query on first access, then cached.
server_version_internalRaw login-response version string. Free. See note below.
server_capabilitiesNegotiated ServerCapabilities, or None if the reply couldn’t be decoded.

Connection is also a context manager (with informix_db.connect(...) as conn:), which closes on exit.

There is no conn.transaction() helper and no conn.autocommit attribute. Earlier versions of this page listed both, and neither has ever existed. Set autocommit at connect time with connect(autocommit=True), and manage transactions with commit() / rollback():

conn = informix_db.connect(..., autocommit=False)
try:
cur = conn.cursor()
cur.execute("UPDATE accounts SET balance = balance - ? WHERE id = ?", (100, 1))
cur.execute("UPDATE accounts SET balance = balance + ? WHERE id = ?", (100, 2))
conn.commit()
except Exception:
conn.rollback()
raise

Fetch methods return plain tuples by default. Pass row_factory to get rows that also answer to a column name and an attribute, the shape pyodbc and mssql-python provide:

conn = informix_db.connect(..., row_factory=informix_db.Row)
cur = conn.cursor()
cur.execute("SELECT tabid, tabname FROM systables")
row = cur.fetchone()
row[0] # 1
row["tabname"] # 'systables'
row.tabname # 'systables'

Set on the connection, so it applies to every cursor from it. A cursor can override it with cur.row_factory = informix_db.Row. Pools and the async API forward it unchanged.

Row subclasses tuple, so row == (1, "systables") is still true and anything treating rows as sequences keeps working. Slices return plain tuples, since a slice has no column map. row.keys() gives the column names and row._asdict() gives a dict.

Four behaviours worth knowing:

  • Informix folds unquoted identifiers to lower case, so SELECT Config_Key is reachable as row.config_key. The .lower() people add by hand when building this themselves is already a no-op.
  • Expression columns get server-generated names like (count(*)), which cannot be Python attributes. Those are reachable by subscript only.
  • Duplicate column names resolve to the first occurrence, matching pyodbc. Positional access still reaches both.
  • A column beats a method of the same name. tuple defines count and index; Row adds keys, _asdict and _fields. A column with any of those names wins, because otherwise it would hand back a bound method instead of a value. The methods stay reachable as tuple.count(row, x) and Row.keys(row).
Method / propertyDescription
execute(sql, params=())Prepare + execute. Returns the cursor.
executemany(sql, seq_of_params)Pipelined batch execute.
fetchone()One row tuple, or None.
fetchmany(size=arraysize)List of row tuples.
fetchall()All remaining rows.
scroll(value, mode="relative")Scrollable cursor positioning. Needs cursor(scrollable=True).
fetch_first() / fetch_last()Jump to the first / last row. Scrollable cursors only.
fetch_prior() / fetch_relative(n) / fetch_absolute(n)Relative and absolute positioning. Scrollable cursors only.
read_blob_column(sql, params)Read a BLOB or CLOB column → bytes.
write_blob_column(sql, data, params, clob=False)Write a BLOB column; pass clob=True for CLOB.
close()Closes the cursor + releases server resources.
closedTrue after close().
descriptionSequence of column descriptors per PEP 249.
rowcountAffected row count for DML; -1 for SELECT.
rownumberCurrent 0-indexed position, or None before the first row.
arraysizeDefault fetchmany() size.

There are no read_clob_column / write_clob_column methods and no lastrowid attribute. Earlier versions of this page listed all three, and none have existed.

CLOBs go through the BLOB methods. read_blob_column returns bytes either way, so decode it yourself with the column’s encoding:

cur.write_blob_column(
"INSERT INTO docs VALUES (?, BLOB_PLACEHOLDER)",
"café résumé".encode("iso-8859-1"),
(1,),
clob=True,
)
raw = cur.read_blob_column("SELECT txt FROM docs WHERE id = ?", (1,))
text = raw.decode("iso-8859-1")

For a server-assigned SERIAL after an INSERT, ask the server. Informix exposes it through DBINFO:

cur.execute("INSERT INTO people (name) VALUES (?)", ("ada",))
cur.execute("SELECT DBINFO('sqlca.sqlerrd1') FROM systables WHERE tabid = 1")
new_id = cur.fetchone()[0]
MethodDescription
connection()Context manager yielding a connection from the pool.
close()Closes all idle connections; waits for in-use to return.
closedTrue after close().
sizeCurrent pool size.
idle_countConnections currently idle in the pool.

aio.Pool is identical except its connection() is an async context manager and close() is async.

Error
├── Warning
└── DatabaseError
├── InterfaceError
├── DataError
├── OperationalError
│ └── PoolTimeout
├── IntegrityError
├── InternalError
├── ProgrammingError
└── NotSupportedError

See Exceptions & error codes for the SQLCODE → exception mapping.