Created
January 11, 2023 06:19
-
-
Save C-Pro/56733cf720a0cc83119320ba8da185c7 to your computer and use it in GitHub Desktop.
Missing NullUint64 implementation (for pgx driver)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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