Search in sources :

Example 1 with HackRouter

use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.

the class ExplainSQLHandler method onExecute.

@Override
@SneakyThrows
protected Future<Void> onExecute(SQLRequest<MySqlExplainStatement> request, MycatDataContext dataContext, Response response) {
    MySqlExplainStatement explainAst = request.getAst();
    explainAst.accept0(new MySqlASTVisitorAdapter() {

        @Override
        public boolean visit(SQLExprTableSource x) {
            if (x.getSchema() == null) {
                x.setSchema(dataContext.getDefaultSchema());
            }
            return super.visit(x);
        }
    });
    if (explainAst.isDescribe()) {
        SQLName tableName = explainAst.getTableName();
        if (tableName instanceof SQLIdentifierExpr && dataContext.getDefaultSchema() != null) {
            explainAst.setTableName(new SQLPropertyExpr(new SQLIdentifierExpr(dataContext.getDefaultSchema()), ((SQLIdentifierExpr) tableName).getName()));
        }
        return response.proxySelectToPrototype(explainAst.toUnformattedString(), Collections.emptyList());
    }
    SQLStatement statement = request.getAst().getStatement();
    boolean forUpdate = false;
    if (statement instanceof SQLSelectStatement) {
        forUpdate = ((SQLSelectStatement) explainAst.getStatement()).getSelect().getFirstQueryBlock().isForUpdate();
    }
    ResultSetBuilder builder = ResultSetBuilder.create().addColumnInfo("plan", JDBCType.VARCHAR);
    try {
        HackRouter hackRouter = new HackRouter(statement, dataContext);
        if (hackRouter.analyse()) {
            Pair<String, String> plan = hackRouter.getPlan();
            builder.addObjectRowPayload(Arrays.asList("targetName: " + plan.getKey() + "   sql: " + plan.getValue()));
        } else {
            List<SQLCommentHint> hints = explainAst.getHints();
            if (hints != null) {
                statement.setHeadHints(hints);
            }
            DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(statement, dataContext.getDefaultSchema());
            Plan plan;
            if (statement instanceof SQLInsertStatement || statement instanceof SQLUpdateStatement || statement instanceof SQLDeleteStatement) {
                plan = UpdateSQLHandler.getPlan(drdsSqlWithParams);
            } else {
                plan = DrdsRunnerHelper.getPlan(drdsSqlWithParams);
            }
            List<String> explain = plan.explain(dataContext, drdsSqlWithParams, true);
            for (String s1 : explain) {
                builder.addObjectRowPayload(Arrays.asList(s1));
            }
        }
    } catch (Throwable th) {
        LOGGER.error("", th);
        builder.addObjectRowPayload(Arrays.asList(th.toString()));
    }
    return response.sendResultSet(RowIterable.create(builder.build()));
}
Also used : MySqlExplainStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExplainStatement) MySqlASTVisitorAdapter(com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter) ResultSetBuilder(io.mycat.beans.mycat.ResultSetBuilder) SQLName(com.alibaba.druid.sql.ast.SQLName) SQLIdentifierExpr(com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr) SQLPropertyExpr(com.alibaba.druid.sql.ast.expr.SQLPropertyExpr) Plan(io.mycat.calcite.spm.Plan) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) HackRouter(io.mycat.prototypeserver.mysql.HackRouter) DrdsSqlWithParams(io.mycat.DrdsSqlWithParams) SQLCommentHint(com.alibaba.druid.sql.ast.SQLCommentHint) SneakyThrows(lombok.SneakyThrows)

Example 2 with HackRouter

use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.

the class CreateViewSQLHandler method onExecute.

@Override
protected Future<Void> onExecute(SQLRequest<SQLCreateViewStatement> request, MycatDataContext dataContext, Response response) {
    LockService lockService = MetaClusterCurrent.wrapper(LockService.class);
    SQLCreateViewStatement ast = request.getAst();
    resolveSQLExprTableSource(ast.getTableSource(), dataContext);
    return lockService.lock(DDL_LOCK, new Supplier<Future<Void>>() {

        @Override
        public Future<Void> get() {
            String schemaName = Optional.ofNullable(ast.getSchema()).orElse(dataContext.getDefaultSchema());
            schemaName = SQLUtils.normalize(schemaName);
            String viewName = SQLUtils.normalize(ast.getName().getSimpleName());
            SQLSelect subQuery = ast.getSubQuery();
            SQLSelectStatement sqlSelectStatement = new SQLSelectStatement();
            sqlSelectStatement.setSelect(subQuery);
            List<String> aliasList = Optional.ofNullable(ast.getColumns()).orElse(Collections.emptyList()).stream().map(i -> SQLUtils.normalize(i.toString())).collect(Collectors.toList());
            HackRouter hackRouter = new HackRouter(sqlSelectStatement, dataContext);
            boolean distSql = !hackRouter.analyse();
            try (MycatRouterConfigOps ops = ConfigUpdater.getOps()) {
                if (!distSql) {
                    Pair<String, String> plan = hackRouter.getPlan();
                    JdbcConnectionManager jdbcConnectionManager = MetaClusterCurrent.wrapper(JdbcConnectionManager.class);
                    try (DefaultConnection connection = jdbcConnectionManager.getConnection(plan.getKey())) {
                        Connection rawConnection = connection.getRawConnection();
                        Statement statement = rawConnection.createStatement();
                        statement.setMaxRows(0);
                        MycatRowMetaData metaData = connection.executeQuery(plan.getValue()).getMetaData();
                        if (!aliasList.isEmpty()) {
                            metaData = RenameMycatRowMetaData.of(metaData, aliasList);
                        }
                        String createTableSql = PrototypeService.generateSql(schemaName, viewName, metaData.metaData());
                        ops.putNormalTable(schemaName, viewName, (MySqlCreateTableStatement) SQLUtils.parseSingleMysqlStatement(createTableSql));
                        statement.close();
                        try {
                            SQLSelectStatement phySQLSelectStatement = (SQLSelectStatement) SQLUtils.parseSingleMysqlStatement(plan.getValue());
                            ast.setSubQuery(phySQLSelectStatement.getSelect());
                            // 建立物理视图
                            JdbcUtils.execute(rawConnection, ast.toString());
                        } catch (Throwable throwable) {
                            LOGGER.error("build phy view fail", throwable);
                        }
                    }
                } else {
                    ops.addView(schemaName, viewName, ast.toString());
                }
                ops.commit();
                return response.sendOk();
            } catch (Throwable throwable) {
                return Future.failedFuture(throwable);
            }
        }
    });
}
Also used : SQLSelect(com.alibaba.druid.sql.ast.statement.SQLSelect) SQLCreateViewStatement(com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement) MySqlCreateTableStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement) Statement(java.sql.Statement) SQLSelectStatement(com.alibaba.druid.sql.ast.statement.SQLSelectStatement) Connection(java.sql.Connection) DefaultConnection(io.mycat.datasource.jdbc.datasource.DefaultConnection) MycatRouterConfigOps(io.mycat.config.MycatRouterConfigOps) HackRouter(io.mycat.prototypeserver.mysql.HackRouter) DefaultConnection(io.mycat.datasource.jdbc.datasource.DefaultConnection) SQLCreateViewStatement(com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement) Future(io.vertx.core.Future) SQLSelectStatement(com.alibaba.druid.sql.ast.statement.SQLSelectStatement) List(java.util.List) JdbcConnectionManager(io.mycat.datasource.jdbc.datasource.JdbcConnectionManager) MySqlCreateTableStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement) Pair(io.mycat.util.Pair) MycatRowMetaData(io.mycat.beans.mycat.MycatRowMetaData) RenameMycatRowMetaData(io.mycat.beans.mycat.RenameMycatRowMetaData)

Example 3 with HackRouter

use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.

the class ShardingSQLHandler method onExecute.

@Override
protected Future<Void> onExecute(SQLRequest<SQLSelectStatement> request, MycatDataContext dataContext, Response response) {
    Optional<Future<Void>> op = Optional.empty();
    if (dataContext.isDebug()) {
        op = testExample(request, dataContext, response);
        if (op.isPresent())
            return op.get();
    }
    DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(request.getAst(), dataContext.getDefaultSchema());
    HackRouter hackRouter = new HackRouter(drdsSqlWithParams.getParameterizedStatement(), dataContext);
    try {
        if (hackRouter.analyse()) {
            Pair<String, String> plan = hackRouter.getPlan();
            return response.proxySelect(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
        } else {
            return DrdsRunnerHelper.runOnDrds(dataContext, drdsSqlWithParams, response);
        }
    } catch (Throwable throwable) {
        LOGGER.error(request.getAst().toString(), throwable);
        return Future.failedFuture(throwable);
    }
}
Also used : Future(io.vertx.core.Future) DrdsSqlWithParams(io.mycat.DrdsSqlWithParams) HackRouter(io.mycat.prototypeserver.mysql.HackRouter)

Example 4 with HackRouter

use of io.mycat.prototypeserver.mysql.HackRouter in project Mycat2 by MyCATApache.

the class UpdateSQLHandler method updateHandler.

@SneakyThrows
public static Future<Void> updateHandler(SQLStatement sqlStatement, MycatDataContext dataContext, SQLTableSource tableSourceArg, Response receiver) {
    boolean insert = sqlStatement instanceof SQLInsertStatement;
    if (tableSourceArg instanceof SQLExprTableSource) {
        SQLExprTableSource tableSource = (SQLExprTableSource) tableSourceArg;
        String schemaName = Optional.ofNullable(tableSource.getSchema() == null ? dataContext.getDefaultSchema() : tableSource.getSchema()).map(i -> SQLUtils.normalize(i)).orElse(null);
        String tableName = SQLUtils.normalize(tableSource.getTableName());
        if (schemaName == null) {
            return receiver.sendError("unknown schema", MySQLErrorCode.ER_UNKNOWN_ERROR);
        }
        tableSource.setSchema(schemaName);
        SchemaHandler schemaHandler;
        MetadataManager metadataManager = MetaClusterCurrent.wrapper(MetadataManager.class);
        Optional<NameMap<SchemaHandler>> handlerMapOptional = Optional.ofNullable(metadataManager.getSchemaMap());
        Optional<String> targetNameOptional = Optional.ofNullable(metadataManager.getPrototype());
        if (!handlerMapOptional.isPresent()) {
            if (targetNameOptional.isPresent()) {
                if (insert) {
                    DrdsSqlWithParams drdsSqlWithParams = MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement);
                    return receiver.proxyInsert(Collections.singletonList(targetNameOptional.get()), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
                } else {
                    DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
                    return receiver.proxyUpdate(Collections.singletonList(targetNameOptional.get()), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
                }
            } else {
                return receiver.sendError(new MycatException("Unable to route:" + sqlStatement));
            }
        } else {
            NameMap<SchemaHandler> handlerMap = handlerMapOptional.get();
            schemaHandler = Optional.ofNullable(handlerMap.get(schemaName)).orElseGet(() -> {
                if (dataContext.getDefaultSchema() == null) {
                    // 可能schemaName有值,但是值名不是配置的名字
                    throw new MycatException("unknown schema:" + schemaName);
                }
                return handlerMap.get(dataContext.getDefaultSchema());
            });
            if (schemaHandler == null) {
                return receiver.sendError(new MycatException("Unable to route:" + sqlStatement));
            }
        }
        String defaultTargetName = schemaHandler.defaultTargetName();
        NameMap<TableHandler> tableMap = schemaHandler.logicTables();
        TableHandler tableHandler = tableMap.get(tableName);
        // /////////////////////////////common///////////////////////////////
        if (tableHandler == null) {
            if (insert) {
                DrdsSqlWithParams drdsSqlWithParams = MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement);
                return receiver.proxyInsert(Collections.singletonList(Objects.requireNonNull(defaultTargetName, "can not route :" + drdsSqlWithParams)), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
            } else {
                DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, null);
                return receiver.proxyUpdate(Collections.singletonList(Objects.requireNonNull(defaultTargetName, "can not route :" + drdsSqlWithParams)), drdsSqlWithParams.getParameterizedSQL(), drdsSqlWithParams.getParams());
            }
        }
        switch(tableHandler.getType()) {
            case NORMAL:
                DrdsSqlWithParams drdsSqlWithParams;
                if (insert) {
                    drdsSqlWithParams = MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement);
                } else {
                    drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
                }
                HackRouter hackRouter = new HackRouter(drdsSqlWithParams.getParameterizedStatement(), dataContext);
                if (hackRouter.analyse()) {
                    Pair<String, String> plan = hackRouter.getPlan();
                    if (insert) {
                        return receiver.proxyInsert(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
                    } else {
                        return receiver.proxyUpdate(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
                    }
                }
                break;
            default:
                break;
        }
        DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
        return executeUpdate(drdsSqlWithParams, dataContext, receiver, schemaName);
    }
    DrdsSqlWithParams drdsSqlWithParams = insert ? MycatPreparedStatementUtil.outputToParameterizedProxySql((MySqlInsertStatement) sqlStatement) : DrdsRunnerHelper.preParse(sqlStatement, dataContext.getDefaultSchema());
    HackRouter hackRouter = new HackRouter(drdsSqlWithParams.getParameterizedStatement(), dataContext);
    if (hackRouter.analyse()) {
        Pair<String, String> plan = hackRouter.getPlan();
        if (insert) {
            return receiver.proxyInsert(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
        } else {
            return receiver.proxyUpdate(Collections.singletonList(plan.getKey()), plan.getValue(), drdsSqlWithParams.getParams());
        }
    }
    return receiver.sendError(new MycatException("can not route " + sqlStatement));
}
Also used : io.mycat(io.mycat) HackRouter(io.mycat.prototypeserver.mysql.HackRouter) SneakyThrows(lombok.SneakyThrows) SQLRequest(io.mycat.sqlhandler.SQLRequest) UpdatePlanCache(io.mycat.calcite.spm.UpdatePlanCache) SchemaHandler(io.mycat.calcite.table.SchemaHandler) MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement) MySqlUpdateStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement) PlanImplementor(io.mycat.calcite.plan.PlanImplementor) MycatRel(io.mycat.calcite.MycatRel) MySQLErrorCode(io.mycat.beans.mysql.MySQLErrorCode) OptimizationContext(io.mycat.calcite.rewriter.OptimizationContext) Pair(io.mycat.util.Pair) SQLUtils(com.alibaba.druid.sql.SQLUtils) SQLInsertStatement(com.alibaba.druid.sql.ast.statement.SQLInsertStatement) AbstractSQLHandler(io.mycat.sqlhandler.AbstractSQLHandler) Future(io.vertx.core.Future) Objects(java.util.Objects) Nullable(org.jetbrains.annotations.Nullable) SQLTableSource(com.alibaba.druid.sql.ast.statement.SQLTableSource) NameMap(io.mycat.util.NameMap) MycatPreparedStatementUtil(io.mycat.calcite.executor.MycatPreparedStatementUtil) Optional(java.util.Optional) DrdsRunnerHelper(io.mycat.calcite.DrdsRunnerHelper) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) Collections(java.util.Collections) Plan(io.mycat.calcite.spm.Plan) SchemaHandler(io.mycat.calcite.table.SchemaHandler) NameMap(io.mycat.util.NameMap) MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement) HackRouter(io.mycat.prototypeserver.mysql.HackRouter) SQLInsertStatement(com.alibaba.druid.sql.ast.statement.SQLInsertStatement) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) SneakyThrows(lombok.SneakyThrows)

Aggregations

HackRouter (io.mycat.prototypeserver.mysql.HackRouter)4 Future (io.vertx.core.Future)3 SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)2 DrdsSqlWithParams (io.mycat.DrdsSqlWithParams)2 Plan (io.mycat.calcite.spm.Plan)2 Pair (io.mycat.util.Pair)2 SneakyThrows (lombok.SneakyThrows)2 SQLUtils (com.alibaba.druid.sql.SQLUtils)1 SQLCommentHint (com.alibaba.druid.sql.ast.SQLCommentHint)1 SQLName (com.alibaba.druid.sql.ast.SQLName)1 SQLIdentifierExpr (com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr)1 SQLPropertyExpr (com.alibaba.druid.sql.ast.expr.SQLPropertyExpr)1 SQLCreateViewStatement (com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement)1 SQLExprTableSource (com.alibaba.druid.sql.ast.statement.SQLExprTableSource)1 SQLInsertStatement (com.alibaba.druid.sql.ast.statement.SQLInsertStatement)1 SQLSelect (com.alibaba.druid.sql.ast.statement.SQLSelect)1 SQLSelectStatement (com.alibaba.druid.sql.ast.statement.SQLSelectStatement)1 SQLTableSource (com.alibaba.druid.sql.ast.statement.SQLTableSource)1 MySqlCreateTableStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement)1 MySqlExplainStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExplainStatement)1