diff --git a/column.go b/column.go index 6dcbb17..9daa02b 100644 --- a/column.go +++ b/column.go @@ -17,7 +17,7 @@ import ( type BufferLen api.SQLLEN func (l *BufferLen) IsNull() bool { - return *l == api.SQL_NULL_DATA + return *l == api.SQL_NULL_DATA || int64(*l) == 0x00000000ffffffff } func (l *BufferLen) GetData(h api.SQLHSTMT, idx int, ctype api.SQLSMALLINT, buf []byte) api.SQLRETURN { diff --git a/column_test.go b/column_test.go new file mode 100644 index 0000000..928022f --- /dev/null +++ b/column_test.go @@ -0,0 +1,49 @@ +// Copyright 2012 The Go Authors. All rights reserved. + +// Use of this source code is governed by a BSD-style + +// license that can be found in the LICENSE file. + +package odbc + +import ( + "fmt" + "testing" + "unsafe" +) + +func TestBufferLen_IsNull(t *testing.T) { + tests := []struct { + name string + i interface{} + l BufferLen + want bool + }{ + // TODO: Add test cases. + {name: "IsNull ", i: int64(-1), want: true}, + {name: "IsNull ", i: int32(-1), want: true}, + {name: "IsNull ", i: int64(0x00000000ffffffff), want: true}, + + {name: "NotNull ", i: int32(1)}, + {name: "NotNull ", i: int32(0x7fffffff)}, + {name: "NotNull ", i: int64(0x1ffffffff)}, + } + for _, tt := range tests { + switch i := tt.i.(type) { + case int64: + if unsafe.Sizeof(tt.l) != 8 { + continue + } + tt.l = BufferLen(i) + tt.name += fmt.Sprintf("0x%016x", uint64(i)) + case int32: + tt.l = BufferLen(i) + tt.name += fmt.Sprintf("0x%08x", uint32(i)) + } + t.Run(tt.name, func(t *testing.T) { + if got := tt.l.IsNull(); got != tt.want { + t.Errorf("BufferLen.IsNull() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/mssql_test.go b/mssql_test.go index fc91098..90c99eb 100644 --- a/mssql_test.go +++ b/mssql_test.go @@ -620,6 +620,8 @@ var typeTests = []typeTest{ {"select cast('abcde' as nvarchar(3))", match([]byte("abc"))}, {"select cast('' as nvarchar(5))", match([]byte(""))}, {"select cast(NULL as nvarchar(5))", match(nil)}, + {"select cast('你好世界' as varchar(21))", match([]byte("你好世界"))}, + {"select cast('Γεια σου κόσμε' as varchar(21))", match([]byte("Γεια σου κόσμε"))}, // datetime, smalldatetime {"select cast('20151225' as datetime)", match(time.Date(2015, 12, 25, 0, 0, 0, 0, time.Local))}, diff --git a/param.go b/param.go index f66d00d..ed9b38b 100644 --- a/param.go +++ b/param.go @@ -80,6 +80,9 @@ func (p *Parameter) BindValue(h api.SQLHSTMT, idx int, v driver.Value, conn *Con // https://docs.microsoft.com/en-us/sql/odbc/microsoft/microsoft-access-data-types sqltype = api.SQL_WLONGVARCHAR } + if p.isDescribed && p.Size > 0 { + size = p.Size + } case int64: if -0x80000000 < d && d < 0x7fffffff { // Some ODBC drivers do not support SQL_BIGINT. @@ -156,6 +159,9 @@ func (p *Parameter) BindValue(h api.SQLHSTMT, idx int, v driver.Value, conn *Con default: sqltype = api.SQL_BINARY } + if p.isDescribed && p.Size > 0 { + size = p.Size + } default: return fmt.Errorf("unsupported type %T", v) }