github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/memo/interner.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package memo
    12  
    13  import (
    14  	"bytes"
    15  	"math"
    16  	"math/rand"
    17  	"reflect"
    18  	"unsafe"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/geo/geoindex"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/opt"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/opt/props/physical"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    26  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    27  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    28  	"github.com/cockroachdb/errors"
    29  )
    30  
    31  const (
    32  	// offset64 is the initial hash value, and is taken from fnv.go
    33  	offset64 = 14695981039346656037
    34  
    35  	// prime64 is a large-ish prime number used in hashing and taken from fnv.go.
    36  	prime64 = 1099511628211
    37  )
    38  
    39  // internHash is a 64-bit hash value, computed using the FNV-1a algorithm.
    40  type internHash uint64
    41  
    42  // interner interns relational and scalar expressions, which means that multiple
    43  // equivalent expressions are mapped to a single in-memory instance. If two
    44  // expressions with the same values for all fields are interned, the intern
    45  // method will return the first expression in both cases. Interned expressions
    46  // can therefore be checked for equivalence by simple pointer comparison.
    47  // Equivalence is defined more strictly than SQL equivalence; two values are
    48  // equivalent only if their binary encoded representations are identical. For
    49  // example, positive and negative float64 values *are not* equivalent, whereas
    50  // NaN float values *are* equivalent.
    51  //
    52  // To use interner, first call the Init method to initialize storage. Call the
    53  // appropriate Intern method to retrieve the canonical instance of that
    54  // expression. Release references to other instances, including the expression
    55  // passed to Intern.
    56  //
    57  // The interner computes a hash function for each expression operator type that
    58  // enables quick determination of whether an expression has already been added
    59  // to the interner. A hashXXX and isXXXEqual method must be added for every
    60  // unique type of every field in every expression struct. Optgen generates
    61  // Intern methods which use these methods to compute the hash and check whether
    62  // an equivalent expression is already present in the cache. Because hashing is
    63  // used, interned expressions must remain immutable after interning. That is,
    64  // once set, they can never be modified again, else their hash value would
    65  // become invalid.
    66  //
    67  // The non-cryptographic hash function is adapted from fnv.go in Golang's
    68  // standard library. That in turn was taken from FNV-1a, described here:
    69  //
    70  //   https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
    71  //
    72  // Each expression type follows the same interning pattern:
    73  //
    74  //   1. Compute an int64 hash value for the expression using FNV-1a.
    75  //   2. Do a fast 64-bit Go map lookup to determine if an expression with the
    76  //      same hash is already in the cache.
    77  //   3. If so, then test whether the existing expression is equivalent, since
    78  //      there may be a hash value collision.
    79  //   4. Expressions with colliding hash values are linked together in a list.
    80  //      Rather than use an explicit linked list data structure, colliding
    81  //      entries are rehashed using a randomly generated hash value that is
    82  //      stored in the existing entry. This effectively uses the Go map as if it
    83  //      were a hash table of size 2^64.
    84  //
    85  // This pattern enables very low overhead hashing of expressions - the
    86  // allocation of a Go map with a fast 64-bit key, plus a couple of reusable
    87  // scratch byte arrays.
    88  type interner struct {
    89  	// hasher is a helper struct to compute hashes and test equality.
    90  	hasher hasher
    91  
    92  	// cache is a helper struct that implements the interning pattern described
    93  	// in the header over a Go map.
    94  	cache internCache
    95  }
    96  
    97  // Clear clears all interned expressions. Expressions interned before the call
    98  // to Clear will not be connected to expressions interned after.
    99  func (in *interner) Clear() {
   100  	in.cache.Clear()
   101  }
   102  
   103  // Count returns the number of expressions that have been interned.
   104  func (in *interner) Count() int {
   105  	return in.cache.Count()
   106  }
   107  
   108  var physPropsType = reflect.TypeOf((*physical.Required)(nil))
   109  var physPropsTypePtr = uint64(reflect.ValueOf(physPropsType).Pointer())
   110  
   111  // InternPhysicalProps interns a set of physical properties using the same
   112  // pattern as that used by the expression intern methods, with one difference.
   113  // This intern method does not force the incoming physical properties to escape
   114  // to the heap. It does this by making a copy of the physical properties before
   115  // adding them to the cache.
   116  func (in *interner) InternPhysicalProps(val *physical.Required) *physical.Required {
   117  	// Hash the physical.Required reflect type to distinguish it from other values.
   118  	in.hasher.Init()
   119  	in.hasher.HashUint64(physPropsTypePtr)
   120  	in.hasher.HashPhysProps(val)
   121  
   122  	// Loop over any items with the same hash value, checking for equality.
   123  	in.cache.Start(in.hasher.hash)
   124  	for in.cache.Next() {
   125  		// There's an existing item, so check for equality.
   126  		if existing, ok := in.cache.Item().(*physical.Required); ok {
   127  			if in.hasher.IsPhysPropsEqual(val, existing) {
   128  				// Found equivalent item, so return it.
   129  				return existing
   130  			}
   131  		}
   132  	}
   133  
   134  	// Shallow copy the props to prevent "val" from escaping.
   135  	copy := *val
   136  	in.cache.Add(&copy)
   137  	return &copy
   138  }
   139  
   140  // internCache is a helper class that implements the interning pattern described
   141  // in the comment for the interner struct. Here is a usage example:
   142  //
   143  //   var cache internCache
   144  //   cache.Start(hash)
   145  //   for cache.Next() {
   146  //     if isEqual(cache.Item(), other) {
   147  //       // Found existing item in cache.
   148  //     }
   149  //   }
   150  //   cache.Add(other)
   151  //
   152  // The calls to the Next method iterate over any entries with the same hash,
   153  // until either a match is found or it is proven their are no matches, in which
   154  // case the new item can be added to the cache.
   155  type internCache struct {
   156  	// cache is a Go map that's being used as if it were a hash table of size
   157  	// 2^64. Items are hashed according to their 64-bit hash value, and any
   158  	// colliding entries are linked together using the collision field in
   159  	// cacheEntry.
   160  	cache map[internHash]cacheEntry
   161  
   162  	// hash stores the lookup value used by the next call to the Next method.
   163  	hash internHash
   164  
   165  	// prev stores the cache entry last fetched from the map by the Next method.
   166  	prev cacheEntry
   167  }
   168  
   169  // cacheEntry is the Go map value. In case of hash value collisions it functions
   170  // as a linked list node; its collision field is a randomly generated re-hash
   171  // value that "points" to the colliding node. That node in turn can point to yet
   172  // another colliding node, and so on. Walking a collision list therefore
   173  // consists of computing an initial hash based on the value of the node, and
   174  // then following the list of collision hash values by indexing into the cache
   175  // map repeatedly.
   176  type cacheEntry struct {
   177  	item      interface{}
   178  	collision internHash
   179  }
   180  
   181  // Item returns the cache item that was fetched by the Next method.
   182  func (c *internCache) Item() interface{} {
   183  	return c.prev.item
   184  }
   185  
   186  // Count returns the number of items in the cache.
   187  func (c *internCache) Count() int {
   188  	return len(c.cache)
   189  }
   190  
   191  // Clear clears all items in the cache.
   192  func (c *internCache) Clear() {
   193  	c.cache = nil
   194  }
   195  
   196  // Start prepares to look up an item in the cache by its hash value. It must be
   197  // called before Next.
   198  func (c *internCache) Start(hash internHash) {
   199  	if c.cache == nil {
   200  		c.cache = make(map[internHash]cacheEntry)
   201  	}
   202  	c.hash = hash
   203  	c.prev = cacheEntry{}
   204  }
   205  
   206  // Next iterates over a collision list of cache items. It begins with the hash
   207  // value set via the call to Start, and continues with any collision hash values
   208  // it finds in the collision list. If it is at the end of an existing collision
   209  // list, it generates a new random hash value and links it to the existing
   210  // entry.
   211  func (c *internCache) Next() bool {
   212  	// If item is set, then the previous lookup must not have matched, so try to
   213  	// get the next value in the collision list, or return false if at the end of
   214  	// the list.
   215  	if c.prev.item != nil {
   216  		if c.prev.collision == 0 {
   217  			// This was the last item in the collision list.
   218  			return false
   219  		}
   220  
   221  		// A collision link already exists, so follow that.
   222  		c.hash = c.prev.collision
   223  	}
   224  
   225  	var ok bool
   226  	c.prev, ok = c.cache[c.hash]
   227  	return ok
   228  }
   229  
   230  // Add inserts the given item into the cache. The caller should have already
   231  // checked that the item is not yet in the cache.
   232  func (c *internCache) Add(item interface{}) {
   233  	if item == nil {
   234  		panic(errors.AssertionFailedf("cannot add the nil value to the cache"))
   235  	}
   236  
   237  	if c.prev.item == nil {
   238  		// There was no collision, so directly insert the item into the cache.
   239  		c.cache[c.hash] = cacheEntry{item: item}
   240  		return
   241  	}
   242  
   243  	// There was a collision, so re-hash the item and link it to the existing
   244  	// item. Loop until the generated random hash value doesn't collide with any
   245  	// existing item.
   246  	for {
   247  		// Using global rand is OK, since collisions of 64-bit random values should
   248  		// virtually never happen, so there won't be contention.
   249  		newHash := internHash(rand.Uint64())
   250  		if newHash != 0 {
   251  			if _, ok := c.cache[newHash]; !ok {
   252  				c.cache[c.hash] = cacheEntry{item: c.prev.item, collision: newHash}
   253  				c.cache[newHash] = cacheEntry{item: item}
   254  				return
   255  			}
   256  		}
   257  	}
   258  }
   259  
   260  // hasher is a helper struct that exposes methods for computing hash values and
   261  // testing equality on all the various types of values. It is embedded in the
   262  // interner. To use, first call the init method, then a series of hash methods.
   263  // The final value is stored in the hash field.
   264  type hasher struct {
   265  	// bytes is a scratch byte array used to serialize certain types of values
   266  	// during hashing and equality testing.
   267  	bytes []byte
   268  
   269  	// bytes2 is a scratch byte array used to serialize certain types of values
   270  	// during equality testing.
   271  	bytes2 []byte
   272  
   273  	// hash stores the hash value as it is incrementally computed.
   274  	hash internHash
   275  }
   276  
   277  func (h *hasher) Init() {
   278  	h.hash = offset64
   279  }
   280  
   281  // ----------------------------------------------------------------------
   282  //
   283  // Hash functions
   284  //   Each field in each item to be hashed must have a hash function that
   285  //   corresponds to the type of that field. Each type mutates the hash field
   286  //   of the interner using the FNV-1a hash algorithm.
   287  //
   288  // ----------------------------------------------------------------------
   289  
   290  func (h *hasher) HashBool(val bool) {
   291  	i := 0
   292  	if val {
   293  		i = 1
   294  	}
   295  	h.hash ^= internHash(i)
   296  	h.hash *= prime64
   297  }
   298  
   299  func (h *hasher) HashInt(val int) {
   300  	h.hash ^= internHash(val)
   301  	h.hash *= prime64
   302  }
   303  
   304  func (h *hasher) HashUint64(val uint64) {
   305  	h.hash ^= internHash(val)
   306  	h.hash *= prime64
   307  }
   308  
   309  func (h *hasher) HashFloat64(val float64) {
   310  	h.hash ^= internHash(math.Float64bits(val))
   311  	h.hash *= prime64
   312  }
   313  
   314  func (h *hasher) HashRune(val rune) {
   315  	h.hash ^= internHash(val)
   316  	h.hash *= prime64
   317  }
   318  
   319  func (h *hasher) HashString(val string) {
   320  	for _, c := range val {
   321  		h.HashRune(c)
   322  	}
   323  }
   324  
   325  func (h *hasher) HashByte(val byte) {
   326  	h.HashRune(rune(val))
   327  }
   328  
   329  func (h *hasher) HashBytes(val []byte) {
   330  	for _, c := range val {
   331  		h.HashByte(c)
   332  	}
   333  }
   334  
   335  func (h *hasher) HashOperator(val opt.Operator) {
   336  	h.HashUint64(uint64(val))
   337  }
   338  
   339  func (h *hasher) HashGoType(val reflect.Type) {
   340  	h.HashUint64(uint64(reflect.ValueOf(val).Pointer()))
   341  }
   342  
   343  func (h *hasher) HashDatum(val tree.Datum) {
   344  	// Distinguish distinct values with the same representation (i.e. 1 can
   345  	// be a Decimal or Int) using the reflect.Type of the value.
   346  	h.HashGoType(reflect.TypeOf(val))
   347  
   348  	// Special case some datum types that are simple to hash. For the others,
   349  	// hash the key encoding or string representation.
   350  	switch t := val.(type) {
   351  	case *tree.DBool:
   352  		h.HashBool(bool(*t))
   353  	case *tree.DInt:
   354  		h.HashUint64(uint64(*t))
   355  	case *tree.DFloat:
   356  		h.HashFloat64(float64(*t))
   357  	case *tree.DString:
   358  		h.HashString(string(*t))
   359  	case *tree.DBytes:
   360  		h.HashBytes([]byte(*t))
   361  	case *tree.DDate:
   362  		h.HashUint64(uint64(t.PGEpochDays()))
   363  	case *tree.DTime:
   364  		h.HashUint64(uint64(*t))
   365  	case *tree.DJSON:
   366  		h.HashString(t.String())
   367  	case *tree.DTuple:
   368  		// If labels are present, then hash of tuple's static type is needed to
   369  		// disambiguate when everything is the same except labels.
   370  		alwaysHashType := len(t.ResolvedType().TupleLabels()) != 0
   371  		h.hashDatumsWithType(t.D, t.ResolvedType(), alwaysHashType)
   372  	case *tree.DArray:
   373  		// If the array is empty, then hash of tuple's static type is needed to
   374  		// disambiguate.
   375  		alwaysHashType := len(t.Array) == 0
   376  		h.hashDatumsWithType(t.Array, t.ResolvedType(), alwaysHashType)
   377  	case *tree.DCollatedString:
   378  		h.HashString(t.Locale)
   379  		h.HashString(t.Contents)
   380  	default:
   381  		h.bytes = encodeDatum(h.bytes[:0], val)
   382  		h.HashBytes(h.bytes)
   383  	}
   384  }
   385  
   386  func (h *hasher) hashDatumsWithType(datums tree.Datums, typ *types.T, alwaysHashType bool) {
   387  	for _, d := range datums {
   388  		if d == tree.DNull {
   389  			// At least one NULL exists, so need to compare static types (e.g. a
   390  			// NULL::int is indistinguishable from NULL::string).
   391  			alwaysHashType = true
   392  		}
   393  		h.HashDatum(d)
   394  	}
   395  	if alwaysHashType {
   396  		h.HashType(typ)
   397  	}
   398  }
   399  
   400  func (h *hasher) HashType(val *types.T) {
   401  	// NOTE: type.String() is not a perfect hash of the type, as items such as
   402  	// precision and width may be lost. Collision handling must still occur.
   403  	h.HashString(val.String())
   404  }
   405  
   406  func (h *hasher) HashTypedExpr(val tree.TypedExpr) {
   407  	h.HashUint64(uint64(reflect.ValueOf(val).Pointer()))
   408  }
   409  
   410  func (h *hasher) HashStatement(val tree.Statement) {
   411  	h.HashUint64(uint64(reflect.ValueOf(val).Pointer()))
   412  }
   413  
   414  func (h *hasher) HashColumnID(val opt.ColumnID) {
   415  	h.HashUint64(uint64(val))
   416  }
   417  
   418  func (h *hasher) HashColSet(val opt.ColSet) {
   419  	hash := h.hash
   420  	for c, ok := val.Next(0); ok; c, ok = val.Next(c + 1) {
   421  		hash ^= internHash(c)
   422  		hash *= prime64
   423  	}
   424  	h.hash = hash
   425  }
   426  
   427  func (h *hasher) HashColList(val opt.ColList) {
   428  	hash := h.hash
   429  	for _, id := range val {
   430  		hash ^= internHash(id)
   431  		hash *= prime64
   432  	}
   433  	h.hash = hash
   434  }
   435  
   436  func (h *hasher) HashOrdering(val opt.Ordering) {
   437  	hash := h.hash
   438  	for _, id := range val {
   439  		hash ^= internHash(id)
   440  		hash *= prime64
   441  	}
   442  	h.hash = hash
   443  }
   444  
   445  func (h *hasher) HashOrderingChoice(val physical.OrderingChoice) {
   446  	h.HashColSet(val.Optional)
   447  
   448  	for i := range val.Columns {
   449  		choice := &val.Columns[i]
   450  		h.HashColSet(choice.Group)
   451  		h.HashBool(choice.Descending)
   452  	}
   453  }
   454  
   455  func (h *hasher) HashSchemaID(val opt.SchemaID) {
   456  	h.HashUint64(uint64(val))
   457  }
   458  
   459  func (h *hasher) HashTableID(val opt.TableID) {
   460  	h.HashUint64(uint64(val))
   461  }
   462  
   463  func (h *hasher) HashSequenceID(val opt.SequenceID) {
   464  	h.HashUint64(uint64(val))
   465  }
   466  
   467  func (h *hasher) HashUniqueID(val opt.UniqueID) {
   468  	h.HashUint64(uint64(val))
   469  }
   470  
   471  func (h *hasher) HashWithID(val opt.WithID) {
   472  	h.HashUint64(uint64(val))
   473  }
   474  
   475  func (h *hasher) HashScanLimit(val ScanLimit) {
   476  	h.HashUint64(uint64(val))
   477  }
   478  
   479  func (h *hasher) HashScanFlags(val ScanFlags) {
   480  	h.HashBool(val.NoIndexJoin)
   481  	h.HashBool(val.ForceIndex)
   482  	h.HashInt(int(val.Direction))
   483  	h.HashUint64(uint64(val.Index))
   484  }
   485  
   486  func (h *hasher) HashJoinFlags(val JoinFlags) {
   487  	h.HashUint64(uint64(val))
   488  }
   489  
   490  func (h *hasher) HashFKCascades(val FKCascades) {
   491  	for i := range val {
   492  		h.HashUint64(uint64(reflect.ValueOf(val[i].Builder).Pointer()))
   493  	}
   494  }
   495  
   496  func (h *hasher) HashExplainOptions(val tree.ExplainOptions) {
   497  	h.HashUint64(uint64(val.Mode))
   498  	hash := h.hash
   499  	for i, val := range val.Flags {
   500  		if val {
   501  			hash ^= internHash(uint64(i))
   502  			hash *= prime64
   503  		}
   504  	}
   505  	h.hash = hash
   506  }
   507  
   508  func (h *hasher) HashStatementType(val tree.StatementType) {
   509  	h.HashUint64(uint64(val))
   510  }
   511  
   512  func (h *hasher) HashShowTraceType(val tree.ShowTraceType) {
   513  	h.HashString(string(val))
   514  }
   515  
   516  func (h *hasher) HashJobCommand(val tree.JobCommand) {
   517  	h.HashInt(int(val))
   518  }
   519  
   520  func (h *hasher) HashIndexOrdinal(val cat.IndexOrdinal) {
   521  	h.HashInt(val)
   522  }
   523  
   524  func (h *hasher) HashViewDeps(val opt.ViewDeps) {
   525  	// Hash the length and address of the first element.
   526  	h.HashInt(len(val))
   527  	if len(val) > 0 {
   528  		h.HashPointer(unsafe.Pointer(&val[0]))
   529  	}
   530  }
   531  
   532  func (h *hasher) HashWindowFrame(val WindowFrame) {
   533  	h.HashInt(int(val.StartBoundType))
   534  	h.HashInt(int(val.EndBoundType))
   535  	h.HashInt(int(val.Mode))
   536  	h.HashInt(int(val.FrameExclusion))
   537  }
   538  
   539  func (h *hasher) HashTupleOrdinal(val TupleOrdinal) {
   540  	h.HashUint64(uint64(val))
   541  }
   542  
   543  func (h *hasher) HashPhysProps(val *physical.Required) {
   544  	// Note: the Any presentation is not the same as the 0-column presentation.
   545  	if !val.Presentation.Any() {
   546  		h.HashInt(len(val.Presentation))
   547  		for i := range val.Presentation {
   548  			col := &val.Presentation[i]
   549  			h.HashString(col.Alias)
   550  			h.HashColumnID(col.ID)
   551  		}
   552  	}
   553  	h.HashOrderingChoice(val.Ordering)
   554  	h.HashFloat64(val.LimitHint)
   555  }
   556  
   557  func (h *hasher) HashLockingItem(val *tree.LockingItem) {
   558  	if val != nil {
   559  		h.HashByte(byte(val.Strength))
   560  		h.HashByte(byte(val.WaitPolicy))
   561  	}
   562  }
   563  
   564  func (h *hasher) HashGeoRelationshipType(val geoindex.RelationshipType) {
   565  	h.HashUint64(uint64(val))
   566  }
   567  
   568  func (h *hasher) HashRelExpr(val RelExpr) {
   569  	h.HashUint64(uint64(reflect.ValueOf(val).Pointer()))
   570  }
   571  
   572  func (h *hasher) HashScalarExpr(val opt.ScalarExpr) {
   573  	h.HashUint64(uint64(reflect.ValueOf(val).Pointer()))
   574  }
   575  
   576  func (h *hasher) HashScalarListExpr(val ScalarListExpr) {
   577  	for i := range val {
   578  		h.HashScalarExpr(val[i])
   579  	}
   580  }
   581  
   582  func (h *hasher) HashFiltersExpr(val FiltersExpr) {
   583  	for i := range val {
   584  		h.HashScalarExpr(val[i].Condition)
   585  	}
   586  }
   587  
   588  func (h *hasher) HashProjectionsExpr(val ProjectionsExpr) {
   589  	for i := range val {
   590  		item := &val[i]
   591  		h.HashColumnID(item.Col)
   592  		h.HashScalarExpr(item.Element)
   593  	}
   594  }
   595  
   596  func (h *hasher) HashAggregationsExpr(val AggregationsExpr) {
   597  	for i := range val {
   598  		item := &val[i]
   599  		h.HashColumnID(item.Col)
   600  		h.HashScalarExpr(item.Agg)
   601  	}
   602  }
   603  
   604  func (h *hasher) HashWindowsExpr(val WindowsExpr) {
   605  	for i := range val {
   606  		item := &val[i]
   607  		h.HashColumnID(item.Col)
   608  		h.HashScalarExpr(item.Function)
   609  		h.HashWindowFrame(item.Frame)
   610  	}
   611  }
   612  
   613  func (h *hasher) HashZipExpr(val ZipExpr) {
   614  	for i := range val {
   615  		item := &val[i]
   616  		h.HashColList(item.Cols)
   617  		h.HashScalarExpr(item.Fn)
   618  	}
   619  }
   620  
   621  func (h *hasher) HashFKChecksExpr(val FKChecksExpr) {
   622  	for i := range val {
   623  		h.HashRelExpr(val[i].Check)
   624  	}
   625  }
   626  
   627  func (h *hasher) HashKVOptionsExpr(val KVOptionsExpr) {
   628  	for i := range val {
   629  		h.HashString(val[i].Key)
   630  		h.HashScalarExpr(val[i].Value)
   631  	}
   632  }
   633  
   634  func (h *hasher) HashPresentation(val physical.Presentation) {
   635  	for i := range val {
   636  		col := &val[i]
   637  		h.HashString(col.Alias)
   638  		h.HashColumnID(col.ID)
   639  	}
   640  }
   641  
   642  func (h *hasher) HashOpaqueMetadata(val opt.OpaqueMetadata) {
   643  	h.HashUint64(uint64(reflect.ValueOf(val).Pointer()))
   644  }
   645  
   646  func (h *hasher) HashPointer(val unsafe.Pointer) {
   647  	h.HashUint64(uint64(uintptr(val)))
   648  }
   649  
   650  func (h *hasher) HashMaterializeClause(val tree.MaterializeClause) {
   651  	h.HashBool(val.Set)
   652  	h.HashBool(val.Materialize)
   653  }
   654  
   655  // ----------------------------------------------------------------------
   656  //
   657  // Equality functions
   658  //   Each field in each item to be hashed must have an equality function that
   659  //   corresponds to the type of that field. An equality function returns true
   660  //   if the two values are equivalent. If all fields in two items are
   661  //   equivalent, then the items are considered equivalent, and only one is
   662  //   retained in the cache.
   663  //
   664  // ----------------------------------------------------------------------
   665  
   666  func (h *hasher) IsBoolEqual(l, r bool) bool {
   667  	return l == r
   668  }
   669  
   670  func (h *hasher) IsIntEqual(l, r int) bool {
   671  	return l == r
   672  }
   673  
   674  func (h *hasher) IsFloat64Equal(l, r float64) bool {
   675  	// Compare bit representations so that NaN == NaN and 0 != -0.
   676  	return math.Float64bits(l) == math.Float64bits(r)
   677  }
   678  
   679  func (h *hasher) IsRuneEqual(l, r rune) bool {
   680  	return l == r
   681  }
   682  
   683  func (h *hasher) IsStringEqual(l, r string) bool {
   684  	return l == r
   685  }
   686  
   687  func (h *hasher) IsByteEqual(l, r byte) bool {
   688  	return l == r
   689  }
   690  
   691  func (h *hasher) IsBytesEqual(l, r []byte) bool {
   692  	return bytes.Equal(l, r)
   693  }
   694  
   695  func (h *hasher) IsGoTypeEqual(l, r reflect.Type) bool {
   696  	return l == r
   697  }
   698  
   699  func (h *hasher) IsOperatorEqual(l, r opt.Operator) bool {
   700  	return l == r
   701  }
   702  
   703  func (h *hasher) IsTypeEqual(l, r *types.T) bool {
   704  	return l.Identical(r)
   705  }
   706  
   707  func (h *hasher) IsDatumEqual(l, r tree.Datum) bool {
   708  	if reflect.TypeOf(l) != reflect.TypeOf(r) {
   709  		return false
   710  	}
   711  	switch lt := l.(type) {
   712  	case *tree.DBool:
   713  		rt := r.(*tree.DBool)
   714  		return *lt == *rt
   715  	case *tree.DInt:
   716  		rt := r.(*tree.DInt)
   717  		return *lt == *rt
   718  	case *tree.DFloat:
   719  		rt := r.(*tree.DFloat)
   720  		return h.IsFloat64Equal(float64(*lt), float64(*rt))
   721  	case *tree.DString:
   722  		rt := r.(*tree.DString)
   723  		return h.IsStringEqual(string(*lt), string(*rt))
   724  	case *tree.DCollatedString:
   725  		rt := r.(*tree.DCollatedString)
   726  		return lt.Locale == rt.Locale && h.IsStringEqual(lt.Contents, rt.Contents)
   727  	case *tree.DBytes:
   728  		rt := r.(*tree.DBytes)
   729  		return bytes.Equal([]byte(*lt), []byte(*rt))
   730  	case *tree.DDate:
   731  		rt := r.(*tree.DDate)
   732  		return lt.Date == rt.Date
   733  	case *tree.DTime:
   734  		rt := r.(*tree.DTime)
   735  		return uint64(*lt) == uint64(*rt)
   736  	case *tree.DJSON:
   737  		rt := r.(*tree.DJSON)
   738  		return h.IsStringEqual(lt.String(), rt.String())
   739  	case *tree.DTuple:
   740  		rt := r.(*tree.DTuple)
   741  		// Compare datums and then compare static types if nulls or labels
   742  		// are present.
   743  		ltyp := lt.ResolvedType()
   744  		rtyp := rt.ResolvedType()
   745  		if !h.areDatumsWithTypeEqual(lt.D, rt.D, ltyp, rtyp) {
   746  			return false
   747  		}
   748  		return len(ltyp.TupleLabels()) == 0 || h.IsTypeEqual(ltyp, rtyp)
   749  	case *tree.DArray:
   750  		rt := r.(*tree.DArray)
   751  		// Compare datums and then compare static types if nulls are present
   752  		// or if arrays are empty.
   753  		ltyp := lt.ResolvedType()
   754  		rtyp := rt.ResolvedType()
   755  		if !h.areDatumsWithTypeEqual(lt.Array, rt.Array, ltyp, rtyp) {
   756  			return false
   757  		}
   758  		return len(lt.Array) != 0 || h.IsTypeEqual(ltyp, rtyp)
   759  	default:
   760  		h.bytes = encodeDatum(h.bytes[:0], l)
   761  		h.bytes2 = encodeDatum(h.bytes2[:0], r)
   762  		return bytes.Equal(h.bytes, h.bytes2)
   763  	}
   764  }
   765  
   766  func (h *hasher) areDatumsWithTypeEqual(ldatums, rdatums tree.Datums, ltyp, rtyp *types.T) bool {
   767  	if len(ldatums) != len(rdatums) {
   768  		return false
   769  	}
   770  	foundNull := false
   771  	for i := range ldatums {
   772  		if !h.IsDatumEqual(ldatums[i], rdatums[i]) {
   773  			return false
   774  		}
   775  		if ldatums[i] == tree.DNull {
   776  			// At least one NULL exists, so need to compare static types (e.g. a
   777  			// NULL::int is indistinguishable from NULL::string).
   778  			foundNull = true
   779  		}
   780  	}
   781  	if foundNull {
   782  		return h.IsTypeEqual(ltyp, rtyp)
   783  	}
   784  	return true
   785  }
   786  
   787  func (h *hasher) IsTypedExprEqual(l, r tree.TypedExpr) bool {
   788  	return l == r
   789  }
   790  
   791  func (h *hasher) IsStatementEqual(l, r tree.Statement) bool {
   792  	return l == r
   793  }
   794  
   795  func (h *hasher) IsColumnIDEqual(l, r opt.ColumnID) bool {
   796  	return l == r
   797  }
   798  
   799  func (h *hasher) IsColSetEqual(l, r opt.ColSet) bool {
   800  	return l.Equals(r)
   801  }
   802  
   803  func (h *hasher) IsColListEqual(l, r opt.ColList) bool {
   804  	return l.Equals(r)
   805  }
   806  
   807  func (h *hasher) IsOrderingEqual(l, r opt.Ordering) bool {
   808  	return l.Equals(r)
   809  }
   810  
   811  func (h *hasher) IsOrderingChoiceEqual(l, r physical.OrderingChoice) bool {
   812  	return l.Equals(&r)
   813  }
   814  
   815  func (h *hasher) IsSchemaIDEqual(l, r opt.SchemaID) bool {
   816  	return l == r
   817  }
   818  
   819  func (h *hasher) IsTableIDEqual(l, r opt.TableID) bool {
   820  	return l == r
   821  }
   822  
   823  func (h *hasher) IsSequenceIDEqual(l, r opt.SequenceID) bool {
   824  	return l == r
   825  }
   826  
   827  func (h *hasher) IsUniqueIDEqual(l, r opt.UniqueID) bool {
   828  	return l == r
   829  }
   830  
   831  func (h *hasher) IsWithIDEqual(l, r opt.WithID) bool {
   832  	return l == r
   833  }
   834  
   835  func (h *hasher) IsScanLimitEqual(l, r ScanLimit) bool {
   836  	return l == r
   837  }
   838  
   839  func (h *hasher) IsScanFlagsEqual(l, r ScanFlags) bool {
   840  	return l == r
   841  }
   842  
   843  func (h *hasher) IsJoinFlagsEqual(l, r JoinFlags) bool {
   844  	return l == r
   845  }
   846  
   847  func (h *hasher) IsFKCascadesEqual(l, r FKCascades) bool {
   848  	if len(l) != len(r) {
   849  		return false
   850  	}
   851  	for i := range l {
   852  		// It's sufficient to compare the CascadeBuilder instances.
   853  		if l[i].Builder != r[i].Builder {
   854  			return false
   855  		}
   856  	}
   857  	return true
   858  }
   859  
   860  func (h *hasher) IsExplainOptionsEqual(l, r tree.ExplainOptions) bool {
   861  	return l == r
   862  }
   863  
   864  func (h *hasher) IsStatementTypeEqual(l, r tree.StatementType) bool {
   865  	return l == r
   866  }
   867  
   868  func (h *hasher) IsShowTraceTypeEqual(l, r tree.ShowTraceType) bool {
   869  	return l == r
   870  }
   871  
   872  func (h *hasher) IsJobCommandEqual(l, r tree.JobCommand) bool {
   873  	return l == r
   874  }
   875  
   876  func (h *hasher) IsIndexOrdinalEqual(l, r cat.IndexOrdinal) bool {
   877  	return l == r
   878  }
   879  
   880  func (h *hasher) IsViewDepsEqual(l, r opt.ViewDeps) bool {
   881  	if len(l) != len(r) {
   882  		return false
   883  	}
   884  	return len(l) == 0 || &l[0] == &r[0]
   885  }
   886  
   887  func (h *hasher) IsWindowFrameEqual(l, r WindowFrame) bool {
   888  	return l.StartBoundType == r.StartBoundType &&
   889  		l.EndBoundType == r.EndBoundType &&
   890  		l.Mode == r.Mode &&
   891  		l.FrameExclusion == r.FrameExclusion
   892  }
   893  
   894  func (h *hasher) IsTupleOrdinalEqual(l, r TupleOrdinal) bool {
   895  	return l == r
   896  }
   897  
   898  func (h *hasher) IsPhysPropsEqual(l, r *physical.Required) bool {
   899  	return l.Equals(r)
   900  }
   901  
   902  func (h *hasher) IsLockingItemEqual(l, r *tree.LockingItem) bool {
   903  	if l == nil || r == nil {
   904  		return l == r
   905  	}
   906  	return l.Strength == r.Strength && l.WaitPolicy == r.WaitPolicy
   907  }
   908  
   909  func (h *hasher) IsGeoRelationshipTypeEqual(l, r geoindex.RelationshipType) bool {
   910  	return l == r
   911  }
   912  
   913  func (h *hasher) IsPointerEqual(l, r unsafe.Pointer) bool {
   914  	return l == r
   915  }
   916  
   917  func (h *hasher) IsRelExprEqual(l, r RelExpr) bool {
   918  	return l == r
   919  }
   920  
   921  func (h *hasher) IsScalarExprEqual(l, r opt.ScalarExpr) bool {
   922  	return l == r
   923  }
   924  
   925  func (h *hasher) IsScalarListExprEqual(l, r ScalarListExpr) bool {
   926  	if len(l) != len(r) {
   927  		return false
   928  	}
   929  	for i := range l {
   930  		if l[i] != r[i] {
   931  			return false
   932  		}
   933  	}
   934  	return true
   935  }
   936  
   937  func (h *hasher) IsFiltersExprEqual(l, r FiltersExpr) bool {
   938  	if len(l) != len(r) {
   939  		return false
   940  	}
   941  	for i := range l {
   942  		if l[i].Condition != r[i].Condition {
   943  			return false
   944  		}
   945  	}
   946  	return true
   947  }
   948  
   949  func (h *hasher) IsProjectionsExprEqual(l, r ProjectionsExpr) bool {
   950  	if len(l) != len(r) {
   951  		return false
   952  	}
   953  	for i := range l {
   954  		if l[i].Col != r[i].Col || l[i].Element != r[i].Element {
   955  			return false
   956  		}
   957  	}
   958  	return true
   959  }
   960  
   961  func (h *hasher) IsAggregationsExprEqual(l, r AggregationsExpr) bool {
   962  	if len(l) != len(r) {
   963  		return false
   964  	}
   965  	for i := range l {
   966  		if l[i].Col != r[i].Col || l[i].Agg != r[i].Agg {
   967  			return false
   968  		}
   969  	}
   970  	return true
   971  }
   972  
   973  func (h *hasher) IsWindowsExprEqual(l, r WindowsExpr) bool {
   974  	if len(l) != len(r) {
   975  		return false
   976  	}
   977  	for i := range l {
   978  		if l[i].Col != r[i].Col ||
   979  			l[i].Function != r[i].Function ||
   980  			l[i].Frame != r[i].Frame {
   981  			return false
   982  		}
   983  	}
   984  	return true
   985  }
   986  
   987  func (h *hasher) IsZipExprEqual(l, r ZipExpr) bool {
   988  	if len(l) != len(r) {
   989  		return false
   990  	}
   991  	for i := range l {
   992  		if !l[i].Cols.Equals(r[i].Cols) || l[i].Fn != r[i].Fn {
   993  			return false
   994  		}
   995  	}
   996  	return true
   997  }
   998  
   999  func (h *hasher) IsFKChecksExprEqual(l, r FKChecksExpr) bool {
  1000  	if len(l) != len(r) {
  1001  		return false
  1002  	}
  1003  	for i := range l {
  1004  		if l[i].Check != r[i].Check {
  1005  			return false
  1006  		}
  1007  	}
  1008  	return true
  1009  }
  1010  
  1011  func (h *hasher) IsKVOptionsExprEqual(l, r KVOptionsExpr) bool {
  1012  	if len(l) != len(r) {
  1013  		return false
  1014  	}
  1015  	for i := range l {
  1016  		if l[i].Key != r[i].Key || l[i].Value != r[i].Value {
  1017  			return false
  1018  		}
  1019  	}
  1020  	return true
  1021  }
  1022  
  1023  func (h *hasher) IsPresentationEqual(l, r physical.Presentation) bool {
  1024  	if len(l) != len(r) {
  1025  		return false
  1026  	}
  1027  	for i := range l {
  1028  		if l[i].ID != r[i].ID || l[i].Alias != r[i].Alias {
  1029  			return false
  1030  		}
  1031  	}
  1032  	return true
  1033  }
  1034  
  1035  func (h *hasher) IsOpaqueMetadataEqual(l, r opt.OpaqueMetadata) bool {
  1036  	return l == r
  1037  }
  1038  
  1039  func (h *hasher) IsMaterializeClauseEqual(l, r tree.MaterializeClause) bool {
  1040  	return l.Set == r.Set && l.Materialize == r.Materialize
  1041  }
  1042  
  1043  // encodeDatum turns the given datum into an encoded string of bytes. If two
  1044  // datums are equivalent, then their encoded bytes will be identical.
  1045  // Conversely, if two datums are not equivalent, then their encoded bytes will
  1046  // differ. This will panic if the datum cannot be encoded.
  1047  // Notice: DCollatedString does not encode its collation and won't work here.
  1048  func encodeDatum(b []byte, val tree.Datum) []byte {
  1049  	var err error
  1050  
  1051  	// Fast path: encode the datum using table key encoding. This does not always
  1052  	// work, because the encoding does not uniquely represent some values which
  1053  	// should not be considered equivalent by the interner (e.g. decimal values
  1054  	// 1.0 and 1.00).
  1055  	if !sqlbase.HasCompositeKeyEncoding(val.ResolvedType()) {
  1056  		b, err = sqlbase.EncodeTableKey(b, val, encoding.Ascending)
  1057  		if err == nil {
  1058  			return b
  1059  		}
  1060  	}
  1061  
  1062  	b, err = sqlbase.EncodeTableValue(b, sqlbase.ColumnID(encoding.NoColumnID), val, nil /* scratch */)
  1063  	if err != nil {
  1064  		panic(err)
  1065  	}
  1066  	return b
  1067  }