Open shueybubbles opened 3 years ago
Hello.
Yes, it should do the same as for typeBigChar
.
r, err := db.Query("SELECT CAST('1' AS CHAR(10)), CAST(0x02 AS BINARY(20)), CAST(0x03 AS VARBINARY(30))")
if err != nil {
log.Fatalln(err)
}
c, err := r.ColumnTypes()
if err != nil {
log.Fatalln(err)
}
for i := range c {
fmt.Println(c[i].Length())
}
// 10 true
// 0 false (should be 20 true)
// 30 true
I think you can make a PR.
varbinary handling overall looks funny. EDIT: this behavior difference seems to be a convention for varbinary conversion to string as described here: https://docs.microsoft.com/sql/odbc/reference/appendixes/sql-to-c-binary?view=sql-server-ver15
When binary SQL data is converted to character C data, each byte (8 bits) of source data is represented as two ASCII characters. These characters are the ASCII character representation of the number in its hexadecimal form. For example, a binary 00000001 is converted to "01" and a binary 11111111 is converted to "FF".
I tried with my own app and with usql and it doesn't print what I expect.
ms:sqltools2019-3-> select cast(0x123456 as varbinary(max)) as name;
name
--------
\x124V
(1 row)
Whereas both SSMS and SqlCmd do this:
1> select cast(0x123456 as varbinary(max)) as mylongenoughname
2> go
mylongenoughname
----------------
0x123456
(1 rows affected)
1> select cast('123456' as varbinary(max)) as mylongenoughname
2> go
mylongenoughname
----------------
0x313233343536
(1 rows affected)
Looks like your program is displaying the value as a string literal: 0x12 has to be escaped as \x12
, then you have 0x34 4
and 0x56 V
.
This is correct, actually.
You don't have to cast, the literal value already is a varbinary(3)
.
The link you shared is from the ODBC driver, and it talks about reading C strings. That is not relevant here. go-mssqldb never handles C strings and is unrelated to ODBC.
yeah it's not that the bits on the wire are wrong somehow, it's just a matter of end user expectations for rendering such as the scenarios of printing out query results to a screen or file. The previous tools provided by Microsoft like SSMS and sqlcmd emit binary values using that convention. It's easy enough for my own app to print them this way to follow that convention. I was only referencing the ODBC doc for reference to the convention.
That doesn't happen in the driver.
I think SSMS just reads the []byte
value from the driver, and then it prints it itself as 0x123456
.
Even in ADO.NET, I tried GetString
and GetSqlChars
instead of GetValue
or GetSqlBinary
, and all I got was an exception:
System.InvalidCastException : 'Unable to cast object of type 'System.Byte[]' to type 'System.String'.'
The only difference in Go is that scanning a binary into a string is allowed. And you get something closer to what would happen in T-SQL:
declare @val varchar(max)
select @val = 0x123456
select @val
https://github.com/denisenkom/go-mssqldb/blob/ee2fbc25fd8f2d8c56af5ca2d7b661fb50fdb23a/types.go#L1467
I think this should
return ti.Size, true