github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/hashcode.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  	"bytes"
    18  	"encoding/binary"
    19  	"sort"
    20  
    21  	"github.com/whtcorpsinc/milevadb/soliton/plancodec"
    22  )
    23  
    24  func encodeIntAsUint32(result []byte, value int) []byte {
    25  	var buf [4]byte
    26  	binary.BigEndian.PutUint32(buf[:], uint32(value))
    27  	return append(result, buf[:]...)
    28  }
    29  
    30  // HashCode implements LogicalCauset interface.
    31  func (p *baseLogicalCauset) HashCode() []byte {
    32  	// We use CausetID for the default hash, so if two plans do not have
    33  	// the same id, the hash value will never be the same.
    34  	result := make([]byte, 0, 4)
    35  	result = encodeIntAsUint32(result, p.id)
    36  	return result
    37  }
    38  
    39  // HashCode implements LogicalCauset interface.
    40  func (p *LogicalProjection) HashCode() []byte {
    41  	// CausetType + SelectOffset + ExprNum + [Exprs]
    42  	// Expressions are commonly `DeferredCauset`s, whose hashcode has the length 9, so
    43  	// we pre-alloc 10 bytes for each expr's hashcode.
    44  	result := make([]byte, 0, 12+len(p.Exprs)*10)
    45  	result = encodeIntAsUint32(result, plancodec.TypeStringToPhysicalID(p.tp))
    46  	result = encodeIntAsUint32(result, p.SelectBlockOffset())
    47  	result = encodeIntAsUint32(result, len(p.Exprs))
    48  	for _, expr := range p.Exprs {
    49  		exprHashCode := expr.HashCode(p.ctx.GetStochastikVars().StmtCtx)
    50  		result = encodeIntAsUint32(result, len(exprHashCode))
    51  		result = append(result, exprHashCode...)
    52  	}
    53  	return result
    54  }
    55  
    56  // HashCode implements LogicalCauset interface.
    57  func (p *LogicalBlockDual) HashCode() []byte {
    58  	// CausetType + SelectOffset + RowCount
    59  	result := make([]byte, 0, 12)
    60  	result = encodeIntAsUint32(result, plancodec.TypeStringToPhysicalID(p.tp))
    61  	result = encodeIntAsUint32(result, p.SelectBlockOffset())
    62  	result = encodeIntAsUint32(result, p.RowCount)
    63  	return result
    64  }
    65  
    66  // HashCode implements LogicalCauset interface.
    67  func (p *LogicalSelection) HashCode() []byte {
    68  	// CausetType + SelectOffset + ConditionNum + [Conditions]
    69  	// Conditions are commonly `ScalarFunction`s, whose hashcode usually has a
    70  	// length larger than 20, so we pre-alloc 25 bytes for each expr's hashcode.
    71  	result := make([]byte, 0, 12+len(p.Conditions)*25)
    72  	result = encodeIntAsUint32(result, plancodec.TypeStringToPhysicalID(p.tp))
    73  	result = encodeIntAsUint32(result, p.SelectBlockOffset())
    74  	result = encodeIntAsUint32(result, len(p.Conditions))
    75  
    76  	condHashCodes := make([][]byte, len(p.Conditions))
    77  	for i, expr := range p.Conditions {
    78  		condHashCodes[i] = expr.HashCode(p.ctx.GetStochastikVars().StmtCtx)
    79  	}
    80  	// Sort the conditions, so `a > 1 and a < 100` can equal to `a < 100 and a > 1`.
    81  	sort.Slice(condHashCodes, func(i, j int) bool { return bytes.Compare(condHashCodes[i], condHashCodes[j]) < 0 })
    82  
    83  	for _, condHashCode := range condHashCodes {
    84  		result = encodeIntAsUint32(result, len(condHashCode))
    85  		result = append(result, condHashCode...)
    86  	}
    87  	return result
    88  }
    89  
    90  // HashCode implements LogicalCauset interface.
    91  func (p *LogicalLimit) HashCode() []byte {
    92  	// CausetType + SelectOffset + Offset + Count
    93  	result := make([]byte, 24)
    94  	binary.BigEndian.PutUint32(result, uint32(plancodec.TypeStringToPhysicalID(p.tp)))
    95  	binary.BigEndian.PutUint32(result[4:], uint32(p.SelectBlockOffset()))
    96  	binary.BigEndian.PutUint64(result[8:], p.Offset)
    97  	binary.BigEndian.PutUint64(result[16:], p.Count)
    98  	return result
    99  }