Skip to content

Commit ee7f231

Browse files
committed
Unwrap wrapped values before computing their hash.
1 parent d41f701 commit ee7f231

17 files changed

+71
-30
lines changed

enginetest/enginetests.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -3046,7 +3046,7 @@ func TestRenameColumn(t *testing.T, harness Harness) {
30463046
TestQueryWithContext(t, ctx, e, harness, "ALTER TABLE mydb.tabletest RENAME COLUMN s TO i1", []sql.Row{{types.NewOkResult(0)}}, nil, nil, nil)
30473047
TestQueryWithContext(t, ctx, e, harness, "SHOW FULL COLUMNS FROM mydb.tabletest", []sql.Row{
30483048
{"i", "int", nil, "NO", "PRI", nil, "", "", ""},
3049-
{"i1", "varchar(20)", "utf8mb4_0900_bin", "NO", "", nil, "", "", ""},
3049+
{"i1", "text", "utf8mb4_0900_bin", "NO", "", nil, "", "", ""},
30503050
}, nil, nil, nil)
30513051
})
30523052
}

enginetest/join_planning_tests.go

+21
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,27 @@ where u in (select * from rec);`,
945945
},
946946
},
947947
},
948+
{
949+
name: "join varchar and text columns",
950+
setup: []string{
951+
"CREATE table varchartable (pk int primary key, s varchar(20));",
952+
"CREATE table texttable (pk int primary key, t text);",
953+
"insert into varchartable values (1,'first'), (2,'second'), (3,'third');",
954+
"insert into texttable values (1,'first'), (2,'second'), (3,'third');",
955+
},
956+
// write a bunch of left joins and make sure they are converted to anti joins
957+
tests: []JoinPlanTest{
958+
{
959+
q: "select /*+ HASH_JOIN(varchartable,texttable) */ * from varchartable where s not in (select t from texttable) order by pk",
960+
types: []plan.JoinType{plan.JoinTypeLeftOuterHashExcludeNulls},
961+
exp: []sql.Row{
962+
{1, "first"},
963+
{2, "second"},
964+
{3, "third"},
965+
},
966+
},
967+
},
968+
},
948969
{
949970
name: "join concat tests",
950971
setup: []string{

enginetest/queries/queries.go

+12
Original file line numberDiff line numberDiff line change
@@ -5665,6 +5665,18 @@ SELECT * FROM cte WHERE d = 2;`,
56655665
{"third row"},
56665666
},
56675667
},
5668+
{
5669+
Query: "select * from mytable intersect select * from tabletest",
5670+
Expected: []sql.Row{{1, "first row"}, {2, "second row"}, {3, "third row"}},
5671+
},
5672+
{
5673+
Query: "select * from mytable union distinct select * from tabletest",
5674+
Expected: []sql.Row{{1, "first row"}, {2, "second row"}, {3, "third row"}},
5675+
},
5676+
{
5677+
Query: "select * from mytable except select * from tabletest",
5678+
Expected: []sql.Row{},
5679+
},
56685680
{
56695681
SkipPrepared: true,
56705682
Query: "",

enginetest/scriptgen/setup/scripts/tabletest

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
exec
22
create table tabletest (
33
i int primary key,
4-
s varchar(20) not null
4+
s text not null
55
)
66
----
77

enginetest/scriptgen/setup/setup_data.sg.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

memory/table.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -1971,7 +1971,7 @@ func (t *Table) DropCheck(ctx *sql.Context, chName string) error {
19711971
return fmt.Errorf("check '%s' was not found on the table", chName)
19721972
}
19731973

1974-
func (t *Table) createIndex(data *TableData, name string, columns []sql.IndexColumn, constraint sql.IndexConstraint, comment string) (sql.Index, error) {
1974+
func (t *Table) createIndex(ctx *sql.Context, data *TableData, name string, columns []sql.IndexColumn, constraint sql.IndexConstraint, comment string) (sql.Index, error) {
19751975
if name == "" {
19761976
for _, column := range columns {
19771977
name += column.Name + "_"
@@ -2005,7 +2005,7 @@ func (t *Table) createIndex(data *TableData, name string, columns []sql.IndexCol
20052005
}
20062006

20072007
if constraint == sql.IndexConstraint_Unique {
2008-
err := data.errIfDuplicateEntryExist(colNames, name)
2008+
err := data.errIfDuplicateEntryExist(ctx, colNames, name)
20092009
if err != nil {
20102010
return nil, err
20112011
}
@@ -2041,7 +2041,7 @@ func (t *Table) CreateIndex(ctx *sql.Context, idx sql.IndexDef) error {
20412041
data.indexes = make(map[string]sql.Index)
20422042
}
20432043

2044-
index, err := t.createIndex(data, idx.Name, idx.Columns, idx.Constraint, idx.Comment)
2044+
index, err := t.createIndex(ctx, data, idx.Name, idx.Columns, idx.Constraint, idx.Comment)
20452045
if err != nil {
20462046
return err
20472047
}
@@ -2107,7 +2107,7 @@ func (t *Table) CreateFulltextIndex(ctx *sql.Context, indexDef sql.IndexDef, key
21072107
data.indexes = make(map[string]sql.Index)
21082108
}
21092109

2110-
index, err := t.createIndex(data, indexDef.Name, indexDef.Columns, indexDef.Constraint, indexDef.Comment)
2110+
index, err := t.createIndex(ctx, data, indexDef.Name, indexDef.Columns, indexDef.Constraint, indexDef.Comment)
21112111
if err != nil {
21122112
return err
21132113
}
@@ -2138,7 +2138,7 @@ func (t *Table) CreateVectorIndex(ctx *sql.Context, idx sql.IndexDef, distanceTy
21382138
data.indexes = make(map[string]sql.Index)
21392139
}
21402140

2141-
index, err := t.createIndex(data, idx.Name, idx.Columns, idx.Constraint, idx.Comment)
2141+
index, err := t.createIndex(ctx, data, idx.Name, idx.Columns, idx.Constraint, idx.Comment)
21422142
if err != nil {
21432143
return err
21442144
}

memory/table_data.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package memory
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"sort"
2021
"strconv"
@@ -274,7 +275,7 @@ func (td *TableData) numRows(ctx *sql.Context) (uint64, error) {
274275
}
275276

276277
// throws an error if any two or more rows share the same |cols| values.
277-
func (td *TableData) errIfDuplicateEntryExist(cols []string, idxName string) error {
278+
func (td *TableData) errIfDuplicateEntryExist(ctx context.Context, cols []string, idxName string) error {
278279
columnMapping, err := td.columnIndexes(cols)
279280

280281
// We currently skip validating duplicates on unique virtual columns.
@@ -296,7 +297,7 @@ func (td *TableData) errIfDuplicateEntryExist(cols []string, idxName string) err
296297
if hasNulls(idxPrefixKey) {
297298
continue
298299
}
299-
h, err := sql.HashOf(idxPrefixKey)
300+
h, err := sql.HashOf(ctx, idxPrefixKey)
300301
if err != nil {
301302
return err
302303
}

sql/cache.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package sql
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"runtime"
2021
"sync"
@@ -25,7 +26,7 @@ import (
2526
)
2627

2728
// HashOf returns a hash of the given value to be used as key in a cache.
28-
func HashOf(v Row) (uint64, error) {
29+
func HashOf(ctx context.Context, v Row) (uint64, error) {
2930
hash := digestPool.Get().(*xxhash.Digest)
3031
hash.Reset()
3132
defer digestPool.Put(hash)
@@ -36,7 +37,10 @@ func HashOf(v Row) (uint64, error) {
3637
return 0, err
3738
}
3839
}
39-
40+
x, err := UnwrapAny(ctx, x)
41+
if err != nil {
42+
return 0, err
43+
}
4044
// TODO: probably much faster to do this with a type switch
4145
// TODO: we don't have the type info necessary to appropriately encode the value of a string with a non-standard
4246
// collation, which means that two strings that differ only in their collations will hash to the same value.

sql/cache_test.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package sql
1616

1717
import (
18+
"context"
1819
"errors"
1920
"testing"
2021

@@ -179,10 +180,11 @@ func TestRowsCache(t *testing.T) {
179180
}
180181

181182
func BenchmarkHashOf(b *testing.B) {
183+
ctx := context.Background()
182184
row := NewRow(1, "1")
183185
b.ResetTimer()
184186
for i := 0; i < b.N; i++ {
185-
sum, err := HashOf(row)
187+
sum, err := HashOf(ctx, row)
186188
if err != nil {
187189
b.Fatal(err)
188190
}
@@ -193,11 +195,12 @@ func BenchmarkHashOf(b *testing.B) {
193195
}
194196

195197
func BenchmarkParallelHashOf(b *testing.B) {
198+
ctx := context.Background()
196199
row := NewRow(1, "1")
197200
b.ResetTimer()
198201
b.RunParallel(func(pb *testing.PB) {
199202
for pb.Next() {
200-
sum, err := HashOf(row)
203+
sum, err := HashOf(ctx, row)
201204
if err != nil {
202205
b.Fatal(err)
203206
}

sql/iters/rel_iters.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ func (di *distinctIter) Next(ctx *sql.Context) (sql.Row, error) {
571571
return nil, err
572572
}
573573

574-
hash, err := sql.HashOf(row)
574+
hash, err := sql.HashOf(ctx, row)
575575
if err != nil {
576576
return nil, err
577577
}
@@ -647,7 +647,7 @@ func (ii *IntersectIter) Next(ctx *sql.Context) (sql.Row, error) {
647647
return nil, err
648648
}
649649

650-
hash, herr := sql.HashOf(res)
650+
hash, herr := sql.HashOf(ctx, res)
651651
if herr != nil {
652652
return nil, herr
653653
}
@@ -669,7 +669,7 @@ func (ii *IntersectIter) Next(ctx *sql.Context) (sql.Row, error) {
669669
return nil, err
670670
}
671671

672-
hash, herr := sql.HashOf(res)
672+
hash, herr := sql.HashOf(ctx, res)
673673
if herr != nil {
674674
return nil, herr
675675
}
@@ -714,7 +714,7 @@ func (ei *ExceptIter) Next(ctx *sql.Context) (sql.Row, error) {
714714
return nil, err
715715
}
716716

717-
hash, herr := sql.HashOf(res)
717+
hash, herr := sql.HashOf(ctx, res)
718718
if herr != nil {
719719
return nil, herr
720720
}
@@ -736,7 +736,7 @@ func (ei *ExceptIter) Next(ctx *sql.Context) (sql.Row, error) {
736736
return nil, err
737737
}
738738

739-
hash, herr := sql.HashOf(res)
739+
hash, herr := sql.HashOf(ctx, res)
740740
if herr != nil {
741741
return nil, herr
742742
}

sql/plan/hash_lookup.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ func (n *HashLookup) GetHashKey(ctx *sql.Context, e sql.Expression, row sql.Row)
127127
return nil, err
128128
}
129129
if s, ok := key.([]interface{}); ok {
130-
return sql.HashOf(s)
130+
return sql.HashOf(ctx, s)
131131
}
132132
// byte slices are not hashable
133133
if k, ok := key.([]byte); ok {

sql/plan/insubquery.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func NewInSubquery(left sql.Expression, right sql.Expression) *InSubquery {
4747
return &InSubquery{expression.BinaryExpressionStub{LeftChild: left, RightChild: right}}
4848
}
4949

50-
var nilKey, _ = sql.HashOf(sql.NewRow(nil))
50+
var nilKey, _ = sql.HashOf(nil, sql.NewRow(nil))
5151

5252
// Eval implements the Expression interface.
5353
func (in *InSubquery) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
@@ -96,7 +96,7 @@ func (in *InSubquery) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
9696
return false, nil
9797
}
9898

99-
key, err := sql.HashOf(sql.NewRow(nLeft))
99+
key, err := sql.HashOf(ctx, sql.NewRow(nLeft))
100100
if err != nil {
101101
return nil, err
102102
}

sql/plan/subquery.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ func putAllRows(ctx *sql.Context, cache sql.KeyValueCache, vals []interface{}) e
477477
if err != nil {
478478
return err
479479
}
480-
rowKey, err := sql.HashOf(sql.NewRow(val))
480+
rowKey, err := sql.HashOf(ctx, sql.NewRow(val))
481481
if err != nil {
482482
return err
483483
}

sql/rowexec/join_iters.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ func (i *fullJoinIter) Next(ctx *sql.Context) (sql.Row, error) {
462462

463463
rightRow, err := i.r.Next(ctx)
464464
if err == io.EOF {
465-
key, err := sql.HashOf(i.leftRow)
465+
key, err := sql.HashOf(ctx, i.leftRow)
466466
if err != nil {
467467
return nil, err
468468
}
@@ -485,12 +485,12 @@ func (i *fullJoinIter) Next(ctx *sql.Context) (sql.Row, error) {
485485
if !sql.IsTrue(matches) {
486486
continue
487487
}
488-
rkey, err := sql.HashOf(rightRow)
488+
rkey, err := sql.HashOf(ctx, rightRow)
489489
if err != nil {
490490
return nil, err
491491
}
492492
i.seenRight[rkey] = struct{}{}
493-
lKey, err := sql.HashOf(i.leftRow)
493+
lKey, err := sql.HashOf(ctx, i.leftRow)
494494
if err != nil {
495495
return nil, err
496496
}
@@ -517,7 +517,7 @@ func (i *fullJoinIter) Next(ctx *sql.Context) (sql.Row, error) {
517517
return nil, io.EOF
518518
}
519519

520-
key, err := sql.HashOf(rightRow)
520+
key, err := sql.HashOf(ctx, rightRow)
521521
if err != nil {
522522
return nil, err
523523
}

sql/rowexec/other_iters.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ func (ci *concatIter) Next(ctx *sql.Context) (sql.Row, error) {
334334
if err != nil {
335335
return nil, err
336336
}
337-
hash, err := sql.HashOf(res)
337+
hash, err := sql.HashOf(ctx, res)
338338
if err != nil {
339339
return nil, err
340340
}

sql/rowexec/rel_iters.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ func (r *recursiveCteIter) Next(ctx *sql.Context) (sql.Row, error) {
446446

447447
var key uint64
448448
if r.deduplicate {
449-
key, _ = sql.HashOf(row)
449+
key, _ = sql.HashOf(ctx, row)
450450
if k, _ := r.cache.Get(key); k != nil {
451451
// skip duplicate
452452
continue

sql/rowexec/update.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func (u *updateJoinIter) Next(ctx *sql.Context) (sql.Row, error) {
248248

249249
// Determine whether this row in the table has already been updated
250250
cache := u.getOrCreateCache(ctx, tableName)
251-
hash, err := sql.HashOf(oldTableRow)
251+
hash, err := sql.HashOf(ctx, oldTableRow)
252252
if err != nil {
253253
return nil, err
254254
}

0 commit comments

Comments
 (0)