func (a maybe) Join(other Lattice) (Lattice, error) {
	b, ok := other.(maybe)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case a.Lattice == nil:
		return b, nil
	case b.Lattice == nil:
		return a, nil
	default:
		join, err := a.Lattice.Join(b.Lattice)
		if err != nil {
			return nil, err
		}
		return maybe{Lattice: join}, nil
	}
}
Join implements Lattice.
package schemacmp
import (
	"fmt"
	"github.com/pingcap/tidb/parser/mysql"
	"github.com/pingcap/tidb/parser/types"
)
type IncompatibleError struct {
	Msg  string
	Args []interface{}
}
const (
	ErrMsgTypeMismatch           = "type mismatch (%T vs %T)"
	ErrMsgTupleLengthMismatch    = "tuple length mismatch (%d vs %d)"
	ErrMsgDistinctSingletons     = "distinct singletons (%v vs %v)"
	ErrMsgIncompatibleType       = "incompatible mysql type (%v vs %v)"
	ErrMsgAtTupleIndex           = "at tuple index %d: %v"
	ErrMsgAtMapKey               = "at map key %q: %v"
	ErrMsgNonInclusiveBitSets    = "non-inclusive bit sets (%#x vs %#x)"
	ErrMsgContradictingOrders    = "combining contradicting orders (%d && %d)"
	ErrMsgStringListElemMismatch = "at string list index %d: distinct values (%q vs %q)"
)
func (e *IncompatibleError) Error() string {
	return fmt.Sprintf(e.Msg, e.Args...)
}
func typeMismatchError(a, b Lattice) *IncompatibleError {
	return &IncompatibleError{
		Msg:  ErrMsgTypeMismatch,
		Args: []interface{}{a, b},
	}
}
func tupleLengthMismatchError(a, b int) *IncompatibleError {
	return &IncompatibleError{
		Msg:  ErrMsgTupleLengthMismatch,
		Args: []interface{}{a, b},
	}
}
func distinctSingletonsErrors(a, b interface{}) *IncompatibleError {
	return &IncompatibleError{
		Msg:  ErrMsgDistinctSingletons,
		Args: []interface{}{a, b},
	}
}
func incompatibleTypeError(a, b interface{}) *IncompatibleError {
	return &IncompatibleError{
		Msg:  ErrMsgIncompatibleType,
		Args: []interface{}{a, b},
	}
}
func wrapTupleIndexError(i int, inner error) *IncompatibleError {
	return &IncompatibleError{
		Msg:  ErrMsgAtTupleIndex,
		Args: []interface{}{i, inner},
	}
}
func wrapMapKeyError(key string, inner error) *IncompatibleError {
	return &IncompatibleError{
		Msg:  ErrMsgAtMapKey,
		Args: []interface{}{key, inner},
	}
}
type Lattice interface {
	Unwrap() interface{}
	Compare(other Lattice) (int, error)
	Join(other Lattice) (Lattice, error)
}
type Bool bool
func (a Bool) Unwrap() interface{} {
	return bool(a)
}
func (a Bool) Compare(other Lattice) (int, error) {
	b, ok := other.(Bool)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a == b:
		return 0, nil
	case bool(a):
		return 1, nil
	default:
		return -1, nil
	}
}
func (a Bool) Join(other Lattice) (Lattice, error) {
	b, ok := other.(Bool)
	if !ok {
		return nil, typeMismatchError(a, other)
	}
	return a || b, nil
}
type singleton struct{ value interface{} }
func (a singleton) Unwrap() interface{} {
	return a.value
}
func Singleton(value interface{}) Lattice {
	return singleton{value: value}
}
func (a singleton) Compare(other Lattice) (int, error) {
	b, ok := other.(singleton)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a.value != b.value:
		return 0, distinctSingletonsErrors(a.value, b.value)
	default:
		return 0, nil
	}
}
func (a singleton) Join(other Lattice) (Lattice, error) {
	b, ok := other.(singleton)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case a.value != b.value:
		return nil, distinctSingletonsErrors(a.value, b.value)
	default:
		return a, nil
	}
}
type Equality interface {
	Equals(other Equality) bool
}
type equalitySingleton struct{ Equality }
func EqualitySingleton(value Equality) Lattice {
	return equalitySingleton{Equality: value}
}
func (a equalitySingleton) Unwrap() interface{} {
	return a.Equality
}
func (a equalitySingleton) Compare(other Lattice) (int, error) {
	b, ok := other.(equalitySingleton)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case !a.Equals(b.Equality):
		return 0, distinctSingletonsErrors(a.Equality, b.Equality)
	default:
		return 0, nil
	}
}
func (a equalitySingleton) Join(other Lattice) (Lattice, error) {
	b, ok := other.(equalitySingleton)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case !a.Equals(b.Equality):
		return nil, distinctSingletonsErrors(a.Equality, b.Equality)
	default:
		return a, nil
	}
}
type BitSet uint
func (a BitSet) Unwrap() interface{} {
	return uint(a)
}
func (a BitSet) Compare(other Lattice) (int, error) {
	b, ok := other.(BitSet)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a == b:
		return 0, nil
	case a&^b == 0:
		return -1, nil
	case b&^a == 0:
		return 1, nil
	default:
		return 0, &IncompatibleError{
			Msg:  ErrMsgNonInclusiveBitSets,
			Args: []interface{}{a, b},
		}
	}
}
func (a BitSet) Join(other Lattice) (Lattice, error) {
	b, ok := other.(BitSet)
	if !ok {
		return nil, typeMismatchError(a, other)
	}
	return a | b, nil
}
type Byte byte
func (a Byte) Unwrap() interface{} {
	return byte(a)
}
func (a Byte) Compare(other Lattice) (int, error) {
	b, ok := other.(Byte)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a == b:
		return 0, nil
	case a > b:
		return 1, nil
	default:
		return -1, nil
	}
}
func (a Byte) Join(other Lattice) (Lattice, error) {
	b, ok := other.(Byte)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case a >= b:
		return a, nil
	default:
		return b, nil
	}
}
type fieldTp struct {
	value byte
}
func FieldTp(value byte) Lattice {
	return fieldTp{value: value}
}
func (a fieldTp) Unwrap() interface{} {
	return a.value
}
func (a fieldTp) Compare(other Lattice) (int, error) {
	b, ok := other.(fieldTp)
	if !ok {
		return 0, typeMismatchError(a, other)
	}
	if a.value == b.value {
		return 0, nil
	}
	if mysql.IsIntegerType(a.value) && mysql.IsIntegerType(b.value) {
		return compareMySQLIntegerType(a.value, b.value), nil
	}
	if types.IsTypeBlob(a.value) && types.IsTypeBlob(b.value) {
		return compareMySQLBlobType(a.value, b.value), nil
	}
	return 0, incompatibleTypeError(a.value, b.value)
}
func (a fieldTp) Join(other Lattice) (Lattice, error) {
	b, ok := other.(fieldTp)
	if !ok {
		return nil, typeMismatchError(a, other)
	}
	if a.value == b.value {
		return a, nil
	}
	if mysql.IsIntegerType(a.value) && mysql.IsIntegerType(b.value) {
		if compareMySQLIntegerType(a.value, b.value) < 0 {
			return b, nil
		}
		return a, nil
	}
	if types.IsTypeBlob(a.value) && types.IsTypeBlob(b.value) {
		if compareMySQLBlobType(a.value, b.value) < 0 {
			return b, nil
		}
		return a, nil
	}
	return nil, incompatibleTypeError(a.value, b.value)
}
type Int int
func (a Int) Unwrap() interface{} {
	return int(a)
}
func (a Int) Compare(other Lattice) (int, error) {
	b, ok := other.(Int)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a == b:
		return 0, nil
	case a > b:
		return 1, nil
	default:
		return -1, nil
	}
}
func (a Int) Join(other Lattice) (Lattice, error) {
	b, ok := other.(Int)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case a >= b:
		return a, nil
	default:
		return b, nil
	}
}
type Int64 int64
func (a Int64) Unwrap() interface{} {
	return int64(a)
}
func (a Int64) Compare(other Lattice) (int, error) {
	b, ok := other.(Int64)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a == b:
		return 0, nil
	case a > b:
		return 1, nil
	default:
		return -1, nil
	}
}
func (a Int64) Join(other Lattice) (Lattice, error) {
	b, ok := other.(Int64)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case a >= b:
		return a, nil
	default:
		return b, nil
	}
}
type Uint uint
func (a Uint) Unwrap() interface{} {
	return uint(a)
}
func (a Uint) Compare(other Lattice) (int, error) {
	b, ok := other.(Uint)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a == b:
		return 0, nil
	case a > b:
		return 1, nil
	default:
		return -1, nil
	}
}
func (a Uint) Join(other Lattice) (Lattice, error) {
	b, ok := other.(Uint)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case a >= b:
		return a, nil
	default:
		return b, nil
	}
}
type Tuple []Lattice
func (a Tuple) Unwrap() interface{} {
	res := make([]interface{}, 0, len(a))
	for _, value := range a {
		res = append(res, value.Unwrap())
	}
	return res
}
func (a Tuple) Compare(other Lattice) (int, error) {
	b, ok := other.(Tuple)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case len(a) != len(b):
		return 0, tupleLengthMismatchError(len(a), len(b))
	}
	result := 0
	for i, left := range a {
		res, err := left.Compare(b[i])
		if err != nil {
			return 0, wrapTupleIndexError(i, err)
		}
		result, err = CombineCompareResult(result, res)
		if err != nil {
			return 0, wrapTupleIndexError(i, err)
		}
	}
	return result, nil
}
func CombineCompareResult(x int, y int) (int, error) {
	switch {
	case x == y || y == 0:
		return x, nil
	case x == 0:
		return y, nil
	default:
		return 0, &IncompatibleError{
			Msg:  ErrMsgContradictingOrders,
			Args: []interface{}{x, y},
		}
	}
}
func (a Tuple) Join(other Lattice) (Lattice, error) {
	b, ok := other.(Tuple)
	switch {
	case !ok:
		return nil, typeMismatchError(a, other)
	case len(a) != len(b):
		return nil, tupleLengthMismatchError(len(a), len(b))
	}
	result := make(Tuple, 0, len(a))
	for i, left := range a {
		res, err := left.Join(b[i])
		if err != nil {
			return nil, wrapTupleIndexError(i, err)
		}
		result = append(result, res)
	}
	return result, nil
}
type maybe struct{ Lattice }
func Maybe(inner Lattice) Lattice {
	return maybe{Lattice: inner}
}
func MaybeSingletonInterface(value interface{}) Lattice {
	if value == nil {
		return Maybe(nil)
	}
	return Maybe(Singleton(value))
}
func MaybeSingletonString(s string) Lattice {
	if len(s) == 0 {
		return Maybe(nil)
	}
	return Maybe(Singleton(s))
}
func (a maybe) Unwrap() interface{} {
	if a.Lattice != nil {
		return a.Lattice.Unwrap()
	}
	return nil
}
func (a maybe) Compare(other Lattice) (int, error) {
	b, ok := other.(maybe)
	switch {
	case !ok:
		return 0, typeMismatchError(a, other)
	case a.Lattice == nil && b.Lattice == nil:
		return 0, nil
	case a.Lattice == nil:
		return -1, nil
	case b.Lattice == nil:
		return 1, nil
	default:
		return a.Lattice.Compare(b.Lattice)
	}
}