Skip to content

Fix stdlib to return time.Time for PostgreSQL time columns#2528

Open
abrightwell wants to merge 1 commit intojackc:masterfrom
abrightwell:abrightwell-time-type
Open

Fix stdlib to return time.Time for PostgreSQL time columns#2528
abrightwell wants to merge 1 commit intojackc:masterfrom
abrightwell:abrightwell-time-type

Conversation

@abrightwell
Copy link
Copy Markdown
Contributor

@abrightwell abrightwell commented Apr 3, 2026

The TimeOID case was missing from the stdlib Rows.Next() switch, causing time columns to fall through to the default case. The default case scans into a string, which is not a valid driver.Value for temporal types. When database/sql attempts to assign the resulting string to a *time.Time scan destination, it fails with:

sql: Scan error on column index 0, name "t": unsupported Scan, storing
driver.Value type string into type *time.Time

To fix this, a TimeOID case is added that scans into pgtype.Time and converts microseconds since midnight to time.Time, matching the existing conversion in timeWrapper.ScanTime
(pgtype/builtin_wrappers.go).

Fixes: #2508

The `TimeOID` case was missing from the stdlib `Rows.Next()` switch,
causing `time` columns to fall through to the `default` case. The
`default` case scans into a `string`, which is not a valid
`driver.Value` for temporal types. When `database/sql` attempts to
assign the resulting `string` to a `*time.Time` scan destination,
it fails with:

```
sql: Scan error on column index 0, name "t": unsupported Scan, storing
driver.Value type string into type *time.Time
```

To fix this, a `TimeOID` case is added that scans into `pgtype.Time` and
converts microseconds since midnight to `time.Time`, matching the
existing conversion in `timeWrapper.ScanTime`
(`pgtype/builtin_wrappers.go`).
@abrightwell
Copy link
Copy Markdown
Contributor Author

As mentioned in #2508, the only potential concern is that those who are currently scanning into a string would see different values. The time would be correct, but it would not be the same string.

For instance:

Before: "22:45:00"
After: "2000-01-01T22:45:00Z"

@jackc
Copy link
Copy Markdown
Owner

jackc commented Apr 3, 2026

As mentioned in #2508, the only potential concern is that those who are currently scanning into a string would see different values. The time would be correct, but it would not be the same string.

For instance:

Before: "22:45:00" After: "2000-01-01T22:45:00Z"

I know you mentioned a string issue before, but it didn't quite register with me. That is a bigger incompatibility than I realized. If I understand correctly, there would no longer be anyway to get the actual text aside from casting to text in your SQL query. That would be unfortunate. Worse, a value like 24:00:00 might not work at all. This isn't a problem with the native pgx interface because it knows the source and destination types. With database/sql everything has to go through driver.Value without knowledge of where it will end up.

We already have a few of these edge cases, like for Infinity, but I'm not sure that we should add more.

It's unfortunate that golang/go#67546 is still pending. Whenever it is finally resolved that will solve all these issues.

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.

Can persist an entity, but get am error, when reading using sqlx

2 participants