Comments (8)
所以应该改动哪里呢
from odbc.
我个人的处理办法是在param.go的67行下增加
if p.isDescribed && (p.SQLType == api.SQL_VARCHAR || p.SQLType == api.SQL_CHAR) {
size = api.SQLULEN(len(d))
if size < 1 {
// size cannot be less then 1 even for empty fields
size = 1
}
}
个人能力有限。你要好好测试一下。
from odbc.
@dotqi 好奇请教一下
UTF16 和 UTF8 在中文长度上有区别么?
from odbc.
package main
import (
"fmt"
"unicode/utf16"
)
func main() {
val := "你好"
fmt.Println(val)
u16 := StringToUTF16(val)
fmt.Println("u16", len(u16), u16)
// u16 3 [20320 22909 0]
u8 := []byte(val)
fmt.Println("u8", len(u8), u8)
// u8 6 [228 189 160 229 165 189]
}
func StringToUTF16(s string) []uint16 { return utf16.Encode([]rune(s + "\x00")) }
from odbc.
package main
import ( "fmt" "unicode/utf16" )
func main() { val := "你好" fmt.Println(val) u16 := StringToUTF16(val) fmt.Println("u16", len(u16), u16) // u16 3 [20320 22909 0] u8 := []byte(val) fmt.Println("u8", len(u8), u8) // u8 6 [228 189 160 229 165 189] }
func StringToUTF16(s string) []uint16 { return utf16.Encode([]rune(s + "\x00")) }
@dotqi 你这个实验,我做了,感觉你这个不对
- UTF16 和 UTF8 都是可变长度的编码,区别在于 UTF16 最小是两字节,UTF8 最小是一字节
- 你这个计算的是 []uint16 的长度,而非 []byte 长度
u16 := StringToUTF16(val) fmt.Println("u16", len(u16), u16)
- 你这个计算的是 []byte 的长度
u8 := []byte(val) fmt.Println("u8", len(u8), u8)
但实际上,u16 可以转回成 []rune,他们的长度是一模一样的
val := "你好𠀾"
[]uint16 = [20320 22909 55360 56382]
[]rune = [20320 22909 131134]
[]byte = [228 189 160 229 165 189 240 160 128 190]
rune 实际是 int32,比 uint16 表示的多,131134 和 55360 56382 都表示 “𠀾”,它实际占 4 个字节 [240 160 128 190]
from odbc.
分析:
- size = api.SQLULEN(len(d)) 看你改的方式,实际上是 len(s),其实就是 []byte 的长度
- 看这个库原来的方式,比较奇怪,它底层是用的 cgo 调的 c 的 odbc,不明白它为什么转 utf16 而不是转 byte,因为 c 里边都是 char,api.StringToUTF16 给字符串后面加了一个 \0,就是告诉 c 这是一个字符串,它转完 utf16 又给长度*2 做了 buflen
b := api.StringToUTF16(d) p.Data = b buf = unsafe.Pointer(&b[0]) l := len(b) l -= 1 // remove terminating 0 size = api.SQLULEN(l) if size < 1 { // size cannot be less then 1 even for empty fields size = 1 } l *= 2 // every char takes 2 bytes buflen = api.SQLLEN(l) plen = p.StoreStrLen_or_IndPtr(buflen)
- []byte 长度可以为 0,string 就必须是1,应该是因为 \0 的缘故
错误的点:
l *= 2 // every char takes 2 bytes
4字节的 utf16 转换后是 2 个 uint16,*2 没问题
但是 3字节的 utf16 转换后可能是 1 个 uint16,这里 *2 就错了,*3才对
按照 case []byte:
的改写:
case string:
ctype = api.SQL_C_WCHAR
// b := api.StringToUTF16(d)
// p.Data = b
// buf = unsafe.Pointer(&b[0])
// l := len(b)
// l -= 1 // remove terminating 0
// size = api.SQLULEN(l)
// if size < 1 {
// // size cannot be less then 1 even for empty fields
// size = 1
// }
// l *= 2 // every char takes 2 bytes
// buflen = api.SQLLEN(l)
// plen = p.StoreStrLen_or_IndPtr(buflen)
b := []byte(d)
p.Data = append(b, byte(0))
buf = unsafe.Pointer(&b[0])
buflen = api.SQLLEN(len(b))
plen = p.StoreStrLen_or_IndPtr(buflen)
size = api.SQLULEN(len(b))
if size < 1 {
// size cannot be less then 1 even for empty fields
size = 1
}
大胆点:因为使用了 append 所以不用再判断 size < 1 了,我不太明白为什么 buflen 不能包含 \0 的长度,所以参照原来减 1 了
b := append([]byte(d), byte(0))
p.Data = b
buf = unsafe.Pointer(&b[0])
buflen = api.SQLLEN(len(b) - 1)
plen = p.StoreStrLen_or_IndPtr(buflen)
size = api.SQLULEN(len(b))
from odbc.
谢谢,回头按你的方式测试一下。
from odbc.
增加一个PR:#195
from odbc.
Related Issues (20)
- signal 13 received but handler not on signal stack HOT 4
- Low max message length HOT 3
- Add tags to the repo HOT 1
- Implement QueryerContext interface HOT 1
- Implement RowsColumnTypeDatabaseTypeName HOT 1
- error when build from linux HOT 2
- only half of unicode string is inserted.
- Issue with Unixodbc-2.3.7 for master and for_issue_88 branch HOT 1
- Maintain releases HOT 5
- The package is returning a panic instead of an error HOT 4
- Issues with parametrized queries Windows/DuckDB HOT 2
- abount microsoft access long binary data type HOT 1
- Unrecognized Data Type on Column
- random errors when doing the db.query using Denodo odbc driver HOT 1
- Does this package support `-buildmode=c-shared` HOT 1
- Have error `api/api_unix.go:15:11: fatal error: 'sql.h' file not found` HOT 1
- Error : unrecognized import path "golang.zx2c4.com/go118/netip" HOT 2
- connect db2 when column is NULL, parsing data error execution an error occurred is {wrong column #1 length 4294967295 returned, 16 expected} HOT 3
- (duckdb ODBC) Cannot Insert INTEGER HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from odbc.