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 }