odbc
odbc copied to clipboard
Test fails on RedHat Linux 5.9 with unixODBC 2.3.1 and FreeTDS 0.91RC2
What steps will reproduce the problem?
1. Install freetds package with 'yum install'
2. Compile unixODBC 2.3.1 from source
3. Install the package with "go get code.google.com/p/odbc"
4. Run test with go test -mssrv SERVER -msuser USER -mspass PASSWD -msdb DB
What is the expected output?
All tests pass
What do you see instead?
I see the following runtime error:
panic: runtime error: slice bounds out of range [recovered]
panic: runtime error: slice bounds out of range
goroutine 4 [running]:
testing.func·004()
/usr/local/src/go/src/pkg/testing/testing.go:348 +0xcd
code.google.com/p/odbc.(*BindableColumn).Value(0xc200070e40, 0x6b6c050, 0x6,
0x4f36c0, 0xc200087cc0, ...)
/home/oracle/gosrc/src/code.google.com/p/odbc/column.go:239 +0x283
code.google.com/p/odbc.(*Rows).Next(0xc2000004c8, 0xc200054540, 0x7, 0x7,
0x54ee20, ...)
/home/oracle/gosrc/src/code.google.com/p/odbc/rows.go:34 +0x137
database/sql.(*Rows).Next(0xc20008a300, 0x3)
/usr/local/src/go/src/pkg/database/sql/sql.go:1310 +0xc1
code.google.com/p/odbc.TestMSSQLCreateInsertDelete(0xc200098000)
/home/oracle/gosrc/src/code.google.com/p/odbc/mssql_test.go:270 +0x62f
testing.tRunner(0xc200098000, 0x815780)
/usr/local/src/go/src/pkg/testing/testing.go:353 +0x8a
created by testing.RunTests
/usr/local/src/go/src/pkg/testing/testing.go:433 +0x86b
goroutine 1 [chan receive]:
testing.RunTests(0x583330, 0x815780, 0xf, 0xf, 0x1, ...)
/usr/local/src/go/src/pkg/testing/testing.go:434 +0x88e
testing.Main(0x583330, 0x815780, 0xf, 0xf, 0x824580, ...)
/usr/local/src/go/src/pkg/testing/testing.go:365 +0x8a
main.main()
code.google.com/p/odbc/_test/_testmain.go:73 +0x9a
goroutine 2 [syscall]:
exit status 2
FAIL code.google.com/p/odbc 0.101s
What version of the product are you using? On what operating system?
[oracle@custservices odbc]$ go version
go version go1.1.2 linux/amd64
[oracle@custservices odbc]$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 5.9 (Tikanga)
[oracle@custservices odbc]$ uname -a
Linux custservices 2.6.18-348.3.1.el5 #1 SMP Tue Mar 5 13:19:32 EST 2013 x86_64
x86_64 x86_64 GNU/Linux
Please provide any additional information below.
Original issue reported on code.google.com by victor.kryukov on 12 Nov 2013 at 2:54
Ok, so I did some more digging (trying to access the same database through ODBC
from R) and it looks like it's may be caused by SQLRowCount returning negative
numbers. Here is what I see when I do a manual select in the isql tool:
> select * from people
...
SQLRowCount returns -4294966952
344 rows fetched
Original comment by victor.kryukov on 12 Nov 2013 at 3:46
Cannot reproduce it here.
Please, run test with this extra line:
diff -r 703276ff5038 column.go
--- a/column.go Fri Nov 01 11:01:50 2013 +1100
+++ b/column.go Tue Nov 12 15:37:36 2013 +1100
@@ -236,6 +236,7 @@
if !c.IsVariableWidth && int(c.Len) != c.Size {
panic(fmt.Errorf("wrong column #%d length %d returned, %d expected", idx, c.Len, c.Size))
}
+ fmt.Printf("%d: c=%+v c.Buffer=%+v\n", idx, c, c.Buffer)
return c.BaseColumn.Value(c.Buffer[:c.Len])
}
and tell use the output just before it fails.
What is your database server? (version and all)
I don't think SQLRowCount has anything to do with it.
Thank you.
Alex
Original comment by [email protected] on 12 Nov 2013 at 4:40
- Changed state: Accepted
Hi Alex, and thanks for the quick response.
Here is the output with the extra line. I'm getting the MS SQL version...
warning: building out-of-date packages:
code.google.com/p/odbc/api
installing these packages with 'go test -i' will speed future tests.
=== RUN TestMSSQLCreateInsertDelete
0: c=&{BaseColumn:0xc200087a40 IsBound:true IsVariableWidth:true Size:21 Len:6
Buffer:[103 108 101 110 100 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0
0 0 0 0]} c.Buffer=[103 108 101 110 100 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1: c=&{BaseColumn:0xc200087a80 IsBound:true IsVariableWidth:false Size:4 Len:4
Buffer:[5 0 0 0] smallBuf:[5 0 0 0 0 0 0 0]} c.Buffer=[5 0 0 0]
2: c=&{BaseColumn:0xc200087ac0 IsBound:true IsVariableWidth:false Size:1 Len:1
Buffer:[1] smallBuf:[1 0 0 0 0 0 0 0]} c.Buffer=[1]
3: c=&{BaseColumn:0xc200087b00 IsBound:true IsVariableWidth:false Size:8 Len:8
Buffer:[0 0 0 0 0 0 47 64] smallBuf:[0 0 0 0 0 0 47 64]} c.Buffer=[0 0 0 0 0 0
47 64]
4: c=&{BaseColumn:0xc200087b20 IsBound:true IsVariableWidth:false Size:16
Len:16 Buffer:[208 7 5 0 10 0 11 0 1 0 1 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
c.Buffer=[208 7 5 0 10 0 11 0 1 0 1 0 0 0 0 0]
5: c=&{BaseColumn:0xc200087b40 IsBound:true IsVariableWidth:true Size:10 Len:6
Buffer:[0 0 11 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]} c.Buffer=[0 0
11 173 192 222 0 0 0 0]
6: c=&{BaseColumn:0xc200087b60 IsBound:true IsVariableWidth:true Size:11 Len:2
Buffer:[97 97 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]} c.Buffer=[97 97 0
0 0 0 0 0 0 0 0]
0: c=&{BaseColumn:0xc200087a40 IsBound:true IsVariableWidth:true Size:21 Len:6
Buffer:[103 111 112 104 101 114 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0
0 0 0 0 0]} c.Buffer=[103 111 112 104 101 114 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1: c=&{BaseColumn:0xc200087a80 IsBound:true IsVariableWidth:false Size:4 Len:4
Buffer:[3 0 0 0] smallBuf:[3 0 0 0 0 0 0 0]} c.Buffer=[3 0 0 0]
2: c=&{BaseColumn:0xc200087ac0 IsBound:true IsVariableWidth:false Size:1 Len:1
Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]} c.Buffer=[0]
3: c=&{BaseColumn:0xc200087b00 IsBound:true IsVariableWidth:false Size:8 Len:8
Buffer:[31 133 235 81 184 30 58 64] smallBuf:[31 133 235 81 184 30 58 64]}
c.Buffer=[31 133 235 81 184 30 58 64]
4: c=&{BaseColumn:0xc200087b20 IsBound:true IsVariableWidth:false Size:16
Len:16 Buffer:[217 7 5 0 10 0 11 0 1 0 1 0 192 212 84 7] smallBuf:[0 0 0 0 0 0
0 0]} c.Buffer=[217 7 5 0 10 0 11 0 1 0 1 0 192 212 84 7]
5: c=&{BaseColumn:0xc200087b40 IsBound:true IsVariableWidth:true Size:10 Len:1
Buffer:[0 0 11 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]} c.Buffer=[0 0
11 173 192 222 0 0 0 0]
6: c=&{BaseColumn:0xc200087b60 IsBound:true IsVariableWidth:true Size:11 Len:3
Buffer:[98 98 98 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]} c.Buffer=[98 98
98 0 0 0 0 0 0 0 0]
0: c=&{BaseColumn:0xc200087a40 IsBound:true IsVariableWidth:true Size:21 Len:5
Buffer:[99 104 114 105 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0
0 0 0]} c.Buffer=[99 104 114 105 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1: c=&{BaseColumn:0xc200087a80 IsBound:true IsVariableWidth:false Size:4 Len:4
Buffer:[25 0 0 0] smallBuf:[25 0 0 0 0 0 0 0]} c.Buffer=[25 0 0 0]
2: c=&{BaseColumn:0xc200087ac0 IsBound:true IsVariableWidth:false Size:1 Len:1
Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]} c.Buffer=[0]
3: c=&{BaseColumn:0xc200087b00 IsBound:true IsVariableWidth:false Size:8 Len:8
Buffer:[0 0 0 0 0 0 73 64] smallBuf:[0 0 0 0 0 0 73 64]} c.Buffer=[0 0 0 0 0 0
73 64]
4: c=&{BaseColumn:0xc200087b20 IsBound:true IsVariableWidth:false Size:16
Len:16 Buffer:[223 7 12 0 25 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
c.Buffer=[223 7 12 0 25 0 0 0 0 0 0 0 0 0 0 0]
5: c=&{BaseColumn:0xc200087b40 IsBound:true IsVariableWidth:true Size:10 Len:3
Buffer:[99 99 99 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]} c.Buffer=[99
99 99 173 192 222 0 0 0 0]
6: c=&{BaseColumn:0xc200087b60 IsBound:true IsVariableWidth:true Size:11
Len:4294967295 Buffer:[98 98 98 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
c.Buffer=[98 98 98 0 0 0 0 0 0 0 0]
--- FAIL: TestMSSQLCreateInsertDelete (0.07 seconds)
panic: runtime error: slice bounds out of range [recovered]
panic: runtime error: slice bounds out of range
goroutine 4 [running]:
testing.func·004()
/usr/local/src/go/src/pkg/testing/testing.go:348 +0xcd
code.google.com/p/odbc.(*BindableColumn).Value(0xc200070e40, 0xd449000, 0x6,
0x4f37a0, 0xc2000b4440, ...)
/home/oracle/gosrc/src/code.google.com/p/odbc/column.go:240 +0x36a
code.google.com/p/odbc.(*Rows).Next(0xc2000004c8, 0xc200054540, 0x7, 0x7,
0x54ef00, ...)
/home/oracle/gosrc/src/code.google.com/p/odbc/rows.go:34 +0x137
database/sql.(*Rows).Next(0xc20008a300, 0x3)
/usr/local/src/go/src/pkg/database/sql/sql.go:1310 +0xc1
code.google.com/p/odbc.TestMSSQLCreateInsertDelete(0xc200098000)
/home/oracle/gosrc/src/code.google.com/p/odbc/mssql_test.go:270 +0x62f
testing.tRunner(0xc200098000, 0x815780)
/usr/local/src/go/src/pkg/testing/testing.go:353 +0x8a
created by testing.RunTests
/usr/local/src/go/src/pkg/testing/testing.go:433 +0x86b
goroutine 1 [chan receive]:
testing.RunTests(0x583450, 0x815780, 0xf, 0xf, 0x1, ...)
/usr/local/src/go/src/pkg/testing/testing.go:434 +0x88e
testing.Main(0x583450, 0x815780, 0xf, 0xf, 0x824580, ...)
/usr/local/src/go/src/pkg/testing/testing.go:365 +0x8a
main.main()
code.google.com/p/odbc/_test/_testmain.go:73 +0x9a
goroutine 2 [syscall]:
exit status 2
FAIL code.google.com/p/odbc 0.083s
Original comment by victor.kryukov on 12 Nov 2013 at 5:34
Here is my MS SQL Version:
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64)
Apr 2 2010 15:48:46
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)
Original comment by victor.kryukov on 12 Nov 2013 at 5:38
Incidentally, 4294967295 is 0xFFFFFFFF. I don't know what MS SQL server is
trying to say here...
I checked the dbo.temp table that was created at the server, and it looks OK
with the following 4 records:
glenda 5 1 15.50 2000-05-10 11:01:01.0 00000BADC0DE aa
gopher 3 0 26.12 2009-05-10 11:01:01.123 00 bbb
chris 25 0 50.00 2015-12-25 00:00:00.0 636363
null 0 0 0.00 2015-12-25 01:02:03.0
Original comment by victor.kryukov on 12 Nov 2013 at 5:46
The following change make the TestMSSQLCreateInsertDelete pass, but now it
hands on TestMSSQLTransactions
diff -r 703276ff5038 column.go
--- a/column.go Fri Nov 01 11:01:50 2013 +1100
+++ b/column.go Tue Nov 12 18:05:28 2013 +0000
@@ -229,13 +229,14 @@
return nil, NewError("SQLGetData", h)
}
}
- if c.Len.IsNull() {
+ if c.Len.IsNull() || c.Len == 0xFFFFFFFF {
// is NULL
return nil, nil
}
if !c.IsVariableWidth && int(c.Len) != c.Size {
panic(fmt.Errorf("wrong column #%d length %d returned, %d expected", idx, c.Len, c.Size))
}
+ fmt.Printf("%d: c=%+v c.Buffer=%+v\n", idx, c, c.Buffer)
return c.BaseColumn.Value(c.Buffer[:c.Len])
}
Original comment by victor.kryukov on 12 Nov 2013 at 6:06
s/hands/hangs/
Original comment by victor.kryukov on 12 Nov 2013 at 6:06
May be related:
https://code.google.com/p/pyodbc/issues/detail?id=51
Specifically,
"On Windows, SQLLEN is an int64 and SQL_NULL_DATA is (-1). Assuming the 64-bit
driver
is correctly putting a 64-bit -1 in the field, it should work."
Original comment by victor.kryukov on 12 Nov 2013 at 6:09
I think you are correct, it is something to do with how ODBC types are defined
on your system. I hate this - that is why I use Go - there is never a question.
:-)
To help us determine what is going on, please change mssql_test.go, like:
diff --git a/mssql_test.go b/mssql_test.go
--- a/mssql_test.go
+++ b/mssql_test.go
@@ -15,6 +15,9 @@
"sync/atomic"
"testing"
"time"
+ "unsafe"
+
+ "code.google.com/p/odbc/api"
)
var (
@@ -1210,3 +1213,11 @@
exec(t, db, "drop table dbo.temp")
}
+
+func TestALEX(t *testing.T) {
+ fmt.Printf("api.SQL_NULL_DATA=%d\n", api.SQL_NULL_DATA)
+ var l api.SQLLEN
+ fmt.Printf("unsafe.Sizeof(api.SQLLEN)=%d\n", unsafe.Sizeof(l))
+ l = api.SQL_NULL_DATA
+ fmt.Printf("l=%d\n", l)
+}
and run it like
go test -run=ALEX
and show us the output.
That is what I see here on windows/amd64:
c:\go\path\src\code.google.com\p\odbc>go test -v -run=ALEX
=== RUN TestALEX
api.SQL_NULL_DATA=-1
unsafe.Sizeof(api.SQLLEN)=8
l=-1
--- PASS: TestALEX (0.00 seconds)
PASS
ok code.google.com/p/odbc 0.050s
Thank you.
Alex
Original comment by [email protected] on 13 Nov 2013 at 1:34
Here you are, Alex:
[oracle@custservices odbc]$ go test -run=ALEX
warning: building out-of-date packages:
code.google.com/p/odbc/api
installing these packages with 'go test -i' will speed future tests.
api.SQL_NULL_DATA=-1
unsafe.Sizeof(api.SQLLEN)=8
l=-1
PASS
ok code.google.com/p/odbc 0.016s
Original comment by victor.kryukov on 13 Nov 2013 at 1:38
Here is another test:
diff -r 703276ff5038 mssql_test.go
--- a/mssql_test.go Fri Nov 01 11:01:50 2013 +1100
+++ b/mssql_test.go Wed Nov 13 01:48:57 2013 +0000
@@ -13,10 +13,14 @@
"strconv"
"strings"
"sync/atomic"
"testing"
"time"
+ "reflect"
+ "unsafe"
+
+ "code.google.com/p/odbc/api"
)
var (
mssrv = flag.String("mssrv", "server", "ms sql server name")
msdb = flag.String("msdb", "dbname", "ms sql server database name")
@@ -1208,5 +1212,21 @@
}
}
exec(t, db, "drop table dbo.temp")
}
+
+func TestALEX(t *testing.T) {
+ fmt.Printf("api.SQL_NULL_DATA=%d\n", api.SQL_NULL_DATA)
+ var l api.SQLLEN
+ fmt.Printf("unsafe.Sizeof(api.SQLLEN)=%d\n", unsafe.Sizeof(l))
+ l = api.SQL_NULL_DATA
+ fmt.Printf("l=%d\n", l)
+}
+
+func TestVICTOR(t *testing.T) {
+ var x api.SQLLEN = 1
+ v := reflect.ValueOf(x)
+ fmt.Println("type:", v.Type())
+ fmt.Println("kind is uint64:", v.Kind() == reflect.Uint64)
+ fmt.Println("kind is int64:", v.Kind() == reflect.Int64)
+}
[oracle@custservices odbc]$ go test -run=VICTOR
warning: building out-of-date packages:
code.google.com/p/odbc/api
installing these packages with 'go test -i' will speed future tests.
type: api.SQLLEN
kind is uint64: false
kind is int64: true
PASS
ok code.google.com/p/odbc 0.015s
Original comment by victor.kryukov on 13 Nov 2013 at 1:50
Well, could it be that in NewVariableWidthColumn, colWidth is api.SQLULEN, not
api.SQLLEN?
Original comment by victor.kryukov on 13 Nov 2013 at 1:54
I don't think so. I am thinking - I am a slow thinker.
Alex
Original comment by [email protected] on 13 Nov 2013 at 1:58
What about if you make this change:
diff --git a/odbcstmt.go b/odbcstmt.go
--- a/odbcstmt.go
+++ b/odbcstmt.go
@@ -130,7 +130,7 @@
}
// fetch column descriptions
s.Cols = make([]Column, n)
- binding := true
+ binding := false
for i := range s.Cols {
c, err := NewColumn(s.h, i)
if err != nil {
Do tests run OK?
Alex
Original comment by [email protected] on 13 Nov 2013 at 6:37
[deleted comment]
No, same problem:
=== RUN TestMSSQLCreateInsertDelete
--- FAIL: TestMSSQLCreateInsertDelete (0.03 seconds)
panic: runtime error: slice bounds out of range [recovered]
panic: runtime error: slice bounds out of range
goroutine 4 [running]:
testing.func·004()
/usr/local/src/go/src/pkg/testing/testing.go:348 +0xcd
code.google.com/p/odbc.(*BindableColumn).Value(0xc200070e40, 0xbaedfd0, 0x6,
0x4f36c0, 0xc200087cc0, ...)
/home/oracle/gosrc/src/code.google.com/p/odbc/column.go:239 +0x283
code.google.com/p/odbc.(*Rows).Next(0xc2000004c8, 0xc200054540, 0x7, 0x7,
0x54ee20, ...)
/home/oracle/gosrc/src/code.google.com/p/odbc/rows.go:34 +0x137
database/sql.(*Rows).Next(0xc20008a300, 0x3)
/usr/local/src/go/src/pkg/database/sql/sql.go:1310 +0xc1
code.google.com/p/odbc.TestMSSQLCreateInsertDelete(0xc200098000)
/home/oracle/gosrc/src/code.google.com/p/odbc/mssql_test.go:270 +0x62f
testing.tRunner(0xc200098000, 0x815780)
/usr/local/src/go/src/pkg/testing/testing.go:353 +0x8a
created by testing.RunTests
/usr/local/src/go/src/pkg/testing/testing.go:433 +0x86b
goroutine 1 [chan receive]:
testing.RunTests(0x583330, 0x815780, 0xf, 0xf, 0x1, ...)
/usr/local/src/go/src/pkg/testing/testing.go:434 +0x88e
testing.Main(0x583330, 0x815780, 0xf, 0xf, 0x824580, ...)
/usr/local/src/go/src/pkg/testing/testing.go:365 +0x8a
main.main()
code.google.com/p/odbc/_test/_testmain.go:73 +0x9a
goroutine 2 [syscall]:
exit status 2
FAIL code.google.com/p/odbc 0.056s
Original comment by victor.kryukov on 13 Nov 2013 at 4:56
I am still puzzled. I suspect your SQLBindCol and SQLGetData return unexpected
(maybe invalid) values. Can you apply this patch:
diff --git a/column.go b/column.go
--- a/column.go
+++ b/column.go
@@ -13,22 +13,31 @@
"unsafe"
)
-type BufferLen api.SQLLEN
+type BufferLen struct {
+ Pre int64
+ Value api.SQLLEN
+ Post int64
+}
func (l *BufferLen) IsNull() bool {
- return *l == api.SQL_NULL_DATA
+ return l.Value == api.SQL_NULL_DATA
}
func (l *BufferLen) GetData(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN {
return api.SQLGetData(h, api.SQLUSMALLINT(idx+1), ctype,
api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)),
- (*api.SQLLEN)(l))
+ &l.Value)
}
func (l *BufferLen) Bind(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN {
return api.SQLBindCol(h, api.SQLUSMALLINT(idx+1), ctype,
api.SQLPOINTER(unsafe.Pointer(&buf[0])), api.SQLLEN(len(buf)),
- (*api.SQLLEN)(l))
+ &l.Value)
+}
+
+func (l *BufferLen) ValueBytes() []byte {
+ n := unsafe.Sizeof(l.Value)
+ return (*[100]byte)(unsafe.Pointer(&l.Value))[:n]
}
// Column provides access to row columns.
@@ -224,7 +233,9 @@
func (c *BindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) {
if !c.IsBound {
+ fmt.Printf("before GetData: c=%+v c.Len.ValueBytes=%+v\n", c,
c.Len.ValueBytes())
ret := c.Len.GetData(h, idx, c.CType, c.Buffer)
+ fmt.Printf("after GetData: c=%+v c.Len.ValueBytes=%+v\n", c,
c.Len.ValueBytes())
if IsError(ret) {
return nil, NewError("SQLGetData", h)
}
@@ -233,10 +244,10 @@
// is NULL
return nil, nil
}
- if !c.IsVariableWidth && int(c.Len) != c.Size {
+ if !c.IsVariableWidth && int(c.Len.Value) != c.Size {
panic(fmt.Errorf("wrong column #%d length %d returned, %d expected", idx, c.Len, c.Size))
}
- return c.BaseColumn.Value(c.Buffer[:c.Len])
+ return c.BaseColumn.Value(c.Buffer[:c.Len.Value])
}
// NonBindableColumn provide access to columns, that can't be bound.
@@ -263,7 +274,7 @@
// is NULL
return nil, nil
}
- total = append(total, b[:l]...)
+ total = append(total, b[:l.Value]...)
break loop
case api.SQL_SUCCESS_WITH_INFO:
err := NewError("SQLGetData", h).(*Error)
@@ -278,12 +289,12 @@
i-- // remove null-termination character
}
total = append(total, b[:i]...)
- if l != api.SQL_NO_TOTAL {
+ if l.Value != api.SQL_NO_TOTAL {
// odbc gives us a hint about remaining data,
// lets get it in one go.
- n := int(l) // total bytes for our data
- n -= i // subtract already received
- n += 2 // room for biggest (wchar) null-terminator
+ n := int(l.Value) // total bytes for our data
+ n -= i // subtract already received
+ n += 2 // room for biggest (wchar) null-terminator
if len(b) < n {
b = make([]byte, n)
}
diff --git a/mssql_test.go b/mssql_test.go
--- a/mssql_test.go
+++ b/mssql_test.go
@@ -1220,3 +1220,20 @@
t.Fatal("comparison fails")
}
}
+
+func TestMSSQLALEX(t *testing.T) {
+ db, sc, err := mssqlConnect()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer closeDB(t, db, sc, sc)
+
+ var s sql.NullString
+ err = db.QueryRow("select cast(null as varchar(10))").Scan(&s)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if s.Valid {
+ t.Errorf("expected NULL string, but received %v", s)
+ }
+}
diff --git a/odbcstmt.go b/odbcstmt.go
--- a/odbcstmt.go
+++ b/odbcstmt.go
@@ -130,7 +130,7 @@
}
// fetch column descriptions
s.Cols = make([]Column, n)
- binding := true
+ binding := false
for i := range s.Cols {
c, err := NewColumn(s.h, i)
if err != nil {
and run TestMSSQLALEX test and provide output here.
Thank you.
Alex
Original comment by [email protected] on 15 Nov 2013 at 4:33
Here you are:
=== RUN TestMSSQLALEX
before GetData: c=&{BaseColumn:0xc200087580 IsBound:false IsVariableWidth:true
Size:11 Len:{Pre:0 Value:0 Post:0} Buffer:[0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0
0 0 0 0 0 0]} c.Len.ValueBytes=[0 0 0 0 0 0 0 0]
after GetData: c=&{BaseColumn:0xc200087580 IsBound:false IsVariableWidth:true
Size:11 Len:{Pre:0 Value:4294967295 Post:0} Buffer:[0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]} c.Len.ValueBytes=[255 255 255 255 0 0 0 0]
--- FAIL: TestMSSQLALEX (0.01 seconds)
panic: runtime error: slice bounds out of range [recovered]
panic: runtime error: slice bounds out of range
goroutine 4 [running]:
testing.func·004()
/usr/local/src/go/src/pkg/testing/testing.go:348 +0xcd
code.google.com/p/odbc.(*BindableColumn).Value(0xc200074230, 0x1d170910, 0x0,
0x1, 0x41ad2a, ...)
/home/oracle/gosrc/src/code.google.com/p/odbc/column.go:250 +0x53e
code.google.com/p/odbc.(*Rows).Next(0xc2000001f0, 0xc200077ff0, 0x1, 0x1, 0x1,
...)
/home/oracle/gosrc/src/code.google.com/p/odbc/rows.go:34 +0x137
database/sql.(*Rows).Next(0xc20008a300, 0x52bce0)
/usr/local/src/go/src/pkg/database/sql/sql.go:1310 +0xc1
database/sql.(*Row).Scan(0xc2000875a0, 0x2abe22b91f50, 0x1, 0x1, 0x0, ...)
/usr/local/src/go/src/pkg/database/sql/sql.go:1424 +0x1ae
code.google.com/p/odbc.TestMSSQLALEX(0xc20009b000)
/home/oracle/gosrc/src/code.google.com/p/odbc/mssql_test.go:1222 +0x1e1
testing.tRunner(0xc20009b000, 0x8168d0)
/usr/local/src/go/src/pkg/testing/testing.go:353 +0x8a
created by testing.RunTests
/usr/local/src/go/src/pkg/testing/testing.go:433 +0x86b
goroutine 1 [chan receive]:
testing.RunTests(0x583e38, 0x816780, 0x10, 0x10, 0x1, ...)
/usr/local/src/go/src/pkg/testing/testing.go:434 +0x88e
testing.Main(0x583e38, 0x816780, 0x10, 0x10, 0x825580, ...)
/usr/local/src/go/src/pkg/testing/testing.go:365 +0x8a
main.main()
code.google.com/p/odbc/_test/_testmain.go:75 +0x9a
goroutine 2 [syscall]:
exit status 2
FAIL code.google.com/p/odbc 0.035s
Original comment by victor.kryukov on 15 Nov 2013 at 4:39
Please, run this
diff --git a/column.go b/column.go
--- a/column.go
+++ b/column.go
@@ -16,7 +16,7 @@
type BufferLen api.SQLLEN
func (l *BufferLen) IsNull() bool {
- return *l == api.SQL_NULL_DATA
+ return *l == 4294967295
}
func (l *BufferLen) GetData(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN {
@@ -224,7 +224,9 @@
func (c *BindableColumn) Value(h api.SQLHSTMT, idx int) (driver.Value, error) {
if !c.IsBound {
+ fmt.Printf("before GetData: c=%+v\n", c)
ret := c.Len.GetData(h, idx, c.CType, c.Buffer)
+ fmt.Printf("after GetData: c=%+v\n", c)
if IsError(ret) {
return nil, NewError("SQLGetData", h)
}
diff --git a/mssql_test.go b/mssql_test.go
--- a/mssql_test.go
+++ b/mssql_test.go
@@ -1220,3 +1220,20 @@
t.Fatal("comparison fails")
}
}
+
+func TestMSSQLALEX(t *testing.T) {
+ db, sc, err := mssqlConnect()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer closeDB(t, db, sc, sc)
+
+ var s sql.NullString
+ err = db.QueryRow("select cast(null as varchar(10))").Scan(&s)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if s.Valid {
+ t.Errorf("expected NULL string, but received %v", s)
+ }
+}
diff --git a/odbcstmt.go b/odbcstmt.go
--- a/odbcstmt.go
+++ b/odbcstmt.go
@@ -130,7 +130,7 @@
}
// fetch column descriptions
s.Cols = make([]Column, n)
- binding := true
+ binding := false
for i := range s.Cols {
c, err := NewColumn(s.h, i)
if err != nil {
diff --git a/param.go b/param.go
--- a/param.go
+++ b/param.go
@@ -47,7 +47,7 @@
buf = nil
size = 1
buflen = 0
- plen = p.StoreStrLen_or_IndPtr(api.SQL_NULL_DATA)
+ plen = p.StoreStrLen_or_IndPtr(4294967295)
sqltype = api.SQL_WCHAR
case string:
ctype = api.SQL_C_WCHAR
Thank you.
Alex
Original comment by [email protected] on 15 Nov 2013 at 4:59
Hi Alex, sorry for the long silence. Now everything passes:
=== RUN TestMSSQLALEX
before GetData: c=&{BaseColumn:0xc200087580 IsBound:false IsVariableWidth:true
Size:11 Len:0 Buffer:[0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200087580 IsBound:false IsVariableWidth:true
Size:11 Len:4294967295 Buffer:[0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0
0]}
--- PASS: TestMSSQLALEX (0.01 seconds)
PASS
ok code.google.com/p/odbc 0.020s
Original comment by victor.kryukov on 7 Dec 2013 at 9:17
When I run the full test suite, though, it hangs at TestMSSQLTransactions:
=== RUN TestMSSQLCreateInsertDelete
before GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:0 Buffer:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0
0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:6 Buffer:[103 108 101 110 100 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:0 Buffer:[0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[5 0 0 0] smallBuf:[5 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:0 Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:1 Buffer:[1] smallBuf:[1 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:0 Buffer:[0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:8 Buffer:[0 0 0 0 0 0 47 64] smallBuf:[0 0 0 0 0 0 47 64]}
before GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:0 Buffer:[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0
0]}
after GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:16 Buffer:[208 7 5 0 10 0 11 0 1 0 1 0 0 0 0 0] smallBuf:[0 0 0 0 0
0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:0 Buffer:[0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:6 Buffer:[0 0 11 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:0 Buffer:[0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:2 Buffer:[97 97 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:6 Buffer:[103 108 101 110 100 97 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:6 Buffer:[103 111 112 104 101 114 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[5 0 0 0] smallBuf:[5 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[3 0 0 0] smallBuf:[3 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:1 Buffer:[1] smallBuf:[1 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:1 Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:8 Buffer:[0 0 0 0 0 0 47 64] smallBuf:[0 0 0 0 0 0 47 64]}
after GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:8 Buffer:[31 133 235 81 184 30 58 64] smallBuf:[31 133 235 81 184 30
58 64]}
before GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:16 Buffer:[208 7 5 0 10 0 11 0 1 0 1 0 0 0 0 0] smallBuf:[0 0 0 0 0
0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:16 Buffer:[217 7 5 0 10 0 11 0 1 0 1 0 192 212 84 7] smallBuf:[0 0
0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:6 Buffer:[0 0 11 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:1 Buffer:[0 0 11 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:2 Buffer:[97 97 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:3 Buffer:[98 98 98 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:6 Buffer:[103 111 112 104 101 114 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:5 Buffer:[99 104 114 105 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[3 0 0 0] smallBuf:[3 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[25 0 0 0] smallBuf:[25 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:1 Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:1 Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:8 Buffer:[31 133 235 81 184 30 58 64] smallBuf:[31 133 235 81 184 30
58 64]}
after GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:8 Buffer:[0 0 0 0 0 0 73 64] smallBuf:[0 0 0 0 0 0 73 64]}
before GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:16 Buffer:[217 7 5 0 10 0 11 0 1 0 1 0 192 212 84 7] smallBuf:[0 0
0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:16 Buffer:[223 7 12 0 25 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0
0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:1 Buffer:[0 0 11 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:3 Buffer:[99 99 99 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:3 Buffer:[98 98 98 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:4294967295 Buffer:[98 98 98 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0
0 0]}
before GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:5 Buffer:[99 104 114 105 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a20 IsBound:false IsVariableWidth:true
Size:21 Len:4 Buffer:[110 117 108 108 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[25 0 0 0] smallBuf:[25 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088a60 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:1 Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088aa0 IsBound:false IsVariableWidth:false
Size:1 Len:1 Buffer:[0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:8 Buffer:[0 0 0 0 0 0 73 64] smallBuf:[0 0 0 0 0 0 73 64]}
after GetData: c=&{BaseColumn:0xc200088ae0 IsBound:false IsVariableWidth:false
Size:8 Len:8 Buffer:[0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:16 Buffer:[223 7 12 0 25 0 0 0 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0
0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b00 IsBound:false IsVariableWidth:false
Size:16 Len:16 Buffer:[223 7 12 0 25 0 1 0 2 0 3 0 0 0 0 0] smallBuf:[0 0 0 0 0
0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:3 Buffer:[99 99 99 173 192 222 0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc200088b20 IsBound:false IsVariableWidth:true
Size:10 Len:4294967295 Buffer:[99 99 99 173 192 222 0 0 0 0] smallBuf:[0 0 0 0
0 0 0 0]}
before GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:4294967295 Buffer:[98 98 98 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0
0 0]}
after GetData: c=&{BaseColumn:0xc200088b40 IsBound:false IsVariableWidth:true
Size:11 Len:4294967295 Buffer:[98 98 98 0 0 0 0 0 0 0 0] smallBuf:[0 0 0 0 0 0
0 0]}
--- PASS: TestMSSQLCreateInsertDelete (0.13 seconds)
=== RUN TestMSSQLTransactions
before GetData: c=&{BaseColumn:0xc2000b4d40 IsBound:false IsVariableWidth:false
Size:4 Len:0 Buffer:[0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc2000b4d40 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
before GetData: c=&{BaseColumn:0xc2000b4e80 IsBound:false IsVariableWidth:false
Size:4 Len:0 Buffer:[0 0 0 0] smallBuf:[0 0 0 0 0 0 0 0]}
after GetData: c=&{BaseColumn:0xc2000b4e80 IsBound:false IsVariableWidth:false
Size:4 Len:4 Buffer:[1 0 0 0] smallBuf:[1 0 0 0 0 0 0 0]}
Original comment by victor.kryukov on 7 Dec 2013 at 9:19
victor,
I googled again, and as you pointed yourself earlier
(https://code.google.com/p/pyodbc/issues/detail?id=51), I think there is a
mismatch here somewhere. I suspect your unixODBC is compiled as 64-bit, while
freetds is 32-bit. This http://bugs.mysql.com/bug.php?id=68185 describes
situation similar to yours, but with a different language and different driver.
I don't think I can help you any here. I am no good with Linux, you have to
work out how to rebuild / reinstall your libs.
I don't think we should start investigating TestMSSQLTransactions until you
sore previous problem. Sorry.
Alex
Original comment by [email protected] on 9 Dec 2013 at 12:44
I see a similar panic. Note that c.Len is no ware near -1 or MAXINT and my environment is 64 bit.
ALAN 259 len buffer 256 len 324
2018/11/02 11:13:36 http2: panic serving 172.26.0.1:57406: runtime error: slice bounds out of range
goroutine 54 [running]:
net/http.(*http2serverConn).runHandler.func1(0xc4202da000, 0xc4203b5faf, 0xc420020380)
/usr/lib/go-1.10/src/net/http/h2_bundle.go:5753 +0x190
panic(0x7f7e20, 0xc8eec0)
/usr/lib/go-1.10/src/runtime/panic.go:502 +0x229
bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/alexbrainman/odbc.(*BindableColumn).Value(0xc4205afa80, 0x7f76c00008c0, 0x61, 0x7cf2e0, 0xc4204031e8, 0x0, 0x0)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/alexbrainman/odbc/column.go:260 +0x3e7
bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/alexbrainman/odbc.(*Rows).Next(0xc4202da018, 0xc4200a9800, 0x62, 0x62, 0x0, 0xc4203b4408)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/alexbrainman/odbc/rows.go:35 +0xbf
database/sql.(*Rows).nextLocked(0xc4202ece00, 0xc420320000)
/usr/lib/go-1.10/src/database/sql/sql.go:2622 +0xc4
database/sql.(*Rows).Next.func1()
/usr/lib/go-1.10/src/database/sql/sql.go:2600 +0x3c
database/sql.withLock(0x8c8a00, 0xc4202ece30, 0xc4203b4458)
/usr/lib/go-1.10/src/database/sql/sql.go:3032 +0x63
database/sql.(*Rows).Next(0xc4202ece00, 0xc4202da130)
/usr/lib/go-1.10/src/database/sql/sql.go:2599 +0x7a
bitbucket.eng.zebrium.com/zsw/zwsd/link.EventMapAction(0xc42016e630, 0xc4205a6900, 0xc4202ce5c0, 0x873877, 0x10)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/link/event_map.go:179 +0x3069
bitbucket.eng.zebrium.com/zsw/zwsd/zwsd/handlers/eventmap.EventMapAPI.Post(0xc42016e630)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/zwsd/handlers/eventmap/eventmap_api_Map.go:37 +0x234
main.(EventMapInterface).Post-fm(0xc42016e630)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/zwsd/eventmap_if.go:19 +0x39
bitbucket.eng.zebrium.com/zsw/zwsd/link.TokenAuthHandler.ServeHTTP(0xc420162620, 0x8c9b40, 0xc4202da000, 0xc420142700)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/link/auth.go:145 +0x8f9
bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/gorilla/mux.(*Router).ServeHTTP(0xc4201607e0, 0x8c9b40, 0xc4202da000, 0xc420142700)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/gorilla/mux/mux.go:162 +0xed
bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/watercraft/handlers.(*cors).ServeHTTP(0xc4201d6120, 0x8c9b40, 0xc4202da000, 0xc420364100)
/home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/watercraft/handlers/cors.go:51 +0xa04
net/http.serverHandler.ServeHTTP(0xc4201de000, 0x8c9b40, 0xc4202da000, 0xc420364100)
/usr/lib/go-1.10/src/net/http/server.go:2694 +0xbc
net/http.initNPNRequest.ServeHTTP(0xc4200f8a80, 0xc4201de000, 0x8c9b40, 0xc4202da000, 0xc420364100)
/usr/lib/go-1.10/src/net/http/server.go:3260 +0x9a
net/http.(Handler).ServeHTTP-fm(0x8c9b40, 0xc4202da000, 0xc420364100)
/usr/lib/go-1.10/src/net/http/h2_bundle.go:5475 +0x4d
net/http.(*http2serverConn).runHandler(0xc420020380, 0xc4202da000, 0xc420364100, 0xc42000c080)
/usr/lib/go-1.10/src/net/http/h2_bundle.go:5760 +0x89
created by net/http.(*http2serverConn).processHeaders
/usr/lib/go-1.10/src/net/http/h2_bundle.go:5494 +0x46b
bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/alexbrainman/odbc.(*BindableColumn).Value(0xc4205afa80, 0x7f76c00008c0, 0x61, 0x7cf2e0, 0xc4204031e8, 0x0, 0x0) /home/alan-y/go/src/bitbucket.eng.zebrium.com/zsw/zwsd/vendor/github.com/alexbrainman/odbc/column.go:260 +0x3e7
Current version of column.go line 260 https://github.com/alexbrainman/odbc/blob/2d7d0e45c7870320611501683ca6073a0d9dfeed/column.go#L260 does not have panic. And you did not say how do I reproduce the problem.
Alex