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  }