github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/sqle/common_test.go (about) 1 // Copyright 2020 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 sqle 16 17 import ( 18 "context" 19 "io" 20 "testing" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 26 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 27 "github.com/dolthub/dolt/go/libraries/doltcore/dtestutils" 28 "github.com/dolthub/dolt/go/libraries/doltcore/env" 29 "github.com/dolthub/dolt/go/libraries/doltcore/envtestutils" 30 "github.com/dolthub/dolt/go/libraries/doltcore/row" 31 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 32 "github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo" 33 "github.com/dolthub/dolt/go/libraries/doltcore/sql/sqltestutil" 34 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil" 35 "github.com/dolthub/dolt/go/store/types" 36 ) 37 38 // SetupFunc can be run to perform additional setup work before a test case 39 type SetupFn func(t *testing.T, dEnv *env.DoltEnv) 40 41 // Runs the query given and returns the result. The schema result of the query's execution is currently ignored, and 42 // the targetSchema given is used to prepare all rows. 43 func executeSelect(ctx context.Context, dEnv *env.DoltEnv, root *doltdb.RootValue, query string) ([]sql.Row, sql.Schema, error) { 44 var err error 45 db := NewDatabase("dolt", dEnv.DbData()) 46 engine, sqlCtx, err := NewTestEngine(ctx, db, root) 47 if err != nil { 48 return nil, nil, err 49 } 50 51 sch, iter, err := engine.Query(sqlCtx, query) 52 if err != nil { 53 return nil, nil, err 54 } 55 56 sqlRows := make([]sql.Row, 0) 57 var r sql.Row 58 for r, err = iter.Next(); err == nil; r, err = iter.Next() { 59 sqlRows = append(sqlRows, r) 60 } 61 62 if err != io.EOF { 63 return nil, nil, err 64 } 65 66 return sqlRows, sch, nil 67 } 68 69 // Runs the query given and returns the error (if any). 70 func executeModify(ctx context.Context, dEnv *env.DoltEnv, root *doltdb.RootValue, query string) (*doltdb.RootValue, error) { 71 db := NewDatabase("dolt", dEnv.DbData()) 72 engine, sqlCtx, err := NewTestEngine(ctx, db, root) 73 74 if err != nil { 75 return nil, err 76 } 77 78 _, iter, err := engine.Query(sqlCtx, query) 79 if err != nil { 80 return nil, err 81 } 82 83 for { 84 _, err := iter.Next() 85 if err == io.EOF { 86 break 87 } 88 if err != nil { 89 return nil, err 90 } 91 } 92 93 err = iter.Close(sqlCtx) 94 if err != nil { 95 return nil, err 96 } 97 98 return db.GetRoot(sqlCtx) 99 } 100 101 // Returns the dolt rows given transformed to sql rows. Exactly the columns in the schema provided are present in the 102 // final output rows, even if the input rows contain different columns. The tag numbers for columns in the row and 103 // schema given must match. 104 func ToSqlRows(sch schema.Schema, rs ...row.Row) []sql.Row { 105 sqlRows := make([]sql.Row, len(rs)) 106 compressedSch := CompressSchema(sch) 107 for i := range rs { 108 sqlRows[i], _ = sqlutil.DoltRowToSqlRow(CompressRow(sch, rs[i]), compressedSch) 109 } 110 return sqlRows 111 } 112 113 // SubsetSchema returns a schema that is a subset of the schema given, with keys and constraints removed. Column names 114 // must be verified before subsetting. Unrecognized column names will cause a panic. 115 func SubsetSchema(sch schema.Schema, colNames ...string) schema.Schema { 116 srcColls := sch.GetAllCols() 117 118 var cols []schema.Column 119 for _, name := range colNames { 120 if col, ok := srcColls.GetByName(name); !ok { 121 panic("Unrecognized name " + name) 122 } else { 123 cols = append(cols, col) 124 } 125 } 126 colColl := schema.NewColCollection(cols...) 127 return schema.UnkeyedSchemaFromCols(colColl) 128 } 129 130 func schemaNewColumn(t *testing.T, name string, tag uint64, sqlType sql.Type, partOfPK bool, constraints ...schema.ColConstraint) schema.Column { 131 return schemaNewColumnWDefVal(t, name, tag, sqlType, partOfPK, "", constraints...) 132 } 133 134 func schemaNewColumnWDefVal(t *testing.T, name string, tag uint64, sqlType sql.Type, partOfPK bool, defaultVal string, constraints ...schema.ColConstraint) schema.Column { 135 typeInfo, err := typeinfo.FromSqlType(sqlType) 136 require.NoError(t, err) 137 col, err := schema.NewColumnWithTypeInfo(name, tag, typeInfo, partOfPK, defaultVal, false, "", constraints...) 138 require.NoError(t, err) 139 return col 140 } 141 142 func equalSchemas(t *testing.T, expectedSch schema.Schema, sch schema.Schema) { 143 require.NotNil(t, expectedSch) 144 require.NotNil(t, sch) 145 require.Equal(t, expectedSch.GetAllCols().Size(), sch.GetAllCols().Size()) 146 cols := sch.GetAllCols().GetColumns() 147 for i, expectedCol := range expectedSch.GetAllCols().GetColumns() { 148 col := cols[i] 149 col.Tag = expectedCol.Tag 150 assert.Equal(t, expectedCol, col) 151 } 152 } 153 154 // TODO: this shouldn't be here 155 func CreateWorkingRootUpdate() map[string]envtestutils.TableUpdate { 156 return map[string]envtestutils.TableUpdate{ 157 sqltestutil.TableWithHistoryName: { 158 RowUpdates: []row.Row{ 159 mustRow(row.New(types.Format_Default, sqltestutil.ReaddAgeAt5HistSch, row.TaggedValues{ 160 0: types.Int(6), 1: types.String("Katie"), 2: types.String("McCulloch"), 161 })), 162 }, 163 }, 164 } 165 } 166 167 // Returns the dolt schema given as a sql.Schema, or panics. 168 func mustSqlSchema(sch schema.Schema) sql.Schema { 169 sqlSchema, err := sqlutil.FromDoltSchema("", sch) 170 if err != nil { 171 panic(err) 172 } 173 174 return sqlSchema 175 } 176 177 // Convenience function to return a row or panic on an error 178 func mustRow(r row.Row, err error) row.Row { 179 if err != nil { 180 panic(err) 181 } 182 183 return r 184 } 185 186 // Returns the schema given reduced to just its column names and types. 187 func reduceSchema(sch sql.Schema) sql.Schema { 188 newSch := make(sql.Schema, len(sch)) 189 for i, column := range sch { 190 newSch[i] = &sql.Column{ 191 Name: column.Name, 192 Type: column.Type, 193 } 194 } 195 return newSch 196 } 197 198 // Asserts that the two schemas are equal, comparing only names and types of columns. 199 func assertSchemasEqual(t *testing.T, expected, actual sql.Schema) { 200 assert.Equal(t, reduceSchema(expected), reduceSchema(actual)) 201 } 202 203 // CreateTableFn returns a SetupFunc that creates a table with the rows given 204 func CreateTableFn(tableName string, tableSchema schema.Schema, initialRows ...row.Row) SetupFn { 205 return func(t *testing.T, dEnv *env.DoltEnv) { 206 dtestutils.CreateTestTable(t, dEnv, tableName, tableSchema, initialRows...) 207 } 208 } 209 210 // CreateTableWithRowsFn returns a SetupFunc that creates a table with the rows given, creating the rows on the fly 211 // from Value types conforming to the schema given. 212 func CreateTableWithRowsFn(tableName string, tableSchema schema.Schema, initialRows ...[]types.Value) SetupFn { 213 return func(t *testing.T, dEnv *env.DoltEnv) { 214 rows := make([]row.Row, len(initialRows)) 215 for i, r := range initialRows { 216 rows[i] = NewRowWithSchema(tableSchema, r...) 217 } 218 dtestutils.CreateTestTable(t, dEnv, tableName, tableSchema, rows...) 219 } 220 } 221 222 // Compose takes an arbitrary number of SetupFns and composes them into a single func which executes all funcs given. 223 func Compose(fns ...SetupFn) SetupFn { 224 return func(t *testing.T, dEnv *env.DoltEnv) { 225 for _, f := range fns { 226 f(t, dEnv) 227 } 228 } 229 }