steino / odbc

Automatically exported from code.google.com/p/odbc
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Test fails on RedHat Linux 5.9 with unixODBC 2.3.1 and FreeTDS 0.91RC2 #25

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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 alex.bra...@gmail.com on 12 Nov 2013 at 4:40

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
s/hands/hangs/

Original comment by victor.kryukov on 12 Nov 2013 at 6:06

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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 alex.bra...@gmail.com on 13 Nov 2013 at 1:34

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
I don't think so. I am thinking - I am a slow thinker.

Alex

Original comment by alex.bra...@gmail.com on 13 Nov 2013 at 1:58

GoogleCodeExporter commented 9 years ago
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 alex.bra...@gmail.com on 13 Nov 2013 at 6:37

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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 alex.bra...@gmail.com on 15 Nov 2013 at 4:33

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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 alex.bra...@gmail.com on 15 Nov 2013 at 4:59

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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

GoogleCodeExporter commented 9 years ago
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 alex.bra...@gmail.com on 9 Dec 2013 at 12:44