Skip to content

Bind DateTime parameters as DATETIME so MariaDB keeps pre-1970 values - #252

Merged
quinnj-bot[bot] merged 1 commit into
mainfrom
claude/datetime-param-type
Oct 30, 2026
Merged

quinnj-bot[bot] merged 1 commit into
mainfrom
claude/datetime-param-type

Conversation

@quinnj-bot

@quinnj-bot quinnj-bot Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

On MariaDB, a DateTime parameter before 1970 or after 2106 is stored as NULL. There is no warning, even in strict mode. This affects prepared execute, execute(conn, sql, params), executemany, and MySQL.load of a DateTime column. MySQL is not affected.

Cause: DateTime parameters were sent as MYSQL_TYPE_TIMESTAMP, which was the 1.x mapping. MariaDB applies the TIMESTAMP range to a TIMESTAMP-typed parameter and turns values outside it into NULL, even when the target column is DATETIME. Timestamp{P} parameters already used MYSQL_TYPE_DATETIME and were correct.

Fix: bind DateTime as MYSQL_TYPE_DATETIME, the same as Timestamp.

Before (MariaDB 11.4.13 and 11.8.9, column DATETIME(3)):

prepared insert DateTime(1969,12,31,23,59,59), DateTime(1970,1,1,0,0,1), DateTime(2020,6,1,12,30,45,123), DateTime(2200,1,1), DateTime(1000,1,1)
  -> [NULL, 1970-01-01T00:00:01, 2020-06-01T12:30:45.123, NULL, NULL]
MySQL.load((id=[1, 2], born=[DateTime(1955,3,4), DateTime(1990,1,1)]), conn, "t")
  -> [NULL, 1990-01-01T00:00:00]

After: every value reads back unchanged on MariaDB 11.4.13, MariaDB 11.8.9, and MySQL 8.4.13.

Checks:

  • TIMESTAMP columns store the same instant with either parameter type. I checked this on both servers with session time_zone = '+05:30', using UNIX_TIMESTAMP of the stored value.
  • WHERE dt = ? with an out-of-range DateTime matched correctly before the fix, so only stored values were affected.
  • New test in test/user_workflow.jl, which runs on both live lanes. It inserts DateTime values from 1955, 1969, and 2200 with executemany and with MySQL.load, then reads them back. Without the fix it fails 2 tests on MariaDB 11.4 and 11.8 (all three values read back missing). With the fix it passes on all three servers. The serverless signature test now expects MYSQL_TYPE_DATETIME.
  • Full Pkg.test() locally on Julia 1.12.6, with Docker lanes mysql:8 (8.4.13) and mariadb:11.4, the integration tests, and the --trim=safe build: 2294/2294 passed.

Found by a differential comparison of MySQL.jl against PyMySQL and an independent binary-protocol decoder, on MySQL 8.4 and MariaDB 11.8. Every type was checked through text and binary, buffered and streaming paths. This was the only value mismatch.

🤖 Generated with Claude Code

MariaDB stores NULL for a MYSQL_TYPE_TIMESTAMP parameter outside the
TIMESTAMP range (before 1970 or after 2106), even in a DATETIME column,
without a warning and in strict mode. DateTime parameters (and so
MySQL.load of DateTime columns) silently lost every such value on
MariaDB 11.4 and 11.8. Timestamp parameters already used
MYSQL_TYPE_DATETIME; MySQL treats both types the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@quinnj-bot
quinnj-bot Bot merged commit 27b0893 into main Oct 30, 2026
17 checks passed
@quinnj-bot
quinnj-bot Bot deleted the claude/datetime-param-type branch October 30, 2026 14:15
@quinnj-bot quinnj-bot Bot mentioned this pull request Oct 30, 2026
quinnj referenced this pull request Oct 30, 2026
Co-authored-by: Jacob Quinn <quinn.jacobd@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant