github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/util.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package embedded
    15  
    16  import (
    17  	"fmt"
    18  	"sort"
    19  	"strings"
    20  
    21  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    22  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    23  	"github.com/whtcorpsinc/milevadb/memex"
    24  	"github.com/whtcorpsinc/milevadb/soliton/ranger"
    25  	"github.com/whtcorpsinc/milevadb/soliton/set"
    26  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    27  	"github.com/whtcorpsinc/milevadb/types"
    28  )
    29  
    30  // AggregateFuncExtractor visits Expr tree.
    31  // It converts DefCausunmNameExpr to AggregateFuncExpr and collects AggregateFuncExpr.
    32  type AggregateFuncExtractor struct {
    33  	inAggregateFuncExpr bool
    34  	// AggFuncs is the collected AggregateFuncExprs.
    35  	AggFuncs []*ast.AggregateFuncExpr
    36  }
    37  
    38  // Enter implements Visitor interface.
    39  func (a *AggregateFuncExtractor) Enter(n ast.Node) (ast.Node, bool) {
    40  	switch n.(type) {
    41  	case *ast.AggregateFuncExpr:
    42  		a.inAggregateFuncExpr = true
    43  	case *ast.SelectStmt, *ast.SetOprStmt:
    44  		return n, true
    45  	}
    46  	return n, false
    47  }
    48  
    49  // Leave implements Visitor interface.
    50  func (a *AggregateFuncExtractor) Leave(n ast.Node) (ast.Node, bool) {
    51  	switch v := n.(type) {
    52  	case *ast.AggregateFuncExpr:
    53  		a.inAggregateFuncExpr = false
    54  		a.AggFuncs = append(a.AggFuncs, v)
    55  	}
    56  	return n, true
    57  }
    58  
    59  // WindowFuncExtractor visits Expr tree.
    60  // It converts DefCausunmNameExpr to WindowFuncExpr and collects WindowFuncExpr.
    61  type WindowFuncExtractor struct {
    62  	// WindowFuncs is the collected WindowFuncExprs.
    63  	windowFuncs []*ast.WindowFuncExpr
    64  }
    65  
    66  // Enter implements Visitor interface.
    67  func (a *WindowFuncExtractor) Enter(n ast.Node) (ast.Node, bool) {
    68  	switch n.(type) {
    69  	case *ast.SelectStmt, *ast.SetOprStmt:
    70  		return n, true
    71  	}
    72  	return n, false
    73  }
    74  
    75  // Leave implements Visitor interface.
    76  func (a *WindowFuncExtractor) Leave(n ast.Node) (ast.Node, bool) {
    77  	switch v := n.(type) {
    78  	case *ast.WindowFuncExpr:
    79  		a.windowFuncs = append(a.windowFuncs, v)
    80  	}
    81  	return n, true
    82  }
    83  
    84  // logicalSchemaProducer stores the schemaReplicant for the logical plans who can produce schemaReplicant directly.
    85  type logicalSchemaProducer struct {
    86  	schemaReplicant *memex.Schema
    87  	names           types.NameSlice
    88  	baseLogicalCauset
    89  }
    90  
    91  // Schema implements the Causet.Schema interface.
    92  func (s *logicalSchemaProducer) Schema() *memex.Schema {
    93  	if s.schemaReplicant == nil {
    94  		s.schemaReplicant = memex.NewSchema()
    95  	}
    96  	return s.schemaReplicant
    97  }
    98  
    99  func (s *logicalSchemaProducer) OutputNames() types.NameSlice {
   100  	return s.names
   101  }
   102  
   103  func (s *logicalSchemaProducer) SetOutputNames(names types.NameSlice) {
   104  	s.names = names
   105  }
   106  
   107  // SetSchema implements the Causet.SetSchema interface.
   108  func (s *logicalSchemaProducer) SetSchema(schemaReplicant *memex.Schema) {
   109  	s.schemaReplicant = schemaReplicant
   110  }
   111  
   112  func (s *logicalSchemaProducer) setSchemaAndNames(schemaReplicant *memex.Schema, names types.NameSlice) {
   113  	s.schemaReplicant = schemaReplicant
   114  	s.names = names
   115  }
   116  
   117  // inlineProjection prunes unneeded columns inline a interlock.
   118  func (s *logicalSchemaProducer) inlineProjection(parentUsedDefCauss []*memex.DeferredCauset) {
   119  	used := memex.GetUsedList(parentUsedDefCauss, s.schemaReplicant)
   120  	for i := len(used) - 1; i >= 0; i-- {
   121  		if !used[i] {
   122  			s.schemaReplicant.DeferredCausets = append(s.schemaReplicant.DeferredCausets[:i], s.schemaReplicant.DeferredCausets[i+1:]...)
   123  		}
   124  	}
   125  }
   126  
   127  // physicalSchemaProducer stores the schemaReplicant for the physical plans who can produce schemaReplicant directly.
   128  type physicalSchemaProducer struct {
   129  	schemaReplicant *memex.Schema
   130  	basePhysicalCauset
   131  }
   132  
   133  func (s *physicalSchemaProducer) cloneWithSelf(newSelf PhysicalCauset) (*physicalSchemaProducer, error) {
   134  	base, err := s.basePhysicalCauset.cloneWithSelf(newSelf)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	return &physicalSchemaProducer{
   139  		basePhysicalCauset: *base,
   140  		schemaReplicant:    s.schemaReplicant.Clone(),
   141  	}, nil
   142  }
   143  
   144  // Schema implements the Causet.Schema interface.
   145  func (s *physicalSchemaProducer) Schema() *memex.Schema {
   146  	if s.schemaReplicant == nil {
   147  		s.schemaReplicant = memex.NewSchema()
   148  	}
   149  	return s.schemaReplicant
   150  }
   151  
   152  // SetSchema implements the Causet.SetSchema interface.
   153  func (s *physicalSchemaProducer) SetSchema(schemaReplicant *memex.Schema) {
   154  	s.schemaReplicant = schemaReplicant
   155  }
   156  
   157  // baseSchemaProducer stores the schemaReplicant for the base plans who can produce schemaReplicant directly.
   158  type baseSchemaProducer struct {
   159  	schemaReplicant *memex.Schema
   160  	names           types.NameSlice
   161  	baseCauset
   162  }
   163  
   164  // OutputNames returns the outputting names of each column.
   165  func (s *baseSchemaProducer) OutputNames() types.NameSlice {
   166  	return s.names
   167  }
   168  
   169  func (s *baseSchemaProducer) SetOutputNames(names types.NameSlice) {
   170  	s.names = names
   171  }
   172  
   173  // Schema implements the Causet.Schema interface.
   174  func (s *baseSchemaProducer) Schema() *memex.Schema {
   175  	if s.schemaReplicant == nil {
   176  		s.schemaReplicant = memex.NewSchema()
   177  	}
   178  	return s.schemaReplicant
   179  }
   180  
   181  // SetSchema implements the Causet.SetSchema interface.
   182  func (s *baseSchemaProducer) SetSchema(schemaReplicant *memex.Schema) {
   183  	s.schemaReplicant = schemaReplicant
   184  }
   185  
   186  func (s *baseSchemaProducer) setSchemaAndNames(schemaReplicant *memex.Schema, names types.NameSlice) {
   187  	s.schemaReplicant = schemaReplicant
   188  	s.names = names
   189  }
   190  
   191  // Schema implements the Causet.Schema interface.
   192  func (p *LogicalMaxOneRow) Schema() *memex.Schema {
   193  	s := p.Children()[0].Schema().Clone()
   194  	resetNotNullFlag(s, 0, s.Len())
   195  	return s
   196  }
   197  
   198  func buildLogicalJoinSchema(joinType JoinType, join LogicalCauset) *memex.Schema {
   199  	leftSchema := join.Children()[0].Schema()
   200  	switch joinType {
   201  	case SemiJoin, AntiSemiJoin:
   202  		return leftSchema.Clone()
   203  	case LeftOuterSemiJoin, AntiLeftOuterSemiJoin:
   204  		newSchema := leftSchema.Clone()
   205  		newSchema.Append(join.Schema().DeferredCausets[join.Schema().Len()-1])
   206  		return newSchema
   207  	}
   208  	newSchema := memex.MergeSchema(leftSchema, join.Children()[1].Schema())
   209  	if joinType == LeftOuterJoin {
   210  		resetNotNullFlag(newSchema, leftSchema.Len(), newSchema.Len())
   211  	} else if joinType == RightOuterJoin {
   212  		resetNotNullFlag(newSchema, 0, leftSchema.Len())
   213  	}
   214  	return newSchema
   215  }
   216  
   217  // BuildPhysicalJoinSchema builds the schemaReplicant of PhysicalJoin from it's children's schemaReplicant.
   218  func BuildPhysicalJoinSchema(joinType JoinType, join PhysicalCauset) *memex.Schema {
   219  	switch joinType {
   220  	case SemiJoin, AntiSemiJoin:
   221  		return join.Children()[0].Schema().Clone()
   222  	case LeftOuterSemiJoin, AntiLeftOuterSemiJoin:
   223  		newSchema := join.Children()[0].Schema().Clone()
   224  		newSchema.Append(join.Schema().DeferredCausets[join.Schema().Len()-1])
   225  		return newSchema
   226  	}
   227  	return memex.MergeSchema(join.Children()[0].Schema(), join.Children()[1].Schema())
   228  }
   229  
   230  // GetStatsInfo gets the statistics info from a physical plan tree.
   231  func GetStatsInfo(i interface{}) map[string]uint64 {
   232  	if i == nil {
   233  		// it's a workaround for https://github.com/whtcorpsinc/milevadb/issues/17419
   234  		// To entirely fix this, uncomment the assertion in TestPreparedIssue17419
   235  		return nil
   236  	}
   237  	p := i.(Causet)
   238  	var physicalCauset PhysicalCauset
   239  	switch x := p.(type) {
   240  	case *Insert:
   241  		physicalCauset = x.SelectCauset
   242  	case *UFIDelate:
   243  		physicalCauset = x.SelectCauset
   244  	case *Delete:
   245  		physicalCauset = x.SelectCauset
   246  	case PhysicalCauset:
   247  		physicalCauset = x
   248  	}
   249  
   250  	if physicalCauset == nil {
   251  		return nil
   252  	}
   253  
   254  	statsInfos := make(map[string]uint64)
   255  	statsInfos = DefCauslectCausetStatsVersion(physicalCauset, statsInfos)
   256  	return statsInfos
   257  }
   258  
   259  // extractStringFromStringSet helps extract string info from set.StringSet
   260  func extractStringFromStringSet(set set.StringSet) string {
   261  	if len(set) < 1 {
   262  		return ""
   263  	}
   264  	l := make([]string, 0, len(set))
   265  	for k := range set {
   266  		l = append(l, fmt.Sprintf(`"%s"`, k))
   267  	}
   268  	sort.Strings(l)
   269  	return fmt.Sprintf("%s", strings.Join(l, ","))
   270  }
   271  
   272  func blockHasDirtyContent(ctx stochastikctx.Context, blockInfo *perceptron.BlockInfo) bool {
   273  	pi := blockInfo.GetPartitionInfo()
   274  	if pi == nil {
   275  		return ctx.HasDirtyContent(blockInfo.ID)
   276  	}
   277  	// Currently, we add UnionScan on every partition even though only one partition's data is changed.
   278  	// This is limited by current implementation of Partition Prune. It'll be uFIDelated once we modify that part.
   279  	for _, partition := range pi.Definitions {
   280  		if ctx.HasDirtyContent(partition.ID) {
   281  			return true
   282  		}
   283  	}
   284  	return false
   285  }
   286  
   287  func cloneExprs(exprs []memex.Expression) []memex.Expression {
   288  	cloned := make([]memex.Expression, 0, len(exprs))
   289  	for _, e := range exprs {
   290  		cloned = append(cloned, e.Clone())
   291  	}
   292  	return cloned
   293  }
   294  
   295  func cloneDefCauss(defcaus []*memex.DeferredCauset) []*memex.DeferredCauset {
   296  	cloned := make([]*memex.DeferredCauset, 0, len(defcaus))
   297  	for _, c := range defcaus {
   298  		cloned = append(cloned, c.Clone().(*memex.DeferredCauset))
   299  	}
   300  	return cloned
   301  }
   302  
   303  func cloneDefCausInfos(defcaus []*perceptron.DeferredCausetInfo) []*perceptron.DeferredCausetInfo {
   304  	cloned := make([]*perceptron.DeferredCausetInfo, 0, len(defcaus))
   305  	for _, c := range defcaus {
   306  		cloned = append(cloned, c.Clone())
   307  	}
   308  	return cloned
   309  }
   310  
   311  func cloneRanges(ranges []*ranger.Range) []*ranger.Range {
   312  	cloned := make([]*ranger.Range, 0, len(ranges))
   313  	for _, r := range ranges {
   314  		cloned = append(cloned, r.Clone())
   315  	}
   316  	return cloned
   317  }
   318  
   319  func clonePhysicalCauset(plans []PhysicalCauset) ([]PhysicalCauset, error) {
   320  	cloned := make([]PhysicalCauset, 0, len(plans))
   321  	for _, p := range plans {
   322  		c, err := p.Clone()
   323  		if err != nil {
   324  			return nil, err
   325  		}
   326  		cloned = append(cloned, c)
   327  	}
   328  	return cloned, nil
   329  }