From 92ebbdee2f982e87ce7e100df360010a3d551d24 Mon Sep 17 00:00:00 2001 From: Yako Date: Mon, 10 Nov 2014 21:22:33 +0800 Subject: [PATCH] improve sqlparser --- .../MySqlLoadDataInFileStatement.java | 19 ++++++- .../mysql/parser/MySqlStatementParser.java | 50 +++++++++++++++++-- .../mysql/visitor/MySqlOutputVisitor.java | 12 +++++ .../sql/mysql/LoadDataInFileSyntaxTest.java | 36 +++++++++++++ 4 files changed, 112 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLoadDataInFileStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLoadDataInFileStatement.java index 9e0e36e891..7449b804cf 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLoadDataInFileStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLoadDataInFileStatement.java @@ -48,7 +48,9 @@ public class MySqlLoadDataInFileStatement extends MySqlStatementImpl { private SQLExpr ignoreLinesNumber; - private final List setList = new ArrayList(); + private List setList = new ArrayList(); + + private List columns = new ArrayList(); public boolean isLowPriority() { return lowPriority; @@ -188,4 +190,19 @@ public class MySqlLoadDataInFileStatement extends MySqlStatementImpl { } visitor.endVisit(this); } + + + public List getColumns() { + return columns; + } + + + public void setColumns(List columns) { + this.columns = columns; + } + + + public void setSetList(List setList) { + this.setList = setList; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index be42fdfe96..84d25de089 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -1787,19 +1787,61 @@ public class MySqlStatementParser extends SQLStatementParser { } if (identifierEquals("FIELDS") || identifierEquals("COLUMNS")) { - throw new ParserException("TODO"); + lexer.nextToken(); + if (identifierEquals("TERMINATED")) { + lexer.nextToken(); + accept(Token.BY); + stmt.setColumnsTerminatedBy((SQLLiteralExpr) this.exprParser.expr()); + } + + if (identifierEquals("OPTIONALLY")) { + stmt.setColumnsEnclosedOptionally(true); + lexer.nextToken(); + } + + if (identifierEquals("ENCLOSED")) { + lexer.nextToken(); + accept(Token.BY); + stmt.setColumnsEnclosedBy((SQLLiteralExpr) this.exprParser.expr()); + } + + if (identifierEquals("ESCAPED")) { + lexer.nextToken(); + accept(Token.BY); + stmt.setColumnsEscaped((SQLLiteralExpr) this.exprParser.expr()); + } } if (identifierEquals("LINES")) { - throw new ParserException("TODO"); + lexer.nextToken(); + if (identifierEquals("STARTING")) { + lexer.nextToken(); + accept(Token.BY); + stmt.setLinesStartingBy((SQLLiteralExpr) this.exprParser.expr()); + } + + if (identifierEquals("TERMINATED")) { + lexer.nextToken(); + accept(Token.BY); + stmt.setLinesTerminatedBy((SQLLiteralExpr) this.exprParser.expr()); + } } if (identifierEquals(IGNORE)) { - throw new ParserException("TODO"); + lexer.nextToken(); + stmt.setIgnoreLinesNumber((SQLLiteralExpr) this.exprParser.expr()); + acceptIdentifier("LINES"); + } + + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + this.exprParser.exprList(stmt.getColumns(), stmt); + accept(Token.RPAREN); } if (lexer.token() == Token.SET) { - throw new ParserException("TODO"); + lexer.nextToken(); + this.exprParser.exprList(stmt.getSetList(), stmt); } return stmt; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 58e246b2ff..e14fda7181 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -1037,7 +1037,19 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV x.getLinesTerminatedBy().accept(this); } } + + if(x.getIgnoreLinesNumber() != null) { + print(" IGNORE "); + x.getIgnoreLinesNumber().accept(this); + print(" LINES"); + } + if (x.getColumns().size() != 0) { + print(" ("); + printAndAccept(x.getColumns(), ", "); + print(")"); + } + if (x.getSetList().size() != 0) { print(" SET "); printAndAccept(x.getSetList(), ", "); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/LoadDataInFileSyntaxTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/LoadDataInFileSyntaxTest.java index 6f964f21d4..abf1863500 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/LoadDataInFileSyntaxTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/LoadDataInFileSyntaxTest.java @@ -38,6 +38,42 @@ public class LoadDataInFileSyntaxTest extends TestCase { Assert.assertEquals("LOAD DATA INFILE 'data.txt' INTO TABLE db2.my_table;", text); } + public void test_1() throws Exception { + String sql = "LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test FIELDS TERMINATED BY ',' LINES STARTING BY 'xxx';"; + + SQLStatementParser parser = new MySqlStatementParser(sql); + List stmtList = parser.parseStatementList(); + + String text = output(stmtList); + + Assert.assertEquals("LOAD DATA INFILE '/tmp/test.txt' INTO TABLE test COLUMNS TERMINATED BY ',' LINES STARTING BY 'xxx';", + text); + } + + public void test_2() throws Exception { + String sql = "LOAD DATA INFILE '/home/Order.txt' INTO TABLE Orders (Order_Number, Order_Date, Customer_ID);"; + + SQLStatementParser parser = new MySqlStatementParser(sql); + List stmtList = parser.parseStatementList(); + + String text = output(stmtList); + + Assert.assertEquals("LOAD DATA INFILE '/home/Order.txt' INTO TABLE Orders (Order_Number, Order_Date, Customer_ID);", + text); + } + + public void test_3() throws Exception { + String sql = "LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES;"; + + SQLStatementParser parser = new MySqlStatementParser(sql); + List stmtList = parser.parseStatementList(); + + String text = output(stmtList); + + Assert.assertEquals("LOAD DATA INFILE 'data.txt' INTO TABLE tbl_name COLUMNS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES;", + text); + } + private String output(List stmtList) { StringBuilder out = new StringBuilder();