Ejemplo n.º 1
0
        protected override Expression VisitIn(InExpression expression)
        {
            if (!ShouldRewrite(expression)) {
                return base.VisitIn(expression);
            }

            Array array = expression.Values.OfType<ConstantExpression>().Select(item => item.Value).Distinct().ToArray();

            var vfpDataXml = new ArrayXmlToCursor(array);
            var tableAlias = new TableAlias();
            var columnType = _language.TypeSystem.GetColumnType(vfpDataXml.ItemType);
            var columnExpression = new ColumnExpression(vfpDataXml.ItemType, columnType, tableAlias, ArrayXmlToCursor.ColumnName);

            var columns = new List<ColumnDeclaration> {
                new ColumnDeclaration(string.Empty, columnExpression, columnType)
            };

            var xml = Expression.Constant(vfpDataXml.Xml);
            var cursorName = Expression.Constant("curTemp_" + DateTime.Now.ToString("ddHHssmm"));
            var check = Expression.GreaterThan(new XmlToCursorExpression(xml, cursorName), Expression.Constant(0));
            var from = Expression.Condition(check, cursorName, Expression.Constant(string.Empty));
            var select = new SelectExpression(tableAlias, columns, from, null);

            return new InExpression(expression.Expression, select);
        }
Ejemplo n.º 2
0
 protected void AddAlias(TableAlias alias)
 {
     if (!this.aliasMap.ContainsKey(alias))
     {
         this.aliasMap.Add(alias, this.aliasMap.Count);
     }
 }
Ejemplo n.º 3
0
 internal static Expression Parameterize(TableAlias outerAlias, Expression expr, int parameterCounter)
 {
     OuterParameterizer op = new OuterParameterizer();
     op.outerAlias = outerAlias;
     op.parameterCounter = parameterCounter;
     return op.Visit(expr);
 }
Ejemplo n.º 4
0
 protected override Expression VisitSelect(SelectExpression select)
 {
     TableAlias newAlias = new TableAlias();
     this.map[select.Alias] = newAlias;
     select = (SelectExpression)base.VisitSelect(select);
     return new SelectExpression(newAlias, select.Columns, select.From, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take, select.IsReverse);
 }
Ejemplo n.º 5
0
 internal Scope(Scope outer, ParameterExpression fieldReader, TableAlias alias, IEnumerable<ColumnDeclaration> columns)
 {
     this.outer = outer;
     this.fieldReader = fieldReader;
     this.Alias = alias;
     this.nameMap = columns.Select((c, i) => new { c, i }).ToDictionary(x => x.c.Name, x => x.i);
 }
        public static SelectExpression AddRedundantSelect(this SelectExpression sel, QueryLanguage language, TableAlias newAlias)
        {
            var newColumns =
                from d in sel.Columns
                let qt = (d.Expression is ColumnExpression) ? ((ColumnExpression)d.Expression).QueryType : language.TypeSystem.GetColumnType(d.Expression.Type)
                select new ColumnDeclaration(d.Name, new ColumnExpression(d.Expression.Type, qt, newAlias, d.Name), qt);

            var newFrom = new SelectExpression(newAlias, sel.Columns, sel.From, sel.Where, sel.OrderBy, sel.GroupBy, sel.IsDistinct, sel.Skip, sel.Take, sel.IsReverse);
            return new SelectExpression(sel.Alias, newColumns, newFrom, null, null, null, false, null, null, false);
        }
Ejemplo n.º 7
0
 private void MarkColumnAsUsed(TableAlias alias, string name)
 {
     HashSet<string> columns;
     if (!this.allColumnsUsed.TryGetValue(alias, out columns))
     {
         columns = new HashSet<string>();
         this.allColumnsUsed.Add(alias, columns);
     }
     columns.Add(name);
 }
Ejemplo n.º 8
0
 public override TableAlias Visit(TableAlias item)
 {
     if (item == null)
         return null;
     TableAlias result;
     if (!aliasesMapping.TryGetValue(item, out result))
         if (!aliasesMapping.TryGetValue(TableAlias.All, out result))
             return item;
     return result;
 }
        protected override Expression VisitProjection(ProjectionExpression proj)
        {
            SelectExpression save = this.currentSelect;
            this.currentSelect = proj.Source;
            try
            {
                if (!this.isTopLevel)
                {
                    if (this.CanJoinOnClient(this.currentSelect))
                    {
                        // make a query that combines all the constraints from the outer queries into a single select
                        SelectExpression newOuterSelect = (SelectExpression)QueryDuplicator.Duplicate(save);

                        // remap any references to the outer select to the new alias;
                        SelectExpression newInnerSelect = (SelectExpression)ColumnMapper.Map(proj.Source, newOuterSelect.Alias, save.Alias);
                        // add outer-join test
                        ProjectionExpression newInnerProjection = new ProjectionExpression(newInnerSelect, proj.Projector).AddOuterJoinTest();
                        newInnerSelect = newInnerProjection.Source;
                        Expression newProjector = newInnerProjection.Projector;

                        TableAlias newAlias = new TableAlias();
                        var pc = ColumnProjector.ProjectColumns(this.language.CanBeColumn, newProjector, newOuterSelect.Columns, newAlias, newOuterSelect.Alias, newInnerSelect.Alias);
                        JoinExpression join = new JoinExpression(JoinType.OuterApply, newOuterSelect, newInnerSelect, null);
                        SelectExpression joinedSelect = new SelectExpression(newAlias, pc.Columns, join, null, null, null, proj.IsSingleton, null, null);

                        // apply client-join treatment recursively
                        this.currentSelect = joinedSelect;
                        newProjector = this.Visit(pc.Projector); 

                        // compute keys (this only works if join condition was a single column comparison)
                        List<Expression> outerKeys = new List<Expression>();
                        List<Expression> innerKeys = new List<Expression>();
                        if (this.GetEquiJoinKeyExpressions(newInnerSelect.Where, newOuterSelect.Alias, outerKeys, innerKeys))
                        {
                            // outerKey needs to refer to the outer-scope's alias
                            var outerKey = outerKeys.Select(k => ColumnMapper.Map(k, save.Alias, newOuterSelect.Alias));
                            // innerKey needs to refer to the new alias for the select with the new join
                            var innerKey = innerKeys.Select(k => ColumnMapper.Map(k, joinedSelect.Alias, ((ColumnExpression)k).Alias));
                            ProjectionExpression newProjection = new ProjectionExpression(joinedSelect, newProjector, proj.Aggregator);
                            return new ClientJoinExpression(newProjection, outerKey, innerKey);
                        }
                    }
                }
                else
                {
                    this.isTopLevel = false;
                }

                return base.VisitProjection(proj);
            }
            finally 
            {
                this.currentSelect = save;
            }
        }
Ejemplo n.º 10
0
 private bool IsColumnUsed(TableAlias alias, string name)
 {
     HashSet<string> columnsUsed;
     if (this.allColumnsUsed.TryGetValue(alias, out columnsUsed))
     {
         if (columnsUsed != null)
         {
             return columnsUsed.Contains(name);
         }
     }
     return false;
 }
Ejemplo n.º 11
0
 private ColumnProjector(Func <Expression, bool> fnCanBeColumn, Expression expression, IEnumerable <ColumnDeclaration> existingColumns, TableAlias newAlias, IEnumerable <TableAlias> existingAliases)
 {
     this.newAlias        = newAlias;
     this.existingAliases = new HashSet <TableAlias>(existingAliases);
     this.map             = new Dictionary <ColumnExpression, ColumnExpression>();
     if (existingColumns != null)
     {
         this.columns     = new List <ColumnDeclaration>(existingColumns);
         this.columnNames = new HashSet <string>(existingColumns.Select(c => c.Name));
     }
     else
     {
         this.columns     = new List <ColumnDeclaration>();
         this.columnNames = new HashSet <string>();
     }
     this.candidates = Nominator.Nominate(fnCanBeColumn, expression);
 }
Ejemplo n.º 12
0
        internal static ProjectionExpression GetTableQuery(TranslateContext transContext, EntityMetadata entity, bool isNoTracking, bool isAsync)
        {
            var tableAlias  = new TableAlias();
            var selectAlias = new TableAlias();
            var entityType  = entity.EntityType;
            var table       = new TableExpression(tableAlias, entity.TableName, entityType);

            var projector = GetTypeProjection(transContext, table, entity);
            var pc        = ColumnProjector.ProjectColumns(CanBeColumnExpression, projector, null, selectAlias, tableAlias);

            var proj = new ProjectionExpression(
                new SelectExpression(selectAlias, pc.Columns, table, null),
                pc.Projector, isAsync, isNoTracking
                );

            return((ProjectionExpression)transContext.QueryPolicy.ApplyPolicy(proj, entityType, ex => QueryBinder.Bind(transContext, ex)));
        }
Ejemplo n.º 13
0
        protected override Expression VisitProjection(ProjectionExpression proj)
        {
            if (isTopLevel)
            {
                isTopLevel    = false;
                currentSelect = proj.Source;
                Expression projector = Visit(proj.Projector);
                if (projector != proj.Projector || currentSelect != proj.Source)
                {
                    return(new ProjectionExpression(currentSelect, projector, proj.Aggregator));
                }
                return(proj);
            }

            if (proj.IsSingleton && CanJoinOnServer(currentSelect))
            {
                TableAlias newAlias = new TableAlias();
                currentSelect = currentSelect.AddRedundantSelect(newAlias);

                // remap any references to the outer select to the new alias;
                SelectExpression source =
                    (SelectExpression)ColumnMapper.Map(proj.Source, newAlias, currentSelect.Alias);

                // add outer-join test
                ProjectionExpression pex = new ProjectionExpression(source, proj.Projector).AddOuterJoinTest();

                var pc = ColumnProjector.ProjectColumns(language.CanBeColumn, pex.Projector, currentSelect.Columns,
                                                        currentSelect.Alias, newAlias, proj.Source.Alias);

                JoinExpression join = new JoinExpression(JoinType.OuterApply, currentSelect.From, pex.Source, null);

                currentSelect = new SelectExpression(currentSelect.Alias, pc.Columns, join, null);
                return(Visit(pc.Projector));
            }

            var saveTop    = isTopLevel;
            var saveSelect = currentSelect;

            isTopLevel    = true;
            currentSelect = null;
            Expression result = base.VisitProjection(proj);

            isTopLevel    = saveTop;
            currentSelect = saveSelect;
            return(result);
        }
Ejemplo n.º 14
0
 private ColumnProjector(Func<Expression, bool> fnCanBeColumn, Expression expression, IEnumerable<ColumnDeclaration> existingColumns, TableAlias newAlias, IEnumerable<TableAlias> existingAliases)
 {
     this.newAlias = newAlias;
     this.existingAliases = new HashSet<TableAlias>(existingAliases);
     this.map = new Dictionary<ColumnExpression, ColumnExpression>();
     if (existingColumns != null)
     {
         this.columns = new List<ColumnDeclaration>(existingColumns);
         this.columnNames = new HashSet<string>(existingColumns.Select(c => c.Name));
     }
     else
     {
         this.columns = new List<ColumnDeclaration>();
         this.columnNames = new HashSet<string>();
     }
     this.candidates = Nominator.Nominate(fnCanBeColumn, expression);
 }
Ejemplo n.º 15
0
        internal static ProjectionExpression GetTableQuery(EntityMetadata entity, bool isNoTracking)
        {
            var tableAlias  = new TableAlias();
            var selectAlias = new TableAlias();
            var entityType  = entity.EntityType;
            var table       = new TableExpression(tableAlias, entity.TableName, entityType);

            var projector = GetTypeProjection(table, entity, isNoTracking);
            var pc        = ColumnProjector.ProjectColumns(CanBeColumnExpression, projector, null, selectAlias, tableAlias);

            var proj = new ProjectionExpression(
                new SelectExpression(selectAlias, pc.Columns, table, null),
                pc.Projector
                );

            return((ProjectionExpression)ApplyPolicy(proj, entityType));
        }
Ejemplo n.º 16
0
 private ColumnProjector(Expression expression, IEnumerable<ColumnDeclaration> existingColumns, TableAlias newAlias, IEnumerable<TableAlias> existingAliases)
 {
     this.newAlias = newAlias;
     this.existingAliases = new HashSet<TableAlias>(existingAliases, TableAlias.Comparer);
     this.map = new Dictionary<ColumnExpression, ColumnExpression>();
     if (existingColumns != null)
     {
         this.columns = new List<ColumnDeclaration>(existingColumns);
         this.columnNames = new HashSet<string>(existingColumns.Select(c => c.Name), StringComparer.Ordinal);
     }
     else
     {
         this.columns = new List<ColumnDeclaration>();
         this.columnNames = new HashSet<string>(StringComparer.Ordinal);
     }
     this.candidates = Nominator.Nominate(expression);
 }
Ejemplo n.º 17
0
        private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions)
        {
            if (predicate.NodeType == ExpressionType.Equal)
            {
                var b = (BinaryExpression)predicate;
                ColumnExpression leftCol  = this.GetColumnExpression(b.Left);
                ColumnExpression rightCol = this.GetColumnExpression(b.Right);
                if (leftCol != null && rightCol != null)
                {
                    if (leftCol.Alias == outerAlias)
                    {
                        outerExpressions.Add(b.Left);
                        innerExpressions.Add(b.Right);
                        return(true);
                    }
                    else if (rightCol.Alias == outerAlias)
                    {
                        innerExpressions.Add(b.Left);
                        outerExpressions.Add(b.Right);
                        return(true);
                    }
                }
            }

            bool hadKey = false;
            var  parts  = predicate.Split(ExpressionType.And, ExpressionType.AndAlso);

            if (parts.Length > 1)
            {
                foreach (var part in parts)
                {
                    bool hasOuterAliasReference = ReferencedAliasGatherer.Gather(part).Contains(outerAlias);
                    if (hasOuterAliasReference)
                    {
                        if (!GetEquiJoinKeyExpressions(part, outerAlias, outerExpressions, innerExpressions))
                        {
                            return(false);
                        }
                        hadKey = true;
                    }
                }
            }

            return(hadKey);
        }
Ejemplo n.º 18
0
 public IWhereClauseBuilder Or <TEntity>(Expression <Func <TEntity, bool> > expression,
                                         TableAlias alias,
                                         string tableName   = null,
                                         string tableSchema = null)
 {
     if (string.IsNullOrWhiteSpace(Sql()))
     {
         return(Where <TEntity>(expression, alias, false,
                                tableName,
                                tableSchema));
     }
     else
     {
         return(Or <TEntity>(expression, Utils.Alias(alias),
                             tableName,
                             tableSchema));
     }
 }
Ejemplo n.º 19
0
 public IWhereClauseBuilder Where <TEntity>(Expression <Func <TEntity, bool> > expression,
                                            TableAlias alias, bool ClearBeforeWhereeClause = false,
                                            string tableName   = null,
                                            string tableSchema = null)
 {
     if (string.IsNullOrWhiteSpace(Sql()) || ClearBeforeWhereeClause == true)
     {
         return(Where <TEntity>(expression, Utils.Alias(alias),
                                tableName,
                                tableSchema));
     }
     else
     {
         return(And <TEntity>(expression, Utils.Alias(alias),
                              tableName,
                              tableSchema));
     }
 }
Ejemplo n.º 20
0
 public IWhereClauseBuilder AndIn <TEntity, TMember>(Expression <Func <TEntity, TMember> > selector,
                                                     TMember[] values, TableAlias alias,
                                                     string tableName   = null,
                                                     string tableSchema = null)
 {
     if (string.IsNullOrWhiteSpace(Sql()))
     {
         return(WhereIn <TEntity, TMember>(selector, values, alias, false,
                                           tableName,
                                           tableSchema));
     }
     else
     {
         return(AndIn <TEntity, TMember>(selector, values, Utils.Alias(alias),
                                         tableName,
                                         tableSchema));
     }
 }
Ejemplo n.º 21
0
        public virtual Expression GetMemberExpression(Expression root, IEntityMapping mapping, IMemberMapping mm)
        {
            var m = mm.Member;

            if (mm.IsRelationship)
            {
                IEntityMapping       relatedEntity = mm.RelatedEntity;
                ProjectionExpression projection    = this.GetQueryExpression(relatedEntity);

                // make where clause for joining back to 'root'
                var thisKeyMembers  = mm.ThisKeyMembers;
                var otherKeyMembers = mm.OtherKeyMembers;

                Expression where = null;
                for (int i = 0, n = otherKeyMembers.Length; i < n; i++)
                {
                    Expression equal =
                        this.GetMemberExpression(projection.Projector, relatedEntity, otherKeyMembers[i]).Equal(
                            this.GetMemberExpression(root, mapping, thisKeyMembers[i])
                            );
                    where = (where != null) ? where.And(equal) : equal;
                }

                TableAlias newAlias = new TableAlias();
                var        pc       = ColumnProjector.ProjectColumns(projection.Projector, null, newAlias, projection.Select.Alias);

                LambdaExpression aggregator = Aggregator.GetAggregator(mm.MemberType, typeof(IEnumerable <>).MakeGenericType(pc.Projector.Type));
                var result = new ProjectionExpression(
                    new SelectExpression(newAlias, pc.Columns, projection.Select, where),
                    pc.Projector, aggregator
                    );

                return(ApplyPolicy(result, m));
            }
            else
            {
                AliasedExpression aliasedRoot = root as AliasedExpression;
                if (aliasedRoot != null && mm.IsColumn)
                {
                    return(new ColumnExpression(mm.MemberType, mm.SqlType, aliasedRoot.Alias, mm.ColumnName));
                }
                return(QueryBinder.BindMember(root, m));
            }
        }
        protected override Expression VisitProjection(ProjectionExpression proj)
        {
            if (isTopLevel)
            {
                isTopLevel = false;
                currentSelect = proj.Source;
                Expression projector = Visit(proj.Projector);
                if (projector != proj.Projector || currentSelect != proj.Source)
                {
                    return new ProjectionExpression(currentSelect, projector, proj.Aggregator);
                }
                return proj;
            }

            if (proj.IsSingleton && CanJoinOnServer(currentSelect))
            {
                TableAlias newAlias = new TableAlias();
                currentSelect = currentSelect.AddRedundantSelect(newAlias);

                // remap any references to the outer select to the new alias;
                SelectExpression source =
                    (SelectExpression) ColumnMapper.Map(proj.Source, newAlias, currentSelect.Alias);

                // add outer-join test
                ProjectionExpression pex = new ProjectionExpression(source, proj.Projector).AddOuterJoinTest();

                var pc = ColumnProjector.ProjectColumns(language.CanBeColumn, pex.Projector, currentSelect.Columns,
                                                        currentSelect.Alias, newAlias, proj.Source.Alias);

                JoinExpression join = new JoinExpression(JoinType.OuterApply, currentSelect.From, pex.Source, null);

                currentSelect = new SelectExpression(currentSelect.Alias, pc.Columns, join, null);
                return Visit(pc.Projector);
            }

            var saveTop = isTopLevel;
            var saveSelect = currentSelect;
            isTopLevel = true;
            currentSelect = null;
            Expression result = base.VisitProjection(proj);
            isTopLevel = saveTop;
            currentSelect = saveSelect;
            return result;
        }
Ejemplo n.º 23
0
        public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector)
        {
            var tables = this.mapping.GetTables(entity);

            if (tables.Count < 2)
            {
                return(base.GetInsertExpression(entity, instance, selector));
            }

            var commands = new List <Expression>();

            var map    = this.GetDependentGeneratedColumns(entity);
            var vexMap = new Dictionary <MemberInfo, Expression>();

            foreach (var table in this.GetDependencyOrderedTables(entity))
            {
                var tableAlias  = new TableAlias();
                var tex         = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table));
                var assignments = this.GetColumnAssignments(tex,
                                                            instance,
                                                            entity,
                                                            (e, m) => this.mapping.GetAlias(e, m) == this.mapping.GetAlias(table) && !this.mapping.IsGenerated(e, m),
                                                            vexMap);
                var totalAssignments = assignments.Concat(
                    this.GetRelatedColumnAssignments(tex, entity, table, vexMap));
                commands.Add(new InsertCommand(tex, totalAssignments));

                List <MemberInfo> members;
                if (map.TryGetValue(this.mapping.GetAlias(table), out members))
                {
                    var d = this.GetDependentGeneratedVariableDeclaration(entity, table, members, instance, vexMap);
                    commands.Add(d);
                }
            }

            if (selector != null)
            {
                commands.Add(this.GetInsertResult(entity, instance, selector, vexMap));
            }

            return(new BlockCommand(commands));
        }
Ejemplo n.º 24
0
        private Expression MakeSubquery(Expression expression)
        {
            var newAlias = new TableAlias();
            var aliases = TableAliasGatherer.Gather(expression);

            var decls = new List<ColumnDeclaration>();
            foreach (var ta in aliases)
            {
                foreach (var col in this.columns[ta])
                {
                    string name = decls.GetAvailableColumnName(col.Name);
                    var decl = new ColumnDeclaration(name, col, col.SqlType);
                    decls.Add(decl);
                    var newCol = new ColumnExpression(col.Type, col.SqlType, newAlias, name);
                    this.map.Add(col, newCol);
                }
            }

            return new SelectExpression(newAlias, decls, expression, null);
        }
Ejemplo n.º 25
0
 public IWhereClauseBuilder OrBetween <TEntity, TMember>(Expression <Func <TEntity, TMember> > selector,
                                                         TMember start,
                                                         TMember end,
                                                         TableAlias alias,
                                                         string tableName   = null,
                                                         string tableSchema = null)
 {
     if (string.IsNullOrWhiteSpace(Sql()))
     {
         return(WhereBetween <TEntity, TMember>(selector, start, end, Utils.Alias(alias),
                                                tableName,
                                                tableSchema));
     }
     else
     {
         return(OrBetween <TEntity, TMember>(selector, start, end, Utils.Alias(alias),
                                             tableName,
                                             tableSchema));
     }
 }
Ejemplo n.º 26
0
        private Expression MakeSubquery(Expression expression)
        {
            var newAlias = new TableAlias();
            var aliases  = DeclaredAliasGatherer.Gather(expression);

            var decls = new List <ColumnDeclaration>();

            foreach (var ta in aliases)
            {
                foreach (var col in columns[ta])
                {
                    var name = decls.GetAvailableColumnName(col.Name);
                    var decl = new ColumnDeclaration(name, col);
                    decls.Add(decl);
                    var newCol = new ColumnExpression(col.Type, newAlias, name, null);
                    map.Add(col, newCol);
                }
            }

            return(new SelectExpression(newAlias, decls, expression, null));
        }
Ejemplo n.º 27
0
        protected override DeclarationCommand GetGeneratedIdCommand(MappingEntity entity, List <MemberInfo> members, Dictionary <MemberInfo, Expression> map)
        {
            var columns = new List <ColumnDeclaration>();
            var decls   = new List <VariableDeclaration>();
            var alias   = new TableAlias();

            var orderBy = new List <OrderExpression> {
                new OrderExpression(OrderType.Ascending, Expression.Constant(1))
            };

            foreach (var member in members)
            {
                var genId = Translator.Linguist.Language.GetGeneratedIdExpression(member);

                var colType = GetColumnType(entity, member);
                columns.Add(new ColumnDeclaration(member.Name, genId, colType));
                decls.Add(new VariableDeclaration(member.Name, colType, new ColumnExpression(genId.Type, colType, alias, member.Name)));
                if (map != null)
                {
                    var vex = new VariableExpression(member.Name, TypeHelper.GetMemberType(member), colType);
                    map.Add(member, vex);
                }
            }

            var attributeMapping = entity as VfpAttributeMapping.AttributeMappingEntity;
            var tableId          = entity.TableId;

            if (attributeMapping != null)
            {
                tableId = attributeMapping.TableName;
            }

            var        from = new TableExpression(alias, entity, tableId);
            Expression take = Expression.Constant(1);

            var select = new SelectExpression(alias, columns, from, null, new ReadOnlyCollection <OrderExpression>(orderBy), null, false, null, take, false);

            return(new DeclarationCommand(decls, select));
        }
Ejemplo n.º 28
0
        public virtual ProjectionExpression GetQueryExpression(IEntityMapping mapping)
        {
            Expression           projector;
            TableAlias           selectAlias;
            ProjectedColumns     pc;
            ProjectionExpression proj;

            var tableAlias = new TableAlias();

            selectAlias = new TableAlias();
            var table = new TableExpression(tableAlias, mapping);

            projector = this.GetEntityExpression(table, mapping);
            pc        = ColumnProjector.ProjectColumns(projector, null, selectAlias, tableAlias);

            proj = new ProjectionExpression(
                new SelectExpression(selectAlias, pc.Columns, table, null),
                pc.Projector
                );

            return((ProjectionExpression)ApplyPolicy(proj, mapping.EntityType));
        }
Ejemplo n.º 29
0
        internal DeclarationCommand GetGeneratedIdCommand(IEntityMapping mapping, List <IMemberMapping> members, Dictionary <MemberInfo, Expression> map)
        {
            var columns = new List <ColumnDeclaration>();
            var decls   = new List <VariableDeclaration>();
            var alias   = new TableAlias();

            foreach (var member in members)
            {
                Expression genId   = this.GetGeneratedIdExpression(member);
                var        name    = member.Member.Name;
                var        colType = member.SqlType;
                columns.Add(new ColumnDeclaration(name, genId, colType));
                decls.Add(new VariableDeclaration(name, colType, new ColumnExpression(genId.Type, colType, alias, name)));
                if (map != null)
                {
                    var vex = new VariableExpression(name, member.MemberType, colType);
                    map.Add(member.Member, vex);
                }
            }
            var select = new SelectExpression(alias, columns, null, null);

            return(new DeclarationCommand(decls, select));
        }
        private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions)
        {
            // predicate can be AND's and EQUAL's between columns
            BinaryExpression b = predicate as BinaryExpression;

            if (b != null)
            {
                switch (predicate.NodeType)
                {
                case ExpressionType.And:
                case ExpressionType.AndAlso:
                    return(this.GetEquiJoinKeyExpressions(b.Left, outerAlias, outerExpressions, innerExpressions) &&
                           this.GetEquiJoinKeyExpressions(b.Right, outerAlias, outerExpressions, innerExpressions));

                case ExpressionType.Equal:
                    ColumnExpression left  = b.Left as ColumnExpression;
                    ColumnExpression right = b.Right as ColumnExpression;
                    if (left != null && right != null)
                    {
                        if (left.Alias == outerAlias)
                        {
                            outerExpressions.Add(left);
                            innerExpressions.Add(right);
                            return(true);
                        }
                        else if (right.Alias == outerAlias)
                        {
                            innerExpressions.Add(left);
                            outerExpressions.Add(right);
                            return(true);
                        }
                    }
                    break;
                }
            }
            return(false);
        }
Ejemplo n.º 31
0
        public IEntityWriter <IdType, EntityType> Update(IList <EntityType> entities)
        {
            foreach (var entity in entities)
            {
                var task = new ExecuteTask <EntityType>(_tasks.Count)
                {
                    TaskType = ActionType.Update,
                    Entity   = entity,
                };

                task.Queries.Add(
                    new QueryElement()
                {
                    FieldName  = IdColumn,
                    Operator   = Operator.Equals,
                    Value      = entity.Id,
                    TableAlias = TableAlias.ToString()
                });

                _tasks.Add(task);
            }

            return(this);
        }
Ejemplo n.º 32
0
        public virtual Expression GetInsertExpression(IEntityMapping mapping, Expression instance, LambdaExpression selector)
        {
            var tableAlias  = new TableAlias();
            var table       = new TableExpression(tableAlias, mapping);
            var assignments = this.GetInsertColumnAssignments(table, instance, mapping, m => !m.IsGenerated && !m.IsVersion).ToArray();

            object o = null;
            var    c = instance as ConstantExpression;

            if (c != null)
            {
                o = c.Value;
            }

            if (selector != null)
            {
                return(new BlockCommand(
                           new InsertCommand(table, assignments, o),
                           this.GetInsertResult(mapping, instance, selector, null)
                           ));
            }

            return(new InsertCommand(table, assignments, o));
        }
Ejemplo n.º 33
0
        private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions)
        {
            var b = predicate as BinaryExpression;

            if (b != null)
            {
                switch (predicate.NodeType)
                {
                case ExpressionType.And:
                case ExpressionType.AndAlso:
                    return(GetEquiJoinKeyExpressions(b.Left, outerAlias, outerExpressions, innerExpressions) &&
                           GetEquiJoinKeyExpressions(b.Right, outerAlias, outerExpressions, innerExpressions));

                case ExpressionType.Equal:
                    var left  = b.Left as ColumnExpression;
                    var right = b.Right as ColumnExpression;
                    if (left != null && right != null)
                    {
                        if (left.Alias == outerAlias)
                        {
                            outerExpressions.Add(left);
                            innerExpressions.Add(right);
                            return(true);
                        }
                        else if (right.Alias == outerAlias)
                        {
                            innerExpressions.Add(left);
                            outerExpressions.Add(right);
                            return(true);
                        }
                    }
                    break;
                }
            }
            return(false);
        }
Ejemplo n.º 34
0
        /// <summary>
        /// 创建 INSRT 命令
        /// </summary>
        /// <param name="dbQuery">查询语义</param>
        /// <param name="token">解析上下文</param>
        /// <returns></returns>
        protected override RawCommand ResolveInsertCommand <T>(IDbQueryableInfo_Insert dbQuery, ResolveToken token)
        {
            TableAlias  aliases     = new TableAlias();
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            if (dbQuery.Entity != null)
            {
                object      entity      = dbQuery.Entity;
                ISqlBuilder seg_Columns = this.CreateSqlBuilder(token);
                ISqlBuilder seg_Values  = this.CreateSqlBuilder(token);

                // 指定插入列
                MemberAccessorCollection memberAccessors = typeRuntime.Members;
                if (dbQuery.EntityColumns != null && dbQuery.EntityColumns.Count > 0)
                {
                    memberAccessors = new MemberAccessorCollection();
                    for (int i = 0; i < dbQuery.EntityColumns.Count; i++)
                    {
                        Expression curExpr = dbQuery.EntityColumns[i];
                        if (curExpr.NodeType == ExpressionType.Lambda)
                        {
                            curExpr = (curExpr as LambdaExpression).Body.ReduceUnary();
                        }
                        if (curExpr.NodeType != ExpressionType.MemberAccess)
                        {
                            throw new XFrameworkException("Can't read field name from expression {0}", dbQuery.EntityColumns[i]);
                        }

                        MemberExpression member = curExpr as MemberExpression;
                        string           name   = member.Member.Name;
                        memberAccessors[name] = typeRuntime.Members[name];
                    }
                }

                foreach (var m in memberAccessors)
                {
                    var column = m.Column;
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (m.ForeignKey != null)
                    {
                        continue;
                    }
                    if (m.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    if (m != typeRuntime.Identity)
                    {
                        seg_Columns.AppendMember(m.Member.Name);
                        seg_Columns.Append(',');

                        var    value = m.Invoke(entity);
                        string seg   = this.DbValue.GetSqlValueWidthDefault(value, token, column);
                        seg_Values.Append(seg);
                        seg_Values.Append(',');
                    }
                }
                seg_Columns.Length -= 1;
                seg_Values.Length  -= 1;

                if (dbQuery.Bulk == null || !dbQuery.Bulk.OnlyValue)
                {
                    builder.Append("INSERT INTO ");
                    builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                    builder.Append('(');
                    builder.Append(seg_Columns);
                    builder.Append(')');
                    builder.AppendNewLine();
                    builder.AppendTab();
                    builder.Append("VALUES");
                }

                builder.Append('(');
                builder.Append(seg_Values);
                builder.Append(')');
                if (dbQuery.Bulk != null && !dbQuery.Bulk.IsEndPos)
                {
                    builder.Append(",");
                }

                if (dbQuery.Bulk == null && typeRuntime.Identity != null)
                {
                    builder.Append(';');
                    builder.AppendNewLine();

                    builder.AppendFormat("SELECT LAST_INSERT_ROWID()");
                    builder.Append(" AS ");
                    builder.Append(this.QuotePrefix);
                    builder.Append(Constant.AUTO_INCREMENT_NAME);
                    builder.Append(this.QuoteSuffix);
                }
            }
            else if (dbQuery.Query != null)
            {
                builder.Append("INSERT INTO ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append('(');

                int            i   = 0;
                MappingCommand cmd = this.ResolveSelectCommandImpl(dbQuery.Query, 0, false, token) as MappingCommand;
                //for (int i = 0; i < seg.Columns.Count; i++)
                foreach (var column in cmd.PickColumns)
                {
                    builder.AppendMember(column.Name);
                    if (i < cmd.PickColumns.Count - 1)
                    {
                        builder.Append(',');
                    }
                    i++;
                }

                builder.Append(')');
                builder.AppendNewLine();
                builder.Append(cmd.CommandText);
            }

            if (dbQuery.Bulk == null || dbQuery.Bulk.IsEndPos)
            {
                builder.Append(';');
            }
            return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Ejemplo n.º 35
0
 protected override Expression VisitTable(TableExpression table)
 {
     TableAlias newAlias = new TableAlias();
     this.map[table.Alias] = newAlias;
     return new TableExpression(newAlias, table.Entity, table.Name);
 }
Ejemplo n.º 36
0
        // make a variable declaration / initialization for dependent generated values
        private CommandExpression GetDependentGeneratedVariableDeclaration(MappingEntity entity, MappingTable table, List<MemberInfo> members, Expression instance, Dictionary<MemberInfo, Expression> map)
        {
            // first make command that retrieves the generated ids if any
            DeclarationCommand genIdCommand = null;
            var generatedIds = this.mapping.GetMappedMembers(entity).Where(m => this.mapping.IsPrimaryKey(entity, m) && this.mapping.IsGenerated(entity, m)).ToList();
            if (generatedIds.Count > 0)
            {
                genIdCommand = this.GetGeneratedIdCommand(entity, members, map);

                // if that's all there is then just return the generated ids
                if (members.Count == generatedIds.Count)
                {
                    return genIdCommand;
                }
            }

            // next make command that retrieves the generated members
            // only consider members that were not generated ids
            members = members.Except(generatedIds).ToList();

            var tableAlias = new TableAlias();
            var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table));

            Expression where = null;
            if (generatedIds.Count > 0)
            {
                where = generatedIds.Select((m, i) =>
                    this.GetMemberExpression(tex, entity, m).Equal(map[m])
                    ).Aggregate((x, y) => x.And(y));
            }
            else
            {
                where = this.GetIdentityCheck(tex, entity, instance);
            }

            TableAlias selectAlias = new TableAlias();
            var columns = new List<ColumnDeclaration>();
            var variables = new List<VariableDeclaration>();
            foreach (var mi in members)
            {
                ColumnExpression col = (ColumnExpression)this.GetMemberExpression(tex, entity, mi);
                columns.Add(new ColumnDeclaration(this.mapping.GetColumnName(entity, mi), col, col.QueryType));
                ColumnExpression vcol = new ColumnExpression(col.Type, col.QueryType, selectAlias, col.Name);
                variables.Add(new VariableDeclaration(mi.Name, col.QueryType, vcol));
                map.Add(mi, new VariableExpression(mi.Name, col.Type, col.QueryType));
            }

            var genMembersCommand = new DeclarationCommand(variables, new SelectExpression(selectAlias, columns, tex, where));

            if (genIdCommand != null)
            {
                return new BlockCommand(genIdCommand, genMembersCommand);
            }

            return genMembersCommand;
        }
Ejemplo n.º 37
0
        public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector)
        {
            var tables = this.mapping.GetTables(entity);
            if (tables.Count < 2)
            {
                return base.GetInsertExpression(entity, instance, selector);
            }

            var commands = new List<Expression>();

            var map = this.GetDependentGeneratedColumns(entity);
            var vexMap = new Dictionary<MemberInfo, Expression>();

            foreach (var table in this.GetDependencyOrderedTables(entity))
            {
                var tableAlias = new TableAlias();
                var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table));
                var assignments = this.GetColumnAssignments(tex, instance, entity,
                    (e, m) => this.mapping.GetAlias(e, m) == this.mapping.GetAlias(table) && !this.mapping.IsGenerated(e, m),
                    vexMap
                    );
                var totalAssignments = assignments.Concat(
                    this.GetRelatedColumnAssignments(tex, entity, table, vexMap)
                    );
                commands.Add(new InsertCommand(tex, totalAssignments));

                List<MemberInfo> members;
                if (map.TryGetValue(this.mapping.GetAlias(table), out members))
                {
                    var d = this.GetDependentGeneratedVariableDeclaration(entity, table, members, instance, vexMap);
                    commands.Add(d);
                }
            }

            if (selector != null)
            {
                commands.Add(this.GetInsertResult(entity, instance, selector, vexMap));
            }

            return new BlockCommand(commands);
        }
Ejemplo n.º 38
0
 protected virtual bool CompareAlias(TableAlias a, TableAlias b)
 {
     if (this.aliasScope != null)
     {
         TableAlias mapped;
         if (this.aliasScope.TryGetValue(a, out mapped))
             return mapped == b;
     }
     return a == b;
 }
Ejemplo n.º 39
0
        public override ProjectionExpression GetQueryExpression(MappingEntity entity)
        {
            var tables = this.mapping.GetTables(entity);
            if (tables.Count <= 1)
            {
                return base.GetQueryExpression(entity);
            }

            var aliases = new Dictionary<string, TableAlias>();
            MappingTable rootTable = tables.Single(ta => !this.mapping.IsExtensionTable(ta));
            var tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(rootTable));
            aliases.Add(this.mapping.GetAlias(rootTable), tex.Alias);
            Expression source = tex;

            foreach (MappingTable table in tables.Where(t => this.mapping.IsExtensionTable(t)))
            {
                TableAlias joinedTableAlias = new TableAlias();
                string extensionAlias = this.mapping.GetAlias(table);
                aliases.Add(extensionAlias, joinedTableAlias);

                List<string> keyColumns = this.mapping.GetExtensionKeyColumnNames(table).ToList();
                List<MemberInfo> relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToList();
                string relatedAlias = this.mapping.GetExtensionRelatedAlias(table);

                TableAlias relatedTableAlias;
                aliases.TryGetValue(relatedAlias, out relatedTableAlias);

                TableExpression joinedTex = new TableExpression(joinedTableAlias, entity, this.mapping.GetTableName(table));

                Expression cond = null;
                for (int i = 0, n = keyColumns.Count; i < n; i++)
                {
                    var memberType = TypeHelper.GetMemberType(relatedMembers[i]);
                    var colType = this.GetColumnType(entity, relatedMembers[i]);
                    var relatedColumn = new ColumnExpression(memberType, colType, relatedTableAlias, this.mapping.GetColumnName(entity, relatedMembers[i]));
                    var joinedColumn = new ColumnExpression(memberType, colType, joinedTableAlias, keyColumns[i]);
                    var eq = joinedColumn.Equal(relatedColumn);
                    cond = (cond != null) ? cond.And(eq) : eq;
                }

                source = new JoinExpression(JoinType.SingletonLeftOuter, source, joinedTex, cond);
            }

            var columns = new List<ColumnDeclaration>();
            this.GetColumns(entity, aliases, columns);
            SelectExpression root = new SelectExpression(new TableAlias(), columns, source, null);
            var existingAliases = aliases.Values.ToArray();

            Expression projector = this.GetEntityExpression(root, entity);
            var selectAlias = new TableAlias();
            var pc = ColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, root.Alias);
            var proj = new ProjectionExpression(
                new SelectExpression(selectAlias, pc.Columns, root, null),
                pc.Projector
                );

            return (ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType);
        }
Ejemplo n.º 40
0
 private ColumnMapper(IEnumerable <TableAlias> oldAliases, TableAlias newAlias)
 {
     _oldAliases = new HashSet <TableAlias>(oldAliases);
     _newAlias   = newAlias;
 }
Ejemplo n.º 41
0
 private void ClearColumnsUsed(TableAlias alias)
 {
     this.allColumnsUsed[alias] = new HashSet<string>();
 }
Ejemplo n.º 42
0
 protected virtual string GetAliasName(TableAlias alias)
 {
     string name;
     if (!this.aliases.TryGetValue(alias, out name))
     {
         name = "t" + this.aliases.Count;
         this.aliases.Add(alias, name);
     }
     return name;
 }
        /// <summary>
        /// 创建 UPDATE 命令
        /// </summary>
        /// <param name="dbQuery">查询语义</param>
        /// <param name="token">解析上下文</param>
        /// <returns></returns>
        protected override RawCommand ResolveUpdateCommand <T>(IDbQueryableInfo_Update dbQuery, ResolveToken token)
        {
            var         context     = (SqlServerDbContext)token.DbContext;
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE t0 SET");
            builder.AppendNewLine();

            if (dbQuery.Entity != null)
            {
                object      entity    = dbQuery.Entity;
                ISqlBuilder seg_Where = this.CreateSqlBuilder(token);
                bool        useKey    = false;
                int         length    = 0;

                foreach (var m in typeRuntime.Members)
                {
                    var column = m.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // Fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (m.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                    // 行版本号
                    }
                    if (m.ForeignKey != null)
                    {
                        continue;
                    }
                    if (m.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember("t0", m.Member.Name);
                    builder.Append(" = ");

gotoLabel:
                    var value = m.Invoke(entity);
                    var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                    if (column == null || !column.IsIdentity)
                    {
                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        seg_Where.AppendMember("t0", m.Member.Name);
                        seg_Where.Append(" = ");
                        seg_Where.Append(seg);
                        seg_Where.Append(" AND ");
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require entity must have key column.");
                }

                builder.Length    = length;
                seg_Where.Length -= 5;

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.Append(" t0");

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(seg_Where);
            }
            else if (dbQuery.Expression != null)
            {
                TableAlias            aliases = this.PrepareTableAlias(dbQuery.Query, token);
                ExpressionVisitorBase visitor = null;
                visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression);
                visitor.Write(builder);

                builder.AppendNewLine();
                builder.Append("FROM ");
                builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                builder.AppendAs("t0");

                var cmd = new SqlServerMappingCommand(context, aliases, token)
                {
                    HasMany = dbQuery.Query.HasMany
                };

                visitor = new SqlServerJoinExpressionVisitor(context, aliases, dbQuery.Query.Joins);
                visitor.Write(cmd.JoinFragment);

                visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Query.Where);
                visitor.Write(cmd.WhereFragment);
                cmd.AddNavMembers(visitor.NavMembers);

                builder.Append(cmd.CommandText);
            }

            return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Ejemplo n.º 44
0
        /// <summary>
        /// 创建 UPDATE 命令
        /// </summary>
        /// <param name="dbQuery">查询语义</param>
        /// <param name="token">解析上下文</param>
        /// <returns></returns>
        protected override RawCommand ResolveUpdateCommand <T>(IDbQueryableInfo_Update dbQuery, ResolveToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("UPDATE ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" SET");
            builder.AppendNewLine();

            if (dbQuery.Entity != null)
            {
                object      entity    = dbQuery.Entity;
                ISqlBuilder seg_Where = this.CreateSqlBuilder(token);
                bool        useKey    = false;
                int         length    = 0;

                foreach (var m in typeRuntime.Members)
                {
                    var column = m.Column;
                    if (column != null && column.IsIdentity)
                    {
                        goto gotoLabel;                                      // Fix issue# 自增列同时又是主键
                    }
                    if (column != null && column.NoMapped)
                    {
                        continue;
                    }
                    if (m.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp)
                    {
                        continue;                                                                                                    // 行版本号
                    }
                    if (m.ForeignKey != null)
                    {
                        continue;
                    }
                    if (m.Member.MemberType == System.Reflection.MemberTypes.Method)
                    {
                        continue;
                    }

                    builder.AppendMember(m.Member.Name);
                    builder.Append(" = ");

gotoLabel:
                    var value = m.Invoke(entity);
                    var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column);

                    if (column == null || !column.IsIdentity)
                    {
                        builder.Append(seg);
                        length = builder.Length;
                        builder.Append(',');
                        builder.AppendNewLine();
                    }

                    if (column != null && column.IsKey)
                    {
                        useKey = true;
                        seg_Where.AppendMember(m.Member.Name);
                        seg_Where.Append(" = ");
                        seg_Where.Append(seg);
                        seg_Where.Append(" AND ");
                    }
                }

                if (!useKey)
                {
                    throw new XFrameworkException("Update<T>(T value) require entity must have key column.");
                }

                builder.Length    = length;
                seg_Where.Length -= 5;

                builder.AppendNewLine();
                builder.Append("WHERE ");
                builder.Append(seg_Where);
            }
            else if (dbQuery.Expression != null)
            {
                // SELECT 表达式
                LambdaExpression lambda = dbQuery.Expression as LambdaExpression;
                var        body         = lambda.Body;
                Expression expression   = null;
                if (body.NodeType == ExpressionType.MemberInit)
                {
                    var memberInit = body as MemberInitExpression;
                    var bindings   = new List <MemberBinding>(memberInit.Bindings);
                    foreach (var m in typeRuntime.KeyMembers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], m.Member);
                        var binding = Expression.Bind(m.Member, member);
                        if (!bindings.Any(x => x.Member == m.Member))
                        {
                            bindings.Add(binding);
                        }
                    }
                    expression = Expression.MemberInit(memberInit.NewExpression, bindings);
                }
                else if (body.NodeType == ExpressionType.New)
                {
                    var newExpression = body as NewExpression;
                    var bindings      = new List <MemberBinding>();
                    for (int i = 0; i < newExpression.Members.Count; i++)
                    {
                        var m       = typeRuntime.GetMember(newExpression.Members[i].Name);
                        var binding = Expression.Bind(m.Member, newExpression.Arguments[i].Type != m.DataType
                            ? Expression.Convert(newExpression.Arguments[i], m.DataType)
                            : newExpression.Arguments[i]);
                        bindings.Add(binding);
                    }

                    foreach (var m in typeRuntime.KeyMembers)
                    {
                        var member  = Expression.MakeMemberAccess(lambda.Parameters[0], m.Member);
                        var binding = Expression.Bind(m.Member, member);
                        if (!bindings.Any(x => x.Member == m.Member))
                        {
                            bindings.Add(binding);
                        }
                    }

                    var newExpression2 = Expression.New(typeRuntime.Constructor.Constructor);
                    expression = Expression.MemberInit(newExpression2, bindings);
                }

                // 解析查询以确定是否需要嵌套
                dbQuery.Query.Select = new DbExpression(DbExpressionType.Select, expression);
                var cmd = (MappingCommand)this.ResolveSelectCommand(dbQuery.Query, 1, false, null);

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.Query.Joins.Count > 0)
                {
                    if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.Count == 0)
                    {
                        throw new XFrameworkException("Update<T>(Expression<Func<T, object>> updateExpression) require entity must have key column.");
                    }

                    // SET 字段
                    var visitor = new SQLiteUpdateExpressionVisitor(this, null, dbQuery, null);
                    visitor.ParseCommand = this.ResolveSelectCommand;
                    visitor.Write(builder);

                    // WHERE部分
                    builder.AppendNewLine();
                    builder.Append("WHERE EXISTS");
                    visitor.VisitArgument(dbQuery.Query.Select.Expressions[0], true);
                }
                else
                {
                    // 直接 SQL 的 UPDATE 语法
                    TableAlias aliases = this.PrepareTableAlias(dbQuery.Query, token);
                    var        visitor = new SQLiteUpdateExpressionVisitor(this, aliases, dbQuery, null);
                    visitor.ParseCommand = this.ResolveSelectCommand;
                    visitor.Write(builder);

                    var visitor2 = new WhereExpressionVisitor(this, null, dbQuery.Query.Where);
                    visitor2.Write(builder);
                }
            }

            builder.Append(';');
            return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Ejemplo n.º 45
0
 public static Expression Map(Expression expression, TableAlias newAlias, IEnumerable<TableAlias> oldAliases)
 {
     return new ColumnMapper(oldAliases, newAlias).Visit(expression);
 }
Ejemplo n.º 46
0
 private ColumnMapper(IEnumerable<TableAlias> oldAliases, TableAlias newAlias)
 {
     this.oldAliases = new HashSet<TableAlias>(oldAliases, TableAlias.Comparer);
     this.newAlias = newAlias;
 }
Ejemplo n.º 47
0
        // 创建 SELECT 命令
        RawCommand ResolveSelectCommandImpl(IDbQueryableInfo_Select dbQuery, int indent, bool isOuter, ResolveToken token)
        {
            // 说明:
            // 1.OFFSET 前必须要有 'ORDER BY',即 'Skip' 子句前必须使用 'OrderBy' 子句
            // 2.在有聚合函数的<MAX,MIN...>情况下,如果有 'Distinct' 'GroupBy' 'Skip' 'Take' 子句,则需要使用嵌套查询
            // 3.'Any' 子句将翻译成 IF EXISTS...
            // 4.分组再分页时需要使用嵌套查询,此时子查询不需要 'OrderBy' 子句,但最外层则需要
            // 5.'Skip' 'Take' 子句视为语义结束符,在其之后的子句将使用嵌套查询
            // 6.导航属性中有 1:n 关系的,需要使用嵌套查询,否则分页查询会有问题


            // 导航属性中有1:n关系,只统计主表
            // 例:AccountList = a.Client.AccountList,
            var subQuery = dbQuery.Subquery as IDbQueryableInfo_Select;

            if (dbQuery.HasMany && subQuery != null && subQuery.Aggregate != null)
            {
                dbQuery = subQuery;
            }

            bool   useStatis  = dbQuery.Aggregate != null;
            bool   useNesting = dbQuery.HasDistinct || dbQuery.GroupBy != null || dbQuery.Skip > 0 || dbQuery.Take > 0;
            string alias0     = token != null && !string.IsNullOrEmpty(token.AliasPrefix) ? (token.AliasPrefix + "0") : "t0";
            // 没有聚合函数或者使用 'Skip' 子句,则解析OrderBy
            // 导航属性如果使用嵌套,除非有 TOP 或者 OFFSET 子句,否则不能用ORDER BY
            bool useOrderBy = (!useStatis || dbQuery.Skip > 0) && !dbQuery.HasAny && (!dbQuery.IsParsedByMany || (dbQuery.Skip > 0 || dbQuery.Take > 0));

            TableAlias aliases = this.PrepareTableAlias(dbQuery, token);
            var        result  = new MappingCommand(this, aliases, token)
            {
                HasMany = dbQuery.HasMany
            };
            ISqlBuilder jf = result.JoinFragment;
            ISqlBuilder wf = result.WhereFragment;

            jf.Indent = indent;

            #region 嵌套查询

            if (useStatis && useNesting)
            {
                // SELECT
                jf.Append("SELECT ");
                jf.AppendNewLine();

                // SELECT COUNT(1)
                var visitor_ = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy, alias0);
                visitor_.Write(jf);
                result.AddNavMembers(visitor_.NavMembers);

                // SELECT COUNT(1) FROM
                jf.AppendNewLine();
                jf.Append("FROM ( ");

                indent   += 1;
                jf.Indent = indent;
            }

            #endregion

            #region  择子句

            // SELECT 子句
            if (jf.Indent > 0)
            {
                jf.AppendNewLine();
            }
            jf.Append("SELECT ");

            if (dbQuery.HasAny)
            {
                jf.Append("CASE WHEN COUNT(1) = 1 THEN 1 ELSE 0 END FROM (");
                indent   += 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append("SELECT 1 ");
            }

            if (useStatis && !useNesting)
            {
                // 如果有聚合函数,并且不是嵌套的话,则直接使用SELECT <MAX,MIN...>,不需要解析选择的字段
                jf.AppendNewLine();
                var visitor_ = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy);
                visitor_.Write(jf);
                result.AddNavMembers(visitor_.NavMembers);
            }
            else
            {
                // DISTINCT 子句
                if (dbQuery.HasDistinct)
                {
                    jf.Append("DISTINCT ");
                }

                #region  择字段

                if (!dbQuery.HasAny)
                {
                    // SELECT 范围
                    var visitor2 = new SQLiteColumnExpressionVisitor(this, aliases, dbQuery);
                    visitor2.Write(jf);

                    result.PickColumns        = visitor2.PickColumns;
                    result.PickColumnText     = visitor2.PickColumnText;
                    result.PickNavDescriptors = visitor2.PickNavDescriptors;
                    result.AddNavMembers(visitor2.NavMembers);
                }

                #endregion
            }

            #endregion

            #region 顺序解析

            // FROM 子句
            jf.AppendNewLine();
            jf.Append("FROM ");
            if (dbQuery.Subquery != null)
            {
                // 子查询
                jf.Append('(');
                RawCommand cmd = this.ResolveSelectCommandImpl(dbQuery.Subquery, indent + 1, false, token);
                jf.Append(cmd.CommandText);
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
                jf.Append(' ');
            }
            else
            {
                var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(dbQuery.FromType);
                jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
                jf.Append(' ');
                jf.Append(alias0);
                jf.Append(' ');
            }

            // LEFT<INNER> JOIN 子句
            ExpressionVisitorBase visitor = new JoinExpressionVisitor(this, aliases, dbQuery.Joins);
            visitor.Write(jf);

            wf.Indent = jf.Indent;

            // WHERE 子句
            visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Where);
            visitor.Write(wf);
            result.AddNavMembers(visitor.NavMembers);

            // GROUP BY 子句
            visitor = new GroupByExpressionVisitor(this, aliases, dbQuery.GroupBy);
            visitor.Write(wf);
            result.AddNavMembers(visitor.NavMembers);

            // HAVING 子句
            visitor = new HavingExpressionVisitor(this, aliases, dbQuery.Having, dbQuery.GroupBy);
            visitor.Write(wf);
            result.AddNavMembers(visitor.NavMembers);

            // ORDER 子句
            if (dbQuery.OrderBys.Count > 0 && useOrderBy)
            {
                visitor = new OrderByExpressionVisitor(this, aliases, dbQuery.OrderBys, dbQuery.GroupBy);
                visitor.Write(wf);
                result.AddNavMembers(visitor.NavMembers);
            }

            #endregion

            #region 分页查询

            if (dbQuery.Take > 0)
            {
                wf.AppendNewLine().AppendFormat("LIMIT {0}", this.DbValue.GetSqlValue(dbQuery.Take, token));
            }
            else if (dbQuery.Take == 0 && dbQuery.Skip > 0)
            {
                wf.AppendNewLine().AppendFormat("LIMIT {0}", this.DbValue.GetSqlValue(-1, token));
            }
            if (dbQuery.Skip > 0)
            {
                wf.AppendFormat(" OFFSET {0}", this.DbValue.GetSqlValue(dbQuery.Skip, token));
            }

            #endregion

            #region 嵌套查询

            if (useStatis && useNesting)
            {
                result.CombineFragments();
                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
            }

            #endregion

            #region 嵌套导航

            // TODO Include 从表,没分页,OrderBy 报错
            if (dbQuery.HasMany && subQuery != null && subQuery.OrderBys.Count > 0 && subQuery.Aggregate == null && !(subQuery.Skip > 0 || subQuery.Take > 0))
            {
                result.CombineFragments();
                visitor = new OrderByExpressionVisitor(this, aliases, subQuery.OrderBys);//, null, "t0");
                visitor.Write(jf);
            }

            #endregion

            #region 并集查询

            // UNION 子句
            if (dbQuery.Unions != null && dbQuery.Unions.Count > 0)
            {
                result.CombineFragments();
                for (int index = 0; index < dbQuery.Unions.Count; index++)
                {
                    jf.AppendNewLine();
                    jf.Append("UNION ALL");
                    if (indent == 0)
                    {
                        jf.AppendNewLine();
                    }
                    RawCommand cmd = this.ResolveSelectCommand(dbQuery.Unions[index], indent, isOuter, token);
                    jf.Append(cmd.CommandText);
                }
            }

            #endregion

            #region Any 子句

            // 'Any' 子句
            if (dbQuery.HasAny)
            {
                // 产生 WHERE 子句
                result.CombineFragments();

                // 如果没有分页,则显式指定只查一笔记录
                if (dbQuery.Take == 0 && dbQuery.Skip == 0)
                {
                    jf.AppendNewLine();
                    jf.Append("LIMIT 1");
                }

                indent   -= 1;
                jf.Indent = indent;
                jf.AppendNewLine();
                jf.Append(") ");
                jf.Append(alias0);
            }

            #endregion

            return(result);
        }
Ejemplo n.º 48
0
 internal static Expression Map(Expression expression, TableAlias newAlias, params TableAlias[] oldAliases)
 {
     return(new ColumnMapper((IEnumerable <TableAlias>)oldAliases, newAlias).Visit(expression));
 }
Ejemplo n.º 49
0
 public void Visit(TableAlias alias)
 {
 }
Ejemplo n.º 50
0
        /// <summary>
        /// 创建 DELETE 命令
        /// </summary>
        /// <param name="dbQuery">查询语义</param>
        /// <param name="token">解析上下文</param>
        /// <returns></returns>
        protected override RawCommand ResolveDeleteCommand <T>(IDbQueryableInfo_Delete dbQuery, ResolveToken token)
        {
            ISqlBuilder builder     = this.CreateSqlBuilder(token);
            var         typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>();

            builder.Append("DELETE FROM ");
            builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary);
            builder.Append(" ");

            if (dbQuery.Entity != null)
            {
                if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.Count == 0)
                {
                    throw new XFrameworkException("Delete<T>(T value) require entity must have key column.");
                }

                object entity = dbQuery.Entity;

                builder.AppendNewLine();
                builder.Append("WHERE ");

                foreach (var m in typeRuntime.KeyMembers)
                {
                    var column = m.Column;
                    var value  = m.Invoke(entity);
                    var seg    = this.DbValue.GetSqlValue(value, token, column);

                    builder.AppendMember(m.Member.Name);
                    builder.Append(" = ");
                    builder.Append(seg);
                    builder.Append(" AND ");
                }
                builder.Length -= 5;
            }
            else if (dbQuery.Query != null)
            {
                // 解析查询用来确定是否需要嵌套
                var cmd = this.ResolveSelectCommand(dbQuery.Query, 1, false, null) as MappingCommand;
                if (token != null && token.Extendsions == null)
                {
                    token.Extendsions = new Dictionary <string, object>();
                    if (!token.Extendsions.ContainsKey("SQLiteDelete"))
                    {
                        token.Extendsions.Add("SQLiteDelete", null);
                    }
                }

                if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.Query.Joins.Count > 0)
                {
                    // 最外层仅选择 RowID 列
                    var outQuery = dbQuery.Query;
                    outQuery.Select = new DbExpression(DbExpressionType.Select, Expression.Constant("t0.RowId", typeof(string)));
                    var iterator = outQuery;
                    while (iterator.Subquery != null)
                    {
                        var subQuery = new SQLiteDbQueryableInfo_Select(iterator.Subquery);
                        iterator.Subquery = subQuery;
                        iterator          = subQuery;
                    }

                    // 解析成 RowId IN 结构
                    cmd = (MappingCommand)this.ResolveSelectCommand(dbQuery.Query, 1, false, token);
                    builder.Append("WHERE ");
                    builder.AppendMember("RowID");
                    builder.Append(" IN(");
                    builder.AppendNewLine(cmd.CommandText);
                    builder.Append(')');
                }
                else
                {
                    TableAlias            aliases = this.PrepareTableAlias(dbQuery.Query, token);
                    ExpressionVisitorBase visitor = null;

                    visitor = new JoinExpressionVisitor(this, aliases, dbQuery.Query.Joins);
                    visitor.Write(builder);

                    visitor = new WhereExpressionVisitor(this, null, dbQuery.Query.Where);
                    visitor.Write(builder);
                }
            }

            builder.Append(';');
            return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text));
        }
Ejemplo n.º 51
0
 public static Expression Map(Expression expression, TableAlias newAlias, params TableAlias[] oldAliases)
 {
     return Map(expression, newAlias, (IEnumerable<TableAlias>)oldAliases);
 }
Ejemplo n.º 52
0
 protected virtual Expression GetUpdateResult(MappingEntity entity, Expression instance, LambdaExpression selector)
 {
     var tq = this.GetQueryExpression(entity);
     Expression where = this.GetIdentityCheck(tq.Select, entity, instance);
     Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], tq.Projector);
     TableAlias newAlias = new TableAlias();
     var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, selection, null, newAlias, tq.Select.Alias);
     return new ProjectionExpression(
         new SelectExpression(newAlias, pc.Columns, tq.Select, where),
         pc.Projector,
         Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type))
         );
 }
Ejemplo n.º 53
0
 protected void AddAlias(TableAlias alias)
 {
     string name;
     if (!this.aliases.TryGetValue(alias, out name))
     {
         name = "t" + this.aliases.Count;
         this.aliases.Add(alias, name);
     }
 }
Ejemplo n.º 54
0
 public static Expression Map(Expression expression, TableAlias newAlias, IEnumerable <TableAlias> oldAliases)
 {
     return(new ColumnMapper(oldAliases, newAlias).Visit(expression));
 }
Ejemplo n.º 55
0
 protected virtual DeclarationCommand GetGeneratedIdCommand(MappingEntity entity, List<MemberInfo> members, Dictionary<MemberInfo, Expression> map)
 {
     var columns = new List<ColumnDeclaration>();
     var decls = new List<VariableDeclaration>();
     var alias = new TableAlias();
     foreach (var member in members)
     {
         Expression genId = this.translator.Linguist.Language.GetGeneratedIdExpression(member);
         var name = member.Name;
         var colType = this.GetColumnType(entity, member);
         columns.Add(new ColumnDeclaration(member.Name, genId, colType));
         decls.Add(new VariableDeclaration(member.Name, colType, new ColumnExpression(genId.Type, colType, alias, member.Name)));
         if (map != null)
         {
             var vex = new VariableExpression(member.Name, TypeHelper.GetMemberType(member), colType);
             map.Add(member, vex);
         }
     }
     var select = new SelectExpression(alias, columns, null, null);
     return new DeclarationCommand(decls, select);
 }
Ejemplo n.º 56
0
 public static Expression Map(Expression expression, TableAlias newAlias, params TableAlias[] oldAliases)
 {
     return(Map(expression, newAlias, (IEnumerable <TableAlias>)oldAliases));
 }
Ejemplo n.º 57
0
        public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector)
        {
            var tableAlias = new TableAlias();
            var table = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity));
            var assignments = this.GetColumnAssignments(table, instance, entity, (e, m) => !this.mapping.IsGenerated(e, m));

            if (selector != null)
            {
                return new BlockCommand(
                    new InsertCommand(table, assignments),
                    this.GetInsertResult(entity, instance, selector, null)
                    );
            }

            return new InsertCommand(table, assignments);
        }
Ejemplo n.º 58
0
        public override Expression GetUpdateExpression(MappingEntity entity, Expression instance, LambdaExpression updateCheck, LambdaExpression selector, Expression @else)
        {
            var tableAlias = new TableAlias();
            var table = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity));

            var where = this.GetIdentityCheck(table, entity, instance);
            if (updateCheck != null)
            {
                Expression typeProjector = this.GetEntityExpression(table, entity);
                Expression pred = DbExpressionReplacer.Replace(updateCheck.Body, updateCheck.Parameters[0], typeProjector);
                where = where.And(pred);
            }

            var assignments = this.GetColumnAssignments(table, instance, entity, (e, m) => this.mapping.IsUpdatable(e, m));

            Expression update = new UpdateCommand(table, where, assignments);

            if (selector != null)
            {
                return new BlockCommand(
                    update,
                    new IFCommand(
                        this.translator.Linguist.Language.GetRowsAffectedExpression(update).GreaterThan(Expression.Constant(0)),
                        this.GetUpdateResult(entity, instance, selector),
                        @else
                        )
                    );
            }
            else if (@else != null)
            {
                return new BlockCommand(
                    update,
                    new IFCommand(
                        this.translator.Linguist.Language.GetRowsAffectedExpression(update).LessThanOrEqual(Expression.Constant(0)),
                        @else,
                        null
                        )
                    );
            }
            else
            {
                return update;
            }
        }
 private void ClearColumnsUsed(TableAlias alias)
 {
     this.allColumnsUsed[alias] = new HashSet <string>();
 }
Ejemplo n.º 60
0
        protected virtual Expression GetInsertResult(MappingEntity entity, Expression instance, LambdaExpression selector, Dictionary<MemberInfo, Expression> map)
        {
            var tableAlias = new TableAlias();
            var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity));
            var aggregator = Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type));

            Expression where;
            DeclarationCommand genIdCommand = null;
            var generatedIds = this.mapping.GetMappedMembers(entity).Where(m => this.mapping.IsPrimaryKey(entity, m) && this.mapping.IsGenerated(entity, m)).ToList();
            if (generatedIds.Count > 0)
            {
                if (map == null || !generatedIds.Any(m => map.ContainsKey(m)))
                {
                    var localMap = new Dictionary<MemberInfo, Expression>();
                    genIdCommand = this.GetGeneratedIdCommand(entity, generatedIds.ToList(), localMap);
                    map = localMap;
                }

                // is this just a retrieval of one generated id member?
                var mex = selector.Body as MemberExpression;
                if (mex != null && this.mapping.IsPrimaryKey(entity, mex.Member) && this.mapping.IsGenerated(entity, mex.Member))
                {
                    if (genIdCommand != null)
                    {
                        // just use the select from the genIdCommand
                        return new ProjectionExpression(
                            genIdCommand.Source,
                            new ColumnExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name),
                            aggregator
                            );
                    }
                    else
                    {
                        TableAlias alias = new TableAlias();
                        var colType = this.GetColumnType(entity, mex.Member);
                        return new ProjectionExpression(
                            new SelectExpression(alias, new[] { new ColumnDeclaration("", map[mex.Member], colType) }, null, null),
                            new ColumnExpression(TypeHelper.GetMemberType(mex.Member), colType, alias, ""),
                            aggregator
                            );
                    }
                }

                where = generatedIds.Select((m, i) =>
                    this.GetMemberExpression(tex, entity, m).Equal(map[m])
                    ).Aggregate((x, y) => x.And(y));
            }
            else
            {
                where = this.GetIdentityCheck(tex, entity, instance);
            }

            Expression typeProjector = this.GetEntityExpression(tex, entity);
            Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector);
            TableAlias newAlias = new TableAlias();
            var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, selection, null, newAlias, tableAlias);
            var pe = new ProjectionExpression(
                new SelectExpression(newAlias, pc.Columns, tex, where),
                pc.Projector,
                aggregator
                );

            if (genIdCommand != null)
            {
                return new BlockCommand(genIdCommand, pe);
            }
            return pe;
        }