Altibase into Apache Arrow with ADBC
Altibase 7.3.0.1.4 (A+ Edition), read and written through adbcBridge — the ADBC driver that loads the database's ODBC driver — verified on Linux. Everything below is the compatibility matrix's record for this row.
Status
PASS
driver unavailable: Altibase publishes no macOS client (its supported-platforms list is Linux, AIX, HP-UX and a Windows-only client)
driver unavailable: Altibase's Windows ODBC client "is provided only up to Altibase version 6.5.1, and not provided to Altibase version 7 or later" (its Windows ODBC development guide), so nothing drives a 7.x server; the downloads sit behind the vendor portal in any case
Driver and connection string
- ODBC driver
- Altibase ODBC (
libaltibase_odbc-64bit-ul64.so, native wire) - Wire
- native ODBC
- adbcBridge
- 0.1.1 (release)
The connection string the matrix used, as the connection strings reference records it (Databases with their own native protocol and ODBC driver); {drv} is the driver library or its name from odbcinst.ini, and the host, port and credentials are the test server's.
Driver={drv};Server=127.0.0.1;Port=20300;User=sys;Password=manager;NLS_USE=UTF8;
Python
import adbcbridge
# {drv}: the ODBC driver library (path), or its name from odbcinst.ini
conn = adbcbridge.connect(uri="Driver={drv};Server=127.0.0.1;Port=20300;User=sys;Password=manager;NLS_USE=UTF8;")
with conn.cursor() as cur:
cur.execute("SELECT * FROM my_table")
table = cur.fetch_arrow_table() # pyarrow.Table
Polars and pandas
import polars as pl, pandas as pd
df = pl.read_database("SELECT * FROM my_table", connection=conn) # Polars, Arrow-native
pdf = pd.read_sql("SELECT * FROM my_table", conn) # pandas 2.2+, ADBC connection
pip install adbcbridge brings the driver library; the Altibase ODBC driver is installed the way its vendor documents, then named in Driver=. Rust, Go, C# and Java use the same connection string through their ADBC driver managers — see the docs.
What the matrix recorded
first-party driver on 20300, linked against nothing but libc, lifted out of the server image with docker cp (-ul64 is the 8-byte-SQLLEN build unixODBC wants; the -ul32 sibling sits beside it).
What this stack needed
- Server side,
altibase/altibaseis licence-gated — it ships a 1-byteconf/licenseand the boot stops atCheck LicensewithNo valid license present!(ERR-42000), a 90-day trial key being a registration away — so the entry runs the same vendor's freealtibase/a_plus_edition, which needs none; it wantsMODE=foreground(the image defaultMODE=initstarts a shell and exits) andDB_CHARSET=UTF8(the default is KO16KSC5601). - Driver quirks handled: the wide and narrow paths disagree above the BMP — a
SQL_C_WCHARparameter is stored as CESU-8 (héllo 🚀is 13 bytes,LENGTH()8) and reading that back narrow yields bytes no UTF-8 decoder accepts, whileSQL_C_CHARin and out round-trips it byte for byte, so both ends stay narrow (wchar_as_utf8+narrow_params, as Informix); its byte types carry vendorSQL_DATA_TYPEcodes outside the ODBC range (BYTE 20001, NIBBLE 20002, VARBYTE 20003, BLOB 30, CLOB 40, VARBIT -100) and, unrecognised, BYTE/VARBYTE/BLOB fall through to the text path and come back hex-encoded, so those three are read asSQL_C_BINARY(as Db2's ownSQL_BLOB-98 already is);SQLGetTypeInfohas noSQL_LONGVARCHARat all and reports CREATE_PARAMSprecision— notlength— forVARCHAR, so generated ingest DDL got a bareVARCHAR, which in Altibase meansVARCHAR(1)and fails the first insert with 22026Invalid data type length, fixed by namingVARCHAR(32000)(ddl_string_type_name, as Firebird);SQL_IDENTIFIER_QUOTE_CHARis a blank, so ingest quotes nothing and the server upper-cases what it emits (the entry leaves its own SQL unquoted too, as Ignite's does). - Types: no
BOOLEAN(HY004Unable to create a column with the specified data type, soboisSMALLINT→ int16), noDOUBLE PRECISION(DOUBLE), noVARBINARY, andDATE*is* the timestamp — microseconds and all, describedSQL_TYPE_TIMESTAMP— so it carries bothdandts; BYTE, VARBYTE, NIBBLE, BIT and VARBIT accept no boundSQL_C_BINARYparameter at all (22018Conversion not applicable, 135180), which is whybis aBLOB. - Its parameter arrays are one round trip and beat the multi-row
INSERT26×, soprefer_param_arrays— the third driver to need it, aftermaodbcand Vertica's; ingest 30k rows/s multi-row, 778–816k as an array, fetch 2.0–2.3M rows/s