// Copyright 2018 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. package memo import ( plannercore "github.com/pingcap/tidb/planner/core" ) // Operand is the node of a pattern tree, it represents a logical expression operator. // Different from logical plan operator which holds the full information about an expression // operator, Operand only stores the type information. // An Operand may correspond to a concrete logical plan operator, or it can has special meaning, // e.g, a placeholder for any logical plan operator. type Operand int const ( // OperandAny is a placeholder for any Operand. OperandAny Operand = iota // OperandJoin for LogicalJoin. OperandJoin // OperandAggregation for LogicalAggregation. OperandAggregation // OperandProjection for LogicalProjection. OperandProjection // OperandSelection for LogicalSelection. OperandSelection // OperandApply for LogicalApply. OperandApply // OperandMaxOneRow for LogicalMaxOneRow. OperandMaxOneRow // OperandTableDual for LogicalTableDual. OperandTableDual // OperandDataSource for DataSource. OperandDataSource // OperandUnionScan for LogicalUnionScan. OperandUnionScan // OperandUnionAll for LogicalUnionAll. OperandUnionAll // OperandSort for LogicalSort. OperandSort // OperandTopN for LogicalTopN. OperandTopN // OperandLock for LogicalLock. OperandLock // OperandLimit for LogicalLimit. OperandLimit // OperandUnsupported is upper bound of defined Operand yet. OperandUnsupported ) // GetOperand maps logical plan operator to Operand. func GetOperand(p plannercore.LogicalPlan) Operand { switch p.(type) { case *plannercore.LogicalJoin: return OperandJoin case *plannercore.LogicalAggregation: return OperandAggregation case *plannercore.LogicalProjection: return OperandProjection case *plannercore.LogicalSelection: return OperandSelection case *plannercore.LogicalApply: return OperandApply case *plannercore.LogicalMaxOneRow: return OperandMaxOneRow case *plannercore.LogicalTableDual: return OperandTableDual case *plannercore.DataSource: return OperandDataSource case *plannercore.LogicalUnionScan: return OperandUnionScan case *plannercore.LogicalUnionAll: return OperandUnionAll case *plannercore.LogicalSort: return OperandSort case *plannercore.LogicalTopN: return OperandTopN case *plannercore.LogicalLock: return OperandLock case *plannercore.LogicalLimit: return OperandLimit default: return OperandUnsupported } } // Match checks if current Operand matches specified one. func (o Operand) Match(t Operand) bool { if o == OperandAny || t == OperandAny { return true } if o == t { return true } return false } // Pattern defines the Match pattern for a rule. // It describes a piece of logical expression. // It's a tree-like structure and each node in the tree is an Operand. type Pattern struct { Operand Children []*Pattern } // NewPattern creats a pattern node according to the Operand. func NewPattern(operand Operand) *Pattern { return &Pattern{Operand: operand} } // SetChildren sets the Children information for a pattern node. func (p *Pattern) SetChildren(children ...*Pattern) { p.Children = children } // BuildPattern builds a Pattern from Operand and child Patterns. // Used in GetPattern() of Transformation interface to generate a Pattern. func BuildPattern(operand Operand, children ...*Pattern) *Pattern { p := &Pattern{Operand: operand} p.Children = children return p }