Skip to content

Commit

Permalink
WIP.
Browse files Browse the repository at this point in the history
  • Loading branch information
efritz committed Sep 12, 2024
1 parent 1142098 commit 2c8613d
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 21 deletions.
33 changes: 12 additions & 21 deletions db_transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestTransaction(t *testing.T) {

// Add record outside of transaction, ensure it's visible
err := db.Exec(context.Background(), Query(
`INSERT INTO test VALUES (1, 42)`,
`INSERT INTO test (x, y) VALUES (1, 42)`,
Args{},
))
require.NoError(t, err)
Expand All @@ -28,7 +28,7 @@ func TestTransaction(t *testing.T) {
tx1, err := db.Transact(context.Background())
require.NoError(t, err)
err = tx1.Exec(context.Background(), Query(
`INSERT INTO test VALUES (2, 43)`,
`INSERT INTO test (x, y) VALUES (2, 43)`,
Args{},
))
require.NoError(t, err)
Expand All @@ -37,7 +37,7 @@ func TestTransaction(t *testing.T) {
tx2, err := db.Transact(context.Background())
require.NoError(t, err)
err = tx2.Exec(context.Background(), Query(
`INSERT INTO test VALUES (3, 44)`,
`INSERT INTO test (x, y) VALUES (3, 44)`,
Args{},
))
require.NoError(t, err)
Expand Down Expand Up @@ -83,7 +83,7 @@ func TestConcurrentTransactions(t *testing.T) {
}

return tx.Exec(context.Background(), Query(
`INSERT INTO test VALUES ({:routine}, {:routine})`,
`INSERT INTO test (x, y) VALUES ({:routine}, {:routine})`,
Args{"routine": routine},
))
})
Expand Down Expand Up @@ -118,7 +118,7 @@ func TestConcurrentTransactions(t *testing.T) {
}

return tx.Exec(context.Background(), Query(
`INSERT INTO test VALUES ({:routine}, {:routine})`,
`INSERT INTO test (x, y) VALUES ({:routine}, {:routine})`,
Args{"routine": routine},
))
})
Expand Down Expand Up @@ -168,7 +168,7 @@ func recurSavepoints(t *testing.T, db DB, index, rollbackAt int) {
}()

require.NoError(t, tx.Exec(context.Background(), Query(
`INSERT INTO test VALUES ({:index}, {:index} * 2)`,
`INSERT INTO test (x, y) VALUES ({:index}, {:index} * 2)`,
Args{"index": index},
)))

Expand All @@ -178,34 +178,25 @@ func recurSavepoints(t *testing.T, db DB, index, rollbackAt int) {
func setupTestTransactionTable(t *testing.T, db DB) {
require.NoError(t, db.Exec(context.Background(), Query(`
CREATE TABLE test (
id SERIAL PRIMARY KEY,
value INTEGER
id SERIAL PRIMARY KEY,
x INTEGER NOT NULL,
y INTEGER NOT NULL
);
`,
Args{},
)))
}

type testPair struct {
id int
value int
}

var testPairScanner = NewSliceScanner(func(s Scanner) (p testPair, _ error) {
err := s.Scan(&p.id, &p.value)
return p, err
})

func testTableContents(t *testing.T, db DB) map[int]int {
pairs, err := testPairScanner(db.Query(context.Background(), Query(
`SELECT id, value FROM test`,
pairs, err := scanTestPairs(db.Query(context.Background(), Query(
`SELECT x, y FROM test`,
Args{},
)))
require.NoError(t, err)

pairsMap := make(map[int]int)
for _, p := range pairs {
pairsMap[p.id] = p.value
pairsMap[p.x] = p.y
}

return pairsMap
Expand Down
157 changes: 157 additions & 0 deletions rows_slice_scanner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package pgutil

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestSliceScanner(t *testing.T) {
t.Run("scalar values", func(t *testing.T) {
values, err := ScanInts(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1), (2), (3)) AS t(number)`,
Args{},
)))

require.NoError(t, err)
assert.Equal(t, []int{1, 2, 3}, values)
})

t.Run("custom struct values", func(t *testing.T) {
values, err := scanTestPairs(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1,2), (2,3), (3,4)) AS t(x,y)`,
Args{},
)))

require.NoError(t, err)
assert.Equal(t, []testPair{{1, 2}, {2, 3}, {3, 4}}, values)
})

t.Run("no values", func(t *testing.T) {
values, err := ScanInts(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1), (2), (3)) AS t(number) LIMIT 0`,
Args{},
)))

require.NoError(t, err)
assert.Empty(t, values)
})
}

func TestMaybeSliceScanner(t *testing.T) {
values, err := scanMaybeTestPairs(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1,2), (2,3), (0,0), (3,4)) AS t(x,y)`,
Args{},
)))

require.NoError(t, err)
assert.Equal(t, []testPair{{1, 2}, {2, 3}}, values)
}

func TestFirstScanner(t *testing.T) {
t.Run("scalar value", func(t *testing.T) {
value, ok, err := ScanInt(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1)) AS t(number)`,
Args{},
)))

require.NoError(t, err)
assert.True(t, ok)
assert.Equal(t, 1, value)
})

t.Run("scalar value (ignores non-first values)", func(t *testing.T) {
value, ok, err := ScanInt(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1), (2), (3)) AS t(number)`,
Args{},
)))

require.NoError(t, err)
assert.True(t, ok)
assert.Equal(t, 1, value)
})

t.Run("custom struct value", func(t *testing.T) {
value, ok, err := scanFirstTestPair(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1,2)) AS t(x,y)`,
Args{},
)))

require.NoError(t, err)
assert.True(t, ok)
assert.Equal(t, testPair{1, 2}, value)
})

t.Run("no value", func(t *testing.T) {
_, ok, err := ScanInt(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1), (2), (3)) AS t(number) LIMIT 0`,
Args{},
)))

require.NoError(t, err)
assert.False(t, ok)
})
}

func TestMaybeFirstScanner(t *testing.T) {
t.Run("custom struct value", func(t *testing.T) {
value, ok, err := scanMaybeFirstTestPair(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (1,2)) AS t(x,y)`,
Args{},
)))

require.NoError(t, err)
assert.True(t, ok)
assert.Equal(t, testPair{1, 2}, value)
})

t.Run("rejected value", func(t *testing.T) {
type testPair struct {
x int
y int
}
scanner := NewMaybeFirstScanner(func(s Scanner) (p testPair, _ bool, _ error) {
err := s.Scan(&p.x, &p.y)
return p, p.x != 0 && p.y != 0, err
})

_, ok, err := scanner(NewTestDB(t).Query(context.Background(), Query(
`SELECT * FROM (VALUES (0,0), (1,2)) AS t(x,y)`,
Args{},
)))

require.NoError(t, err)
assert.False(t, ok)
})
}

//
//
//

type testPair struct {
x int
y int
}

var scanTestPairs = NewSliceScanner(func(s Scanner) (p testPair, _ error) {
err := s.Scan(&p.x, &p.y)
return p, err
})

var scanMaybeTestPairs = NewMaybeSliceScanner(func(s Scanner) (p testPair, _ bool, _ error) {
err := s.Scan(&p.x, &p.y)
return p, p.x != 0 && p.y != 0, err
})

var scanFirstTestPair = NewFirstScanner(func(s Scanner) (p testPair, _ error) {
err := s.Scan(&p.x, &p.y)
return p, err
})

var scanMaybeFirstTestPair = NewMaybeFirstScanner(func(s Scanner) (p testPair, _ bool, _ error) {
err := s.Scan(&p.x, &p.y)
return p, p.x != 0 && p.y != 0, err
})
27 changes: 27 additions & 0 deletions rows_value_scanner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package pgutil

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestCollector(t *testing.T) {
db := NewTestDB(t)
collector := NewCollector[int](NewAnyValueScanner[int]())
scanner := NewRowScanner(collector.Scanner())

require.NoError(t, scanner(db.Query(context.Background(), Query(
`SELECT * FROM (VALUES (1), (2), (3)) AS t(number)`,
Args{},
))))

require.NoError(t, scanner(db.Query(context.Background(), Query(
`SELECT * FROM (VALUES (4), (5), (6)) AS t(number)`,
Args{},
))))

assert.Equal(t, []int{1, 2, 3, 4, 5, 6}, collector.Slice())
}

0 comments on commit 2c8613d

Please sign in to comment.