github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/concat.go (about) 1 // Copyright 2021 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 plan 16 17 import ( 18 "github.com/dolthub/go-mysql-server/sql" 19 ) 20 21 // Concat is a node that returns everything in Left and then everything in 22 // Right, but it excludes any results in Right that already appeared in Left. 23 // Similar to Distinct(Union(...)) but allows Left to return the same row 24 // more than once. 25 type Concat struct { 26 BinaryNode 27 } 28 29 var _ sql.Node = (*Concat)(nil) 30 var _ sql.CollationCoercible = (*Concat)(nil) 31 32 // NewConcat creates a new Concat node with the given children. 33 // See concatJoin memo expression for more details. 34 func NewConcat(left, right sql.Node) *Concat { 35 return &Concat{ 36 BinaryNode: BinaryNode{left: left, right: right}, 37 } 38 } 39 40 func (c *Concat) Schema() sql.Schema { 41 ls := c.left.Schema() 42 rs := c.right.Schema() 43 ret := make([]*sql.Column, len(ls)) 44 for i := range ls { 45 c := *ls[i] 46 if i < len(rs) { 47 c.Nullable = ls[i].Nullable || rs[i].Nullable 48 } 49 ret[i] = &c 50 } 51 return ret 52 } 53 54 // WithChildren implements the Node interface. 55 func (c *Concat) WithChildren(children ...sql.Node) (sql.Node, error) { 56 if len(children) != 2 { 57 return nil, sql.ErrInvalidChildrenNumber.New(c, len(children), 2) 58 } 59 return NewConcat(children[0], children[1]), nil 60 } 61 62 // CheckPrivileges implements the interface sql.Node. 63 func (c *Concat) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 64 return c.left.CheckPrivileges(ctx, opChecker) && c.right.CheckPrivileges(ctx, opChecker) 65 } 66 67 // CollationCoercibility implements the interface sql.CollationCoercible. 68 func (*Concat) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 69 // As this is similar to UNION, it isn't possible to determine what the resulting coercibility may be 70 return sql.Collation_binary, 7 71 } 72 73 func (c *Concat) IsReadOnly() bool { 74 return c.left.IsReadOnly() && c.right.IsReadOnly() 75 } 76 77 func (c Concat) String() string { 78 pr := sql.NewTreePrinter() 79 _ = pr.WriteNode("Concat") 80 _ = pr.WriteChildren(c.left.String(), c.right.String()) 81 return pr.String() 82 } 83 84 func (c Concat) DebugString() string { 85 pr := sql.NewTreePrinter() 86 _ = pr.WriteNode("Concat") 87 _ = pr.WriteChildren(sql.DebugString(c.left), sql.DebugString(c.right)) 88 return pr.String() 89 }