Skip to content

Commit e40b1ed

Browse files
author
James Cor
committed
unique IN values
1 parent f6c4ebd commit e40b1ed

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

sql/analyzer/costed_index_scan.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,18 @@ func (b *indexScanRangeBuilder) buildRangeCollection(f indexFilter) (sql.MySQLRa
839839
case *iScanOr:
840840
ranges, err = b.rangeBuildOr(f, inScan)
841841
case *iScanLeaf:
842+
// TODO: special case for in set. can skip overlapping ranges since it's a series of equality checks
843+
// TODO: sequential integers can be converted to a single partition, but i guess that's harder?
844+
if f.Op() == sql.IndexScanOpInSet {
845+
bb := sql.NewMySQLIndexBuilder(b.idx)
846+
b.rangeBuildDefaultLeaf(bb, f, inScan)
847+
if _, err := bb.Build(b.ctx); err != nil {
848+
return nil, err
849+
}
850+
ranges = bb.Ranges(b.ctx)
851+
return ranges, nil
852+
}
853+
842854
ranges, err = b.rangeBuildLeaf(f, inScan)
843855
default:
844856
return nil, fmt.Errorf("unknown indexFilter type: %T", f)
@@ -1429,14 +1441,18 @@ func newLeaf(ctx *sql.Context, id indexScanId, e sql.Expression, underlying stri
14291441

14301442
if op == sql.IndexScanOpInSet || op == sql.IndexScanOpNotInSet {
14311443
tup := right.(expression.Tuple)
1432-
var litSet []interface{}
1444+
litSet := make(map[any]struct{}, len(tup))
1445+
setVals := make([]any, 0, len(tup))
14331446
var litType sql.Type
14341447
for _, lit := range tup {
14351448
value, err := lit.Eval(ctx, nil)
14361449
if err != nil {
14371450
return nil, false
14381451
}
1439-
litSet = append(litSet, value)
1452+
if _, ok = litSet[value]; !ok {
1453+
litSet[value] = struct{}{}
1454+
setVals = append(setVals, value)
1455+
}
14401456
if litType == nil {
14411457
litType = lit.Type()
14421458
}
@@ -1445,7 +1461,7 @@ func newLeaf(ctx *sql.Context, id indexScanId, e sql.Expression, underlying stri
14451461
id: id,
14461462
gf: gf,
14471463
op: op,
1448-
setValues: litSet,
1464+
setValues: setVals,
14491465
litType: litType,
14501466
underlying: underlying,
14511467
}, true

sql/index_builder.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,17 @@ type MySQLIndexBuilder struct {
4242
// NewMySQLIndexBuilder returns a new MySQLIndexBuilder. Used internally to construct a range that will later be passed to
4343
// integrators through the Index function NewLookup.
4444
func NewMySQLIndexBuilder(idx Index) *MySQLIndexBuilder {
45-
colExprTypes := make(map[string]Type)
46-
ranges := make(map[string][]MySQLRangeColumnExpr)
47-
for _, cet := range idx.ColumnExpressionTypes() {
45+
cets := idx.ColumnExpressionTypes()
46+
colExprTypes := make(map[string]Type, len(cets))
47+
ranges := make(map[string][]MySQLRangeColumnExpr, len(cets))
48+
for _, cet := range cets {
4849
typ := cet.Type
4950
if _, ok := typ.(StringType); ok {
5051
typ = typ.Promote()
5152
}
52-
colExprTypes[strings.ToLower(cet.Expression)] = typ
53-
ranges[strings.ToLower(cet.Expression)] = []MySQLRangeColumnExpr{AllRangeColumnExpr(typ)}
53+
expr := strings.ToLower(cet.Expression)
54+
colExprTypes[expr] = typ
55+
ranges[expr] = []MySQLRangeColumnExpr{AllRangeColumnExpr(typ)}
5456
}
5557
return &MySQLIndexBuilder{
5658
idx: idx,
@@ -493,7 +495,6 @@ func (b *MySQLIndexBuilder) updateCol(ctx *Context, colExpr string, potentialRan
493495
var newRanges []MySQLRangeColumnExpr
494496
for _, currentRange := range currentRanges {
495497
for _, potentialRange := range potentialRanges {
496-
497498
newRange, ok, err := currentRange.TryIntersect(potentialRange)
498499
if err != nil {
499500
b.isInvalid = true

0 commit comments

Comments
 (0)