vitess.io/vitess@v0.16.2/go/vt/vtgate/semantics/dependencies.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 semantics
    18  
    19  import (
    20  	querypb "vitess.io/vitess/go/vt/proto/query"
    21  	vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
    22  	"vitess.io/vitess/go/vt/vterrors"
    23  )
    24  
    25  type (
    26  	// these types are used to go over dependencies provided by multiple
    27  	// tables and figure out bindings and/or errors by merging dependencies together
    28  	dependencies interface {
    29  		empty() bool
    30  		get() (dependency, error)
    31  		merge(other dependencies, allowMulti bool) dependencies
    32  	}
    33  	dependency struct {
    34  		direct    TableSet
    35  		recursive TableSet
    36  		typ       *Type
    37  	}
    38  	nothing struct{}
    39  	certain struct {
    40  		dependency
    41  		err error
    42  	}
    43  	uncertain struct {
    44  		dependency
    45  		fail bool
    46  	}
    47  )
    48  
    49  var ambigousErr = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "ambiguous")
    50  
    51  func createCertain(direct TableSet, recursive TableSet, qt *Type) *certain {
    52  	c := &certain{
    53  		dependency: dependency{
    54  			direct:    direct,
    55  			recursive: recursive,
    56  		},
    57  	}
    58  	if qt != nil && qt.Type != querypb.Type_NULL_TYPE {
    59  		c.typ = qt
    60  	}
    61  	return c
    62  }
    63  
    64  func createUncertain(direct TableSet, recursive TableSet) *uncertain {
    65  	return &uncertain{
    66  		dependency: dependency{
    67  			direct:    direct,
    68  			recursive: recursive,
    69  		},
    70  	}
    71  }
    72  
    73  var _ dependencies = (*nothing)(nil)
    74  var _ dependencies = (*certain)(nil)
    75  var _ dependencies = (*uncertain)(nil)
    76  
    77  func (u *uncertain) empty() bool {
    78  	return false
    79  }
    80  
    81  func (u *uncertain) get() (dependency, error) {
    82  	if u.fail {
    83  		return dependency{}, ambigousErr
    84  	}
    85  	return u.dependency, nil
    86  }
    87  
    88  func (u *uncertain) merge(d dependencies, _ bool) dependencies {
    89  	switch d := d.(type) {
    90  	case *uncertain:
    91  		if d.recursive != u.recursive {
    92  			u.fail = true
    93  		}
    94  		return u
    95  	case *certain:
    96  		return d
    97  	default:
    98  		return u
    99  	}
   100  }
   101  
   102  func (c *certain) empty() bool {
   103  	return false
   104  }
   105  
   106  func (c *certain) get() (dependency, error) {
   107  	return c.dependency, c.err
   108  }
   109  
   110  func (c *certain) merge(d dependencies, allowMulti bool) dependencies {
   111  	switch d := d.(type) {
   112  	case *certain:
   113  		if d.recursive == c.recursive {
   114  			return c
   115  		}
   116  		c.direct = c.direct.Merge(d.direct)
   117  		c.recursive = c.recursive.Merge(d.recursive)
   118  		if !allowMulti {
   119  			c.err = ambigousErr
   120  		}
   121  
   122  		return c
   123  	}
   124  
   125  	return c
   126  }
   127  
   128  func (n *nothing) empty() bool {
   129  	return true
   130  }
   131  
   132  func (n *nothing) get() (dependency, error) {
   133  	return dependency{}, nil
   134  }
   135  
   136  func (n *nothing) merge(d dependencies, _ bool) dependencies {
   137  	return d
   138  }