Exemplo n.º 1
0
        public override SqlFragment Visit(DbGroupByExpression expression)
        {
            // first process the input
            DbGroupExpressionBinding e           = expression.Input;
            SelectStatement          innerSelect = VisitInputExpressionEnsureSelect(e.Expression, e.VariableName, e.VariableType);

            scope.Add(e.GroupVariableName, innerSelect);

            SelectStatement select = WrapIfNotCompatible(innerSelect, expression.ExpressionKind);

            CollectionType ct = (CollectionType)expression.ResultType.EdmType;
            RowType        rt = (RowType)ct.TypeUsage.EdmType;

            int propIndex = 0;

            foreach (DbExpression key in expression.Keys)
            {
                var fragment = key.Accept(this);
                select.AddGroupBy(fragment);
                propIndex++;

                var colFragment = fragment as ColumnFragment;

                if (colFragment != null)
                {
                    colFragment             = colFragment.Clone();
                    colFragment.ColumnAlias = String.Format("K{0}", propIndex);
                    select.Columns.Add(colFragment);
                }
            }

            for (int agg = 0; agg < expression.Aggregates.Count; agg++)
            {
                DbAggregate         a  = expression.Aggregates[agg];
                DbFunctionAggregate fa = a as DbFunctionAggregate;
                if (fa == null)
                {
                    throw new NotSupportedException();
                }

                string         alias       = rt.Properties[propIndex++].Name;
                ColumnFragment functionCol = new ColumnFragment(null, null);
                functionCol.Literal     = HandleFunction(fa, a.Arguments[0].Accept(this));
                functionCol.ColumnAlias = alias;
                select.Columns.Add(functionCol);
            }

            return(select);
        }
Exemplo n.º 2
0
        protected internal SelectStatement FuseSelectWithInnerSelect(SelectStatement outer, SelectStatement inner)
        {
            string oldTableName = (inner.From as TableFragment).Name;
            string newTableName = inner.Name;
            Dictionary <string, ColumnFragment> dicColumns = new Dictionary <string, ColumnFragment>();

            foreach (ColumnFragment cf in inner.Columns)
            {
                if (cf.ColumnAlias != null)
                {
                    dicColumns.Add(cf.ColumnAlias, cf);
                }
            }
            outer.From = inner.From;
            (outer.From as TableFragment).Name = newTableName;
            // Dispatch Where
            if (outer.Where == null)
            {
                outer.Where = inner.Where;
            }
            else if (inner.Where != null)
            {
                outer.Where = new BinaryFragment()
                {
                    Left = outer.Where, Right = inner.Where, Operator = "AND"
                };
            }
            VisitAndReplaceTableName(outer.Where, oldTableName, newTableName, dicColumns);
            // For the next constructions, either is defined on outer or at inner, not both
            // Dispatch Limit
            if (outer.Limit == null)
            {
                outer.Limit = inner.Limit;
                VisitAndReplaceTableName(outer.Limit, oldTableName, newTableName, dicColumns);
            }
            // Dispatch GroupBy
            if (outer.GroupBy == null && inner.GroupBy != null)
            {
                foreach (SqlFragment sf in inner.GroupBy)
                {
                    outer.AddGroupBy(sf);
                }
                foreach (SqlFragment sf in outer.GroupBy)
                {
                    VisitAndReplaceTableName(sf, oldTableName, newTableName, dicColumns);
                }
            }
            // Dispatch OrderBy
            if (outer.OrderBy != null || inner.OrderBy != null)
            {
                if (inner.OrderBy != null)
                {
                    foreach (SortFragment sf in inner.OrderBy)
                    {
                        outer.AddOrderBy(sf);
                    }
                }
                foreach (SortFragment sf in outer.OrderBy)
                {
                    VisitAndReplaceTableName(sf, oldTableName, newTableName, dicColumns);
                }
            }
            // Dispatch Skip
            if (outer.Skip == null)
            {
                outer.Skip = inner.Skip;
            }
            return(outer);
        }
Exemplo n.º 3
0
        /// <summary>
        /// If input sqlFragment is a group by structure, is flattened to remove some nested correlation queries.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private SqlFragment TryFlatteningGroupBy(SqlFragment input)
        {
            SelectStatement select = null;
            SelectStatement tmpFrag = null, tmpFrag2 = null, tmpFrag3 = null;
            InputFragment   table = null;
            string          objName = null, colName = null, queryName = null;

            // First part assert is a kind-of structure we are looking for
            tmpFrag = input as SelectStatement;
            if (tmpFrag == null)
            {
                goto NoChanges;
            }
            tmpFrag = (tmpFrag).From as SelectStatement;
            if (tmpFrag == null)
            {
                goto NoChanges;
            }
            queryName = tmpFrag.Name;
            if (tmpFrag.Columns.Count < 2)
            {
                goto NoChanges;
            }
            if (!(tmpFrag.Columns[0] is ColumnFragment))
            {
                goto NoChanges;
            }
            colName  = objName = (tmpFrag.Columns[0] as ColumnFragment).ActualColumnName;
            tmpFrag2 = tmpFrag.From as SelectStatement;
            if (tmpFrag2 == null)
            {
                goto NoChanges;
            }
            if (tmpFrag2.Columns.Count < 1 || !(tmpFrag2.Columns[0] is ColumnFragment))
            {
                goto NoChanges;
            }
            if (string.CompareOrdinal(objName, tmpFrag2.Columns[0].ActualColumnName) != 0)
            {
                goto NoChanges;
            }
            if (tmpFrag.Columns[1].Literal == null)
            {
                goto NoChanges;
            }
            tmpFrag2 = tmpFrag.Columns[1].Literal as SelectStatement;
            if (tmpFrag2 == null)
            {
                goto NoChanges;
            }
            if ((tmpFrag2.Columns.Count != 1) || !(tmpFrag2.Columns[0].Literal != null))
            {
                goto NoChanges;
            }
            tmpFrag3 = tmpFrag2.From as SelectStatement;
            if (tmpFrag3 == null)
            {
                goto NoChanges;
            }
            table = tmpFrag3.From as InputFragment;
            if (table == null)
            {
                goto NoChanges;
            }
            FunctionFragment func = tmpFrag2.Columns[0].Literal as FunctionFragment;

            if (tmpFrag3.Columns.Count != 1 || !(tmpFrag3.Columns[0] is ColumnFragment))
            {
                goto NoChanges;
            }
            if (func == null)
            {
                goto NoChanges;
            }
            // Yes it is the kind-of type we like, then optimize it
            select     = new SelectStatement(this);
            table.Name = null;
            string        tableName = null;
            TableFragment t         = tmpFrag3.From as TableFragment;

            if (t == null)
            {
                tableName = tmpFrag3.Columns[0].TableName;
            }
            else
            {
                tableName = t.Table;
            }
            select.From = table;
            select.Columns.Add(new ColumnFragment(tableName, colName));
            select.Columns.Add(new ColumnFragment(tableName, "C0")
            {
                ColumnAlias = "C1",
                Literal     = new FunctionFragment()
                {
                    Argument = new ColumnFragment(tableName, tmpFrag3.Columns[0].ActualColumnName),
                    Distinct = tmpFrag3.IsDistinct,
                    Name     = func.Name
                }
            });
            select.Wrap(null);
            select.Name = queryName;
            select.AddGroupBy(select.Columns[0]);
            (input as SelectStatement).From = select;
NoChanges:
            return(input);
        }