diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index 68ac72fbc4..08d42327dd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -79,6 +79,7 @@ public class OracleExprParser extends SQLExprParser { + public boolean allowStringAdditive = false; /** @@ -389,12 +390,6 @@ public class OracleExprParser extends SQLExprParser { sqlExpr = cursorExpr; return primaryRest(sqlExpr); default: - if (identifierEquals("DATE")) { - return primaryRest(parseDate()); - } - if (identifierEquals("TIMESTAMP")) { - return primaryRest(parseTimestamp()); - } return super.primary(); } } @@ -413,8 +408,46 @@ public class OracleExprParser extends SQLExprParser { } public SQLExpr primaryRest(SQLExpr expr) { + if (expr.getClass() == SQLIdentifierExpr.class) { + String ident = ((SQLIdentifierExpr)expr).getName(); + + if ("DATE".equalsIgnoreCase(ident)) { + OracleDateExpr timestamp = new OracleDateExpr(); + + String literal = lexer.stringVal(); + timestamp.setLiteral(literal); + accept(Token.LITERAL_CHARS); + + return primaryRest(timestamp); + } + if ("TIMESTAMP".equalsIgnoreCase(ident)) { + if (lexer.token() != Token.LITERAL_ALIAS && lexer.token() != Token.LITERAL_CHARS) { + return new SQLIdentifierExpr("TIMESTAMP"); + } + + OracleTimestampExpr timestamp = new OracleTimestampExpr(); + + String literal = lexer.stringVal(); + timestamp.setLiteral(literal); + accept(Token.LITERAL_CHARS); + + if (identifierEquals("AT")) { + lexer.nextToken(); + acceptIdentifier("TIME"); + acceptIdentifier("ZONE"); + + String timezone = lexer.stringVal(); + timestamp.setTimeZone(timezone); + accept(Token.LITERAL_CHARS); + } + + + return primaryRest(timestamp); + } + } if (lexer.token() == Token.IDENTIFIER && expr instanceof SQLNumericLiteralExpr) { String ident = lexer.stringVal(); + if (ident.length() == 1) { char unit = ident.charAt(0); switch (unit) { @@ -570,44 +603,6 @@ public class OracleExprParser extends SQLExprParser { return super.dotRest(expr); } - public OracleDateExpr parseDate() { - acceptIdentifier("DATE"); - - OracleDateExpr timestamp = new OracleDateExpr(); - - String literal = lexer.stringVal(); - timestamp.setLiteral(literal); - accept(Token.LITERAL_CHARS); - - return timestamp; - } - - public SQLExpr parseTimestamp() { - acceptIdentifier("TIMESTAMP"); - - if (lexer.token() != Token.LITERAL_ALIAS && lexer.token() != Token.LITERAL_CHARS) { - return new SQLIdentifierExpr("TIMESTAMP"); - } - - OracleTimestampExpr timestamp = new OracleTimestampExpr(); - - String literal = lexer.stringVal(); - timestamp.setLiteral(literal); - accept(Token.LITERAL_CHARS); - - if (identifierEquals("AT")) { - lexer.nextToken(); - acceptIdentifier("TIME"); - acceptIdentifier("ZONE"); - - String timezone = lexer.stringVal(); - timestamp.setTimeZone(timezone); - accept(Token.LITERAL_CHARS); - } - - return timestamp; - } - @Override public OracleOrderBy parseOrderBy() { if (lexer.token() == (Token.ORDER)) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index 82791df7e6..74c633377b 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -15,6 +15,8 @@ */ package com.alibaba.druid.sql.parser; +import java.util.List; + import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLSetQuantifier; @@ -243,12 +245,30 @@ public class SQLSelectParser extends SQLParser { } } - protected void parseSelectList(SQLSelectQueryBlock queryBlock) { - queryBlock.getSelectList().add(new SQLSelectItem(expr(), as())); - - while (lexer.token() == Token.COMMA) { + protected final void parseSelectList(SQLSelectQueryBlock queryBlock) { + final List selectList = queryBlock.getSelectList(); + for (;;) { + SQLExpr expr; + if (lexer.token() == Token.IDENTIFIER) { + expr = new SQLIdentifierExpr(lexer.stringVal()); + lexer.nextTokenComma(); + + if (lexer.token() != Token.COMMA) { + expr = this.exprParser.primaryRest(expr); + expr = this.exprParser.exprRest(expr); + } + } else { + expr = expr(); + } + final String alias = as(); + + final SQLSelectItem selectItem = new SQLSelectItem(expr, alias); + selectList.add(selectItem); + if (lexer.token() != Token.COMMA) { + break; + } + lexer.nextToken(); - queryBlock.getSelectList().add(new SQLSelectItem(expr(), as())); } } diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java new file mode 100644 index 0000000000..56e2c6dd00 --- /dev/null +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlPerfMain_select.java @@ -0,0 +1,71 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.benckmark.sql; + +import java.lang.management.ManagementFactory; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; +import com.alibaba.druid.sql.test.TestUtils; +import com.alibaba.druid.util.IOUtils; + +public class MySqlPerfMain_select { + + public static void main(String[] args) throws Exception { + System.out.println(System.getProperty("java.vm.name") + " " + System.getProperty("java.runtime.version")); + List arguments = ManagementFactory.getRuntimeMXBean().getInputArguments(); + System.out.println(arguments); + + String sql = "SELECT ID, NAME, AGE FROM USER WHERE ID = ?"; + + for (int i = 0; i < 10; ++i) { + perfMySql(sql); + } + } + + static long perfMySql(String sql) { + long startYGC = TestUtils.getYoungGC(); + long startYGCTime = TestUtils.getYoungGCTime(); + long startFGC = TestUtils.getFullGC(); + + long startMillis = System.currentTimeMillis(); + for (int i = 0; i < 1000 * 1000; ++i) { + execMySql(sql); + } + long millis = System.currentTimeMillis() - startMillis; + + long ygc = TestUtils.getYoungGC() - startYGC; + long ygct = TestUtils.getYoungGCTime() - startYGCTime; + long fgc = TestUtils.getFullGC() - startFGC; + + System.out.println("MySql\t" + millis + ", ygc " + ygc + ", ygct " + ygct + ", fgc " + fgc); + return millis; + } + + static String execMySql(String sql) { + StringBuilder out = new StringBuilder(); + MySqlOutputVisitor visitor = new MySqlOutputVisitor(out); + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + // for (SQLStatement statement : statementList) { + // statement.accept(visitor); + // visitor.println(); + // } + return out.toString(); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_8.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_8.java new file mode 100644 index 0000000000..4f0f7fd120 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_8.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; + +public class MySqlSelectTest_8 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "select 1"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + SQLSelectStatement selectStmt = (SQLSelectStatement) stmt; + + SQLSelect select = selectStmt.getSelect(); + Assert.assertNotNull(select.getQuery()); + MySqlSelectQueryBlock queryBlock = (MySqlSelectQueryBlock) select.getQuery(); + Assert.assertNull(queryBlock.getOrderBy()); + + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + Assert.assertEquals(0, visitor.getOrderByColumns().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest11.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest11.java new file mode 100644 index 0000000000..9902a7958d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest11.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.test.TestUtils; + +public class SQLServerSelectTest11 extends TestCase { + + public void test_simple() throws Exception { + String sql = "SELECT 1"; + + String expect = "SELECT 1"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + String text = TestUtils.outputSqlServer(stmt); + + Assert.assertEquals(expect, text); + + System.out.println(text); + } +}