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  }