예제 #1
0
 public override IAliasedExpression Visit(SelectStatement item)
 {
     IDictionary<string, TableAlias> oldLoadedReferences = loadedReferences;
     Dictionary<TableAlias, TableAlias> oldAliasesMapping = AliasesMapping;
     FromClause oldFrom = currentFrom;
     loadedReferences = new Dictionary<string, TableAlias>();
     AliasesMapping = new Dictionary<TableAlias, TableAlias>();
     bool wasInFrom = inFrom;
     inFrom = false;
     var oldConstraint = constraint;
     IAliasedExpression select = base.Visit(item);
     inFrom = wasInFrom;
     if (select is SelectStatement)
     {
         SelectStatement sel = (SelectStatement)select;
         if (constraint != null)
         {
             if (sel.Where == null || sel.Where.Expression == null)
                 sel.Where = new NLinq.Expressions.WhereClause(constraint);
             else
                 sel.Where = new NLinq.Expressions.WhereClause(new NLinq.Expressions.BinaryExpression(NLinq.Expressions.BinaryExpressionType.And, sel.Where.Expression, constraint));
             constraint = oldConstraint;
         }
         select = updater.Update(sel, sel.Columns, currentFrom, sel.Where, sel.OrderBy, sel.Alias);
     }
     select = new LazyAliasResolver(AliasesMapping).Visit(select);
     loadedReferences = oldLoadedReferences;
     AliasesMapping = oldAliasesMapping;
     currentFrom = oldFrom;
     return select;
 }
예제 #2
0
        public override NLinq.Expressions.Expression Visit(NLinq.Expressions.MemberExpression item)
        {
            NLinq.Expressions.Expression target = Visit(item.Previous);
            TableAlias entityAlias = currentAlias;
            NLinq.Expressions.Expression statement = Visit(item.Statement);

            if (statement.ExpressionType==NLinq.Expressions.ExpressionTypes.Identifier)
            {
                string propertyName = ((Evaluant.NLinq.Expressions.Identifier)statement).Text;
                if (inFrom && currentEntity.References.ContainsKey(propertyName))
                {
                    Mapping.Reference reference = currentEntity.References[propertyName];
                    TableAlias newTableAlias;
                    IAliasedExpression join = mapping.Mapper.Join(reference, out newTableAlias);
                    //registeredAliasedExpression.Add(join, newTableAlias);
                    lastAliasDefined = ((JoinedTableExpression)join).RightTable.Alias;
                    loadedReferences.Add(referencePath.ToString(), lastAliasDefined);
                    AliasesMapping.Add(newTableAlias, entityAlias);
                    return (NLinq.Expressions.Expression)join;
                }
                else
                {
                    string targetReferencePath = referencePath.ToString().Substring(0, referencePath.Length - propertyName.Length);
                    //If this is not a reference leave the treatment to another visitor
                    if (currentEntity != null && currentEntity.References.ContainsKey(propertyName))
                    {
                        bool exists = currentFrom == null;
                        Mapping.Reference reference = currentEntity.References[propertyName];
                        if (!loadedReferences.ContainsKey(referencePath.ToString()))
                        {
                            currentEntity = reference.Target;
                            TableAlias newTableAlias;
                            //New target to reduce the already processed tree
                            target = (NLinq.Expressions.Expression)mapping.Mapper.Join(reference, out newTableAlias);
                            if (reference.IsComposite || loadedReferences.ContainsKey(targetReferencePath))
                            {
                                target = new LazyAliasResolver(new Dictionary<TableAlias, TableAlias>() { { newTableAlias, currentAlias } }).Visit(target);
                                newTableAlias = currentAlias;
                                //AliasesMapping[loadedReferences[targetReferencePath]] = target.Alias;
                            }


                            //Add JoinedTableExpression to load reference in query
                            if (!exists)
                                target = ((JoinedTableExpression)target).Replace(newTableAlias, currentFrom[0]);
                            else
                            {
                                //Case of Exists in where clause
                                Evaluant.NLinq.Expressions.Expression constraint;
                                target = (NLinq.Expressions.Expression)((JoinedTableExpression)target).Replace(newTableAlias, loadedReferences[targetReferencePath], out constraint);

                                if (this.constraint == null)
                                    this.constraint = constraint;
                                else
                                    this.constraint = new NLinq.Expressions.BinaryExpression(NLinq.Expressions.BinaryExpressionType.And, this.constraint, constraint);
                            }

                            //if (target == null)
                            //    throw new NotSupportedException("The alias specified could not be found");
                            if (loadedReferences.ContainsKey(targetReferencePath))
                                target = new LazyAliasResolver(new Dictionary<TableAlias, TableAlias>() { { loadedReferences[targetReferencePath], newTableAlias } }).Visit(target);
                            currentFrom = new FromClause((IAliasedExpression)target);
                            lastAliasDefined = ((JoinedTableExpression)target).RightTable.Alias;
                            loadedReferences.Add(referencePath.ToString(), lastAliasDefined);
                        }
                        else
                        {
                            if (!inFrom)
                                lastAliasDefined = loadedReferences[referencePath.ToString()];
                        }
                        if (exists)
                        {
                            var constraint = this.constraint;
                            this.constraint = null;
                            return constraint;
                        }
                        return new EntityExpression(lastAliasDefined) { Type = reference.Target.Type };
                    }
                    //else
                    //{
                    //    if (!loadedReferences.ContainsKey(targetReferencePath))
                    //        return updater.Update(item, target, statement);
                    //    //return new ComplexColumnExpression(currentAlias, target is SelectStatement ? new EntityIdentifier(propertyName, currentEntityExpression) : new Evaluant.NLinq.Expressions.Identifier(propertyName));
                    //    return updater.Update(item, target, statement);
                    //    //return new ComplexColumnExpression(currentAlias, target is SelectStatement ? new EntityIdentifier(propertyName, new EntityExpression(loadedReferences[targetReferencePath]) { Type = currentEntity.Type }) : new Evaluant.NLinq.Expressions.Identifier(propertyName));
                    //    //return updater.Update(item, target, target is SelectStatement ? new EntityIdentifier(propertyName, new EntityExpression(loadedReferences[targetReferencePath]) { Type = currentEntity.Type }) : new Evaluant.NLinq.Expressions.Identifier(propertyName));
                    //}
                }
            }
            return updater.Update(item, target, statement);
        }
예제 #3
0
 public IAliasedExpression Replace(TableAlias aliasToFind, TableAlias aliasToReplaceBy, out NLinq.Expressions.Expression constraint)
 {
     IAliasedExpression result;
     var visitor= new Visitors.LazyAliasResolver(new Dictionary<TableAlias, TableAlias>() { { aliasToFind, aliasToReplaceBy } });
     if (LeftTable.Alias == aliasToFind)
     {
         constraint = visitor.Visit(On);
         return visitor.Visit(RightTable);
     }
     if (RightTable.Alias == aliasToFind)
     {
         constraint = visitor.Visit(On);
         return visitor.Visit(RightTable);
     }
     if (LeftTable is JoinedTableExpression && (result = ((JoinedTableExpression)LeftTable).Replace(aliasToFind, aliasToReplaceBy, out constraint)) != null)
     {
         LeftTable = result;
         //LeftTable = (JoinedTableExpression)new Visitors.LazyAliasResolver(new Dictionary<TableAlias, TableAlias>() { { aliasToFind, expressionReplacement.Alias } }).Visit(this);
         return this;
     }
     if (RightTable is JoinedTableExpression && (result = ((JoinedTableExpression)RightTable).Replace(aliasToFind, aliasToReplaceBy, out constraint)) != null)
     {
         RightTable = result;
         //RightTable = new Visitors.LazyAliasResolver(new Dictionary<TableAlias, TableAlias>() { { aliasToFind, expressionReplacement.Alias } }).Visit(this);
         return this;
     }
     constraint = null;
     return null;
 }
예제 #4
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");
        }