github.com/dolthub/go-mysql-server@v0.18.0/sql/rowexec/limit_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 "fmt" 19 "io" 20 "reflect" 21 "testing" 22 23 "github.com/stretchr/testify/require" 24 25 "github.com/dolthub/go-mysql-server/memory" 26 "github.com/dolthub/go-mysql-server/sql" 27 "github.com/dolthub/go-mysql-server/sql/expression" 28 "github.com/dolthub/go-mysql-server/sql/plan" 29 "github.com/dolthub/go-mysql-server/sql/types" 30 ) 31 32 var testingTable *memory.Table 33 var testingTableSize int 34 35 func TestLimitPlan(t *testing.T) { 36 require := require.New(t) 37 _, table, _ := getTestingTable(t) 38 39 limitPlan := plan.NewLimit(expression.NewLiteral(0, types.Int8), plan.NewResolvedTable(table, nil, nil)) 40 require.Equal(1, len(limitPlan.Children())) 41 42 iterator, err := getLimitedIterator(t, 1) 43 require.NoError(err) 44 require.NotNil(iterator) 45 } 46 47 func TestLimitImplementsNode(t *testing.T) { 48 require := require.New(t) 49 _, table, _ := getTestingTable(t) 50 51 limitPlan := plan.NewLimit(expression.NewLiteral(0, types.Int8), plan.NewResolvedTable(table, nil, nil)) 52 childSchema := table.Schema() 53 nodeSchema := limitPlan.Schema() 54 require.True(reflect.DeepEqual(childSchema, nodeSchema)) 55 require.True(receivesNode(limitPlan)) 56 require.True(limitPlan.Resolved()) 57 } 58 59 func TestLimit0(t *testing.T) { 60 db, _, size := getTestingTable(t) 61 pro := memory.NewDBProvider(db) 62 ctx := newContext(pro) 63 64 testingLimit := 0 65 iterator, _ := getLimitedIterator(t, int64(testingLimit)) 66 testLimitOverflow(t, ctx, iterator, testingLimit, size) 67 } 68 69 func TestLimitLessThanTotal(t *testing.T) { 70 db, _, size := getTestingTable(t) 71 pro := memory.NewDBProvider(db) 72 ctx := newContext(pro) 73 74 testingLimit := size - 1 75 iterator, _ := getLimitedIterator(t, int64(testingLimit)) 76 testLimitOverflow(t, ctx, iterator, testingLimit, size) 77 } 78 79 func TestLimitEqualThanTotal(t *testing.T) { 80 db, _, size := getTestingTable(t) 81 pro := memory.NewDBProvider(db) 82 ctx := newContext(pro) 83 84 testingLimit := size 85 iterator, _ := getLimitedIterator(t, int64(testingLimit)) 86 testLimitOverflow(t, ctx, iterator, testingLimit, size) 87 } 88 89 func TestLimitGreaterThanTotal(t *testing.T) { 90 db, _, size := getTestingTable(t) 91 pro := memory.NewDBProvider(db) 92 ctx := newContext(pro) 93 94 testingLimit := size + 1 95 iterator, _ := getLimitedIterator(t, int64(testingLimit)) 96 testLimitOverflow(t, ctx, iterator, testingLimit, size) 97 } 98 99 func testLimitOverflow(t *testing.T, ctx *sql.Context, iter sql.RowIter, limit int, dataSize int) { 100 require := require.New(t) 101 for i := 0; i < limit+1; i++ { 102 row, err := iter.Next(ctx) 103 hint := fmt.Sprintf("Iter#%d : size.%d : limit.%d", i, dataSize, limit) 104 if i >= limit || i >= dataSize { 105 require.Nil(row, hint) 106 require.Equal(io.EOF, err, hint) 107 } else { 108 require.NotNil(row, hint) 109 require.Nil(err, hint) 110 } 111 } 112 } 113 114 func getTestingTable(t *testing.T) (*memory.Database, *memory.Table, int) { 115 t.Helper() 116 if &testingTable == nil { 117 return nil, testingTable, testingTableSize 118 } 119 120 db := memory.NewDatabase("test") 121 childSchema := sql.NewPrimaryKeySchema(sql.Schema{ 122 {Name: "col1", Type: types.Text}, 123 }) 124 testingTable = memory.NewTable(db, "test", childSchema, nil) 125 126 rows := []sql.Row{ 127 sql.NewRow("11a"), 128 sql.NewRow("22a"), 129 sql.NewRow("33a"), 130 } 131 132 pro := memory.NewDBProvider(db) 133 ctx := newContext(pro) 134 135 for _, r := range rows { 136 require.NoError(t, testingTable.Insert(ctx, r)) 137 } 138 139 return db, testingTable, len(rows) 140 } 141 142 func getLimitedIterator(t *testing.T, limitSize int64) (sql.RowIter, error) { 143 t.Helper() 144 145 db, table, _ := getTestingTable(t) 146 pro := memory.NewDBProvider(db) 147 ctx := newContext(pro) 148 149 limitPlan := plan.NewLimit(expression.NewLiteral(limitSize, types.Int64), plan.NewResolvedTable(table, nil, nil)) 150 return DefaultBuilder.Build(ctx, limitPlan, nil) 151 } 152 153 func receivesNode(n sql.Node) bool { 154 return true 155 }