use of com.alibaba.druid.sql.ast.SQLStatement in project sharding-jdbc by dangdangdotcom.
the class SQLParserFactory method create.
/**
* 创建解析器引擎对象.
*
* @param databaseType 数据库类型
* @param sql SQL语句
* @param parameters SQL中参数的值
* @param shardingRule 分片规则
* @return 解析器引擎对象
* @throws SQLParserException SQL解析异常
*/
public static SQLParseEngine create(final DatabaseType databaseType, final String sql, final List<Object> parameters, final ShardingRule shardingRule) throws SQLParserException {
log.debug("Logic SQL: {}, {}", sql, parameters);
SQLStatement sqlStatement = getSQLStatementParser(databaseType, sql).parseStatement();
log.trace("Get {} SQL Statement", sqlStatement.getClass().getName());
return new SQLParseEngine(sqlStatement, parameters, getSQLVisitor(databaseType, sqlStatement), shardingRule);
}
use of com.alibaba.druid.sql.ast.SQLStatement in project Mycat-Server by MyCATApache.
the class ShareRowOutPutDataHandler method route.
public void route(SystemConfig sysConfig, SchemaConfig schema, int sqlType, String realSQL, String charset, ServerConnection sc, LayerCachePool cachePool) {
int rs = ServerParse.parse(realSQL);
this.sqltype = rs & 0xff;
this.sysConfig = sysConfig;
this.schema = schema;
this.charset = charset;
this.sc = sc;
this.cachePool = cachePool;
try {
// RouteStrategy routes=RouteStrategyFactory.getRouteStrategy();
// rrs =RouteStrategyFactory.getRouteStrategy().route(sysConfig, schema, sqlType2, realSQL,charset, sc, cachePool);
MySqlStatementParser parser = new MySqlStatementParser(realSQL);
SQLStatement statement = parser.parseStatement();
if (statement instanceof SQLSelectStatement) {
SQLSelectStatement st = (SQLSelectStatement) statement;
SQLSelectQuery sqlSelectQuery = st.getSelect().getQuery();
if (sqlSelectQuery instanceof MySqlSelectQueryBlock) {
MySqlSelectQueryBlock mysqlSelectQuery = (MySqlSelectQueryBlock) st.getSelect().getQuery();
joinParser = new JoinParser(mysqlSelectQuery, realSQL);
joinParser.parser();
}
}
/*
if (routes instanceof DruidMysqlRouteStrategy) {
SQLSelectStatement st=((DruidMysqlRouteStrategy) routes).getSQLStatement();
SQLSelectQuery sqlSelectQuery =st.getSelect().getQuery();
if(sqlSelectQuery instanceof MySqlSelectQueryBlock) {
MySqlSelectQueryBlock mysqlSelectQuery = (MySqlSelectQueryBlock)st.getSelect().getQuery();
joinParser=new JoinParser(mysqlSelectQuery,realSQL);
joinParser.parser();
}
}
*/
} catch (Exception e) {
}
}
use of com.alibaba.druid.sql.ast.SQLStatement in project Mycat-Server by MyCATApache.
the class MycatPrivileges method checkDmlPrivilege.
// 审计SQL权限
@Override
public boolean checkDmlPrivilege(String user, String schema, String sql) {
if (schema == null) {
return true;
}
boolean isPassed = false;
MycatConfig conf = MycatServer.getInstance().getConfig();
UserConfig userConfig = conf.getUsers().get(user);
if (userConfig != null) {
UserPrivilegesConfig userPrivilege = userConfig.getPrivilegesConfig();
if (userPrivilege != null && userPrivilege.isCheck()) {
UserPrivilegesConfig.SchemaPrivilege schemaPrivilege = userPrivilege.getSchemaPrivilege(schema);
if (schemaPrivilege != null) {
String tableName = null;
int index = -1;
//TODO 此处待优化,寻找更优SQL 解析器
SQLStatementParser parser = new MycatStatementParser(sql);
SQLStatement stmt = parser.parseStatement();
if (stmt instanceof MySqlReplaceStatement || stmt instanceof SQLInsertStatement) {
index = 0;
} else if (stmt instanceof SQLUpdateStatement) {
index = 1;
} else if (stmt instanceof SQLSelectStatement) {
index = 2;
} else if (stmt instanceof SQLDeleteStatement) {
index = 3;
}
if (index > -1) {
SchemaStatVisitor schemaStatVisitor = new MycatSchemaStatVisitor();
stmt.accept(schemaStatVisitor);
String key = schemaStatVisitor.getCurrentTable();
if (key != null) {
if (key.contains("`")) {
key = key.replaceAll("`", "");
}
int dotIndex = key.indexOf(".");
if (dotIndex > 0) {
tableName = key.substring(dotIndex + 1);
} else {
tableName = key;
}
//获取table 权限, 此处不需要检测空值, 无设置则自动继承父级权限
UserPrivilegesConfig.TablePrivilege tablePrivilege = schemaPrivilege.getTablePrivilege(tableName);
if (tablePrivilege.getDml()[index] > 0) {
isPassed = true;
}
} else {
//skip
isPassed = true;
}
} else {
//skip
isPassed = true;
}
} else {
//skip
isPassed = true;
}
} else {
//skip
isPassed = true;
}
} else {
//skip
isPassed = true;
}
if (!isPassed) {
ALARM.error(new StringBuilder().append(Alarms.DML_ATTACK).append("[sql=").append(sql).append(",user=").append(user).append(']').toString());
}
return isPassed;
}
use of com.alibaba.druid.sql.ast.SQLStatement in project Mycat-Server by MyCATApache.
the class DruidMycatRouteStrategy method routeNormalSqlWithAST.
@Override
public RouteResultset routeNormalSqlWithAST(SchemaConfig schema, String stmt, RouteResultset rrs, String charset, LayerCachePool cachePool) throws SQLNonTransientException {
/**
* 只有mysql时只支持mysql语法
*/
SQLStatementParser parser = null;
if (schema.isNeedSupportMultiDBType()) {
parser = new MycatStatementParser(stmt);
} else {
parser = new MySqlStatementParser(stmt);
}
MycatSchemaStatVisitor visitor = null;
SQLStatement statement;
/**
* 解析出现问题统一抛SQL语法错误
*/
try {
statement = parser.parseStatement();
visitor = new MycatSchemaStatVisitor();
} catch (Exception t) {
LOGGER.error("DruidMycatRouteStrategyError", t);
throw new SQLSyntaxErrorException(t);
}
/**
* 检验unsupported statement
*/
checkUnSupportedStatement(statement);
DruidParser druidParser = DruidParserFactory.create(schema, statement, visitor);
druidParser.parser(schema, rrs, statement, stmt, cachePool, visitor);
DruidShardingParseInfo ctx = druidParser.getCtx();
rrs.setTables(ctx.getTables());
/**
* DruidParser 解析过程中已完成了路由的直接返回
*/
if (rrs.isFinishedRoute()) {
return rrs;
}
/**
* 没有from的select语句或其他
*/
if ((ctx.getTables() == null || ctx.getTables().size() == 0) && (ctx.getTableAliasMap() == null || ctx.getTableAliasMap().isEmpty())) {
return RouterUtil.routeToSingleNode(rrs, schema.getRandomDataNode(), druidParser.getCtx().getSql());
}
if (druidParser.getCtx().getRouteCalculateUnits().size() == 0) {
RouteCalculateUnit routeCalculateUnit = new RouteCalculateUnit();
druidParser.getCtx().addRouteCalculateUnit(routeCalculateUnit);
}
SortedSet<RouteResultsetNode> nodeSet = new TreeSet<RouteResultsetNode>();
for (RouteCalculateUnit unit : druidParser.getCtx().getRouteCalculateUnits()) {
RouteResultset rrsTmp = RouterUtil.tryRouteForTables(schema, druidParser.getCtx(), unit, rrs, isSelect(statement), cachePool);
if (rrsTmp != null) {
for (RouteResultsetNode node : rrsTmp.getNodes()) {
nodeSet.add(node);
}
}
}
RouteResultsetNode[] nodes = new RouteResultsetNode[nodeSet.size()];
int i = 0;
for (RouteResultsetNode aNodeSet : nodeSet) {
nodes[i] = aNodeSet;
if (statement instanceof MySqlInsertStatement && ctx.getTables().size() == 1 && schema.getTables().containsKey(ctx.getTables().get(0))) {
RuleConfig rule = schema.getTables().get(ctx.getTables().get(0)).getRule();
if (rule != null && rule.getRuleAlgorithm() instanceof SlotFunction) {
aNodeSet.setStatement(ParseUtil.changeInsertAddSlot(aNodeSet.getStatement(), aNodeSet.getSlot()));
}
}
i++;
}
rrs.setNodes(nodes);
/**
* subTables="t_order$1-2,t_order3"
*目前分表 1.6 开始支持 幵丏 dataNode 在分表条件下只能配置一个,分表条件下不支持join。
*/
if (rrs.isDistTable()) {
return this.routeDisTable(statement, rrs);
}
return rrs;
}
use of com.alibaba.druid.sql.ast.SQLStatement in project Mycat-Server by MyCATApache.
the class GlobalTableUtil method convertInsertSQL.
/**
* Syntax:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
{VALUES | VALUE} ({expr | DEFAULT},...),(...),...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
Or:
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
SET col_name={expr | DEFAULT}, ...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
Or:
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name,...)]
[(col_name,...)]
SELECT ...
[ ON DUPLICATE KEY UPDATE
col_name=expr
[, col_name=expr] ... ]
mysql> insert user value (33333333,'ddd');
mysql> insert into user value (333333,'ddd');
mysql> insert user values (3333,'ddd');
* insert into user(id,name) valueS(1111,'dig'),
* (1111, 'dig'), (1111,'dig') ,(1111,'dig');
* @param sql
* @return
*/
private static String convertInsertSQL(String sql) {
try {
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement statement = parser.parseStatement();
MySqlInsertStatement insert = (MySqlInsertStatement) statement;
String tableName = StringUtil.removeBackquote(insert.getTableName().getSimpleName());
if (!isGlobalTable(tableName))
return sql;
if (!isInnerColExist(tableName))
return sql;
if (// insert into tab select
insert.getQuery() != null)
return sql;
StringBuilder sb = // 指定初始容量可以提高性能
new StringBuilder(200).append("insert into ").append(tableName);
List<SQLExpr> columns = insert.getColumns();
int idx = -1;
int colSize = -1;
if (columns == null || columns.size() <= 0) {
// insert 没有带列名:insert into t values(xxx,xxx)
String columnsList = tableColumsMap.get(tableName.toUpperCase());
if (StringUtils.isNotBlank(columnsList)) {
//"id,name,_mycat_op_time"
//newSQL = "insert into t(id,name,_mycat_op_time)";
// 构建一个虚拟newSQL来寻找 内部列的索引位置
String newSQL = "insert into " + tableName + "(" + columnsList + ")";
MySqlStatementParser newParser = new MySqlStatementParser(newSQL);
SQLStatement newStatement = newParser.parseStatement();
MySqlInsertStatement newInsert = (MySqlInsertStatement) newStatement;
List<SQLExpr> newColumns = newInsert.getColumns();
for (int i = 0; i < newColumns.size(); i++) {
String column = StringUtil.removeBackquote(newInsert.getColumns().get(i).toString());
if (column.equalsIgnoreCase(GLOBAL_TABLE_MYCAT_COLUMN))
// 找到 内部列的索引位置
idx = i;
}
colSize = newColumns.size();
sb.append("(").append(columnsList).append(")");
} else {
// tableName 是全局表,但是 tableColumsMap 没有其对应的列list,这种情况不应该存在
LOGGER.warn("you'd better do not use 'insert into t values(a,b)' Syntax (without column list) on global table, " + "If you do. Then you must make sure inner column '_mycat_op_time' is last column of global table: " + tableName + " in all database. Good luck. ^_^");
// 我们假定 内部列位于表中所有列的最后,后面我们在values 子句的最后 给他附加上时间戳
}
} else {
// insert 语句带有 列名
sb.append("(");
for (int i = 0; i < columns.size(); i++) {
if (i < columns.size() - 1)
sb.append(columns.get(i).toString()).append(",");
else
sb.append(columns.get(i).toString());
String column = StringUtil.removeBackquote(insert.getColumns().get(i).toString());
if (column.equalsIgnoreCase(GLOBAL_TABLE_MYCAT_COLUMN))
idx = i;
}
if (idx <= -1)
sb.append(",").append(GLOBAL_TABLE_MYCAT_COLUMN);
sb.append(")");
colSize = columns.size();
}
sb.append(" values");
List<ValuesClause> vcl = insert.getValuesList();
if (vcl != null && vcl.size() > 1) {
// 批量insert
for (int j = 0; j < vcl.size(); j++) {
if (j != vcl.size() - 1)
appendValues(vcl.get(j).getValues(), sb, idx, colSize).append(",");
else
appendValues(vcl.get(j).getValues(), sb, idx, colSize);
}
} else {
// 非批量 insert
List<SQLExpr> valuse = insert.getValues().getValues();
appendValues(valuse, sb, idx, colSize);
}
List<SQLExpr> dku = insert.getDuplicateKeyUpdate();
if (dku != null && dku.size() > 0) {
sb.append(" on duplicate key update ");
for (int i = 0; i < dku.size(); i++) {
SQLExpr exp = dku.get(i);
if (exp != null) {
if (i < dku.size() - 1)
sb.append(exp.toString()).append(",");
else
sb.append(exp.toString());
}
}
}
return sb.toString();
} catch (Exception e) {
// 发生异常,则返回原始 sql
LOGGER.warn(e.getMessage());
return sql;
}
}
Aggregations