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

     1  /*
     2  Copyright 2020 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 planbuilder
    18  
    19  import (
    20  	"fmt"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  
    25  	"vitess.io/vitess/go/vt/sqlparser"
    26  	"vitess.io/vitess/go/vt/vtgate/engine"
    27  	"vitess.io/vitess/go/vt/vtgate/vindexes"
    28  )
    29  
    30  /*
    31  
    32  This test file only tests the V3 planner. It does not test the Subshard opcode
    33  
    34  For easy reference, opcodes are:
    35  	Unsharded   	 0
    36  	EqualUnique 	 1
    37  	Equal       	 2
    38  	IN          	 3
    39  	MultiEqual  	 4
    40  	Scatter     	 5
    41  	Next        	 6
    42  	DBA         	 7
    43  	Reference   	 8
    44  	None        	 9
    45  */
    46  
    47  func TestJoinCanMerge(t *testing.T) {
    48  	testcases := [][]bool{
    49  		{true, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    50  		{false, true, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    51  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    52  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    53  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    54  
    55  		{false, false, false, false, false, false, false, false, false, false, false, false}, // this whole line is not tested
    56  
    57  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    58  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    59  		{false, false, false, false, false /*not tested*/, false, false, false, true, true, false, false},
    60  		{true, true, true, true, true /*not tested*/, false, true, true, true, true, true, true},
    61  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    62  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
    63  	}
    64  
    65  	ks := &vindexes.Keyspace{}
    66  	for left, vals := range testcases {
    67  		for right, val := range vals {
    68  			name := fmt.Sprintf("%s:%s", engine.Opcode(left).String(), engine.Opcode(right).String())
    69  			if left == int(engine.SubShard) || right == int(engine.SubShard) {
    70  				continue // not used by v3
    71  			}
    72  
    73  			t.Run(name, func(t *testing.T) {
    74  				lRoute := &route{
    75  					// Setting condition will make SelectEqualUnique match itself.
    76  					condition: &sqlparser.ColName{},
    77  				}
    78  				pb := &primitiveBuilder{
    79  					plan: lRoute,
    80  				}
    81  				rRoute := &route{
    82  					condition: &sqlparser.ColName{},
    83  				}
    84  				lRoute.eroute = engine.NewSimpleRoute(engine.Opcode(left), ks)
    85  				rRoute.eroute = engine.NewSimpleRoute(engine.Opcode(right), ks)
    86  				assert.Equal(t, val, lRoute.JoinCanMerge(pb, rRoute, nil, nil), fmt.Sprintf("%v:%v", lRoute.eroute.RouteType(), rRoute.eroute.RouteType()))
    87  			})
    88  		}
    89  	}
    90  }
    91  
    92  func TestSubqueryCanMerge(t *testing.T) {
    93  	testcases := [][]bool{
    94  		// US    EU    E      IN      ME         subShard        scatter  nxt   dba    ref   none   byD
    95  		{true, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},   // unsharded
    96  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},  // equalUnique
    97  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // equal
    98  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // in
    99  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // multiEqual
   100  
   101  		{false, false, false, false, false, false, false, false, false, false, false, false, false}, // subshard - this whole line is not tested
   102  
   103  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // scatter
   104  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},  // next
   105  		{false, false, false, false, false /*not tested*/, false, false, false, true, true, false, false},   // dba
   106  		{true, true, false, false, false /*not tested*/, false, false, true, true, true, false, false},      // reference
   107  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // none
   108  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false}, // byDestination
   109  	}
   110  
   111  	ks := &vindexes.Keyspace{}
   112  	lRoute := &route{}
   113  	pb := &primitiveBuilder{
   114  		plan: lRoute,
   115  	}
   116  	rRoute := &route{}
   117  	for left, vals := range testcases {
   118  		lRoute.eroute = engine.NewSimpleRoute(engine.Opcode(left), ks)
   119  		for right, val := range vals {
   120  			name := fmt.Sprintf("%s:%s", engine.Opcode(left).String(), engine.Opcode(right).String())
   121  			t.Run(name, func(t *testing.T) {
   122  				if left == int(engine.SubShard) || right == int(engine.SubShard) {
   123  					t.Skip("not used by v3")
   124  				}
   125  
   126  				rRoute.eroute = engine.NewSimpleRoute(engine.Opcode(right), ks)
   127  				assert.Equal(t, val, lRoute.SubqueryCanMerge(pb, rRoute), fmt.Sprintf("%v:%v", lRoute.eroute.RouteType(), rRoute.eroute.RouteType()))
   128  			})
   129  		}
   130  	}
   131  }
   132  
   133  func TestUnionCanMerge(t *testing.T) {
   134  	testcases := [][]bool{
   135  		{true, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   136  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   137  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   138  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   139  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   140  
   141  		{false, false, false, false, false, false, false, false, false, false, false, false, false}, // this whole line is not tested
   142  
   143  		{false, false, false, false, false /*not tested*/, false, true, false, false, false, false, false},
   144  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   145  		{false, false, false, false, false /*not tested*/, false, false, false, true, false, false, false},
   146  		{false, false, false, false, false /*not tested*/, false, false, false, false, true, false, false},
   147  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   148  		{false, false, false, false, false /*not tested*/, false, false, false, false, false, false, false},
   149  	}
   150  
   151  	ks := &vindexes.Keyspace{}
   152  	lRoute := &route{}
   153  	rRoute := &route{}
   154  	for left, vals := range testcases {
   155  		lRoute.eroute = engine.NewSimpleRoute(engine.Opcode(left), ks)
   156  		for right, val := range vals {
   157  			name := fmt.Sprintf("%s:%s", engine.Opcode(left).String(), engine.Opcode(right).String())
   158  			t.Run(name, func(t *testing.T) {
   159  				if left == int(engine.SubShard) || right == int(engine.SubShard) {
   160  					t.Skip("not used by v3")
   161  				}
   162  
   163  				rRoute.eroute = engine.NewSimpleRoute(engine.Opcode(right), ks)
   164  				assert.Equal(t, val, lRoute.unionCanMerge(rRoute, false), fmt.Sprintf("can't create a single route from these two inputs %v:%v", lRoute.eroute.RouteType(), rRoute.eroute.RouteType()))
   165  			})
   166  		}
   167  	}
   168  }