Skip to content

fix(sqlx): write time.Time in a MySQL-compatible format#5517

Open
kayoch1n wants to merge 4 commits into
zeromicro:masterfrom
kayoch1n:bugfix/sqlx-write-value-of-time
Open

fix(sqlx): write time.Time in a MySQL-compatible format#5517
kayoch1n wants to merge 4 commits into
zeromicro:masterfrom
kayoch1n:bugfix/sqlx-write-value-of-time

Conversation

@kayoch1n

@kayoch1n kayoch1n commented Mar 28, 2026

Copy link
Copy Markdown

Fixes issue #5515: the bulk inserter used Time.String() to convert variables of type time.Time into strings. Time.String() returns a string in the format "2006-01-02 15:04:05.999999999 -0700 MST" that is not accepted by MySQL.

To fix this problem, use Time.Format() to convert time.Time into string.

Changes:

  • core/stores/sqlx/utils.go: convert time variables into strings using a MySQL-compatible format
  • core/stores/sqlx/utils_test.go: modify assertions and add a nil pointer case

All unittest cases passed. This change only affects bulk inserter and loggings.

@codecov

codecov Bot commented Mar 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@kevwan kevwan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! The core change is correct — Time.String() produces a format MySQL rejects while Time.Format(time.DateTime) produces standard SQL format.

However, time.DateTime ("2006-01-02 15:04:05") truncates to second-level precision. Since writeValue is called from BulkInserter where the formatted value is actually executed as SQL, this would silently discard sub-second data. MySQL DATETIME(6) and TIMESTAMP(6) support microsecond precision.

Please consider using a format that preserves microseconds instead:

v.Format("2006-01-02 15:04:05.999999")

The .999999 pattern in Go's time formatting trims trailing zeros, so it produces clean output (2026-03-28 17:26:54.88284) while preserving precision when present. This is MySQL-compatible.

Comment thread core/stores/sqlx/utils.go Outdated
Comment thread core/stores/sqlx/utils.go Outdated
@kayoch1n kayoch1n force-pushed the bugfix/sqlx-write-value-of-time branch from da33846 to 94c3265 Compare March 28, 2026 15:04
@kayoch1n kayoch1n requested a review from kevwan March 28, 2026 15:08
@kayoch1n kayoch1n changed the title fix(sqlx): write time.Time in time.DateTime format fix(sqlx): write time.Time in a MySQL-compatible format Mar 30, 2026
@kayoch1n kayoch1n force-pushed the bugfix/sqlx-write-value-of-time branch from 94c3265 to bb00076 Compare April 15, 2026 11:51
@kevwan kevwan added kind/bug Something isn't working area/orm Categorizes issue or PR as related to orm. area/core labels Apr 30, 2026
@kevwan

kevwan commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Review

Clean and correct fix for the BulkInserter time.Time serialization bug (#5515).

Analysis:

time.Time.String() produces a Go-specific representation ("2006-01-02 15:04:05.999999999 -0700 MST m=+...") that MySQL rejects. Using time.Format("2006-01-02 15:04:05.999999") produces a MySQL-compatible datetime format.

Code quality:

  • ✅ The format constant timeFormat = "2006-01-02 15:04:05.999999" is well-chosen — uses Go reference time, includes microsecond precision (999999 trailing zeros are omitted)
  • ✅ Added nil-pointer handling for *time.Time — previously this would have been a nil dereference panic or wrong output
  • ✅ Tests updated with table-driven subtests

One question — timezone handling: time.Format() formats using the time's location. If the time.Time value is in a non-UTC timezone, the formatted string won't include timezone info. MySQL will interpret the timestamp in the server's session timezone. This is consistent with how github.com/go-sql-driver/mysql handles time (with parseTime=true), but worth documenting. Users should ensure their time.Time values use the correct timezone before inserting.

Suggestion (non-blocking): Consider using v.UTC().Format(timeFormat) or at least document the timezone behavior — but this is a judgment call and not a correctness issue for most users.

LGTM — this is a clear bug fix with no downside.

@kayoch1n kayoch1n force-pushed the bugfix/sqlx-write-value-of-time branch from 8fea813 to b361de0 Compare May 30, 2026 04:01
@kayoch1n kayoch1n force-pushed the bugfix/sqlx-write-value-of-time branch from b361de0 to 27ed099 Compare June 12, 2026 06:13
@kayoch1n kayoch1n force-pushed the bugfix/sqlx-write-value-of-time branch 3 times, most recently from 8b5113e to 3ee9aa2 Compare June 27, 2026 07:49
@kayoch1n kayoch1n force-pushed the bugfix/sqlx-write-value-of-time branch from 3ee9aa2 to d37c7a7 Compare July 1, 2026 01:33
@kayoch1n

kayoch1n commented Jul 8, 2026

Copy link
Copy Markdown
Author

@kevwan Hi, could you please have a look at this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core area/orm Categorizes issue or PR as related to orm. kind/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants