This is an automated email from the ASF dual-hosted git repository.

zeroshade 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 12aaf2c  ARROW-13804: [Go] Add Interval type Month, Day, Nano
12aaf2c is described below

commit 12aaf2ce15600d1a8d8cbdaf71ca7a922f520a82
Author: Matthew Topol <[email protected]>
AuthorDate: Wed Oct 13 16:58:24 2021 -0400

    ARROW-13804: [Go] Add Interval type Month, Day, Nano
    
    #10177 Added the interval type Month, Day, Nano to the flatbuffer and 
C++/Java, this updates the flatbuffer generated files and adds support for the 
type to Go.
    
    Closes #11310 from zeroshade/arrow-13804-month-day-nano
    
    Authored-by: Matthew Topol <[email protected]>
    Signed-off-by: Matthew Topol <[email protected]>
---
 .github/workflows/archery.yml                      |   2 +
 dev/archery/archery/integration/datagen.py         |   2 -
 go/arrow/array/array.go                            |   4 +-
 go/arrow/array/array_test.go                       |   3 +-
 go/arrow/array/builder.go                          |   3 +
 go/arrow/array/compare.go                          |   6 +
 go/arrow/array/interval.go                         | 199 +++++++++++++++++++++
 go/arrow/array/interval_test.go                    | 131 ++++++++++++++
 go/arrow/cdata/cdata.go                            |   1 +
 go/arrow/cdata/cdata_exports.go                    |   2 +
 go/arrow/cdata/cdata_test.go                       |   1 +
 go/arrow/datatype_fixedwidth.go                    |  98 ++++++----
 go/arrow/internal/arrdata/arrdata.go               |  19 +-
 go/arrow/internal/arrjson/arrjson.go               |  48 +++++
 go/arrow/internal/arrjson/arrjson_test.go          | 174 ++++++++++++++++--
 .../cmd/arrow-flight-integration-server/main.go    |   1 -
 go/arrow/internal/flight_integration/scenario.go   |  20 ++-
 go/arrow/ipc/file_reader.go                        |   2 +-
 go/arrow/ipc/metadata.go                           |   8 +
 go/arrow/scalar/parse.go                           |   2 +
 go/arrow/scalar/scalar.go                          |  14 +-
 go/arrow/scalar/scalar_test.go                     |  27 +++
 go/arrow/scalar/temporal.go                        |  42 +++++
 go/arrow/type_traits_interval.go                   |  62 ++++++-
 go/arrow/type_traits_test.go                       |  34 ++++
 .../java/org/apache/arrow/flight/FlightStream.java |  10 +-
 26 files changed, 836 insertions(+), 79 deletions(-)

diff --git a/.github/workflows/archery.yml b/.github/workflows/archery.yml
index 66cd04a..fa84f4dc 100644
--- a/.github/workflows/archery.yml
+++ b/.github/workflows/archery.yml
@@ -56,6 +56,8 @@ jobs:
         uses: actions/setup-python@v1
         with:
           python-version: '3.6'
+      - name: Install pygit2 binary wheel
+        run: pip install pygit2 --only-binary pygit2
       - name: Install Archery, Crossbow- and Test Dependencies
         run: pip install pytest responses -e dev/archery[all]
       - name: Archery Unittests
diff --git a/dev/archery/archery/integration/datagen.py 
b/dev/archery/archery/integration/datagen.py
index 7e23047..8a9f4de 100644
--- a/dev/archery/archery/integration/datagen.py
+++ b/dev/archery/archery/integration/datagen.py
@@ -1564,7 +1564,6 @@ def get_generated_json_files(tempdir=None):
         generate_null_case([10, 0])
         .skip_category('C#')
         .skip_category('Go')    # TODO(ARROW-7901)
-        .skip_category('Go')    # TODO(ARROW-7901)
         .skip_category('JS'),   # TODO(ARROW-7900)
 
         generate_null_trivial_case([0, 0])
@@ -1590,7 +1589,6 @@ def get_generated_json_files(tempdir=None):
 
         generate_month_day_nano_interval_case()
         .skip_category('C#')
-        .skip_category('Go')
         .skip_category('JS')
         .skip_category('Rust'),
 
diff --git a/go/arrow/array/array.go b/go/arrow/array/array.go
index 8679773..5779717 100644
--- a/go/arrow/array/array.go
+++ b/go/arrow/array/array.go
@@ -207,10 +207,10 @@ func init() {
                arrow.LARGE_STRING:            unsupportedArrayType,
                arrow.LARGE_BINARY:            unsupportedArrayType,
                arrow.LARGE_LIST:              unsupportedArrayType,
-               arrow.INTERVAL_MONTH_DAY_NANO: unsupportedArrayType,
                arrow.INTERVAL:                func(data *Data) Interface { 
return NewIntervalData(data) },
+               arrow.INTERVAL_MONTH_DAY_NANO: func(data *Data) Interface { 
return NewMonthDayNanoIntervalData(data) },
 
-               // invalid data types to fill out array size 2⁵-1
+               // invalid data types to fill out array to size 2^6 - 1
                63: invalidDataType,
        }
 }
diff --git a/go/arrow/array/array_test.go b/go/arrow/array/array_test.go
index 5d93245..b986332 100644
--- a/go/arrow/array/array_test.go
+++ b/go/arrow/array/array_test.go
@@ -68,7 +68,8 @@ func TestMakeFromData(t *testing.T) {
                {name: "time64", d: &testDataType{arrow.TIME64}},
                {name: "month_interval", d: 
arrow.FixedWidthTypes.MonthInterval},
                {name: "day_time_interval", d: 
arrow.FixedWidthTypes.DayTimeInterval},
-               {name: "decimal", d: &testDataType{arrow.DECIMAL128}},
+               {name: "decimal128", d: &testDataType{arrow.DECIMAL128}},
+               {name: "month_day_nano_interval", d: 
arrow.FixedWidthTypes.MonthDayNanoInterval},
 
                {name: "list", d: &testDataType{arrow.LIST}, child: 
[]*array.Data{
                        array.NewData(&testDataType{arrow.INT64}, 0 /* length 
*/, make([]*memory.Buffer, 2 /*null bitmap, values*/), nil /* childData */, 0 
/* nulls */, 0 /* offset */),
diff --git a/go/arrow/array/builder.go b/go/arrow/array/builder.go
index 5342c5f..77d0d42 100644
--- a/go/arrow/array/builder.go
+++ b/go/arrow/array/builder.go
@@ -266,12 +266,15 @@ func NewBuilder(mem memory.Allocator, dtype 
arrow.DataType) Builder {
                        return NewDayTimeIntervalBuilder(mem)
                case *arrow.MonthIntervalType:
                        return NewMonthIntervalBuilder(mem)
+               case *arrow.MonthDayNanoIntervalType:
+                       return NewMonthDayNanoIntervalBuilder(mem)
                }
        case arrow.INTERVAL_MONTHS:
                return NewMonthIntervalBuilder(mem)
        case arrow.INTERVAL_DAY_TIME:
                return NewDayTimeIntervalBuilder(mem)
        case arrow.INTERVAL_MONTH_DAY_NANO:
+               return NewMonthDayNanoIntervalBuilder(mem)
        case arrow.DECIMAL128:
                if typ, ok := dtype.(*arrow.Decimal128Type); ok {
                        return NewDecimal128Builder(mem, typ)
diff --git a/go/arrow/array/compare.go b/go/arrow/array/compare.go
index f0ff5ed..c4ee046 100644
--- a/go/arrow/array/compare.go
+++ b/go/arrow/array/compare.go
@@ -161,6 +161,9 @@ func ArrayEqual(left, right Interface) bool {
        case *DayTimeInterval:
                r := right.(*DayTimeInterval)
                return arrayEqualDayTimeInterval(l, r)
+       case *MonthDayNanoInterval:
+               r := right.(*MonthDayNanoInterval)
+               return arrayEqualMonthDayNanoInterval(l, r)
        case *Duration:
                r := right.(*Duration)
                return arrayEqualDuration(l, r)
@@ -355,6 +358,9 @@ func arrayApproxEqual(left, right Interface, opt 
equalOption) bool {
        case *DayTimeInterval:
                r := right.(*DayTimeInterval)
                return arrayEqualDayTimeInterval(l, r)
+       case *MonthDayNanoInterval:
+               r := right.(*MonthDayNanoInterval)
+               return arrayEqualMonthDayNanoInterval(l, r)
        case *Duration:
                r := right.(*Duration)
                return arrayEqualDuration(l, r)
diff --git a/go/arrow/array/interval.go b/go/arrow/array/interval.go
index d313558..c9191eb 100644
--- a/go/arrow/array/interval.go
+++ b/go/arrow/array/interval.go
@@ -34,6 +34,8 @@ func NewIntervalData(data *Data) Interface {
                return NewMonthIntervalData(data)
        case *arrow.DayTimeIntervalType:
                return NewDayTimeIntervalData(data)
+       case *arrow.MonthDayNanoIntervalType:
+               return NewMonthDayNanoIntervalData(data)
        default:
                panic(xerrors.Errorf("arrow/array: unknown interval data type 
%T", data.dtype))
        }
@@ -425,10 +427,207 @@ func (b *DayTimeIntervalBuilder) newData() (data *Data) {
        return
 }
 
+// A type which represents an immutable sequence of arrow.DayTimeInterval 
values.
+type MonthDayNanoInterval struct {
+       array
+       values []arrow.MonthDayNanoInterval
+}
+
+func NewMonthDayNanoIntervalData(data *Data) *MonthDayNanoInterval {
+       a := &MonthDayNanoInterval{}
+       a.refCount = 1
+       a.setData(data)
+       return a
+}
+
+func (a *MonthDayNanoInterval) Value(i int) arrow.MonthDayNanoInterval { 
return a.values[i] }
+func (a *MonthDayNanoInterval) MonthDayNanoIntervalValues() 
[]arrow.MonthDayNanoInterval {
+       return a.values
+}
+
+func (a *MonthDayNanoInterval) 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 *MonthDayNanoInterval) setData(data *Data) {
+       a.array.setData(data)
+       vals := data.buffers[1]
+       if vals != nil {
+               a.values = 
arrow.MonthDayNanoIntervalTraits.CastFromBytes(vals.Bytes())
+               beg := a.array.data.offset
+               end := beg + a.array.data.length
+               a.values = a.values[beg:end]
+       }
+}
+
+func arrayEqualMonthDayNanoInterval(left, right *MonthDayNanoInterval) bool {
+       for i := 0; i < left.Len(); i++ {
+               if left.IsNull(i) {
+                       continue
+               }
+               if left.Value(i) != right.Value(i) {
+                       return false
+               }
+       }
+       return true
+}
+
+type MonthDayNanoIntervalBuilder struct {
+       builder
+
+       data    *memory.Buffer
+       rawData []arrow.MonthDayNanoInterval
+}
+
+func NewMonthDayNanoIntervalBuilder(mem memory.Allocator) 
*MonthDayNanoIntervalBuilder {
+       return &MonthDayNanoIntervalBuilder{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 *MonthDayNanoIntervalBuilder) 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 *MonthDayNanoIntervalBuilder) Append(v arrow.MonthDayNanoInterval) {
+       b.Reserve(1)
+       b.UnsafeAppend(v)
+}
+
+func (b *MonthDayNanoIntervalBuilder) AppendNull() {
+       b.Reserve(1)
+       b.UnsafeAppendBoolToBitmap(false)
+}
+
+func (b *MonthDayNanoIntervalBuilder) UnsafeAppend(v 
arrow.MonthDayNanoInterval) {
+       bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
+       b.rawData[b.length] = v
+       b.length++
+}
+
+func (b *MonthDayNanoIntervalBuilder) 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 *MonthDayNanoIntervalBuilder) AppendValues(v 
[]arrow.MonthDayNanoInterval, valid []bool) {
+       if len(v) != len(valid) && len(valid) != 0 {
+               panic("len(v) != len(valid) && len(valid) != 0")
+       }
+
+       if len(v) == 0 {
+               return
+       }
+
+       b.Reserve(len(v))
+       arrow.MonthDayNanoIntervalTraits.Copy(b.rawData[b.length:], v)
+       b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
+}
+
+func (b *MonthDayNanoIntervalBuilder) init(capacity int) {
+       b.builder.init(capacity)
+
+       b.data = memory.NewResizableBuffer(b.mem)
+       bytesN := arrow.MonthDayNanoIntervalTraits.BytesRequired(capacity)
+       b.data.Resize(bytesN)
+       b.rawData = 
arrow.MonthDayNanoIntervalTraits.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 *MonthDayNanoIntervalBuilder) 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 *MonthDayNanoIntervalBuilder) 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.MonthDayNanoIntervalTraits.BytesRequired(n))
+               b.rawData = 
arrow.MonthDayNanoIntervalTraits.CastFromBytes(b.data.Bytes())
+       }
+}
+
+// NewArray creates a MonthDayNanoInterval array from the memory buffers used 
by the builder and resets the MonthDayNanoIntervalBuilder
+// so it can be used to build a new array.
+func (b *MonthDayNanoIntervalBuilder) NewArray() Interface {
+       return b.NewMonthDayNanoIntervalArray()
+}
+
+// NewMonthDayNanoIntervalArray creates a MonthDayNanoInterval array from the 
memory buffers used by the builder and resets the MonthDayNanoIntervalBuilder
+// so it can be used to build a new array.
+func (b *MonthDayNanoIntervalBuilder) NewMonthDayNanoIntervalArray() (a 
*MonthDayNanoInterval) {
+       data := b.newData()
+       a = NewMonthDayNanoIntervalData(data)
+       data.Release()
+       return
+}
+
+func (b *MonthDayNanoIntervalBuilder) newData() (data *Data) {
+       bytesRequired := 
arrow.MonthDayNanoIntervalTraits.BytesRequired(b.length)
+       if bytesRequired > 0 && bytesRequired < b.data.Len() {
+               // trim buffers
+               b.data.Resize(bytesRequired)
+       }
+       data = NewData(arrow.FixedWidthTypes.MonthDayNanoInterval, 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 (
        _ Interface = (*MonthInterval)(nil)
        _ Interface = (*DayTimeInterval)(nil)
+       _ Interface = (*MonthDayNanoInterval)(nil)
 
        _ Builder = (*MonthIntervalBuilder)(nil)
        _ Builder = (*DayTimeIntervalBuilder)(nil)
+       _ Builder = (*MonthDayNanoIntervalBuilder)(nil)
 )
diff --git a/go/arrow/array/interval_test.go b/go/arrow/array/interval_test.go
index 3e47881..0e983fd 100644
--- a/go/arrow/array/interval_test.go
+++ b/go/arrow/array/interval_test.go
@@ -17,6 +17,7 @@
 package array_test
 
 import (
+       "math"
        "testing"
 
        "github.com/apache/arrow/go/arrow"
@@ -274,3 +275,133 @@ func TestDayTimeIntervalBuilder_Empty(t *testing.T) {
        assert.Equal(t, want, dtValues(arr))
        arr.Release()
 }
+
+func TestMonthDayNanoArray(t *testing.T) {
+       mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+       defer mem.AssertSize(t, 0)
+
+       var (
+               want = []arrow.MonthDayNanoInterval{
+                       {1, 1, 1000}, {2, 2, 2000}, {3, 3, 3000}, {4, 4, 4000},
+                       {0, 0, 0}, {-1, -2, -300}, {math.MaxInt32, 
math.MinInt32, math.MaxInt64},
+                       {math.MinInt32, math.MaxInt32, math.MinInt64},
+               }
+               valids = []bool{true, true, false, true, true, true, false, 
true}
+       )
+
+       b := array.NewMonthDayNanoIntervalBuilder(mem)
+       defer b.Release()
+
+       b.Retain()
+       b.Release()
+
+       b.AppendValues(want[:2], nil)
+       b.AppendNull()
+       b.Append(want[3])
+       b.AppendValues(want[4:], valids[4:])
+
+       if got, want := b.Len(), len(want); got != want {
+               t.Fatalf("invalid len: got=%d, want=%d", got, want)
+       }
+
+       if got, want := b.NullN(), 2; got != want {
+               t.Fatalf("invalid nulls: got=%d, want=%d", got, want)
+       }
+
+       arr := b.NewMonthDayNanoIntervalArray()
+       defer arr.Release()
+
+       arr.Retain()
+       arr.Release()
+
+       if got, want := arr.Len(), len(want); got != want {
+               t.Fatalf("invalid len: got=%d, want=%d", got, want)
+       }
+
+       if got, want := arr.NullN(), 2; got != want {
+               t.Fatalf("invalid nulls: got=%d, want=%d", got, want)
+       }
+
+       for i := range want {
+               if arr.IsNull(i) != !valids[i] {
+                       t.Fatalf("arr[%d]-validity: got=%v want=%v", i, 
!arr.IsNull(i), valids[i])
+               }
+               switch {
+               case arr.IsNull(i):
+               default:
+                       got := arr.Value(i)
+                       if got != want[i] {
+                               t.Fatalf("arr[%d]: got=%q, want=%q", i, got, 
want[i])
+                       }
+               }
+       }
+
+       sub := array.MakeFromData(arr.Data())
+       defer sub.Release()
+
+       if sub.DataType().ID() != arrow.INTERVAL_MONTH_DAY_NANO {
+               t.Fatalf("invalid type: got=%q, want=interval", 
sub.DataType().Name())
+       }
+
+       if _, ok := sub.(*array.MonthDayNanoInterval); !ok {
+               t.Fatalf("could not type-assert to array.MonthDayNanoInterval")
+       }
+
+       if got, want := arr.String(), `[{1 1 1000} {2 2 2000} (null) {4 4 4000} 
{0 0 0} {-1 -2 -300} (null) {-2147483648 2147483647 -9223372036854775808}]`; 
got != want {
+               t.Fatalf("got=%q, want=%q", got, want)
+       }
+       slice := array.NewSliceData(arr.Data(), 2, 4)
+       defer slice.Release()
+
+       sub1 := array.MakeFromData(slice)
+       defer sub1.Release()
+
+       v, ok := sub1.(*array.MonthDayNanoInterval)
+       if !ok {
+               t.Fatalf("could not type-assert to array.MonthDayNanoInterval")
+       }
+
+       if got, want := v.String(), `[(null) {4 4 4000}]`; got != want {
+               t.Fatalf("got=%q, want=%q", got, want)
+       }
+}
+
+func TestMonthDayNanoIntervalBuilder_Empty(t *testing.T) {
+       mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+       defer mem.AssertSize(t, 0)
+
+       want := []arrow.MonthDayNanoInterval{{1, 1, 1000}, {2, 2, 2000}, {3, 3, 
3000}, {4, 4, 4000}}
+
+       b := array.NewMonthDayNanoIntervalBuilder(mem)
+       defer b.Release()
+
+       dtValues := func(a *array.MonthDayNanoInterval) 
[]arrow.MonthDayNanoInterval {
+               vs := make([]arrow.MonthDayNanoInterval, a.Len())
+               for i := range vs {
+                       vs[i] = a.Value(i)
+               }
+               return vs
+       }
+
+       b.AppendValues([]arrow.MonthDayNanoInterval{}, nil)
+       arr := b.NewMonthDayNanoIntervalArray()
+       assert.Zero(t, arr.Len())
+       arr.Release()
+
+       b.AppendValues(nil, nil)
+       arr = b.NewMonthDayNanoIntervalArray()
+       assert.Zero(t, arr.Len())
+       arr.Release()
+
+       b.AppendValues([]arrow.MonthDayNanoInterval{}, nil)
+       b.AppendValues(want, nil)
+       arr = b.NewMonthDayNanoIntervalArray()
+       assert.Equal(t, want, dtValues(arr))
+       arr.Release()
+
+       b.AppendValues(want, nil)
+       b.AppendValues([]arrow.MonthDayNanoInterval{}, nil)
+       arr = b.NewMonthDayNanoIntervalArray()
+       assert.Equal(t, want, dtValues(arr))
+       arr.Release()
+}
diff --git a/go/arrow/cdata/cdata.go b/go/arrow/cdata/cdata.go
index a8d1a5d..c3b50cd 100644
--- a/go/arrow/cdata/cdata.go
+++ b/go/arrow/cdata/cdata.go
@@ -87,6 +87,7 @@ var formatToSimpleType = map[string]arrow.DataType{
        "tDn": arrow.FixedWidthTypes.Duration_ns,
        "tiM": arrow.FixedWidthTypes.MonthInterval,
        "tiD": arrow.FixedWidthTypes.DayTimeInterval,
+       "tin": arrow.FixedWidthTypes.MonthDayNanoInterval,
 }
 
 // decode metadata from C which is encoded as
diff --git a/go/arrow/cdata/cdata_exports.go b/go/arrow/cdata/cdata_exports.go
index 8565952..926a1cc 100644
--- a/go/arrow/cdata/cdata_exports.go
+++ b/go/arrow/cdata/cdata_exports.go
@@ -208,6 +208,8 @@ func (exp *schemaExporter) exportFormat(dt arrow.DataType) 
string {
                return "tiM"
        case *arrow.DayTimeIntervalType:
                return "tiD"
+       case *arrow.MonthDayNanoIntervalType:
+               return "tin"
        case *arrow.ListType:
                return "+l"
        case *arrow.FixedSizeListType:
diff --git a/go/arrow/cdata/cdata_test.go b/go/arrow/cdata/cdata_test.go
index 47cd334..cf6aba3 100644
--- a/go/arrow/cdata/cdata_test.go
+++ b/go/arrow/cdata/cdata_test.go
@@ -149,6 +149,7 @@ func TestImportTemporalSchema(t *testing.T) {
                {arrow.FixedWidthTypes.Duration_ns, "tDn"},
                {arrow.FixedWidthTypes.MonthInterval, "tiM"},
                {arrow.FixedWidthTypes.DayTimeInterval, "tiD"},
+               {arrow.FixedWidthTypes.MonthDayNanoInterval, "tin"},
                {arrow.FixedWidthTypes.Timestamp_s, "tss:"},
                {&arrow.TimestampType{Unit: arrow.Second, TimeZone: 
"Europe/Paris"}, "tss:Europe/Paris"},
                {arrow.FixedWidthTypes.Timestamp_ms, "tsm:"},
diff --git a/go/arrow/datatype_fixedwidth.go b/go/arrow/datatype_fixedwidth.go
index b30ee63..541f091 100644
--- a/go/arrow/datatype_fixedwidth.go
+++ b/go/arrow/datatype_fixedwidth.go
@@ -150,7 +150,7 @@ type Decimal128Type struct {
        Scale     int32
 }
 
-func (*Decimal128Type) ID() Type      { return DECIMAL }
+func (*Decimal128Type) ID() Type      { return DECIMAL128 }
 func (*Decimal128Type) Name() string  { return "decimal" }
 func (*Decimal128Type) BitWidth() int { return 128 }
 func (t *Decimal128Type) String() string {
@@ -193,45 +193,69 @@ func (*DayTimeIntervalType) Fingerprint() string { return 
typeIDFingerprint(INTE
 // BitWidth returns the number of bits required to store a single element of 
this data type in memory.
 func (t *DayTimeIntervalType) BitWidth() int { return 64 }
 
+// MonthDayNanoInterval represents a number of months, days and nanoseconds 
(fraction of day).
+type MonthDayNanoInterval struct {
+       Months      int32 `json:"months"`
+       Days        int32 `json:"days"`
+       Nanoseconds int64 `json:"nanoseconds"`
+}
+
+// MonthDayNanoIntervalType is encoded as two signed 32-bit integers 
representing
+// a number of months and a number of days, followed by a 64-bit integer 
representing
+// the number of nanoseconds since midnight for fractions of a day.
+type MonthDayNanoIntervalType struct{}
+
+func (*MonthDayNanoIntervalType) ID() Type       { return 
INTERVAL_MONTH_DAY_NANO }
+func (*MonthDayNanoIntervalType) Name() string   { return 
"month_day_nano_interval" }
+func (*MonthDayNanoIntervalType) String() string { return 
"month_day_nano_interval" }
+func (*MonthDayNanoIntervalType) Fingerprint() string {
+       return typeIDFingerprint(INTERVAL_MONTH_DAY_NANO) + "N"
+}
+
+// BitWidth returns the number of bits required to store a single element of 
this data type in memory.
+func (*MonthDayNanoIntervalType) BitWidth() int { return 128 }
+
 var (
        FixedWidthTypes = struct {
-               Boolean         FixedWidthDataType
-               Date32          FixedWidthDataType
-               Date64          FixedWidthDataType
-               DayTimeInterval FixedWidthDataType
-               Duration_s      FixedWidthDataType
-               Duration_ms     FixedWidthDataType
-               Duration_us     FixedWidthDataType
-               Duration_ns     FixedWidthDataType
-               Float16         FixedWidthDataType
-               MonthInterval   FixedWidthDataType
-               Time32s         FixedWidthDataType
-               Time32ms        FixedWidthDataType
-               Time64us        FixedWidthDataType
-               Time64ns        FixedWidthDataType
-               Timestamp_s     FixedWidthDataType
-               Timestamp_ms    FixedWidthDataType
-               Timestamp_us    FixedWidthDataType
-               Timestamp_ns    FixedWidthDataType
+               Boolean              FixedWidthDataType
+               Date32               FixedWidthDataType
+               Date64               FixedWidthDataType
+               DayTimeInterval      FixedWidthDataType
+               Duration_s           FixedWidthDataType
+               Duration_ms          FixedWidthDataType
+               Duration_us          FixedWidthDataType
+               Duration_ns          FixedWidthDataType
+               Float16              FixedWidthDataType
+               MonthInterval        FixedWidthDataType
+               Time32s              FixedWidthDataType
+               Time32ms             FixedWidthDataType
+               Time64us             FixedWidthDataType
+               Time64ns             FixedWidthDataType
+               Timestamp_s          FixedWidthDataType
+               Timestamp_ms         FixedWidthDataType
+               Timestamp_us         FixedWidthDataType
+               Timestamp_ns         FixedWidthDataType
+               MonthDayNanoInterval FixedWidthDataType
        }{
-               Boolean:         &BooleanType{},
-               Date32:          &Date32Type{},
-               Date64:          &Date64Type{},
-               DayTimeInterval: &DayTimeIntervalType{},
-               Duration_s:      &DurationType{Unit: Second},
-               Duration_ms:     &DurationType{Unit: Millisecond},
-               Duration_us:     &DurationType{Unit: Microsecond},
-               Duration_ns:     &DurationType{Unit: Nanosecond},
-               Float16:         &Float16Type{},
-               MonthInterval:   &MonthIntervalType{},
-               Time32s:         &Time32Type{Unit: Second},
-               Time32ms:        &Time32Type{Unit: Millisecond},
-               Time64us:        &Time64Type{Unit: Microsecond},
-               Time64ns:        &Time64Type{Unit: Nanosecond},
-               Timestamp_s:     &TimestampType{Unit: Second, TimeZone: "UTC"},
-               Timestamp_ms:    &TimestampType{Unit: Millisecond, TimeZone: 
"UTC"},
-               Timestamp_us:    &TimestampType{Unit: Microsecond, TimeZone: 
"UTC"},
-               Timestamp_ns:    &TimestampType{Unit: Nanosecond, TimeZone: 
"UTC"},
+               Boolean:              &BooleanType{},
+               Date32:               &Date32Type{},
+               Date64:               &Date64Type{},
+               DayTimeInterval:      &DayTimeIntervalType{},
+               Duration_s:           &DurationType{Unit: Second},
+               Duration_ms:          &DurationType{Unit: Millisecond},
+               Duration_us:          &DurationType{Unit: Microsecond},
+               Duration_ns:          &DurationType{Unit: Nanosecond},
+               Float16:              &Float16Type{},
+               MonthInterval:        &MonthIntervalType{},
+               Time32s:              &Time32Type{Unit: Second},
+               Time32ms:             &Time32Type{Unit: Millisecond},
+               Time64us:             &Time64Type{Unit: Microsecond},
+               Time64ns:             &Time64Type{Unit: Nanosecond},
+               Timestamp_s:          &TimestampType{Unit: Second, TimeZone: 
"UTC"},
+               Timestamp_ms:         &TimestampType{Unit: Millisecond, 
TimeZone: "UTC"},
+               Timestamp_us:         &TimestampType{Unit: Microsecond, 
TimeZone: "UTC"},
+               Timestamp_ns:         &TimestampType{Unit: Nanosecond, 
TimeZone: "UTC"},
+               MonthDayNanoInterval: &MonthDayNanoIntervalType{},
        }
 
        _ FixedWidthDataType = (*FixedSizeBinaryType)(nil)
diff --git a/go/arrow/internal/arrdata/arrdata.go 
b/go/arrow/internal/arrdata/arrdata.go
index 69dc8a1..77f3d35 100644
--- a/go/arrow/internal/arrdata/arrdata.go
+++ b/go/arrow/internal/arrdata/arrdata.go
@@ -553,6 +553,7 @@ func makeIntervalsRecords() []array.Record {
                []arrow.Field{
                        arrow.Field{Name: "months", Type: 
arrow.FixedWidthTypes.MonthInterval, Nullable: true},
                        arrow.Field{Name: "days", Type: 
arrow.FixedWidthTypes.DayTimeInterval, Nullable: true},
+                       arrow.Field{Name: "nanos", Type: 
arrow.FixedWidthTypes.MonthDayNanoInterval, Nullable: true},
                }, nil,
        )
 
@@ -561,14 +562,17 @@ func makeIntervalsRecords() []array.Record {
                []array.Interface{
                        arrayOf(mem, []arrow.MonthInterval{1, 2, 3, 4, 5}, 
mask),
                        arrayOf(mem, []arrow.DayTimeInterval{{1, 1}, {2, 2}, 
{3, 3}, {4, 4}, {5, 5}}, mask),
+                       arrayOf(mem, []arrow.MonthDayNanoInterval{{1, 1, 1000}, 
{2, 2, 2000}, {3, 3, 3000}, {4, 4, 4000}, {5, 5, 5000}}, mask),
                },
                []array.Interface{
-                       arrayOf(mem, []arrow.MonthInterval{11, 12, 13, 14, 15}, 
mask),
-                       arrayOf(mem, []arrow.DayTimeInterval{{11, 11}, {12, 
12}, {13, 13}, {14, 14}, {15, 15}}, mask),
+                       arrayOf(mem, []arrow.MonthInterval{-11, -12, -13, -14, 
-15}, mask),
+                       arrayOf(mem, []arrow.DayTimeInterval{{-11, -11}, {-12, 
-12}, {-13, -13}, {-14, -14}, {-15, -15}}, mask),
+                       arrayOf(mem, []arrow.MonthDayNanoInterval{{-11, -11, 
-11000}, {-12, -12, -12000}, {-13, -13, -13000}, {-14, -14, -14000}, {-15, -15, 
-15000}}, mask),
                },
                []array.Interface{
-                       arrayOf(mem, []arrow.MonthInterval{21, 22, 23, 24, 25}, 
mask),
-                       arrayOf(mem, []arrow.DayTimeInterval{{21, 21}, {22, 
22}, {23, 23}, {24, 24}, {25, 25}}, mask),
+                       arrayOf(mem, []arrow.MonthInterval{21, 22, 23, 24, 25, 
0}, append(mask, true)),
+                       arrayOf(mem, []arrow.DayTimeInterval{{21, 21}, {22, 
22}, {23, 23}, {24, 24}, {25, 25}, {0, 0}}, append(mask, true)),
+                       arrayOf(mem, []arrow.MonthDayNanoInterval{{21, 21, 
21000}, {22, 22, 22000}, {23, 23, 23000}, {24, 24, 24000}, {25, 25, 25000}, {0, 
0, 0}}, append(mask, true)),
                },
        }
 
@@ -1153,6 +1157,13 @@ func arrayOf(mem memory.Allocator, a interface{}, valids 
[]bool) array.Interface
                bldr.AppendValues(a, valids)
                return bldr.NewArray()
 
+       case []arrow.MonthDayNanoInterval:
+               bldr := array.NewMonthDayNanoIntervalBuilder(mem)
+               defer bldr.Release()
+
+               bldr.AppendValues(a, valids)
+               return bldr.NewArray()
+
        case []duration_s:
                bldr := array.NewDurationBuilder(mem, &arrow.DurationType{Unit: 
arrow.Second})
                defer bldr.Release()
diff --git a/go/arrow/internal/arrjson/arrjson.go 
b/go/arrow/internal/arrjson/arrjson.go
index a8209ea..c792229 100644
--- a/go/arrow/internal/arrjson/arrjson.go
+++ b/go/arrow/internal/arrjson/arrjson.go
@@ -169,6 +169,8 @@ func (f FieldWrapper) MarshalJSON() ([]byte, error) {
                typ = unitZoneJSON{Name: "interval", Unit: "YEAR_MONTH"}
        case *arrow.DayTimeIntervalType:
                typ = unitZoneJSON{Name: "interval", Unit: "DAY_TIME"}
+       case *arrow.MonthDayNanoIntervalType:
+               typ = unitZoneJSON{Name: "interval", Unit: "MONTH_DAY_NANO"}
        case *arrow.DurationType:
                switch dt.Unit {
                case arrow.Second:
@@ -388,6 +390,8 @@ func (f *FieldWrapper) UnmarshalJSON(data []byte) error {
                        f.arrowType = arrow.FixedWidthTypes.MonthInterval
                case "DAY_TIME":
                        f.arrowType = arrow.FixedWidthTypes.DayTimeInterval
+               case "MONTH_DAY_NANO":
+                       f.arrowType = arrow.FixedWidthTypes.MonthDayNanoInterval
                }
        case "duration":
                t := unitZoneJSON{}
@@ -889,6 +893,14 @@ func arrayFromJSON(mem memory.Allocator, dt 
arrow.DataType, arr Array) array.Int
                bldr.AppendValues(data, valids)
                return bldr.NewArray()
 
+       case *arrow.MonthDayNanoIntervalType:
+               bldr := array.NewMonthDayNanoIntervalBuilder(mem)
+               defer bldr.Release()
+               data := monthDayNanointervalFromJSON(arr.Data)
+               valids := validsFromJSON(arr.Valids)
+               bldr.AppendValues(data, valids)
+               return bldr.NewArray()
+
        case *arrow.DurationType:
                bldr := array.NewDurationBuilder(mem, dt)
                defer bldr.Release()
@@ -1155,6 +1167,13 @@ func arrayToJSON(field arrow.Field, arr array.Interface) 
Array {
                        Data:   daytimeintervalToJSON(arr),
                        Valids: validsToJSON(arr),
                }
+       case *array.MonthDayNanoInterval:
+               return Array{
+                       Name:   field.Name,
+                       Count:  arr.Len(),
+                       Data:   monthDayNanointervalToJSON(arr),
+                       Valids: validsToJSON(arr),
+               }
        case *array.Duration:
                return Array{
                        Name:   field.Name,
@@ -1672,6 +1691,35 @@ func daytimeintervalToJSON(arr *array.DayTimeInterval) 
[]interface{} {
        return o
 }
 
+func monthDayNanointervalFromJSON(vs []interface{}) 
[]arrow.MonthDayNanoInterval {
+       o := make([]arrow.MonthDayNanoInterval, len(vs))
+       for i, vv := range vs {
+               v := vv.(map[string]interface{})
+               months, err := v["months"].(json.Number).Int64()
+               if err != nil {
+                       panic(err)
+               }
+               days, err := v["days"].(json.Number).Int64()
+               if err != nil {
+                       panic(err)
+               }
+               ns, err := v["nanoseconds"].(json.Number).Int64()
+               if err != nil {
+                       panic(err)
+               }
+               o[i] = arrow.MonthDayNanoInterval{Months: int32(months), Days: 
int32(days), Nanoseconds: ns}
+       }
+       return o
+}
+
+func monthDayNanointervalToJSON(arr *array.MonthDayNanoInterval) []interface{} 
{
+       o := make([]interface{}, arr.Len())
+       for i := range o {
+               o[i] = arr.Value(i)
+       }
+       return o
+}
+
 func durationFromJSON(vs []interface{}) []arrow.Duration {
        o := make([]arrow.Duration, len(vs))
        for i, v := range vs {
diff --git a/go/arrow/internal/arrjson/arrjson_test.go 
b/go/arrow/internal/arrjson/arrjson_test.go
index 6ffbfa9..c16145b 100644
--- a/go/arrow/internal/arrjson/arrjson_test.go
+++ b/go/arrow/internal/arrjson/arrjson_test.go
@@ -2673,6 +2673,15 @@ func makeIntervalsWantJSONs() string {
         },
         "nullable": true,
         "children": []
+      },
+      {
+        "name": "nanos",
+        "type": {
+          "name": "interval",
+          "unit": "MONTH_DAY_NANO"
+        },
+        "nullable": true,
+        "children": []
       }
     ]
   },
@@ -2730,6 +2739,44 @@ func makeIntervalsWantJSONs() string {
               "milliseconds": 5
             }
           ]
+        },
+        {
+          "name": "nanos",
+          "count": 5,
+          "VALIDITY": [
+            1,
+            0,
+            0,
+            1,
+            1
+          ],
+          "DATA": [
+            {
+              "months": 1,
+              "days": 1,
+              "nanoseconds": 1000
+            },
+            {
+              "months": 2,
+              "days": 2,
+              "nanoseconds": 2000
+            },
+            {
+              "months": 3,
+              "days": 3,
+              "nanoseconds": 3000
+            },
+            {
+              "months": 4,
+              "days": 4,
+              "nanoseconds": 4000
+            },
+            {
+              "months": 5,
+              "days": 5,
+              "nanoseconds": 5000
+            }
+          ]
         }
       ]
     },
@@ -2747,11 +2794,11 @@ func makeIntervalsWantJSONs() string {
             1
           ],
           "DATA": [
-            11,
-            12,
-            13,
-            14,
-            15
+            -11,
+            -12,
+            -13,
+            -14,
+            -15
           ]
         },
         {
@@ -2766,40 +2813,79 @@ func makeIntervalsWantJSONs() string {
           ],
           "DATA": [
             {
-              "days": 11,
-              "milliseconds": 11
+              "days": -11,
+              "milliseconds": -11
             },
             {
-              "days": 12,
-              "milliseconds": 12
+              "days": -12,
+              "milliseconds": -12
             },
             {
-              "days": 13,
-              "milliseconds": 13
+              "days": -13,
+              "milliseconds": -13
             },
             {
-              "days": 14,
-              "milliseconds": 14
+              "days": -14,
+              "milliseconds": -14
             },
             {
-              "days": 15,
-              "milliseconds": 15
+              "days": -15,
+              "milliseconds": -15
+            }
+          ]
+        },
+        {
+          "name": "nanos",
+          "count": 5,
+          "VALIDITY": [
+            1,
+            0,
+            0,
+            1,
+            1
+          ],
+          "DATA": [
+            {
+              "months": -11,
+              "days": -11,
+              "nanoseconds": -11000
+            },
+            {
+              "months": -12,
+              "days": -12,
+              "nanoseconds": -12000
+            },
+            {
+              "months": -13,
+              "days": -13,
+              "nanoseconds": -13000
+            },
+            {
+              "months": -14,
+              "days": -14,
+              "nanoseconds": -14000
+            },
+            {
+              "months": -15,
+              "days": -15,
+              "nanoseconds": -15000
             }
           ]
         }
       ]
     },
     {
-      "count": 5,
+      "count": 6,
       "columns": [
         {
           "name": "months",
-          "count": 5,
+          "count": 6,
           "VALIDITY": [
             1,
             0,
             0,
             1,
+            1,
             1
           ],
           "DATA": [
@@ -2807,17 +2893,19 @@ func makeIntervalsWantJSONs() string {
             22,
             23,
             24,
-            25
+            25,
+            0
           ]
         },
         {
           "name": "days",
-          "count": 5,
+          "count": 6,
           "VALIDITY": [
             1,
             0,
             0,
             1,
+            1,
             1
           ],
           "DATA": [
@@ -2840,6 +2928,54 @@ func makeIntervalsWantJSONs() string {
             {
               "days": 25,
               "milliseconds": 25
+            },
+            {
+              "days": 0,
+              "milliseconds": 0
+            }
+          ]
+        },
+        {
+          "name": "nanos",
+          "count": 6,
+          "VALIDITY": [
+            1,
+            0,
+            0,
+            1,
+            1,
+            1
+          ],
+          "DATA": [
+            {
+              "months": 21,
+              "days": 21,
+              "nanoseconds": 21000
+            },
+            {
+              "months": 22,
+              "days": 22,
+              "nanoseconds": 22000
+            },
+            {
+              "months": 23,
+              "days": 23,
+              "nanoseconds": 23000
+            },
+            {
+              "months": 24,
+              "days": 24,
+              "nanoseconds": 24000
+            },
+            {
+              "months": 25,
+              "days": 25,
+              "nanoseconds": 25000
+            },
+            {
+              "months": 0,
+              "days": 0,
+              "nanoseconds": 0
             }
           ]
         }
diff --git 
a/go/arrow/internal/flight_integration/cmd/arrow-flight-integration-server/main.go
 
b/go/arrow/internal/flight_integration/cmd/arrow-flight-integration-server/main.go
index 7384a74..5459086 100644
--- 
a/go/arrow/internal/flight_integration/cmd/arrow-flight-integration-server/main.go
+++ 
b/go/arrow/internal/flight_integration/cmd/arrow-flight-integration-server/main.go
@@ -36,7 +36,6 @@ func main() {
 
        s := flight_integration.GetScenario(*scenario)
        srv := s.MakeServer(*port)
-       srv.Init(fmt.Sprintf("0.0.0.0:%d", *port))
        srv.SetShutdownOnSignals(syscall.SIGTERM, os.Interrupt)
        _, p, _ := net.SplitHostPort(srv.Addr().String())
        fmt.Printf("Server listening on localhost:%s\n", p)
diff --git a/go/arrow/internal/flight_integration/scenario.go 
b/go/arrow/internal/flight_integration/scenario.go
index edafe05..32e5006 100644
--- a/go/arrow/internal/flight_integration/scenario.go
+++ b/go/arrow/internal/flight_integration/scenario.go
@@ -21,6 +21,7 @@ import (
        "context"
        "fmt"
        "io"
+       "net"
        "os"
        "strconv"
 
@@ -58,6 +59,13 @@ func GetScenario(name string, args ...string) Scenario {
        panic(fmt.Errorf("scenario not found: %s", name))
 }
 
+func initServer(port int, srv flight.Server) int {
+       srv.Init(fmt.Sprintf("0.0.0.0:%d", port))
+       _, p, _ := net.SplitHostPort(srv.Addr().String())
+       port, _ = strconv.Atoi(p)
+       return port
+}
+
 type integrationDataSet struct {
        schema *arrow.Schema
        chunks []array.Record
@@ -209,7 +217,6 @@ func (s *defaultIntegrationTester) RunClient(addr string, 
opts ...grpc.DialOptio
 }
 
 func (s *defaultIntegrationTester) MakeServer(port int) flight.Server {
-       s.port = port
        s.uploadedChunks = make(map[string]integrationDataSet)
        srv := flight.NewServerWithMiddleware(nil, nil)
        srv.RegisterFlightService(&flight.FlightServiceService{
@@ -217,6 +224,7 @@ func (s *defaultIntegrationTester) MakeServer(port int) 
flight.Server {
                DoGet:         s.DoGet,
                DoPut:         s.DoPut,
        })
+       s.port = initServer(port, srv)
        return srv
 }
 
@@ -236,7 +244,7 @@ func (s *defaultIntegrationTester) GetFlightInfo(ctx 
context.Context, in *flight
                        FlightDescriptor: in,
                        Endpoint: []*flight.FlightEndpoint{{
                                Ticket:   &flight.Ticket{Ticket: 
[]byte(in.Path[0])},
-                               Location: []*flight.Location{{Uri: 
fmt.Sprintf("127.0.0.1:%d", s.port)}},
+                               Location: []*flight.Location{{Uri: 
fmt.Sprintf("grpc+tcp://127.0.0.1:%d", s.port)}},
                        }},
                        TotalRecords: 0,
                        TotalBytes:   -1,
@@ -420,12 +428,13 @@ func (s *authBasicProtoTester) RunClient(addr string, 
opts ...grpc.DialOption) e
        return CheckActionResults(ctx, client, &flight.Action{}, 
[]string{authUsername})
 }
 
-func (s *authBasicProtoTester) MakeServer(_ int) flight.Server {
+func (s *authBasicProtoTester) MakeServer(port int) flight.Server {
        srv := flight.NewServerWithMiddleware(&authBasicValidator{
                auth: flight.BasicAuth{Username: authUsername, Password: 
authPassword}}, nil)
        srv.RegisterFlightService(&flight.FlightServiceService{
                DoAction: s.DoAction,
        })
+       initServer(port, srv)
        return srv
 }
 
@@ -470,12 +479,13 @@ func (m *middlewareScenarioTester) RunClient(addr string, 
opts ...grpc.DialOptio
        return nil
 }
 
-func (m *middlewareScenarioTester) MakeServer(_ int) flight.Server {
+func (m *middlewareScenarioTester) MakeServer(port int) flight.Server {
        srv := flight.NewServerWithMiddleware(nil, []flight.ServerMiddleware{
                flight.CreateServerMiddleware(testServerMiddleware{})})
        srv.RegisterFlightService(&flight.FlightServiceService{
                GetFlightInfo: m.GetFlightInfo,
        })
+       initServer(port, srv)
        return srv
 }
 
@@ -489,7 +499,7 @@ func (m *middlewareScenarioTester) GetFlightInfo(ctx 
context.Context, desc *flig
                FlightDescriptor: desc,
                Endpoint: []*flight.FlightEndpoint{{
                        Ticket:   &flight.Ticket{Ticket: []byte("foo")},
-                       Location: []*flight.Location{{Uri: "localhost:10010"}},
+                       Location: []*flight.Location{{Uri: 
"grpc+tcp://localhost:10010"}},
                }},
                TotalRecords: -1,
                TotalBytes:   -1,
diff --git a/go/arrow/ipc/file_reader.go b/go/arrow/ipc/file_reader.go
index 04d736f..d744358 100644
--- a/go/arrow/ipc/file_reader.go
+++ b/go/arrow/ipc/file_reader.go
@@ -430,7 +430,7 @@ func (ctx *arrayLoaderContext) loadArray(dt arrow.DataType) 
array.Interface {
                *arrow.Time32Type, *arrow.Time64Type,
                *arrow.TimestampType,
                *arrow.Date32Type, *arrow.Date64Type,
-               *arrow.MonthIntervalType, *arrow.DayTimeIntervalType,
+               *arrow.MonthIntervalType, *arrow.DayTimeIntervalType, 
*arrow.MonthDayNanoIntervalType,
                *arrow.DurationType:
                return ctx.loadPrimitive(dt)
 
diff --git a/go/arrow/ipc/metadata.go b/go/arrow/ipc/metadata.go
index 9f6333b..9d2d7f0 100644
--- a/go/arrow/ipc/metadata.go
+++ b/go/arrow/ipc/metadata.go
@@ -370,6 +370,12 @@ func (fv *fieldVisitor) visit(field arrow.Field) {
                flatbuf.IntervalAddUnit(fv.b, flatbuf.IntervalUnitDAY_TIME)
                fv.offset = flatbuf.IntervalEnd(fv.b)
 
+       case *arrow.MonthDayNanoIntervalType:
+               fv.dtype = flatbuf.TypeInterval
+               flatbuf.IntervalStart(fv.b)
+               flatbuf.IntervalAddUnit(fv.b, 
flatbuf.IntervalUnitMONTH_DAY_NANO)
+               fv.offset = flatbuf.IntervalEnd(fv.b)
+
        case *arrow.DurationType:
                fv.dtype = flatbuf.TypeDuration
                unit := unitToFB(dt.Unit)
@@ -806,6 +812,8 @@ func intervalFromFB(data flatbuf.Interval) (arrow.DataType, 
error) {
                return arrow.FixedWidthTypes.MonthInterval, nil
        case flatbuf.IntervalUnitDAY_TIME:
                return arrow.FixedWidthTypes.DayTimeInterval, nil
+       case flatbuf.IntervalUnitMONTH_DAY_NANO:
+               return arrow.FixedWidthTypes.MonthDayNanoInterval, nil
        }
        return nil, xerrors.Errorf("arrow/ipc: Interval type with %d unit not 
implemented", data.Unit())
 }
diff --git a/go/arrow/scalar/parse.go b/go/arrow/scalar/parse.go
index 2a96372..78bbff8 100644
--- a/go/arrow/scalar/parse.go
+++ b/go/arrow/scalar/parse.go
@@ -150,6 +150,8 @@ func MakeScalar(val interface{}) Scalar {
                return NewMonthIntervalScalar(v)
        case arrow.DayTimeInterval:
                return NewDayTimeIntervalScalar(v)
+       case arrow.MonthDayNanoInterval:
+               return NewMonthDayNanoIntervalScalar(v)
        case arrow.DataType:
                return MakeNullScalar(v)
        }
diff --git a/go/arrow/scalar/scalar.go b/go/arrow/scalar/scalar.go
index 1662081..0275866 100644
--- a/go/arrow/scalar/scalar.go
+++ b/go/arrow/scalar/scalar.go
@@ -295,7 +295,7 @@ func (s *Decimal128) CastTo(to arrow.DataType) (Scalar, 
error) {
        }
 
        switch to.ID() {
-       case arrow.DECIMAL:
+       case arrow.DECIMAL128:
                return NewDecimal128Scalar(s.Value, to), nil
        case arrow.STRING:
                dt := s.Type.(*arrow.Decimal128Type)
@@ -431,10 +431,14 @@ func init() {
                        if arrow.TypeEqual(dt, 
arrow.FixedWidthTypes.MonthInterval) {
                                return &MonthInterval{scalar: scalar{dt, false}}
                        }
+                       if arrow.TypeEqual(dt, 
arrow.FixedWidthTypes.MonthDayNanoInterval) {
+                               return &MonthDayNanoInterval{scalar: scalar{dt, 
false}}
+                       }
                        return &DayTimeInterval{scalar: scalar{dt, false}}
                },
                arrow.INTERVAL_MONTHS:         func(dt arrow.DataType) Scalar { 
return &MonthInterval{scalar: scalar{dt, false}} },
                arrow.INTERVAL_DAY_TIME:       func(dt arrow.DataType) Scalar { 
return &DayTimeInterval{scalar: scalar{dt, false}} },
+               arrow.INTERVAL_MONTH_DAY_NANO: func(dt arrow.DataType) Scalar { 
return &MonthDayNanoInterval{scalar: scalar{dt, false}} },
                arrow.DECIMAL128:              func(dt arrow.DataType) Scalar { 
return &Decimal128{scalar: scalar{dt, false}} },
                arrow.LIST:                    func(dt arrow.DataType) Scalar { 
return &List{scalar: scalar{dt, false}} },
                arrow.STRUCT:                  func(dt arrow.DataType) Scalar { 
return &Struct{scalar: scalar{dt, false}} },
@@ -449,9 +453,7 @@ func init() {
                arrow.EXTENSION:               func(dt arrow.DataType) Scalar { 
return &Extension{scalar: scalar{dt, false}} },
                arrow.FIXED_SIZE_LIST:         func(dt arrow.DataType) Scalar { 
return &FixedSizeList{&List{scalar: scalar{dt, false}}} },
                arrow.DURATION:                func(dt arrow.DataType) Scalar { 
return &Duration{scalar: scalar{dt, false}} },
-               arrow.INTERVAL_MONTH_DAY_NANO: unsupportedScalarType,
-
-               // invalid data types to fill out array size 2⁵-1
+               // invalid data types to fill out array size 2^6 - 1
                63: invalidScalarType,
        }
 
@@ -530,6 +532,8 @@ func GetScalar(arr array.Interface, idx int) (Scalar, 
error) {
                return NewMapScalar(slice), nil
        case *array.MonthInterval:
                return NewMonthIntervalScalar(arr.Value(idx)), nil
+       case *array.MonthDayNanoInterval:
+               return NewMonthDayNanoIntervalScalar(arr.Value(idx)), nil
        case *array.Null:
                return ScalarNull, nil
        case *array.String:
@@ -773,6 +777,8 @@ func Hash(seed maphash.Seed, s Scalar) uint64 {
                out ^= Hash(seed, s.Value)
        case *DayTimeInterval:
                return valueHash(s.Value.Days) & valueHash(s.Value.Milliseconds)
+       case *MonthDayNanoInterval:
+               return valueHash(s.Value.Months) & valueHash(s.Value.Days) & 
valueHash(s.Value.Nanoseconds)
        case PrimitiveScalar:
                h.Write(s.Data())
                hash()
diff --git a/go/arrow/scalar/scalar_test.go b/go/arrow/scalar/scalar_test.go
index 6791c4a..dc476e8 100644
--- a/go/arrow/scalar/scalar_test.go
+++ b/go/arrow/scalar/scalar_test.go
@@ -493,6 +493,31 @@ func TestDayTimeIntervalScalarBasics(t *testing.T) {
        assert.False(t, scalar.Equals(tsNull, tsVal2))
 }
 
+func TestMonthDayNanoIntervalScalarBasics(t *testing.T) {
+       typ := arrow.FixedWidthTypes.MonthDayNanoInterval
+
+       val1 := arrow.MonthDayNanoInterval{Months: 1, Days: 2, Nanoseconds: 
3000}
+       val2 := arrow.MonthDayNanoInterval{Months: 2, Days: 3, Nanoseconds: 
4000}
+       tsVal1 := scalar.NewMonthDayNanoIntervalScalar(val1)
+       tsVal2 := scalar.NewMonthDayNanoIntervalScalar(val2)
+       tsNull := scalar.MakeNullScalar(typ)
+       assert.NoError(t, tsVal1.ValidateFull())
+       assert.NoError(t, tsVal2.ValidateFull())
+       assert.NoError(t, tsNull.ValidateFull())
+
+       assert.Equal(t, val1, tsVal1.Value)
+
+       assert.True(t, arrow.TypeEqual(tsVal1.Type, typ))
+       assert.True(t, arrow.TypeEqual(tsVal2.DataType(), typ))
+       assert.True(t, tsVal1.Valid)
+       assert.False(t, tsNull.IsValid())
+       assert.True(t, arrow.TypeEqual(typ, tsNull.DataType()))
+
+       assert.False(t, scalar.Equals(tsVal1, tsVal2))
+       assert.False(t, scalar.Equals(tsVal1, tsNull))
+       assert.False(t, scalar.Equals(tsNull, tsVal2))
+}
+
 func TestNumericScalarCasts(t *testing.T) {
        tests := []arrow.DataType{
                arrow.PrimitiveTypes.Int8,
@@ -793,6 +818,7 @@ func TestStructScalarValidateErrors(t *testing.T) {
 func getScalars(mem memory.Allocator) []scalar.Scalar {
        hello := memory.NewBufferBytes([]byte("hello"))
        daytime := arrow.DayTimeInterval{Days: 1, Milliseconds: 100}
+       monthdaynano := arrow.MonthDayNanoInterval{Months: 5, Days: 4, 
Nanoseconds: 100}
 
        int8Bldr := array.NewInt8Builder(mem)
        defer int8Bldr.Release()
@@ -828,6 +854,7 @@ func getScalars(mem memory.Allocator) []scalar.Scalar {
                scalar.NewTimestampScalar(111, 
arrow.FixedWidthTypes.Timestamp_ms),
                scalar.NewMonthIntervalScalar(1),
                scalar.NewDayTimeIntervalScalar(daytime),
+               scalar.NewMonthDayNanoIntervalScalar(monthdaynano),
                scalar.NewDurationScalar(60, arrow.FixedWidthTypes.Duration_s),
                scalar.NewBinaryScalar(hello, arrow.BinaryTypes.Binary),
                scalar.NewFixedSizeBinaryScalar(hello, 
&arrow.FixedSizeBinaryType{ByteWidth: hello.Len()}),
diff --git a/go/arrow/scalar/temporal.go b/go/arrow/scalar/temporal.go
index 47a4dec4..3dba569 100644
--- a/go/arrow/scalar/temporal.go
+++ b/go/arrow/scalar/temporal.go
@@ -464,6 +464,48 @@ func NewDayTimeIntervalScalar(val arrow.DayTimeInterval) 
*DayTimeInterval {
        return &DayTimeInterval{scalar{arrow.FixedWidthTypes.DayTimeInterval, 
true}, val}
 }
 
+type MonthDayNanoInterval struct {
+       scalar
+       Value arrow.MonthDayNanoInterval
+}
+
+func (MonthDayNanoInterval) temporal()             {}
+func (MonthDayNanoInterval) interval()             {}
+func (s *MonthDayNanoInterval) value() interface{} { return s.Value }
+func (s *MonthDayNanoInterval) Data() []byte {
+       return 
(*[arrow.MonthDayNanoIntervalSizeBytes]byte)(unsafe.Pointer(&s.Value))[:]
+}
+func (s *MonthDayNanoInterval) String() string {
+       if !s.Valid {
+               return "null"
+       }
+       val, err := s.CastTo(arrow.BinaryTypes.String)
+       if err != nil {
+               return "..."
+       }
+       return string(val.(*String).Value.Bytes())
+}
+
+func (s *MonthDayNanoInterval) CastTo(to arrow.DataType) (Scalar, error) {
+       if !s.Valid {
+               return MakeNullScalar(to), nil
+       }
+
+       if !arrow.TypeEqual(s.DataType(), to) {
+               return nil, xerrors.Errorf("non-null month_day_nano_interval 
scalar cannot be cast to anything other than monthinterval")
+       }
+
+       return s, nil
+}
+
+func (s *MonthDayNanoInterval) equals(rhs Scalar) bool {
+       return s.Value == rhs.(*MonthDayNanoInterval).Value
+}
+
+func NewMonthDayNanoIntervalScalar(val arrow.MonthDayNanoInterval) 
*MonthDayNanoInterval {
+       return 
&MonthDayNanoInterval{scalar{arrow.FixedWidthTypes.MonthDayNanoInterval, true}, 
val}
+}
+
 var (
        _ Scalar = (*Date32)(nil)
 )
diff --git a/go/arrow/type_traits_interval.go b/go/arrow/type_traits_interval.go
index f4f4dfe..13ede6c 100644
--- a/go/arrow/type_traits_interval.go
+++ b/go/arrow/type_traits_interval.go
@@ -21,13 +21,21 @@ import (
        "unsafe"
 
        "github.com/apache/arrow/go/arrow/endian"
+       "github.com/apache/arrow/go/arrow/internal/debug"
 )
 
 var (
-       MonthIntervalTraits   monthTraits
-       DayTimeIntervalTraits daytimeTraits
+       MonthIntervalTraits        monthTraits
+       DayTimeIntervalTraits      daytimeTraits
+       MonthDayNanoIntervalTraits monthDayNanoTraits
 )
 
+func init() {
+       debug.Assert(MonthIntervalSizeBytes == 4, "MonthIntervalSizeBytes 
should be 4")
+       debug.Assert(DayTimeIntervalSizeBytes == 8, "DayTimeIntervalSizeBytes 
should be 8")
+       debug.Assert(MonthDayNanoIntervalSizeBytes == 16, 
"MonthDayNanoIntervalSizeBytes should be 16")
+}
+
 // MonthInterval traits
 
 const (
@@ -124,3 +132,53 @@ func (daytimeTraits) CastToBytes(b []DayTimeInterval) 
[]byte {
 
 // Copy copies src to dst.
 func (daytimeTraits) Copy(dst, src []DayTimeInterval) { copy(dst, src) }
+
+// DayTimeInterval traits
+
+const (
+       // MonthDayNanoIntervalSizeBytes specifies the number of bytes required 
to store a single DayTimeInterval in memory
+       MonthDayNanoIntervalSizeBytes = 
int(unsafe.Sizeof(MonthDayNanoInterval{}))
+)
+
+type monthDayNanoTraits struct{}
+
+// BytesRequired returns the number of bytes required to store n elements in 
memory.
+func (monthDayNanoTraits) BytesRequired(n int) int { return 
MonthDayNanoIntervalSizeBytes * n }
+
+// PutValue
+func (monthDayNanoTraits) PutValue(b []byte, v MonthDayNanoInterval) {
+       endian.Native.PutUint32(b[0:4], uint32(v.Months))
+       endian.Native.PutUint32(b[4:8], uint32(v.Days))
+       endian.Native.PutUint64(b[8:], uint64(v.Nanoseconds))
+}
+
+// CastFromBytes reinterprets the slice b to a slice of type 
MonthDayNanoInterval.
+//
+// NOTE: len(b) must be a multiple of MonthDayNanoIntervalSizeBytes.
+func (monthDayNanoTraits) CastFromBytes(b []byte) []MonthDayNanoInterval {
+       h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+
+       var res []MonthDayNanoInterval
+       s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+       s.Data = h.Data
+       s.Len = h.Len / MonthDayNanoIntervalSizeBytes
+       s.Cap = h.Cap / MonthDayNanoIntervalSizeBytes
+
+       return res
+}
+
+// CastToBytes reinterprets the slice b to a slice of bytes.
+func (monthDayNanoTraits) CastToBytes(b []MonthDayNanoInterval) []byte {
+       h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+
+       var res []byte
+       s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+       s.Data = h.Data
+       s.Len = h.Len * MonthDayNanoIntervalSizeBytes
+       s.Cap = h.Cap * MonthDayNanoIntervalSizeBytes
+
+       return res
+}
+
+// Copy copies src to dst.
+func (monthDayNanoTraits) Copy(dst, src []MonthDayNanoInterval) { copy(dst, 
src) }
diff --git a/go/arrow/type_traits_test.go b/go/arrow/type_traits_test.go
index 59ad06e..b367475 100644
--- a/go/arrow/type_traits_test.go
+++ b/go/arrow/type_traits_test.go
@@ -199,3 +199,37 @@ func TestDayTimeIntervalTraits(t *testing.T) {
                t.Fatalf("invalid values:\nv1=%v\nv2=%v\n", v1, v2)
        }
 }
+
+func TestMonthDayNanoIntervalTraits(t *testing.T) {
+       const N = 10
+       b1 := 
arrow.MonthDayNanoIntervalTraits.CastToBytes([]arrow.MonthDayNanoInterval{
+               {0, 0, 0}, {1, 1, 1000}, {2, 2, 2000}, {3, 3, 3000}, {4, 4, 
4000}, {5, 5, 5000}, {6, 6, 6000}, {7, 7, 7000}, {8, 8, 8000}, {9, 9, 9000},
+       })
+
+       b2 := make([]byte, arrow.MonthDayNanoIntervalTraits.BytesRequired(N))
+       for i := 0; i < N; i++ {
+               beg := i * arrow.MonthDayNanoIntervalSizeBytes
+               end := (i + 1) * arrow.MonthDayNanoIntervalSizeBytes
+               arrow.MonthDayNanoIntervalTraits.PutValue(b2[beg:end], 
arrow.MonthDayNanoInterval{int32(i), int32(i), int64(i) * 1000})
+       }
+
+       if !reflect.DeepEqual(b1, b2) {
+               v1 := arrow.MonthDayNanoIntervalTraits.CastFromBytes(b1)
+               v2 := arrow.MonthDayNanoIntervalTraits.CastFromBytes(b2)
+               t.Fatalf("invalid values:\nb1=%v\nb2=%v\nv1=%v\nv2=%v\n", b1, 
b2, v1, v2)
+       }
+
+       v1 := arrow.MonthDayNanoIntervalTraits.CastFromBytes(b1)
+       for i, v := range v1 {
+               if got, want := v, (arrow.MonthDayNanoInterval{int32(i), 
int32(i), int64(i) * 1000}); got != want {
+                       t.Fatalf("invalid value[%d]. got=%v, want=%v", i, got, 
want)
+               }
+       }
+
+       v2 := make([]arrow.MonthDayNanoInterval, N)
+       arrow.MonthDayNanoIntervalTraits.Copy(v2, v1)
+
+       if !reflect.DeepEqual(v1, v2) {
+               t.Fatalf("invalid values:\nv1=%v\nv2=%v\n", v1, v2)
+       }
+}
diff --git 
a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightStream.java
 
b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightStream.java
index 5ac22c0..03ce13c 100644
--- 
a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightStream.java
+++ 
b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightStream.java
@@ -399,6 +399,14 @@ public class FlightStream implements AutoCloseable {
         }
         case SCHEMA: {
           Schema schema = msg.asSchema();
+          
+          // if there is app metadata in the schema message, make sure
+          // that we don't leak it.
+          ArrowBuf meta = msg.getApplicationMetadata();
+          if (meta != null) {
+            meta.close();
+          }
+
           final List<Field> fields = new ArrayList<>();
           final Map<Long, Dictionary> dictionaryMap = new HashMap<>();
           for (final Field originalField : schema.getFields()) {
@@ -419,7 +427,7 @@ public class FlightStream implements AutoCloseable {
           }
 
           synchronized (completed) {
-            if (!completed.isDone()) {
+            if (!completed.isDone()) {              
               fulfilledRoot = VectorSchemaRoot.create(schema, allocator);
               loader = new VectorLoader(fulfilledRoot);
               if (msg.getDescriptor() != null) {

Reply via email to