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

zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 3adf236  feat(go/sqldriver): convert Arrow times and dates to Golang 
time.Time (#393)
3adf236 is described below

commit 3adf23635040c2f95bdb39814d0ecf723667469f
Author: Jacob Marble <[email protected]>
AuthorDate: Fri Jan 27 10:14:08 2023 -0800

    feat(go/sqldriver): convert Arrow times and dates to Golang time.Time (#393)
    
    * feat(go/sqldriver): convert Arrow times and dates to Golang time.Time
    
    * chore: add unit test
    
    * chore: remove TODO comment
---
 go/adbc/sqldriver/driver.go                |  23 ++---
 go/adbc/sqldriver/driver_internals_test.go | 130 +++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/go/adbc/sqldriver/driver.go b/go/adbc/sqldriver/driver.go
index a9a8ad4..53aa40a 100644
--- a/go/adbc/sqldriver/driver.go
+++ b/go/adbc/sqldriver/driver.go
@@ -40,6 +40,7 @@ import (
        "reflect"
        "strconv"
        "strings"
+       "time"
        "unsafe"
 
        "github.com/apache/arrow-adbc/go/adbc"
@@ -635,15 +636,15 @@ func (r *rows) Next(dest []driver.Value) error {
                case *array.LargeBinary:
                        dest[i] = col.Value(int(r.curRow))
                case *array.Date32:
-                       dest[i] = col.Value(int(r.curRow))
+                       dest[i] = col.Value(int(r.curRow)).ToTime()
                case *array.Date64:
-                       dest[i] = col.Value(int(r.curRow))
+                       dest[i] = col.Value(int(r.curRow)).ToTime()
                case *array.Time32:
-                       dest[i] = col.Value(int(r.curRow))
+                       dest[i] = 
col.Value(int(r.curRow)).ToTime(col.DataType().(*arrow.Time32Type).Unit)
                case *array.Time64:
-                       dest[i] = col.Value(int(r.curRow))
+                       dest[i] = 
col.Value(int(r.curRow)).ToTime(col.DataType().(*arrow.Time64Type).Unit)
                case *array.Timestamp:
-                       dest[i] = col.Value(int(r.curRow))
+                       dest[i] = 
col.Value(int(r.curRow)).ToTime(col.DataType().(*arrow.TimestampType).Unit)
                default:
                        return &adbc.Error{
                                Code: adbc.StatusNotImplemented,
@@ -703,16 +704,8 @@ func (r *rows) ColumnTypeScanType(index int) reflect.Type {
                return reflect.TypeOf([]byte{})
        case arrow.STRING:
                return reflect.TypeOf(string(""))
-       case arrow.TIME32:
-               return reflect.TypeOf(arrow.Time32(0))
-       case arrow.TIME64:
-               return reflect.TypeOf(arrow.Time64(0))
-       case arrow.DATE32:
-               return reflect.TypeOf(arrow.Date32(0))
-       case arrow.DATE64:
-               return reflect.TypeOf(arrow.Date64(0))
-       case arrow.TIMESTAMP:
-               return reflect.TypeOf(arrow.Timestamp(0))
+       case arrow.TIME32, arrow.TIME64, arrow.DATE32, arrow.DATE64, 
arrow.TIMESTAMP:
+               return reflect.TypeOf(time.Time{})
        }
        return nil
 }
diff --git a/go/adbc/sqldriver/driver_internals_test.go 
b/go/adbc/sqldriver/driver_internals_test.go
index 97ef4e8..74f86e4 100644
--- a/go/adbc/sqldriver/driver_internals_test.go
+++ b/go/adbc/sqldriver/driver_internals_test.go
@@ -18,12 +18,18 @@
 package sqldriver
 
 import (
+       "database/sql/driver"
        "fmt"
        "strings"
        "testing"
+       "time"
 
        "github.com/apache/arrow-adbc/go/adbc"
+       "github.com/apache/arrow/go/v11/arrow"
+       "github.com/apache/arrow/go/v11/arrow/array"
+       "github.com/apache/arrow/go/v11/arrow/memory"
        "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
 )
 
 func TestParseConnectStr(t *testing.T) {
@@ -59,3 +65,127 @@ func TestParseConnectStr(t *testing.T) {
                assert.Equal(t, expectOpts, gotOpts)
        }
 }
+
+var (
+       tz       = time.FixedZone("North Idaho", -int((8 * 
time.Hour).Seconds()))
+       testTime = time.Date(2023, time.January, 26, 15, 40, 39, 123456789, tz)
+)
+
+func TestNextRowTypes(t *testing.T) {
+       tests := []struct {
+               arrowType      arrow.DataType
+               arrowValueFunc func(*testing.T, array.Builder)
+               golangValue    any
+       }{
+               {
+                       arrowType: &arrow.StringType{},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               b.(*array.StringBuilder).Append("my-string")
+                       },
+                       golangValue: "my-string",
+               },
+               {
+                       arrowType: &arrow.Date32Type{},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               
b.(*array.Date32Builder).Append(arrow.Date32FromTime(testTime))
+                       },
+                       golangValue: testTime.UTC().Truncate(24 * time.Hour),
+               },
+               {
+                       arrowType: &arrow.Date64Type{},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               
b.(*array.Date64Builder).Append(arrow.Date64FromTime(testTime))
+                       },
+                       golangValue: testTime.UTC().Truncate(24 * time.Hour),
+               },
+               {
+                       arrowType: &arrow.TimestampType{Unit: arrow.Second, 
TimeZone: "North Idaho"},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               s := testTime.Format("2006-01-02 
15:04:05-07:00")
+                               timestamp, _, err := 
arrow.TimestampFromStringInLocation(s, arrow.Second, tz)
+                               require.NoError(t, err)
+                               b.(*array.TimestampBuilder).Append(timestamp)
+                       },
+                       golangValue: testTime.UTC().Truncate(time.Second),
+               },
+               {
+                       arrowType: &arrow.TimestampType{Unit: 
arrow.Millisecond},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               s := testTime.Format("2006-01-02 
15:04:05.999-07:00")
+                               timestamp, _, err := 
arrow.TimestampFromStringInLocation(s, arrow.Millisecond, tz)
+                               require.NoError(t, err)
+                               b.(*array.TimestampBuilder).Append(timestamp)
+                       },
+                       golangValue: testTime.UTC().Truncate(time.Millisecond),
+               },
+               {
+                       arrowType: &arrow.Time32Type{Unit: arrow.Second},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               s := testTime.Format("15:04:05")
+                               t.Log(s)
+                               time32, err := arrow.Time32FromString(s, 
arrow.Second)
+                               require.NoError(t, err)
+                               b.(*array.Time32Builder).Append(time32)
+                               t.Log("end of avf")
+                       },
+                       golangValue: time.Date(1970, time.January, 1, 
testTime.Hour(), testTime.Minute(), testTime.Second(), 0, time.UTC),
+               },
+               {
+                       arrowType: &arrow.Time32Type{Unit: arrow.Millisecond},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               s := testTime.Format("15:04:05.999")
+                               time32, err := arrow.Time32FromString(s, 
arrow.Millisecond)
+                               require.NoError(t, err)
+                               b.(*array.Time32Builder).Append(time32)
+                       },
+                       golangValue: time.Date(1970, time.January, 1, 
testTime.Hour(), testTime.Minute(), testTime.Second(), 
testTime.Nanosecond()-testTime.Nanosecond()%int(time.Millisecond), time.UTC),
+               },
+               {
+                       arrowType: &arrow.Time64Type{Unit: arrow.Microsecond},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               s := testTime.Format("15:04:05.999999")
+                               time64, err := arrow.Time64FromString(s, 
arrow.Microsecond)
+                               require.NoError(t, err)
+                               b.(*array.Time64Builder).Append(time64)
+                       },
+                       golangValue: time.Date(1970, time.January, 1, 
testTime.Hour(), testTime.Minute(), testTime.Second(), 
testTime.Nanosecond()-testTime.Nanosecond()%int(time.Microsecond), time.UTC),
+               },
+               {
+                       arrowType: &arrow.Time64Type{Unit: arrow.Nanosecond},
+                       arrowValueFunc: func(t *testing.T, b array.Builder) {
+                               t.Helper()
+                               s := testTime.Format("15:04:05.999999999")
+                               time64, err := arrow.Time64FromString(s, 
arrow.Nanosecond)
+                               require.NoError(t, err)
+                               b.(*array.Time64Builder).Append(time64)
+                       },
+                       golangValue: time.Date(1970, time.January, 1, 
testTime.Hour(), testTime.Minute(), testTime.Second(), testTime.Nanosecond(), 
time.UTC),
+               },
+       }
+
+       for i, test := range tests {
+               t.Run(fmt.Sprintf("%d-%s", i, test.arrowType.String()), func(t 
*testing.T) {
+                       schema := arrow.NewSchema([]arrow.Field{{Type: 
test.arrowType}}, nil)
+                       recordBuilder := 
array.NewRecordBuilder(memory.DefaultAllocator, schema)
+                       t.Cleanup(recordBuilder.Release)
+                       test.arrowValueFunc(t, recordBuilder.Field(0))
+                       record := recordBuilder.NewRecord()
+                       t.Cleanup(record.Release)
+
+                       r := &rows{curRecord: record}
+                       dest := make([]driver.Value, 1)
+                       err := r.Next(dest)
+                       assert.NoError(t, err)
+                       assert.IsType(t, test.golangValue, dest[0])
+                       assert.Equal(t, test.golangValue, dest[0])
+               })
+       }
+}

Reply via email to