Search in sources :

Example 6 with TableConfig

use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.

the class DruidInsertParser method visitorParse.

@Override
public SchemaConfig visitorParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt, ServerSchemaStatVisitor visitor, ServerConnection sc) throws SQLException {
    MySqlInsertStatement insert = (MySqlInsertStatement) stmt;
    String schemaName = schema == null ? null : schema.getName();
    SQLExprTableSource tableSource = insert.getTableSource();
    SchemaInfo schemaInfo = SchemaUtil.getSchemaInfo(sc.getUser(), schemaName, tableSource);
    if (!ServerPrivileges.checkPrivilege(sc, schemaInfo.getSchema(), schemaInfo.getTable(), CheckType.INSERT)) {
        String msg = "The statement DML privilege check is not passed, sql:" + stmt;
        throw new SQLNonTransientException(msg);
    }
    schema = schemaInfo.getSchemaConfig();
    String tableName = schemaInfo.getTable();
    if (parserNoSharding(sc, schemaName, schemaInfo, rrs, insert)) {
        return schema;
    }
    if (insert.getQuery() != null) {
        // insert into .... select ....
        String msg = "`INSERT ... SELECT Syntax` is not supported!";
        LOGGER.info(msg);
        throw new SQLNonTransientException(msg);
    }
    TableConfig tc = schema.getTables().get(tableName);
    if (tc == null) {
        String msg = "Table '" + schema.getName() + "." + tableName + "' doesn't exist";
        throw new SQLException(msg, "42S02", ErrorCode.ER_NO_SUCH_TABLE);
    }
    if (tc.isGlobalTable()) {
        String sql = rrs.getStatement();
        if (tc.isAutoIncrement() || GlobalTableUtil.useGlobalTableCheck()) {
            sql = convertInsertSQL(schemaInfo, insert, sql, tc, GlobalTableUtil.useGlobalTableCheck());
        } else {
            sql = RouterUtil.removeSchema(sql, schemaInfo.getSchema());
        }
        rrs.setStatement(sql);
        RouterUtil.routeToMultiNode(false, rrs, tc.getDataNodes(), tc.isGlobalTable());
        rrs.setFinishedRoute(true);
        return schema;
    }
    if (tc.isAutoIncrement()) {
        String sql = convertInsertSQL(schemaInfo, insert, rrs.getStatement(), tc, false);
        rrs.setStatement(sql);
        SQLStatementParser parser = new MySqlStatementParser(sql);
        stmt = parser.parseStatement();
        insert = (MySqlInsertStatement) stmt;
    }
    // insert childTable will finished router while parser
    if (tc.getParentTC() != null) {
        parserChildTable(schemaInfo, rrs, insert, sc);
        return schema;
    }
    String partitionColumn = tc.getPartitionColumn();
    if (partitionColumn != null) {
        if (isMultiInsert(insert)) {
            parserBatchInsert(schemaInfo, rrs, partitionColumn, insert);
        } else {
            parserSingleInsert(schemaInfo, rrs, partitionColumn, insert);
        }
    } else {
        rrs.setStatement(RouterUtil.removeSchema(rrs.getStatement(), schemaInfo.getSchema()));
        ctx.addTable(tableName);
    }
    return schema;
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) SQLStatementParser(com.alibaba.druid.sql.parser.SQLStatementParser) SQLException(java.sql.SQLException) TableConfig(com.actiontech.dble.config.model.TableConfig) MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) SchemaInfo(com.actiontech.dble.server.util.SchemaUtil.SchemaInfo)

Example 7 with TableConfig

use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.

the class DruidInsertParser method parserSingleInsert.

/**
 * @param schemaInfo SchemaInfo
 * @param rrs RouteResultset
 * @param partitionColumn partitionColumn
 * @param insertStmt insertStmt
 * @throws SQLNonTransientException if not find an valid data node
 */
private void parserSingleInsert(SchemaInfo schemaInfo, RouteResultset rrs, String partitionColumn, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
    int shardingColIndex = tryGetShardingColIndex(schemaInfo, insertStmt, partitionColumn);
    SQLExpr valueExpr = insertStmt.getValues().getValues().get(shardingColIndex);
    String shardingValue = shardingValueToSting(valueExpr);
    TableConfig tableConfig = schemaInfo.getSchemaConfig().getTables().get(schemaInfo.getTable());
    AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
    Integer nodeIndex = algorithm.calculate(shardingValue);
    if (nodeIndex == null || nodeIndex >= tableConfig.getDataNodes().size()) {
        String msg = "can't find any valid data node :" + schemaInfo.getTable() + " -> " + partitionColumn + " -> " + shardingValue;
        LOGGER.info(msg);
        throw new SQLNonTransientException(msg);
    }
    RouteResultsetNode[] nodes = new RouteResultsetNode[1];
    nodes[0] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex), rrs.getSqlType(), RouterUtil.removeSchema(insertStmt.toString(), schemaInfo.getSchema()));
    // INSERT INTO TABLEName (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
    if (insertStmt.getDuplicateKeyUpdate() != null) {
        List<SQLExpr> updateList = insertStmt.getDuplicateKeyUpdate();
        for (SQLExpr expr : updateList) {
            SQLBinaryOpExpr opExpr = (SQLBinaryOpExpr) expr;
            String column = StringUtil.removeBackQuote(opExpr.getLeft().toString().toUpperCase());
            if (column.equals(partitionColumn)) {
                String msg = "Sharding column can't be updated: " + schemaInfo.getTable() + " -> " + partitionColumn;
                LOGGER.info(msg);
                throw new SQLNonTransientException(msg);
            }
        }
    }
    rrs.setNodes(nodes);
    rrs.setFinishedRoute(true);
}
Also used : AbstractPartitionAlgorithm(com.actiontech.dble.route.function.AbstractPartitionAlgorithm) SQLNonTransientException(java.sql.SQLNonTransientException) RouteResultsetNode(com.actiontech.dble.route.RouteResultsetNode) TableConfig(com.actiontech.dble.config.model.TableConfig) SQLBinaryOpExpr(com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr)

Example 8 with TableConfig

use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.

the class DruidLockTableParser method visitorParse.

@Override
public SchemaConfig visitorParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt, ServerSchemaStatVisitor visitor, ServerConnection sc) throws SQLNonTransientException {
    // for lock tables table1 write, table2
    // DruidParser can only parser table1,
    // use "," to judge
    String sql = rrs.getStatement();
    sql = sql.replaceAll("\n", " ").replaceAll("\t", " ");
    String[] stmts = SplitUtil.split(sql, ',', true);
    // contains ","
    if (stmts.length > 1) {
        String tmpStmt = null;
        String[] tmpWords = null;
        for (int i = 1; i < stmts.length; i++) {
            tmpStmt = stmts[i];
            tmpWords = SplitUtil.split(tmpStmt, ' ', true);
            if (tmpWords.length == 2 && ("READ".equalsIgnoreCase(tmpWords[1]) || "WRITE".equalsIgnoreCase(tmpWords[1]))) {
                // unsupport lock multi-table
                continue;
            } else {
                // unsupport lock multi-table
                throw new SQLNonTransientException("You have an error in your SQL syntax, don't support lock multi tables!");
            }
        }
        LOGGER.info("can't lock multi-table");
        throw new SQLNonTransientException("can't lock multi-table");
    }
    MySqlLockTableStatement lockTableStat = (MySqlLockTableStatement) stmt;
    String table = lockTableStat.getTableSource().toString();
    if (DbleServer.getInstance().getSystemVariables().isLowerCaseTableNames()) {
        table = table.toLowerCase();
    }
    TableConfig tableConfig = schema.getTables().get(table);
    if (tableConfig == null) {
        String msg = "can't find table define of " + table + " in schema:" + schema.getName();
        LOGGER.info(msg);
        throw new SQLNonTransientException(msg);
    }
    LockType lockType = lockTableStat.getLockType();
    if (LockType.WRITE != lockType && LockType.READ != lockType) {
        String msg = "lock type must be write or read";
        LOGGER.info(msg);
        throw new SQLNonTransientException(msg);
    }
    List<String> dataNodes = tableConfig.getDataNodes();
    RouteResultsetNode[] nodes = new RouteResultsetNode[dataNodes.size()];
    for (int i = 0; i < dataNodes.size(); i++) {
        nodes[i] = new RouteResultsetNode(dataNodes.get(i), ServerParse.LOCK, stmt.toString());
    }
    rrs.setNodes(nodes);
    rrs.setFinishedRoute(true);
    return schema;
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) MySqlLockTableStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement) RouteResultsetNode(com.actiontech.dble.route.RouteResultsetNode) TableConfig(com.actiontech.dble.config.model.TableConfig) LockType(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlLockTableStatement.LockType)

Example 9 with TableConfig

use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.

the class DruidReplaceParser method parserBatchInsert.

/**
 * insert into .... select .... OR insert into table() values (),(),....
 *
 * @param schemaInfo SchemaInfo
 * @param rrs RouteResultset
 * @param partitionColumn partitionColumn
 * @param replace MySqlReplaceStatement
 * @throws SQLNonTransientException  if the column size of values is not correct
 */
private void parserBatchInsert(SchemaInfo schemaInfo, RouteResultset rrs, String partitionColumn, MySqlReplaceStatement replace) throws SQLNonTransientException {
    // insert into table() values (),(),....
    SchemaConfig schema = schemaInfo.getSchemaConfig();
    String tableName = schemaInfo.getTable();
    // column number
    int columnNum = getTableColumns(schemaInfo, replace.getColumns());
    int shardingColIndex = tryGetShardingColIndex(schemaInfo, replace, partitionColumn);
    List<SQLInsertStatement.ValuesClause> valueClauseList = replace.getValuesList();
    Map<Integer, List<SQLInsertStatement.ValuesClause>> nodeValuesMap = new HashMap<>();
    TableConfig tableConfig = schema.getTables().get(tableName);
    AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
    for (SQLInsertStatement.ValuesClause valueClause : valueClauseList) {
        if (valueClause.getValues().size() != columnNum) {
            String msg = "bad insert sql columnSize != valueSize:" + columnNum + " != " + valueClause.getValues().size() + "values:" + valueClause;
            LOGGER.info(msg);
            throw new SQLNonTransientException(msg);
        }
        SQLExpr expr = valueClause.getValues().get(shardingColIndex);
        String shardingValue = shardingValueToSting(expr);
        Integer nodeIndex = algorithm.calculate(shardingValue);
        // no part find for this record
        if (nodeIndex == null) {
            String msg = "can't find any valid datanode :" + tableName + " -> " + partitionColumn + " -> " + shardingValue;
            LOGGER.info(msg);
            throw new SQLNonTransientException(msg);
        }
        if (nodeValuesMap.get(nodeIndex) == null) {
            nodeValuesMap.put(nodeIndex, new ArrayList<SQLInsertStatement.ValuesClause>());
        }
        nodeValuesMap.get(nodeIndex).add(valueClause);
    }
    RouteResultsetNode[] nodes = new RouteResultsetNode[nodeValuesMap.size()];
    int count = 0;
    for (Map.Entry<Integer, List<SQLInsertStatement.ValuesClause>> node : nodeValuesMap.entrySet()) {
        Integer nodeIndex = node.getKey();
        List<SQLInsertStatement.ValuesClause> valuesList = node.getValue();
        ReplaceTemp temp = new ReplaceTemp(replace);
        temp.setValuesList(valuesList);
        nodes[count] = new RouteResultsetNode(tableConfig.getDataNodes().get(nodeIndex), rrs.getSqlType(), RouterUtil.removeSchema(temp.toString(), schemaInfo.getSchema()));
        count++;
    }
    rrs.setNodes(nodes);
    rrs.setFinishedRoute(true);
}
Also used : AbstractPartitionAlgorithm(com.actiontech.dble.route.function.AbstractPartitionAlgorithm) SchemaConfig(com.actiontech.dble.config.model.SchemaConfig) ReplaceTemp(com.actiontech.dble.route.parser.druid.ReplaceTemp) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) SQLNonTransientException(java.sql.SQLNonTransientException) RouteResultsetNode(com.actiontech.dble.route.RouteResultsetNode) SQLInsertStatement(com.alibaba.druid.sql.ast.statement.SQLInsertStatement) TableConfig(com.actiontech.dble.config.model.TableConfig)

Example 10 with TableConfig

use of com.actiontech.dble.config.model.TableConfig in project dble by actiontech.

the class DruidReplaceParser method visitorParse.

@Override
public SchemaConfig visitorParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt, ServerSchemaStatVisitor visitor, ServerConnection sc) throws SQLException {
    // data & object prepare
    MySqlReplaceStatement replace = (MySqlReplaceStatement) stmt;
    String schemaName = schema == null ? null : schema.getName();
    SQLExprTableSource tableSource = replace.getTableSource();
    SchemaInfo schemaInfo = SchemaUtil.getSchemaInfo(sc.getUser(), schemaName, tableSource);
    // privilege check
    if (!ServerPrivileges.checkPrivilege(sc, schemaInfo.getSchema(), schemaInfo.getTable(), ServerPrivileges.CheckType.INSERT)) {
        String msg = "The statement DML privilege check is not passed, sql:" + stmt;
        throw new SQLNonTransientException(msg);
    }
    // No sharding table check
    schema = schemaInfo.getSchemaConfig();
    String tableName = schemaInfo.getTable();
    if (parserNoSharding(sc, schemaName, schemaInfo, rrs, replace)) {
        return schema;
    }
    if (replace.getQuery() != null) {
        // replace into ...select with sharding not supported
        String msg = "`INSERT ... SELECT Syntax` is not supported!";
        LOGGER.info(msg);
        throw new SQLNonTransientException(msg);
    }
    // check the config of target table
    TableConfig tc = schema.getTables().get(tableName);
    if (tc == null) {
        String msg = "Table '" + schema.getName() + "." + tableName + "' doesn't exist";
        throw new SQLException(msg, "42S02", ErrorCode.ER_NO_SUCH_TABLE);
    }
    // if the target table is global table than
    if (tc.isGlobalTable()) {
        String sql = rrs.getStatement();
        if (tc.isAutoIncrement() || GlobalTableUtil.useGlobalTableCheck()) {
            sql = convertReplaceSQL(schemaInfo, replace, sql, tc, GlobalTableUtil.useGlobalTableCheck(), sc);
        } else {
            sql = RouterUtil.removeSchema(sql, schemaInfo.getSchema());
        }
        rrs.setStatement(sql);
        RouterUtil.routeToMultiNode(false, rrs, tc.getDataNodes(), tc.isGlobalTable());
        rrs.setFinishedRoute(true);
        return schema;
    }
    if (tc.isAutoIncrement()) {
        String sql = convertReplaceSQL(schemaInfo, replace, rrs.getStatement(), tc, false, sc);
        rrs.setStatement(sql);
        SQLStatementParser parser = new MySqlStatementParser(sql);
        stmt = parser.parseStatement();
        replace = (MySqlReplaceStatement) stmt;
    }
    // childTable can be route in this part
    if (tc.getParentTC() != null) {
        parserChildTable(schemaInfo, rrs, replace, sc);
        return schema;
    }
    String partitionColumn = tc.getPartitionColumn();
    if (partitionColumn != null) {
        if (isMultiReplace(replace)) {
            parserBatchInsert(schemaInfo, rrs, partitionColumn, replace);
        } else {
            parserSingleInsert(schemaInfo, rrs, partitionColumn, replace);
        }
    } else {
        rrs.setStatement(RouterUtil.removeSchema(rrs.getStatement(), schemaInfo.getSchema()));
        ctx.addTable(tableName);
    }
    return schema;
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) SQLStatementParser(com.alibaba.druid.sql.parser.SQLStatementParser) MySqlReplaceStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement) SQLException(java.sql.SQLException) TableConfig(com.actiontech.dble.config.model.TableConfig) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) SchemaInfo(com.actiontech.dble.server.util.SchemaUtil.SchemaInfo)

Aggregations

TableConfig (com.actiontech.dble.config.model.TableConfig)32 SchemaConfig (com.actiontech.dble.config.model.SchemaConfig)16 SQLNonTransientException (java.sql.SQLNonTransientException)16 SQLException (java.sql.SQLException)7 RouteResultsetNode (com.actiontech.dble.route.RouteResultsetNode)6 SchemaInfo (com.actiontech.dble.server.util.SchemaUtil.SchemaInfo)5 RouteResultset (com.actiontech.dble.route.RouteResultset)4 AbstractPartitionAlgorithm (com.actiontech.dble.route.function.AbstractPartitionAlgorithm)4 SQLExpr (com.alibaba.druid.sql.ast.SQLExpr)4 SQLExprTableSource (com.alibaba.druid.sql.ast.statement.SQLExprTableSource)4 MySqlStatementParser (com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser)4 CacheService (com.actiontech.dble.cache.CacheService)3 ServerConfig (com.actiontech.dble.config.ServerConfig)3 SQLStatementParser (com.alibaba.druid.sql.parser.SQLStatementParser)3 Matcher (java.util.regex.Matcher)3 PhysicalDBNode (com.actiontech.dble.backend.datasource.PhysicalDBNode)2 FetchStoreNodeOfChildTableHandler (com.actiontech.dble.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler)2 EOFPacket (com.actiontech.dble.net.mysql.EOFPacket)2 FieldPacket (com.actiontech.dble.net.mysql.FieldPacket)2 RowDataPacket (com.actiontech.dble.net.mysql.RowDataPacket)2