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  }