Skip to content

Commit a8cde6f

Browse files
authored
Merge pull request #251 from ydb-platform/interval
Interval <-> time.Duration fix
2 parents 819b51c + 672a337 commit a8cde6f

File tree

9 files changed

+114
-16
lines changed

9 files changed

+114
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Fixed bug with convert ydb value to `time.Duration` in `result.Scan[WithDefaults,Named]()`
2+
* Fixed bug with make ydb value from `time.Duration` in `types.IntervalValueFromDuration(d)`
3+
* Marked `table/types.{IntervalValue,NullableIntervalValue}` as deprecated
4+
15
## v3.26.8
26
* Removed the processing of trailer metadata on stream calls
37

internal/table/scanner/scan_raw.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func (s *rawConverter) Timestamp() (v time.Time) {
173173

174174
func (s *rawConverter) Interval() (v time.Duration) {
175175
s.unwrap()
176-
return timeutil.UnmarshalInterval(s.int64())
176+
return timeutil.MicrosecondsToDuration(s.int64())
177177
}
178178

179179
func (s *rawConverter) TzDate() (v time.Time) {

internal/table/scanner/scanner.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ func (s *scanner) any() interface{} {
378378
case value.TypeInt64:
379379
return s.int64()
380380
case value.TypeInterval:
381-
return timeutil.UnmarshalInterval(s.int64())
381+
return timeutil.MicrosecondsToDuration(s.int64())
382382
case value.TypeTzDate:
383383
src, err := timeutil.UnmarshalTzDate(s.text())
384384
if err != nil {
@@ -750,7 +750,7 @@ func (s *scanner) scanRequired(value interface{}) {
750750
case *time.Time:
751751
s.setTime(v)
752752
case *time.Duration:
753-
*v = timeutil.UnmarshalInterval(s.int64())
753+
*v = timeutil.MicrosecondsToDuration(s.int64())
754754
case *string:
755755
s.setString(v)
756756
case *[]byte:
@@ -910,7 +910,7 @@ func (s *scanner) scanOptional(value interface{}, defaultValueForOptional bool)
910910
if s.isNull() {
911911
*v = nil
912912
} else {
913-
src := timeutil.UnmarshalInterval(s.int64())
913+
src := timeutil.MicrosecondsToDuration(s.int64())
914914
*v = &src
915915
}
916916
case **string:

internal/table/scanner/scanner_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ func valueFromPrimitiveTypeID(c *column, r xrand.Rand) (*Ydb.Value, interface{})
250250
Int64Value: v,
251251
},
252252
}
253-
src := timeutil.UnmarshalInterval(v)
253+
src := timeutil.MicrosecondsToDuration(v)
254254
if c.optional && !c.testDefault {
255255
vp := &src
256256
return ydbval, &vp

internal/timeutil/time.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ const (
1717

1818
var unix = time.Unix(0, 0)
1919

20-
// UnmarshalInterval up to ±292 years.
21-
func UnmarshalInterval(n int64) time.Duration {
22-
return time.Duration(n)
20+
// MicrosecondsToDuration returns time.Duration from given microseconds
21+
func MicrosecondsToDuration(n int64) time.Duration {
22+
return time.Duration(n) * time.Microsecond
2323
}
2424

25-
func MarshalInterval(d time.Duration) int64 {
26-
return int64(d)
25+
// DurationToMicroseconds returns microseconds from given time.Duration
26+
func DurationToMicroseconds(d time.Duration) int64 {
27+
return int64(d / time.Microsecond)
2728
}
2829

2930
// UnmarshalDate up to 11761191-01-20 00:00:00 +0000 UTC.

internal/value/value.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ func TimestampValue(v uint64) Value {
339339
}
340340
}
341341

342+
// IntervalValue makes Value from given microseconds value
342343
func IntervalValue(v int64) Value {
343344
return Value{
344345
t: TypeInterval,

table/table_regress_test.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import (
77
"context"
88
"os"
99
"testing"
10+
"time"
1011

1112
"github.com/stretchr/testify/require"
1213

13-
"github.com/ydb-platform/ydb-go-sdk/v3/table"
14-
1514
"github.com/ydb-platform/ydb-go-sdk/v3"
15+
"github.com/ydb-platform/ydb-go-sdk/v3/table"
16+
"github.com/ydb-platform/ydb-go-sdk/v3/table/types"
1617
)
1718

1819
type issue229Struct struct{}
@@ -49,3 +50,31 @@ func connect(t *testing.T) ydb.Connection {
4950
require.NoError(t, err)
5051
return db
5152
}
53+
54+
func TestIssue259IntervalFromDuration(t *testing.T) {
55+
// https://github.com/ydb-platform/ydb-go-sdk/issues/259
56+
ctx, cancel := context.WithCancel(context.Background())
57+
defer cancel()
58+
59+
db := connect(t)
60+
err := db.Table().DoTx(ctx, func(ctx context.Context, tx table.TransactionActor) error {
61+
res, err := tx.Execute(ctx, `DECLARE $ts as Interval;
62+
$ten_micro = CAST(10 as Interval);
63+
SELECT $ts == $ten_micro, $ten_micro;`, table.NewQueryParameters(
64+
table.ValueParam(`$ts`, types.IntervalValueFromDuration(10*time.Microsecond)),
65+
))
66+
require.NoError(t, err)
67+
require.NoError(t, res.NextResultSetErr(ctx))
68+
require.True(t, res.NextRow())
69+
70+
var (
71+
val bool
72+
tenMicro time.Duration
73+
)
74+
require.NoError(t, res.Scan(&val, &tenMicro))
75+
require.True(t, val)
76+
require.Equal(t, 10*time.Microsecond, tenMicro)
77+
return nil
78+
}, table.WithTxSettings(table.TxSettings(table.WithSerializableReadWrite())))
79+
require.NoError(t, err)
80+
}

table/types/value.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,56 +42,109 @@ func DatetimeValue(v uint32) Value { return value.DatetimeValue(v) }
4242

4343
func TimestampValue(v uint64) Value { return value.TimestampValue(v) }
4444

45+
// IntervalValueFromMicroseconds makes Value from given microseconds value
46+
func IntervalValueFromMicroseconds(v int64) Value { return value.IntervalValue(v) }
47+
48+
// IntervalValue makes Value from given microseconds value
49+
//
50+
// Deprecated: use IntervalValueFromMicroseconds instead
4551
func IntervalValue(v int64) Value { return value.IntervalValue(v) }
4652

53+
// TzDateValue makes TzDate value from string
4754
func TzDateValue(v string) Value { return value.TzDateValue(v) }
4855

56+
// TzDatetimeValue makes TzDatetime value from string
4957
func TzDatetimeValue(v string) Value { return value.TzDatetimeValue(v) }
5058

59+
// TzTimestampValue makes TzTimestamp value from string
5160
func TzTimestampValue(v string) Value { return value.TzTimestampValue(v) }
5261

62+
// DateValueFromTime makes Date value from time.Time
63+
//
64+
// Warning: all *From* helpers will be removed at next major release
65+
// (functional will be implements with go1.18 type lists)
5366
func DateValueFromTime(v time.Time) Value { return value.DateValue(timeutil.MarshalDate(v)) }
5467

68+
// DatetimeValueFromTime makes Datetime value from time.Time
69+
//
70+
// Warning: all *From* helpers will be removed at next major release
71+
// (functional will be implements with go1.18 type lists)
5572
func DatetimeValueFromTime(v time.Time) Value {
5673
return value.DatetimeValue(timeutil.MarshalDatetime(v))
5774
}
5875

76+
// TimestampValueFromTime makes Timestamp value from time.Time
77+
//
78+
// Warning: all *From* helpers will be removed at next major release
79+
// (functional will be implements with go1.18 type lists)
5980
func TimestampValueFromTime(v time.Time) Value {
6081
return value.TimestampValue(timeutil.MarshalTimestamp(v))
6182
}
6283

84+
// IntervalValueFromDuration makes Interval value from time.Duration
85+
//
86+
// Warning: all *From* helpers will be removed at next major release
87+
// (functional will be implements with go1.18 type lists)
6388
func IntervalValueFromDuration(v time.Duration) Value {
64-
return value.IntervalValue(timeutil.MarshalInterval(v))
89+
return value.IntervalValue(timeutil.DurationToMicroseconds(v))
6590
}
6691

92+
// TzDateValueFromTime makes TzDate value from time.Time
93+
//
94+
// Warning: all *From* helpers will be removed at next major release
95+
// (functional will be implements with go1.18 type lists)
6796
func TzDateValueFromTime(v time.Time) Value { return value.TzDateValue(timeutil.MarshalTzDate(v)) }
6897

98+
// TzDatetimeValueFromTime makes TzDatetime value from time.Time
99+
//
100+
// Warning: all *From* helpers will be removed at next major release
101+
// (functional will be implements with go1.18 type lists)
69102
func TzDatetimeValueFromTime(v time.Time) Value {
70103
return value.TzDatetimeValue(timeutil.MarshalTzDatetime(v))
71104
}
72105

106+
// TzTimestampValueFromTime makes TzTimestamp value from time.Time
107+
//
108+
// Warning: all *From* helpers will be removed at next major release
109+
// (functional will be implements with go1.18 type lists)
73110
func TzTimestampValueFromTime(v time.Time) Value {
74111
return value.TzTimestampValue(timeutil.MarshalTzTimestamp(v))
75112
}
76113

77114
func StringValue(v []byte) Value { return value.StringValue(v) }
78115

116+
// StringValueFromString makes String value from string
117+
//
118+
// Warning: all *From* helpers will be removed at next major release
119+
// (functional will be implements with go1.18 type lists)
79120
func StringValueFromString(v string) Value { return value.StringValue([]byte(v)) }
80121

81122
func UTF8Value(v string) Value { return value.UTF8Value(v) }
82123

83124
func YSONValue(v string) Value { return value.YSONValue(v) }
84125

126+
// YSONValueFromBytes makes YSON value from bytes
127+
//
128+
// Warning: all *From* helpers will be removed at next major release
129+
// (functional will be implements with go1.18 type lists)
85130
func YSONValueFromBytes(v []byte) Value { return value.YSONValue(string(v)) }
86131

87132
func JSONValue(v string) Value { return value.JSONValue(v) }
88133

134+
// JSONValueFromBytes makes JSON value from bytes
135+
//
136+
// Warning: all *From* helpers will be removed at next major release
137+
// (functional will be implements with go1.18 type lists)
89138
func JSONValueFromBytes(v []byte) Value { return value.JSONValue(string(v)) }
90139

91140
func UUIDValue(v [16]byte) Value { return value.UUIDValue(v) }
92141

93142
func JSONDocumentValue(v string) Value { return value.JSONDocumentValue(v) }
94143

144+
// JSONDocumentValueFromBytes makes JSONDocument value from bytes
145+
//
146+
// Warning: all *From* helpers will be removed at next major release
147+
// (functional will be implements with go1.18 type lists)
95148
func JSONDocumentValueFromBytes(v []byte) Value { return value.JSONDocumentValue(string(v)) }
96149

97150
func DyNumberValue(v string) Value { return value.DyNumberValue(v) }
@@ -344,13 +397,23 @@ func NullableTzTimestampValueFromTime(v *time.Time) Value {
344397
return OptionalValue(TzTimestampValueFromTime(*v))
345398
}
346399

400+
// NullableIntervalValue makes Value which maybe nil or valued
401+
//
402+
// Deprecated: use NullableIntervalValueFromMicroseconds instead
347403
func NullableIntervalValue(v *int64) Value {
348404
if v == nil {
349405
return NullValue(TypeInterval)
350406
}
351407
return OptionalValue(IntervalValue(*v))
352408
}
353409

410+
func NullableIntervalValueFromMicroseconds(v *int64) Value {
411+
if v == nil {
412+
return NullValue(TypeInterval)
413+
}
414+
return OptionalValue(IntervalValueFromMicroseconds(*v))
415+
}
416+
354417
func NullableIntervalValueFromDuration(v *time.Duration) Value {
355418
if v == nil {
356419
return NullValue(TypeInterval)
@@ -492,7 +555,7 @@ func Nullable(t Type, v interface{}) Value {
492555
case TypeInterval:
493556
switch tt := v.(type) {
494557
case *int64:
495-
return NullableIntervalValue(tt)
558+
return NullableIntervalValueFromMicroseconds(tt)
496559
case *time.Duration:
497560
return NullableIntervalValueFromDuration(tt)
498561
default:

table/types/value_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ func TestNullable(t *testing.T) {
217217
exp: NullValue(TypeTzDate),
218218
},
219219
{
220-
name: "interval from int32",
220+
name: "interval from int64",
221221
t: TypeInterval,
222222
v: func(v int64) *int64 { return &v }(123),
223-
exp: OptionalValue(IntervalValue(123)),
223+
exp: OptionalValue(IntervalValueFromMicroseconds(123)),
224224
},
225225
{
226226
name: "interval from time.Time",

0 commit comments

Comments
 (0)