Search in sources :

Example 1 with SQLStatement

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);
}
Also used : SQLStatement(com.alibaba.druid.sql.ast.SQLStatement)

Example 2 with SQLStatement

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) {
    }
}
Also used : SQLSelectQuery(com.alibaba.druid.sql.ast.statement.SQLSelectQuery) SQLSelectStatement(com.alibaba.druid.sql.ast.statement.SQLSelectStatement) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) MySqlSelectQueryBlock(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock)

Example 3 with SQLStatement

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;
}
Also used : SQLStatementParser(com.alibaba.druid.sql.parser.SQLStatementParser) MycatStatementParser(io.mycat.route.parser.druid.MycatStatementParser) MycatSchemaStatVisitor(io.mycat.route.parser.druid.MycatSchemaStatVisitor) SQLUpdateStatement(com.alibaba.druid.sql.ast.statement.SQLUpdateStatement) UserConfig(io.mycat.config.model.UserConfig) UserPrivilegesConfig(io.mycat.config.model.UserPrivilegesConfig) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) MySqlReplaceStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement) SQLDeleteStatement(com.alibaba.druid.sql.ast.statement.SQLDeleteStatement) SQLInsertStatement(com.alibaba.druid.sql.ast.statement.SQLInsertStatement) SQLSelectStatement(com.alibaba.druid.sql.ast.statement.SQLSelectStatement) SchemaStatVisitor(com.alibaba.druid.sql.visitor.SchemaStatVisitor) MycatSchemaStatVisitor(io.mycat.route.parser.druid.MycatSchemaStatVisitor)

Example 4 with SQLStatement

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;
}
Also used : DruidShardingParseInfo(io.mycat.route.parser.druid.DruidShardingParseInfo) RouteCalculateUnit(io.mycat.route.parser.druid.RouteCalculateUnit) SQLStatementParser(com.alibaba.druid.sql.parser.SQLStatementParser) MycatStatementParser(io.mycat.route.parser.druid.MycatStatementParser) MycatSchemaStatVisitor(io.mycat.route.parser.druid.MycatSchemaStatVisitor) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) SQLNonTransientException(java.sql.SQLNonTransientException) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) SlotFunction(io.mycat.route.function.SlotFunction) DruidParser(io.mycat.route.parser.druid.DruidParser) TreeSet(java.util.TreeSet) RouteResultsetNode(io.mycat.route.RouteResultsetNode) RuleConfig(io.mycat.config.model.rule.RuleConfig) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) RouteResultset(io.mycat.route.RouteResultset)

Example 5 with SQLStatement

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;
    }
}
Also used : MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) SQLConstraint(com.alibaba.druid.sql.ast.statement.SQLConstraint) ValuesClause(com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause)

Aggregations

SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)1652 MySqlStatementParser (com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser)915 SQLStatementParser (com.alibaba.druid.sql.parser.SQLStatementParser)431 MySqlSchemaStatVisitor (com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor)346 OracleStatementParser (com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser)273 OracleSchemaStatVisitor (com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor)254 Column (com.alibaba.druid.stat.TableStat.Column)122 PGSQLStatementParser (com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser)109 PGSchemaStatVisitor (com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor)107 SQLServerStatementParser (com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser)100 SchemaStatVisitor (com.alibaba.druid.sql.visitor.SchemaStatVisitor)67 MySqlOutputVisitor (com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor)60 SQLServerSchemaStatVisitor (com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor)46 OdpsStatementParser (com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser)44 DB2SchemaStatVisitor (com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor)34 DB2StatementParser (com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser)33 Test (org.junit.Test)31 MysqlTest (com.alibaba.druid.sql.MysqlTest)29 ArrayList (java.util.ArrayList)29 SQLASTOutputVisitor (com.alibaba.druid.sql.visitor.SQLASTOutputVisitor)28