Skip to content

Commit

Permalink
executor: fix building hash table with TypeNull when join (#15913)
Browse files Browse the repository at this point in the history
  • Loading branch information
SunRunAway authored Apr 1, 2020
1 parent 5a2f7da commit dec9371
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 21 deletions.
16 changes: 16 additions & 0 deletions executor/join_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,22 @@ func (s *testSuiteJoin1) TestIssue5278(c *C) {
tk.MustQuery("select * from t left join tt on t.a=tt.a left join t ttt on t.a=ttt.a").Check(testkit.Rows("1 1 <nil> <nil> 1 1"))
}

func (s *testSuiteJoin1) TestIssue15850JoinNullValue(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustQuery("SELECT * FROM (select null) v NATURAL LEFT JOIN (select null) v1;").Check(testkit.Rows("<nil>"))
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0))

tk.MustExec("drop table if exists t0;")
tk.MustExec("drop view if exists v0;")
tk.MustExec("CREATE TABLE t0(c0 TEXT);")
tk.MustExec("CREATE VIEW v0(c0) AS SELECT NULL;")
tk.MustQuery("SELECT /*+ HASH_JOIN(v0) */ * FROM v0 NATURAL LEFT JOIN t0;").Check(testkit.Rows("<nil>"))
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0))
tk.MustQuery("SELECT /*+ MERGE_JOIN(v0) */ * FROM v0 NATURAL LEFT JOIN t0;").Check(testkit.Rows("<nil>"))
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0))
}

func (s *testSuiteJoin1) TestIndexLookupJoin(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down
9 changes: 9 additions & 0 deletions util/codec/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,15 @@ func HashChunkSelected(sc *stmtctx.StatementContext, h []hash.Hash64, chk *chunk
_, _ = h[i].Write(buf)
_, _ = h[i].Write(b)
}
case mysql.TypeNull:
for i := 0; i < rows; i++ {
if sel != nil && !sel[i] {
continue
}
isNull[i] = true
buf[0] = NilFlag
_, _ = h[i].Write(buf)
}
default:
return errors.Errorf("unsupport column type for encode %d", tp.Tp)
}
Expand Down
47 changes: 26 additions & 21 deletions util/codec/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@ func datumsForTest(sc *stmtctx.StatementContext) ([]types.Datum, []*types.FieldT
value interface{}
tp *types.FieldType
}{
{nil, types.NewFieldType(mysql.TypeNull)},
{nil, types.NewFieldType(mysql.TypeLonglong)},
{int64(1), types.NewFieldType(mysql.TypeTiny)},
{int64(1), types.NewFieldType(mysql.TypeShort)},
Expand Down Expand Up @@ -1103,6 +1104,7 @@ func (s *testCodecSuite) TestHashChunkRow(c *C) {
c.Assert(err, IsNil)
c.Assert(e, IsTrue)

testHashChunkRowEqual(c, nil, nil, true)
testHashChunkRowEqual(c, uint64(1), int64(1), true)
testHashChunkRowEqual(c, uint64(18446744073709551615), int64(-1), false)

Expand Down Expand Up @@ -1174,35 +1176,38 @@ func (s *testCodecSuite) TestHashChunkColumns(c *C) {
vecHash := []hash.Hash64{fnv.New64(), fnv.New64(), fnv.New64()}
rowHash := []hash.Hash64{fnv.New64(), fnv.New64(), fnv.New64()}

// Test hash value of the first `Null` column
c.Assert(chk.GetRow(0).IsNull(0), Equals, true)
err1 := HashChunkColumns(sc, vecHash, chk, tps[0], 0, buf, hasNull)
err2 := HashChunkRow(sc, rowHash[0], chk.GetRow(0), tps, colIdx[0:1], buf)
err3 := HashChunkRow(sc, rowHash[1], chk.GetRow(1), tps, colIdx[0:1], buf)
err4 := HashChunkRow(sc, rowHash[2], chk.GetRow(2), tps, colIdx[0:1], buf)
c.Assert(err1, IsNil)
c.Assert(err2, IsNil)
c.Assert(err3, IsNil)
c.Assert(err4, IsNil)
// Test hash value of the first two `Null` columns
for i := 0; i < 2; i++ {
c.Assert(chk.GetRow(0).IsNull(i), Equals, true)
err1 := HashChunkColumns(sc, vecHash, chk, tps[i], i, buf, hasNull)
err2 := HashChunkRow(sc, rowHash[0], chk.GetRow(0), tps, colIdx[i:i+1], buf)
err3 := HashChunkRow(sc, rowHash[1], chk.GetRow(1), tps, colIdx[i:i+1], buf)
err4 := HashChunkRow(sc, rowHash[2], chk.GetRow(2), tps, colIdx[i:i+1], buf)
c.Assert(err1, IsNil)
c.Assert(err2, IsNil)
c.Assert(err3, IsNil)
c.Assert(err4, IsNil)

c.Assert(hasNull[0], Equals, true)
c.Assert(hasNull[1], Equals, true)
c.Assert(hasNull[2], Equals, true)
c.Assert(vecHash[0].Sum64(), Equals, rowHash[0].Sum64())
c.Assert(vecHash[1].Sum64(), Equals, rowHash[1].Sum64())
c.Assert(vecHash[2].Sum64(), Equals, rowHash[2].Sum64())
c.Assert(hasNull[0], Equals, true)
c.Assert(hasNull[1], Equals, true)
c.Assert(hasNull[2], Equals, true)
c.Assert(vecHash[0].Sum64(), Equals, rowHash[0].Sum64())
c.Assert(vecHash[1].Sum64(), Equals, rowHash[1].Sum64())
c.Assert(vecHash[2].Sum64(), Equals, rowHash[2].Sum64())

}

// Test hash value of every single column that is not `Null`
for i := 1; i < len(tps); i++ {
for i := 2; i < len(tps); i++ {
hasNull = []bool{false, false, false}
vecHash = []hash.Hash64{fnv.New64(), fnv.New64(), fnv.New64()}
rowHash = []hash.Hash64{fnv.New64(), fnv.New64(), fnv.New64()}

c.Assert(chk.GetRow(0).IsNull(i), Equals, false)
err1 = HashChunkColumns(sc, vecHash, chk, tps[i], i, buf, hasNull)
err2 = HashChunkRow(sc, rowHash[0], chk.GetRow(0), tps, colIdx[i:i+1], buf)
err3 = HashChunkRow(sc, rowHash[1], chk.GetRow(1), tps, colIdx[i:i+1], buf)
err4 = HashChunkRow(sc, rowHash[2], chk.GetRow(2), tps, colIdx[i:i+1], buf)
err1 := HashChunkColumns(sc, vecHash, chk, tps[i], i, buf, hasNull)
err2 := HashChunkRow(sc, rowHash[0], chk.GetRow(0), tps, colIdx[i:i+1], buf)
err3 := HashChunkRow(sc, rowHash[1], chk.GetRow(1), tps, colIdx[i:i+1], buf)
err4 := HashChunkRow(sc, rowHash[2], chk.GetRow(2), tps, colIdx[i:i+1], buf)
c.Assert(err1, IsNil)
c.Assert(err2, IsNil)
c.Assert(err3, IsNil)
Expand Down

0 comments on commit dec9371

Please sign in to comment.