| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- package DB
- import (
- "path/filepath"
- "strings"
- "testing"
- "git.ycl.pub/yl32940/TsDB2/DB/core/types"
- )
- // TestQueryPropagatesRowConversionError 回归测试: 某行反序列化失败时,
- // FindAll / Select / Query.Scan 必须返回错误, 而不是静默跳过该行、
- // 返回"看起来成功"的部分结果。
- //
- // 触发方式: 用 core 层直接写入一行指向不存在链的 blob 引用
- // (FirstPageID=0 且 TotalLen>0 → 读链必失败), 再经 ORM 全表扫描读到它。
- func TestQueryPropagatesRowConversionError(t *testing.T) {
- type badBlob struct {
- BaseModel
- Data []byte `vrtx:"type:blob"`
- }
- db, err := Open(filepath.Join(t.TempDir(), "test.db"))
- if err != nil {
- t.Fatalf("open: %v", err)
- }
- defer db.Close()
- tbl, err := UseTable[badBlob](db, "badblob")
- if err != nil {
- t.Fatalf("use table: %v", err)
- }
- // 一行正常数据
- if err := tbl.Insert(&badBlob{Data: []byte("hello")}); err != nil {
- t.Fatalf("insert good row: %v", err)
- }
- // 一行坏数据: 行内 blob ref 指向文件之外的页号 (core 层对 types.BlobRef 原样透传),
- // 读链必然失败
- coreTbl, ok := db.CoreDB().FindTable("badblob")
- if !ok {
- t.Fatalf("core table not found")
- }
- if _, err := coreTbl.InsertRowWithID(999, []types.FieldValue{
- {FieldName: []byte("Data"), Value: types.BlobRef{TotalLen: 10, FirstPageID: 0x00FFFFFF}},
- }); err != nil {
- t.Fatalf("insert bad row: %v", err)
- }
- if err := db.Commit(); err != nil {
- t.Fatalf("commit: %v", err)
- }
- // FindAll: 旧实现会静默跳过坏行, 只返回 1 行且 err == nil
- rows, err := tbl.FindAll()
- if err == nil {
- t.Fatalf("FindAll 应返回反序列化错误, 却返回了 %d 行 nil error", len(rows))
- }
- if !strings.Contains(err.Error(), "blob") {
- t.Fatalf("错误信息应说明 blob 读取失败, 得到: %v", err)
- }
- // Select: 同样必须报错而不是跳过
- selErr := tbl.Select(func(*badBlob) bool { return true })
- if selErr == nil {
- t.Fatalf("Select 应返回反序列化错误")
- }
- // Query.Scan: 同样必须报错而不是跳过
- scanErr := tbl.Query().Scan(func(*badBlob) bool { return true })
- if scanErr == nil {
- t.Fatalf("Scan 应返回反序列化错误")
- }
- // 坏行之前的正常行不受影响: 主键点查仍应拿到正确内容
- got, err := tbl.Find(1)
- if err != nil {
- t.Fatalf("Find good row: %v", err)
- }
- if string(got.Data) != "hello" {
- t.Fatalf("good row Data = %q, 想要 hello", got.Data)
- }
- }
|