Example #1
0
 public override Identifier Visit(EntityIdentifier identifier)
 {
     if (visitingColumns)
     {
         currentAlias = identifier.Entity.Alias;
         return identifier;
     }
     return base.Visit(identifier);
 }
Example #2
0
 public virtual Evaluant.NLinq.Expressions.Identifier Update(EntityIdentifier entityIdentifier, EntityExpression entity, Evaluant.NLinq.Expressions.Identifier identifier)
 {
     if (entityIdentifier.Entity != entity || entityIdentifier.Identifier != identifier)
         return new EntityIdentifier(identifier, entity);
     return entityIdentifier;
 }
Example #3
0
        public override Evaluant.NLinq.Expressions.Expression Visit(Evaluant.NLinq.Expressions.MemberExpression expression)
        {
            if (getAlias)
            {
                if (expression.Previous is EntityIdentifier)
                {
                    EntityIdentifier identifier = (EntityIdentifier)expression.Previous;
                    if (!entityIdentifierAliases.ContainsKey(identifier.Text))
                        entityIdentifierAliases.Add(identifier.Text, identifier.Entity.Alias);
                    return identifier;
                }

                if (expression.Previous != null)
                    return Visit(expression.Previous);
                return base.Visit(expression);

            }
            if (getPreviousType)
            {
                if (expression.Previous is EntityIdentifier)
                    return ((EntityIdentifier)expression.Previous).Entity;

                if (expression.Previous != null)
                {
                    EntityExpression entity = (EntityExpression)Visit(expression.Previous);
                    Model.Reference reference = engine.Factory.Model.Entities[entity.Type].References[((Evaluant.NLinq.Expressions.Identifier)expression.Statement).Text];
                    entity = new EntityExpression(new TableAlias()) { Type = reference.ChildType, Expression = expression };
                    return entity;
                }
            }

            if (expression.Statement.ExpressionType == NLinq.Expressions.ExpressionTypes.Call)
            {
                NLinq.Expressions.MethodCall item = (NLinq.Expressions.MethodCall)expression.Statement;
                AggregateFunctionType aggregateType;
                switch (item.Identifier.Text)
                {
                    case "Count":
                        aggregateType = AggregateFunctionType.Count;
                        break;
                    case "Average":
                        aggregateType = AggregateFunctionType.Avg;
                        break;
                    case "Max":
                        aggregateType = AggregateFunctionType.Max;
                        break;
                    case "Min":
                        aggregateType = AggregateFunctionType.Min;
                        break;
                    case "Sum":
                        aggregateType = AggregateFunctionType.Sum;
                        break;
                    default:
                        aggregateType = AggregateFunctionType.Unknown;
                        break;
                }
                if (aggregateType == AggregateFunctionType.Unknown)
                {
                    SelectStatement oldSelect = select;
                    if (item.Identifier.Text == "Take")
                    {
                        Visit(expression.Previous);
                        select.Top = (int)((Constant)item.Parameters[0]).Value;
                        return select;
                    }
                    if (item.Identifier.Text == "Skip")
                    {
                        Visit(expression.Previous);
                        if (Convert.ToInt32(((Constant)item.Parameters[0]).Value) == 0)
                            return select;

                        if (select.OrderBy == null)
                            throw new NotSupportedException("A skip operation cannot be done on a statement which is not ordered");


                        List<IAliasedExpression> columns = new List<IAliasedExpression>(select.Columns);
                        columns.Add(new ComplexColumnExpression(null, new RowNumber(select.OrderBy), "rn" + select.Alias));
                        select.Columns = columns.ToArray();
                        columns.RemoveAt(columns.Count - 1);
                        oldSelect = select;
                        select = new SelectStatement(new TableAlias(), null, new FromClause(select), null, new NLinq.Expressions.WhereClause(new NLinq.Expressions.BinaryExpression(NLinq.Expressions.BinaryExpressionType.Greater, new ColumnExpression(select.Alias, "rn" + select.Alias), item.Parameters[0])));
                        columns = new List<IAliasedExpression>();
                        foreach (IAliasedExpression expr in oldSelect.Columns)
                        {
                            IAliasedExpression column = null;
                            if (expr.DbExpressionType == DbExpressionType.Column)
                            {
                                column = new ColumnExpression(oldSelect.Alias, ((ColumnExpression)expr).ColumnAlias, ((ColumnExpression)expr).ColumnAlias);
                            }
                            else if (expr.DbExpressionType == DbExpressionType.Entity)
                            {
                                EntityExpression entity = expr as EntityExpression;
                                column = new ComplexColumnExpression(oldSelect.Alias, new NLinq.Expressions.MemberExpression(((NLinq.Expressions.MemberExpression)entity.Expression).Statement, entity.Expression));
                            }
                            else
                                throw new NotSupportedException();
                            if (column != null)
                                columns.Add(column);
                        }
                        if (oldSelect.OrderBy != null && oldSelect.OrderBy.Count > 0)
                        {
                            List<Evaluant.NLinq.Expressions.OrderByCriteria> criterias = new List<NLinq.Expressions.OrderByCriteria>();
                            foreach (var criteria in oldSelect.OrderBy.Criterias)
                            {
                                if (criteria.Expression != null)
                                {
                                    if (criteria.Expression.ExpressionType == NLinq.Expressions.ExpressionTypes.MemberAccess)
                                    {
                                        criterias.Add(new NLinq.Expressions.OrderByCriteria(new ColumnExpression(oldSelect.Alias, (NLinq.Expressions.Identifier)((NLinq.Expressions.MemberExpression)criteria.Expression).Statement), criteria.Ascending));
                                    }
                                }
                            }
                            if (criterias.Count > 0)
                                select.OrderBy = new NLinq.Expressions.OrderByClause(criterias);
                        }
                        //Since we include a surrounding select, we need to clone some information with alias changing
                        var aliasChanger = new LazyAliasResolver(new Dictionary<TableAlias, TableAlias> { { TableAlias.All, oldSelect.Alias } });
                        select.Columns = aliasChanger.VisitColumns(columns);

                        select.OrderBy = aliasChanger.VisitOrderBy(select.OrderBy);
                        oldSelect.OrderBy = null;
                        return select;
                    }
                    if (item.Identifier.Text == "First")
                    {
                        Visit(expression.Previous);
                        select.Top = 1;
                        return select;
                    }
                    if (item.Identifier.Text == "Last")
                    {
                        Visit(expression.Previous);
                        if (select.OrderBy != null && select.OrderBy.Criterias != null && select.OrderBy.Criterias.Count > 0)
                        {
                            foreach (NLinq.Expressions.OrderByCriteria criteria in select.OrderBy.Criterias)
                            {
                                criteria.Ascending = !criteria.Ascending;
                            }
                        }
                        else
                            throw new NotSupportedException("To use Last or LastOrDefault, you have to specify an order in your query.");
                        select.Top = 1;
                        return select;
                    }
                    if (item.Identifier.Text == "Any")
                    {
                        if (expression.Previous.ExpressionType != NLinq.Expressions.ExpressionTypes.Quote)
                        {
                            select = new SelectStatement(new TableAlias());
                            select.Columns = new[] { new ComplexColumnExpression(
                                    null,
                                    new Constant(1, System.Data.DbType.Int32)) 
                                };
                            select.Where = new NLinq.Expressions.WhereClause(Visit(expression.Previous));
                            var result = new Exists(select);
                            select = oldSelect;
                            return result;
                        }
                        return new Exists(Visit(expression.Previous));
                    }
                    if (item.Identifier.Text == "Distinct")
                    {
                        Visit(expression.Previous);
                        select.Distinct = true;
                        return select;
                    }
                    return expression;
                    select = new SelectStatement(new TableAlias());
                    Visit(expression.Previous);
                    SelectStatement previousSelect = select;
                    select = oldSelect;
                    if (item.Parameters.Length == 0)
                        return new SelectStatement(new TableAlias(), new IAliasedExpression[] { new Aggregate(item.Identifier, ColumnExpression.AllColumns) }, new FromClause(previousSelect), null, null);
                    else
                        return new SelectStatement(new TableAlias(), new IAliasedExpression[] { new Aggregate(item.Identifier, item.Parameters) }, new FromClause(previousSelect), null, null);
                }
                else
                {
                    IAliasedExpression result;
                    if (expression.Previous is Evaluant.NLinq.Expressions.MemberExpression)
                    {
                        //If we are aggregating results
                        if (select == null)
                        {
                            Visit(expression.Previous);
                            SelectStatement oldSelect = select;
                            select = new SelectStatement(new TableAlias());
                            var columns = new IAliasedExpression[] { new Aggregate(aggregateType, new Constant(1, System.Data.DbType.Int32)) };
                            select.Columns = columns;
                            select.From = new FromClause(oldSelect);
                            //Prevent order by if counting (useless, and causes crashes on SQLServer
                            if (oldSelect.OrderBy != null)
                                oldSelect.OrderBy = null;
                            return select;
                        }
                        else
                        {
                            SelectStatement oldSelect = select;
                            select = new SelectStatement(new TableAlias());
                            //from var veryPrevious in oldSelect.From 
                            //from var a in expression.Previous 
                            //where veryPrevious==oldSelect.Select
                            //select a
                            getAlias = true;
                            EntityIdentifier identifier = (EntityIdentifier)Visit(expression);
                            getAlias = false;
                            getPreviousType = true;
                            EntityExpression previousEntity = (EntityExpression)Visit(expression.Previous);
                            getPreviousType = false;
                            select.From = oldSelect.From;

                            Evaluant.NLinq.Expressions.Identifier generatedIdentifier = new Evaluant.NLinq.Expressions.Identifier("source" + expression.GetHashCode());
                            generatedIdentifier = new EntityIdentifier(generatedIdentifier, new EntityExpression(identifier.Entity.Alias) { Type = previousEntity.Type, Expression = generatedIdentifier });

                            Evaluant.NLinq.Expressions.Identifier generatedTargetIdentifier = new Evaluant.NLinq.Expressions.Identifier("target" + expression.GetHashCode());
                            generatedTargetIdentifier = new EntityIdentifier(generatedTargetIdentifier, new EntityExpression(new TableAlias()) { Type = previousEntity.Type, Expression = generatedTargetIdentifier });

                            //from generatedIdentifier
                            //from generatedTargetIdentifier in expression
                            //where generatedIdentifier==identifier
                            //select generatedTargetIdentifier


                            //Add a join to load the reference on which we want to aggregate
                            Evaluant.NLinq.Expressions.QueryExpression query = new Evaluant.NLinq.Expressions.QueryExpression(
                                new NLinq.Expressions.FromClause(identifier.Entity.Type, generatedIdentifier, null),
                                new Evaluant.NLinq.Expressions.QueryBody(
                                    new Evaluant.NLinq.Expressions.ClauseList{
                            new NLinq.Expressions.FromClause(previousEntity.Type, generatedTargetIdentifier, expression.Previous),
                                    new Evaluant.NLinq.Expressions.WhereClause(
                            new Evaluant.NLinq.Expressions.BinaryExpression(
                                Evaluant.NLinq.Expressions.BinaryExpressionType.Equal,
                                    new EntityReferenceExpression(((EntityIdentifier)generatedIdentifier).Entity),
                                    new EntityReferenceExpression(identifier.Entity)))
                                }, new Evaluant.NLinq.Expressions.SelectClause(
                                        new EntityReferenceExpression(((EntityIdentifier)generatedTargetIdentifier).Entity)),
                                    null));

                            result = (IAliasedExpression)Visit(query);
                            select = oldSelect;
                        }
                    }
                    else
                        result = (IAliasedExpression)Visit(expression.Previous);
                    if (item.Parameters.Length == 0)
                        result = new SelectStatement(new TableAlias(), new IAliasedExpression[] { new Aggregate(aggregateType, ColumnExpression.AllColumns) }, new FromClause(result), null, null);
                    else
                        result = new SelectStatement(new TableAlias(), new IAliasedExpression[] { new Aggregate(aggregateType, item.Parameters) }, new FromClause(result), null, null);
                    return (NLinq.Expressions.Expression)result;
                }
            }
            return base.Visit(expression);

            //throw new NotSupportedException("There should be at least one previous");
        }