github.com/dolthub/go-mysql-server@v0.18.0/sql/rowexec/distinct_test.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 rowexec 16 17 import ( 18 "io" 19 "testing" 20 21 "github.com/stretchr/testify/require" 22 23 "github.com/dolthub/go-mysql-server/memory" 24 "github.com/dolthub/go-mysql-server/sql" 25 "github.com/dolthub/go-mysql-server/sql/expression" 26 "github.com/dolthub/go-mysql-server/sql/plan" 27 "github.com/dolthub/go-mysql-server/sql/types" 28 ) 29 30 func TestDistinct(t *testing.T) { 31 require := require.New(t) 32 33 db := memory.NewDatabase("test") 34 pro := memory.NewDBProvider(db) 35 ctx := newContext(pro) 36 37 childSchema := sql.NewPrimaryKeySchema(sql.Schema{ 38 {Name: "name", Type: types.Text, Nullable: true}, 39 {Name: "email", Type: types.Text, Nullable: true}, 40 }) 41 child := memory.NewTable(db.BaseDatabase, "test", childSchema, nil) 42 43 rows := []sql.Row{ 44 sql.NewRow("john", "john@doe.com"), 45 sql.NewRow("jane", "jane@doe.com"), 46 sql.NewRow("john", "johnx@doe.com"), 47 sql.NewRow("martha", "marthax@doe.com"), 48 sql.NewRow("martha", "martha@doe.com"), 49 } 50 51 for _, r := range rows { 52 require.NoError(child.Insert(ctx, r)) 53 } 54 55 p := plan.NewProject([]sql.Expression{ 56 expression.NewGetField(0, types.Text, "name", true), 57 }, plan.NewResolvedTable(child, nil, nil)) 58 d := plan.NewDistinct(p) 59 60 iter, err := DefaultBuilder.Build(ctx, d, nil) 61 require.NoError(err) 62 require.NotNil(iter) 63 64 var results []string 65 for { 66 row, err := iter.Next(ctx) 67 if err == io.EOF { 68 break 69 } 70 71 require.NoError(err) 72 result, ok := row[0].(string) 73 require.True(ok, "first row column should be string, but is %T", row[0]) 74 results = append(results, result) 75 } 76 77 require.Equal([]string{"john", "jane", "martha"}, results) 78 } 79 80 func TestOrderedDistinct(t *testing.T) { 81 require := require.New(t) 82 83 db := memory.NewDatabase("test") 84 pro := memory.NewDBProvider(db) 85 ctx := newContext(pro) 86 87 childSchema := sql.NewPrimaryKeySchema(sql.Schema{ 88 {Name: "name", Type: types.Text, Nullable: true}, 89 {Name: "email", Type: types.Text, Nullable: true}, 90 }) 91 child := memory.NewTable(db.BaseDatabase, "test", childSchema, nil) 92 93 rows := []sql.Row{ 94 sql.NewRow("jane", "jane@doe.com"), 95 sql.NewRow("john", "john@doe.com"), 96 sql.NewRow("john", "johnx@doe.com"), 97 sql.NewRow("martha", "martha@doe.com"), 98 sql.NewRow("martha", "marthax@doe.com"), 99 } 100 101 for _, r := range rows { 102 require.NoError(child.Insert(ctx, r)) 103 } 104 105 p := plan.NewProject([]sql.Expression{ 106 expression.NewGetField(0, types.Text, "name", true), 107 }, plan.NewResolvedTable(child, nil, nil)) 108 d := plan.NewOrderedDistinct(p) 109 110 iter, err := DefaultBuilder.Build(ctx, d, nil) 111 require.NoError(err) 112 require.NotNil(iter) 113 114 var results []string 115 for { 116 row, err := iter.Next(ctx) 117 if err == io.EOF { 118 break 119 } 120 121 require.NoError(err) 122 result, ok := row[0].(string) 123 require.True(ok, "first row column should be string, but is %T", row[0]) 124 results = append(results, result) 125 } 126 127 require.Equal([]string{"jane", "john", "martha"}, results) 128 } 129 130 func BenchmarkDistinct(b *testing.B) { 131 require := require.New(b) 132 ctx := sql.NewEmptyContext() 133 134 for i := 0; i < b.N; i++ { 135 p := plan.NewProject([]sql.Expression{ 136 expression.NewGetField(0, types.Text, "strfield", true), 137 expression.NewGetField(1, types.Float64, "floatfield", true), 138 expression.NewGetField(2, types.Boolean, "boolfield", false), 139 expression.NewGetField(3, types.Int32, "intfield", false), 140 expression.NewGetField(4, types.Int64, "bigintfield", false), 141 expression.NewGetField(5, types.Blob, "blobfield", false), 142 }, plan.NewResolvedTable(benchtable, nil, nil)) 143 d := plan.NewDistinct(p) 144 145 iter, err := DefaultBuilder.Build(ctx, d, nil) 146 require.NoError(err) 147 require.NotNil(iter) 148 149 var rows int 150 for { 151 _, err := iter.Next(ctx) 152 if err == io.EOF { 153 break 154 } 155 156 require.NoError(err) 157 rows++ 158 } 159 require.Equal(100, rows) 160 } 161 } 162 163 func BenchmarkOrderedDistinct(b *testing.B) { 164 require := require.New(b) 165 ctx := sql.NewEmptyContext() 166 167 for i := 0; i < b.N; i++ { 168 p := plan.NewProject([]sql.Expression{ 169 expression.NewGetField(0, types.Text, "strfield", true), 170 expression.NewGetField(1, types.Float64, "floatfield", true), 171 expression.NewGetField(2, types.Boolean, "boolfield", false), 172 expression.NewGetField(3, types.Int32, "intfield", false), 173 expression.NewGetField(4, types.Int64, "bigintfield", false), 174 expression.NewGetField(5, types.Blob, "blobfield", false), 175 }, plan.NewResolvedTable(benchtable, nil, nil)) 176 d := plan.NewOrderedDistinct(p) 177 178 iter, err := DefaultBuilder.Build(ctx, d, nil) 179 require.NoError(err) 180 require.NotNil(iter) 181 182 var rows int 183 for { 184 _, err := iter.Next(ctx) 185 if err == io.EOF { 186 break 187 } 188 189 require.NoError(err) 190 rows++ 191 } 192 require.Equal(100, rows) 193 } 194 }