mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
Merge branch 'master' of https://github.com/alibaba/druid
This commit is contained in:
@@ -428,7 +428,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.13.2</version>
|
||||
<version>2.17.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -60,7 +60,7 @@ public enum DbType {
|
||||
|
||||
oscar (1 << 40),
|
||||
|
||||
|
||||
tidb ( 1 << 41),
|
||||
|
||||
ingres (0),
|
||||
cloudscape (0),
|
||||
|
||||
@@ -71,7 +71,6 @@ public class FilterManager {
|
||||
loadFilterConfig(filterProperties, ClassLoader.getSystemClassLoader());
|
||||
loadFilterConfig(filterProperties, FilterManager.class.getClassLoader());
|
||||
loadFilterConfig(filterProperties, Thread.currentThread().getContextClassLoader());
|
||||
loadFilterConfig(filterProperties, FilterManager.class.getClassLoader());
|
||||
|
||||
return filterProperties;
|
||||
}
|
||||
|
||||
@@ -170,6 +170,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
protected volatile long timeBetweenConnectErrorMillis = DEFAULT_TIME_BETWEEN_CONNECT_ERROR_MILLIS;
|
||||
|
||||
protected volatile ValidConnectionChecker validConnectionChecker = null;
|
||||
|
||||
protected volatile boolean usePingMethod = false;
|
||||
|
||||
protected final Map<DruidPooledConnection, Object> activeConnections = new IdentityHashMap<DruidPooledConnection, Object>();
|
||||
protected final static Object PRESENT = new Object();
|
||||
@@ -641,6 +643,14 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
this.validConnectionChecker = validConnectionChecker;
|
||||
}
|
||||
|
||||
public boolean isUsePingMethod() {
|
||||
return usePingMethod;
|
||||
}
|
||||
|
||||
public void setUsePingMethod(boolean usePingMethod) {
|
||||
this.usePingMethod = usePingMethod;
|
||||
}
|
||||
|
||||
public String getValidConnectionCheckerClassName() {
|
||||
if (validConnectionChecker == null) {
|
||||
return null;
|
||||
@@ -1856,7 +1866,7 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements
|
||||
}
|
||||
|
||||
DbType dbType = DbType.of(this.dbTypeName);
|
||||
if (dbType == DbType.mysql || dbType == DbType.ads) {
|
||||
if (JdbcUtils.isMysqlDbType(dbType)) {
|
||||
if (variables != null) {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
|
||||
@@ -843,10 +843,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
}
|
||||
|
||||
DbType dbType = DbType.of(this.dbTypeName);
|
||||
if (dbType == DbType.mysql
|
||||
|| dbType == DbType.mariadb
|
||||
|| dbType == DbType.oceanbase
|
||||
|| dbType == DbType.ads) {
|
||||
if (JdbcUtils.isMysqlDbType(dbType)) {
|
||||
boolean cacheServerConfigurationSet = false;
|
||||
if (this.connectProperties.containsKey("cacheServerConfiguration")) {
|
||||
cacheServerConfigurationSet = true;
|
||||
@@ -1321,7 +1318,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
|
||||
String realDriverClassName = driver.getClass().getName();
|
||||
if (JdbcUtils.isMySqlDriver(realDriverClassName)) {
|
||||
this.validConnectionChecker = new MySqlValidConnectionChecker();
|
||||
this.validConnectionChecker = new MySqlValidConnectionChecker(usePingMethod);
|
||||
|
||||
} else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)
|
||||
|| realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) {
|
||||
@@ -1336,7 +1333,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat
|
||||
|| realDriverClassName.equals(JdbcConstants.ENTERPRISEDB_DRIVER)
|
||||
|| realDriverClassName.equals(JdbcConstants.POLARDB_DRIVER)) {
|
||||
this.validConnectionChecker = new PGValidConnectionChecker();
|
||||
} else if (realDriverClassName.equals(JdbcConstants.OCEANBASE_DRIVER)
|
||||
|| (realDriverClassName.equals(JdbcConstants.OCEANBASE_DRIVER2))) {
|
||||
DbType dbType = DbType.of(this.dbTypeName);
|
||||
this.validConnectionChecker = new OceanBaseValidConnectionChecker(dbType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initExceptionSorter() {
|
||||
|
||||
@@ -138,7 +138,7 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DbType.mysql != DbType.of(dataSource.dbTypeName)) {
|
||||
if (!JdbcUtils.isMysqlDbType(dataSource.dbTypeName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -45,7 +45,7 @@ public class MySqlValidConnectionChecker extends ValidConnectionCheckerAdapter i
|
||||
private Method ping;
|
||||
private boolean usePingMethod = false;
|
||||
|
||||
public MySqlValidConnectionChecker(){
|
||||
public MySqlValidConnectionChecker(boolean usePingMethod){
|
||||
try {
|
||||
clazz = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
|
||||
if (clazz == null) {
|
||||
@@ -56,8 +56,8 @@ public class MySqlValidConnectionChecker extends ValidConnectionCheckerAdapter i
|
||||
ping = clazz.getMethod("pingInternal", boolean.class, int.class);
|
||||
}
|
||||
|
||||
if (ping != null) {
|
||||
usePingMethod = true;
|
||||
if (ping != null && usePingMethod == true) {
|
||||
this.usePingMethod = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Cannot resolve com.mysql.jdbc.Connection.ping method. Will use 'SELECT 1' instead.", e);
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 1999-2018 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.pool.vendor;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.pool.ValidConnectionChecker;
|
||||
import com.alibaba.druid.pool.ValidConnectionCheckerAdapter;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import sun.security.pkcs11.Secmod;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class OceanBaseValidConnectionChecker extends ValidConnectionCheckerAdapter implements ValidConnectionChecker {
|
||||
private String oracleModeValidateQuery = "SELECT 'x' FROM DUAL";
|
||||
private String mysqlModeValidateQuery = "SELECT 'x'";
|
||||
private DbType dbType;
|
||||
public OceanBaseValidConnectionChecker() { configFromProperties(System.getProperties()); dbType = null; }
|
||||
public OceanBaseValidConnectionChecker(DbType dbType) {this.dbType = dbType;configFromProperties(System.getProperties()); }
|
||||
public boolean isValidConnection(final Connection c, String validateQuery, int validationQueryTimeout) throws Exception {
|
||||
if (c.isClosed()) {
|
||||
return false;
|
||||
}
|
||||
if (validateQuery == null || validateQuery.isEmpty()) {
|
||||
if(dbType != null) {
|
||||
if(dbType == DbType.oceanbase) {
|
||||
validateQuery = mysqlModeValidateQuery;
|
||||
} else {
|
||||
validateQuery = oracleModeValidateQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Statement stmt = null;
|
||||
|
||||
try {
|
||||
stmt = c.createStatement();
|
||||
if (validationQueryTimeout > 0) {
|
||||
stmt.setQueryTimeout(validationQueryTimeout);
|
||||
}
|
||||
stmt.execute(validateQuery);
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
throw e;
|
||||
} finally {
|
||||
JdbcUtils.close(stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -157,12 +158,15 @@ public class PagerUtils {
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case h2:
|
||||
case ads:
|
||||
case clickhouse:
|
||||
return limitMySqlQueryBlock(queryBlock, dbType, offset, count, check);
|
||||
case postgresql:
|
||||
case hive:
|
||||
case odps:
|
||||
case presto:
|
||||
return limitSQLQueryBlock(queryBlock, dbType, offset, count, check);
|
||||
case oracle:
|
||||
case oceanbase_oracle:
|
||||
@@ -534,6 +538,7 @@ public class PagerUtils {
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case ads:
|
||||
return new MySqlSelectQueryBlock();
|
||||
case oracle:
|
||||
@@ -638,7 +643,7 @@ public class PagerUtils {
|
||||
public static boolean hasUnorderedLimit(String sql, DbType dbType) {
|
||||
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
|
||||
|
||||
if (DbType.mysql == dbType) {
|
||||
if (JdbcUtils.isMysqlDbType(dbType)) {
|
||||
|
||||
MySqlUnorderedLimitDetectVisitor visitor = new MySqlUnorderedLimitDetectVisitor();
|
||||
|
||||
@@ -695,6 +700,7 @@ public class PagerUtils {
|
||||
private static class OracleUnorderedLimitDetectVisitor extends OracleASTVisitorAdapter {
|
||||
public int unorderedLimitCount;
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
SQLExpr left = x.getLeft();
|
||||
SQLExpr right = x.getRight();
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleToMySqlOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.dialect.presto.visitor.PrestoOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor;
|
||||
import com.alibaba.druid.sql.parser.*;
|
||||
@@ -478,6 +479,7 @@ public class SQLUtils {
|
||||
}
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
return new MySqlOutputVisitor(out);
|
||||
case postgresql:
|
||||
return new PGOutputVisitor(out);
|
||||
@@ -498,6 +500,8 @@ public class SQLUtils {
|
||||
return new BlinkOutputVisitor(out);
|
||||
case antspark:
|
||||
return new AntsparkOutputVisitor(out);
|
||||
case presto:
|
||||
return new PrestoOutputVisitor(out);
|
||||
case clickhouse:
|
||||
return new ClickhouseOutputVisitor(out);
|
||||
default:
|
||||
@@ -532,6 +536,7 @@ public class SQLUtils {
|
||||
return new OracleSchemaStatVisitor(repository);
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case elastic_search:
|
||||
return new MySqlSchemaStatVisitor(repository);
|
||||
case postgresql:
|
||||
@@ -639,7 +644,7 @@ public class SQLUtils {
|
||||
dbType = DbType.mysql;
|
||||
}
|
||||
String formatMethod = "";
|
||||
if (DbType.mysql == dbType) {
|
||||
if (JdbcUtils.isMysqlDbType(dbType)) {
|
||||
formatMethod = "STR_TO_DATE";
|
||||
if (StringUtils.isEmpty(pattern)) pattern = "%Y-%m-%d %H:%i:%s";
|
||||
} else if (DbType.oracle == dbType) {
|
||||
@@ -1011,7 +1016,7 @@ public class SQLUtils {
|
||||
if (OracleUtils.isKeyword(normalizeName)) {
|
||||
return name;
|
||||
}
|
||||
} else if (DbType.mysql == dbType) {
|
||||
} else if (JdbcUtils.isMysqlDbType(dbType)) {
|
||||
if (MySqlUtils.isKeyword(normalizeName)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,9 @@ public class SQLDateExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValua
|
||||
, DbType.postgresql
|
||||
, DbType.ads
|
||||
, DbType.hive
|
||||
, DbType.odps);
|
||||
, DbType.odps
|
||||
, DbType.mariadb
|
||||
, DbType.tidb);
|
||||
|
||||
public static boolean isSupport(DbType dbType) {
|
||||
return (dbType.mask & supportDbTypes) != 0;
|
||||
|
||||
@@ -149,6 +149,8 @@ public class SQLDateTimeExpr extends SQLExprImpl implements SQLLiteralExpr, SQLV
|
||||
, DbType.presto
|
||||
, DbType.trino
|
||||
, DbType.postgresql
|
||||
, DbType.mariadb
|
||||
, DbType.tidb
|
||||
);
|
||||
|
||||
public static boolean isSupport(DbType dbType) {
|
||||
|
||||
@@ -150,6 +150,8 @@ public class SQLTimeExpr extends SQLExprImpl implements SQLLiteralExpr, SQLValua
|
||||
, DbType.presto
|
||||
, DbType.trino
|
||||
, DbType.postgresql
|
||||
, DbType.mariadb
|
||||
, DbType.tidb
|
||||
);
|
||||
|
||||
public static boolean isSupport(DbType dbType) {
|
||||
|
||||
@@ -127,6 +127,8 @@ public class SQLDeleteBuilderImpl implements SQLDeleteBuilder {
|
||||
case oracle:
|
||||
return new OracleDeleteStatement();
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
return new MySqlDeleteStatement();
|
||||
case postgresql:
|
||||
return new PGDeleteStatement();
|
||||
|
||||
@@ -161,6 +161,7 @@ public class SQLUpdateBuilderImpl extends SQLBuilderImpl implements SQLUpdateBui
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
return new MySqlUpdateStatement();
|
||||
case oracle:
|
||||
return new OracleUpdateStatement();
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 1999-2017 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.sql.dialect.presto.ast.stmt;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
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.presto.visitor.PrestoVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
/**
|
||||
* presto 的 select语句
|
||||
*
|
||||
* @author zhangcanlong
|
||||
* @date 2022/01/11
|
||||
*/
|
||||
public class PrestoSelectStatement extends SQLSelectStatement implements SQLStatement {
|
||||
|
||||
public PrestoSelectStatement() {
|
||||
super(DbType.postgresql);
|
||||
}
|
||||
|
||||
public PrestoSelectStatement(SQLSelect select) {
|
||||
super(select, DbType.postgresql);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept0(SQLASTVisitor visitor) {
|
||||
if (visitor instanceof PrestoVisitor) {
|
||||
this.accept0((PrestoVisitor) visitor);
|
||||
} else {
|
||||
super.accept0(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
public void accept0(PrestoVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
this.acceptChild(visitor, this.select);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,9 @@
|
||||
package com.alibaba.druid.sql.dialect.presto.parser;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntervalExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntervalUnit;
|
||||
import com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixLexer;
|
||||
import com.alibaba.druid.sql.parser.*;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.SQLExprParser;
|
||||
import com.alibaba.druid.sql.parser.SQLParserFeature;
|
||||
|
||||
/**
|
||||
* Created by wenshao on 16/9/13.
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 1999-2017 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.sql.dialect.presto.parser;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLLimit;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.parser.SQLExprParser;
|
||||
import com.alibaba.druid.sql.parser.SQLSelectListCache;
|
||||
import com.alibaba.druid.sql.parser.SQLSelectParser;
|
||||
import com.alibaba.druid.sql.parser.Token;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
|
||||
/**
|
||||
* presto的 选择解析器
|
||||
*
|
||||
* @author zhangcanlong
|
||||
* @date 2022/01/11
|
||||
*/
|
||||
public class PrestoSelectParser extends SQLSelectParser {
|
||||
|
||||
public PrestoSelectParser(SQLExprParser exprParser) {
|
||||
super(exprParser);
|
||||
}
|
||||
|
||||
public PrestoSelectParser(SQLExprParser exprParser, SQLSelectListCache selectListCache) {
|
||||
super(exprParser, selectListCache);
|
||||
}
|
||||
|
||||
public PrestoSelectParser(String sql) {
|
||||
this(new PrestoExprParser(sql));
|
||||
}
|
||||
|
||||
protected SQLExprParser createExprParser() {
|
||||
return new PrestoExprParser(this.lexer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLSelectQuery query(SQLObject parent, boolean acceptUnion) {
|
||||
if (this.lexer.token() == Token.LPAREN) {
|
||||
this.lexer.nextToken();
|
||||
|
||||
SQLSelectQuery select = this.query();
|
||||
this.accept(Token.RPAREN);
|
||||
|
||||
return this.queryRest(select, acceptUnion);
|
||||
}
|
||||
|
||||
if (this.lexer.token() == Token.VALUES) {
|
||||
return this.valuesQuery(acceptUnion);
|
||||
}
|
||||
|
||||
SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock(this.dbType);
|
||||
|
||||
if (this.lexer.hasComment() && this.lexer.isKeepComments()) {
|
||||
queryBlock.addBeforeComment(this.lexer.readAndResetComments());
|
||||
}
|
||||
|
||||
this.accept(Token.SELECT);
|
||||
|
||||
if (this.lexer.token() == Token.HINT) {
|
||||
this.exprParser.parseHints(queryBlock.getHints());
|
||||
}
|
||||
|
||||
if (this.lexer.token() == Token.COMMENT) {
|
||||
this.lexer.nextToken();
|
||||
}
|
||||
|
||||
if (DbType.informix == this.dbType) {
|
||||
if (this.lexer.identifierEquals(FnvHash.Constants.SKIP)) {
|
||||
this.lexer.nextToken();
|
||||
SQLExpr offset = this.exprParser.primary();
|
||||
queryBlock.setOffset(offset);
|
||||
}
|
||||
|
||||
if (this.lexer.identifierEquals(FnvHash.Constants.FIRST)) {
|
||||
this.lexer.nextToken();
|
||||
SQLExpr first = this.exprParser.primary();
|
||||
queryBlock.setFirst(first);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.lexer.token() == Token.DISTINCT) {
|
||||
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
|
||||
this.lexer.nextToken();
|
||||
} else if (this.lexer.token() == Token.UNIQUE) {
|
||||
queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);
|
||||
this.lexer.nextToken();
|
||||
} else if (this.lexer.token() == Token.ALL) {
|
||||
queryBlock.setDistionOption(SQLSetQuantifier.ALL);
|
||||
this.lexer.nextToken();
|
||||
}
|
||||
|
||||
this.parseSelectList(queryBlock);
|
||||
|
||||
if (this.lexer.token() == Token.INTO) {
|
||||
this.lexer.nextToken();
|
||||
|
||||
SQLExpr expr = this.expr();
|
||||
if (this.lexer.token() != Token.COMMA) {
|
||||
queryBlock.setInto(expr);
|
||||
}
|
||||
}
|
||||
|
||||
this.parseFrom(queryBlock);
|
||||
|
||||
this.parseWhere(queryBlock);
|
||||
|
||||
this.parseGroupBy(queryBlock);
|
||||
|
||||
if (this.lexer.identifierEquals(FnvHash.Constants.WINDOW)) {
|
||||
this.parseWindow(queryBlock);
|
||||
}
|
||||
|
||||
this.parseSortBy(queryBlock);
|
||||
|
||||
this.parseFetchClause(queryBlock);
|
||||
|
||||
if (this.lexer.token() == Token.FOR) {
|
||||
this.lexer.nextToken();
|
||||
this.accept(Token.UPDATE);
|
||||
|
||||
queryBlock.setForUpdate(true);
|
||||
|
||||
if (this.lexer.identifierEquals(FnvHash.Constants.NO_WAIT) || this.lexer.identifierEquals(FnvHash.Constants.NOWAIT)) {
|
||||
this.lexer.nextToken();
|
||||
queryBlock.setNoWait(true);
|
||||
} else if (this.lexer.identifierEquals(FnvHash.Constants.WAIT)) {
|
||||
this.lexer.nextToken();
|
||||
SQLExpr waitTime = this.exprParser.primary();
|
||||
queryBlock.setWaitTime(waitTime);
|
||||
}
|
||||
}
|
||||
|
||||
return this.queryRest(queryBlock, acceptUnion);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void parseFetchClause(SQLSelectQueryBlock queryBlock) {
|
||||
|
||||
// 如果是presto,则先解析 offset 再解析limit
|
||||
if (this.lexer.identifierEquals(FnvHash.Constants.OFFSET) || this.lexer.token() == Token.OFFSET) {
|
||||
this.lexer.nextToken();
|
||||
SQLExpr offset = this.exprParser.expr();
|
||||
queryBlock.setOffset(offset);
|
||||
if (this.lexer.identifierEquals(FnvHash.Constants.ROW) || this.lexer.identifierEquals(FnvHash.Constants.ROWS)) {
|
||||
this.lexer.nextToken();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.lexer.token() == Token.LIMIT) {
|
||||
SQLLimit limit = queryBlock.getLimit();
|
||||
// 原始的limit
|
||||
SQLLimit originLimit = this.exprParser.parseLimit();
|
||||
if (limit == null) {
|
||||
limit = originLimit;
|
||||
}
|
||||
limit.setRowCount(originLimit.getRowCount());
|
||||
queryBlock.setLimit(limit);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (this.lexer.token() == Token.FETCH) {
|
||||
this.lexer.nextToken();
|
||||
if (this.lexer.token() == Token.FIRST || this.lexer.token() == Token.NEXT || this.lexer.identifierEquals(FnvHash.Constants.NEXT)) {
|
||||
this.lexer.nextToken();
|
||||
} else {
|
||||
this.acceptIdentifier("FIRST");
|
||||
}
|
||||
SQLExpr first = this.exprParser.primary();
|
||||
queryBlock.setFirst(first);
|
||||
if (this.lexer.identifierEquals(FnvHash.Constants.ROW) || this.lexer.identifierEquals(FnvHash.Constants.ROWS)) {
|
||||
this.lexer.nextToken();
|
||||
}
|
||||
|
||||
if (this.lexer.token() == Token.ONLY) {
|
||||
this.lexer.nextToken();
|
||||
} else {
|
||||
this.acceptIdentifier("ONLY");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-1
@@ -18,7 +18,8 @@ package com.alibaba.druid.sql.dialect.presto.parser;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertInto;
|
||||
import com.alibaba.druid.sql.dialect.phoenix.parser.PhoenixExprParser;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
import com.alibaba.druid.sql.parser.Token;
|
||||
@@ -35,6 +36,18 @@ public class PrestoStatementParser extends SQLStatementParser {
|
||||
super(new PrestoExprParser(lexer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrestoSelectParser createSQLSelectParser() {
|
||||
return new PrestoSelectParser(this.exprParser, selectListCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PGSelectStatement parseSelect() {
|
||||
PrestoSelectParser selectParser = createSQLSelectParser();
|
||||
SQLSelect select = selectParser.select();
|
||||
return new PGSelectStatement(select);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parseInsertColumns(SQLInsertInto insert) {
|
||||
if (lexer.token() == Token.RPAREN ) {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 1999-2017 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.sql.dialect.presto.visitor;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLLimit;
|
||||
import com.alibaba.druid.sql.dialect.phoenix.visitor.PhoenixASTVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
|
||||
|
||||
/**
|
||||
* presto 的输出的视图信息
|
||||
*
|
||||
* @author zhangcanlong
|
||||
* @since 2022-01-07
|
||||
*/
|
||||
public class PrestoOutputVisitor extends SQLASTOutputVisitor implements PhoenixASTVisitor {
|
||||
public PrestoOutputVisitor(Appendable appender) {
|
||||
super(appender);
|
||||
}
|
||||
|
||||
public PrestoOutputVisitor(Appendable appender, boolean parameterized) {
|
||||
super(appender, parameterized);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLLimit x) {
|
||||
if (x.getOffset() != null) {
|
||||
this.print0(this.ucase ? " OFFSET " : " offset ");
|
||||
x.getOffset().accept(this);
|
||||
}
|
||||
this.print0(this.ucase ? " LIMIT " : " limit ");
|
||||
x.getRowCount().accept(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -413,6 +413,7 @@ public class SchemaRepository {
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case sqlite:
|
||||
resolveVisitor = new SchemaResolveVisitorFactory.MySqlResolveVisitor(this, optionsValue);
|
||||
break;
|
||||
|
||||
@@ -29,6 +29,7 @@ public class SQLRefactorVisitor extends SQLASTVisitorAdapter {
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case ads:
|
||||
quote = '`';
|
||||
break;
|
||||
|
||||
@@ -43,6 +43,7 @@ public final class ExportParameterVisitorUtils {
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
return new MySqlExportParameterVisitor(out);
|
||||
case oracle:
|
||||
return new OracleExportParameterVisitor(out);
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTParameterizedVisito
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.phoenix.visitor.PhoenixOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.presto.visitor.PrestoOutputVisitor;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor;
|
||||
import com.alibaba.druid.sql.parser.SQLParserFeature;
|
||||
import com.alibaba.druid.sql.parser.SQLParserUtils;
|
||||
@@ -78,7 +79,7 @@ public class ParameterizedOutputVisitorUtils {
|
||||
return parameterize(sql, dbType, null, null);
|
||||
}
|
||||
|
||||
public static String parameterize(String sql, DbType dbType, VisitorFeature ...features) {
|
||||
public static String parameterize(String sql, DbType dbType, VisitorFeature...features) {
|
||||
return parameterize(sql, dbType, null, features);
|
||||
}
|
||||
|
||||
@@ -408,6 +409,8 @@ public class ParameterizedOutputVisitorUtils {
|
||||
return new DB2OutputVisitor(out, true);
|
||||
case phoenix:
|
||||
return new PhoenixOutputVisitor(out, true);
|
||||
case presto:
|
||||
return new PrestoOutputVisitor(out, true);
|
||||
default:
|
||||
return new SQLASTOutputVisitor(out, true);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ public class SQLEvalVisitorUtils {
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case h2:
|
||||
return new MySqlEvalVisitorImpl();
|
||||
case oracle:
|
||||
|
||||
@@ -602,6 +602,8 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter {
|
||||
final SQLASTVisitor orderByVisitor;
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
return new MySqlOrderByStatVisitor(x);
|
||||
case postgresql:
|
||||
return new PGOrderByStatVisitor(x);
|
||||
|
||||
@@ -56,6 +56,9 @@ public interface JdbcConstants {
|
||||
String MARIADB = "mariadb";
|
||||
String MARIADB_DRIVER = "org.mariadb.jdbc.Driver";
|
||||
|
||||
DbType TIDB = DbType.tidb;
|
||||
String TIDB_DRIVER = "io.tidb.bigdata.jdbc.TiDBDriver";
|
||||
|
||||
DbType DERBY = DbType.derby;
|
||||
|
||||
String HBASE = "hbase";
|
||||
@@ -82,6 +85,7 @@ public interface JdbcConstants {
|
||||
DbType OCEANBASE = DbType.oceanbase;
|
||||
DbType OCEANBASE_ORACLE = DbType.oceanbase_oracle;
|
||||
String OCEANBASE_DRIVER = "com.alipay.oceanbase.jdbc.Driver";
|
||||
String OCEANBASE_DRIVER2 = "com.oceanbase.jdbc.Driver";
|
||||
|
||||
DbType INFORMIX = DbType.informix;
|
||||
|
||||
@@ -147,4 +151,5 @@ public interface JdbcConstants {
|
||||
*/
|
||||
DbType OSCAR = DbType.oscar;
|
||||
String OSCAR_DRIVER = "com.oscar.Driver";
|
||||
|
||||
}
|
||||
|
||||
@@ -418,6 +418,8 @@ public final class JdbcUtils implements JdbcConstants {
|
||||
return LOG4JDBC_DRIVER;
|
||||
} else if (rawUrl.startsWith("jdbc:mariadb:")) {
|
||||
return MARIADB_DRIVER;
|
||||
} else if (rawUrl.startsWith("jdbc:tidb:")) {
|
||||
return TIDB_DRIVER;
|
||||
} else if (rawUrl.startsWith("jdbc:oracle:") //
|
||||
|| rawUrl.startsWith("JDBC:oracle:")) {
|
||||
return ORACLE_DRIVER;
|
||||
@@ -544,6 +546,8 @@ public final class JdbcUtils implements JdbcConstants {
|
||||
return DbType.mysql;
|
||||
} else if (rawUrl.startsWith("jdbc:mariadb:")) {
|
||||
return DbType.mariadb;
|
||||
} else if (rawUrl.startsWith("jdbc:tidb:")) {
|
||||
return DbType.tidb;
|
||||
} else if (rawUrl.startsWith("jdbc:oracle:") || rawUrl.startsWith("jdbc:log4jdbc:oracle:")) {
|
||||
return DbType.oracle;
|
||||
} else if (rawUrl.startsWith("jdbc:alibaba:oracle:")) {
|
||||
@@ -886,7 +890,7 @@ public final class JdbcUtils implements JdbcConstants {
|
||||
}
|
||||
|
||||
public static List<String> showTables(Connection conn, DbType dbType) throws SQLException {
|
||||
if (DbType.mysql == dbType || DbType.oceanbase == dbType) {
|
||||
if (isMysqlDbType(dbType)) {
|
||||
return MySqlUtils.showTables(conn);
|
||||
}
|
||||
|
||||
@@ -905,7 +909,7 @@ public final class JdbcUtils implements JdbcConstants {
|
||||
}
|
||||
|
||||
public static String getCreateTableScript(Connection conn, DbType dbType, boolean sorted, boolean simplify) throws SQLException {
|
||||
if (DbType.mysql == dbType || DbType.oceanbase == dbType) {
|
||||
if (isMysqlDbType(dbType)) {
|
||||
return MySqlUtils.getCreateTableScript(conn, sorted, simplify);
|
||||
}
|
||||
|
||||
@@ -924,13 +928,13 @@ public final class JdbcUtils implements JdbcConstants {
|
||||
|
||||
public static boolean isOracleDbType(String dbType) {
|
||||
return DbType.oracle.name().equals(dbType) || //
|
||||
DbType.oceanbase.name().equals(dbType) || //
|
||||
DbType.oceanbase_oracle.name().equals(dbType) || //
|
||||
DbType.ali_oracle.name().equalsIgnoreCase(dbType);
|
||||
}
|
||||
|
||||
public static boolean isOracleDbType(DbType dbType) {
|
||||
return DbType.oracle == dbType || //
|
||||
DbType.oceanbase == dbType || //
|
||||
DbType.oceanbase_oracle == dbType || //
|
||||
DbType.ali_oracle == dbType;
|
||||
}
|
||||
|
||||
@@ -947,8 +951,10 @@ public final class JdbcUtils implements JdbcConstants {
|
||||
switch (dbType) {
|
||||
case mysql:
|
||||
case oceanbase:
|
||||
case ads:
|
||||
case drds:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case h2:
|
||||
return true;
|
||||
default:
|
||||
|
||||
@@ -134,6 +134,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
case oceanbase:
|
||||
case drds:
|
||||
case mariadb:
|
||||
case tidb:
|
||||
case h2:
|
||||
case presto:
|
||||
case trino:
|
||||
|
||||
@@ -239,7 +239,7 @@ public class DataSourceTest3 extends PoolTestCase {
|
||||
|
||||
public void test_ValidConnectionChecker() throws Exception {
|
||||
dataSource.getValidConnectionCheckerClassName();
|
||||
dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker());
|
||||
dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker(false));
|
||||
Assert.assertEquals(MySqlValidConnectionChecker.class.getName(),
|
||||
dataSource.getValidConnectionCheckerClassName());
|
||||
}
|
||||
@@ -326,7 +326,7 @@ public class DataSourceTest3 extends PoolTestCase {
|
||||
|
||||
public void test_error_validateConnection_3() throws Exception {
|
||||
dataSource.setValidationQuery(null);
|
||||
dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker());
|
||||
dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker(false));
|
||||
|
||||
DruidPooledConnection conn = dataSource.getConnection().unwrap(DruidPooledConnection.class);
|
||||
dataSource.validateConnection(conn);
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public class MySQLValidConnectionCheckerTest extends PoolTestCase {
|
||||
dataSource.setUrl("jdbc:mock:xxx");
|
||||
dataSource.setDbType("mysql");
|
||||
dataSource.setValidationQuery("select 1");
|
||||
dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker());
|
||||
dataSource.setValidConnectionChecker(new MySqlValidConnectionChecker(false));
|
||||
dataSource.setInitialSize(1);
|
||||
dataSource.setTestOnBorrow(true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.alibaba.druid.bvt.sql;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.PagerUtils;
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Assert;
|
||||
|
||||
/**
|
||||
* 分页工具类的单元测试,presto SQL类型的
|
||||
*
|
||||
* @author zhangcanlong
|
||||
* @date 2022/02/08
|
||||
*/
|
||||
public class PagerUtilsTest_Limit_presto_0 extends TestCase {
|
||||
|
||||
public void test_presto_0() throws Exception {
|
||||
String result = PagerUtils.limit("SELECT * FROM test", DbType.presto, 0, 10);
|
||||
System.out.println(result);
|
||||
String sureResult = "SELECT *\n" + "FROM test\n" + " OFFSET 1 LIMIT 10";
|
||||
Assert.assertEquals(sureResult, result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,4 +40,27 @@ public class JdbcUtilsTest extends TestCase {
|
||||
assertEquals("not support log4jdbc mysql, url like jdbc:log4jdbc:mysql:...", DbType.mysql, dbType);
|
||||
}
|
||||
|
||||
public void testGetDbTypeTiDB() {
|
||||
String jdbcUrl = "jdbc:tidb://localhost:4000/test";
|
||||
String dbType = JdbcUtils.getDbType(jdbcUrl, null);
|
||||
assertEquals("Does not support TiDB, for url like jdbc:tidb:...", DbType.tidb, dbType);
|
||||
}
|
||||
|
||||
public void testTiDBIsMySQLDBType() {
|
||||
assertTrue("TiDB suppose to be a MySQL compatible DB", JdbcUtils.isMysqlDbType(DbType.tidb));
|
||||
assertTrue("TiDB suppose to be a MySQL compatible DB", JdbcUtils.isMysqlDbType("tidb"));
|
||||
assertTrue("TiDB suppose to be a MySQL compatible DB", JdbcUtils.isMySqlDriver(JdbcUtils.TIDB_DRIVER));
|
||||
}
|
||||
|
||||
public void testGetTypeOceanBase_mysql() {
|
||||
String jdbcUrl = "jdbc:oceanbase://localhost:3306/test";
|
||||
String dbType = JdbcUtils.getDbType(jdbcUrl, null);
|
||||
assertEquals("Does not support OceanBase, for url like jdbc:oceanbase:...", DbType.oceanbase, dbType);
|
||||
}
|
||||
|
||||
public void testGetTypeOceanBase_oracle() {
|
||||
String jdbcUrl = "jdbc:oceanbase:oracle://localhost:3306/test";
|
||||
String dbType = JdbcUtils.getDbType(jdbcUrl, null);
|
||||
assertEquals("Does not support OceanBase, for url like jdbc:oceanbase:oracle:...", DbType.oceanbase_oracle, dbType);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user