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