示例#1
0
            public static void RouteForTableMeta(RouteResultset rrs,
                                                 SchemaConfig schema,
                                                 ISqlStatement ast,
                                                 PartitionKeyVisitor visitor,
                                                 string stmt)
            {
                var sql = stmt;

                if (visitor.IsSchemaTrimmed())
                {
                    sql = GenSql(ast, stmt);
                }

                var tables = visitor.GetMetaReadTable();

                if (tables == null)
                {
                    throw new ArgumentException(string.Format("route err: tables[] is null for meta read table: {0}",
                                                              stmt));
                }

                string[] dataNodes;
                if (tables.Length <= 0)
                {
                    dataNodes = schema.MetaDataNodes;
                }
                else
                {
                    if (tables.Length == 1)
                    {
                        dataNodes    = new string[1];
                        dataNodes[0] = GetMetaReadDataNode(schema, tables[0]);
                    }
                    else
                    {
                        ICollection <string> dataNodeSet = new HashSet <string>();
                        foreach (var table in tables)
                        {
                            var dataNode = GetMetaReadDataNode(schema, table);
                            dataNodeSet.Add(dataNode);
                        }
                        dataNodes = dataNodeSet.ToArray();
                        //dataNodes = new string[dataNodeSet.Count];
                        //IEnumerator<string> iter = dataNodeSet.GetEnumerator();
                        //for (int i = 0; i < dataNodes.Length; ++i)
                        //{
                        //    dataNodes[i] = iter.Current;
                        //}
                    }
                }

                var nodes = new RouteResultsetNode[dataNodes.Length];

                rrs.Nodes = nodes;
                for (var i1 = 0; i1 < dataNodes.Length; ++i1)
                {
                    nodes[i1] = new RouteResultsetNode(dataNodes[i1], sql);
                }
            }
示例#2
0
        //private static readonly Logger Logger = Logger.GetLogger(typeof(ServerRouter));

        public static RouteResultset Route(SchemaConfig schema,
                                           string stmt,
                                           string charset,
                                           object info)
        {
            var rrs = new RouteResultset(stmt);
            // 检查是否含有cobar hint
            var prefixIndex = HintRouter.IndexOfPrefix(stmt);

            if (prefixIndex >= 0)
            {
                HintRouter.RouteFromHint(info, schema, rrs, prefixIndex, stmt);
                return(rrs);
            }

            // 检查schema是否含有拆分库
            if (schema.IsNoSharding)
            {
                if (schema.IsKeepSqlSchema)
                {
                    var ast     = SqlParserDelegate.Parse(stmt, charset ?? MySqlParser.DefaultCharset);
                    var visitor = new PartitionKeyVisitor(schema.Tables);
                    visitor.SetTrimSchema(schema.Name);
                    ast.Accept(visitor);
                    if (visitor.IsSchemaTrimmed())
                    {
                        stmt = GenSql(ast, stmt);
                    }
                }
                var nodes = new RouteResultsetNode[1];
                nodes[0]  = new RouteResultsetNode(schema.DataNode, stmt);
                rrs.Nodes = nodes;
                return(rrs);
            }

            // 生成和展开AST
            var ast1     = SqlParserDelegate.Parse(stmt, charset ?? MySqlParser.DefaultCharset);
            var visitor1 = new PartitionKeyVisitor(schema.Tables);

            visitor1.SetTrimSchema(schema.IsKeepSqlSchema ? schema.Name : null);
            ast1.Accept(visitor1);
            // 如果sql包含用户自定义的schema,则路由到default节点
            if (schema.IsKeepSqlSchema && visitor1.IsCustomedSchema())
            {
                if (visitor1.IsSchemaTrimmed())
                {
                    stmt = GenSql(ast1, stmt);
                }
                var nodes = new RouteResultsetNode[1];
                nodes[0]  = new RouteResultsetNode(schema.DataNode, stmt);
                rrs.Nodes = nodes;
                return(rrs);
            }

            // 元数据语句路由
            if (visitor1.IsTableMetaRead())
            {
                MetaRouter.RouteForTableMeta(rrs, schema, ast1, visitor1, stmt);
                if (visitor1.IsNeedRewriteField())
                {
                    rrs.Flag = RouteResultset.RewriteField;
                }
                return(rrs);
            }

            // 匹配规则
            TableConfig matchedTable = null;
            RuleConfig  rule         = null;
            IDictionary <string, IList <object> > columnValues = null;
            var astExt = visitor1.GetColumnValue();
            var tables = schema.Tables;

            foreach (var e in astExt)
            {
                var col2Val = e.Value;
                var tc      = tables.GetValue(e.Key);
                if (tc == null)
                {
                    continue;
                }
                if (matchedTable == null)
                {
                    matchedTable = tc;
                }
                if (col2Val == null || col2Val.IsEmpty())
                {
                    continue;
                }
                var tr = tc.Rule;
                if (tr != null)
                {
                    foreach (var rc in tr.Rules)
                    {
                        var match = true;
                        foreach (var ruleColumn in rc.Columns)
                        {
                            match &= col2Val.ContainsKey(ruleColumn);
                        }

                        if (match)
                        {
                            columnValues = col2Val;
                            rule         = rc;
                            matchedTable = tc;
                            goto ft_break;
                        }
                    }
                }
            }
ft_break:
            ;

            // 规则匹配处理,表级别和列级别。
            if (matchedTable == null)
            {
                var sql = visitor1.IsSchemaTrimmed() ? GenSql(ast1, stmt) : stmt;
                var rn  = new RouteResultsetNode[1];
                if (string.Empty.Equals(schema.DataNode) && IsSystemReadSql(ast1))
                {
                    rn[0] = new RouteResultsetNode(schema.RandomDataNode, sql);
                }
                else
                {
                    rn[0] = new RouteResultsetNode(schema.DataNode, sql);
                }
                rrs.Nodes = rn;
                return(rrs);
            }
            if (rule == null)
            {
                if (matchedTable.IsRuleRequired)
                {
                    throw new ArgumentException(string.Format("route rule for table {0} is required: {1}",
                                                              matchedTable.Name, stmt));
                }
                var dataNodes = matchedTable.DataNodes;
                var sql       = visitor1.IsSchemaTrimmed() ? GenSql(ast1, stmt) : stmt;
                var rn        = new RouteResultsetNode[dataNodes.Length];
                for (var i = 0; i < dataNodes.Length; ++i)
                {
                    rn[i] = new RouteResultsetNode(dataNodes[i], sql);
                }
                rrs.Nodes = rn;
                SetGroupFlagAndLimit(rrs, visitor1);
                return(rrs);
            }

            // 规则计算
            ValidateAst(ast1, matchedTable, rule, visitor1);
            var dnMap = RuleCalculate(matchedTable, rule, columnValues);

            if (dnMap == null || dnMap.IsEmpty())
            {
                throw new ArgumentException("No target dataNode for rule " + rule);
            }

            // 判断路由结果是单库还是多库
            if (dnMap.Count == 1)
            {
                var dataNode = matchedTable.DataNodes[dnMap.Keys.FirstOrDefault()];
                //string dataNode = matchedTable.GetDataNodes()[dnMap.Keys.GetEnumerator().Current];
                var sql = visitor1.IsSchemaTrimmed() ? GenSql(ast1, stmt) : stmt;
                var rn  = new RouteResultsetNode[1];
                rn[0]     = new RouteResultsetNode(dataNode, sql);
                rrs.Nodes = rn;
            }
            else
            {
                var rn = new RouteResultsetNode[dnMap.Count];
                if (ast1 is DmlInsertReplaceStatement)
                {
                    var ir = (DmlInsertReplaceStatement)ast1;
                    DispatchInsertReplace(rn, ir, rule.Columns, dnMap, matchedTable, stmt, visitor1);
                }
                else
                {
                    DispatchWhereBasedStmt(rn, ast1, rule.Columns, dnMap, matchedTable, stmt, visitor1);
                }
                rrs.Nodes = rn;
                SetGroupFlagAndLimit(rrs, visitor1);
            }
            return(rrs);
        }
示例#3
0
        private static void DispatchWhereBasedStmt(RouteResultsetNode[] rn,
                                                   ISqlStatement stmtAST,
                                                   IList <string> ruleColumns,
                                                   IDictionary <int, IList <object[]> > dataNodeMap,
                                                   TableConfig matchedTable,
                                                   string originalSQL,
                                                   PartitionKeyVisitor visitor)
        {
            // [perf tag] 11.617 us: sharding multivalue
            if (ruleColumns.Count > 1)
            {
                string sql;
                if (visitor.IsSchemaTrimmed())
                {
                    sql = GenSql(stmtAST, originalSQL);
                }
                else
                {
                    sql = originalSQL;
                }

                var i = -1;
                foreach (var dataNodeId in dataNodeMap.Keys)
                {
                    var dataNode = matchedTable.DataNodes[dataNodeId];
                    rn[++i] = new RouteResultsetNode(dataNode, sql);
                }
                return;
            }

            var table       = matchedTable.Name;
            var columnIndex = visitor.GetColumnIndex(table);
            var valueMap    = columnIndex.GetValue(ruleColumns[0]);

            ReplacePartitionKeyOperand(columnIndex, ruleColumns);
            var unreplacedInExpr      = new Dictionary <InExpression, ICollection <IExpression> >(1);
            var unreplacedSingleExprs = new HashSet <IReplacableExpression>();
            // [perf tag] 12.2755 us: sharding multivalue
            var nodeId = -1;

            foreach (var en in dataNodeMap)
            {
                var tuples = en.Value;
                unreplacedSingleExprs.Clear();
                unreplacedInExpr.Clear();

                foreach (var tuple in tuples)
                {
                    var value = tuple[0];
                    var indexedExpressionPair = GetExpressionSet(valueMap, value);
                    foreach (var pair in indexedExpressionPair)
                    {
                        var expr   = pair.Key;
                        var parent = (InExpression)pair.Value;
                        if (PartitionKeyVisitor.IsPartitionKeyOperandSingle(expr, parent))
                        {
                            unreplacedSingleExprs.Add((IReplacableExpression)expr);
                        }
                        else if (PartitionKeyVisitor.IsPartitionKeyOperandIn(expr, parent))
                        {
                            var newInSet = unreplacedInExpr.GetValue(parent);
                            if (newInSet == null)
                            {
                                newInSet = new HashSet <IExpression>();
                                unreplacedInExpr[parent] = newInSet;
                            }
                            newInSet.Add(expr);
                        }
                    }
                }
                // [perf tag] 15.3745 us: sharding multivalue
                foreach (var expr1 in unreplacedSingleExprs)
                {
                    expr1.ClearReplaceExpr();
                }

                foreach (var entemp in unreplacedInExpr)
                {
                    var @in = entemp.Key;
                    var set = entemp.Value;
                    if (set == null || set.IsEmpty())
                    {
                        @in.ReplaceExpr = ReplacableExpressionConstants.BoolFalse;
                    }
                    else
                    {
                        @in.ClearReplaceExpr();
                        var inlist = @in.GetInExpressionList();
                        if (inlist != null)
                        {
                            inlist.ReplaceExpr = new List <IExpression>(set);
                        }
                    }
                }

                // [perf tag] 16.506 us: sharding multivalue
                var sql = GenSql(stmtAST, originalSQL);
                // [perf tag] 21.3425 us: sharding multivalue
                var dataNodeName = matchedTable.DataNodes[en.Key];
                rn[++nodeId] = new RouteResultsetNode(dataNodeName, sql);
                foreach (var expr2 in unreplacedSingleExprs)
                {
                    expr2.ReplaceExpr = ReplacableExpressionConstants.BoolFalse;
                }

                foreach (var in1 in unreplacedInExpr.Keys)
                {
                    in1.ReplaceExpr = ReplacableExpressionConstants.BoolFalse;
                    var list = in1.GetInExpressionList();
                    if (list != null)
                    {
                        list.ClearReplaceExpr();
                    }
                }
            }
        }