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  }