Skip to content

Commit 8a65b48

Browse files
committed
SliceScan 后,仅 sql.RawBytes 需要做深拷贝逻辑。
1 parent a783a21 commit 8a65b48

1 file changed

Lines changed: 10 additions & 16 deletions

File tree

sqlen/rows.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -98,22 +98,16 @@ func (rs *EnhanceRows) SliceScan() ([]any, error) {
9898
// 之前为了能让 Scan 修改数据,保存的是指针,而返回上层时候只需要实际数据,因此进行解引用。
9999
dest[i] = destRefVal[i].Elem().Interface()
100100

101-
// 注意:database/sql 的 driver 可能在后续复用其内部 buffer。
102-
// Scan 返回后到“下一次使用该连接”之前,[]byte/sql.RawBytes 仍然有效;
103-
// 但如果将该 []byte 直接向上层暴露,可能在之后被覆盖,导致数据损坏。
104-
// 因此这里必须对 []byte 做一次 deep copy,将数据拷贝到独立内存中。
105-
switch v := dest[i].(type) {
106-
case []byte:
107-
if v != nil {
108-
nb := make([]byte, len(v))
109-
copy(nb, v)
110-
dest[i] = nb
111-
}
112-
case sql.RawBytes:
113-
if v != nil {
114-
nb := make([]byte, len(v))
115-
copy(nb, v)
116-
dest[i] = sql.RawBytes(nb)
101+
// 注意:根据 sql.RawBytes 类型的定义,database/sql 的有效性仅在下一次 Scan 或 Close 之前。
102+
// 如果将该 sql.RawBytes 直接向上层暴露,会因为之后被覆写,导致数据损坏。
103+
// 因此这里必须对 sql.RawBytes 做一次 deep copy,将数据拷贝到独立内存中。
104+
if raw, ok := dest[i].(sql.RawBytes); ok {
105+
if raw == nil {
106+
dest[i] = nil
107+
} else {
108+
frozen := make(sql.RawBytes, len(raw))
109+
copy(frozen, raw)
110+
dest[i] = frozen
117111
}
118112
}
119113

0 commit comments

Comments
 (0)