Kinetica into Apache Arrow with ADBC
Kinetica 7.1.9 (Developer Edition), read and written through adbcBridge — the ADBC driver that loads the database's ODBC driver — read-only on Linux. Everything below is the compatibility matrix's record for this row.
Status
PASS (read)
driver unavailable: the server image ships Linux and Windows ODBC clients only (/opt/gpudb/downloads)
FAIL on this tree — the Windows driver (KineticaODBC.dll 7.1.9.16, windows-odbc-client.zip from the server image, registered as Kinetica ODBC 7.1) exports the W entry points but transcodes W statement text through the ANSI code page inside itself: the literal 'héllo 🚀' lands as cp1252 bytes and every later read of that row fails HY000 (50311) "Error converting invalid input with source encoding UTF-8 using ICU", identical through pyodbc; its narrow statement path hands UTF-8 through byte for byte and its wide fetch is correct (its narrow fetch is not, so the Ignite treatment does not fit). With narrow_sql set in the Kinetica quirk block on Windows the entry passes — Kinetica (via ODBC) 7.1.9.33, fetch 450–480k rows/s — a proposed bridge fix, not yet in this tree. Any Windows host also needs enable_worker_http_servers = false in the server's gpudb.conf: the driver's multi-head inserter dials the container-internal worker URLs the server advertises
Driver and connection string
- ODBC driver
- Kinetica ODBC 7.1.9.16 (
libKineticaODBC.so, Simba Engine SDK 10.1.6, REST/SQL on 9191) - 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};URL=http://127.0.0.1:29191;UID=admin;PWD=admin;
Python
import adbcbridge
# {drv}: the ODBC driver library (path), or its name from odbcinst.ini
conn = adbcbridge.connect(uri="Driver={drv};URL=http://127.0.0.1:29191;UID=admin;PWD=admin;")
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 Kinetica 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
a vectorized analytic database with a first-party driver — and the driver has the sharpest parameter bug in this matrix.
What this stack needed
- It does not *refuse*
SQLBindParameterthe way the Flight SQL driver does; it accepts every bind and then executes parameter *N* with the value bound at *N+1*, sending the last parameter as NULL. - A one-parameter
INSERTtherefore stores NULL underSQL_SUCCESSwith an empty diagnostic queue, a three-parameter one writes the values shifted a column left, and an eight-parameter one failsHY000 (1040) Driver Error: type: %d— an unformatted format string. - Reproduced with no pyodbc in the picture, binding
SQL_C_LONG→SQL_INTEGERandSQL_C_CHAR→SQL_VARCHARthrough unixODBC directly:HY000 (1040) Driver Error: stod; Setting column 'i' with value: 'hello', the second parameter's text landing in the first column. SQLDescribeParamcompounds it by reporting every parameter asSQL_VARCHAR(1024)whatever the target column is, and a string parameter onSELECT ?segfaults the process.- Nothing a caller binds can be trusted to arrive, so the entry is read-only and
setupbuilds both tables with literal SQL — Kinetica itself writes fine that way,SQLExecDirectis exact, and emoji,BYTES,DATEandBOOLEANall round-trip. - Two bridge quirks, both keyed on the driver/DBMS name
Kinetica:decimal_fixed_precision— the server has exactly one decimal type,DECIMAL(18,4)(everyDECIMAL(p,s)in DDL is stored as it, asSHOW CREATE TABLEconfirms), and the driver misdescribes such a column three different ways:SQLDescribeColsays precision 38 scale 0,SQLColumnssays (18,18), andSQLGetTypeInfosays 38; believing scale 0 read the12.3450the driver hands over as adecimal128(38,0)holding12, so the real pair is named instead.zero_row_suffix— Kinetica's planner constant-folds a provably false predicate and answers the query from its empty pseudo-tableSYSTEM.ITER, which cannot project aBYTEScolumn (Invalid attribute: BYTES(null) for table: SYSTEM.ITER … Unknown function: BYTES), soGetTableSchemaand theGetObjectsdescribe fallback failed outright on any table holding binary; they ask for no rows withLIMIT 0, which the planner does not fold. - Also worth knowing:
SQL_TXN_CAPABLEis 0,SQLGetTypeInfonames the temporal typesTYPE_DATE/TYPE_TIME/TYPE_TIMESTAMP(ODBC C constants, not names any DDL accepts),DATETIMEis millisecond precision,SELECT VERSION()answers with a hard-coded *PostgreSQL 9.5* banner, andUID=admin;PWD=(a non-empty user with an empty password) is refused1010 Insufficient credentialswhere omitting both connects. - Server side: the Developer Edition image needs
GPUDB_START_ALL=1or the database never starts, and it needs no GPU and no licence key; the Linux ODBC client tarball ships inside it.