Search in sources :

Example 1 with Pair

use of io.mycat.util.Pair 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 2 with Pair

use of io.mycat.util.Pair in project Mycat2 by MyCATApache.

the class HackRouter method analyse.

public boolean analyse() {
    Set<Pair<String, String>> tableNames = new HashSet<>();
    Set<String> methods = new HashSet<>();
    AtomicBoolean hasVar = new AtomicBoolean(false);
    selectStatement.accept(new MySqlASTVisitorAdapter() {

        @Override
        public boolean visit(SQLExprTableSource x) {
            String tableName = x.getTableName();
            if (tableName != null) {
                String schema = Optional.ofNullable(x.getSchema()).orElse(defaultSchema);
                if (schema == null) {
                    throw new MycatException("please use schema;");
                }
                tableNames.add(Pair.of(SQLUtils.normalize(schema), SQLUtils.normalize(tableName)));
            }
            return super.visit(x);
        }

        @Override
        public boolean visit(SQLMethodInvokeExpr x) {
            methods.add(x.getMethodName());
            return super.visit(x);
        }

        @Override
        public boolean visit(SQLVariantRefExpr x) {
            if (!"?".equals(x.getName())) {
                hasVar.set(true);
            }
            return super.visit(x);
        }
    });
    this.metadataManager = MetaClusterCurrent.wrapper(MetadataManager.class);
    if (PUSH_DOWN_SELECT_DUAL && tableNames.isEmpty() && !hasVar.get()) {
        if (!methods.isEmpty() && methods.stream().noneMatch(name -> SQLRBORewriter.Information_Functions.containsKey(SQLUtils.normalize(name), false))) {
            targetMap = NameMap.immutableCopyOf(Collections.emptyMap());
            targetName = MetadataManager.getPrototype();
            return true;
        }
    }
    res = metadataManager.checkVaildNormalRoute(tableNames);
    if (res.isPresent()) {
        Distribution distribution = res.get();
        ImmutableMap.Builder<String, Partition> builder = ImmutableMap.builder();
        builder.putAll(distribution.getGlobalTables().stream().collect(Collectors.toMap(k -> k.getUniqueName(), v -> v.getDataNode())));
        Map<String, Partition> normalMap = distribution.getNormalTables().stream().collect(Collectors.toMap(k -> k.getUniqueName(), v -> v.getDataNode()));
        builder.putAll(normalMap);
        targetMap = NameMap.immutableCopyOf(builder.build());
        switch(distribution.type()) {
            case BROADCAST:
                List<Partition> globalDataNode = distribution.getGlobalTables().get(0).getGlobalDataNode();
                int i = ThreadLocalRandom.current().nextInt(0, globalDataNode.size());
                targetName = globalDataNode.get(i).getTargetName();
                return true;
            case SHARDING:
                return false;
            case PHY:
                {
                    targetName = normalMap.values().iterator().next().getTargetName();
                    return true;
                }
        }
    } else {
        return false;
    }
    return false;
}
Also used : MySqlASTVisitorAdapter(com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter) Distribution(io.mycat.calcite.rewriter.Distribution) Pair(io.mycat.util.Pair) java.util(java.util) SQLUtils(com.alibaba.druid.sql.SQLUtils) SQLMethodInvokeExpr(com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr) io.mycat(io.mycat) ImmutableMap(com.google.common.collect.ImmutableMap) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Collectors(java.util.stream.Collectors) SQLRBORewriter(io.mycat.calcite.rewriter.SQLRBORewriter) MycatSQLExprTableSourceUtil(io.mycat.util.MycatSQLExprTableSourceUtil) MySqlASTVisitorAdapter(com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter) NameMap(io.mycat.util.NameMap) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) SQLVariantRefExpr(com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr) SQLMethodInvokeExpr(com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr) ImmutableMap(com.google.common.collect.ImmutableMap) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Distribution(io.mycat.calcite.rewriter.Distribution) SQLVariantRefExpr(com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) Pair(io.mycat.util.Pair)

Example 3 with Pair

use of io.mycat.util.Pair 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

Pair (io.mycat.util.Pair)3 SQLUtils (com.alibaba.druid.sql.SQLUtils)2 SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)2 SQLExprTableSource (com.alibaba.druid.sql.ast.statement.SQLExprTableSource)2 io.mycat (io.mycat)2 HackRouter (io.mycat.prototypeserver.mysql.HackRouter)2 NameMap (io.mycat.util.NameMap)2 Future (io.vertx.core.Future)2 SQLMethodInvokeExpr (com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr)1 SQLVariantRefExpr (com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr)1 SQLCreateViewStatement (com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement)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 MySqlInsertStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement)1 MySqlUpdateStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement)1 MySqlASTVisitorAdapter (com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter)1 ImmutableMap (com.google.common.collect.ImmutableMap)1