diff --git a/parser/ast/dml.go b/parser/ast/dml.go index 95ad60034f..f4614b88b9 100755 --- a/parser/ast/dml.go +++ b/parser/ast/dml.go @@ -1117,7 +1117,36 @@ type LoadDataStmt struct { // Restore implements Node interface. func (n *LoadDataStmt) Restore(ctx *RestoreCtx) error { - return errors.New("Not implemented") + ctx.WriteKeyWord("LOAD DATA ") + if n.IsLocal { + ctx.WriteKeyWord("LOCAL ") + } + ctx.WriteKeyWord("INFILE ") + ctx.WriteString(n.Path) + ctx.WriteKeyWord(" INTO TABLE ") + if err := n.Table.Restore(ctx); err != nil { + return errors.Annotate(err, "An error occurred while restore LoadDataStmt.Table") + } + n.FieldsInfo.Restore(ctx) + n.LinesInfo.Restore(ctx) + if n.IgnoreLines != 0 { + ctx.WriteKeyWord(" IGNORE ") + ctx.WritePlainf("%d", n.IgnoreLines) + ctx.WriteKeyWord(" LINES") + } + if len(n.Columns) != 0 { + ctx.WritePlain(" (") + for i, column := range n.Columns { + if i != 0 { + ctx.WritePlain(",") + } + if err := column.Restore(ctx); err != nil { + return errors.Annotate(err, "An error occurred while restore LoadDataStmt.Columns") + } + } + ctx.WritePlain(")") + } + return nil } // Accept implements Node Accept interface. @@ -1151,12 +1180,52 @@ type FieldsClause struct { Escaped byte } +// Restore for FieldsClause +func (n *FieldsClause) Restore(ctx *RestoreCtx) error { + if n.Terminated != "\t" || n.Escaped != '\\' { + ctx.WriteKeyWord(" FIELDS") + if n.Terminated != "\t" { + ctx.WriteKeyWord(" TERMINATED BY ") + ctx.WriteString(n.Terminated) + } + if n.Enclosed != 0 { + ctx.WriteKeyWord(" ENCLOSED BY ") + ctx.WriteString(string(n.Enclosed)) + } + if n.Escaped != '\\' { + ctx.WriteKeyWord(" ESCAPED BY ") + if n.Escaped == 0 { + ctx.WritePlain("''") + } else { + ctx.WriteString(string(n.Escaped)) + } + } + } + return nil +} + // LinesClause represents lines references clause in load data statement. type LinesClause struct { Starting string Terminated string } +// Restore for LinesClause +func (n *LinesClause) Restore(ctx *RestoreCtx) error { + if n.Starting != "" || n.Terminated != "\n" { + ctx.WriteKeyWord(" LINES") + if n.Starting != "" { + ctx.WriteKeyWord(" STARTING BY ") + ctx.WriteString(n.Starting) + } + if n.Terminated != "\n" { + ctx.WriteKeyWord(" TERMINATED BY ") + ctx.WriteString(n.Terminated) + } + } + return nil +} + // InsertStmt is a statement to insert new rows into an existing table. // See https://dev.mysql.com/doc/refman/5.7/en/insert.html type InsertStmt struct { diff --git a/parser/parser_test.go b/parser/parser_test.go index 595a1f05e2..b27b5be1ab 100755 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -395,44 +395,44 @@ func (s *testParserSuite) TestDMLStmt(c *C) { {"DO 1 from t", false, ""}, // load data - {"load data infile '/tmp/t.csv' into table t", true, ""}, - {"load data infile '/tmp/t.csv' into table t character set utf8", true, ""}, - {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab'", true, ""}, - {"load data infile '/tmp/t.csv' into table t columns terminated by 'ab'", true, ""}, - {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b'", true, ""}, - {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*'", true, ""}, - {"load data infile '/tmp/t.csv' into table t lines starting by 'ab'", true, ""}, - {"load data infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy'", true, ""}, - {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab' lines terminated by 'xy'", true, ""}, + {"load data infile '/tmp/t.csv' into table t", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t`"}, + {"load data infile '/tmp/t.csv' into table t character set utf8", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t`"}, + {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab'", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab'"}, + {"load data infile '/tmp/t.csv' into table t columns terminated by 'ab'", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab'"}, + {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b'", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b'"}, + {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*'", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' ESCAPED BY '*'"}, + {"load data infile '/tmp/t.csv' into table t lines starting by 'ab'", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` LINES STARTING BY 'ab'"}, + {"load data infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy'", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` LINES STARTING BY 'ab' TERMINATED BY 'xy'"}, + {"load data infile '/tmp/t.csv' into table t fields terminated by 'ab' lines terminated by 'xy'", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' LINES TERMINATED BY 'xy'"}, {"load data infile '/tmp/t.csv' into table t terminated by 'xy' fields terminated by 'ab'", false, ""}, - {"load data local infile '/tmp/t.csv' into table t", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab'", true, ""}, - {"load data local infile '/tmp/t.csv' into table t columns terminated by 'ab'", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b'", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*'", true, ""}, - {"load data local infile '/tmp/t.csv' into table t character set utf8 fields terminated by 'ab' enclosed by 'b' escaped by '*'", true, ""}, - {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab'", true, ""}, - {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy'", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' lines terminated by 'xy'", true, ""}, + {"load data local infile '/tmp/t.csv' into table t", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t`"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab'"}, + {"load data local infile '/tmp/t.csv' into table t columns terminated by 'ab'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab'"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b'"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' ESCAPED BY '*'"}, + {"load data local infile '/tmp/t.csv' into table t character set utf8 fields terminated by 'ab' enclosed by 'b' escaped by '*'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' ESCAPED BY '*'"}, + {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` LINES STARTING BY 'ab'"}, + {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` LINES STARTING BY 'ab' TERMINATED BY 'xy'"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' lines terminated by 'xy'", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' LINES TERMINATED BY 'xy'"}, {"load data local infile '/tmp/t.csv' into table t terminated by 'xy' fields terminated by 'ab'", false, ""}, - {"load data infile '/tmp/t.csv' into table t (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t columns terminated by 'ab' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t character set utf8 fields terminated by 'ab' enclosed by 'b' escaped by '*' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t character set utf8 fields terminated by 'ab' lines terminated by 'xy' (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' lines terminated by 'xy' (a,b)", true, ""}, + {"load data infile '/tmp/t.csv' into table t (a,b)", true, "LOAD DATA INFILE '/tmp/t.csv' INTO TABLE `t` (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t columns terminated by 'ab' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' ESCAPED BY '*' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t character set utf8 fields terminated by 'ab' enclosed by 'b' escaped by '*' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' ESCAPED BY '*' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` LINES STARTING BY 'ab' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` LINES STARTING BY 'ab' TERMINATED BY 'xy' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t character set utf8 fields terminated by 'ab' lines terminated by 'xy' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' LINES TERMINATED BY 'xy' (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' lines terminated by 'xy' (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' LINES TERMINATED BY 'xy' (`a`,`b`)"}, {"load data local infile '/tmp/t.csv' into table t (a,b) fields terminated by 'ab'", false, ""}, - {"load data local infile '/tmp/t.csv' into table t ignore 1 lines", true, ""}, + {"load data local infile '/tmp/t.csv' into table t ignore 1 lines", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` IGNORE 1 LINES"}, {"load data local infile '/tmp/t.csv' into table t ignore -1 lines", false, ""}, {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' (a,b) ignore 1 lines", false, ""}, - {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy' ignore 1 lines", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*' ignore 1 lines (a,b)", true, ""}, - {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by ''", true, ""}, + {"load data local infile '/tmp/t.csv' into table t lines starting by 'ab' terminated by 'xy' ignore 1 lines", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` LINES STARTING BY 'ab' TERMINATED BY 'xy' IGNORE 1 LINES"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by '*' ignore 1 lines (a,b)", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' ESCAPED BY '*' IGNORE 1 LINES (`a`,`b`)"}, + {"load data local infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by 'b' escaped by ''", true, "LOAD DATA LOCAL INFILE '/tmp/t.csv' INTO TABLE `t` FIELDS TERMINATED BY 'ab' ENCLOSED BY 'b' ESCAPED BY ''"}, // select for update {"SELECT * from t for update", true, "SELECT * FROM `t` FOR UPDATE"},