Add implementation and testcase for Teradata Insert

This commit is contained in:
Louis Xu
2016-03-31 17:38:55 +08:00
parent ddcc4f6187
commit 32139bd98a
4 changed files with 321 additions and 1 deletions
@@ -0,0 +1,56 @@
package com.alibaba.druid.sql.dialect.teradata.ast.stmt;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.dialect.teradata.visitor.TeradataASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class TeradataInsertStatement extends SQLInsertStatement {
private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();
public ValuesClause getValues() {
if (valuesList.size() == 0) {
return null;
}
return valuesList.get(0);
}
public void setValues(ValuesClause values) {
if (valuesList.size() == 0) {
valuesList.add(values);
} else {
valuesList.set(0, values);
}
}
public List<ValuesClause> getValuesList() {
return valuesList;
}
public void addValueCause(ValuesClause valueClause) {
valueClause.setParent(this);
valuesList.add(valueClause);
}
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor instanceof TeradataASTVisitor) {
accept0((TeradataASTVisitor) visitor);
} else {
throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName());
}
}
protected void accept0(TeradataASTVisitor visitor) {
if (visitor.visit(this)) {
this.acceptChild(visitor, getTableSource());
this.acceptChild(visitor, getColumns());
this.acceptChild(visitor, getValuesList());
this.acceptChild(visitor, getQuery());
}
visitor.endVisit(this);
}
}
@@ -32,6 +32,7 @@ import com.alibaba.druid.sql.dialect.teradata.ast.expr.TeradataIntervalUnit;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.util.JdbcConstants;
@@ -82,6 +83,10 @@ public class TeradataExprParser extends SQLExprParser {
}
}
public SQLSelectParser createSelectParser() {
return new TeradataSelectParser(this);
}
protected SQLExpr methodRest(SQLExpr expr, boolean acceptLPAREN) {
if (acceptLPAREN) {
accept(Token.LPAREN);
@@ -15,12 +15,22 @@
*/
package com.alibaba.druid.sql.dialect.teradata.parser;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleSelectParser;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;
import com.alibaba.druid.sql.dialect.teradata.ast.stmt.TeradataInsertStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.util.JdbcConstants;
@@ -48,6 +58,160 @@ public class TeradataStatementParser extends SQLStatementParser {
return new SQLSelectStatement(selectParser.select(), JdbcConstants.TERADATA);
}
public SQLInsertStatement parseInsert() {
TeradataInsertStatement insertStatement = new TeradataInsertStatement();
if (lexer.token() == Token.INSERT) {
lexer.nextToken();
if (lexer.token() == Token.INTO) {
lexer.nextToken();
}
SQLName tableName = this.exprParser.name();
insertStatement.setTableName(tableName);
if (lexer.token() == Token.IDENTIFIER && !identifierEquals("VALUE")) {
insertStatement.setAlias(lexer.stringVal());
lexer.nextToken();
}
}
int columnSize = 0;
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
if (lexer.token() == (Token.SELECT)) {
SQLSelect select = this.exprParser.createSelectParser().select();
select.setParent(insertStatement);
insertStatement.setQuery(select);
} else {
this.exprParser.exprList(insertStatement.getColumns(), insertStatement);
columnSize = insertStatement.getColumns().size();
}
accept(Token.RPAREN);
}
if (lexer.token() == Token.VALUES || identifierEquals("VALUE")) {
lexer.nextTokenLParen();
parseValueClause(insertStatement.getValuesList(), columnSize);
} else if (lexer.token() == Token.SET) {
lexer.nextToken();
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
insertStatement.getValuesList().add(values);
for (;;) {
SQLName name = this.exprParser.name();
insertStatement.addColumn(name);
if (lexer.token() == Token.EQ) {
lexer.nextToken();
} else {
accept(Token.COLONEQ);
}
values.addValue(this.exprParser.expr());
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
} else if (lexer.token() == (Token.SELECT)) {
SQLSelect select = this.exprParser.createSelectParser().select();
select.setParent(insertStatement);
insertStatement.setQuery(select);
} else if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
SQLSelect select = this.exprParser.createSelectParser().select();
select.setParent(insertStatement);
insertStatement.setQuery(select);
accept(Token.RPAREN);
}
return insertStatement;
}
private void parseValueClause(List<ValuesClause> valueClauseList, int columnSize) {
for (;;) {
if (lexer.token() != Token.LPAREN) {
throw new ParserException("syntax error, expect ')'");
}
lexer.nextTokenValue();
if (lexer.token() != Token.RPAREN) {
List<SQLExpr> valueExprList;
if (columnSize > 0) {
valueExprList = new ArrayList<SQLExpr>(columnSize);
} else {
valueExprList = new ArrayList<SQLExpr>();
}
for (;;) {
SQLExpr expr;
if (lexer.token() == Token.LITERAL_INT) {
expr = new SQLIntegerExpr(lexer.integerValue());
lexer.nextTokenComma();
} else if (lexer.token() == Token.LITERAL_CHARS) {
expr = new SQLCharExpr(lexer.stringVal());
lexer.nextTokenComma();
} else if (lexer.token() == Token.LITERAL_NCHARS) {
expr = new SQLNCharExpr(lexer.stringVal());
lexer.nextTokenComma();
} else {
expr = exprParser.expr();
}
if (lexer.token() == Token.COMMA) {
valueExprList.add(expr);
lexer.nextTokenValue();
continue;
} else if (lexer.token() == Token.RPAREN) {
valueExprList.add(expr);
break;
} else {
expr = this.exprParser.primaryRest(expr);
if (lexer.token() != Token.COMMA && lexer.token() != Token.RPAREN) {
expr = this.exprParser.exprRest(expr);
}
valueExprList.add(expr);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else {
break;
}
}
}
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(valueExprList);
valueClauseList.add(values);
} else {
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(new ArrayList<SQLExpr>(0));
valueClauseList.add(values);
}
if (lexer.token() != Token.RPAREN) {
throw new ParserException("syntax error");
}
if (!parseCompleteValues && valueClauseList.size() >= parseValuesSize) {
lexer.skipToEOF();
break;
}
lexer.nextTokenComma();
if (lexer.token() == Token.COMMA) {
lexer.nextTokenLParen();
continue;
} else {
break;
}
}
}
public void parseStatementList(List<SQLStatement> statementList, int max) {
for (;;) {
if (max != -1) {
@@ -0,0 +1,95 @@
package com.alibaba.druid.bvt.sql.teradata;
import java.util.List;
import org.junit.Assert;
import com.alibaba.druid.sql.TeradataTest;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.teradata.ast.stmt.TeradataInsertStatement;
import com.alibaba.druid.sql.dialect.teradata.ast.stmt.TeradataSelectQueryBlock;
import com.alibaba.druid.sql.dialect.teradata.parser.TeradataStatementParser;
import com.alibaba.druid.sql.dialect.teradata.visitor.TeradataSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat.Column;
public class TeradataInsertTest_1 extends TeradataTest {
public void test_values() throws Exception {
String ins_sql = "INSERT INTO t1(c1, c2) VALUES "
+ "('a', 'b'),"
+ "('c', 'd'),"
+ "('e', 'f')";
TeradataStatementParser parser = new TeradataStatementParser(ins_sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
Assert.assertTrue(stmt instanceof SQLInsertStatement);
TeradataInsertStatement insertStmt = (TeradataInsertStatement) stmt;
Assert.assertEquals("t1", insertStmt.getTableSource().toString());
Assert.assertEquals("c1", insertStmt.getColumns().get(0).toString());
Assert.assertEquals("c2", insertStmt.getColumns().get(1).toString());
Assert.assertEquals(3, insertStmt.getValuesList().size());
Assert.assertEquals(2, insertStmt.getValuesList().get(0).getValues().size());
SQLSelect insertQuery = insertStmt.getQuery();
Assert.assertNull(insertQuery);
TeradataSchemaStatVisitor visitor = new TeradataSchemaStatVisitor();
insertStmt.accept(visitor);
System.out.println(visitor.getColumns());
System.out.println(visitor.getTables());
System.out.println("------ end of " + new Object(){}.getClass().getEnclosingMethod().getName() + " ------");
}
public void test_select() throws Exception {
String ins_sql = "INSERT INTO d1.t1(col1, col2) "
+ "SELECT c1, c2 "
+ "FROM d2.t2 "
+ "WHERE c1=0;";
TeradataStatementParser parser = new TeradataStatementParser(ins_sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement stmt = statementList.get(0);
Assert.assertTrue(stmt instanceof SQLInsertStatement);
TeradataInsertStatement insertStmt = (TeradataInsertStatement) stmt;
SQLSelect insertQuery = insertStmt.getQuery();
Assert.assertNotNull(insertQuery);
// retrieve SELECT sub-clause from INSERT query
TeradataSelectQueryBlock insertBlock = (TeradataSelectQueryBlock) insertQuery.getQuery();
Assert.assertNotNull(insertBlock);
// target table
Assert.assertEquals("d1.t1", insertStmt.getTableSource().toString());
Assert.assertEquals(2, insertStmt.getColumns().size());
Assert.assertEquals("col1", insertStmt.getColumns().get(0).toString());
Assert.assertEquals("col2", insertStmt.getColumns().get(1).toString());
// source table
Assert.assertEquals("d2.t2", insertBlock.getFrom().toString());
Assert.assertEquals(2, insertBlock.getSelectList().size());
Assert.assertEquals("c1", insertBlock.getSelectList().get(0).toString());
Assert.assertEquals("c2", insertBlock.getSelectList().get(1).toString());
System.out.println("***********below is useful info **********");
System.out.println("target table: " + insertStmt.getTableSource());
System.out.println("target columns: " + insertStmt.getColumns());
System.out.println("source from: " + insertBlock.getFrom());
System.out.println("source columns : " + insertBlock.getSelectList());
System.out.println("source condition: " + insertBlock.getWhere());
System.out.println("********");
TeradataSchemaStatVisitor visitor = new TeradataSchemaStatVisitor();
stmt.accept(visitor);
System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
System.out.println("coditions : " + visitor.getConditions());
System.out.println("orderBy : " + visitor.getOrderByColumns());
System.out.println("------ end of " + new Object(){}.getClass().getEnclosingMethod().getName() + " ------");
}
}