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 }