Skip to content

Commit 0270726

Browse files
authored
Fix schema for call to hash.HashOf() in HashLookups (#3038)
1 parent 7d22a78 commit 0270726

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

enginetest/queries/join_queries.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,6 +1161,45 @@ var JoinScriptTests = []ScriptTest{
11611161
},
11621162
},
11631163
},
1164+
{
1165+
// After this change: https://github.com/dolthub/go-mysql-server/pull/3038
1166+
// hash.HashOf takes in a sql.Schema to convert and hash keys, so
1167+
// we need to pass in the schema of the join key.
1168+
// This tests a bug introduced in that same PR where we incorrectly pass in the entire schema,
1169+
// resulting in incorrect conversions.
1170+
Name: "HashLookup on multiple columns with tables with different schemas",
1171+
SetUpScript: []string{
1172+
"create table t1 (i int primary key, k int);",
1173+
"create table t2 (i int primary key, j varchar(1), k int);",
1174+
"insert into t1 values (111111, 111111);",
1175+
"insert into t2 values (111111, 'a', 111111);",
1176+
},
1177+
Assertions: []ScriptTestAssertion{
1178+
{
1179+
Query: "select /*+ HASH_JOIN(t1, t2) */ * from t1 join t2 on t1.i = t2.i and t1.k = t2.k;",
1180+
Expected: []sql.Row{
1181+
{111111, 111111, 111111, "a", 111111},
1182+
},
1183+
},
1184+
},
1185+
},
1186+
{
1187+
Name: "HashLookup on multiple columns with collations",
1188+
SetUpScript: []string{
1189+
"create table t1 (i int primary key, j varchar(128) collate utf8mb4_0900_ai_ci);",
1190+
"create table t2 (i int primary key, j varchar(128) collate utf8mb4_0900_ai_ci);",
1191+
"insert into t1 values (1, 'ABCDE');",
1192+
"insert into t2 values (1, 'abcde');",
1193+
},
1194+
Assertions: []ScriptTestAssertion{
1195+
{
1196+
Query: "select /*+ HASH_JOIN(t1, t2) */ * from t1 join t2 on t1.i = t2.i and t1.j = t2.j;",
1197+
Expected: []sql.Row{
1198+
{1, "ABCDE", 1, "abcde"},
1199+
},
1200+
},
1201+
},
1202+
},
11641203
}
11651204

11661205
var LateralJoinScriptTests = []ScriptTest{

sql/hash/hash.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ var digestPool = sync.Pool{
3030
},
3131
}
3232

33+
// ExprsToSchema converts a list of sql.Expression to a sql.Schema.
34+
// This is used for functions that use HashOf, but don't already have a schema.
35+
// The generated schema ONLY contains the types of the expressions without any column names or any other info.
36+
func ExprsToSchema(exprs ...sql.Expression) sql.Schema {
37+
var sch sql.Schema
38+
for _, expr := range exprs {
39+
sch = append(sch, &sql.Column{Type: expr.Type()})
40+
}
41+
return sch
42+
}
43+
3344
// HashOf returns a hash of the given value to be used as key in a cache.
3445
func HashOf(ctx *sql.Context, sch sql.Schema, row sql.Row) (uint64, error) {
3546
hash := digestPool.Get().(*xxhash.Digest)

sql/plan/hash_lookup.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ import (
3333
// on the projected results. If cached results are not available, it
3434
// simply delegates to the child.
3535
func NewHashLookup(n sql.Node, rightEntryKey sql.Expression, leftProbeKey sql.Expression, joinType JoinType) *HashLookup {
36+
leftKeySch := hash.ExprsToSchema(leftProbeKey)
3637
return &HashLookup{
3738
UnaryNode: UnaryNode{n},
3839
RightEntryKey: rightEntryKey,
3940
LeftProbeKey: leftProbeKey,
4041
Mutex: new(sync.Mutex),
4142
JoinType: joinType,
43+
leftKeySch: leftKeySch,
4244
}
4345
}
4446

@@ -49,6 +51,7 @@ type HashLookup struct {
4951
Mutex *sync.Mutex
5052
Lookup *map[interface{}][]sql.Row
5153
JoinType JoinType
54+
leftKeySch sql.Schema
5255
}
5356

5457
var _ sql.Node = (*HashLookup)(nil)
@@ -70,6 +73,7 @@ func (n *HashLookup) WithExpressions(exprs ...sql.Expression) (sql.Node, error)
7073
ret := *n
7174
ret.RightEntryKey = exprs[0]
7275
ret.LeftProbeKey = exprs[1]
76+
ret.leftKeySch = hash.ExprsToSchema(ret.LeftProbeKey)
7377
return &ret, nil
7478
}
7579

@@ -127,7 +131,7 @@ func (n *HashLookup) GetHashKey(ctx *sql.Context, e sql.Expression, row sql.Row)
127131
return nil, err
128132
}
129133
if s, ok := key.([]interface{}); ok {
130-
return hash.HashOf(ctx, n.Schema(), s)
134+
return hash.HashOf(ctx, n.leftKeySch, s)
131135
}
132136
// byte slices are not hashable
133137
if k, ok := key.([]byte); ok {

0 commit comments

Comments
 (0)