コード例 #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 void LogExplicitReplicaSet(object frontConn, string sql, RouteResultset rrs)
 {
     //LogExplicitReplicaSet
     //if (frontConn != null && Logger.IsInfoEnabled())
     //{
     //    StringBuilder s = new StringBuilder();
     //    s.Append(frontConn).Append("Explicit data node replica set from, sql=[");
     //    s.Append(sql).Append(']');
     //    Logger.Info(s.ToString());
     //}
 }
コード例 #3
0
 private static IDictionary<string, RouteResultsetNode> GetNodeMap(RouteResultset
                                                                       rrs, int expectSize)
 {
     var routeNodes = rrs.Nodes;
     Assert.AreEqual(expectSize, routeNodes.Length);
     var nodeMap = new Dictionary<string, RouteResultsetNode>(expectSize);
     for (var i = 0; i < expectSize; i++)
     {
         var routeNode = routeNodes[i];
         nodeMap[routeNode.Name] = routeNode;
     }
     Assert.AreEqual(expectSize, nodeMap.Count);
     return nodeMap;
 }
コード例 #4
0
        private static void SetGroupFlagAndLimit(RouteResultset rrs, PartitionKeyVisitor visitor)
        {
            rrs.LimitSize = visitor.GetLimitSize();
            switch (visitor.GetGroupFuncType())
            {
            case PartitionKeyVisitor.GroupSum:
            {
                rrs.Flag = RouteResultset.SumFlag;
                break;
            }

            case PartitionKeyVisitor.GroupMax:
            {
                rrs.Flag = RouteResultset.MaxFlag;
                break;
            }

            case PartitionKeyVisitor.GroupMin:
            {
                rrs.Flag = RouteResultset.MinFlag;
                break;
            }
            }
        }
コード例 #5
0
            /// <exception cref="System.SqlSyntaxErrorException" />
            public static void RouteFromHint(object frontConn,
                                             SchemaConfig schema,
                                             RouteResultset rrs,
                                             int prefixIndex,
                                             string sql)
            {
                var         hint             = CobarHint.ParserCobarHint(sql, prefixIndex);
                var         outputSql        = hint.OutputSql;
                var         replica          = hint.Replica;
                var         table            = hint.Table;
                var         dataNodes        = hint.DataNodes;
                var         partitionOperand = hint.PartitionOperand;
                TableConfig tableConfig      = null;

                if (table == null ||
                    schema.Tables == null ||
                    (tableConfig = schema.Tables.GetValue(table)) == null)
                {
                    // table not indicated
                    var nodes = new RouteResultsetNode[1];
                    rrs.Nodes = nodes;
                    if (dataNodes != null && !dataNodes.IsEmpty())
                    {
                        var replicaIndex = dataNodes[0].Value;
                        if (replicaIndex >= 0 && RouteResultsetNode.DefaultReplicaIndex != replicaIndex)
                        {
                            // replica index indicated in dataNodes references
                            nodes[0] = new RouteResultsetNode(schema.DataNode, replicaIndex, outputSql);
                            LogExplicitReplicaSet(frontConn, sql, rrs);
                            return;
                        }
                    }
                    nodes[0] = new RouteResultsetNode(schema.DataNode, replica, outputSql);
                    if (replica != RouteResultsetNode.DefaultReplicaIndex)
                    {
                        LogExplicitReplicaSet(frontConn, sql, rrs);
                    }
                    return;
                }

                if (dataNodes != null && !dataNodes.IsEmpty())
                {
                    var nodes = new RouteResultsetNode[dataNodes.Count];
                    rrs.Nodes = nodes;
                    var i          = 0;
                    var replicaSet = false;
                    foreach (var pair in dataNodes)
                    {
                        var dataNodeName = tableConfig.DataNodes[pair.Key];
                        var replicaIndex = dataNodes[i].Value;
                        if (replicaIndex >= 0 && RouteResultsetNode.DefaultReplicaIndex != replicaIndex)
                        {
                            replicaSet = true;
                            nodes[i]   = new RouteResultsetNode(dataNodeName, replicaIndex, outputSql);
                        }
                        else
                        {
                            replicaSet = replicaSet || (replica != RouteResultsetNode.DefaultReplicaIndex);
                            nodes[i]   = new RouteResultsetNode(dataNodeName, replica, outputSql);
                        }
                        ++i;
                    }
                    if (replicaSet)
                    {
                        LogExplicitReplicaSet(frontConn, sql, rrs);
                    }
                    return;
                }

                if (partitionOperand == null)
                {
                    var tableDataNodes = tableConfig.DataNodes;
                    var nodes          = new RouteResultsetNode[tableDataNodes.Length];
                    rrs.Nodes = nodes;
                    for (var i = 0; i < nodes.Length; ++i)
                    {
                        nodes[i] = new RouteResultsetNode(tableDataNodes[i], replica, outputSql);
                    }
                    return;
                }

                var cols = partitionOperand.Key;
                var vals = partitionOperand.Value;

                if (cols == null || vals == null)
                {
                    throw new SqlSyntaxErrorException("${partitionOperand} is invalid: " + sql);
                }
                RuleConfig rule  = null;
                var        tr    = tableConfig.Rule;
                var        rules = tr == null ? null : tr.Rules;

                if (rules != null)
                {
                    foreach (var r in rules)
                    {
                        var ruleCols = r.Columns;
                        var match    = true;
                        foreach (var ruleCol in ruleCols)
                        {
                            match &= cols.Contains(ruleCol);
                        }
                        if (match)
                        {
                            rule = r;
                            break;
                        }
                    }
                }

                var tableDataNodes1 = tableConfig.DataNodes;

                if (rule == null)
                {
                    var nodes = new RouteResultsetNode[tableDataNodes1.Length];
                    rrs.Nodes = nodes;
                    var replicaSet = false;
                    for (var i = 0; i < tableDataNodes1.Length; ++i)
                    {
                        replicaSet = replicaSet || (replica != RouteResultsetNode.DefaultReplicaIndex);
                        nodes[i]   = new RouteResultsetNode(tableDataNodes1[i], replica, outputSql);
                    }
                    if (replicaSet)
                    {
                        LogExplicitReplicaSet(frontConn, sql, rrs);
                    }
                    return;
                }

                var destDataNodes = CalcHintDataNodes(rule, cols, vals, tableDataNodes1);
                var nodes1        = new RouteResultsetNode[destDataNodes.Count];

                rrs.Nodes = nodes1;
                var i1          = 0;
                var replicaSet1 = false;

                foreach (var dataNode in destDataNodes)
                {
                    replicaSet1  = replicaSet1 || (replica != RouteResultsetNode.DefaultReplicaIndex);
                    nodes1[i1++] = new RouteResultsetNode(dataNode, replica, outputSql);
                }
                if (replicaSet1)
                {
                    LogExplicitReplicaSet(frontConn, sql, rrs);
                }
            }
コード例 #6
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);
        }