github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/distinct.go (about) 1 // Copyright 2020-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 // Distinct is a node that ensures all rows that come from it are unique. 22 type Distinct struct { 23 UnaryNode 24 } 25 26 var _ sql.Node = (*Distinct)(nil) 27 var _ sql.CollationCoercible = (*Distinct)(nil) 28 29 // NewDistinct creates a new Distinct node. 30 func NewDistinct(child sql.Node) *Distinct { 31 return &Distinct{ 32 UnaryNode: UnaryNode{Child: child}, 33 } 34 } 35 36 // Resolved implements the Resolvable interface. 37 func (d *Distinct) Resolved() bool { 38 return d.UnaryNode.Child.Resolved() 39 } 40 41 // WithChildren implements the Node interface. 42 func (d *Distinct) WithChildren(children ...sql.Node) (sql.Node, error) { 43 if len(children) != 1 { 44 return nil, sql.ErrInvalidChildrenNumber.New(d, len(children), 1) 45 } 46 47 return NewDistinct(children[0]), nil 48 } 49 50 // CheckPrivileges implements the interface sql.Node. 51 func (d *Distinct) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 52 return d.Child.CheckPrivileges(ctx, opChecker) 53 } 54 55 func (d *Distinct) IsReadOnly() bool { 56 return d.Child.IsReadOnly() 57 } 58 59 // CollationCoercibility implements the interface sql.CollationCoercible. 60 func (d *Distinct) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 61 return sql.GetCoercibility(ctx, d.Child) 62 } 63 64 // Describe implements sql.Describable 65 func (d Distinct) Describe(options sql.DescribeOptions) string { 66 p := sql.NewTreePrinter() 67 _ = p.WriteNode("Distinct") 68 _ = p.WriteChildren(sql.Describe(d.Child, options)) 69 return p.String() 70 } 71 72 // String implements fmt.Stringer 73 func (d Distinct) String() string { 74 p := sql.NewTreePrinter() 75 _ = p.WriteNode("Distinct") 76 _ = p.WriteChildren(d.Child.String()) 77 return p.String() 78 } 79 80 // DebugString implements sql.DebugStringer 81 func (d Distinct) DebugString() string { 82 p := sql.NewTreePrinter() 83 _ = p.WriteNode("Distinct") 84 _ = p.WriteChildren(sql.DebugString(d.Child)) 85 return p.String() 86 } 87 88 // OrderedDistinct is a Distinct node optimized for sorted row sets. 89 // It's 2 orders of magnitude faster and uses 2 orders of magnitude less memory. 90 type OrderedDistinct struct { 91 UnaryNode 92 } 93 94 var _ sql.Node = (*OrderedDistinct)(nil) 95 var _ sql.CollationCoercible = (*OrderedDistinct)(nil) 96 97 // NewOrderedDistinct creates a new OrderedDistinct node. 98 func NewOrderedDistinct(child sql.Node) *OrderedDistinct { 99 if d, ok := child.(*OrderedDistinct); ok { 100 child = d.Child 101 } 102 return &OrderedDistinct{ 103 UnaryNode: UnaryNode{Child: child}, 104 } 105 } 106 107 // Resolved implements the Resolvable interface. 108 func (d *OrderedDistinct) Resolved() bool { 109 return d.UnaryNode.Child.Resolved() 110 } 111 112 // WithChildren implements the Node interface. 113 func (d *OrderedDistinct) WithChildren(children ...sql.Node) (sql.Node, error) { 114 if len(children) != 1 { 115 return nil, sql.ErrInvalidChildrenNumber.New(d, len(children), 1) 116 } 117 118 return NewOrderedDistinct(children[0]), nil 119 } 120 121 // CheckPrivileges implements the interface sql.Node. 122 func (d *OrderedDistinct) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool { 123 return d.Child.CheckPrivileges(ctx, opChecker) 124 } 125 126 func (d *OrderedDistinct) IsReadOnly() bool { 127 return d.Child.IsReadOnly() 128 } 129 130 // CollationCoercibility implements the interface sql.CollationCoercible. 131 func (d *OrderedDistinct) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 132 return sql.GetCoercibility(ctx, d.Child) 133 } 134 135 func (d OrderedDistinct) String() string { 136 p := sql.NewTreePrinter() 137 _ = p.WriteNode("OrderedDistinct") 138 _ = p.WriteChildren(d.Child.String()) 139 return p.String() 140 } 141 142 func (d OrderedDistinct) DebugString() string { 143 p := sql.NewTreePrinter() 144 _ = p.WriteNode("OrderedDistinct") 145 _ = p.WriteChildren(sql.DebugString(d.Child)) 146 return p.String() 147 }