github.com/turingchain2020/turingchain@v1.1.21/common/db/table/join.go (about) 1 package table 2 3 import ( 4 "errors" 5 "strings" 6 7 "github.com/turingchain2020/turingchain/common/db" 8 "github.com/turingchain2020/turingchain/common/log/log15" 9 "github.com/turingchain2020/turingchain/types" 10 "github.com/turingchain2020/turingchain/util" 11 ) 12 13 var tablelog = log15.New("module", "db.table") 14 15 /* 16 设计表的联查: 17 18 我们不可能做到数据库这样强大的功能,但是联查功能几乎是不可能绕过的功能。 19 20 table1: 21 22 [gameId, status] 23 24 table2: 25 [txhash, gameId, addr] 26 27 他们都独立的构造, 与更新 28 29 如果设置了两个表的: join, 比如: addr & status 要作为一个查询key, 那么我们需要维护一个: 30 31 join_table2_table1: 32 //table2 primary key 33 //table1 primary key 34 //addr_status 的一个关联index 35 [txhash, gameId, addr_status] 36 37 能够join的前提: 38 table2 包含 table1 的primary key 39 40 数据更新: 41 table1 数据更新 自动触发: join_table2_table1 更新 addr & status 42 table2 数据更新 也会自动触发: join_table2_table1 更新 addr & status 43 44 例子: 45 46 table1 更新了 gameId 对应 status -> 触发 join_table2_table1 所有对应 gameId 更新 addr & status 47 table2 更新了 txhash 对应的 addr -> 触发 join_table2_table1 所有对应的 txhash 对应的 addr & status 48 49 注意 join_table2_table1 是自动维护的 50 51 table2 中自动可以查询 addr & status 这个index 52 */ 53 54 //JoinTable 是由两个表格组合成的一个表格,自动维护一个联合结构 55 //其中主表: LeftTable 56 //连接表: RightTable 57 type JoinTable struct { 58 left *Table 59 right *Table 60 *Table 61 Fk string 62 leftIndex []string 63 rightIndex []string 64 } 65 66 //NewJoinTable 新建一个JoinTable 67 func NewJoinTable(left *Table, right *Table, indexes []string) (*JoinTable, error) { 68 if left.kvdb != right.kvdb { 69 return nil, errors.New("jointable: kvdb must same") 70 } 71 if _, ok := left.kvdb.(db.KVDB); !ok { 72 return nil, errors.New("jointable: kvdb must be db.KVDB") 73 } 74 if left.opt.Prefix != right.opt.Prefix { 75 return nil, errors.New("jointable: left and right table prefix must same") 76 } 77 fk := right.opt.Primary 78 if !left.canGet(fk) { 79 return nil, errors.New("jointable: left must has right primary index") 80 } 81 join := &JoinTable{left: left, right: right, Fk: fk} 82 for _, index := range indexes { 83 joinindex := strings.Split(index, joinsep) 84 if len(joinindex) != 2 { 85 return nil, errors.New("jointable: index config error") 86 } 87 if joinindex[0] != "" && !left.canGet(joinindex[0]) { 88 return nil, errors.New("jointable: left table can not get: " + joinindex[0]) 89 } 90 if joinindex[0] != "" { 91 join.leftIndex = append(join.leftIndex, joinindex[0]) 92 } 93 if joinindex[1] == "" || !right.canGet(joinindex[1]) { 94 return nil, errors.New("jointable: right table can not get: " + joinindex[1]) 95 } 96 if joinindex[1] != "" { 97 join.rightIndex = append(join.rightIndex, joinindex[1]) 98 } 99 } 100 opt := &Option{ 101 Join: true, 102 Prefix: left.opt.Prefix, 103 Name: left.opt.Name + joinsep + right.opt.Name, 104 Primary: left.opt.Primary, 105 Index: indexes, 106 } 107 mytable, err := NewTable(&JoinMeta{ 108 left: left.meta, 109 right: right.meta}, left.kvdb, opt) 110 if err != nil { 111 return nil, err 112 } 113 join.Table = mytable 114 return join, nil 115 } 116 117 //GetLeft get left table 118 func (join *JoinTable) GetLeft() *Table { 119 return join.left 120 } 121 122 //GetRight get right table 123 func (join *JoinTable) GetRight() *Table { 124 return join.right 125 } 126 127 //GetTable get table by name 128 func (join *JoinTable) GetTable(name string) (*Table, error) { 129 if join.left.opt.Name == name { 130 return join.left, nil 131 } 132 if join.right.opt.Name == name { 133 return join.right, nil 134 } 135 return nil, types.ErrNotFound 136 } 137 138 //MustGetTable if name not exist, panic 139 func (join *JoinTable) MustGetTable(name string) *Table { 140 table, err := join.GetTable(name) 141 if err != nil { 142 panic(err) 143 } 144 return table 145 } 146 147 //GetData rewrite get data of jointable 148 func (join *JoinTable) GetData(primaryKey []byte) (*Row, error) { 149 leftrow, err := join.left.GetData(primaryKey) 150 if err != nil { 151 return nil, err 152 } 153 rightprimary, err := join.left.index(leftrow, join.Fk) 154 if err != nil { 155 return nil, err 156 } 157 rightrow, err := join.right.GetData(rightprimary) 158 if err != nil { 159 return nil, err 160 } 161 rowjoin := join.meta.CreateRow() 162 rowjoin.Ty = None 163 rowjoin.Primary = leftrow.Primary 164 rowjoin.Data.(*JoinData).Left = leftrow.Data 165 rowjoin.Data.(*JoinData).Right = rightrow.Data 166 return rowjoin, nil 167 } 168 169 //ListIndex 查询jointable 数据 170 func (join *JoinTable) ListIndex(indexName string, prefix []byte, primaryKey []byte, count, direction int32) (rows []*Row, err error) { 171 if !strings.Contains(indexName, joinsep) || !join.canGet(indexName) { 172 return nil, errors.New("joinable query: indexName must be join index") 173 } 174 query := &Query{table: join, kvdb: join.left.kvdb.(db.KVDB)} 175 return query.ListIndex(indexName, prefix, primaryKey, count, direction) 176 } 177 178 //Save 重写默认的save 函数,不仅仅 Save left,right table 179 //还要save jointable 180 //没有update 到情况,只有del, add, 性能考虑可以加上 update 的情况 181 //目前update 是通过 del + add 完成 182 //left modify: del index, add new index (query right by primary) (check in cache) 183 //right modify: query all primary in left, include in cache, del index, add new index 184 //TODO: 没有修改过的数据不需要修改 185 func (join *JoinTable) Save() (kvs []*types.KeyValue, err error) { 186 for _, row := range join.left.rows { 187 if row.Ty == None { 188 continue 189 } 190 err := join.saveLeft(row) 191 if err != nil { 192 return nil, err 193 } 194 } 195 for _, row := range join.right.rows { 196 if row.Ty == None { 197 continue 198 } 199 err := join.saveRight(row) 200 if err != nil { 201 return nil, err 202 } 203 } 204 joinkvs, err := join.Table.Save() 205 if err != nil { 206 return nil, err 207 } 208 kvs = append(kvs, joinkvs...) 209 leftkvs, err := join.left.Save() 210 if err != nil { 211 return nil, err 212 } 213 kvs = append(kvs, leftkvs...) 214 rightkvs, err := join.right.Save() 215 if err != nil { 216 return nil, err 217 } 218 kvs = append(kvs, rightkvs...) 219 return util.DelDupKey(kvs), nil 220 } 221 222 func (join *JoinTable) isLeftModify(row *Row) bool { 223 oldrow := &Row{Data: row.old} 224 for _, index := range join.leftIndex { 225 _, _, ismodify, err := join.left.getModify(row, oldrow, index) 226 if ismodify { 227 return true 228 } 229 if err != nil { 230 tablelog.Error("isLeftModify", "err", err) 231 } 232 } 233 return false 234 } 235 236 func (join *JoinTable) isRightModify(row *Row) bool { 237 oldrow := &Row{Data: row.old} 238 for _, index := range join.rightIndex { 239 _, _, ismodify, err := join.right.getModify(row, oldrow, index) 240 if ismodify { 241 return true 242 } 243 if err != nil { 244 tablelog.Error("isLeftModify", "err", err) 245 } 246 } 247 return false 248 } 249 250 func (join *JoinTable) saveLeft(row *Row) error { 251 if row.Ty == Update && !join.isLeftModify(row) { 252 return nil 253 } 254 olddata := &JoinData{} 255 rowjoin := join.meta.CreateRow() 256 rowjoin.Ty = row.Ty 257 rowjoin.Primary = row.Primary 258 rowjoin.Data.(*JoinData).Left = row.Data 259 olddata.Left = row.old 260 rightprimary, err := join.left.index(row, join.Fk) 261 if err != nil { 262 return err 263 } 264 rightrow, incache, err := join.right.findRow(rightprimary) 265 if err != nil { 266 return err 267 } 268 if incache && rightrow.Ty == Update { 269 olddata.Right = rightrow.old 270 } else { 271 olddata.Right = rightrow.Data 272 } 273 //只考虑 left 有变化, 那么就修改(如果right 也修改了,在right中处理) 274 if row.Ty == Update { 275 rowjoin.old = olddata 276 } 277 rowjoin.Data.(*JoinData).Right = rightrow.Data 278 join.addRowCache(rowjoin) 279 return nil 280 } 281 282 func (join *JoinTable) saveRight(row *Row) error { 283 if row.Ty == Update && !join.isRightModify(row) { 284 return nil 285 } 286 indexName := join.right.opt.Primary 287 indexValue := row.Primary 288 q := join.left.GetQuery(join.left.kvdb.(db.KVDB)) 289 rows, err := q.ListIndex(indexName, indexValue, nil, 0, db.ListDESC) 290 if err != nil && err != types.ErrNotFound { 291 return err 292 } 293 rows, err = join.left.mergeCache(rows, indexName, indexValue) 294 if err != nil { 295 return err 296 } 297 for _, onerow := range rows { 298 olddata := &JoinData{Right: row.old, Left: onerow.Data} 299 if onerow.Ty == Update { 300 olddata.Left = onerow.old 301 } 302 rowjoin := join.meta.CreateRow() 303 rowjoin.Ty = row.Ty 304 rowjoin.Primary = onerow.Primary 305 if row.Ty == Update { 306 rowjoin.old = olddata 307 } 308 rowjoin.Data.(*JoinData).Right = row.Data 309 rowjoin.Data.(*JoinData).Left = onerow.Data 310 join.addRowCache(rowjoin) 311 } 312 return nil 313 } 314 315 //JoinData 由left 和 right 两个数据组成 316 type JoinData struct { 317 Left types.Message 318 Right types.Message 319 } 320 321 //Reset data 322 func (msg *JoinData) Reset() { 323 msg.Left.Reset() 324 msg.Right.Reset() 325 } 326 327 //ProtoMessage data 328 func (msg *JoinData) ProtoMessage() { 329 msg.Left.ProtoMessage() 330 msg.Right.ProtoMessage() 331 } 332 333 //String string 334 func (msg *JoinData) String() string { 335 return msg.Left.String() + msg.Right.String() 336 } 337 338 //JoinMeta left right 合成的一个meta 结构 339 type JoinMeta struct { 340 left RowMeta 341 right RowMeta 342 data *JoinData 343 } 344 345 //CreateRow create a meta struct 346 func (tx *JoinMeta) CreateRow() *Row { 347 return &Row{Data: &JoinData{}} 348 } 349 350 //SetPayload 设置数据 351 func (tx *JoinMeta) SetPayload(data types.Message) error { 352 if txdata, ok := data.(*JoinData); ok { 353 tx.data = txdata 354 if tx.data.Left != nil && tx.data.Right != nil { 355 err := tx.left.SetPayload(tx.data.Left) 356 if err != nil { 357 return err 358 } 359 err = tx.right.SetPayload(tx.data.Right) 360 if err != nil { 361 return err 362 } 363 } 364 return nil 365 } 366 return types.ErrTypeAsset 367 } 368 369 //Get 按照indexName 查询 indexValue 370 func (tx *JoinMeta) Get(key string) ([]byte, error) { 371 indexs := strings.Split(key, joinsep) 372 //获取primary 373 if len(indexs) <= 1 { 374 return tx.left.Get(key) 375 } 376 var leftvalue []byte 377 var err error 378 if indexs[0] != "" { 379 leftvalue, err = tx.left.Get(indexs[0]) 380 if err != nil { 381 return nil, err 382 } 383 } 384 rightvalue, err := tx.right.Get(indexs[1]) 385 if err != nil { 386 return nil, err 387 } 388 return JoinKey(leftvalue, rightvalue), nil 389 } 390 391 //JoinKey 两个left 和 right key 合并成一个key 392 func JoinKey(leftvalue, rightvalue []byte) []byte { 393 return types.Encode(&types.KeyValue{Key: leftvalue, Value: rightvalue}) 394 }