@@ -3,11 +3,11 @@ package godatabend
33import (
44 "context"
55 "database/sql/driver"
6- "errors"
7- "fmt"
86 "io"
97 "reflect"
108 "sync/atomic"
9+
10+ "github.com/pkg/errors"
1111)
1212
1313var rowsHack = false
@@ -46,7 +46,7 @@ func waitForData(ctx context.Context, dc *DatabendConn, response *QueryResponse)
4646 response = nextResponse
4747 if response .Error != nil {
4848 _ = dc .rest .CloseQuery (ctx , response )
49- return nil , fmt .Errorf ("query error: %+v" , response .Error )
49+ return nil , errors .Errorf ("query error: %+v" , response .Error )
5050 }
5151 }
5252 return response , nil
@@ -66,7 +66,7 @@ func parse_schema(fields *[]DataField, opts *ColumnTypeOptions) (*resultSchema,
6666 schema .columns = append (schema .columns , field .Name )
6767 parser , err := NewColumnType (field .Type , opts )
6868 if err != nil {
69- return nil , fmt . Errorf ( "newTextRows: failed to create a data parser for the type '%s': %w " , field .Type , err )
69+ return nil , errors . Wrapf ( err , "newTextRows: failed to create a data parser for the type '%s'" , field .Type )
7070 }
7171 schema .types = append (schema .types , parser )
7272 }
@@ -75,6 +75,10 @@ func parse_schema(fields *[]DataField, opts *ColumnTypeOptions) (*resultSchema,
7575}
7676
7777func (dc * DatabendConn ) newNextRows (ctx context.Context , resp * QueryResponse ) (* nextRows , error ) {
78+ if len (resp .Data ) != 0 && (resp .Schema == nil || len (* resp .Schema ) != len (resp .Data [0 ])) {
79+ return nil , errors .New ("newNextRows: internal error, data and schema not match" )
80+ }
81+
7882 schema , err := parse_schema (resp .Schema , dc .columnTypeOptions ())
7983 if err != nil {
8084 return nil , err
@@ -123,6 +127,10 @@ func (r *nextRows) doClose() error {
123127}
124128
125129func (r * nextRows ) Next (dest []driver.Value ) error {
130+ if len (dest ) != len (r .columns ) {
131+ return errors .New ("query error: Next dest must has same size as the Columns() are wide" )
132+ }
133+
126134 if atomic .LoadInt32 (& r .isClosed ) == 1 || r .respData == nil {
127135 // If user already called Rows.Close(), Rows.Next() will not get here.
128136 // Get here only because we doClose() internally,
@@ -147,19 +155,21 @@ func (r *nextRows) Next(dest []driver.Value) error {
147155 if rowsHack {
148156 r .latestRow = lineData
149157 }
158+ if len (lineData ) != len (r .columns ) {
159+ return errors .New ("query error: internal error, data and schema not match" )
160+ }
150161
151- for j := range dest {
152- val := lineData [j ]
162+ for i , val := range lineData {
153163 if val == nil {
154- dest [j ] = nil
164+ dest [i ] = nil
155165 continue
156166 }
157- v , err := r .types [j ].Parse (* val )
167+ v , err := r .types [i ].Parse (* val )
158168 if err != nil {
159- r .dc .log ("fail to parse field" , j , ", error: " , err )
169+ r .dc .log ("fail to parse field" , i , ", error: " , err )
160170 return err
161171 }
162- dest [j ] = v
172+ dest [i ] = v
163173 }
164174 return nil
165175}
@@ -185,12 +195,11 @@ func (r *nextRows) ColumnTypeNullable(index int) (bool, bool) {
185195var _ driver.RowsColumnTypeLength = (* nextRows )(nil )
186196
187197func (r * nextRows ) ColumnTypeLength (index int ) (length int64 , ok bool ) {
188- return 0 , false
198+ return r . types [ index ]. Length ()
189199}
190200
191201var _ driver.RowsColumnTypePrecisionScale = (* nextRows )(nil )
192202
193203func (r * nextRows ) ColumnTypePrecisionScale (index int ) (int64 , int64 , bool ) {
194- // TODO: implement this
195- return 0 , 0 , false
204+ return r .types [index ].PrecisionScale ()
196205}
0 commit comments