Search in sources :

Example 1 with SQLStatement

use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.

the class MySQLDataNode method setHeartbeat.

private void setHeartbeat(String heartbeat) {
    if (heartbeat == null) {
        heartbeatAST = null;
        placeHolderToStringer = null;
        return;
    }
    try {
        final Set<PlaceHolder> plist = new HashSet<PlaceHolder>(1, 1);
        SQLStatement ast = SQLParserDelegate.parse(heartbeat);
        ast.accept(new EmptySQLASTVisitor() {

            @Override
            public void visit(PlaceHolder node) {
                plist.add(node);
            }
        });
        if (plist.isEmpty()) {
            heartbeatAST = null;
            placeHolderToStringer = null;
            return;
        }
        Map<PlaceHolder, Object> phm = new HashMap<PlaceHolder, Object>(plist.size(), 1);
        for (PlaceHolder ph : plist) {
            final String content = ph.getName();
            final int low = Integer.parseInt(content.substring(content.indexOf('(') + 1, content.indexOf(',')).trim());
            final int high = Integer.parseInt(content.substring(content.indexOf(',') + 1, content.indexOf(')')).trim());
            phm.put(ph, new Object() {

                private Random rnd = new Random();

                @Override
                public String toString() {
                    return String.valueOf(rnd.nextInt(high - low + 1) + low);
                }
            });
        }
        heartbeatAST = ast;
        placeHolderToStringer = phm;
    } catch (SQLSyntaxErrorException e) {
        throw new ConfigException("heartbeat syntax err: " + heartbeat, e);
    }
}
Also used : EmptySQLASTVisitor(com.alibaba.cobar.parser.visitor.EmptySQLASTVisitor) PlaceHolder(com.alibaba.cobar.parser.ast.expression.primary.PlaceHolder) HashMap(java.util.HashMap) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) ConfigException(com.alibaba.cobar.config.util.ConfigException) SQLStatement(com.alibaba.cobar.parser.ast.stmt.SQLStatement) Random(java.util.Random) HashSet(java.util.HashSet)

Example 2 with SQLStatement

use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.

the class ServerRouter method route.

public static RouteResultset route(SchemaConfig schema, String stmt, String charset, Object info) throws SQLNonTransientException {
    RouteResultset rrs = new RouteResultset(stmt);
    // 检查是否含有cobar hint
    int prefixIndex = HintRouter.indexOfPrefix(stmt);
    if (prefixIndex >= 0) {
        HintRouter.routeFromHint(info, schema, rrs, prefixIndex, stmt);
        return rrs;
    }
    // 检查schema是否含有拆分库
    if (schema.isNoSharding()) {
        if (schema.isKeepSqlSchema()) {
            SQLStatement ast = SQLParserDelegate.parse(stmt, charset == null ? MySQLParser.DEFAULT_CHARSET : charset);
            PartitionKeyVisitor visitor = new PartitionKeyVisitor(schema.getTables());
            visitor.setTrimSchema(schema.getName());
            ast.accept(visitor);
            if (visitor.isSchemaTrimmed()) {
                stmt = genSQL(ast, stmt);
            }
        }
        RouteResultsetNode[] nodes = new RouteResultsetNode[1];
        nodes[0] = new RouteResultsetNode(schema.getDataNode(), stmt);
        rrs.setNodes(nodes);
        return rrs;
    }
    // 生成和展开AST
    SQLStatement ast = SQLParserDelegate.parse(stmt, charset == null ? MySQLParser.DEFAULT_CHARSET : charset);
    PartitionKeyVisitor visitor = new PartitionKeyVisitor(schema.getTables());
    visitor.setTrimSchema(schema.isKeepSqlSchema() ? schema.getName() : null);
    ast.accept(visitor);
    // 如果sql包含用户自定义的schema,则路由到default节点
    if (schema.isKeepSqlSchema() && visitor.isCustomedSchema()) {
        if (visitor.isSchemaTrimmed()) {
            stmt = genSQL(ast, stmt);
        }
        RouteResultsetNode[] nodes = new RouteResultsetNode[1];
        nodes[0] = new RouteResultsetNode(schema.getDataNode(), stmt);
        rrs.setNodes(nodes);
        return rrs;
    }
    // 元数据语句路由
    if (visitor.isTableMetaRead()) {
        MetaRouter.routeForTableMeta(rrs, schema, ast, visitor, stmt);
        if (visitor.isNeedRewriteField()) {
            rrs.setFlag(RouteResultset.REWRITE_FIELD);
        }
        return rrs;
    }
    // 匹配规则
    TableConfig matchedTable = null;
    RuleConfig rule = null;
    Map<String, List<Object>> columnValues = null;
    Map<String, Map<String, List<Object>>> astExt = visitor.getColumnValue();
    Map<String, TableConfig> tables = schema.getTables();
    ft: for (Entry<String, Map<String, List<Object>>> e : astExt.entrySet()) {
        Map<String, List<Object>> col2Val = e.getValue();
        TableConfig tc = tables.get(e.getKey());
        if (tc == null) {
            continue;
        }
        if (matchedTable == null) {
            matchedTable = tc;
        }
        if (col2Val == null || col2Val.isEmpty()) {
            continue;
        }
        TableRuleConfig tr = tc.getRule();
        if (tr != null) {
            for (RuleConfig rc : tr.getRules()) {
                boolean match = true;
                for (String ruleColumn : rc.getColumns()) {
                    match &= col2Val.containsKey(ruleColumn);
                }
                if (match) {
                    columnValues = col2Val;
                    rule = rc;
                    matchedTable = tc;
                    break ft;
                }
            }
        }
    }
    // 规则匹配处理,表级别和列级别。
    if (matchedTable == null) {
        String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
        RouteResultsetNode[] rn = new RouteResultsetNode[1];
        if ("".equals(schema.getDataNode()) && isSystemReadSQL(ast)) {
            rn[0] = new RouteResultsetNode(schema.getRandomDataNode(), sql);
        } else {
            rn[0] = new RouteResultsetNode(schema.getDataNode(), sql);
        }
        rrs.setNodes(rn);
        return rrs;
    }
    if (rule == null) {
        if (matchedTable.isRuleRequired()) {
            throw new IllegalArgumentException("route rule for table " + matchedTable.getName() + " is required: " + stmt);
        }
        String[] dataNodes = matchedTable.getDataNodes();
        String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
        RouteResultsetNode[] rn = new RouteResultsetNode[dataNodes.length];
        for (int i = 0; i < dataNodes.length; ++i) {
            rn[i] = new RouteResultsetNode(dataNodes[i], sql);
        }
        rrs.setNodes(rn);
        setGroupFlagAndLimit(rrs, visitor);
        return rrs;
    }
    // 规则计算
    validateAST(ast, matchedTable, rule, visitor);
    Map<Integer, List<Object[]>> dnMap = ruleCalculate(matchedTable, rule, columnValues);
    if (dnMap == null || dnMap.isEmpty()) {
        throw new IllegalArgumentException("No target dataNode for rule " + rule);
    }
    // 判断路由结果是单库还是多库
    if (dnMap.size() == 1) {
        String dataNode = matchedTable.getDataNodes()[dnMap.keySet().iterator().next()];
        String sql = visitor.isSchemaTrimmed() ? genSQL(ast, stmt) : stmt;
        RouteResultsetNode[] rn = new RouteResultsetNode[1];
        rn[0] = new RouteResultsetNode(dataNode, sql);
        rrs.setNodes(rn);
    } else {
        RouteResultsetNode[] rn = new RouteResultsetNode[dnMap.size()];
        if (ast instanceof DMLInsertReplaceStatement) {
            DMLInsertReplaceStatement ir = (DMLInsertReplaceStatement) ast;
            dispatchInsertReplace(rn, ir, rule.getColumns(), dnMap, matchedTable, stmt, visitor);
        } else {
            dispatchWhereBasedStmt(rn, ast, rule.getColumns(), dnMap, matchedTable, stmt, visitor);
        }
        rrs.setNodes(rn);
        setGroupFlagAndLimit(rrs, visitor);
    }
    return rrs;
}
Also used : SQLStatement(com.alibaba.cobar.parser.ast.stmt.SQLStatement) CobarHint(com.alibaba.cobar.route.hint.CobarHint) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig) DMLInsertReplaceStatement(com.alibaba.cobar.parser.ast.stmt.dml.DMLInsertReplaceStatement) Entry(java.util.Map.Entry) TableConfig(com.alibaba.cobar.config.model.TableConfig) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) InExpressionList(com.alibaba.cobar.parser.ast.expression.misc.InExpressionList) TableRuleConfig(com.alibaba.cobar.config.model.rule.TableRuleConfig) RuleConfig(com.alibaba.cobar.config.model.rule.RuleConfig) HashMap(java.util.HashMap) Map(java.util.Map) PartitionKeyVisitor(com.alibaba.cobar.route.visitor.PartitionKeyVisitor)

Example 3 with SQLStatement

use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.

the class SQLParserDelegateTest method testProperlyEnd.

public void testProperlyEnd() throws SQLSyntaxErrorException {
    String sql = "select * from tb1;";
    SQLStatement stmt = SQLParserDelegate.parse(sql);
    Assert.assertEquals(DMLSelectStatement.class, stmt.getClass());
    sql = "select * from tb1 ;;;  ";
    stmt = SQLParserDelegate.parse(sql);
    Assert.assertEquals(DMLSelectStatement.class, stmt.getClass());
    sql = "select * from tb1 /***/  ";
    stmt = SQLParserDelegate.parse(sql);
    Assert.assertEquals(DMLSelectStatement.class, stmt.getClass());
    sql = "select * from tb1 ,  ";
    try {
        stmt = SQLParserDelegate.parse(sql);
        Assert.fail("should detect inproperly end");
    } catch (SQLSyntaxErrorException e) {
    }
    sql = "select * from tb1 ;,  ";
    try {
        stmt = SQLParserDelegate.parse(sql);
        Assert.fail("should detect inproperly end");
    } catch (SQLSyntaxErrorException e) {
    }
}
Also used : SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) SQLStatement(com.alibaba.cobar.parser.ast.stmt.SQLStatement)

Example 4 with SQLStatement

use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.

the class MySQLDALParserTest method testSet.

public void testSet() throws Exception {
    String sql = "seT sysVar1 = ? ";
    MySQLLexer lexer = new MySQLLexer(sql);
    MySQLDALParser parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    SQLStatement set = (DALSetStatement) parser.set();
    parser.match(MySQLToken.EOF);
    String output = output2MySQL(set, sql);
    Assert.assertEquals("SET @@sysVar1 = ?", output);
    sql = "SET `sysVar1` = ?, @@gloBal . `var2` :=1 ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET @@`sysVar1` = ?, @@global.`var2` = 1", output);
    sql = "SET @usrVar1 := ?, @@`var2` =1, @@var3:=?, @'var\\'3'=? ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET @usrVar1 = ?, @@`var2` = 1, @@var3 = ?, @'var\\'3' = ?", output);
    sql = "SET GLOBAL var1=1, SESSION var2:=2";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET @@global.var1 = 1, @@var2 = 2", output);
    sql = "SET @@GLOBAL. var1=1, SESSION var2:=2";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET @@global.var1 = 1, @@var2 = 2", output);
    sql = "SET transaction ISOLATION LEVEL READ UNCOMMITTED ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (MTSSetTransactionStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED", output);
    sql = "SET global transaction ISOLATION LEVEL READ COMMITTED ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (MTSSetTransactionStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED", output);
    sql = "SET transaction ISOLATION LEVEL REPEATABLE READ ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (MTSSetTransactionStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ", output);
    sql = "SET session transaction ISOLATION LEVEL SERIALIZABLE ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (MTSSetTransactionStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE", output);
    sql = "SET names default ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetNamesStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET NAMES DEFAULT", output);
    sql = "SET NAMEs 'utf8' collatE \"latin1_danish_ci\" ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetNamesStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET NAMES utf8 COLLATE latin1_danish_ci", output);
    sql = "SET NAMEs utf8  ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetNamesStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET NAMES utf8", output);
    sql = "SET CHARACTEr SEt 'utf8'  ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetCharacterSetStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET CHARACTER SET utf8", output);
    sql = "SET CHARACTEr SEt DEFaULT  ";
    lexer = new MySQLLexer(sql);
    parser = new MySQLDALParser(lexer, new MySQLExprParser(lexer));
    set = (DALSetCharacterSetStatement) parser.set();
    parser.match(MySQLToken.EOF);
    output = output2MySQL(set, sql);
    Assert.assertEquals("SET CHARACTER SET DEFAULT", output);
}
Also used : MySQLLexer(com.alibaba.cobar.parser.recognizer.mysql.lexer.MySQLLexer) SQLStatement(com.alibaba.cobar.parser.ast.stmt.SQLStatement) DALSetStatement(com.alibaba.cobar.parser.ast.stmt.dal.DALSetStatement)

Example 5 with SQLStatement

use of com.alibaba.cobar.parser.ast.stmt.SQLStatement in project cobar by alibaba.

the class ServerRouteTest method testRouteInsertLong.

public void testRouteInsertLong() throws Exception {
    StringBuilder sb = new StringBuilder("insert into offer_detail (offer_id, gmt) values ");
    for (int i = 0; i < 1024; ++i) {
        if (i > 0)
            sb.append(", ");
        sb.append("(" + i + ", now())");
    }
    SchemaConfig schema = schemaMap.get("cndb");
    RouteResultset rrs = ServerRouter.route(schema, sb.toString(), null, null);
    Assert.assertEquals(-1l, rrs.getLimitSize());
    Map<String, RouteResultsetNode> nodeMap = getNodeMap(rrs, 128);
    IndexedNodeNameAsserter nameAsserter = new IndexedNodeNameAsserter("detail_dn", 0, 128);
    nameAsserter.assertRouteNodeNames(nodeMap.keySet());
    RouteNodeAsserter asserter = new RouteNodeAsserter(nameAsserter, new ParseredSQLAsserter() {

        @Override
        protected void assertAST(SQLStatement stmt, int nodeIndex) {
            DMLInsertStatement insert = (DMLInsertStatement) stmt;
            List<RowExpression> rows = insert.getRowList();
            Assert.assertNotNull(rows);
            Assert.assertEquals(8, rows.size());
            List<Integer> vals = new ArrayList<Integer>(8);
            for (RowExpression row : rows) {
                int val = ((Number) row.getRowExprList().get(0).evaluation(null)).intValue();
                vals.add(val);
            }
            Assert.assertEquals(8, vals.size());
            for (int i = 8 * nodeIndex; i < 8 * nodeIndex + 8; ++i) {
                Assert.assertTrue(vals.contains(i));
            }
        }
    });
    for (RouteResultsetNode node : nodeMap.values()) {
        asserter.assertNode(node);
    }
}
Also used : SchemaConfig(com.alibaba.cobar.config.model.SchemaConfig) RowExpression(com.alibaba.cobar.parser.ast.expression.primary.RowExpression) SQLStatement(com.alibaba.cobar.parser.ast.stmt.SQLStatement) DMLInsertStatement(com.alibaba.cobar.parser.ast.stmt.dml.DMLInsertStatement) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

SQLStatement (com.alibaba.cobar.parser.ast.stmt.SQLStatement)7 SQLSyntaxErrorException (java.sql.SQLSyntaxErrorException)3 MySQLLexer (com.alibaba.cobar.parser.recognizer.mysql.lexer.MySQLLexer)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 List (java.util.List)2 SchemaConfig (com.alibaba.cobar.config.model.SchemaConfig)1 TableConfig (com.alibaba.cobar.config.model.TableConfig)1 RuleConfig (com.alibaba.cobar.config.model.rule.RuleConfig)1 TableRuleConfig (com.alibaba.cobar.config.model.rule.TableRuleConfig)1 ConfigException (com.alibaba.cobar.config.util.ConfigException)1 InExpressionList (com.alibaba.cobar.parser.ast.expression.misc.InExpressionList)1 PlaceHolder (com.alibaba.cobar.parser.ast.expression.primary.PlaceHolder)1 RowExpression (com.alibaba.cobar.parser.ast.expression.primary.RowExpression)1 DALSetStatement (com.alibaba.cobar.parser.ast.stmt.dal.DALSetStatement)1 DescTableStatement (com.alibaba.cobar.parser.ast.stmt.ddl.DescTableStatement)1 DMLInsertReplaceStatement (com.alibaba.cobar.parser.ast.stmt.dml.DMLInsertReplaceStatement)1 DMLInsertStatement (com.alibaba.cobar.parser.ast.stmt.dml.DMLInsertStatement)1 MySQLDALParser (com.alibaba.cobar.parser.recognizer.mysql.syntax.MySQLDALParser)1 MySQLDDLParser (com.alibaba.cobar.parser.recognizer.mysql.syntax.MySQLDDLParser)1