Notes · 2026-08-24

What MySQL Connector/ODBC does to a DATETIME(6), and six other findings

Seven findings in MySQL Connector/ODBC 9.4, 8.4 and 26.7.1 with their exact errors - the fractional seconds pyodbc loses, a SIGFPE in get_column_size, two segfaults, and four platform traps.

Twelve entries in a compatibility matrix that drives 53 databases through one ODBC workload speak the MySQL wire protocol, and all twelve go through MySQL Connector/ODBC. Running that workload on Linux (9.4.0), Windows (8.4.0, then 26.7.1) and macOS (26.7.1) turned up seven things worth writing down.

A DATETIME(6) arrives with one fractional digit

INSERT … VALUES (?, ?)  with datetime(2024,2,29,13,45,10,123456)
SELECT CAST(ts AS CHAR) -- 2024-02-29 13:45:10.100000

Connector/ODBC 9.4 describes a DATETIME(6) result column as COLUMN_SIZE 19 / DECIMAL_DIGITS 0, and answers SQLGetTypeInfo(SQL_TYPE_TIMESTAMP) with COLUMN_SIZE 21 / MAXIMUM_SCALE 0. Neither number carries the column's real fractional precision. A client that sizes its bind from the type table — pyodbc does, 21 − 20 = one fractional digit — sends 13:45:10.123456 as 13:45:10.1. The same value as a SQL literal, or bound as a string, round-trips all six digits, and NO_SSPS=1 changes nothing: it happens on the text-substitution path too. The server is not at fault — MariaDB Connector/ODBC and SingleStore's own driver describe the column 26/6, and pyodbc is exact through SingleStore's. Filed on 2026-08-29 as mysql/mysql-connector-odbc#20; a plain-ODBC probe on 2026-09-04 added the consequence and the root cause. Bind the timestamp with an explicit scale rather than take the driver's type table at face value.

SIGFPE inside get_column_size()

SHOW VARIABLES and SHOW COLLATION against a MySQL-wire server that reports a zero character-set width — MatrixOne 4.2.0 — kill the client with SIGFPE in get_column_size() (utility.cc) during SQLExecDirect, before any fetch. The same statements against MySQL 8.4.11 are fine. Filed on 2026-08-29 with a gdb backtrace as mysql/mysql-connector-odbc#21. The only workaround is not to issue them.

SQLColumns segfaults on a NULL NUMERIC_PRECISION

MongoDB's BI Connector (mongosqld) reports NULL for NUMERIC_PRECISION, NUMERIC_SCALE and CHARACTER_OCTET_LENGTH on every column, and Connector/ODBC 9 builds SQLColumns entirely from information_schema (NO_I_S=1 is accepted and changes nothing). For a DECIMAL column it runs strtol() on that NULL pointer and the process dies — per column, not per table, so nothing in a return code separates a safe table from a fatal one. The same server's handshake segfaults too, in the bundled libmysqlclient (authsm_begin_plugin_auth, strcmp() on a NULL plugin name), when the greeting names no auth plugin and PLUGIN_DIR is unset. Both have standalone C reproductions. Point PLUGIN_DIR at the connector's own lib/plugin, and describe a zero-row SELECT rather than call SQLColumns.

Related: SQLColumns segfaults on a NULL NUMERIC_PRECISION from mongosqld

Windows: NO_SSPS=1 against every server that is not MySQL

[HY000] (2031) No data supplied for parameters in prepared statement

Connector/ODBC 8.4.0 fails at the first bound parameter against TiDB, MariaDB, Dolt, MatrixOne and OceanBase, in pyodbc identically; against MySQL itself and Percona the default works, and 26.7.1 still needs it. With NO_SSPS=1 the connector substitutes bound parameters into the statement text.

Related: A Unicode string parameter cannot reach a MySQL-wire warehouse's prepare

Windows: result sets read as 3-byte utf8

héllo 🚀 stores byte-exact and reads back as héllo ??? on every read path including pyodbc; SQL_C_CHAR and SQL_C_WCHAR both return 3f 3f 3f for the emoji, and CHARSET= makes no difference. It is a class, not five incidents: Connector/ODBC 8.4.0 decodes result sets from any MySQL-wire server that does not implement the character-set session variables as 3-byte utf8 — on Windows that is Databend, GreptimeDB, MatrixOne, StarRocks and MongoDB BI. The same driver reads 🚀 from MySQL, Percona, MariaDB, TiDB and Dolt, which expose the variables; 9.4 on Linux and 26.7.1 on Windows read them all.

Linux: the driver stops loading once something imports pyarrow

OSError: /lib/x86_64-linux-gnu/libstdc++.so.6: cannot allocate memory in static TLS block

Through unixODBC it arrives as the misleading Can't open lib '…/libmyodbc9w.so' : file not found. It is not about surplus static TLS running out. libarrow reaches libstdc++'s thread-locals through the dynamic TLS model, and the first such access to a dlopened library with no static TLS offset makes glibc record it as dynamic-TLS-only for the rest of the process' life. Connector/ODBC reaches the same thread-locals (_ZSt11__once_call, _ZSt15__once_callable) through initial-exec, which requires that offset, so after pyarrow the driver cannot be loaded at all, deterministically. import pandas and import adbc_driver_manager.dbapi both do it; import numpy does not. Load the ODBC driver before anything imports pyarrow, or preload libstdc++ from outside the process: LD_PRELOAD=/lib/x86_64-linux-gnu/libstdc++.so.6 python your_program.py. GLIBC_TUNABLES=glibc.rtld.optional_static_tls=N does not help. The analysis is in docs/TROUBLESHOOTING.md.

macOS: an iODBC driver, and its wide parameters

Connector/ODBC 26.7.1 for macOS arm64 links @rpath/libiodbcinst.dylib — it is an iODBC driver, four-byte SQLWCHAR. Loaded through unixODBC (two-byte) every call fails with an empty diagnostic, [H000] [ (0) (SQLDriverConnect), pyodbc the same; relinking is not a valid recipe. Through an iODBC-built stack it writes UTF-16 code units into the four-byte slots, surrogate pairs as two units, but does not read bound SQL_C_WCHAR parameters in four-byte units consistently — plain ASCII comes back inlined as garbage. Bind text narrow there, through UTF-8; it costs nothing measurable.

Related: Vendor macOS drivers are built for iODBC's four-byte SQLWCHAR

Where this comes from: the adbcBridge compatibility matrix runs one workload through every database's ODBC driver on Linux, macOS and Windows and records each failure with its first error; the row for this database is at https://adbcbridge.org/matrix/#mysql, and the finding is on file with its reproduction in docs/UPSTREAM.md of the repository.