github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/sqle/sqldelete_test.go (about)

     1  // Copyright 2019 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  	"testing"
    20  
    21  	sql "github.com/dolthub/go-mysql-server/sql"
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  
    25  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    26  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdocs"
    27  	"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
    28  	"github.com/dolthub/dolt/go/libraries/doltcore/schema"
    29  	. "github.com/dolthub/dolt/go/libraries/doltcore/sql/sqltestutil"
    30  	"github.com/dolthub/dolt/go/libraries/doltcore/sqle/dtables"
    31  	"github.com/dolthub/dolt/go/store/types"
    32  )
    33  
    34  // Set to the name of a single test to run just that test, useful for debugging
    35  const singleDeleteQueryTest = "" //"Natural join with join clause"
    36  
    37  // Structure for a test of a delete query
    38  type DeleteTest struct {
    39  	// The name of this test. Names should be unique and descriptive.
    40  	Name string
    41  	// The delete query to run
    42  	DeleteQuery string
    43  	// The select query to run to verify the results
    44  	SelectQuery string
    45  	// The schema of the result of the query, nil if an error is expected
    46  	ExpectedSchema schema.Schema
    47  	// The rows this query should return, nil if an error is expected
    48  	ExpectedRows []sql.Row
    49  	// An expected error string
    50  	ExpectedErr string
    51  	// Setup logic to run before executing this test, after initial tables have been created and populated
    52  	AdditionalSetup SetupFn
    53  }
    54  
    55  // BasicDeleteTests cover basic delete statement features and error handling
    56  var BasicDeleteTests = []DeleteTest{
    57  	{
    58  		Name:           "delete everything",
    59  		DeleteQuery:    "delete from people",
    60  		SelectQuery:    "select * from people",
    61  		ExpectedRows:   ToSqlRows(PeopleTestSchema),
    62  		ExpectedSchema: CompressSchema(PeopleTestSchema),
    63  	},
    64  	{
    65  		Name:           "delete where id equals",
    66  		DeleteQuery:    "delete from people where id = 2",
    67  		SelectQuery:    "select * from people",
    68  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Homer, Marge, Lisa, Moe, Barney),
    69  		ExpectedSchema: CompressSchema(PeopleTestSchema),
    70  	},
    71  	{
    72  		Name:           "delete where id less than",
    73  		DeleteQuery:    "delete from people where id < 3",
    74  		SelectQuery:    "select * from people",
    75  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Lisa, Moe, Barney),
    76  		ExpectedSchema: CompressSchema(PeopleTestSchema),
    77  	},
    78  	{
    79  		Name:           "delete where id greater than",
    80  		DeleteQuery:    "delete from people where id > 3",
    81  		SelectQuery:    "select * from people",
    82  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Homer, Marge, Bart, Lisa),
    83  		ExpectedSchema: CompressSchema(PeopleTestSchema),
    84  	},
    85  	{
    86  		Name:           "delete where id less than or equal",
    87  		DeleteQuery:    "delete from people where id <= 3",
    88  		SelectQuery:    "select * from people",
    89  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Moe, Barney),
    90  		ExpectedSchema: CompressSchema(PeopleTestSchema),
    91  	},
    92  	{
    93  		Name:           "delete where id greater than or equal",
    94  		DeleteQuery:    "delete from people where id >= 3",
    95  		SelectQuery:    "select * from people",
    96  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Homer, Marge, Bart),
    97  		ExpectedSchema: CompressSchema(PeopleTestSchema),
    98  	},
    99  	{
   100  		Name:           "delete where id equals nothing",
   101  		DeleteQuery:    "delete from people where id = 9999",
   102  		SelectQuery:    "select * from people",
   103  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Homer, Marge, Bart, Lisa, Moe, Barney),
   104  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   105  	},
   106  	{
   107  		Name:           "delete where last_name matches some =",
   108  		DeleteQuery:    "delete from people where last_name = 'Simpson'",
   109  		SelectQuery:    "select * from people",
   110  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Moe, Barney),
   111  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   112  	},
   113  	{
   114  		Name:           "delete where last_name matches some <>",
   115  		DeleteQuery:    "delete from people where last_name <> 'Simpson'",
   116  		SelectQuery:    "select * from people",
   117  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Homer, Marge, Bart, Lisa),
   118  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   119  	},
   120  	{
   121  		Name:           "delete where last_name matches some like",
   122  		DeleteQuery:    "delete from people where last_name like '%pson'",
   123  		SelectQuery:    "select * from people",
   124  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Moe, Barney),
   125  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   126  	},
   127  	{
   128  		Name:           "delete order by",
   129  		DeleteQuery:    "delete from people order by id",
   130  		SelectQuery:    "select * from people",
   131  		ExpectedRows:   ToSqlRows(PeopleTestSchema),
   132  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   133  	},
   134  	{
   135  		Name:           "delete order by asc limit",
   136  		DeleteQuery:    "delete from people order by id asc limit 3",
   137  		SelectQuery:    "select * from people",
   138  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Lisa, Moe, Barney),
   139  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   140  	},
   141  	{
   142  		Name:           "delete order by desc limit",
   143  		DeleteQuery:    "delete from people order by id desc limit 3",
   144  		SelectQuery:    "select * from people",
   145  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Homer, Marge, Bart),
   146  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   147  	},
   148  	{
   149  		Name:           "delete order by desc limit",
   150  		DeleteQuery:    "delete from people order by id desc limit 3 offset 1",
   151  		SelectQuery:    "select * from people",
   152  		ExpectedRows:   ToSqlRows(PeopleTestSchema, Homer, Marge, Barney),
   153  		ExpectedSchema: CompressSchema(PeopleTestSchema),
   154  	},
   155  	{
   156  		Name:        "delete invalid table",
   157  		DeleteQuery: "delete from nobody",
   158  		ExpectedErr: "invalid table",
   159  	},
   160  	{
   161  		Name:        "delete invalid column",
   162  		DeleteQuery: "delete from people where z = 'dne'",
   163  		ExpectedErr: "invalid column",
   164  	},
   165  	{
   166  		Name:        "delete negative limit",
   167  		DeleteQuery: "delete from people limit -1",
   168  		ExpectedErr: "invalid limit number",
   169  	},
   170  	{
   171  		Name:        "delete negative offset",
   172  		DeleteQuery: "delete from people limit 1 offset -1",
   173  		ExpectedErr: "invalid limit number",
   174  	},
   175  }
   176  
   177  func TestExecuteDelete(t *testing.T) {
   178  	for _, test := range BasicDeleteTests {
   179  		t.Run(test.Name, func(t *testing.T) {
   180  			testDeleteQuery(t, test)
   181  		})
   182  	}
   183  }
   184  
   185  func TestExecuteDeleteSystemTables(t *testing.T) {
   186  	for _, test := range systemTableDeleteTests {
   187  		t.Run(test.Name, func(t *testing.T) {
   188  			testDeleteQuery(t, test)
   189  		})
   190  	}
   191  }
   192  
   193  var systemTableDeleteTests = []DeleteTest{
   194  	{
   195  		Name: "delete dolt_docs",
   196  		AdditionalSetup: CreateTableFn("dolt_docs",
   197  			doltdocs.Schema,
   198  			NewRow(types.String("LICENSE.md"), types.String("A license"))),
   199  		DeleteQuery: "delete from dolt_docs",
   200  		ExpectedErr: "cannot delete from table",
   201  	},
   202  	{
   203  		Name: "delete dolt_query_catalog",
   204  		AdditionalSetup: CreateTableFn(doltdb.DoltQueryCatalogTableName,
   205  			dtables.DoltQueryCatalogSchema,
   206  			NewRow(types.String("abc123"), types.Uint(1), types.String("example"), types.String("select 2+2 from dual"), types.String("description"))),
   207  		DeleteQuery:    "delete from dolt_query_catalog",
   208  		SelectQuery:    "select * from dolt_query_catalog",
   209  		ExpectedRows:   ToSqlRows(dtables.DoltQueryCatalogSchema),
   210  		ExpectedSchema: CompressSchema(dtables.DoltQueryCatalogSchema),
   211  	},
   212  	{
   213  		Name: "delete dolt_schemas",
   214  		AdditionalSetup: CreateTableFn(doltdb.SchemasTableName,
   215  			schemasTableDoltSchema(),
   216  			NewRowWithPks([]types.Value{types.String("view"), types.String("name")}, types.String("select 2+2 from dual"))),
   217  		DeleteQuery:    "delete from dolt_schemas",
   218  		SelectQuery:    "select * from dolt_schemas",
   219  		ExpectedRows:   ToSqlRows(dtables.DoltQueryCatalogSchema),
   220  		ExpectedSchema: schemasTableDoltSchema(),
   221  	},
   222  }
   223  
   224  // Tests the given query on a freshly created dataset, asserting that the result has the given schema and rows. If
   225  // expectedErr is set, asserts instead that the execution returns an error that matches.
   226  func testDeleteQuery(t *testing.T, test DeleteTest) {
   227  	if (test.ExpectedRows == nil) != (test.ExpectedSchema == nil) {
   228  		require.Fail(t, "Incorrect test setup: schema and rows must both be provided if one is")
   229  	}
   230  
   231  	if len(singleDeleteQueryTest) > 0 && test.Name != singleDeleteQueryTest {
   232  		t.Skip("Skipping tests until " + singleDeleteQueryTest)
   233  	}
   234  
   235  	dEnv := dtestutils.CreateTestEnv()
   236  	CreateTestDatabase(dEnv, t)
   237  
   238  	if test.AdditionalSetup != nil {
   239  		test.AdditionalSetup(t, dEnv)
   240  	}
   241  
   242  	var err error
   243  	root, _ := dEnv.WorkingRoot(context.Background())
   244  	root, err = executeModify(context.Background(), dEnv, root, test.DeleteQuery)
   245  	if len(test.ExpectedErr) > 0 {
   246  		require.Error(t, err)
   247  		return
   248  	} else {
   249  		require.NoError(t, err)
   250  	}
   251  
   252  	actualRows, sch, err := executeSelect(context.Background(), dEnv, root, test.SelectQuery)
   253  	require.NoError(t, err)
   254  
   255  	assert.Equal(t, test.ExpectedRows, actualRows)
   256  	assertSchemasEqual(t, mustSqlSchema(test.ExpectedSchema), sch)
   257  }