Skip to content

Commit

Permalink
ranger: rerange file and rename some method. (pingcap#5028)
Browse files Browse the repository at this point in the history
  • Loading branch information
winoros authored and coocood committed Nov 7, 2017
1 parent 54a1e0e commit 5922b74
Show file tree
Hide file tree
Showing 6 changed files with 564 additions and 542 deletions.
45 changes: 44 additions & 1 deletion plan/physical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ func (is *PhysicalIndexScan) addPushedDownSelection(copTask *copTask, p *DataSou
if len(is.filterCondition) > 0 {
var indexConds, tableConds []expression.Expression
if copTask.tablePlan != nil {
indexConds, tableConds = ranger.DetachIndexFilterConditions(is.filterCondition, is.Index.Columns, is.Table)
indexConds, tableConds = splitIndexFilterConditions(is.filterCondition, is.Index.Columns, is.Table)
} else {
indexConds = is.filterCondition
}
Expand Down Expand Up @@ -921,6 +921,49 @@ func matchIndicesProp(idxCols []*model.IndexColumn, propCols []*expression.Colum
return true
}

func splitIndexFilterConditions(conditions []expression.Expression, indexColumns []*model.IndexColumn,
table *model.TableInfo) (indexConds, tableConds []expression.Expression) {
var pkName model.CIStr
if table.PKIsHandle {
for _, colInfo := range table.Columns {
if mysql.HasPriKeyFlag(colInfo.Flag) {
pkName = colInfo.Name
break
}
}
}
var indexConditions, tableConditions []expression.Expression
for _, cond := range conditions {
if checkIndexCondition(cond, indexColumns, pkName) {
indexConditions = append(indexConditions, cond)
} else {
tableConditions = append(tableConditions, cond)
}
}
return indexConditions, tableConditions
}

// checkIndexCondition will check whether all columns of condition is index columns or primary key column.
func checkIndexCondition(condition expression.Expression, indexColumns []*model.IndexColumn, pkName model.CIStr) bool {
cols := expression.ExtractColumns(condition)
for _, col := range cols {
if pkName.L == col.ColName.L {
continue
}
isIndexColumn := false
for _, indCol := range indexColumns {
if col.ColName.L == indCol.Name.L && indCol.Length == types.UnspecifiedLength {
isIndexColumn = true
break
}
}
if !isIndexColumn {
return false
}
}
return true
}

func (p *DataSource) forceToTableScan() PhysicalPlan {
ts := PhysicalTableScan{
Table: p.tableInfo,
Expand Down
126 changes: 1 addition & 125 deletions util/ranger/refiner.go → util/ranger/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,12 @@
package ranger

import (
"math"

"github.com/juju/errors"
"github.com/pingcap/tidb/ast"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/types"
)

// fullRange is (-∞, +∞).
var fullRange = []point{
{start: true},
{value: types.MaxValueDatum()},
}

// FullIntRange is (-∞, +∞) for IntColumnRange.
func FullIntRange() []types.IntColumnRange {
return []types.IntColumnRange{{LowVal: math.MinInt64, HighVal: math.MaxInt64}}
}

// FullIndexRange is (-∞, +∞) for IndexRange.
func FullIndexRange() []*types.IndexRange {
return []*types.IndexRange{{LowVal: []types.Datum{{}}, HighVal: []types.Datum{types.MaxValueDatum()}}}
}

// getEQFunctionOffset judge if the expression is a eq function like A = 1 where a is an index.
// If so, it will return the offset of A in index columns. e.g. for index(C,B,A), A's offset is 2.
func getEQFunctionOffset(expr expression.Expression, cols []*model.IndexColumn) int {
Expand Down Expand Up @@ -68,110 +47,6 @@ func getEQFunctionOffset(expr expression.Expression, cols []*model.IndexColumn)
return -1
}

func removeAccessConditions(conditions, accessConds []expression.Expression) []expression.Expression {
for i := len(conditions) - 1; i >= 0; i-- {
for _, cond := range accessConds {
if cond == conditions[i] {
conditions = append(conditions[:i], conditions[i+1:]...)
break
}
}
}
return conditions
}

// checkIndexCondition will check whether all columns of condition is index columns or primary key column.
func checkIndexCondition(condition expression.Expression, indexColumns []*model.IndexColumn, pKName model.CIStr) bool {
cols := expression.ExtractColumns(condition)
for _, col := range cols {
if pKName.L == col.ColName.L {
continue
}
isIndexColumn := false
for _, indCol := range indexColumns {
if col.ColName.L == indCol.Name.L && indCol.Length == types.UnspecifiedLength {
isIndexColumn = true
break
}
}
if !isIndexColumn {
return false
}
}
return true
}

// DetachIndexFilterConditions will detach the access conditions from other conditions.
func DetachIndexFilterConditions(conditions []expression.Expression, indexColumns []*model.IndexColumn, table *model.TableInfo) ([]expression.Expression, []expression.Expression) {
var pKName model.CIStr
if table.PKIsHandle {
for _, colInfo := range table.Columns {
if mysql.HasPriKeyFlag(colInfo.Flag) {
pKName = colInfo.Name
break
}
}
}
var indexConditions, tableConditions []expression.Expression
for _, cond := range conditions {
if checkIndexCondition(cond, indexColumns, pKName) {
indexConditions = append(indexConditions, cond)
} else {
tableConditions = append(tableConditions, cond)
}
}
return indexConditions, tableConditions
}

// DetachColumnConditions distinguishes between access conditions and filter conditions from conditions.
func DetachColumnConditions(conditions []expression.Expression, colName model.CIStr) ([]expression.Expression, []expression.Expression) {
if colName.L == "" {
return nil, conditions
}

var accessConditions, filterConditions []expression.Expression
checker := conditionChecker{
colName: colName,
length: types.UnspecifiedLength,
}
for _, cond := range conditions {
cond = expression.PushDownNot(cond, false, nil)
if !checker.check(cond) {
filterConditions = append(filterConditions, cond)
continue
}
accessConditions = append(accessConditions, cond)
// TODO: it will lead to repeated computation cost.
if checker.shouldReserve {
filterConditions = append(filterConditions, cond)
checker.shouldReserve = false
}
}

return accessConditions, filterConditions
}

// BuildTableRange will build range of pk for PhysicalTableScan
func BuildTableRange(accessConditions []expression.Expression, sc *variable.StatementContext) ([]types.IntColumnRange, error) {
if len(accessConditions) == 0 {
return FullIntRange(), nil
}

rb := builder{sc: sc}
rangePoints := fullRange
for _, cond := range accessConditions {
rangePoints = rb.intersection(rangePoints, rb.build(cond))
if rb.err != nil {
return nil, errors.Trace(rb.err)
}
}
ranges, err := points2TableRanges(sc, rangePoints)
if err != nil {
return nil, errors.Trace(rb.err)
}
return ranges, nil
}

// conditionChecker checks if this condition can be pushed to index plan.
type conditionChecker struct {
idx *model.IndexInfo
Expand Down Expand Up @@ -284,6 +159,7 @@ func (c *conditionChecker) checkLikeFunc(scalar *expression.ScalarFunction) bool
pattern, ok := scalar.GetArgs()[1].(*expression.Constant)
if !ok {
return false

}
if pattern.Value.IsNull() {
return false
Expand Down
Loading

0 comments on commit 5922b74

Please sign in to comment.