Skip to content

Commit

Permalink
Implementing timestamppb.Timestamp behind timestamppb tag
Browse files Browse the repository at this point in the history
  • Loading branch information
tgulacsi committed Aug 10, 2021
1 parent 839cff7 commit 2a3b191
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Implement use of "google.golang.org/protobuf/types/known/timestamppb".Timestamp,
behind the timestamppb tag

### Changed
- Use dpiConn_setCallTimeout for faster recovers.
- Faster setTraceTag, drv.init.
Expand Down
6 changes: 1 addition & 5 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -716,11 +716,7 @@ func maybeBadConn(err error, c *conn) error {
if err == nil {
return nil
}
cl := func() {
if Log != nil {
Log("msg", "maybeBadConn", "error", err)
}
}
cl := func() {}
if c != nil {
cl = func() {
if Log != nil {
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.14

require (
github.com/go-logfmt/logfmt v0.5.0
github.com/google/go-cmp v0.4.0
github.com/google/go-cmp v0.5.5
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
google.golang.org/protobuf v1.27.1
)
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
67 changes: 65 additions & 2 deletions stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ func (st *statement) bindVarTypeSwitch(info *argInfo, get *dataGetter, value int
vlr, isValuer := value.(driver.Valuer)

switch value.(type) {
case *driver.Rows:
case *driver.Rows, *pbTimestamp, *Object:
default:
rv := reflect.ValueOf(value)
kind := rv.Kind()
Expand Down Expand Up @@ -1097,6 +1097,23 @@ func (st *statement) bindVarTypeSwitch(info *argInfo, get *dataGetter, value int
*get = st.conn.dataGetTime
}

case *pbTimestamp:
info.typ, info.natTyp = C.DPI_ORACLE_TYPE_TIMESTAMP_TZ, C.DPI_NATIVE_TYPE_TIMESTAMP
info.set = st.conn.dataSetTime
if info.isOut {
*get = st.conn.dataGetTime
}
case []*pbTimestamp:
info.typ, info.natTyp = C.DPI_ORACLE_TYPE_TIMESTAMP_TZ, C.DPI_NATIVE_TYPE_TIMESTAMP
// info.Typ should be C.DPI_ORACLE_TYPE_TIMESTAMP_TZ, but it does not work for DATE PL/SQL associative arrays
if st.plSQLArrays {
info.typ = C.DPI_ORACLE_TYPE_DATE
}
info.set = st.conn.dataSetTime
if info.isOut {
*get = st.conn.dataGetTime
}

case time.Duration, []time.Duration:
info.typ, info.natTyp = C.DPI_ORACLE_TYPE_INTERVAL_DS, C.DPI_NATIVE_TYPE_INTERVAL_DS
info.set = st.conn.dataSetIntervalDS
Expand Down Expand Up @@ -1132,7 +1149,7 @@ func (st *statement) bindVarTypeSwitch(info *argInfo, get *dataGetter, value int

default:
if !isValuer {
return value, fmt.Errorf("unknown type %T", value)
return value, fmt.Errorf("unknown type %T (%T)", value, &pbTimestamp{})
}
var err error
if value, err = vlr.Value(); err != nil {
Expand Down Expand Up @@ -1221,6 +1238,15 @@ func (c *conn) dataGetTime(v interface{}, data []C.dpiData) error {
c.dataGetTimeC(&x.Time, &data[0])
}

case *pbTimestamp:
if len(data) == 0 || data[0].isNull == 1 {
x.Reset()
return nil
}
var t time.Time
c.dataGetTimeC(&t, &data[0])
setPbTimestamp(x, t)

case *[]time.Time:
n := len(data)
if cap(*x) >= n {
Expand All @@ -1243,6 +1269,19 @@ func (c *conn) dataGetTime(v interface{}, data []C.dpiData) error {
c.dataGetTimeC(&((*x)[i].Time), &data[i])
}
}

case *[]*pbTimestamp:
n := len(data)
if cap(*x) >= n {
*x = (*x)[:n]
} else {
*x = make([]*pbTimestamp, n)
}
var t time.Time
for i := range data {
c.dataGetTimeC(&t, &data[i])
setPbTimestamp((*x)[i], t)
}
}
return nil
}
Expand Down Expand Up @@ -1274,6 +1313,16 @@ func (c *conn) dataSetTime(dv *C.dpiVar, data []C.dpiData, vv interface{}) error
if data[0].isNull = C.int(b2i(!x.Valid)); x.Valid {
times[0] = x.Time
}
case *pbTimestamp:
if !x.IsValid() {
data[0].isNull = 1
} else {
data[0].isNull = 0
times[0] = x.AsTime()
}
if Log != nil {
Log("msg", "dataSetTime", "ts", x, "t", times[0])
}

case []time.Time:
times = x
Expand All @@ -1291,6 +1340,20 @@ func (c *conn) dataSetTime(dv *C.dpiVar, data []C.dpiData, vv interface{}) error
times[i] = x[i].Time
}
}
case []*pbTimestamp:
if cap(times) < len(x) {
times = make([]time.Time, len(x))
} else {
times = times[:len(x)]
}
for i, n := range x {
if !n.IsValid() {
data[i].isNull = 1
} else {
data[i].isNull = 0
times[i] = n.AsTime()
}
}

default:
for i := range data {
Expand Down
25 changes: 25 additions & 0 deletions timestamppb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//go:build timestamppb
// +build timestamppb

// Copyright 2017, 2020 The Godror Authors
//
//
// SPDX-License-Identifier: UPL-1.0 OR Apache-2.0

package godror

import (
"time"

"google.golang.org/protobuf/types/known/timestamppb"
)

// pbTimestamp is google.golang.org/protobuf/types/known/timestamppb#Timestamp.
type pbTimestamp = timestamppb.Timestamp

func setPbTimestamp(ts *pbTimestamp, t time.Time) {
*ts = *timestamppb.New(t)
if Log != nil {
Log("msg", "setPbTimestamp", "t", t, "ts", ts)
}
}
28 changes: 28 additions & 0 deletions timestamppb_none.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//go:build !timestamppb
// +build !timestamppb

// Copyright 2017, 2020 The Godror Authors
//
//
// SPDX-License-Identifier: UPL-1.0 OR Apache-2.0

package godror

import "time"

// pbTimestamp is a placeholder for google.golang.org/protobuf/types/known/timestamppb#Timestamp.
type pbTimestamp struct{}

func (ts *pbTimestamp) Reset() {
panic("build with -tags=timestamppb")
}
func (ts *pbTimestamp) AsTime() time.Time {
panic("build with -tags=timestamppb")
}
func (ts *pbTimestamp) IsValid() bool {
panic("build with -tags=timestamppb")
}

func setPbTimestamp(ts *pbTimestamp, t time.Time) {
panic("build with -tags=timestamppb")
}
29 changes: 29 additions & 0 deletions z_timestamppb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//go:build timestamppb
// +build timestamppb

package godror_test

import (
"context"
"database/sql"
"testing"
"time"

"google.golang.org/protobuf/types/known/timestamppb"
)

func TestTimestamppb(t *testing.T) {
ctx, cancel := context.WithTimeout(testContext("Timestamppb"), 30*time.Second)
defer cancel()
const qry = `SELECT SYSDATE, :1, (SYSDATE-:2)*24*3600 FROM DUAL`
it1, it2 := timestamppb.Now(), timestamppb.New(time.Now().Add(-10*time.Minute))
var ot1, ot2 sql.NullTime
var on3 sql.NullInt64
if err := testDb.QueryRowContext(ctx, qry, it1, it2).Scan(&ot1, &ot2, &on3); err != nil {
t.Fatalf("%s: %v", qry, err)
}
t.Logf("SYSDATE=%v 1=%v 2=%v", ot1, ot2, on3)
if !(ot2.Valid && !ot2.Time.IsZero()) {
t.Errorf("ot2=%v", ot2)
}
}

0 comments on commit 2a3b191

Please sign in to comment.