You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by we...@apache.org on 2018/12/17 16:09:37 UTC
[arrow] branch master updated: ARROW-3674: [Go] Implement Date32
and Date64 array types
This is an automated email from the ASF dual-hosted git repository.
wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push:
new a236464 ARROW-3674: [Go] Implement Date32 and Date64 array types
a236464 is described below
commit a236464551df9427af3f5750a1630100d086d178
Author: Dustin Long <me...@dustmop.io>
AuthorDate: Mon Dec 17 10:09:30 2018 -0600
ARROW-3674: [Go] Implement Date32 and Date64 array types
Implement both Date32 and Date64 types for arrays. Also resolves ARROW-3675. Unit tests follow the same pattern as the existing float64 and Time{32,64} tests.
Author: Dustin Long <me...@dustmop.io>
Closes #3170 from dustmop/date-types and squashes the following commits:
29ae27474 <Dustin Long> ARROW-3674: Date{32,64} as primitive fixed-width types, not parametric
07a261047 <Dustin Long> ARROW-3674: Implement Date32 and Date64 array types
---
go/arrow/array/array.go | 4 +-
go/arrow/array/numeric.gen.go | 90 ++++++++++
go/arrow/array/numeric_test.go | 220 ++++++++++++++++++++++++
go/arrow/array/numericbuilder.gen.go | 270 ++++++++++++++++++++++++++++++
go/arrow/array/numericbuilder_test.go | 220 ++++++++++++++++++++++++
go/arrow/datatype_fixedwidth.go | 2 +
go/arrow/datatype_numeric.gen.go | 16 ++
go/arrow/datatype_numeric.gen.go.tmpldata | 10 ++
go/arrow/numeric.tmpldata | 20 ++-
go/arrow/type_traits_numeric.gen.go | 98 +++++++++++
10 files changed, 947 insertions(+), 3 deletions(-)
diff --git a/go/arrow/array/array.go b/go/arrow/array/array.go
index b188dcd..ef37aef 100644
--- a/go/arrow/array/array.go
+++ b/go/arrow/array/array.go
@@ -180,8 +180,8 @@ func init() {
arrow.STRING: func(data *Data) Interface { return NewStringData(data) },
arrow.BINARY: func(data *Data) Interface { return NewBinaryData(data) },
arrow.FIXED_SIZE_BINARY: func(data *Data) Interface { return NewFixedSizeBinaryData(data) },
- arrow.DATE32: unsupportedArrayType,
- arrow.DATE64: unsupportedArrayType,
+ arrow.DATE32: func(data *Data) Interface { return NewDate32Data(data) },
+ arrow.DATE64: func(data *Data) Interface { return NewDate64Data(data) },
arrow.TIMESTAMP: func(data *Data) Interface { return NewTimestampData(data) },
arrow.TIME32: func(data *Data) Interface { return NewTime32Data(data) },
arrow.TIME64: func(data *Data) Interface { return NewTime64Data(data) },
diff --git a/go/arrow/array/numeric.gen.go b/go/arrow/array/numeric.gen.go
index 1f734c0..1fb8257 100644
--- a/go/arrow/array/numeric.gen.go
+++ b/go/arrow/array/numeric.gen.go
@@ -609,3 +609,93 @@ func (a *Time64) setData(data *Data) {
a.values = a.values[beg:end]
}
}
+
+// A type which represents an immutable sequence of arrow.Date32 values.
+type Date32 struct {
+ array
+ values []arrow.Date32
+}
+
+func NewDate32Data(data *Data) *Date32 {
+ a := &Date32{}
+ a.refCount = 1
+ a.setData(data)
+ return a
+}
+
+func (a *Date32) Value(i int) arrow.Date32 { return a.values[i] }
+func (a *Date32) Date32Values() []arrow.Date32 { return a.values }
+
+func (a *Date32) String() string {
+ o := new(strings.Builder)
+ o.WriteString("[")
+ for i, v := range a.values {
+ if i > 0 {
+ fmt.Fprintf(o, " ")
+ }
+ switch {
+ case a.IsNull(i):
+ o.WriteString("(null)")
+ default:
+ fmt.Fprintf(o, "%v", v)
+ }
+ }
+ o.WriteString("]")
+ return o.String()
+}
+
+func (a *Date32) setData(data *Data) {
+ a.array.setData(data)
+ vals := data.buffers[1]
+ if vals != nil {
+ a.values = arrow.Date32Traits.CastFromBytes(vals.Bytes())
+ beg := a.array.data.offset
+ end := beg + a.array.data.length
+ a.values = a.values[beg:end]
+ }
+}
+
+// A type which represents an immutable sequence of arrow.Date64 values.
+type Date64 struct {
+ array
+ values []arrow.Date64
+}
+
+func NewDate64Data(data *Data) *Date64 {
+ a := &Date64{}
+ a.refCount = 1
+ a.setData(data)
+ return a
+}
+
+func (a *Date64) Value(i int) arrow.Date64 { return a.values[i] }
+func (a *Date64) Date64Values() []arrow.Date64 { return a.values }
+
+func (a *Date64) String() string {
+ o := new(strings.Builder)
+ o.WriteString("[")
+ for i, v := range a.values {
+ if i > 0 {
+ fmt.Fprintf(o, " ")
+ }
+ switch {
+ case a.IsNull(i):
+ o.WriteString("(null)")
+ default:
+ fmt.Fprintf(o, "%v", v)
+ }
+ }
+ o.WriteString("]")
+ return o.String()
+}
+
+func (a *Date64) setData(data *Data) {
+ a.array.setData(data)
+ vals := data.buffers[1]
+ if vals != nil {
+ a.values = arrow.Date64Traits.CastFromBytes(vals.Bytes())
+ beg := a.array.data.offset
+ end := beg + a.array.data.length
+ a.values = a.values[beg:end]
+ }
+}
diff --git a/go/arrow/array/numeric_test.go b/go/arrow/array/numeric_test.go
index 9e8267a..fc7f04a 100644
--- a/go/arrow/array/numeric_test.go
+++ b/go/arrow/array/numeric_test.go
@@ -394,3 +394,223 @@ func TestTime64SliceDataWithNull(t *testing.T) {
t.Fatalf("got=%v, want=%v", got, want)
}
}
+
+func TestNewDate32Data(t *testing.T) {
+ exp := []arrow.Date32{1, 2, 4, 8, 16}
+
+ dtype := &arrow.Date32Type{}
+ ad := array.NewData(
+ dtype, len(exp),
+ []*memory.Buffer{nil, memory.NewBufferBytes(arrow.Date32Traits.CastToBytes(exp))},
+ nil, 0, 0,
+ )
+ fa := array.NewDate32Data(ad)
+
+ assert.Equal(t, len(exp), fa.Len(), "unexpected Len()")
+ assert.Equal(t, exp, fa.Date32Values(), "unexpected Date32Values()")
+}
+
+func TestDate32SliceData(t *testing.T) {
+ pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer pool.AssertSize(t, 0)
+
+ const (
+ beg = 2
+ end = 4
+ )
+
+ var (
+ vs = []arrow.Date32{1, 2, 3, 4, 5}
+ sub = vs[beg:end]
+ )
+
+ b := array.NewDate32Builder(pool)
+ defer b.Release()
+
+ for _, v := range vs {
+ b.Append(v)
+ }
+
+ arr := b.NewArray().(*array.Date32)
+ defer arr.Release()
+
+ if got, want := arr.Len(), len(vs); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := arr.Date32Values(), vs; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+
+ slice := array.NewSlice(arr, beg, end).(*array.Date32)
+ defer slice.Release()
+
+ if got, want := slice.Len(), len(sub); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := slice.Date32Values(), sub; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+}
+
+func TestDate32SliceDataWithNull(t *testing.T) {
+ pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer pool.AssertSize(t, 0)
+
+ const (
+ beg = 2
+ end = 5
+ )
+
+ var (
+ valids = []bool{true, true, true, false, true, true}
+ vs = []arrow.Date32{1, 2, 3, 0, 4, 5}
+ sub = vs[beg:end]
+ )
+
+ b := array.NewDate32Builder(pool)
+ defer b.Release()
+
+ b.AppendValues(vs, valids)
+
+ arr := b.NewArray().(*array.Date32)
+ defer arr.Release()
+
+ if got, want := arr.Len(), len(valids); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := arr.NullN(), 1; got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := arr.Date32Values(), vs; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+
+ slice := array.NewSlice(arr, beg, end).(*array.Date32)
+ defer slice.Release()
+
+ if got, want := slice.NullN(), 1; got != want {
+ t.Errorf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := slice.Len(), len(sub); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := slice.Date32Values(), sub; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+}
+
+func TestNewDate64Data(t *testing.T) {
+ exp := []arrow.Date64{1, 2, 4, 8, 16}
+
+ dtype := &arrow.Date64Type{}
+ ad := array.NewData(
+ dtype, len(exp),
+ []*memory.Buffer{nil, memory.NewBufferBytes(arrow.Date64Traits.CastToBytes(exp))},
+ nil, 0, 0,
+ )
+ fa := array.NewDate64Data(ad)
+
+ assert.Equal(t, len(exp), fa.Len(), "unexpected Len()")
+ assert.Equal(t, exp, fa.Date64Values(), "unexpected Date64Values()")
+}
+
+func TestDate64SliceData(t *testing.T) {
+ pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer pool.AssertSize(t, 0)
+
+ const (
+ beg = 2
+ end = 4
+ )
+
+ var (
+ vs = []arrow.Date64{1, 2, 3, 4, 5}
+ sub = vs[beg:end]
+ )
+
+ b := array.NewDate64Builder(pool)
+ defer b.Release()
+
+ for _, v := range vs {
+ b.Append(v)
+ }
+
+ arr := b.NewArray().(*array.Date64)
+ defer arr.Release()
+
+ if got, want := arr.Len(), len(vs); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := arr.Date64Values(), vs; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+
+ slice := array.NewSlice(arr, beg, end).(*array.Date64)
+ defer slice.Release()
+
+ if got, want := slice.Len(), len(sub); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := slice.Date64Values(), sub; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+}
+
+func TestDate64SliceDataWithNull(t *testing.T) {
+ pool := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer pool.AssertSize(t, 0)
+
+ const (
+ beg = 2
+ end = 5
+ )
+
+ var (
+ valids = []bool{true, true, true, false, true, true}
+ vs = []arrow.Date64{1, 2, 3, 0, 4, 5}
+ sub = vs[beg:end]
+ )
+
+ b := array.NewDate64Builder(pool)
+ defer b.Release()
+
+ b.AppendValues(vs, valids)
+
+ arr := b.NewArray().(*array.Date64)
+ defer arr.Release()
+
+ if got, want := arr.Len(), len(valids); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := arr.NullN(), 1; got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := arr.Date64Values(), vs; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+
+ slice := array.NewSlice(arr, beg, end).(*array.Date64)
+ defer slice.Release()
+
+ if got, want := slice.NullN(), 1; got != want {
+ t.Errorf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := slice.Len(), len(sub); got != want {
+ t.Fatalf("got=%d, want=%d", got, want)
+ }
+
+ if got, want := slice.Date64Values(), sub; !reflect.DeepEqual(got, want) {
+ t.Fatalf("got=%v, want=%v", got, want)
+ }
+}
diff --git a/go/arrow/array/numericbuilder.gen.go b/go/arrow/array/numericbuilder.gen.go
index 3a7dc16..946c5ba 100644
--- a/go/arrow/array/numericbuilder.gen.go
+++ b/go/arrow/array/numericbuilder.gen.go
@@ -1772,6 +1772,274 @@ func (b *Time64Builder) newData() (data *Data) {
return
}
+type Date32Builder struct {
+ builder
+
+ data *memory.Buffer
+ rawData []arrow.Date32
+}
+
+func NewDate32Builder(mem memory.Allocator) *Date32Builder {
+ return &Date32Builder{builder: builder{refCount: 1, mem: mem}}
+}
+
+// Release decreases the reference count by 1.
+// When the reference count goes to zero, the memory is freed.
+func (b *Date32Builder) Release() {
+ debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
+
+ if atomic.AddInt64(&b.refCount, -1) == 0 {
+ if b.nullBitmap != nil {
+ b.nullBitmap.Release()
+ b.nullBitmap = nil
+ }
+ if b.data != nil {
+ b.data.Release()
+ b.data = nil
+ b.rawData = nil
+ }
+ }
+}
+
+func (b *Date32Builder) Append(v arrow.Date32) {
+ b.Reserve(1)
+ b.UnsafeAppend(v)
+}
+
+func (b *Date32Builder) AppendNull() {
+ b.Reserve(1)
+ b.UnsafeAppendBoolToBitmap(false)
+}
+
+func (b *Date32Builder) UnsafeAppend(v arrow.Date32) {
+ bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
+ b.rawData[b.length] = v
+ b.length++
+}
+
+func (b *Date32Builder) UnsafeAppendBoolToBitmap(isValid bool) {
+ if isValid {
+ bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
+ } else {
+ b.nulls++
+ }
+ b.length++
+}
+
+// AppendValues will append the values in the v slice. The valid slice determines which values
+// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
+// all values in v are appended and considered valid.
+func (b *Date32Builder) AppendValues(v []arrow.Date32, valid []bool) {
+ if len(v) != len(valid) && len(valid) != 0 {
+ panic("len(v) != len(valid) && len(valid) != 0")
+ }
+
+ b.Reserve(len(v))
+ if len(v) > 0 {
+ arrow.Date32Traits.Copy(b.rawData[b.length:], v)
+ }
+ b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
+}
+
+func (b *Date32Builder) init(capacity int) {
+ b.builder.init(capacity)
+
+ b.data = memory.NewResizableBuffer(b.mem)
+ bytesN := arrow.Date32Traits.BytesRequired(capacity)
+ b.data.Resize(bytesN)
+ b.rawData = arrow.Date32Traits.CastFromBytes(b.data.Bytes())
+}
+
+// Reserve ensures there is enough space for appending n elements
+// by checking the capacity and calling Resize if necessary.
+func (b *Date32Builder) Reserve(n int) {
+ b.builder.reserve(n, b.Resize)
+}
+
+// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
+// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
+func (b *Date32Builder) Resize(n int) {
+ nBuilder := n
+ if n < minBuilderCapacity {
+ n = minBuilderCapacity
+ }
+
+ if b.capacity == 0 {
+ b.init(n)
+ } else {
+ b.builder.resize(nBuilder, b.init)
+ b.data.Resize(arrow.Date32Traits.BytesRequired(n))
+ b.rawData = arrow.Date32Traits.CastFromBytes(b.data.Bytes())
+ }
+}
+
+// NewArray creates a Date32 array from the memory buffers used by the builder and resets the Date32Builder
+// so it can be used to build a new array.
+func (b *Date32Builder) NewArray() Interface {
+ return b.NewDate32Array()
+}
+
+// NewDate32Array creates a Date32 array from the memory buffers used by the builder and resets the Date32Builder
+// so it can be used to build a new array.
+func (b *Date32Builder) NewDate32Array() (a *Date32) {
+ data := b.newData()
+ a = NewDate32Data(data)
+ data.Release()
+ return
+}
+
+func (b *Date32Builder) newData() (data *Data) {
+ bytesRequired := arrow.Date32Traits.BytesRequired(b.length)
+ if bytesRequired > 0 && bytesRequired < b.data.Len() {
+ // trim buffers
+ b.data.Resize(bytesRequired)
+ }
+ data = NewData(arrow.PrimitiveTypes.Date32, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
+ b.reset()
+
+ if b.data != nil {
+ b.data.Release()
+ b.data = nil
+ b.rawData = nil
+ }
+
+ return
+}
+
+type Date64Builder struct {
+ builder
+
+ data *memory.Buffer
+ rawData []arrow.Date64
+}
+
+func NewDate64Builder(mem memory.Allocator) *Date64Builder {
+ return &Date64Builder{builder: builder{refCount: 1, mem: mem}}
+}
+
+// Release decreases the reference count by 1.
+// When the reference count goes to zero, the memory is freed.
+func (b *Date64Builder) Release() {
+ debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
+
+ if atomic.AddInt64(&b.refCount, -1) == 0 {
+ if b.nullBitmap != nil {
+ b.nullBitmap.Release()
+ b.nullBitmap = nil
+ }
+ if b.data != nil {
+ b.data.Release()
+ b.data = nil
+ b.rawData = nil
+ }
+ }
+}
+
+func (b *Date64Builder) Append(v arrow.Date64) {
+ b.Reserve(1)
+ b.UnsafeAppend(v)
+}
+
+func (b *Date64Builder) AppendNull() {
+ b.Reserve(1)
+ b.UnsafeAppendBoolToBitmap(false)
+}
+
+func (b *Date64Builder) UnsafeAppend(v arrow.Date64) {
+ bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
+ b.rawData[b.length] = v
+ b.length++
+}
+
+func (b *Date64Builder) UnsafeAppendBoolToBitmap(isValid bool) {
+ if isValid {
+ bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
+ } else {
+ b.nulls++
+ }
+ b.length++
+}
+
+// AppendValues will append the values in the v slice. The valid slice determines which values
+// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
+// all values in v are appended and considered valid.
+func (b *Date64Builder) AppendValues(v []arrow.Date64, valid []bool) {
+ if len(v) != len(valid) && len(valid) != 0 {
+ panic("len(v) != len(valid) && len(valid) != 0")
+ }
+
+ b.Reserve(len(v))
+ if len(v) > 0 {
+ arrow.Date64Traits.Copy(b.rawData[b.length:], v)
+ }
+ b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
+}
+
+func (b *Date64Builder) init(capacity int) {
+ b.builder.init(capacity)
+
+ b.data = memory.NewResizableBuffer(b.mem)
+ bytesN := arrow.Date64Traits.BytesRequired(capacity)
+ b.data.Resize(bytesN)
+ b.rawData = arrow.Date64Traits.CastFromBytes(b.data.Bytes())
+}
+
+// Reserve ensures there is enough space for appending n elements
+// by checking the capacity and calling Resize if necessary.
+func (b *Date64Builder) Reserve(n int) {
+ b.builder.reserve(n, b.Resize)
+}
+
+// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
+// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
+func (b *Date64Builder) Resize(n int) {
+ nBuilder := n
+ if n < minBuilderCapacity {
+ n = minBuilderCapacity
+ }
+
+ if b.capacity == 0 {
+ b.init(n)
+ } else {
+ b.builder.resize(nBuilder, b.init)
+ b.data.Resize(arrow.Date64Traits.BytesRequired(n))
+ b.rawData = arrow.Date64Traits.CastFromBytes(b.data.Bytes())
+ }
+}
+
+// NewArray creates a Date64 array from the memory buffers used by the builder and resets the Date64Builder
+// so it can be used to build a new array.
+func (b *Date64Builder) NewArray() Interface {
+ return b.NewDate64Array()
+}
+
+// NewDate64Array creates a Date64 array from the memory buffers used by the builder and resets the Date64Builder
+// so it can be used to build a new array.
+func (b *Date64Builder) NewDate64Array() (a *Date64) {
+ data := b.newData()
+ a = NewDate64Data(data)
+ data.Release()
+ return
+}
+
+func (b *Date64Builder) newData() (data *Data) {
+ bytesRequired := arrow.Date64Traits.BytesRequired(b.length)
+ if bytesRequired > 0 && bytesRequired < b.data.Len() {
+ // trim buffers
+ b.data.Resize(bytesRequired)
+ }
+ data = NewData(arrow.PrimitiveTypes.Date64, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
+ b.reset()
+
+ if b.data != nil {
+ b.data.Release()
+ b.data = nil
+ b.rawData = nil
+ }
+
+ return
+}
+
var (
_ Builder = (*Int64Builder)(nil)
_ Builder = (*Uint64Builder)(nil)
@@ -1786,4 +2054,6 @@ var (
_ Builder = (*TimestampBuilder)(nil)
_ Builder = (*Time32Builder)(nil)
_ Builder = (*Time64Builder)(nil)
+ _ Builder = (*Date32Builder)(nil)
+ _ Builder = (*Date64Builder)(nil)
)
diff --git a/go/arrow/array/numericbuilder_test.go b/go/arrow/array/numericbuilder_test.go
index 65f3c86..3bb49a3 100644
--- a/go/arrow/array/numericbuilder_test.go
+++ b/go/arrow/array/numericbuilder_test.go
@@ -362,3 +362,223 @@ func TestTime64Builder_Resize(t *testing.T) {
ab.Release()
}
+
+func TestNewDate32Builder(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate32Builder(mem)
+
+ ab.Append(1)
+ ab.Append(2)
+ ab.Append(3)
+ ab.AppendNull()
+ ab.Append(5)
+ ab.Append(6)
+ ab.AppendNull()
+ ab.Append(8)
+ ab.Append(9)
+ ab.Append(10)
+
+ // check state of builder before NewDate32Array
+ assert.Equal(t, 10, ab.Len(), "unexpected Len()")
+ assert.Equal(t, 2, ab.NullN(), "unexpected NullN()")
+
+ a := ab.NewDate32Array()
+
+ // check state of builder after NewDate32Array
+ assert.Zero(t, ab.Len(), "unexpected ArrayBuilder.Len(), NewDate32Array did not reset state")
+ assert.Zero(t, ab.Cap(), "unexpected ArrayBuilder.Cap(), NewDate32Array did not reset state")
+ assert.Zero(t, ab.NullN(), "unexpected ArrayBuilder.NullN(), NewDate32Array did not reset state")
+
+ // check state of array
+ assert.Equal(t, 2, a.NullN(), "unexpected null count")
+ assert.Equal(t, []arrow.Date32{1, 2, 3, 0, 5, 6, 0, 8, 9, 10}, a.Date32Values(), "unexpected Date32Values")
+ assert.Equal(t, []byte{0xb7}, a.NullBitmapBytes()[:1]) // 4 bytes due to minBuilderCapacity
+ assert.Len(t, a.Date32Values(), 10, "unexpected length of Date32Values")
+
+ a.Release()
+
+ ab.Append(7)
+ ab.Append(8)
+
+ a = ab.NewDate32Array()
+
+ assert.Equal(t, 0, a.NullN())
+ assert.Equal(t, []arrow.Date32{7, 8}, a.Date32Values())
+ assert.Len(t, a.Date32Values(), 2)
+
+ a.Release()
+}
+
+func TestDate32Builder_AppendValues(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate32Builder(mem)
+
+ exp := []arrow.Date32{1, 2, 3, 4}
+ ab.AppendValues(exp, nil)
+ a := ab.NewDate32Array()
+ assert.Equal(t, exp, a.Date32Values())
+
+ a.Release()
+ ab.Release()
+}
+
+func TestDate32Builder_Empty(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate32Builder(mem)
+
+ exp := []arrow.Date32{1, 2, 3, 4}
+ ab.AppendValues(exp, nil)
+ a := ab.NewDate32Array()
+ assert.Equal(t, exp, a.Date32Values())
+ a.Release()
+
+ a = ab.NewDate32Array()
+ assert.Zero(t, a.Len())
+ a.Release()
+
+ ab.Release()
+}
+
+func TestDate32Builder_Resize(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate32Builder(mem)
+
+ assert.Equal(t, 0, ab.Cap())
+ assert.Equal(t, 0, ab.Len())
+
+ ab.Reserve(63)
+ assert.Equal(t, 64, ab.Cap())
+ assert.Equal(t, 0, ab.Len())
+
+ for i := 0; i < 63; i++ {
+ ab.Append(0)
+ }
+ assert.Equal(t, 64, ab.Cap())
+ assert.Equal(t, 63, ab.Len())
+
+ ab.Resize(5)
+ assert.Equal(t, 5, ab.Len())
+
+ ab.Resize(32)
+ assert.Equal(t, 5, ab.Len())
+
+ ab.Release()
+}
+
+func TestNewDate64Builder(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate64Builder(mem)
+
+ ab.Append(1)
+ ab.Append(2)
+ ab.Append(3)
+ ab.AppendNull()
+ ab.Append(5)
+ ab.Append(6)
+ ab.AppendNull()
+ ab.Append(8)
+ ab.Append(9)
+ ab.Append(10)
+
+ // check state of builder before NewDate64Array
+ assert.Equal(t, 10, ab.Len(), "unexpected Len()")
+ assert.Equal(t, 2, ab.NullN(), "unexpected NullN()")
+
+ a := ab.NewDate64Array()
+
+ // check state of builder after NewDate64Array
+ assert.Zero(t, ab.Len(), "unexpected ArrayBuilder.Len(), NewDate64Array did not reset state")
+ assert.Zero(t, ab.Cap(), "unexpected ArrayBuilder.Cap(), NewDate64Array did not reset state")
+ assert.Zero(t, ab.NullN(), "unexpected ArrayBuilder.NullN(), NewDate64Array did not reset state")
+
+ // check state of array
+ assert.Equal(t, 2, a.NullN(), "unexpected null count")
+ assert.Equal(t, []arrow.Date64{1, 2, 3, 0, 5, 6, 0, 8, 9, 10}, a.Date64Values(), "unexpected Date64Values")
+ assert.Equal(t, []byte{0xb7}, a.NullBitmapBytes()[:1]) // 4 bytes due to minBuilderCapacity
+ assert.Len(t, a.Date64Values(), 10, "unexpected length of Date64Values")
+
+ a.Release()
+
+ ab.Append(7)
+ ab.Append(8)
+
+ a = ab.NewDate64Array()
+
+ assert.Equal(t, 0, a.NullN())
+ assert.Equal(t, []arrow.Date64{7, 8}, a.Date64Values())
+ assert.Len(t, a.Date64Values(), 2)
+
+ a.Release()
+}
+
+func TestDate64Builder_AppendValues(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate64Builder(mem)
+
+ exp := []arrow.Date64{1, 2, 3, 4}
+ ab.AppendValues(exp, nil)
+ a := ab.NewDate64Array()
+ assert.Equal(t, exp, a.Date64Values())
+
+ a.Release()
+ ab.Release()
+}
+
+func TestDate64Builder_Empty(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate64Builder(mem)
+
+ exp := []arrow.Date64{1, 2, 3, 4}
+ ab.AppendValues(exp, nil)
+ a := ab.NewDate64Array()
+ assert.Equal(t, exp, a.Date64Values())
+ a.Release()
+
+ a = ab.NewDate64Array()
+ assert.Zero(t, a.Len())
+ a.Release()
+
+ ab.Release()
+}
+
+func TestDate64Builder_Resize(t *testing.T) {
+ mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+ defer mem.AssertSize(t, 0)
+
+ ab := array.NewDate64Builder(mem)
+
+ assert.Equal(t, 0, ab.Cap())
+ assert.Equal(t, 0, ab.Len())
+
+ ab.Reserve(63)
+ assert.Equal(t, 64, ab.Cap())
+ assert.Equal(t, 0, ab.Len())
+
+ for i := 0; i < 63; i++ {
+ ab.Append(0)
+ }
+ assert.Equal(t, 64, ab.Cap())
+ assert.Equal(t, 63, ab.Len())
+
+ ab.Resize(5)
+ assert.Equal(t, 5, ab.Len())
+
+ ab.Resize(32)
+ assert.Equal(t, 5, ab.Len())
+
+ ab.Release()
+}
diff --git a/go/arrow/datatype_fixedwidth.go b/go/arrow/datatype_fixedwidth.go
index 60cc98a..4444950 100644
--- a/go/arrow/datatype_fixedwidth.go
+++ b/go/arrow/datatype_fixedwidth.go
@@ -37,6 +37,8 @@ type (
Time32 int32
Time64 int64
TimeUnit int
+ Date32 int32
+ Date64 int64
)
const (
diff --git a/go/arrow/datatype_numeric.gen.go b/go/arrow/datatype_numeric.gen.go
index 2ec4c40..9b5dc83 100644
--- a/go/arrow/datatype_numeric.gen.go
+++ b/go/arrow/datatype_numeric.gen.go
@@ -78,6 +78,18 @@ func (t *Float64Type) ID() Type { return FLOAT64 }
func (t *Float64Type) Name() string { return "float64" }
func (t *Float64Type) BitWidth() int { return 64 }
+type Date32Type struct{}
+
+func (t *Date32Type) ID() Type { return DATE32 }
+func (t *Date32Type) Name() string { return "date32" }
+func (t *Date32Type) BitWidth() int { return 32 }
+
+type Date64Type struct{}
+
+func (t *Date64Type) ID() Type { return DATE64 }
+func (t *Date64Type) Name() string { return "date64" }
+func (t *Date64Type) BitWidth() int { return 64 }
+
var (
PrimitiveTypes = struct {
Int8 DataType
@@ -90,6 +102,8 @@ var (
Uint64 DataType
Float32 DataType
Float64 DataType
+ Date32 DataType
+ Date64 DataType
}{
Int8: &Int8Type{},
@@ -102,5 +116,7 @@ var (
Uint64: &Uint64Type{},
Float32: &Float32Type{},
Float64: &Float64Type{},
+ Date32: &Date32Type{},
+ Date64: &Date64Type{},
}
)
diff --git a/go/arrow/datatype_numeric.gen.go.tmpldata b/go/arrow/datatype_numeric.gen.go.tmpldata
index 415b51b..9badc6e 100644
--- a/go/arrow/datatype_numeric.gen.go.tmpldata
+++ b/go/arrow/datatype_numeric.gen.go.tmpldata
@@ -48,5 +48,15 @@
"Name": "Float64",
"Type": "float64",
"Size": 64
+ },
+ {
+ "Name": "Date32",
+ "Type": "date32",
+ "Size": 32
+ },
+ {
+ "Name": "Date64",
+ "Type": "date64",
+ "Size": 64
}
]
diff --git a/go/arrow/numeric.tmpldata b/go/arrow/numeric.tmpldata
index b9e976e..45452ab 100644
--- a/go/arrow/numeric.tmpldata
+++ b/go/arrow/numeric.tmpldata
@@ -107,5 +107,23 @@
"Opt": {
"Parametric": true
}
+ },
+ {
+ "Name": "Date32",
+ "name": "date32",
+ "Type": "Date32",
+ "QualifiedType": "arrow.Date32",
+ "InternalType": "int32",
+ "Default": "0",
+ "Size": "4"
+ },
+ {
+ "Name": "Date64",
+ "name": "date64",
+ "Type": "Date64",
+ "QualifiedType": "arrow.Date64",
+ "InternalType": "int64",
+ "Default": "0",
+ "Size": "8"
}
-]
\ No newline at end of file
+]
diff --git a/go/arrow/type_traits_numeric.gen.go b/go/arrow/type_traits_numeric.gen.go
index 59ed13f..14fafbc 100644
--- a/go/arrow/type_traits_numeric.gen.go
+++ b/go/arrow/type_traits_numeric.gen.go
@@ -38,6 +38,8 @@ var (
TimestampTraits timestampTraits
Time32Traits time32Traits
Time64Traits time64Traits
+ Date32Traits date32Traits
+ Date64Traits date64Traits
)
// Int64 traits
@@ -663,3 +665,99 @@ func (time64Traits) CastToBytes(b []Time64) []byte {
// Copy copies src to dst.
func (time64Traits) Copy(dst, src []Time64) { copy(dst, src) }
+
+// Date32 traits
+
+const (
+ // Date32SizeBytes specifies the number of bytes required to store a single Date32 in memory
+ Date32SizeBytes = int(unsafe.Sizeof(Date32(0)))
+)
+
+type date32Traits struct{}
+
+// BytesRequired returns the number of bytes required to store n elements in memory.
+func (date32Traits) BytesRequired(n int) int { return Date32SizeBytes * n }
+
+// PutValue
+func (date32Traits) PutValue(b []byte, v Date32) {
+ binary.LittleEndian.PutUint32(b, uint32(v))
+}
+
+// CastFromBytes reinterprets the slice b to a slice of type Date32.
+//
+// NOTE: len(b) must be a multiple of Date32SizeBytes.
+func (date32Traits) CastFromBytes(b []byte) []Date32 {
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+
+ var res []Date32
+ s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+ s.Data = h.Data
+ s.Len = h.Len / Date32SizeBytes
+ s.Cap = h.Cap / Date32SizeBytes
+
+ return res
+}
+
+// CastToBytes reinterprets the slice b to a slice of bytes.
+func (date32Traits) CastToBytes(b []Date32) []byte {
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+
+ var res []byte
+ s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+ s.Data = h.Data
+ s.Len = h.Len * Date32SizeBytes
+ s.Cap = h.Cap * Date32SizeBytes
+
+ return res
+}
+
+// Copy copies src to dst.
+func (date32Traits) Copy(dst, src []Date32) { copy(dst, src) }
+
+// Date64 traits
+
+const (
+ // Date64SizeBytes specifies the number of bytes required to store a single Date64 in memory
+ Date64SizeBytes = int(unsafe.Sizeof(Date64(0)))
+)
+
+type date64Traits struct{}
+
+// BytesRequired returns the number of bytes required to store n elements in memory.
+func (date64Traits) BytesRequired(n int) int { return Date64SizeBytes * n }
+
+// PutValue
+func (date64Traits) PutValue(b []byte, v Date64) {
+ binary.LittleEndian.PutUint64(b, uint64(v))
+}
+
+// CastFromBytes reinterprets the slice b to a slice of type Date64.
+//
+// NOTE: len(b) must be a multiple of Date64SizeBytes.
+func (date64Traits) CastFromBytes(b []byte) []Date64 {
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+
+ var res []Date64
+ s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+ s.Data = h.Data
+ s.Len = h.Len / Date64SizeBytes
+ s.Cap = h.Cap / Date64SizeBytes
+
+ return res
+}
+
+// CastToBytes reinterprets the slice b to a slice of bytes.
+func (date64Traits) CastToBytes(b []Date64) []byte {
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+
+ var res []byte
+ s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+ s.Data = h.Data
+ s.Len = h.Len * Date64SizeBytes
+ s.Cap = h.Cap * Date64SizeBytes
+
+ return res
+}
+
+// Copy copies src to dst.
+func (date64Traits) Copy(dst, src []Date64) { copy(dst, src) }