github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/collation.go (about) 1 // Copyright 2023 Dolthub, 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package function 16 17 import ( 18 "fmt" 19 20 "github.com/dolthub/go-mysql-server/sql/types" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/expression" 24 ) 25 26 // Collation is a function that returns the collation of the inner expression. 27 type Collation struct { 28 expression.UnaryExpression 29 } 30 31 var _ sql.FunctionExpression = (*Collation)(nil) 32 var _ sql.CollationCoercible = (*Collation)(nil) 33 34 // NewCollation creates a new Collation expression. 35 func NewCollation(e sql.Expression) sql.Expression { 36 return &Collation{expression.UnaryExpression{Child: e}} 37 } 38 39 // FunctionName implements sql.FunctionExpression 40 func (c *Collation) FunctionName() string { 41 return "collation" 42 } 43 44 // Description implements sql.FunctionExpression 45 func (c *Collation) Description() string { 46 return "Returns the collation of the inner expression" 47 } 48 49 // Eval implements the sql.Expression. 50 func (c *Collation) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 51 val, err := c.Child.Eval(ctx, row) 52 if err != nil { 53 return nil, err 54 } 55 // If the value is nil, then we return 'binary' 56 if val == nil { 57 return sql.Collation_binary.Name(), nil 58 } 59 // Otherwise, we return the collation calculated from the expression 60 collation, _ := sql.GetCoercibility(ctx, c.Child) 61 return collation.Name(), nil 62 } 63 64 // String implements the fmt.Stringer interface. 65 func (c *Collation) String() string { 66 return fmt.Sprintf("%s(%s)", c.FunctionName(), c.Child.String()) 67 } 68 69 // WithChildren implements the Expression interface. 70 func (c *Collation) WithChildren(children ...sql.Expression) (sql.Expression, error) { 71 if len(children) != 1 { 72 return nil, sql.ErrInvalidChildrenNumber.New(c, len(children), 1) 73 } 74 return NewCollation(children[0]), nil 75 } 76 77 // Type implements the Expression interface. 78 func (c *Collation) Type() sql.Type { 79 return types.LongText 80 } 81 82 // CollationCoercibility implements the interface sql.CollationCoercible. 83 func (*Collation) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 84 return sql.Collation_utf8mb3_general_ci, 4 85 } 86 87 // Coercibility is a function that returns the coercibility of the inner expression. 88 type Coercibility struct { 89 expression.UnaryExpression 90 } 91 92 var _ sql.FunctionExpression = (*Coercibility)(nil) 93 var _ sql.CollationCoercible = (*Coercibility)(nil) 94 95 // NewCoercibility creates a new Coercibility expression. 96 func NewCoercibility(e sql.Expression) sql.Expression { 97 return &Coercibility{expression.UnaryExpression{Child: e}} 98 } 99 100 // FunctionName implements sql.FunctionExpression 101 func (c *Coercibility) FunctionName() string { 102 return "coercibility" 103 } 104 105 // Description implements sql.FunctionExpression 106 func (c *Coercibility) Description() string { 107 return "Returns the coercibility of the inner expression" 108 } 109 110 // Eval implements the sql.Expression. 111 func (c *Coercibility) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 112 val, err := c.Child.Eval(ctx, row) 113 if err != nil { 114 return nil, err 115 } 116 // If the value is nil, then we return 'binary' 117 if val == nil { 118 return 6, nil 119 } 120 // Otherwise, we return the collation calculated from the expression 121 _, coercibility := sql.GetCoercibility(ctx, c.Child) 122 return coercibility, nil 123 } 124 125 // String implements the fmt.Stringer interface. 126 func (c *Coercibility) String() string { 127 return fmt.Sprintf("%s(%s)", c.FunctionName(), c.Child.String()) 128 } 129 130 // WithChildren implements the Expression interface. 131 func (c *Coercibility) WithChildren(children ...sql.Expression) (sql.Expression, error) { 132 if len(children) != 1 { 133 return nil, sql.ErrInvalidChildrenNumber.New(c, len(children), 1) 134 } 135 return NewCoercibility(children[0]), nil 136 } 137 138 // Type implements the Expression interface. 139 func (c *Coercibility) Type() sql.Type { 140 return types.Int8 141 } 142 143 // CollationCoercibility implements the interface sql.CollationCoercible. 144 func (*Coercibility) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 145 return sql.Collation_binary, 5 146 }