Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed numeric merging options #74

Merged
merged 2 commits into from
Nov 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go: ["1.18"]
go: ["1.19"]
steps:
- name: Set up Go ${{ matrix.go }}
uses: actions/setup-go@v3
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ Now that we have a record implementation, we can create a column for this struct
```go
players.CreateColumn("location", ForRecord(func() *Location {
return new(Location)
}, nil)) // no merging
}))
```

In order to manipulate the record, we can use the appropriate `Record()`, `SetRecord()` methods of the `Row`, similarly to other column types.
Expand Down
2 changes: 1 addition & 1 deletion codegen/numbers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func make{{.Name}}s(opts ...func(*option[{{.Type}}])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down
5 changes: 2 additions & 3 deletions collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ func BenchmarkRecord(b *testing.B) {
col := NewCollection()
col.CreateColumn("ts", ForRecord(func() *time.Time {
return new(time.Time)
}, nil))
}))

for i := 0; i < amount; i++ {
col.Insert(func(r Row) error {
Expand Down Expand Up @@ -247,7 +247,6 @@ func BenchmarkRecord(b *testing.B) {
})
}
})

}

func TestCollection(t *testing.T) {
Expand Down Expand Up @@ -802,7 +801,7 @@ func newEmpty(capacity int) *Collection {
out.CreateColumn("guild", ForEnum())
out.CreateColumn("location", ForRecord(func() *fixtures.Location {
return new(fixtures.Location)
}, nil))
}))

// index on humans
out.CreateIndex("human", "race", func(r Reader) bool {
Expand Down
2 changes: 1 addition & 1 deletion column.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func ForKind(kind reflect.Kind) (Column, error) {

// --------------------------- Generic Options ----------------------------

// optInt represents options for variouos columns.
// option represents options for variouos columns.
type option[T any] struct {
Merge func(value, delta T) T
}
Expand Down
20 changes: 10 additions & 10 deletions column_numbers.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func makeInts(opts ...func(*option[int])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -78,7 +78,7 @@ func makeInt16s(opts ...func(*option[int16])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -127,7 +127,7 @@ func makeInt32s(opts ...func(*option[int32])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -176,7 +176,7 @@ func makeInt64s(opts ...func(*option[int64])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -225,7 +225,7 @@ func makeUints(opts ...func(*option[uint])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -274,7 +274,7 @@ func makeUint16s(opts ...func(*option[uint16])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -323,7 +323,7 @@ func makeUint32s(opts ...func(*option[uint32])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -372,7 +372,7 @@ func makeUint64s(opts ...func(*option[uint64])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -421,7 +421,7 @@ func makeFloat32s(opts ...func(*option[float32])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down Expand Up @@ -470,7 +470,7 @@ func makeFloat64s(opts ...func(*option[float64])) Column {
fill.Remove(offset)
}
}
},
}, opts,
)
}

Expand Down
2 changes: 1 addition & 1 deletion column_numeric.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type numericColumn[T simd.Number] struct {
func makeNumeric[T simd.Number](
write func(*commit.Buffer, uint32, T),
apply func(*commit.Reader, bitmap.Bitmap, []T, option[T]),
opts ...func(*option[T]),
opts []func(*option[T]),
) *numericColumn[T] {
return &numericColumn[T]{
chunks: make(chunks[T], 0, 4),
Expand Down
14 changes: 6 additions & 8 deletions column_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ type columnRecord struct {
// ForRecord creates a new column that contains a type marshaled into/from binary. It requires
// a constructor for the type as well as optional merge function. If merge function is
// set to nil, "overwrite" strategy will be used.
func ForRecord[T recordType](new func() T, merge func(value, delta T) T) Column {
if merge == nil {
merge = func(value, delta T) T { return delta }
}
func ForRecord[T recordType](new func() T, opts ...func(*option[T])) Column {
mergeFunc := configure(opts, option[T]{
Merge: func(value, delta T) T { return delta },
}).Merge

pool := &sync.Pool{
New: func() any { return new() },
Expand All @@ -52,10 +52,8 @@ func ForRecord[T recordType](new func() T, merge func(value, delta T) T) Column
return v
}

// Apply the user-defined merging strategy
merged := merge(value, delta)

// Marshal the value back
// Apply the user-defined merging strategy and marshal it back
merged := mergeFunc(value, delta)
if encoded, err := merged.MarshalBinary(); err == nil {
return b2s(&encoded)
}
Expand Down
35 changes: 31 additions & 4 deletions column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ func TestRecord(t *testing.T) {
col := NewCollection()
col.CreateColumn("ts", ForRecord(func() *time.Time {
return new(time.Time)
}, nil))
}))

// Insert the time, it implements binary marshaler
idx, _ := col.Insert(func(r Row) error {
Expand Down Expand Up @@ -609,7 +609,7 @@ func TestRecord_Errors(t *testing.T) {
col.CreateColumn("id", ForInt64())
col.CreateColumn("ts", ForRecord(func() *time.Time {
return new(time.Time)
}, nil))
}))

// Column "xxx" does not exist
assert.Panics(t, func() {
Expand Down Expand Up @@ -643,7 +643,7 @@ func TestRecordMerge_ErrDecode(t *testing.T) {
return mockRecord{
errDecode: true,
}
}, nil))
}))

// Insert the time, it implements binary marshaler
idx, _ := col.Insert(func(r Row) error {
Expand All @@ -664,7 +664,7 @@ func TestRecordMerge_ErrEncode(t *testing.T) {
return mockRecord{
errEncode: true,
}
}, nil))
}))

// Insert the time, it implements binary marshaler
idx, _ := col.Insert(func(r Row) error {
Expand All @@ -679,6 +679,33 @@ func TestRecordMerge_ErrEncode(t *testing.T) {
})
}

func TestNumberMerge(t *testing.T) {
col := NewCollection()
col.CreateColumn("age", ForInt32(WithMerge(func(v, d int32) int32 {
v -= d
return v
})))

// Insert the time, it implements binary marshaler
idx, _ := col.Insert(func(r Row) error {
r.SetInt32("age", 10)
return nil
})

for i := 0; i < 10; i++ {
col.QueryAt(idx, func(r Row) error {
r.MergeInt32("age", 1)
return nil
})
}

col.QueryAt(idx, func(r Row) error {
age, _ := r.Int32("age")
assert.Equal(t, int32(0), age)
return nil
})
}

func invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
inputs := make([]reflect.Value, len(args))
for i := range args {
Expand Down
14 changes: 14 additions & 0 deletions commit/buffer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,17 @@ func TestBufferReadFromFailures(t *testing.T) {
assert.Error(t, err)
}
}

func FuzzBufferString(f *testing.F) {
f.Add(uint32(1), "test")

f.Fuzz(func(t *testing.T, i uint32, v string) {
buf := NewBuffer(0)
buf.PutString(Put, i, v)

r := NewReader()
r.Seek(buf)
assert.True(t, r.Next())
assert.Equal(t, v, r.String())
})
}
2 changes: 1 addition & 1 deletion examples/simple/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func main() {
players.CreateColumn("guild", column.ForEnum())
players.CreateColumn("location", column.ForRecord(func() *Location {
return new(Location)
}, nil))
}))

// index on humans
players.CreateIndex("human", "race", func(r column.Reader) bool {
Expand Down
37 changes: 37 additions & 0 deletions txn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,43 @@ import (
"github.com/stretchr/testify/assert"
)

func FuzzInsert(f *testing.F) {
players := newEmpty(10)
defer players.Close()

f.Add("name", true, 30, 7.5)
f.Fuzz(func(t *testing.T, name string, active bool, age int, balance float64) {

idx, err := players.Insert(func(r Row) error {
r.SetString("name", name)
r.SetBool("active", active)
r.SetInt("age", age)
r.SetFloat64("balance", balance)
return nil
})

assert.NoError(t, err)
assert.NoError(t, players.QueryAt(idx, func(r Row) error {
assert.Equal(t, active, r.Bool("active"))

s, ok := r.String("name")
assert.True(t, ok)
assert.Equal(t, name, s)

i, ok := r.Int("age")
assert.True(t, ok)
assert.Equal(t, age, i)

f, ok := r.Float64("balance")
assert.True(t, ok)
assert.Equal(t, balance, f)
return nil
}))

assert.True(t, players.DeleteAt(idx))
})
}

func TestFind(t *testing.T) {
players := loadPlayers(500)
count := 0
Expand Down