summaryrefslogtreecommitdiffstats
path: root/sqlr_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'sqlr_test.go')
-rw-r--r--sqlr_test.go158
1 files changed, 158 insertions, 0 deletions
diff --git a/sqlr_test.go b/sqlr_test.go
new file mode 100644
index 0000000..4323f11
--- /dev/null
+++ b/sqlr_test.go
@@ -0,0 +1,158 @@
+package sqlr
+
+import (
+ "context"
+ "database/sql"
+ "github.com/google/go-cmp/cmp"
+ _ "github.com/mattn/go-sqlite3"
+ "reflect"
+ "testing"
+)
+
+func TestScan(t *testing.T) {
+ ctx := context.Background()
+
+ for _, tc := range []struct {
+ desc string
+ db string
+ query string
+ want any
+ }{{
+ desc: "match field names",
+ db: `
+ CREATE TABLE Tbl (ColA, ColB);
+ INSERT INTO Tbl VALUES (100, "test")`,
+ query: "SELECT ColA, ColB FROM Tbl",
+ want: &struct {
+ ColA int
+ ColB string
+ }{100, "test"},
+ }, {
+ desc: "select star",
+ db: `
+ CREATE TABLE Tbl (ColA, ColB);
+ INSERT INTO Tbl VALUES (100, "test")`,
+ query: "SELECT * FROM Tbl",
+ want: &struct {
+ ColA int
+ ColB string
+ }{100, "test"},
+ }, {
+ desc: "ignored field",
+ db: `
+ CREATE TABLE Tbl (Col);
+ INSERT INTO Tbl VALUES (100)`,
+ query: "SELECT Col FROM Tbl",
+ want: &struct{ Col, OtherField int }{Col: 100},
+ }, {
+ desc: "tag",
+ db: `
+ CREATE TABLE Tbl (col_a, col_b);
+ INSERT INTO Tbl VALUES (100, "test")`,
+ query: "SELECT col_a, col_b FROM Tbl",
+ want: &struct {
+ ColA int `sql:"col_a"`
+ ColB string `sql:"col_b"`
+ }{100, "test"},
+ }} {
+ t.Run(tc.desc, func(t *testing.T) {
+ db, err := sql.Open("sqlite3", ":memory:")
+ if err != nil {
+ t.Fatalf("Failed to create in-memory database: %s", err)
+ }
+ defer db.Close()
+ if _, err := db.ExecContext(ctx, tc.db); err != nil {
+ t.Fatalf("Failed to initialize test database: %s", err)
+ }
+
+ rows, err := db.QueryContext(ctx, tc.query)
+ if err != nil {
+ t.Fatalf("Failed to query test database: %s", err)
+ }
+ if !rows.Next() {
+ t.Fatalf("No data")
+ }
+
+ got := reflect.New(reflect.TypeOf(tc.want).Elem()).Interface()
+ if err := Scan(rows, got); err != nil {
+ t.Fatalf("Scan failed: %s", err)
+ }
+ if err := rows.Close(); err != nil {
+ t.Fatalf("Close rows: %s", err)
+ }
+ if err := rows.Err(); err != nil {
+ t.Fatalf("Database read error: %s", err)
+ }
+
+ if diff := cmp.Diff(tc.want, got); diff != "" {
+ t.Errorf("Scan returned unexpected diff (-want +got):\n%s", diff)
+ }
+ })
+ }
+}
+
+func TestScan_Errors(t *testing.T) {
+ ctx := context.Background()
+
+ for _, tc := range []struct {
+ desc string
+ db string
+ query string
+ out any
+ }{{
+ desc: "wrong type",
+ db: `
+ CREATE TABLE Tbl (Col);
+ INSERT INTO Tbl VALUES (100)`,
+ query: "SELECT Col FROM Tbl",
+ out: 5,
+ }, {
+ desc: "nil pointer",
+ db: `
+ CREATE TABLE Tbl (Col);
+ INSERT INTO Tbl VALUES (100)`,
+ query: "SELECT Col FROM Tbl",
+ out: nil,
+ }, {
+ desc: "no field",
+ db: `
+ CREATE TABLE Tbl (ColA, ColB);
+ INSERT INTO Tbl VALUES (100, "test")`,
+ query: "SELECT ColA, ColB FROM Tbl",
+ out: new(struct{ ColA int }),
+ }, {
+ desc: "ignored field",
+ db: `
+ CREATE TABLE Tbl (Col);
+ INSERT INTO Tbl VALUES (100)`,
+ query: "SELECT Col FROM Tbl",
+ out: new(struct {
+ Col int `sql:"-"`
+ }),
+ }} {
+ t.Run(tc.desc, func(t *testing.T) {
+ db, err := sql.Open("sqlite3", ":memory:")
+ if err != nil {
+ t.Fatalf("Failed to create in-memory database: %s", err)
+ }
+ defer db.Close()
+ if _, err := db.ExecContext(ctx, tc.db); err != nil {
+ t.Fatalf("Failed to initialize test database: %s", err)
+ }
+
+ rows, err := db.QueryContext(ctx, tc.query)
+ if err != nil {
+ t.Fatalf("Failed to query test database: %s", err)
+ }
+ defer rows.Close()
+ if !rows.Next() {
+ t.Fatalf("No data")
+ }
+
+ err = Scan(rows, tc.out)
+ if err == nil {
+ t.Errorf("Scan returned nil, want error")
+ }
+ })
+ }
+}