Skip to content

Instantly share code, notes, and snippets.

@C-Pro
Created January 11, 2023 06:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save C-Pro/56733cf720a0cc83119320ba8da185c7 to your computer and use it in GitHub Desktop.
Save C-Pro/56733cf720a0cc83119320ba8da185c7 to your computer and use it in GitHub Desktop.
Missing NullUint64 implementation (for pgx driver)
package main
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"strconv"
"time"
_ "github.com/jackc/pgx/v5/stdlib"
_ "github.com/lib/pq"
)
type NullUint64 struct {
Uint64 uint64
Valid bool
}
func (n *NullUint64) Scan(value any) error {
if value == nil {
n.Uint64 = 0
n.Valid = false
return nil
}
s, ok := value.(string)
if !ok {
return fmt.Errorf("NullUint64.Scan got wrong type: %T", value)
}
var err error
n.Uint64, err = strconv.ParseUint(s, 10, 64)
if err != nil {
return fmt.Errorf("NullUint64.Scan parse failed: %w", err)
}
n.Valid = true
return nil
}
// Won't work with standard drivers like `lib/pq` that does not support uint types.
func (n NullUint64) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.Uint64, nil
}
func main() {
// change pgx to postgres to switch to lib/pg driver (will fail to insert)
db, err := sql.Open("pgx", "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable")
if err != nil {
panic(err)
}
defer db.Close()
val := NullUint64{^uint64(0), true}
fmt.Println(val.Uint64)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
tx, err := db.BeginTx(ctx, nil)
if err != nil {
panic(err)
}
defer tx.Rollback()
if _, err := tx.Exec("create table ttt (x numeric(30))"); err != nil {
panic(err)
}
// actually can still make it work with lib/pq to like this:
// tx.Exec("insert into ttt values($1::numeric)", strconv.FormatUint(val,10))
if _, err := tx.Exec("insert into ttt values($1)", val); err != nil {
panic(err)
}
var got NullUint64
if err := tx.QueryRow("select x from ttt limit 1").Scan(&got); err != nil {
panic(err)
}
fmt.Println(got.Uint64)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment