Skip to content

Commit 9c94ccd

Browse files
authored
Merge pull request #1651 from ydb-platform/stack-scan
* Added stacktrace call to row scan errors for detect broken client code
2 parents 72617cb + b80de99 commit 9c94ccd

File tree

3 files changed

+110
-9
lines changed

3 files changed

+110
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
* Added stacktrace call to row scan errors for detect broken client code
12
* Fixed DescribeConsumer ignoring PartitionConsumerStats
23
* Added virtualtimestamps field to cdc description
34

internal/query/row.go

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,22 @@ import (
44
"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
55

66
"github.com/ydb-platform/ydb-go-sdk/v3/internal/query/scanner"
7+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors"
78
"github.com/ydb-platform/ydb-go-sdk/v3/query"
89
)
910

1011
var _ query.Row = (*Row)(nil)
1112

1213
type Row struct {
13-
indexedScanner scanner.IndexedScanner
14-
namedScanner scanner.NamedScanner
15-
structScanner scanner.StructScanner
14+
indexedScanner interface {
15+
Scan(dst ...interface{}) error
16+
}
17+
namedScanner interface {
18+
ScanNamed(dst ...scanner.NamedDestination) error
19+
}
20+
structScanner interface {
21+
ScanStruct(dst interface{}, opts ...scanner.ScanStructOption) error
22+
}
1623
}
1724

1825
func NewRow(columns []*Ydb.Column, v *Ydb.Value) *Row {
@@ -25,14 +32,38 @@ func NewRow(columns []*Ydb.Column, v *Ydb.Value) *Row {
2532
}
2633
}
2734

28-
func (r Row) Scan(dst ...interface{}) (err error) {
29-
return r.indexedScanner.Scan(dst...)
35+
func (r Row) Scan(dst ...interface{}) error {
36+
err := r.indexedScanner.Scan(dst...)
37+
if err != nil {
38+
return xerrors.WithStackTrace(
39+
xerrors.WithStackTrace(err),
40+
xerrors.WithSkipDepth(1),
41+
)
42+
}
43+
44+
return nil
3045
}
3146

32-
func (r Row) ScanNamed(dst ...scanner.NamedDestination) (err error) {
33-
return r.namedScanner.ScanNamed(dst...)
47+
func (r Row) ScanNamed(dst ...scanner.NamedDestination) error {
48+
err := r.namedScanner.ScanNamed(dst...)
49+
if err != nil {
50+
return xerrors.WithStackTrace(
51+
xerrors.WithStackTrace(err),
52+
xerrors.WithSkipDepth(1),
53+
)
54+
}
55+
56+
return nil
3457
}
3558

36-
func (r Row) ScanStruct(dst interface{}, opts ...scanner.ScanStructOption) (err error) {
37-
return r.structScanner.ScanStruct(dst, opts...)
59+
func (r Row) ScanStruct(dst interface{}, opts ...scanner.ScanStructOption) error {
60+
err := r.structScanner.ScanStruct(dst, opts...)
61+
if err != nil {
62+
return xerrors.WithStackTrace(
63+
xerrors.WithStackTrace(err),
64+
xerrors.WithSkipDepth(1),
65+
)
66+
}
67+
68+
return nil
3869
}

internal/query/row_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package query
2+
3+
import (
4+
"errors"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
9+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/query/scanner"
10+
)
11+
12+
type testScanner struct {
13+
err error
14+
}
15+
16+
func (s testScanner) Scan(dst ...interface{}) error {
17+
return s.err
18+
}
19+
20+
func (s testScanner) ScanNamed(dst ...scanner.NamedDestination) error {
21+
return s.err
22+
}
23+
24+
func (s testScanner) ScanStruct(dst interface{}, opts ...scanner.ScanStructOption) error {
25+
return s.err
26+
}
27+
28+
func TestRowScan(t *testing.T) {
29+
expErr := errors.New("test error")
30+
row := Row{
31+
indexedScanner: testScanner{err: expErr},
32+
namedScanner: testScanner{err: expErr},
33+
structScanner: testScanner{err: expErr},
34+
}
35+
for _, tt := range []struct {
36+
name string
37+
scan func() error
38+
expErrStr string
39+
}{
40+
{
41+
name: "indexed scan",
42+
scan: func() error {
43+
return row.Scan()
44+
},
45+
expErrStr: "test error at `github.com/ydb-platform/ydb-go-sdk/v3/internal/query.Row.Scan(row.go:39)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/query.TestRowScan.func1(row_test.go:43)`", //nolint:lll
46+
},
47+
{
48+
name: "named scan",
49+
scan: func() error {
50+
return row.ScanNamed()
51+
},
52+
expErrStr: "test error at `github.com/ydb-platform/ydb-go-sdk/v3/internal/query.Row.ScanNamed(row.go:51)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/query.TestRowScan.func2(row_test.go:50)`", //nolint:lll
53+
},
54+
{
55+
name: "struct scan",
56+
scan: func() error {
57+
return row.ScanStruct(nil)
58+
},
59+
expErrStr: "test error at `github.com/ydb-platform/ydb-go-sdk/v3/internal/query.Row.ScanStruct(row.go:63)` at `github.com/ydb-platform/ydb-go-sdk/v3/internal/query.TestRowScan.func3(row_test.go:57)`", //nolint:lll
60+
},
61+
} {
62+
t.Run(tt.name, func(t *testing.T) {
63+
err := tt.scan()
64+
require.Error(t, err)
65+
require.ErrorIs(t, err, expErr)
66+
require.Equal(t, tt.expErrStr, err.Error())
67+
})
68+
}
69+
}

0 commit comments

Comments
 (0)