github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/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/doltdb/durable" 28 "github.com/dolthub/dolt/go/libraries/doltcore/env" 29 "github.com/dolthub/dolt/go/libraries/doltcore/row" 30 "github.com/dolthub/dolt/go/libraries/doltcore/schema" 31 "github.com/dolthub/dolt/go/libraries/doltcore/schema/typeinfo" 32 "github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil" 33 "github.com/dolthub/dolt/go/libraries/doltcore/table/editor" 34 ) 35 36 // SetupFunc can be run to perform additional setup work before a test case 37 type SetupFn func(t *testing.T, dEnv *env.DoltEnv) 38 39 // Runs the query given and returns the result. The schema result of the query's execution is currently ignored, and 40 // the targetSchema given is used to prepare all rows. 41 func executeSelect(t *testing.T, ctx context.Context, dEnv *env.DoltEnv, root doltdb.RootValue, query string) ([]sql.Row, sql.Schema, error) { 42 tmpDir, err := dEnv.TempTableFilesDir() 43 require.NoError(t, err) 44 opts := editor.Options{Deaf: dEnv.DbEaFactory(), Tempdir: tmpDir} 45 db, err := NewDatabase(ctx, "dolt", dEnv.DbData(), opts) 46 require.NoError(t, err) 47 48 engine, sqlCtx, err := NewTestEngine(dEnv, ctx, db) 49 if err != nil { 50 return nil, nil, err 51 } 52 53 sch, iter, err := engine.Query(sqlCtx, query) 54 if err != nil { 55 return nil, nil, err 56 } 57 58 sqlRows := make([]sql.Row, 0) 59 var r sql.Row 60 for r, err = iter.Next(sqlCtx); err == nil; r, err = iter.Next(sqlCtx) { 61 sqlRows = append(sqlRows, r) 62 } 63 64 if err != io.EOF { 65 return nil, nil, err 66 } 67 68 return sqlRows, sch, nil 69 } 70 71 // Runs the query given and returns the error (if any). 72 func executeModify(t *testing.T, ctx context.Context, dEnv *env.DoltEnv, root doltdb.RootValue, query string) (doltdb.RootValue, error) { 73 tmpDir, err := dEnv.TempTableFilesDir() 74 require.NoError(t, err) 75 opts := editor.Options{Deaf: dEnv.DbEaFactory(), Tempdir: tmpDir} 76 db, err := NewDatabase(ctx, "dolt", dEnv.DbData(), opts) 77 require.NoError(t, err) 78 79 engine, sqlCtx, err := NewTestEngine(dEnv, ctx, db) 80 81 if err != nil { 82 return nil, err 83 } 84 85 _, iter, err := engine.Query(sqlCtx, query) 86 if err != nil { 87 return nil, err 88 } 89 90 for { 91 _, err := iter.Next(sqlCtx) 92 if err == io.EOF { 93 break 94 } 95 if err != nil { 96 return nil, err 97 } 98 } 99 100 err = iter.Close(sqlCtx) 101 if err != nil { 102 return nil, err 103 } 104 105 return db.GetRoot(sqlCtx) 106 } 107 108 func schemaNewColumn(t *testing.T, name string, tag uint64, sqlType sql.Type, partOfPK bool, constraints ...schema.ColConstraint) schema.Column { 109 return schemaNewColumnWDefVal(t, name, tag, sqlType, partOfPK, "", constraints...) 110 } 111 112 func schemaNewColumnWDefVal(t *testing.T, name string, tag uint64, sqlType sql.Type, partOfPK bool, defaultVal string, constraints ...schema.ColConstraint) schema.Column { 113 typeInfo, err := typeinfo.FromSqlType(sqlType) 114 require.NoError(t, err) 115 col, err := schema.NewColumnWithTypeInfo(name, tag, typeInfo, partOfPK, defaultVal, false, "", constraints...) 116 require.NoError(t, err) 117 return col 118 } 119 120 func equalSchemas(t *testing.T, expectedSch schema.Schema, sch schema.Schema) { 121 require.NotNil(t, expectedSch) 122 require.NotNil(t, sch) 123 require.Equal(t, expectedSch.GetAllCols().Size(), sch.GetAllCols().Size()) 124 cols := sch.GetAllCols().GetColumns() 125 for i, expectedCol := range expectedSch.GetAllCols().GetColumns() { 126 col := cols[i] 127 col.Tag = expectedCol.Tag 128 assert.Equal(t, expectedCol, col) 129 } 130 } 131 132 // Returns the dolt schema given as a sql.Schema, or panics. 133 func mustSqlSchema(sch schema.Schema) sql.Schema { 134 sqlSchema, err := sqlutil.FromDoltSchema("", "", sch) 135 if err != nil { 136 panic(err) 137 } 138 139 return sqlSchema.Schema 140 } 141 142 // Convenience function to return a row or panic on an error 143 func mustRow(r row.Row, err error) row.Row { 144 if err != nil { 145 panic(err) 146 } 147 148 return r 149 } 150 151 // Returns the schema given reduced to just its column names and types. 152 func reduceSchema(sch sql.Schema) sql.Schema { 153 newSch := make(sql.Schema, len(sch)) 154 for i, column := range sch { 155 newSch[i] = &sql.Column{ 156 Name: column.Name, 157 Type: column.Type, 158 } 159 } 160 return newSch 161 } 162 163 // Asserts that the two schemas are equal, comparing only names and types of columns. 164 func assertSchemasEqual(t *testing.T, expected, actual sql.Schema) { 165 assert.Equal(t, reduceSchema(expected), reduceSchema(actual)) 166 } 167 168 // CreateTableFn returns a SetupFunc that creates a table with the rows given 169 // todo(andy): replace with ExecuteSetupSQL 170 func CreateTableFn(tableName string, tableSchema schema.Schema, queries string) SetupFn { 171 return func(t *testing.T, dEnv *env.DoltEnv) { 172 CreateTestTable(t, dEnv, tableName, tableSchema, queries) 173 } 174 } 175 176 // CreateTestTable creates a new test table with the name, schema, and rows given. 177 func CreateTestTable(t *testing.T, dEnv *env.DoltEnv, tableName string, sch schema.Schema, queries string) { 178 ctx := context.Background() 179 root, err := dEnv.WorkingRoot(ctx) 180 require.NoError(t, err) 181 vrw := dEnv.DoltDB.ValueReadWriter() 182 ns := dEnv.DoltDB.NodeStore() 183 184 rows, err := durable.NewEmptyIndex(ctx, vrw, ns, sch) 185 require.NoError(t, err) 186 tbl, err := doltdb.NewTable(ctx, vrw, ns, sch, rows, nil, nil) 187 require.NoError(t, err) 188 root, err = root.PutTable(ctx, doltdb.TableName{Name: tableName}, tbl) 189 require.NoError(t, err) 190 err = dEnv.UpdateWorkingRoot(ctx, root) 191 require.NoError(t, err) 192 root, err = ExecuteSql(dEnv, root, queries) 193 require.NoError(t, err) 194 err = dEnv.UpdateWorkingRoot(ctx, root) 195 require.NoError(t, err) 196 } 197 198 func ExecuteSetupSQL(ctx context.Context, queries string) SetupFn { 199 return func(t *testing.T, dEnv *env.DoltEnv) { 200 root, err := dEnv.WorkingRoot(ctx) 201 require.NoError(t, err) 202 root, err = ExecuteSql(dEnv, root, queries) 203 require.NoError(t, err) 204 err = dEnv.UpdateWorkingRoot(ctx, root) 205 require.NoError(t, err) 206 } 207 }