vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/operators/querygraph.go (about)

     1  /*
     2  Copyright 2021 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package operators
    18  
    19  import (
    20  	"vitess.io/vitess/go/vt/sqlparser"
    21  	"vitess.io/vitess/go/vt/vtgate/planbuilder/operators/ops"
    22  	"vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext"
    23  	"vitess.io/vitess/go/vt/vtgate/semantics"
    24  )
    25  
    26  type (
    27  	/*QueryGraph represents the FROM and WHERE parts of a query.
    28  	It is an intermediate representation of the query that makes it easier for the planner
    29  	to find all possible join combinations. Instead of storing the query information in a form that is close
    30  	to the syntax (AST), we extract the interesting parts into a graph form with the nodes being tables in the FROM
    31  	clause and the edges between them being predicates. We keep predicates in a hash map keyed by the dependencies of
    32  	the predicate. This makes it very fast to look up connections between tables in the query.
    33  	*/
    34  	QueryGraph struct {
    35  		// the Tables, including predicates that only depend on this particular table
    36  		Tables []*QueryTable
    37  
    38  		// innerJoins contains the predicates that need multiple Tables
    39  		innerJoins []*innerJoin
    40  
    41  		// NoDeps contains the predicates that can be evaluated anywhere.
    42  		NoDeps sqlparser.Expr
    43  
    44  		noInputs
    45  		noColumns
    46  	}
    47  
    48  	innerJoin struct {
    49  		deps  semantics.TableSet
    50  		exprs []sqlparser.Expr
    51  	}
    52  
    53  	// QueryTable is a single FROM table, including all predicates particular to this table
    54  	// This is to be used as an immutable data structure which is created in the logical Operator Tree
    55  	QueryTable struct {
    56  		ID          semantics.TableSet
    57  		Alias       *sqlparser.AliasedTableExpr
    58  		Table       sqlparser.TableName
    59  		Predicates  []sqlparser.Expr
    60  		IsInfSchema bool
    61  	}
    62  )
    63  
    64  var _ ops.Operator = (*QueryGraph)(nil)
    65  
    66  // Introduces implements the TableIDIntroducer interface
    67  func (qg *QueryGraph) Introduces() semantics.TableSet {
    68  	var ts semantics.TableSet
    69  	for _, table := range qg.Tables {
    70  		ts = ts.Merge(table.ID)
    71  	}
    72  	return ts
    73  }
    74  
    75  // GetPredicates returns the predicates that are applicable for the two given TableSets
    76  func (qg *QueryGraph) GetPredicates(lhs, rhs semantics.TableSet) []sqlparser.Expr {
    77  	var allExprs []sqlparser.Expr
    78  	for _, join := range qg.innerJoins {
    79  		tableSet, exprs := join.deps, join.exprs
    80  		if tableSet.IsSolvedBy(lhs.Merge(rhs)) &&
    81  			tableSet.IsOverlapping(rhs) &&
    82  			tableSet.IsOverlapping(lhs) {
    83  			allExprs = append(allExprs, exprs...)
    84  		}
    85  	}
    86  	return allExprs
    87  }
    88  
    89  func newQueryGraph() *QueryGraph {
    90  	return &QueryGraph{}
    91  }
    92  
    93  func (qg *QueryGraph) collectPredicates(ctx *plancontext.PlanningContext, sel *sqlparser.Select) error {
    94  	predicates := sqlparser.SplitAndExpression(nil, sel.Where.Expr)
    95  
    96  	for _, predicate := range predicates {
    97  		err := qg.collectPredicate(ctx, predicate)
    98  		if err != nil {
    99  			return err
   100  		}
   101  	}
   102  	return nil
   103  }
   104  
   105  func (qg *QueryGraph) getPredicateByDeps(ts semantics.TableSet) ([]sqlparser.Expr, bool) {
   106  	for _, join := range qg.innerJoins {
   107  		if join.deps == ts {
   108  			return join.exprs, true
   109  		}
   110  	}
   111  	return nil, false
   112  }
   113  func (qg *QueryGraph) addJoinPredicates(ctx *plancontext.PlanningContext, ts semantics.TableSet, predicate sqlparser.Expr) {
   114  	for _, join := range qg.innerJoins {
   115  		if join.deps == ts {
   116  			if ctx.SemTable.ContainsExpr(predicate, join.exprs) {
   117  				return
   118  			}
   119  
   120  			join.exprs = append(join.exprs, predicate)
   121  			return
   122  		}
   123  	}
   124  
   125  	qg.innerJoins = append(qg.innerJoins, &innerJoin{
   126  		deps:  ts,
   127  		exprs: []sqlparser.Expr{predicate},
   128  	})
   129  }
   130  
   131  func (qg *QueryGraph) collectPredicate(ctx *plancontext.PlanningContext, predicate sqlparser.Expr) error {
   132  	deps := ctx.SemTable.RecursiveDeps(predicate)
   133  	switch deps.NumberOfTables() {
   134  	case 0:
   135  		qg.addNoDepsPredicate(predicate)
   136  	case 1:
   137  		found := qg.addToSingleTable(ctx, deps, predicate)
   138  		if !found {
   139  			// this could be a predicate that only has dependencies from outside this QG
   140  			qg.addJoinPredicates(ctx, deps, predicate)
   141  		}
   142  	default:
   143  		qg.addJoinPredicates(ctx, deps, predicate)
   144  	}
   145  	return nil
   146  }
   147  
   148  func (qg *QueryGraph) addToSingleTable(ctx *plancontext.PlanningContext, table semantics.TableSet, predicate sqlparser.Expr) bool {
   149  	for _, t := range qg.Tables {
   150  		if table == t.ID {
   151  			if !ctx.SemTable.ContainsExpr(predicate, t.Predicates) {
   152  				t.Predicates = append(t.Predicates, predicate)
   153  			}
   154  			return true
   155  		}
   156  	}
   157  	return false
   158  }
   159  
   160  func (qg *QueryGraph) addNoDepsPredicate(predicate sqlparser.Expr) {
   161  	if qg.NoDeps == nil {
   162  		qg.NoDeps = predicate
   163  	} else {
   164  		qg.NoDeps = &sqlparser.AndExpr{
   165  			Left:  qg.NoDeps,
   166  			Right: predicate,
   167  		}
   168  	}
   169  }
   170  
   171  // UnsolvedPredicates implements the unresolved interface
   172  func (qg *QueryGraph) UnsolvedPredicates(_ *semantics.SemTable) []sqlparser.Expr {
   173  	var result []sqlparser.Expr
   174  	tables := TableID(qg)
   175  	for _, join := range qg.innerJoins {
   176  		set, exprs := join.deps, join.exprs
   177  		if !set.IsSolvedBy(tables) {
   178  			result = append(result, exprs...)
   179  		}
   180  	}
   181  	return result
   182  }
   183  
   184  // Clone implements the Operator interface
   185  func (qg *QueryGraph) Clone(inputs []ops.Operator) ops.Operator {
   186  	result := &QueryGraph{
   187  		Tables:     nil,
   188  		innerJoins: nil,
   189  		NoDeps:     nil,
   190  	}
   191  
   192  	result.Tables = append([]*QueryTable{}, qg.Tables...)
   193  	result.innerJoins = append([]*innerJoin{}, qg.innerJoins...)
   194  	result.NoDeps = qg.NoDeps
   195  	return result
   196  }
   197  
   198  func (qg *QueryGraph) AddPredicate(ctx *plancontext.PlanningContext, expr sqlparser.Expr) (ops.Operator, error) {
   199  	for _, e := range sqlparser.SplitAndExpression(nil, expr) {
   200  		err := qg.collectPredicate(ctx, e)
   201  		if err != nil {
   202  			return nil, err
   203  		}
   204  	}
   205  	return qg, nil
   206  }
   207  
   208  // Clone implements the Operator interface
   209  func (qt *QueryTable) Clone() *QueryTable {
   210  	return &QueryTable{
   211  		ID:          qt.ID,
   212  		Alias:       sqlparser.CloneRefOfAliasedTableExpr(qt.Alias),
   213  		Table:       sqlparser.CloneTableName(qt.Table),
   214  		Predicates:  qt.Predicates,
   215  		IsInfSchema: qt.IsInfSchema,
   216  	}
   217  }