func NewError(apiName string, handle interface{}) error { h, ht := ToHandleAndType(handle) err := &Error{APIName: apiName} var ne api.SQLINTEGER state := make([]uint16, 6) msg := make([]uint16, api.SQL_MAX_MESSAGE_LENGTH) for i := 1; ; i++ { ret := api.SQLGetDiagRec(ht, h, api.SQLSMALLINT(i), (*api.SQLWCHAR)(unsafe.Pointer(&state[0])), &ne, (*api.SQLWCHAR)(unsafe.Pointer(&msg[0])), api.SQLSMALLINT(len(msg)), nil) if ret == api.SQL_NO_DATA { break } if IsError(ret) { panic(fmt.Errorf("SQLGetDiagRec failed: ret=%d", ret)) } r := DiagRecord{ State: api.UTF16ToString(state), NativeError: int(ne), Message: api.UTF16ToString(msg), } err.Diag = append(err.Diag, r) } return err }
func NewColumn(h api.SQLHSTMT, idx int) (Column, error) { namebuf := make([]uint16, 150) namelen, sqltype, size, ret := describeColumn(h, idx, namebuf) if ret == api.SQL_SUCCESS_WITH_INFO && namelen > len(namebuf) { // try again with bigger buffer namebuf = make([]uint16, namelen) namelen, sqltype, size, ret = describeColumn(h, idx, namebuf) } if IsError(ret) { return nil, NewError("SQLDescribeCol", h) } if namelen > len(namebuf) { // still complaining about buffer size return nil, errors.New("Failed to allocate column name buffer") } b := &BaseColumn{ name: api.UTF16ToString(namebuf[:namelen]), } switch sqltype { case api.SQL_BIT: return NewBindableColumn(b, api.SQL_C_BIT, 1), nil case api.SQL_TINYINT, api.SQL_SMALLINT, api.SQL_INTEGER: return NewBindableColumn(b, api.SQL_C_LONG, 4), nil case api.SQL_BIGINT: return NewBindableColumn(b, api.SQL_C_SBIGINT, 8), nil case api.SQL_NUMERIC, api.SQL_DECIMAL, api.SQL_FLOAT, api.SQL_REAL, api.SQL_DOUBLE: return NewBindableColumn(b, api.SQL_C_DOUBLE, 8), nil case api.SQL_TYPE_TIMESTAMP: var v api.SQL_TIMESTAMP_STRUCT return NewBindableColumn(b, api.SQL_C_TYPE_TIMESTAMP, int(unsafe.Sizeof(v))), nil case api.SQL_TYPE_DATE: var v api.SQL_DATE_STRUCT return NewBindableColumn(b, api.SQL_C_DATE, int(unsafe.Sizeof(v))), nil case api.SQL_GUID: var v api.SQLGUID return NewBindableColumn(b, api.SQL_C_GUID, int(unsafe.Sizeof(v))), nil case api.SQL_CHAR, api.SQL_VARCHAR: return NewVariableWidthColumn(b, api.SQL_C_CHAR, size), nil case api.SQL_WCHAR, api.SQL_WVARCHAR: return NewVariableWidthColumn(b, api.SQL_C_WCHAR, size), nil case api.SQL_BINARY, api.SQL_VARBINARY: return NewVariableWidthColumn(b, api.SQL_C_BINARY, size), nil case api.SQL_LONGVARCHAR: return NewVariableWidthColumn(b, api.SQL_C_CHAR, 0), nil case api.SQL_WLONGVARCHAR, api.SQL_SS_XML: return NewVariableWidthColumn(b, api.SQL_C_WCHAR, 0), nil case api.SQL_LONGVARBINARY: return NewVariableWidthColumn(b, api.SQL_C_BINARY, 0), nil default: return nil, fmt.Errorf("unsupported column type %d", sqltype) } panic("unreachable") }
// https://code.google.com/p/odbc/issues/detail?id=27 func TestMSSQLUTF16ToUTF8(t *testing.T) { s := []uint16{0x47, 0x75, 0x73, 0x74, 0x61, 0x66, 0x27, 0x73, 0x20, 0x4b, 0x6e, 0xe4, 0x63, 0x6b, 0x65, 0x62, 0x72, 0xf6, 0x64} if api.UTF16ToString(s) != string(utf16toutf8(s)) { t.Fatal("comparison fails") } }