protected virtual Expression VisitProjection(DbProjectionExpression proj) { var select = this.Visit(proj.Select) as DbSelectExpression; var projector = this.Visit(proj.Projector); return(this.UpdateProjection(proj, select, projector, proj.Aggregator)); }
private Expression ExecuteProjection(DbProjectionExpression projection, bool okayToDefer, QueryCommand command, Expression[] values, bool isTopLevel) { okayToDefer &= this.receivingMember != null && this.policy.IsDeferLoaded(this.receivingMember); var saveScope = this.scope; var reader = Expression.Parameter(typeof(FieldReader), "r" + nReaders++); this.scope = new Scope(this.scope, reader, projection.Select.Alias, projection.Select.Columns); var projector = Expression.Lambda(this.Visit(projection.Projector), reader); this.scope = saveScope; var entity = EntityFinder.Find(projection.Projector); var methExecute = okayToDefer ? nameof(QueryExecutor.ExecuteDeferred) : nameof(QueryExecutor.Execute); var result = Expression.Call(this.executor, methExecute, new Type[] { projector.Body.Type }, Expression.Constant(command), projector, Expression.Constant(entity, typeof(MappingEntity)), Expression.NewArrayInit(typeof(object), values)) as Expression; if (projection.Aggregator != null) { result = DbExpressionReplacer.Replace(projection.Aggregator.Body, projection.Aggregator.Parameters[0], result); } return(result); }
protected override Expression VisitDeclaration(DbDeclarationCommand decl) { if (decl.Source != null) { var projection = new DbProjectionExpression ( decl.Source, Expression.NewArrayInit(typeof(object), decl.Variables.Select(v => v.Expression.Type.GetTypeInfo().IsValueType ? Expression.Convert(v.Expression, typeof(object)) : v.Expression).ToArray()), DbAggregator.GetAggregator(typeof(object[]), typeof(IEnumerable <object[]>)) ); var vars = Expression.Parameter(typeof(object[]), "vars"); this.variables.Add(vars); this.initializers.Add(Expression.Constant(null, typeof(object[]))); for (int i = 0, n = decl.Variables.Count; i < n; i++) { var v = decl.Variables[i]; var nv = new DbNamedValueExpression ( v.Name, v.QueryType, Expression.Convert(Expression.ArrayIndex(vars, Expression.Constant(i)), v.Expression.Type) ); this.variableMap.Add(v.Name, nv); } return(MakeAssign(vars, this.Visit(projection))); } throw new InvalidOperationException("Declaration query not allowed for this langauge"); }
protected virtual bool CompareProjection(DbProjectionExpression a, DbProjectionExpression b) { if (!this.Compare(a.Select, b.Select)) { return(false); } var save = this.aliasScope; try { this.aliasScope = new ScopedDictionary <TableAlias, TableAlias>(this.aliasScope); this.aliasScope.Add(a.Select.Alias, b.Select.Alias); return ( this.Compare(a.Projector, b.Projector) && this.Compare(a.Aggregator, b.Aggregator) && a.IsSingleton == b.IsSingleton ); } finally { this.aliasScope = save; } }
protected override Expression VisitProjection(DbProjectionExpression projection) { var projector = this.Visit(projection.Projector); var select = this.Visit(projection.Select) as DbSelectExpression; return(this.UpdateProjection(projection, select, projector, projection.Aggregator)); }
protected DbProjectionExpression UpdateProjection(DbProjectionExpression proj, DbSelectExpression select, Expression projector, LambdaExpression aggregator) { if (select != proj.Select || projector != proj.Projector || aggregator != proj.Aggregator) { return(new DbProjectionExpression(select, projector, aggregator)); } return(proj); }
public override Expression GetMemberExpression(Expression root, MappingEntity entity, MemberInfo member) { if (this.mapping.IsAssociationRelationship(entity, member)) { var relatedEntity = this.mapping.GetRelatedEntity(entity, member); var projection = this.GetQueryExpression(relatedEntity); var declaredTypeMembers = this.mapping.GetAssociationKeyMembers(entity, member).ToList(); var associatedMembers = this.mapping.GetAssociationRelatedKeyMembers(entity, member).ToList(); var where = null as Expression; for (int i = 0, n = associatedMembers.Count; i < n; i++) { var equal = this.GetMemberExpression ( projection.Projector, relatedEntity, associatedMembers[i]).Equal(this.GetMemberExpression(root, entity, declaredTypeMembers[i]) ); where = (where != null) ? where.And(equal) : equal; } var newAlias = new TableAlias(); var pc = DbColumnProjector.ProjectColumns ( this.translator.Linguist.Language, projection.Projector, null, newAlias, projection.Select.Alias ); var aggregator = DbAggregator.GetAggregator(TypeHelper.GetMemberType(member), typeof(IEnumerable <>).MakeGenericType(pc.Projector.Type)); var result = new DbProjectionExpression ( new DbSelectExpression(newAlias, pc.Columns, projection.Select, where), pc.Projector, aggregator ); return(this.translator.Police.ApplyPolicy(result, member)); } if (root is DbAliasedExpression aliasedRoot && this.mapping.IsColumn(entity, member)) { return(new DbColumnExpression ( TypeHelper.GetMemberType(member), this.GetColumnType(entity, member), aliasedRoot.Alias, this.mapping.GetColumnName(entity, member) )); } return(DbQueryBinder.BindMember(root, member)); }
protected override Expression VisitProjection(DbProjectionExpression projection) { if (this.isTop) { this.isTop = false; return(this.ExecuteProjection(projection, okayToDefer: this.scope != null, isTopLevel: true)); } return(this.BuildInner(projection)); }
internal override DbProjectionExpression GetQueryExpression(MappingEntity entity) { var tableAlias = new TableAlias(); var selectAlias = new TableAlias(); var table = new DbTableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var projector = this.GetEntityExpression(table, entity) as Expression; var pc = DbColumnProjector.ProjectColumns(this.translator.Linguist.Language, projector, null, selectAlias, tableAlias); var proj = new DbProjectionExpression(new DbSelectExpression(selectAlias, pc.Columns, table, null), pc.Projector); return(this.Translator.Police.ApplyPolicy(proj, entity.ElementType.GetTypeInfo()) as DbProjectionExpression); }
protected override Expression VisitProjection(DbProjectionExpression proj) { if (isTopLevel) { isTopLevel = false; this.currentSelect = proj.Select; var projector = this.Visit(proj.Projector); if (projector != proj.Projector || this.currentSelect != proj.Select) { return(new DbProjectionExpression(this.currentSelect, projector, proj.Aggregator)); } return(proj); } if (proj.IsSingleton && this.CanJoinOnServer(this.currentSelect)) { var newAlias = new TableAlias(); this.currentSelect = this.currentSelect.AddRedundantSelect(this.language, newAlias); var source = DbColumnMapper.Map(proj.Select, newAlias, this.currentSelect.Alias) as DbSelectExpression; var pex = this.language.AddOuterJoinTest(new DbProjectionExpression(source, proj.Projector)); var pc = DbColumnProjector.ProjectColumns(this.language, pex.Projector, this.currentSelect.Columns, this.currentSelect.Alias, newAlias, proj.Select.Alias); var join = new DbJoinExpression(JoinType.OuterApply, this.currentSelect.From, pex.Select, null); this.currentSelect = new DbSelectExpression(this.currentSelect.Alias, pc.Columns, join, null); return(this.Visit(pc.Projector)); } var saveTop = this.isTopLevel; var saveSelect = this.currentSelect; this.isTopLevel = true; this.currentSelect = null; var result = base.VisitProjection(proj); this.isTopLevel = saveTop; this.currentSelect = saveSelect; return(result); }
public static DbProjectionExpression AddOuterJoinTest(this DbProjectionExpression proj, QueryLanguage language, Expression expression) { var colName = proj.Select.Columns.GetAvailableColumnName("Test"); var colType = language.TypeSystem.GetColumnType(expression.Type); var newSource = proj.Select.AddColumn(new DbColumnDeclaration(colName, expression, colType)); var newProjector = new DbOuterJoinedExpression ( new DbColumnExpression(expression.Type, colType, newSource.Alias, colName), proj.Projector ); return(new DbProjectionExpression(newSource, newProjector, proj.Aggregator)); }
private Expression ExecuteProjection(DbProjectionExpression projection, bool okayToDefer, bool isTopLevel) { projection = this.Parameterize(projection) as DbProjectionExpression; if (this.scope != null) { projection = OuterParameterizer.Parameterize(this.scope.Alias, projection) as DbProjectionExpression; } var commandText = this.linguist.Format(projection.Select); var namedValues = DbNamedValueGatherer.Gather(projection.Select); var command = new QueryCommand(commandText, namedValues.Select(v => new QueryParameter(v.Name, v.Type, v.QueryType))); var values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray() as Expression[]; return(this.ExecuteProjection(projection, okayToDefer, command, values, isTopLevel)); }
protected override Expression VisitProjection(DbProjectionExpression proj) { proj = base.VisitProjection(proj) as DbProjectionExpression; if (proj.Select.From is DbSelectExpression) { var redundant = RedundantSubqueryGatherer.Gather(proj.Select); if (redundant != null) { proj = DbSubqueryRemover.Remove(proj, redundant); } } return(proj); }
protected override Expression VisitProjection(DbProjectionExpression proj) { if ((proj.Projector is DbColumnExpression) || this.ForDebug) { this.Write("("); this.WriteLine(Indentation.Inner); this.Visit(proj.Select); this.Write(")"); this.Indent(Indentation.Outer); } else { throw new NotSupportedException("Non-scalar projections cannot be translated to SQL."); } return(proj); }
protected override Expression VisitExists(DbExistsExpression exists) { var colType = this.linguist.Language.TypeSystem.GetColumnType(typeof(int)); var newSelect = exists.Select.SetColumns(new[] { new DbColumnDeclaration("value", new DbAggregateExpression(typeof(int), "Count", null, false), colType) }); var projection = new DbProjectionExpression ( newSelect, new DbColumnExpression(typeof(int), colType, newSelect.Alias, "value"), DbAggregator.GetAggregator(typeof(int), typeof(IEnumerable <int>)) ); return(this.Visit(projection.GreaterThan(Expression.Constant(0)))); }
protected virtual Expression VisitProjection(DbProjectionExpression projection) { this.AddAlias(projection.Select.Alias); this.Write("Project("); this.WriteLine(Indentation.Inner); this.Write("@\""); this.Visit(projection.Select); this.Write("\","); this.WriteLine(Indentation.Same); this.Visit(projection.Projector); this.Write(","); this.WriteLine(Indentation.Same); this.Visit(projection.Aggregator); this.WriteLine(Indentation.Outer); this.Write(")"); return(projection); }
internal virtual DbProjectionExpression AddOuterJoinTest(DbProjectionExpression proj) { var test = this.GetOuterJoinTest(proj.Select); var select = proj.Select; var testCol = null as DbColumnExpression; foreach (var col in select.Columns) { if (test.Equals(col.Expression)) { testCol = new DbColumnExpression(test.Type, TypeSystem.GetColumnType(test.Type), select.Alias, col.Name); break; } } if (testCol == null) { testCol = test as DbColumnExpression; var colName = testCol != null ? testCol.Name : "Test"; if (colName != null) { colName = proj.Select.Columns.GetAvailableColumnName(colName); } var colType = this.TypeSystem.GetColumnType(test.Type); if (colType != null) { select = select.AddColumn(new DbColumnDeclaration(colName, test, colType)); testCol = new DbColumnExpression(test.Type, colType, select.Alias, colName); } } return(new DbProjectionExpression ( select, new DbOuterJoinedExpression(testCol, proj.Projector), proj.Aggregator )); }
protected override Expression VisitClientJoin(DbClientJoinExpression join) { var innerKey = MakeJoinKey(join.InnerKey); var outerKey = MakeJoinKey(join.OuterKey); var kvpConstructor = typeof(KeyValuePair <,>).MakeGenericType(innerKey.Type, join.Projection.Projector.Type).GetConstructor(new Type[] { innerKey.Type, join.Projection.Projector.Type }); var constructKVPair = Expression.New(kvpConstructor, innerKey, join.Projection.Projector); var newProjection = new DbProjectionExpression(join.Projection.Select, constructKVPair); var iLookup = ++nLookup; var execution = this.ExecuteProjection(newProjection, okayToDefer: false, isTopLevel: false); var kvp = Expression.Parameter(constructKVPair.Type, "kvp"); if (join.Projection.Projector.NodeType == (ExpressionType)DbExpressionType.OuterJoined) { var pred = Expression.Lambda ( Expression.PropertyOrField(kvp, "Value").NotEqual(TypeHelper.GetNullConstant(join.Projection.Projector.Type)), kvp ); execution = Expression.Call(typeof(Enumerable), nameof(Enumerable.Where), new Type[] { kvp.Type }, execution, pred); } var keySelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Key"), kvp); var elementSelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Value"), kvp); var toLookup = Expression.Call(typeof(Enumerable), nameof(Enumerable.ToLookup), new Type[] { kvp.Type, outerKey.Type, join.Projection.Projector.Type }, execution, keySelector, elementSelector); var lookup = Expression.Parameter(toLookup.Type, "lookup" + iLookup); var property = lookup.Type.GetProperty("Item"); var access = Expression.Call(lookup, property.GetGetMethod(), this.Visit(outerKey)) as Expression; if (join.Projection.Aggregator != null) { access = DbExpressionReplacer.Replace(join.Projection.Aggregator.Body, join.Projection.Aggregator.Parameters[0], access); } this.variables.Add(lookup); this.initializers.Add(toLookup); return(access); }
internal override DbProjectionExpression GetQueryExpression(MappingEntity entity) { var tables = this.mapping.GetTables(entity); if (tables.Count <= 1) { return(base.GetQueryExpression(entity)); } var aliases = new Dictionary <string, TableAlias>(); var rootTable = tables.Single(ta => !this.mapping.IsExtensionTable(ta)); var tex = new DbTableExpression(new TableAlias(), entity, this.mapping.GetTableName(rootTable)); aliases.Add(this.mapping.GetAlias(rootTable), tex.Alias); var source = tex as Expression; foreach (var table in tables.Where(t => this.mapping.IsExtensionTable(t))) { var joinedTableAlias = new TableAlias(); var extensionAlias = this.mapping.GetAlias(table); aliases.Add(extensionAlias, joinedTableAlias); var keyColumns = this.mapping.GetExtensionKeyColumnNames(table).ToList(); var relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToList(); var relatedAlias = this.mapping.GetExtensionRelatedAlias(table); aliases.TryGetValue(relatedAlias, out TableAlias relatedTableAlias); var joinedTex = new DbTableExpression(joinedTableAlias, entity, this.mapping.GetTableName(table)); var cond = null as Expression; 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 DbColumnExpression(memberType, colType, relatedTableAlias, this.mapping.GetColumnName(entity, relatedMembers[i])); var joinedColumn = new DbColumnExpression(memberType, colType, joinedTableAlias, keyColumns[i]); var eq = joinedColumn.Equal(relatedColumn); cond = (cond != null) ? cond.And(eq) : eq; } source = new DbJoinExpression(JoinType.SingletonLeftOuter, source, joinedTex, cond); } var columns = new List <DbColumnDeclaration>(); this.GetColumns(entity, aliases, columns); var root = new DbSelectExpression(new TableAlias(), columns, source, null); var existingAliases = aliases.Values.ToArray(); var projector = this.GetEntityExpression(root, entity) as Expression; var selectAlias = new TableAlias(); var pc = DbColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, root.Alias); var proj = new DbProjectionExpression ( new DbSelectExpression(selectAlias, pc.Columns, root, null), pc.Projector ); return(this.Translator.Police.ApplyPolicy(proj, entity.ElementType.GetTypeInfo()) as DbProjectionExpression); }
public static DbProjectionExpression Remove(DbProjectionExpression projection, params DbSelectExpression[] selectsToRemove) { return(Remove(projection, selectsToRemove as IEnumerable <DbSelectExpression>)); }
public static DbProjectionExpression Remove(DbProjectionExpression projection, IEnumerable <DbSelectExpression> selectsToRemove) { return(new DbSubqueryRemover(selectsToRemove).Visit(projection) as DbProjectionExpression); }
protected override Expression VisitProjection(DbProjectionExpression proj) { var save = this.currentSelect; this.currentSelect = proj.Select; try { if (this.isTopLevel == false) { if (this.CanJoinOnClient(this.currentSelect)) { var newOuterSelect = DbQueryDuplicator.Duplicate(save) as DbSelectExpression; var newInnerSelect = DbColumnMapper.Map(proj.Select, newOuterSelect.Alias, save.Alias) as DbSelectExpression; var newInnerProjection = this.language.AddOuterJoinTest(new DbProjectionExpression(newInnerSelect, proj.Projector)); if (newInnerProjection != null) { newInnerSelect = newInnerProjection.Select; } var newProjector = newInnerProjection.Projector; var newAlias = new TableAlias(); var pc = DbColumnProjector.ProjectColumns(this.language, newProjector, null, newAlias, newOuterSelect.Alias, newInnerSelect.Alias); var join = new DbJoinExpression(JoinType.OuterApply, newOuterSelect, newInnerSelect, null); var joinedSelect = new DbSelectExpression(newAlias, pc.Columns, join, null, null, null, proj.IsSingleton, null, null, false); this.currentSelect = joinedSelect; if (pc != null) { newProjector = this.Visit(pc.Projector); } var outerKeys = new List <Expression>(); var innerKeys = new List <Expression>(); if (this.GetEquiJoinKeyExpressions(newInnerSelect.Where, newOuterSelect.Alias, outerKeys, innerKeys)) { var outerKey = outerKeys.Select(k => DbColumnMapper.Map(k, save.Alias, newOuterSelect.Alias)); var innerKey = innerKeys.Select(k => DbColumnMapper.Map(k, joinedSelect.Alias, ((DbColumnExpression)k).Alias)); var newProjection = new DbProjectionExpression(joinedSelect, newProjector, proj.Aggregator); return(new DbClientJoinExpression(newProjection, outerKey, innerKey)); } } else { var 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; } }
protected DbClientJoinExpression UpdateClientJoin(DbClientJoinExpression join, DbProjectionExpression projection, IEnumerable <Expression> outerKey, IEnumerable <Expression> innerKey) { if (projection != join.Projection || outerKey != join.OuterKey || innerKey != join.InnerKey) { return(new DbClientJoinExpression(projection, outerKey, innerKey)); } return(join); }
protected virtual Expression GetInsertResult(MappingEntity entity, Expression instance, LambdaExpression selector, Dictionary <MemberInfo, Expression> map) { var tableAlias = new TableAlias(); var tex = new DbTableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var aggregator = DbAggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable <>).MakeGenericType(selector.Body.Type)); var where = null as Expression; var genIdCommand = null as DbDeclarationCommand; 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; } if (selector.Body is MemberExpression mex && this.mapping.IsPrimaryKey(entity, mex.Member) && this.mapping.IsGenerated(entity, mex.Member)) { if (genIdCommand != null) { return(new DbProjectionExpression ( genIdCommand.Source, new DbColumnExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name), aggregator )); } else { var alias = new TableAlias(); var colType = this.GetColumnType(entity, mex.Member); return(new DbProjectionExpression ( new DbSelectExpression(alias, new[] { new DbColumnDeclaration(string.Empty, map[mex.Member], colType) }, null, null), new DbColumnExpression(TypeHelper.GetMemberType(mex.Member), colType, alias, string.Empty), 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); } var typeProjector = this.GetEntityExpression(tex, entity); var selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); var newAlias = new TableAlias(); var pc = DbColumnProjector.ProjectColumns(this.translator.Linguist.Language, selection, null, newAlias, tableAlias); var pe = new DbProjectionExpression ( new DbSelectExpression(newAlias, pc.Columns, tex, where), pc.Projector, aggregator ); if (genIdCommand != null) { return(new DbBlockCommand(genIdCommand, pe)); } return(pe); }
protected override Expression VisitProjection(DbProjectionExpression proj) { return(this.UpdateProjection(proj, proj.Select, this.Visit(proj.Projector), proj.Aggregator)); }
protected override Expression VisitProjection(DbProjectionExpression proj) { this.Visit(proj.Projector); return(proj); }
public DbClientJoinExpression(DbProjectionExpression projection, IEnumerable <Expression> outerKey, IEnumerable <Expression> innerKey) : base(DbExpressionType.ClientJoin, projection.Type) { this.OuterKey = outerKey.ToReadOnly(); this.InnerKey = innerKey.ToReadOnly(); this.Projection = projection; }