in executor/collision_matrix.go [224:286]
func ExactlyMatch(first, second interface{}) bool {
if (first != nil && second == nil) || (first == nil && second != nil) ||
reflect.TypeOf(first).Kind() != reflect.TypeOf(second).Kind() {
return false
}
// both of them are null is accept
if first == nil && second == nil {
return true
}
switch o := first.(type) {
case bson.M: // recursive
for key := range o {
if v, ok := second.(map[string]interface{}); ok && !ExactlyMatch(o[key], v[key]) {
return false
}
}
case []interface{}: // recursive
if v, ok := second.([]interface{}); ok {
if len(o) != len(v) {
return false
}
}
for i := range o {
if v, ok := second.([]interface{}); ok && !ExactlyMatch(o[i], v[i]) {
return false
}
}
case []byte: // byte array
if v, ok := second.([]byte); ok {
return bytes.Compare(o, v) == 0
}
case primitive.Binary:
if v, ok := second.(primitive.Binary); ok {
return bytes.Compare(o.Data, v.Data) == 0
}
case string:
if v, ok := second.(string); ok {
return o == v
}
case primitive.Timestamp: // numbers
return (first.(primitive.Timestamp)).Equal(second.(primitive.Timestamp))
case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64:
if v1, ok := first.(float64); ok {
if v2, ok := second.(float64); ok {
return v1 == v2
}
}
case bool: // boolean
if v, ok := second.(bool); ok {
return o == v
}
default:
nimo.Assert(fmt.Sprintf("bson value check similar. not recognized [%s]", reflect.TypeOf(first).Name()))
LOG.Critical("bson value check similar. not recognized [%s]", reflect.TypeOf(first).Name())
}
// TODO: execute path may be walked from DEFAULT we meet something that the type
// we don't know now. for safety, we treat these oplogs' unique indexes as equal exactly !!
// This may cause more segments splitted but more safe.
return true
}