protected override Expression VisitSelect(SelectExpression select) { IdentifiableAlias newAlias = new IdentifiableAlias(); this.map[select.Alias] = newAlias; select = (SelectExpression)base.VisitSelect(select); return new SelectExpression(newAlias, select.Fields, select.From, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take, select.IsReverse); }
public OAssociationFilterExpression(IdentifiableAlias alias, AssociationOrigin origin, Type type, Expression source, Expression predicate) : base((DbExpressionType)ODbExpressionType.AssociationFilter, type, alias) { Source = source; Predicate = predicate; Origin = origin; }
protected void AddAlias(IdentifiableAlias alias) { if (!this.aliasMap.ContainsKey(alias)) { this.aliasMap.Add(alias, this.aliasMap.Count); } }
public override Expression GetUpdateExpression(IMappedEntity entity, Expression instance, LambdaExpression updateCheck, LambdaExpression selector) { var IdentifiableAlias = new IdentifiableAlias(); var table = new IdentifiableExpression(IdentifiableAlias, entity, ((OTypeMapping)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.GetFieldAssignments(table, instance, entity, (e, m) => ((OTypeMapping)this.Mapping).IsUpdatable(e, m)); Expression update = new UpdateCommandExpression(table, where, assignments); if (selector != null) { return CreateUpdateCommand(entity, instance, selector, where, assignments); } else { return update; } }
public static SelectExpression AddRedundantSelect(this SelectExpression sel, QueryLanguage language, IdentifiableAlias newAlias) { var newFields = from d in sel.Fields let qt = (d.Expression is FieldExpression) ? ((FieldExpression)d.Expression).QueryType : language.TypeSystem.GetStorageType(d.Expression.Type) select new FieldDeclaration(d.Name, new FieldExpression(d.Expression.Type, qt, newAlias, d.Name), qt); var newFrom = new SelectExpression(newAlias, sel.Fields, sel.From, sel.Where, sel.OrderBy, sel.GroupBy, sel.IsDistinct, sel.Skip, sel.Take, sel.IsReverse); return new SelectExpression(sel.Alias, newFields, newFrom, null, null, null, false, null, null, false); }
public override Expression GetInsertExpression(IMappedEntity entity, Expression instance, LambdaExpression selector) { var IdentifiableAlias = new IdentifiableAlias(); var table = new IdentifiableExpression(IdentifiableAlias, entity, ((OTypeMapping)this.Mapping).GetTableName(entity)); var assignments = this.GetFieldAssignments(table, instance, entity, (e, m) => !((OTypeMapping)this.Mapping).IsGenerated(e, m)); if (selector != null) { return CreateInsertCommand(entity, instance, selector, assignments); } return new InsertCommandExpression(table, assignments); }
private FieldProjector(QueryLanguage language, Expression expression, IEnumerable<FieldDeclaration> existingFields, IdentifiableAlias newAlias, IEnumerable<IdentifiableAlias> existingAliases) { this.language = language; this.newAlias = newAlias; this.existingAliases = new HashSet<IdentifiableAlias>(existingAliases); this.map = new Dictionary<FieldExpression, FieldExpression>(); if (existingFields != null) { this.fields = new List<FieldDeclaration>(existingFields); this.fieldNames = new HashSet<string>(existingFields.Select(c => c.Name)); } else { this.fields = new List<FieldDeclaration>(); this.fieldNames = new HashSet<string>(); } this.candidates = Nominator.Nominate(language, expression); }
protected override Expression VisitProjection(ProjectionExpression proj) { if (isTopLevel) { isTopLevel = false; this.currentSelect = proj.Select; Expression projector = this.Visit(proj.Projector); if (projector != proj.Projector || this.currentSelect != proj.Select) { return new ProjectionExpression(this.currentSelect, projector, proj.Aggregator); } return proj; } if (proj.IsSingleton && this.CanJoinOnServer(this.currentSelect)) { IdentifiableAlias newAlias = new IdentifiableAlias(); this.currentSelect = this.currentSelect.AddRedundantSelect(this.language, newAlias); // remap any references to the outer select to the new alias; SelectExpression source = (SelectExpression)FieldMapper.Map(proj.Select, newAlias, this.currentSelect.Alias); // add outer-join test ProjectionExpression pex = this.language.AddOuterJoinTest(new ProjectionExpression(source, proj.Projector)); var pc = FieldProjector.ProjectFields(this.language, pex.Projector, this.currentSelect.Fields, this.currentSelect.Alias, newAlias, proj.Select.Alias); JoinExpression join = new JoinExpression(JoinType.OuterApply, this.currentSelect.From, pex.Select, null); this.currentSelect = new SelectExpression(this.currentSelect.Alias, pc.Fields, join, null); return this.Visit(pc.Projector); } var saveTop = this.isTopLevel; var saveSelect = this.currentSelect; this.isTopLevel = true; this.currentSelect = null; Expression result = base.VisitProjection(proj); this.isTopLevel = saveTop; this.currentSelect = saveSelect; return result; }
public override ProjectionExpression GetQueryExpression(IMappedEntity entity) { var IdentifiableAlias = new IdentifiableAlias(); var selectAlias = new IdentifiableAlias(); var table = new IdentifiableExpression(IdentifiableAlias, entity, this.mapping.GetTableName(entity)); Expression projector = this.GetEntityExpression(table, entity); var pc = FieldProjector.ProjectFields(this.translator.Linguist.Language, projector, null, selectAlias, IdentifiableAlias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Fields, table, null), pc.Projector ); return (ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.EntityType); }
public override Expression GetMemberExpression(Expression root, IMappedEntity entity, MemberInfo member) { if (this.mapping.IsAssociationRelationship(entity, member)) { var relatedEntity = this.mapping.GetRelatedEntity(entity, member); ProjectionExpression projection = this.GetQueryExpression(relatedEntity); // make where clause for joining back to 'root' var declaredTypeMembers = this.mapping.GetAssociationKeyMembers(entity, member).ToList(); var associatedMembers = this.mapping.GetAssociationRelatedKeyMembers(entity, member).ToList(); Expression where = null; for (int i = 0, n = associatedMembers.Count; i < n; i++) { Expression equal = this.GetMemberExpression(projection.Projector, relatedEntity, associatedMembers[i]).Equal( this.GetMemberExpression(root, entity, declaredTypeMembers[i]) ); where = (where != null) ? where.And(equal) : equal; } IdentifiableAlias newAlias = new IdentifiableAlias(); var pc = FieldProjector.ProjectFields(this.translator.Linguist.Language, projection.Projector, null, newAlias, projection.Select.Alias); LambdaExpression aggregator = Aggregator.GetAggregator(TypeHelper.GetMemberType(member), typeof(IEnumerable<>).MakeGenericType(pc.Projector.Type)); var result = new ProjectionExpression( new SelectExpression(newAlias, pc.Fields, projection.Select, where), pc.Projector, aggregator ); return this.translator.Police.ApplyPolicy(result, member); } else { AliasedExpression aliasedRoot = root as AliasedExpression; if (aliasedRoot != null && this.mapping.IsField(entity, member)) { return new FieldExpression(TypeHelper.GetMemberType(member), this.GetFieldType(entity, member), aliasedRoot.Alias, this.mapping.GetFieldName(entity, member)); } return QueryBinder.BindMember(root, member); } }
public override Expression GetInsertExpression(IMappedEntity entity, Expression instance, LambdaExpression selector) { var IdentifiableAlias = new IdentifiableAlias(); var table = new IdentifiableExpression(IdentifiableAlias, entity, this.mapping.GetTableName(entity)); var assignments = this.GetFieldAssignments(table, instance, entity, (e, m) => !this.mapping.IsGenerated(e, m)); if (selector != null) { return new BlockCommandExpression( new InsertCommandExpression(table, assignments), this.GetInsertResult(entity, instance, selector, null) ); } return new InsertCommandExpression(table, assignments); }
protected virtual bool CompareAlias(IdentifiableAlias a, IdentifiableAlias b) { if (this.aliasScope != null) { IdentifiableAlias mapped; if (this.aliasScope.TryGetValue(a, out mapped)) return mapped == b; } return a == b; }
protected AliasedExpression(DbExpressionType nodeType, Type type, IdentifiableAlias alias) : base(nodeType, type) { this.alias = alias; }
private OUpdateCommandExpression CreateUpdateCommand(IMappedEntity entity, Expression instance, LambdaExpression selector, Expression where, IEnumerable<FieldAssignment> assignments) { var identifiableAlias = new IdentifiableAlias(); var tex = new IdentifiableExpression(identifiableAlias, entity, ((OTypeMapping)this.Mapping).GetTableName(entity)); Expression typeProjector = this.GetEntityExpression(tex, entity); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); IdentifiableAlias newAlias = new IdentifiableAlias(); var pc = FieldProjector.ProjectFields(this.Translator.Linguist.Language, selection, null, newAlias, identifiableAlias); return new OUpdateCommandExpression(tex, where, assignments, pc.Projector); }
protected virtual Expression GetInsertResult(IMappedEntity entity, Expression instance, LambdaExpression selector, Dictionary<MemberInfo, Expression> map) { var IdentifiableAlias = new IdentifiableAlias(); var tex = new IdentifiableExpression(IdentifiableAlias, 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 FieldExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Fields[0].Name), aggregator ); } else { IdentifiableAlias alias = new IdentifiableAlias(); var colType = this.GetFieldType(entity, mex.Member); return new ProjectionExpression( new SelectExpression(alias, new[] { new FieldDeclaration("", map[mex.Member], colType) }, null, null), new FieldExpression(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); IdentifiableAlias newAlias = new IdentifiableAlias(); var pc = FieldProjector.ProjectFields(this.translator.Linguist.Language, selection, null, newAlias, IdentifiableAlias); var pe = new ProjectionExpression( new SelectExpression(newAlias, pc.Fields, tex, where), pc.Projector, aggregator ); if (genIdCommand != null) { return new BlockCommandExpression(genIdCommand, pe); } return pe; }
protected override Expression VisitIdentifiable(IdentifiableExpression table) { IdentifiableAlias newAlias = new IdentifiableAlias(); this.map[table.Alias] = newAlias; return new IdentifiableExpression(newAlias, table.Entity, table.Name); }
protected override Expression VisitProjection(ProjectionExpression proj) { SelectExpression save = this.currentSelect; this.currentSelect = proj.Select; 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)FieldMapper.Map(proj.Select, newOuterSelect.Alias, save.Alias); // add outer-join test ProjectionExpression newInnerProjection = this.language.AddOuterJoinTest(new ProjectionExpression(newInnerSelect, proj.Projector)); newInnerSelect = newInnerProjection.Select; Expression newProjector = newInnerProjection.Projector; IdentifiableAlias newAlias = new IdentifiableAlias(); var pc = FieldProjector.ProjectFields(this.language, newProjector, null, newAlias, newOuterSelect.Alias, newInnerSelect.Alias); JoinExpression join = new JoinExpression(JoinType.OuterApply, newOuterSelect, newInnerSelect, null); SelectExpression joinedSelect = new SelectExpression(newAlias, pc.Fields, join, null, null, null, proj.IsSingleton, null, null, false); // apply client-join treatment recursively this.currentSelect = joinedSelect; newProjector = this.Visit(pc.Projector); // compute keys (this only works if join condition was a single field 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 => FieldMapper.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 => FieldMapper.Map(k, joinedSelect.Alias, ((FieldExpression)k).Alias)); ProjectionExpression newProjection = new ProjectionExpression(joinedSelect, newProjector, proj.Aggregator); return new ClientJoinExpression(newProjection, outerKey, innerKey); } } else { bool saveJoin = this.canJoinOnClient; this.canJoinOnClient = false; var result = base.VisitProjection(proj); this.canJoinOnClient = saveJoin; return result; } } else { this.isTopLevel = false; } return base.VisitProjection(proj); } finally { this.currentSelect = save; } }
private bool GetEquiJoinKeyExpressions(Expression predicate, IdentifiableAlias outerAlias, List<Expression> outerExpressions, List<Expression> innerExpressions) { if (predicate.NodeType == ExpressionType.Equal) { var b = (BinaryExpression)predicate; FieldExpression leftCol = this.GetFieldExpression(b.Left); FieldExpression rightCol = this.GetFieldExpression(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; }
protected virtual string GetAliasName(IdentifiableAlias alias) { string name; if (!this.aliases.TryGetValue(alias, out name)) { name = "A" + alias.GetHashCode() + "?"; this.aliases.Add(alias, name); } return name; }
protected void AddAlias(IdentifiableAlias alias) { string name; if (!this.aliases.TryGetValue(alias, out name)) { name = "t" + this.aliases.Count; this.aliases.Add(alias, name); } }
public override Expression GetUpdateExpression(IMappedEntity entity, Expression instance, LambdaExpression updateCheck, LambdaExpression selector) { var IdentifiableAlias = new IdentifiableAlias(); var table = new IdentifiableExpression(IdentifiableAlias, 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.GetFieldAssignments(table, instance, entity, (e, m) => this.mapping.IsUpdatable(e, m)); Expression update = new UpdateCommandExpression(table, where, assignments); if (selector != null) { return new BlockCommandExpression( update, new IfCommandExpression( this.translator.Linguist.Language.GetRowsAffectedExpression(update).GreaterThan(Expression.Constant(0)), this.GetUpdateResult(entity, instance, selector), null ) ); } else { return update; } }
public static Expression Map(Expression expression, IdentifiableAlias newAlias, IEnumerable<IdentifiableAlias> oldAliases) { return new FieldMapper(oldAliases, newAlias).Visit(expression); }
protected virtual DeclarationCommand GetGeneratedIdCommand(IMappedEntity entity, List<MemberInfo> members, Dictionary<MemberInfo, Expression> map) { var Fields = new List<FieldDeclaration>(); var decls = new List<VariableDeclaration>(); var alias = new IdentifiableAlias(); foreach (var member in members) { Expression genId = this.translator.Linguist.Language.GetGeneratedIdExpression(member); var name = member.Name; var colType = this.GetFieldType(entity, member); Fields.Add(new FieldDeclaration(member.Name, genId, colType)); decls.Add(new VariableDeclaration(member.Name, colType, new FieldExpression(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, Fields, null, null); return new DeclarationCommand(decls, select); }
protected virtual ProjectedFields ProjectFields(Expression expression, IdentifiableAlias newAlias, params IdentifiableAlias[] existingAliases) { return FieldProjector.ProjectFields(this.language, expression, null, newAlias, existingAliases); }
protected virtual Expression GetUpdateResult(IMappedEntity 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); IdentifiableAlias newAlias = new IdentifiableAlias(); var pc = FieldProjector.ProjectFields(this.translator.Linguist.Language, selection, null, newAlias, tq.Select.Alias); return new ProjectionExpression( new SelectExpression(newAlias, pc.Fields, tq.Select, where), pc.Projector, Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type)) ); }
public static ProjectedFields ProjectFields(QueryLanguage language, Expression expression, IEnumerable<FieldDeclaration> existingFields, IdentifiableAlias newAlias, IEnumerable<IdentifiableAlias> existingAliases) { FieldProjector projector = new FieldProjector(language, expression, existingFields, newAlias, existingAliases); Expression expr = projector.Visit(expression); return new ProjectedFields(expr, projector.fields.AsReadOnly()); }
private FieldMapper(IEnumerable<IdentifiableAlias> oldAliases, IdentifiableAlias newAlias) { this.oldAliases = new HashSet<IdentifiableAlias>(oldAliases); this.newAlias = newAlias; }
public static ProjectedFields ProjectFields(QueryLanguage language, Expression expression, IEnumerable<FieldDeclaration> existingFields, IdentifiableAlias newAlias, params IdentifiableAlias[] existingAliases) { return ProjectFields(language, expression, existingFields, newAlias, (IEnumerable<IdentifiableAlias>)existingAliases); }
public GroupByInfo(IdentifiableAlias alias, Expression element) { this.Alias = alias; this.Element = element; }
public static Expression Map(Expression expression, IdentifiableAlias newAlias, params IdentifiableAlias[] oldAliases) { return Map(expression, newAlias, (IEnumerable<IdentifiableAlias>)oldAliases); }