| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- package core
- import (
- "testing"
- "time"
- "git.ycl.pub/yl32940/TsDB2/DB/core/page"
- "git.ycl.pub/yl32940/TsDB2/DB/core/types"
- )
- // TestUpdateNullPreserve 部分更新必须保留旧行的 NULL 列:
- // deserializeRow 不产出 NULL 列, 旧实现"未提供→零值兜底"会把旧行 NULL
- // 静默写成零值 (deleted_at 被污染 → 软删除作用域永久丢失该行,
- // 实测报告 #1/#3 根因)。
- func TestUpdateNullPreserve(t *testing.T) {
- db := fixOpenDB(t)
- tbl, err := db.CreateTable("tp", []types.FieldInfo{
- {FieldType: types.FieldType_Uint64, FieldName: []byte("id")},
- {FieldType: types.FieldType_DateTime, FieldName: []byte("created_at")},
- {FieldType: types.FieldType_DateTime, FieldName: []byte("updated_at")},
- {FieldType: types.FieldType_DateTime, Flag: types.FlagNullable, FieldName: []byte("deleted_at")},
- {FieldType: types.FieldType_String, Flag: types.WidthCodeFor(32) | types.FlagNullable, FieldName: []byte("title")},
- {FieldType: types.FieldType_Int64, Flag: types.FlagNullable, FieldName: []byte("port")},
- })
- if err != nil {
- t.Fatal(err)
- }
- if _, err := tbl.CreateIndex("pk", page.IndexTypePrimary, []byte{0}); err != nil {
- t.Fatal(err)
- }
- if _, err := tbl.InsertRowWithID(1, []types.FieldValue{
- {FieldName: []byte("id"), Value: uint64(1)},
- {FieldName: []byte("created_at"), Value: time.Now()},
- {FieldName: []byte("updated_at"), Value: time.Now()},
- {FieldName: []byte("deleted_at"), Value: nil},
- {FieldName: []byte("title"), Value: "原始"},
- {FieldName: []byte("port"), Value: int64(11)},
- }); err != nil {
- t.Fatal(err)
- }
- db.Commit()
- if err := tbl.UpdateRowByPK(1, []types.FieldValue{
- {FieldName: []byte("title"), Value: "字面量A"},
- {FieldName: []byte("updated_at"), Value: time.Now()},
- }); err != nil {
- t.Fatal(err)
- }
- storeRow, _ := tbl.indexMeta.ResolveByPK(1)
- rowData := storeRow[8:]
- t.Logf("rowData=%x", rowData)
- layout, _ := tbl.parseRowLayout(rowData)
- bm, _ := types.RowNullBitmap(rowData, layout.ends, len(layout.sv.FieldIndices))
- t.Logf("ends=%v bm=%x", layout.ends, bm)
- // deleted_at 的位 (fieldIndex 3 → pos 3)
- t.Logf("deleted_at NullBit=%v", types.NullBitSet(bm, 3))
- }
|