Search in sources :

Example 1 with FetchStoreNodeOfChildTableHandler

use of io.mycat.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler in project Mycat-Server by MyCATApache.

the class DruidInsertParser method parserChildTable.

private RouteResultset parserChildTable(SchemaConfig schema, RouteResultset rrs, String tableName, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
    TableConfig tc = schema.getTables().get(tableName);
    String joinKey = tc.getJoinKey();
    int joinKeyIndex = getJoinKeyIndex(insertStmt.getColumns(), joinKey);
    if (joinKeyIndex == -1) {
        String inf = "joinKey not provided :" + tc.getJoinKey() + "," + insertStmt;
        LOGGER.warn(inf);
        throw new SQLNonTransientException(inf);
    }
    if (isMultiInsert(insertStmt)) {
        String msg = "ChildTable multi insert not provided";
        LOGGER.warn(msg);
        throw new SQLNonTransientException(msg);
    }
    String joinKeyVal = insertStmt.getValues().getValues().get(joinKeyIndex).toString();
    String sql = insertStmt.toString();
    // try to route by ER parent partion key
    RouteResultset theRrs = RouterUtil.routeByERParentKey(null, schema, ServerParse.INSERT, sql, rrs, tc, joinKeyVal);
    if (theRrs != null) {
        rrs.setFinishedRoute(true);
        return theRrs;
    }
    // route by sql query root parent's datanode
    String findRootTBSql = tc.getLocateRTableKeySql().toLowerCase() + joinKeyVal;
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("find root parent's node sql " + findRootTBSql);
    }
    FetchStoreNodeOfChildTableHandler fetchHandler = new FetchStoreNodeOfChildTableHandler();
    String dn = fetchHandler.execute(schema.getName(), findRootTBSql, tc.getRootParent().getDataNodes());
    if (dn == null) {
        throw new SQLNonTransientException("can't find (root) parent sharding node for sql:" + sql);
    }
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("found partion node for child table to insert " + dn + " sql :" + sql);
    }
    return RouterUtil.routeToSingleNode(rrs, dn, sql);
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) FetchStoreNodeOfChildTableHandler(io.mycat.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler) TableConfig(io.mycat.config.model.TableConfig) RouteResultset(io.mycat.route.RouteResultset)

Example 2 with FetchStoreNodeOfChildTableHandler

use of io.mycat.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler in project Mycat-Server by MyCATApache.

the class RouterUtil method processERChildTable.

public static boolean processERChildTable(final SchemaConfig schema, final String origSQL, final ServerConnection sc) throws SQLNonTransientException {
    String tableName = StringUtil.getTableName(origSQL).toUpperCase();
    final TableConfig tc = schema.getTables().get(tableName);
    //判断是否为子表,如果不是,只会返回false
    if (null != tc && tc.isChildTable()) {
        final RouteResultset rrs = new RouteResultset(origSQL, ServerParse.INSERT);
        String joinKey = tc.getJoinKey();
        //因为是Insert语句,用MySqlInsertStatement进行parse
        MySqlInsertStatement insertStmt = (MySqlInsertStatement) (new MySqlStatementParser(origSQL)).parseInsert();
        //判断条件完整性,取得解析后语句列中的joinkey列的index
        int joinKeyIndex = getJoinKeyIndex(insertStmt.getColumns(), joinKey);
        if (joinKeyIndex == -1) {
            String inf = "joinKey not provided :" + tc.getJoinKey() + "," + insertStmt;
            LOGGER.warn(inf);
            throw new SQLNonTransientException(inf);
        }
        //子表不支持批量插入
        if (isMultiInsert(insertStmt)) {
            String msg = "ChildTable multi insert not provided";
            LOGGER.warn(msg);
            throw new SQLNonTransientException(msg);
        }
        //取得joinkey的值
        String joinKeyVal = insertStmt.getValues().getValues().get(joinKeyIndex).toString();
        //解决bug #938,当关联字段的值为char类型时,去掉前后"'"
        String realVal = joinKeyVal;
        if (joinKeyVal.startsWith("'") && joinKeyVal.endsWith("'") && joinKeyVal.length() > 2) {
            realVal = joinKeyVal.substring(1, joinKeyVal.length() - 1);
        }
        String sql = insertStmt.toString();
        // try to route by ER parent partion key
        //如果是二级子表(父表不再有父表),并且分片字段正好是joinkey字段,调用routeByERParentKey
        RouteResultset theRrs = RouterUtil.routeByERParentKey(sc, schema, ServerParse.INSERT, sql, rrs, tc, realVal);
        if (theRrs != null) {
            boolean processedInsert = false;
            //判断是否需要全局序列号
            if (sc != null && tc.isAutoIncrement()) {
                String primaryKey = tc.getPrimaryKey();
                processedInsert = processInsert(sc, schema, ServerParse.INSERT, sql, tc.getName(), primaryKey);
            }
            if (processedInsert == false) {
                rrs.setFinishedRoute(true);
                sc.getSession2().execute(rrs, ServerParse.INSERT);
            }
            return true;
        }
        // route by sql query root parent's datanode
        //如果不是二级子表或者分片字段不是joinKey字段结果为空,则启动异步线程去后台分片查询出datanode
        //只要查询出上一级表的parentkey字段的对应值在哪个分片即可
        final String findRootTBSql = tc.getLocateRTableKeySql().toLowerCase() + joinKeyVal;
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("find root parent's node sql " + findRootTBSql);
        }
        ListenableFuture<String> listenableFuture = MycatServer.getInstance().getListeningExecutorService().submit(new Callable<String>() {

            @Override
            public String call() throws Exception {
                FetchStoreNodeOfChildTableHandler fetchHandler = new FetchStoreNodeOfChildTableHandler();
                //					return fetchHandler.execute(schema.getName(), findRootTBSql, tc.getRootParent().getDataNodes());
                return fetchHandler.execute(schema.getName(), findRootTBSql, tc.getRootParent().getDataNodes(), sc);
            }
        });
        Futures.addCallback(listenableFuture, new FutureCallback<String>() {

            @Override
            public void onSuccess(String result) {
                //结果为空,证明上一级表中不存在那条记录,失败
                if (Strings.isNullOrEmpty(result)) {
                    StringBuilder s = new StringBuilder();
                    LOGGER.warn(s.append(sc.getSession2()).append(origSQL).toString() + " err:" + "can't find (root) parent sharding node for sql:" + origSQL);
                    if (!sc.isAutocommit()) {
                        // 处于事务下失败, 必须回滚
                        sc.setTxInterrupt("can't find (root) parent sharding node for sql:" + origSQL);
                    }
                    sc.writeErrMessage(ErrorCode.ER_PARSE_ERROR, "can't find (root) parent sharding node for sql:" + origSQL);
                    return;
                }
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("found partion node for child table to insert " + result + " sql :" + origSQL);
                }
                //找到分片,进行插入(和其他的一样,需要判断是否需要全局自增ID)
                boolean processedInsert = false;
                if (sc != null && tc.isAutoIncrement()) {
                    try {
                        String primaryKey = tc.getPrimaryKey();
                        processedInsert = processInsert(sc, schema, ServerParse.INSERT, origSQL, tc.getName(), primaryKey);
                    } catch (SQLNonTransientException e) {
                        LOGGER.warn("sequence processInsert error,", e);
                        sc.writeErrMessage(ErrorCode.ER_PARSE_ERROR, "sequence processInsert error," + e.getMessage());
                    }
                }
                if (processedInsert == false) {
                    RouteResultset executeRrs = RouterUtil.routeToSingleNode(rrs, result, origSQL);
                    sc.getSession2().execute(executeRrs, ServerParse.INSERT);
                }
            }

            @Override
            public void onFailure(Throwable t) {
                StringBuilder s = new StringBuilder();
                LOGGER.warn(s.append(sc.getSession2()).append(origSQL).toString() + " err:" + t.getMessage());
                sc.writeErrMessage(ErrorCode.ER_PARSE_ERROR, t.getMessage() + " " + s.toString());
            }
        }, MycatServer.getInstance().getListeningExecutorService());
        return true;
    }
    return false;
}
Also used : FetchStoreNodeOfChildTableHandler(io.mycat.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler) MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement) SQLNonTransientException(java.sql.SQLNonTransientException) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) SQLNonTransientException(java.sql.SQLNonTransientException) TableConfig(io.mycat.config.model.TableConfig) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) RouteResultset(io.mycat.route.RouteResultset)

Aggregations

FetchStoreNodeOfChildTableHandler (io.mycat.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler)2 TableConfig (io.mycat.config.model.TableConfig)2 RouteResultset (io.mycat.route.RouteResultset)2 SQLNonTransientException (java.sql.SQLNonTransientException)2 MySqlInsertStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement)1 MySqlStatementParser (com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser)1 SQLSyntaxErrorException (java.sql.SQLSyntaxErrorException)1