github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/load_queries.go (about) 1 // Copyright 2021 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 queries 16 17 import ( 18 "fmt" 19 "time" 20 21 "github.com/dolthub/go-mysql-server/sql" 22 ) 23 24 var LoadDataScripts = []ScriptTest{ 25 { 26 Name: "Basic load data with enclosed values.", 27 SetUpScript: []string{ 28 "create table loadtable(pk int primary key)", 29 "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"'", 30 }, 31 Assertions: []ScriptTestAssertion{ 32 { 33 Query: "select * from loadtable", 34 Expected: []sql.Row{{int8(1)}, {int8(2)}, {int8(3)}, {int8(4)}}, 35 }, 36 }, 37 }, 38 { 39 Name: "Basic load data check error", 40 SetUpScript: []string{ 41 "create table loadtable(pk int primary key, check (pk > 1))", 42 }, 43 Assertions: []ScriptTestAssertion{ 44 { 45 Query: "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"'", 46 ExpectedErrStr: "Check constraint \"loadtable_chk_1\" violated", 47 }, 48 }, 49 }, 50 { 51 Name: "Load data with csv", 52 SetUpScript: []string{ 53 "create table loadtable(pk int primary key, c1 longtext)", 54 "LOAD DATA INFILE './testdata/test2.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' IGNORE 1 LINES", 55 }, 56 Assertions: []ScriptTestAssertion{ 57 { 58 Query: "select * from loadtable", 59 Expected: []sql.Row{{int8(1), "hi"}, {int8(2), "hello"}}, 60 }, 61 }, 62 }, 63 { 64 Name: "Load data with csv but use IGNORE ROWS syntax", 65 SetUpScript: []string{ 66 "create table loadtable(pk int primary key, c1 longtext)", 67 "LOAD DATA INFILE './testdata/test2.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' IGNORE 1 ROWS", 68 }, 69 Assertions: []ScriptTestAssertion{ 70 { 71 Query: "select * from loadtable", 72 Expected: []sql.Row{{int8(1), "hi"}, {int8(2), "hello"}}, 73 }, 74 }, 75 }, 76 { 77 Name: "Load data with csv with prefix.", 78 SetUpScript: []string{ 79 "create table loadtable(pk longtext, c1 int)", 80 "LOAD DATA INFILE './testdata/test3.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' LINES STARTING BY 'xxx' IGNORE 1 LINES (`pk`, `c1`)", 81 }, 82 Assertions: []ScriptTestAssertion{ 83 { 84 Query: "select * from loadtable", 85 Expected: []sql.Row{{"\"abc\"", int8(1)}, {"\"def\"", int8(2)}, {"\"hello\"", nil}}, 86 }, 87 }, 88 }, 89 { 90 Name: "LOAD DATA with all columns reordered in projection", 91 SetUpScript: []string{ 92 "create table loadtable(pk longtext, c1 int)", 93 "LOAD DATA INFILE './testdata/test3backwards.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' LINES STARTING BY 'xxx' IGNORE 1 LINES (`c1`, `pk`)", 94 }, 95 Assertions: []ScriptTestAssertion{ 96 { 97 Query: "select * from loadtable", 98 Expected: []sql.Row{{"\"abc\"", int8(1)}, {"\"def\"", int8(2)}, {"\"hello\"", nil}}, 99 }, 100 }, 101 }, 102 { 103 Name: "Table has more columns than import.", 104 SetUpScript: []string{ 105 "create table loadtable(pk int primary key, c1 int)", 106 "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"'", 107 }, 108 Assertions: []ScriptTestAssertion{ 109 { 110 Query: "select * from loadtable ORDER BY pk", 111 Expected: []sql.Row{{1, nil}, {2, nil}, {3, nil}, {4, nil}}, 112 }, 113 }, 114 }, 115 { 116 Name: "LOAD DATA handles Windows line-endings and a subset of columns that are not in order", 117 SetUpScript: []string{ 118 "CREATE TABLE inmate_population_snapshots (id char(21) NOT NULL, snapshot_date date NOT NULL, total int," + 119 "total_off_site int, male int, female int, other_gender int, white int, black int, hispanic int," + 120 "asian int, american_indian int, mexican_american int, multi_racial int, other_race int," + 121 "on_probation int, on_parole int, felony int, misdemeanor int, other_offense int," + 122 "convicted_or_sentenced int, detained_or_awaiting_trial int, first_time_incarcerated int, employed int," + 123 "unemployed int, citizen int, noncitizen int, juvenile int, juvenile_male int, juvenile_female int," + 124 "death_row_condemned int, solitary_confinement int, technical_parole_violators int," + 125 "source_url varchar(2043) NOT NULL, source_url_2 varchar(2043), civil_offense int, federal_offense int," + 126 "PRIMARY KEY (id,snapshot_date), KEY id (id));", 127 "LOAD DATA INFILE './testdata/test6.csv' INTO TABLE inmate_population_snapshots " + 128 "FIELDS TERMINATED BY ',' " + 129 "LINES TERMINATED BY '\r\n' " + 130 "IGNORE 1 LINES " + 131 "(federal_offense, misdemeanor, total, detained_or_awaiting_trial, felony, snapshot_date, id, source_url, source_url_2)", 132 }, 133 Assertions: []ScriptTestAssertion{ 134 { 135 Query: "SELECT * FROM inmate_population_snapshots", 136 Expected: []sql.Row{ 137 {"8946", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, nil, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, nil}, 138 {"8976", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 196, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 73, nil, nil, 123, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, 0}, 139 {"8978", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, nil, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, nil}, 140 {"8979", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 71, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 5, 3, nil, nil, 63, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, 0}, 141 }, 142 }, 143 }, 144 }, 145 { 146 Name: "LOAD DATA handles non-nil default values", 147 SetUpScript: []string{ 148 "CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (v2 * 10), v2 BIGINT DEFAULT 5);", 149 "CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (v2 * 10), v2 BIGINT DEFAULT 5);", 150 "CREATE TABLE test3 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (pk * 10), v2 BIGINT DEFAULT (v1 - 1));", 151 "CREATE TABLE test4 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (pk * 10), v2 BIGINT DEFAULT (v1 - 1));", 152 "LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test1;", 153 "LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test2 (pk);", // The (pk) projection results in a different tree 154 "LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test3;", 155 "LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test4 (pk);", 156 }, 157 Assertions: []ScriptTestAssertion{ 158 { 159 Query: "SELECT * FROM test1", 160 Expected: []sql.Row{ 161 {1, 50, 5}, 162 {2, 50, 5}, 163 {3, 50, 5}, 164 }, 165 }, 166 { 167 Query: "SELECT * FROM test2", 168 Expected: []sql.Row{ 169 {1, 50, 5}, 170 {2, 50, 5}, 171 {3, 50, 5}, 172 }, 173 }, 174 { 175 Query: "SELECT * FROM test3", 176 Expected: []sql.Row{ 177 {1, 10, 9}, 178 {2, 20, 19}, 179 {3, 30, 29}, 180 }, 181 }, 182 { 183 Query: "SELECT * FROM test4", 184 Expected: []sql.Row{ 185 {1, 10, 9}, 186 {2, 20, 19}, 187 {3, 30, 29}, 188 }, 189 }, 190 }, 191 }, 192 { 193 Name: "LOAD DATA handles non-nil default values with varying field counts per row", 194 SetUpScript: []string{ 195 "CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (v2 * 10), v2 BIGINT DEFAULT 5);", 196 "CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (pk * 10), v2 BIGINT DEFAULT (v1 - 1));", 197 "LOAD DATA INFILE './testdata/test8.txt' INTO TABLE test1 FIELDS TERMINATED BY ',';", 198 "LOAD DATA INFILE './testdata/test8.txt' INTO TABLE test2 FIELDS TERMINATED BY ',';", 199 }, 200 Assertions: []ScriptTestAssertion{ 201 { 202 Query: "SELECT * FROM test1", 203 Expected: []sql.Row{ 204 {1, 50, 5}, 205 {2, 100, 5}, 206 {3, 50, 5}, 207 }, 208 }, 209 { 210 Query: "SELECT * FROM test2", 211 Expected: []sql.Row{ 212 {1, 10, 9}, 213 {2, 100, 99}, 214 {3, 30, 29}, 215 }, 216 }, 217 }, 218 }, 219 { 220 Name: "Load data can ignore row with existing primary key", 221 SetUpScript: []string{ 222 "create table loadtable(pk int primary key, c1 varchar(10))", 223 "insert into loadtable values (1, 'test')", 224 "LOAD DATA INFILE './testdata/test2.csv' IGNORE INTO TABLE loadtable FIELDS TERMINATED BY ',' IGNORE 1 LINES", 225 }, 226 Assertions: []ScriptTestAssertion{ 227 { 228 Query: "select * from loadtable", 229 Expected: []sql.Row{ 230 {1, "test"}, 231 {2, "hello"}, 232 }, 233 }, 234 }, 235 }, 236 { 237 Name: "Load data can replace row with existing primary key", 238 SetUpScript: []string{ 239 "create table loadtable(pk int primary key, c1 varchar(10))", 240 "insert into loadtable values (1, 'test')", 241 "LOAD DATA INFILE './testdata/test2.csv' REPLACE INTO TABLE loadtable FIELDS TERMINATED BY ',' IGNORE 1 LINES", 242 }, 243 Assertions: []ScriptTestAssertion{ 244 { 245 Query: "select * from loadtable", 246 Expected: []sql.Row{ 247 {1, "hi"}, 248 {2, "hello"}, 249 }, 250 }, 251 }, 252 }, 253 } 254 255 var LoadDataErrorScripts = []ScriptTest{ 256 { 257 Name: "Load data into table that doesn't exist throws error.", 258 Query: "LOAD DATA INFILE 'test1.txt' INTO TABLE loadtable", 259 ExpectedErr: sql.ErrTableNotFound, 260 }, 261 { 262 Name: "Load data with unknown files throws an error.", 263 SetUpScript: []string{ 264 "create table loadtable(pk longtext, c1 int)", 265 }, 266 Assertions: []ScriptTestAssertion{ 267 { 268 Query: "LOAD DATA INFILE './bad/doesnotexist.txt' INTO TABLE loadtable", 269 ExpectedErr: sql.ErrLoadDataCannotOpen, 270 }, 271 }, 272 }, 273 { 274 Name: "Load data with unknown columns throws an error", 275 SetUpScript: []string{ 276 "create table loadtable(pk int primary key, i int)", 277 }, 278 Assertions: []ScriptTestAssertion{ 279 { 280 Query: "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (fake_col, pk, i)", 281 ExpectedErr: sql.ErrUnknownColumn, 282 }, 283 { 284 Query: "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (pk, fake_col, i)", 285 ExpectedErr: sql.ErrUnknownColumn, 286 }, 287 { 288 Query: "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (pk, i, fake_col)", 289 ExpectedErr: sql.ErrUnknownColumn, 290 }, 291 }, 292 }, 293 { 294 Name: "Load data escaped by terms longer than 1 character throws an error", 295 SetUpScript: []string{ 296 "create table loadtable(pk int primary key)", 297 }, 298 Assertions: []ScriptTestAssertion{ 299 { 300 Query: "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ESCAPED BY 'xx' (pk)", 301 ExpectedErr: sql.ErrUnexpectedSeparator, 302 }, 303 }, 304 }, 305 { 306 Name: "Load data enclosed by term longer than 1 character throws an error", 307 SetUpScript: []string{ 308 "create table loadtable(pk int primary key)", 309 }, 310 Assertions: []ScriptTestAssertion{ 311 { 312 Query: "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY 'xx' (pk)", 313 ExpectedErr: sql.ErrUnexpectedSeparator, 314 }, 315 }, 316 }, 317 { 318 Name: "Load data errors on primary key duplicate", 319 SetUpScript: []string{ 320 "create table loadtable(pk int primary key, c1 varchar(10))", 321 "insert into loadtable values (1, 'test')", 322 }, 323 Assertions: []ScriptTestAssertion{ 324 { 325 Query: "LOAD DATA INFILE './testdata/test2.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' IGNORE 1 LINES", 326 ExpectedErrStr: "duplicate primary key given: [1]", 327 }, 328 }, 329 }, 330 } 331 332 var LoadDataFailingScripts = []ScriptTest{ 333 { 334 Name: "Escaped values are correctly parsed.", 335 SetUpScript: []string{ 336 "create table loadtable(pk longtext)", 337 "LOAD DATA INFILE 'test5.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' IGNORE 1 LINES", 338 }, 339 Assertions: []ScriptTestAssertion{ 340 { 341 Query: "select * from loadtable", 342 Expected: []sql.Row{{"hi"}, {"hello"}, {nil}, {"TryN"}, {fmt.Sprintf("%c", 26)}, {fmt.Sprintf("%c", 0)}, {"new\n"}}, 343 }, 344 }, 345 }, 346 { 347 Name: "Load and terminate have the same values.", 348 SetUpScript: []string{ 349 "create table loadtable(pk int primary key)", 350 "LOAD DATA INFILE 'test1.txt' INTO TABLE loadtable FIELDS TERMINATED BY '\"' ENCLOSED BY '\"'", 351 }, 352 Assertions: []ScriptTestAssertion{ 353 { 354 Query: "select * from loadtable", 355 Expected: []sql.Row{{int8(1)}, {int8(2)}, {int8(3)}, {int8(4)}}, 356 }, 357 }, 358 }, 359 { 360 Name: "Loading value into different column type results in default value.", 361 SetUpScript: []string{ 362 "create table loadtable(pk longtext, c1 int)", 363 "LOAD DATA INFILE 'test4.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (c1)", 364 }, 365 Assertions: []ScriptTestAssertion{ 366 { 367 Query: "select * from loadtable", 368 Expected: []sql.Row{{nil, 0}, {nil, 0}}, 369 }, 370 }, 371 }, 372 { 373 Name: "LOAD DATA handles nulls", 374 SetUpScript: []string{ 375 "create table loadtable(pk longtext, c1 int)", 376 "LOAD DATA INFILE 'test4.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"'", 377 }, 378 Assertions: []ScriptTestAssertion{ 379 { 380 Query: "select * from loadtable", 381 Expected: []sql.Row{{"hi", 1}, {"hello", nil}}, 382 }, 383 }, 384 }, 385 { 386 Name: "LOAD DATA can handle a differing column order", 387 SetUpScript: []string{ 388 "create table loadtable(pk int, c1 string) ", 389 "LOAD DATA INFILE 'test4.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (c1, pk)", 390 }, 391 Assertions: []ScriptTestAssertion{ 392 { 393 Query: "select * from loadtable", 394 Expected: []sql.Row{{1, "hi"}, {nil, "hello"}}, 395 }, 396 }, 397 }, 398 }