@@ -121,21 +121,36 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
121
121
result [table ] = lookup
122
122
}
123
123
}
124
- case * expression.In :
124
+ case * expression.In , * expression.NotIn :
125
+ c , ok := e .(expression.Comparer )
126
+ if ! ok {
127
+ return nil , nil
128
+ }
129
+
130
+ _ , negate := e .(* expression.NotIn )
131
+
125
132
// Take the index of a SOMETHING IN SOMETHING expression only if:
126
133
// the right branch is evaluable and the indexlookup supports set
127
134
// operations.
128
- if ! isEvaluable (e .Left ()) && isEvaluable (e .Right ()) {
129
- idx := a .Catalog .IndexByExpression (a .CurrentDatabase , e .Left ())
135
+ if ! isEvaluable (c .Left ()) && isEvaluable (c .Right ()) {
136
+ idx := a .Catalog .IndexByExpression (a .CurrentDatabase , c .Left ())
130
137
if idx != nil {
138
+ var nidx sql.NegateIndex
139
+ if negate {
140
+ nidx , ok = idx .(sql.NegateIndex )
141
+ if ! ok {
142
+ return nil , nil
143
+ }
144
+ }
145
+
131
146
// release the index if it was not used
132
147
defer func () {
133
148
if _ , ok := result [idx .Table ()]; ! ok {
134
149
a .Catalog .ReleaseIndex (idx )
135
150
}
136
151
}()
137
152
138
- value , err := e .Right ().Eval (sql .NewEmptyContext (), nil )
153
+ value , err := c .Right ().Eval (sql .NewEmptyContext (), nil )
139
154
if err != nil {
140
155
return nil , err
141
156
}
@@ -145,14 +160,30 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
145
160
return nil , errInvalidInRightEvaluation .New (value )
146
161
}
147
162
148
- lookup , err := idx .Get (values [0 ])
149
- if err != nil {
163
+ var lookup sql.IndexLookup
164
+ var errLookup error
165
+ if negate {
166
+ lookup , errLookup = nidx .Not (values [0 ])
167
+ } else {
168
+ lookup , errLookup = idx .Get (values [0 ])
169
+
170
+ }
171
+
172
+ if errLookup != nil {
150
173
return nil , err
151
174
}
152
175
153
176
for _ , v := range values [1 :] {
154
- lookup2 , err := idx .Get (v )
155
- if err != nil {
177
+ var lookup2 sql.IndexLookup
178
+ var errLookup error
179
+ if negate {
180
+ lookup2 , errLookup = nidx .Not (v )
181
+ } else {
182
+ lookup2 , errLookup = idx .Get (v )
183
+
184
+ }
185
+
186
+ if errLookup != nil {
156
187
return nil , err
157
188
}
158
189
@@ -161,7 +192,11 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
161
192
return result , nil
162
193
}
163
194
164
- lookup = lookup .(sql.SetOperations ).Union (lookup2 )
195
+ if negate {
196
+ lookup = lookup .(sql.SetOperations ).Intersection (lookup2 )
197
+ } else {
198
+ lookup = lookup .(sql.SetOperations ).Union (lookup2 )
199
+ }
165
200
}
166
201
167
202
result [idx .Table ()] = & indexLookup {
@@ -184,6 +219,15 @@ func getIndexes(e sql.Expression, a *Analyzer) (map[string]*indexLookup, error)
184
219
indexes : []sql.Index {idx },
185
220
lookup : lookup ,
186
221
}
222
+ case * expression.Not :
223
+ r , err := getNegatedIndexes (a , e )
224
+ if err != nil {
225
+ return nil , err
226
+ }
227
+
228
+ for table , indexLookup := range r {
229
+ result [table ] = indexLookup
230
+ }
187
231
case * expression.Between :
188
232
if ! isEvaluable (e .Val ) && isEvaluable (e .Upper ) && isEvaluable (e .Lower ) {
189
233
idx := a .Catalog .IndexByExpression (a .CurrentDatabase , e .Val )
@@ -351,6 +395,90 @@ func comparisonIndexLookup(
351
395
return nil , nil
352
396
}
353
397
398
+ func getNegatedIndexes (a * Analyzer , not * expression.Not ) (map [string ]* indexLookup , error ) {
399
+ switch e := not .Child .(type ) {
400
+ case * expression.Not :
401
+ return getIndexes (e .Child , a )
402
+ case * expression.Equals :
403
+ left , right := e .Left (), e .Right ()
404
+ // if the form is SOMETHING OP {INDEXABLE EXPR}, swap it, so it's {INDEXABLE EXPR} OP SOMETHING
405
+ if ! isEvaluable (right ) {
406
+ left , right = right , left
407
+ }
408
+
409
+ if isEvaluable (left ) || ! isEvaluable (right ) {
410
+ return nil , nil
411
+ }
412
+
413
+ idx := a .Catalog .IndexByExpression (a .CurrentDatabase , left )
414
+ if idx == nil {
415
+ return nil , nil
416
+ }
417
+
418
+ index , ok := idx .(sql.NegateIndex )
419
+ if ! ok {
420
+ return nil , nil
421
+ }
422
+
423
+ value , err := right .Eval (sql .NewEmptyContext (), nil )
424
+ if err != nil {
425
+ a .Catalog .ReleaseIndex (idx )
426
+ return nil , err
427
+ }
428
+
429
+ lookup , err := index .Not (value )
430
+ if err != nil || lookup == nil {
431
+ a .Catalog .ReleaseIndex (idx )
432
+ return nil , err
433
+ }
434
+
435
+ result := map [string ]* indexLookup {
436
+ idx .Table (): & indexLookup {
437
+ indexes : []sql.Index {idx },
438
+ lookup : lookup ,
439
+ },
440
+ }
441
+
442
+ return result , nil
443
+ case * expression.GreaterThan :
444
+ lte := expression .NewLessThanOrEqual (e .Left (), e .Right ())
445
+ return getIndexes (lte , a )
446
+ case * expression.GreaterThanOrEqual :
447
+ lt := expression .NewLessThan (e .Left (), e .Right ())
448
+ return getIndexes (lt , a )
449
+ case * expression.LessThan :
450
+ gte := expression .NewGreaterThanOrEqual (e .Left (), e .Right ())
451
+ return getIndexes (gte , a )
452
+ case * expression.LessThanOrEqual :
453
+ gt := expression .NewGreaterThan (e .Left (), e .Right ())
454
+ return getIndexes (gt , a )
455
+ case * expression.Between :
456
+ or := expression .NewOr (
457
+ expression .NewLessThan (e .Val , e .Lower ),
458
+ expression .NewGreaterThan (e .Val , e .Upper ),
459
+ )
460
+
461
+ return getIndexes (or , a )
462
+ case * expression.Or :
463
+ and := expression .NewAnd (
464
+ expression .NewNot (e .Left ),
465
+ expression .NewNot (e .Right ),
466
+ )
467
+
468
+ return getIndexes (and , a )
469
+ case * expression.And :
470
+ or := expression .NewOr (
471
+ expression .NewNot (e .Left ),
472
+ expression .NewNot (e .Right ),
473
+ )
474
+
475
+ return getIndexes (or , a )
476
+ default :
477
+ return nil , nil
478
+
479
+ }
480
+ }
481
+
354
482
func indexesIntersection (
355
483
a * Analyzer ,
356
484
left , right map [string ]* indexLookup ,
@@ -366,6 +494,7 @@ func indexesIntersection(
366
494
a .Catalog .ReleaseIndex (idx )
367
495
}
368
496
}
497
+
369
498
result [table ] = idx
370
499
}
371
500
@@ -538,46 +667,65 @@ func columnExprsByTable(exprs []sql.Expression) map[string][]columnExpr {
538
667
var result = make (map [string ][]columnExpr )
539
668
540
669
for _ , expr := range exprs {
541
- var left , right sql.Expression
542
- switch e := expr .(type ) {
543
- case * expression.Equals ,
544
- * expression.GreaterThan ,
545
- * expression.LessThan ,
546
- * expression.GreaterThanOrEqual ,
547
- * expression.LessThanOrEqual :
548
- cmp := e .(expression.Comparer )
549
- left , right = cmp .Left (), cmp .Right ()
550
- if ! isEvaluable (right ) {
551
- left , right = right , left
552
- }
670
+ table , colExpr := extractColumnExpr (expr )
671
+ if colExpr == nil {
672
+ continue
673
+ }
553
674
554
- if ! isEvaluable (right ) {
555
- continue
556
- }
675
+ result [table ] = append (result [table ], * colExpr )
676
+ }
557
677
558
- col , ok := left .(* expression.GetField )
559
- if ! ok {
560
- continue
561
- }
678
+ return result
679
+ }
562
680
563
- result [col .Table ()] = append (result [col .Table ()], columnExpr {col , right , e })
564
- case * expression.Between :
565
- if ! isEvaluable (e .Upper ) || ! isEvaluable (e .Lower ) || isEvaluable (e .Val ) {
566
- continue
681
+ func extractColumnExpr (e sql.Expression ) (string , * columnExpr ) {
682
+ switch e := e .(type ) {
683
+ case * expression.Not :
684
+ table , colExpr := extractColumnExpr (e .Child )
685
+ if colExpr != nil {
686
+ colExpr = & columnExpr {
687
+ col : colExpr .col ,
688
+ val : colExpr .val ,
689
+ expr : expression .NewNot (colExpr .expr ),
567
690
}
691
+ }
568
692
569
- col , ok := e .Val .(* expression.GetField )
570
- if ! ok {
571
- continue
572
- }
693
+ return table , colExpr
694
+ case * expression.Equals ,
695
+ * expression.GreaterThan ,
696
+ * expression.LessThan ,
697
+ * expression.GreaterThanOrEqual ,
698
+ * expression.LessThanOrEqual :
699
+ cmp := e .(expression.Comparer )
700
+ left , right := cmp .Left (), cmp .Right ()
701
+ if ! isEvaluable (right ) {
702
+ left , right = right , left
703
+ }
573
704
574
- result [col .Table ()] = append (result [col .Table ()], columnExpr {col , nil , e })
575
- default :
576
- continue
705
+ if ! isEvaluable (right ) {
706
+ return "" , nil
577
707
}
578
- }
579
708
580
- return result
709
+ col , ok := left .(* expression.GetField )
710
+ if ! ok {
711
+ return "" , nil
712
+ }
713
+
714
+ return col .Table (), & columnExpr {col , right , e }
715
+ case * expression.Between :
716
+ if ! isEvaluable (e .Upper ) || ! isEvaluable (e .Lower ) || isEvaluable (e .Val ) {
717
+ return "" , nil
718
+ }
719
+
720
+ col , ok := e .Val .(* expression.GetField )
721
+ if ! ok {
722
+ return "" , nil
723
+ }
724
+
725
+ return col .Table (), & columnExpr {col , nil , e }
726
+ default :
727
+ return "" , nil
728
+ }
581
729
}
582
730
583
731
func containsColumns (e sql.Expression ) bool {
0 commit comments