github.com/turingchain2020/turingchain@v1.1.21/common/db/table/join_test.go (about) 1 package table 2 3 import ( 4 "fmt" 5 "testing" 6 7 protodata "github.com/turingchain2020/turingchain/common/db/table/proto" 8 "github.com/turingchain2020/turingchain/util" 9 "github.com/golang/protobuf/proto" 10 "github.com/stretchr/testify/assert" 11 12 "github.com/turingchain2020/turingchain/types" 13 ) 14 15 func TestJoin(t *testing.T) { 16 dir, ldb, kvdb := util.CreateTestDB() 17 defer util.CloseTestDB(dir, ldb) 18 table1, err := NewTable(NewGameRow(), kvdb, optgame) 19 assert.Nil(t, err) 20 table2, err := NewTable(NewGameAddrRow(), kvdb, optgameaddr) 21 assert.Nil(t, err) 22 tablejoin, err := NewJoinTable(table2, table1, []string{"addr#status", "#status"}) 23 assert.Nil(t, err) 24 assert.Equal(t, tablejoin.GetLeft(), table2) //table2 25 assert.Equal(t, tablejoin.GetRight(), table1) //table1 26 assert.Equal(t, tablejoin.MustGetTable("gameaddr"), table2) //table2 27 assert.Equal(t, tablejoin.MustGetTable("game"), table1) //table1 28 29 rightdata := &protodata.Game{GameID: "gameid1", Status: 1} 30 tablejoin.MustGetTable("game").Replace(rightdata) 31 leftdata := &protodata.GameAddr{GameID: "gameid1", Addr: "addr1", Txhash: "hash1"} 32 tablejoin.MustGetTable("gameaddr").Replace(leftdata) 33 kvs, err := tablejoin.Save() 34 assert.Nil(t, err) 35 assert.Equal(t, 7, len(kvs)) 36 util.SaveKVList(ldb, kvs) 37 //query table 38 //每个表的查询,用 tablejoin.MustGetTable("gameaddr") 39 //join query 用 tablejoin.Query 40 rows, err := tablejoin.ListIndex("addr#status", JoinKey([]byte("addr1"), []byte("1")), nil, 0, 0) 41 assert.Nil(t, err) 42 assert.Equal(t, 1, len(rows)) 43 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Left, leftdata)) 44 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Right, rightdata)) 45 46 rows, err = tablejoin.ListIndex("#status", JoinKey(nil, []byte("1")), nil, 0, 0) 47 assert.Nil(t, err) 48 assert.Equal(t, 1, len(rows)) 49 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Left, leftdata)) 50 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Right, rightdata)) 51 52 rightdata = &protodata.Game{GameID: "gameid1", Status: 2} 53 tablejoin.MustGetTable("game").Replace(rightdata) 54 kvs, err = tablejoin.Save() 55 assert.Nil(t, err) 56 assert.Equal(t, 7, len(kvs)) 57 util.SaveKVList(ldb, kvs) 58 rows, err = tablejoin.ListIndex("addr#status", JoinKey([]byte("addr1"), []byte("2")), nil, 0, 0) 59 assert.Nil(t, err) 60 assert.Equal(t, 1, len(rows)) 61 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Left, leftdata)) 62 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Right, rightdata)) 63 64 rows, err = tablejoin.ListIndex("#status", JoinKey(nil, []byte("2")), nil, 0, 0) 65 assert.Nil(t, err) 66 assert.Equal(t, 1, len(rows)) 67 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Left, leftdata)) 68 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Right, rightdata)) 69 70 rightdata = &protodata.Game{GameID: "gameid1", Status: 2} 71 tablejoin.MustGetTable("game").Replace(rightdata) 72 kvs, err = tablejoin.Save() 73 assert.Nil(t, err) 74 assert.Equal(t, 0, len(kvs)) 75 76 leftdata = &protodata.GameAddr{GameID: "gameid1", Addr: "addr2", Txhash: "hash1"} 77 tablejoin.MustGetTable("gameaddr").Replace(leftdata) 78 kvs, err = tablejoin.Save() 79 assert.Nil(t, err) 80 assert.Equal(t, 5, len(kvs)) 81 util.SaveKVList(ldb, kvs) 82 83 //改回到全部是1的情况 84 rightdata = &protodata.Game{GameID: "gameid1", Status: 1} 85 tablejoin.MustGetTable("game").Replace(rightdata) 86 leftdata = &protodata.GameAddr{GameID: "gameid1", Addr: "addr1", Txhash: "hash1"} 87 tablejoin.MustGetTable("gameaddr").Replace(leftdata) 88 kvs, err = tablejoin.Save() 89 assert.Nil(t, err) 90 assert.Equal(t, 10, len(kvs)) 91 util.SaveKVList(ldb, kvs) 92 rows, err = tablejoin.ListIndex("addr#status", JoinKey([]byte("addr1"), []byte("1")), nil, 0, 0) 93 assert.Nil(t, err) 94 assert.Equal(t, 1, len(rows)) 95 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Left, leftdata)) 96 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Right, rightdata)) 97 98 rows, err = tablejoin.ListIndex("#status", JoinKey(nil, []byte("1")), nil, 0, 0) 99 assert.Nil(t, err) 100 assert.Equal(t, 1, len(rows)) 101 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Left, leftdata)) 102 assert.Equal(t, true, proto.Equal(rows[0].Data.(*JoinData).Right, rightdata)) 103 } 104 105 /* 106 table game 107 data: Game 108 index: addr,status,index,type 109 */ 110 var optgame = &Option{ 111 Prefix: "LODB", 112 Name: "game", 113 Primary: "gameID", 114 Index: []string{"status"}, 115 } 116 117 //GameRow table meta 结构 118 type GameRow struct { 119 *protodata.Game 120 } 121 122 //NewGameRow 新建一个meta 结构 123 func NewGameRow() *GameRow { 124 return &GameRow{Game: &protodata.Game{}} 125 } 126 127 //CreateRow 新建数据行(注意index 数据一定也要保存到数据中,不能就保存eventid) 128 func (tx *GameRow) CreateRow() *Row { 129 return &Row{Data: &protodata.Game{}} 130 } 131 132 //SetPayload 设置数据 133 func (tx *GameRow) SetPayload(data types.Message) error { 134 if txdata, ok := data.(*protodata.Game); ok { 135 tx.Game = txdata 136 return nil 137 } 138 return types.ErrTypeAsset 139 } 140 141 //Get 按照indexName 查询 indexValue 142 func (tx *GameRow) Get(key string) ([]byte, error) { 143 if key == "gameID" { 144 return []byte(tx.GameID), nil 145 } else if key == "status" { 146 return []byte(fmt.Sprint(tx.Status)), nil 147 } 148 return nil, types.ErrNotFound 149 } 150 151 /* 152 table struct 153 data: GameAddr 154 index: addr,status,index,type 155 */ 156 157 var optgameaddr = &Option{ 158 Prefix: "LODB", 159 Name: "gameaddr", 160 Primary: "txhash", 161 Index: []string{"gameID", "addr"}, 162 } 163 164 //GameAddrRow table meta 结构 165 type GameAddrRow struct { 166 *protodata.GameAddr 167 } 168 169 //NewGameAddrRow 新建一个meta 结构 170 func NewGameAddrRow() *GameAddrRow { 171 return &GameAddrRow{GameAddr: &protodata.GameAddr{}} 172 } 173 174 //CreateRow 新建数据行(注意index 数据一定也要保存到数据中,不能就保存eventid) 175 func (tx *GameAddrRow) CreateRow() *Row { 176 return &Row{Data: &protodata.GameAddr{}} 177 } 178 179 //SetPayload 设置数据 180 func (tx *GameAddrRow) SetPayload(data types.Message) error { 181 if txdata, ok := data.(*protodata.GameAddr); ok { 182 tx.GameAddr = txdata 183 return nil 184 } 185 return types.ErrTypeAsset 186 } 187 188 //Get 按照indexName 查询 indexValue 189 func (tx *GameAddrRow) Get(key string) ([]byte, error) { 190 if key == "gameID" { 191 return []byte(tx.GameID), nil 192 } else if key == "addr" { 193 return []byte(tx.Addr), nil 194 } else if key == "txhash" { 195 return []byte(tx.Txhash), nil 196 } 197 return nil, types.ErrNotFound 198 }