Пример #1
0
        public override Expression Evaluate(EvalStore store)
        {
            Stopwatch watch;

            store.Remove("$DATA");
            var facts = store.Get<Table>("Facts");
            var fromList = store.Get<Dictionary<string, Table>>("$FROM_LIST");

            if (fromList == null || fromList.Count == 0) {
                return ConstExpr.Empty;
            }

            HashSet<string> refIds = store.Get<HashSet<string>>("$REFIDS");

            var selFacts = SelectFactTableRows(fromList, facts);

            for (int i = 0; i < _exprs.Count; i++) {
                _exprs[i] = Reduce(store, _exprs[i]);
            }

            Dictionary<int, List<Expression>> exprGroups;
            Dictionary<string, Expression> idExprMap;
            NormalizeExpressions(selFacts, _exprs, out exprGroups, out idExprMap);

            //find out the time range
            if (exprGroups[TIME_FILTER].Count == 0) {
                throw new Exception("Time range expression is not specified.");
            }
            DateTime min = DateTime.MaxValue;
            DateTime max = DateTime.MinValue;
            DateTime[] range = ExtraTimeRange(store, exprGroups[TIME_FILTER][0]);
            if (range != null) {
                if (range[0] < min) min = range[0];
                if (range[1] > max) max = range[1];
            }
            else {
                throw new Exception("Time range is not specified.");
            }

            //find a list of data log by applying filters of various properties from the fact table
            Table sel = null;
            using (EvalScope scope = new EvalScope(store, new EvalContext(EvalContext.ContextType.SEARCH))) {
                if (exprGroups[ATTR_FILTER].Count == 0) {
                    sel = (Table) selFacts["_"];
                }
                else {
                    store.Put<Dictionary<string, Table>>("$SEL_FACTS", selFacts);
                    foreach (Expression expr in exprGroups[ATTR_FILTER]) {
                        Expression e = expr.Evaluate(store);
                        if (e.ExpressionType != Language.ExpressionType.CONST) {
                            throw new Exception("The expression should be evaluated to a value. " + e.ToString());
                        }
                        ConstExpr c = e as ConstExpr;
                        if (c.Value.DataType == ElementType.TABLE) {
                            Table s = c.Value.GetObject<Table>();
                            if (sel == null) sel = s;
                            else sel.IntersectWith(s);
                        }
                        else {
                            if (c.Value.DataType != ElementType.EMPTY) {
                                throw new Exception("The expression should be evaluated to a set of rows or an empty set. " + e.ToString());
                            }
                        }
                    }
                }
            }
            if (sel == null || sel.Rows == 0) return ConstExpr.Empty;

            //creating additional filters for the metric loading queries
            string resFilter = CreateResourceFilters(sel);
            string ctxFilter = CreateContextFilter(store, exprGroups);
            string filters;
            if (!string.IsNullOrEmpty(resFilter) && !string.IsNullOrEmpty(ctxFilter)) {
                filters = (resFilter + " AND " + ctxFilter);
            }
            else if (string.IsNullOrEmpty(resFilter)) {
                filters = ctxFilter;
            }
            else {
                filters = resFilter;
            }

            MetricsDataLoader dataLoader = new MetricsDataLoader();
            Table data = dataLoader.Load(sel, min, max, filters, refIds);
            Trace.WriteLine("WhereClase.Evaluate.TotalRows: " + data.Rows);

            //applies filters that involve result columns
            watch = Stopwatch.StartNew();
            if (exprGroups[OTHER_FILTER].Count > 0) {
                using (EvalScope scope = new EvalScope(store, new EvalContext(EvalContext.ContextType.FILTER))) {
                    store.Put<Table>("$DATA", data);
                    HashSet<int> selRows = new HashSet<int>();
                    for (int i = 0; i < data.Rows; i++) {
                        store.Put<Element[]>("$ROW", data.Row(i));
                        bool include = true;
                        foreach (Expression expr in exprGroups[OTHER_FILTER]) {
                            ConstExpr c = expr.Evaluate(store) as ConstExpr;
                            if (!((bool)c.Value)) {
                                include = false;
                                break;
                            }
                        }
                        if (include) {
                            selRows.Add(i);
                        }
                    }
                    data = data.Select(selRows);
                }
            }

            if (data == null) data = new Table();

            watch.Stop();
            Trace.WriteLine("WhereClase.Evaluate.Filter: " + watch.ElapsedMilliseconds + "ms");
            Trace.WriteLine("WhereClase.Evaluate.SelectedRows: " + data.Rows);

            store.Put<Table>("$DATA", data);
            return new ConstExpr(data);
        }