jackc / jackc/pgx

database/sql: storing driver.Value type string into type *time.Time

Open
#1,574 5 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Go
Stars
14.3k
Forks
1.1k
Avg merge
6d 9h
Merged PRs (30d)
11

Description

**Describe the bug**
database/sql: unsupported Scan, storing driver.Value type string into type *time.Time

**To Reproduce**
```
CREATE TABLE vc (
ts timestamp
);
INSERT INTO vc (ts) VALUES ('infinity');
```
```go
package main

import (
"context"
"log"
"os"
"time"
"database/sql"

_ "github.com/jackc/pgx/v5/stdlib"
)

func main() {
db, err := sql.Open("pgx", os.Getenv("DATABASE_URL"))
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
defer db.Close()

rows, err := db.Query("select * from vc")
if err != nil {
t.Error(err)
return
}

for rows.Next() {
columnTypes, _ := rows.ColumnTypes()
for _, ct := range columnTypes {
fmt.Println(ct.ScanType().Name())
}
ts := time.Time{}
err = rows.Scan(&ts)
if err != nil {
t.Error(err)
}
fmt.Println(ts)
}
}
```

**Expected behavior**
Return without error.

**Actual behavior**
Error in rows.Scan: unsupported Scan, storing driver.Value type string into type *time.Time

This is actually a simplify demo when using gorm library and pgx as driver, the default column type in go for timestamp is time.Time, but when the timestamp value set to infinity, the actual driver.Value is string type, hence the scan error happened.
I think this is a problem about how to represent infinity value in time.Time.
For code reference: https://github.com/jackc/pgx/blob/master/pgtype/timestamp.go#L58
**Version**
- Go: go version go1.19.6 darwin/amd64
- PostgreSQL: PostgreSQL 14.5 (Debian 14.5-2.pgdg110+2) on x86_64-pc-linux-gnu, compiled by gc
c (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
- pgx: v5.3.0

**Additional context**
Add any other context about the problem here.

Contributor guide

Open the contributing guide

Research direction

The report points to pgtype/timestamp.go and reproduces the problem with a PostgreSQL timestamp containing "infinity" scanned through database/sql into *time.Time. Start by reproducing that query and reading the referenced timestamp conversion path; done means the intended infinity behavior is defined and the scan no longer errors, with a regression test covering it.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, postgresql
Domain
database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.