Exemplo n.º 1
0
 public AggregationPointer(AggregationPointer parent, Attribute attribute)
 {
     Parent    = parent;
     Attribute = attribute;
 }
Exemplo n.º 2
0
        public CellSet Execute(QueryCommand cmd)
        {
            Joiner joiner = new Joiner(_pool, _connection, cmd);

            joiner.Run();

            if (_pool.Aggregations.Count == 0)
            {
                return(new CellSet());
            }

            CellSet  cs = new CellSet();
            DateTime t  = DateTime.Now;

            QuerySets.JoinedMembers columns = cmd.Columns.JoinMembers(_pool.FindAggregation(cmd.Columns.Attributes));
            QuerySets.JoinedMembers rows    = cmd.Rows.Count > 0 ?
                                              cmd.Rows.JoinMembers(_pool.FindAggregation(cmd.Rows.Attributes)) :
                                              new QuerySets.JoinedMembers();

            QuerySets.JoinedMembers filters;
            bool reverseFilter = cmd.Filters.ShouldReverse;

            if (!reverseFilter)
            {
                filters = cmd.Filters.Count > 0 ?
                          cmd.Filters.JoinMembers(_pool.FindAggregation(cmd.Filters.Attributes), true) :
                          new QuerySets.JoinedMembers();
            }
            else
            {
                reverseFilter = true;
                QuerySets reversed = cmd.Filters.ReverseMembers();
                filters = reversed.Count > 0 ?
                          reversed.JoinMembers(_pool.FindAggregation(reversed.Attributes), true) :
                          new QuerySets.JoinedMembers();
            }

            // AggregationPointer is for total lookup
            AggregationPointer root = null;
            Aggregation        defaultAggregation = _pool.FindAggregation(GetAttributes());

            if (defaultAggregation != null)
            {
                List <Position> cps = cs.Axes[0].Positions;
                List <Position> rps = cs.Axes[1].Positions;
                for (int i = 0; i < rows.Count; i++)
                {
                    rps.Add(new Position(rows[i], i));
                }
                for (int i = 0; i < columns.Count; i++)
                {
                    cps.Add(new Position(columns[i], i));
                }

                if (filters.Count > 0)
                {
                    if (reverseFilter)
                    {
                        // Query values without filters first
                        Attribute[] crIndex = cmd.Columns.Attributes.Concat(cmd.Rows.Attributes).ToArray();
                        DirectQuery(_pool.FindAggregation(crIndex));

                        // Then query values with filter
                        if (root != null)
                        {
                            root.Clear();
                        }
                        root = null;
                        IEnumerable <Cell> filtered = IncrementalQuery(defaultAggregation);

                        // Substract
                        int i = 0;
                        foreach (Cell cell in filtered)
                        {
                            if (cell.Value != null)
                            {
                                if (cell.DataType == typeof(int))
                                {
                                    cs.Cells[i].Value = (int)cs.Cells[i].Value - (int)cell.Value;
                                }
                                else
                                {
                                    cs.Cells[i].Value = (decimal)cs.Cells[i].Value - (decimal)cell.Value;
                                }
                            }
                            i++;
                        }
                    }
                    else
                    {
                        IncrementalQuery(defaultAggregation, cs.Cells);
                    }
                }
                else
                {
                    DirectQuery(defaultAggregation);
                }
            }

            cs.QueryTime = (DateTime.Now - t).TotalMilliseconds;
            return(cs);

            Attribute[] GetAttributes()
            {
                List <Attribute> attrs = new List <Attribute>();

                attrs.AddRange(filters.Attributes);
                attrs.AddRange(columns.Attributes);
                attrs.AddRange(rows.Attributes);
                return(attrs.ToArray());
            }

            IEnumerable <Cell> IncrementalQuery(Aggregation agg, List <Cell> cells = null)
            {
                List <CellAggregator> cas = new List <CellAggregator>();

                if (rows.Count == 0)
                {
                    for (int i = 0; i < filters.Count; i++)
                    {
                        int pointer = 0;
                        for (int j = 0; j < columns.Count; j++)
                        {
                            if (i == 0)
                            {
                                cas.Add(new CellAggregator(GetValueInfo(agg.GetValue(false, filters[i], columns[j]))));
                            }
                            else
                            {
                                cas[pointer].Add(GetValueInfo(agg.GetValue(false, filters[i], columns[j])));
                                pointer++;
                            }
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < filters.Count; i++)
                    {
                        int pointer = 0;
                        for (int j = 0; j < rows.Count; j++)
                        {
                            for (int k = 0; k < columns.Count; k++)
                            {
                                if (i == 0)
                                {
                                    cas.Add(new CellAggregator(GetValueInfo(agg.GetValue(false, filters[i], columns[k], rows[j]))));
                                }
                                else
                                {
                                    cas[pointer].Add(GetValueInfo(agg.GetValue(false, filters[i], columns[k], rows[j])));
                                    pointer++;
                                }
                            }
                        }
                    }
                }
                //cas.ForEach(_ => cs.Cells.Add(new Cell(_.Calculate())));
                if (cells != null)
                {
                    cas.ForEach(_ => cells.Add(new Cell(_.Calculate())));
                    return(null);
                }
                else
                {
                    return(cas.Select(_ => new Cell(_.Calculate(), _.DataType)));
                }
            }

            void DirectQuery(Aggregation agg)
            {
                if (rows.Count == 0)
                {
                    for (int i = 0; i < columns.Count; i++)
                    {
                        cs.Cells.Add(new Cell(GetValueInfo(agg.GetValue(false, columns[i])).Value));
                    }
                }
                else
                {
                    for (int i = 0; i < rows.Count; i++)
                    {
                        for (int j = 0; j < columns.Count; j++)
                        {
                            cs.Cells.Add(new Cell(GetValueInfo(agg.GetValue(false, columns[j], rows[i])).Value));
                        }
                    }
                }
            }

            Aggregation.ValueInfo GetValueInfo(Aggregation.ValueInfo vinfo)
            {
                // vinfo.IsTotal -> Place holder for total
                // AggregationPointer -> Point to total aggregation indexed by total place holder's attributes
                if (vinfo.IsTotal)
                {
                    // Find or create AggregationPointer based on total place holder's attributes
                    int c = 0;
                    AggregationPointer cp = root;
                    foreach (AttributeMember[] members in vinfo.Members)
                    {
                        foreach (AttributeMember m in members)
                        {
                            if (!m.IsTotal && m.LinkedMeasure == null)
                            {
                                if (c == 0)
                                {
                                    if (root == null)
                                    {
                                        root = new AggregationPointer(m.Attribute);
                                    }
                                    cp = root;
                                }
                                else
                                {
                                    AggregationPointer p = cp[m.Attribute];
                                    if (p == null)
                                    {
                                        p = new AggregationPointer(cp, m.Attribute);
                                        cp.Children.Add(p);
                                    }
                                    cp = p;
                                }
                                c++;
                            }
                        }
                    }

                    // Find and assign total aggregation if it is a new pointer (cp.Aggregation == null)
                    if (cp.Aggregation == null)
                    {
                        cp.Aggregation = _pool.FindAggregation(cp.Attributes);
                    }

                    return(cp.Aggregation.GetValue(true, vinfo.Members));
                }
                else
                {
                    return(vinfo);
                }
            }
        }