private Expression FindSimilarRight(JoinExpression join, JoinExpression compareTo) { if (join == null) { return null; } if (join.Join == compareTo.Join) { if (join.Right.NodeType == compareTo.Right.NodeType && DbExpressionComparer.AreEqual(join.Right, compareTo.Right)) { if (join.Condition == compareTo.Condition) { return join.Right; } var scope = new ScopedDictionary<TableAlias, TableAlias>(null); scope.Add(((AliasedExpression)join.Right).Alias, ((AliasedExpression)compareTo.Right).Alias); if (DbExpressionComparer.AreEqual(null, scope, join.Condition, compareTo.Condition)) { return join.Right; } } } Expression result = FindSimilarRight(join.Left as JoinExpression, compareTo); if (result == null) { result = FindSimilarRight(join.Right as JoinExpression, compareTo); } return result; }
protected override Expression VisitJoin(JoinExpression join) { if (join.Join == JoinType.SingletonLeftOuter) { // first visit right side w/o looking at condition Expression right = this.Visit(join.Right); AliasedExpression ax = right as AliasedExpression; if (ax != null && !this.allColumnsUsed.ContainsKey(ax.Alias)) { // if nothing references the alias on the right, then the join is redundant return this.Visit(join.Left); } // otherwise do it the right way Expression cond = this.Visit(join.Condition); Expression left = this.Visit(join.Left); right = this.Visit(join.Right); return this.UpdateJoin(join, join.Join, left, right, cond); } else { // visit join in reverse order Expression condition = this.Visit(join.Condition); Expression right = this.VisitSource(join.Right); Expression left = this.VisitSource(join.Left); return this.UpdateJoin(join, join.Join, left, right, condition); } }
protected override Expression VisitMemberAccess(MemberExpression m) { Expression source = this.Visit(m.Expression); EntityExpression ex = source as EntityExpression; IMemberMapping mm = null; if (ex != null && (mm = ex.Entity.Get(m.Member)) != null && mm.IsRelationship) { ProjectionExpression projection = (ProjectionExpression)this.Visit(this.expressionBuilder.GetMemberExpression(source, ex.Entity, m.Member)); if (this.currentFrom != null && mm.IsManyToOne) { // convert singleton associations directly to OUTER APPLY projection = this.expressionBuilder.AddOuterJoinTest(projection); Expression newFrom = new JoinExpression(JoinType.OuterApply, this.currentFrom, projection.Select, null); this.currentFrom = newFrom; return projection.Projector; } return projection; } else { Expression result = QueryBinder.BindMember(source, m.Member); MemberExpression mex = result as MemberExpression; if (mex != null && mex.Member == m.Member && mex.Expression == m.Expression) { return m; } return result; } }
protected override Expression VisitMemberAccess(MemberExpression m) { Expression source = this.Visit(m.Expression); if (this.mapping.IsRelationship(m.Member)) { ProjectionExpression projection = (ProjectionExpression)this.Visit(this.mapping.GetMemberExpression(source, m.Member)); if (this.currentFrom != null && this.mapping.IsSingletonRelationship(m.Member)) { // convert singleton associations directly to OUTER APPLY projection = projection.AddOuterJoinTest(); Expression newFrom = new JoinExpression(JoinType.OuterApply, this.currentFrom, projection.Source, null); this.currentFrom = newFrom; return projection.Projector; } return projection; } else { Expression result = QueryBinder.BindMember(source, m.Member); MemberExpression mex = result as MemberExpression; if (mex != null && mex.Member == m.Member && mex.Expression == m.Expression) { return m; } 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; } }
protected override Expression VisitJoin(JoinExpression join) { // visit join in reverse order Expression condition = this.Visit(join.Condition); Expression right = this.VisitSource(join.Right); Expression left = this.VisitSource(join.Left); if (left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(join.Join, left, right, condition); } return join; }
protected override Expression VisitJoin(JoinExpression join) { var saveLastJoin = this.lastJoin; this.lastJoin = join.Join; join = (JoinExpression)base.VisitJoin(join); this.lastJoin = saveLastJoin; if (this.lastJoin != null && (join.Join == JoinType.CrossJoin) != (this.lastJoin == JoinType.CrossJoin)) { var result = this.MakeSubquery(join); return result; } return join; }
private static SelectExpression AddInnerJoins(SelectExpression select, IEnumerable<InExpression> inExpressions) { foreach (var inExpression in inExpressions) { var joinExpression = new JoinExpression(JoinType.InnerJoin, select.From, inExpression.Select, Expression.MakeBinary(ExpressionType.Equal, inExpression.Expression, inExpression.Select.Columns[0].Expression)); select = select.SetFrom(joinExpression); } return select; }
protected override Expression VisitJoin(JoinExpression join) { Expression result = base.VisitJoin(join); join = result as JoinExpression; if (join != null) { AliasedExpression right = join.Right as AliasedExpression; if (right != null) { AliasedExpression similarRight = (AliasedExpression)this.FindSimilarRight(join.Left as JoinExpression, join); if (similarRight != null) { this.map.Add(right.Alias, similarRight.Alias); return join.Left; } } } return result; }
protected override Expression VisitJoin(JoinExpression join) { if (join.Condition != null) this.Visit(join.Condition); else this.VisitSource(join.Right); SourceExpression left = this.VisitSource(join.Left); SourceExpression right = this.VisitSource(join.Right); Expression condition = this.Visit(join.Condition); if (left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(join.JoinType, left, right, condition); } return join; }
protected override Expression VisitJoin(JoinExpression join) { join = (JoinExpression)base.VisitJoin(join); if (join.Join == JoinType.CrossApply || join.Join == JoinType.OuterApply) { if (join.Right is TableExpression) { return new JoinExpression(JoinType.CrossJoin, join.Left, join.Right, null); } else { SelectExpression select = join.Right as SelectExpression; // Only consider rewriting cross apply if // 1) right side is a select // 2) other than in the where clause in the right-side select, no left-side declared aliases are referenced // 3) and has no behavior that would change semantics if the where clause is removed (like groups, aggregates, take, skip, etc). // Note: it is best to attempt this after redundant subqueries have been removed. if (select != null && select.Take == null && select.Skip == null && !AggregateChecker.HasAggregates(select) && (select.GroupBy == null || select.GroupBy.Count == 0)) { SelectExpression selectWithoutWhere = select.SetWhere(null); HashSet<TableAlias> referencedAliases = ReferencedAliasGatherer.Gather(selectWithoutWhere); HashSet<TableAlias> declaredAliases = DeclaredAliasGatherer.Gather(join.Left); referencedAliases.IntersectWith(declaredAliases); if (referencedAliases.Count == 0) { Expression where = select.Where; select = selectWithoutWhere; var pc = ColumnProjector.ProjectColumns(this.CanBeColumn, where, select.Columns, select.Alias, DeclaredAliasGatherer.Gather(select.From)); select = select.SetColumns(pc.Columns); where = pc.Projector; JoinType jt = (where == null) ? JoinType.CrossJoin : (join.Join == JoinType.CrossApply ? JoinType.InnerJoin : JoinType.LeftOuter); return new JoinExpression(jt, join.Left, select, where); } } } } return join; }
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; }
protected override Expression VisitJoin(JoinExpression join) { join = (JoinExpression)base.VisitJoin(join); if (join.Join == JoinType.CrossJoin && this.currentWhere != null) { // try to figure out which parts of the current where expression can be used for a join condition var declaredLeft = DeclaredAliasGatherer.Gather(join.Left); var declaredRight = DeclaredAliasGatherer.Gather(join.Right); var declared = new HashSet<TableAlias>(declaredLeft.Union(declaredRight)); var exprs = this.currentWhere.Split(ExpressionType.And, ExpressionType.AndAlso); var good = exprs.Where(e => CanBeJoinCondition(e, declaredLeft, declaredRight, declared)).ToList(); if (good.Count > 0) { var condition = good.Join(ExpressionType.And); join = this.UpdateJoin(join, JoinType.InnerJoin, join.Left, join.Right, condition); var newWhere = exprs.Where(e => !good.Contains(e)).Join(ExpressionType.And); this.currentWhere = newWhere; } } return join; }
protected override Expression VisitJoin(JoinExpression join) { join = (JoinExpression)base.VisitJoin(join); if (join.JoinType == JoinType.CrossJoin && _currentWhere != null) { // try to figure out which parts of the current where expression can be used for a join condition var declaredLeft = DeclaredAliasGatherer.Gather(join.Left); var declaredRight = DeclaredAliasGatherer.Gather(join.Right); var declared = new HashSet <TableAlias>(declaredLeft.Union(declaredRight)); var exprs = _currentWhere.Split(ExpressionType.And, ExpressionType.AndAlso); var good = exprs.Where(e => CanBeJoinCondition(e, declaredLeft, declaredRight, declared)).ToList(); if (good.Count > 0) { var condition = good.Join(ExpressionType.And); join = join.Update(JoinType.InnerJoin, join.Left, join.Right, condition); var newWhere = exprs.Where(e => !good.Contains(e)).Join(ExpressionType.And); _currentWhere = newWhere; } } return(join); }
public void GetSupersetAlias_ExprsNoSupersetExpr_Null() { List <IExpression> exprs = new List <IExpression>(); IExpression expr1 = ModelResolvers.ExprResolver(); expr1.Structure = ModelResolvers.DsResolver(); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "Id2")); IExpression expr2 = ModelResolvers.ExprResolver(); expr2.Structure = ModelResolvers.DsResolver(); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "Id3")); exprs.Add(expr1); exprs.Add(expr2); Assert.Null(JoinExpression.GetSupersetAlias(exprs)); }
/// <summary> /// Visits the join. /// </summary> /// <param name="join">The join.</param> /// <returns></returns> protected override Expression VisitJoin(JoinExpression join) { join = (JoinExpression)base.VisitJoin(join); if (join.Join == JoinType.CrossApply || join.Join == JoinType.OuterApply) { if (join.Right is TableExpression) { return(new JoinExpression(JoinType.CrossJoin, join.Left, join.Right, null)); } else { SelectExpression select = join.Right as SelectExpression; // Only consider rewriting cross apply if // 1) right side is a select // 2) other than in the where clause in the right-side select, no left-side declared aliases are referenced // 3) and has no behavior that would change semantics if the where clause is removed (like groups, aggregates, take, skip, etc). // Note: it is best to attempt this after redundant subqueries have been removed. if (select != null && select.Take == null && select.Skip == null && !AggregateChecker.HasAggregates(select) && (select.GroupBy == null || select.GroupBy.Count == 0)) { SelectExpression selectWithoutWhere = select.SetWhere(null); HashSet <TableAlias> referencedAliases = ReferencedAliasGatherer.Gather(selectWithoutWhere); HashSet <TableAlias> declaredAliases = DeclaredAliasGatherer.Gather(join.Left); referencedAliases.IntersectWith(declaredAliases); if (referencedAliases.Count == 0) { Expression where = select.Where; select = selectWithoutWhere; var pc = ColumnProjector.ProjectColumns(this.language, where, select.Columns, select.Alias, DeclaredAliasGatherer.Gather(select.From)); select = select.SetColumns(pc.Columns); where = pc.Projector; JoinType jt = (where == null) ? JoinType.CrossJoin : (join.Join == JoinType.CrossApply ? JoinType.InnerJoin : JoinType.LeftOuter); return(new JoinExpression(jt, join.Left, select, where)); } } } } return(join); }
public void GetAliasesSignatures_CompName_Signatures(string compName) { JoinExpression joinExpr = new JoinExpression(TestExprFactory.GetExpression("join", ExpressionFactoryNameTarget.OperatorSymbol)); joinExpr.AddOperand("ds", ModelResolvers.ExprResolver()); IExpression expr1 = TestExprFactory.GetExpression("get", ExpressionFactoryNameTarget.OperatorSymbol); expr1.Structure = ModelResolvers.DsResolver(); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "comp1")); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "comp2")); IExpression expr2 = TestExprFactory.GetExpression("ref", ExpressionFactoryNameTarget.OperatorSymbol); expr2.Structure = ModelResolvers.DsResolver(); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "comp1")); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "comp3")); joinExpr.Operands["ds"].AddOperand("ds_1", expr1); joinExpr.Operands["ds"].AddOperand("ds_2", expr2); List <string> expected = new List <string>(); if (compName != "comp4") { expected.Add("ds_1"); } if (!compName.In("comp2", "comp4")) { expected.Add("ds_2"); } string[] result = joinExpr.GetAliasesSignatures(compName); Assert.Equal(expected.Count, result.Length); for (int i = 0; i < expected.Count; i++) { Assert.Equal(expected[i], result[i]); } }
public void GetSubsetAliasStructure_SubsetStructure() { for (int i = 0; i < 2; i++) { JoinExpression joinExpr = new JoinExpression(TestExprFactory.GetExpression("join", ExpressionFactoryNameTarget.OperatorSymbol)); joinExpr.AddOperand("ds", ModelResolvers.ExprResolver()); IExpression expr1 = ModelResolvers.ExprResolver(); expr1.Structure = ModelResolvers.DsResolver(); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "Id2")); IExpression expr2 = ModelResolvers.ExprResolver(); expr2.Structure = ModelResolvers.DsResolver(); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "Id2")); joinExpr.Operands["ds"].AddOperand("ds_1", expr1); joinExpr.Operands["ds"].AddOperand("ds_2", expr2); IExpression expr3 = ModelResolvers.ExprResolver(); if (i == 1) { expr3.Structure = ModelResolvers.DsResolver(); expr3.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); joinExpr.Operands["ds"].AddOperand("ds_3", expr3); } IDataStructure result = joinExpr.GetSubsetAliasStructure(); if (i == 0) { Assert.True(expr1.Structure.EqualsObj(result)); } else { Assert.True(expr3.Structure.EqualsObj(result)); } } }
protected override Expression VisitJoin(JoinExpression join) { var result = base.VisitJoin(join); join = result as JoinExpression; if (join != null) { var right = join.Right as AliasedExpression; if (right != null) { var similarRight = (AliasedExpression)FindSimilarRight(join.Left as JoinExpression, join); if (similarRight != null) { map.Add(right.Alias, similarRight.Alias); return(join.Left); } } } return(result); }
protected internal override Expression VisitJoin(JoinExpression join) { SourceExpression left = this.VisitSource(join.Left); SourceExpression right = this.VisitSource(join.Right); Expression? condition = this.Visit(join.Condition); if (join.JoinType == JoinType.CrossApply || join.JoinType == JoinType.OuterApply) { if (right is TableExpression) { return(new JoinExpression(join.JoinType == JoinType.OuterApply ? JoinType.LeftOuterJoin : JoinType.InnerJoin, left, right, Schema.Current.Settings.IsPostgres ? (Expression) new SqlConstantExpression(true) : Expression.Equal(new SqlConstantExpression(1), new SqlConstantExpression(1)))); } } if (left != join.Left || right != join.Right || condition != join.Condition) { return(new JoinExpression(join.JoinType, left, right, condition)); } return(join); }
public void GetSubsetAlias_Exprs_SubsetExpr() { for (int i = 0; i < 2; i++) { List <IExpression> exprs = new List <IExpression>(); IExpression expr1 = ModelResolvers.ExprResolver(); expr1.Structure = ModelResolvers.DsResolver(); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); expr1.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "Id2")); IExpression expr2 = ModelResolvers.ExprResolver(); expr2.Structure = ModelResolvers.DsResolver(); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); expr2.Structure.Identifiers.Add(new StructureComponent(BasicDataType.String, "Id2")); exprs.Add(expr1); exprs.Add(expr2); IExpression expr3 = ModelResolvers.ExprResolver(); if (i == 1) { expr3.Structure = ModelResolvers.DsResolver(); expr3.Structure.Identifiers.Add(new StructureComponent(BasicDataType.Integer, "Id1")); exprs.Add(expr3); } IExpression result = JoinExpression.GetSubsetAlias(exprs); if (i == 0) { Assert.Equal(expr1, result); } else { Assert.Equal(expr3, result); } } }
private void TranslateJoin(JoinExpression node) { Translate(node.Source); var joined = node.Joined as CollectionExpression; if (joined == null) { throw new NotSupportedException("Only a collection is allowed to be joined."); } var localFieldValue = AggregateLanguageTranslator.Translate(node.SourceKeySelector); if (localFieldValue.BsonType != BsonType.String) { throw new NotSupportedException("Could not translate the local field."); } var localField = localFieldValue.ToString().Substring(1); // remove '$' var foreignFieldValue = AggregateLanguageTranslator.Translate(node.SourceKeySelector); if (foreignFieldValue.BsonType != BsonType.String) { throw new NotSupportedException("Could not translate the foreign field."); } var foreignField = foreignFieldValue.ToString().Substring(1); // remove '$' _stages.Add(new BsonDocument("$lookup", new BsonDocument { { "from", ((CollectionExpression)node.Joined).CollectionNamespace.CollectionName }, { "localField", localField }, { "foreignField", foreignField }, { "as", node.JoinedItemName } })); _stages.Add(new BsonDocument("$unwind", "$" + node.JoinedItemName)); }
private IJoinQuery<TResult> Join<TR, TKey, TResult>(string type, IQuery<TR> rightQuery, Expression<Func<T, TKey>> leftKeySelector, Expression<Func<TR, TKey>> rightKeySelector, Expression<Func<T, TR, TResult>> resultSelector) where TR : BaseDBModel, new() { var rightTableAlias = "t" + (JoinTableCount + 1); var dynamicParameters = new DynamicParameters(); dynamicParameters.AddDynamicParams(Param); var left = new JoinExpression(leftKeySelector, Map, dynamicParameters); var right = new JoinExpression(rightKeySelector, new Dictionary<string, string> { { "", rightTableAlias } }, dynamicParameters); StringBuilder sqlJoin = new StringBuilder(); foreach (var v in left.JoinDic) { if (sqlJoin.Length > 0) { sqlJoin.Append(" AND "); } sqlJoin.Append("("); sqlJoin.Append(v.Value); sqlJoin.Append("="); sqlJoin.Append(right.JoinDic[v.Key]); sqlJoin.Append(")"); } var joinStr = $"{JoinStr} {type} JOIN {DBTool.GetTableName(rightQuery.DBModel)} {rightTableAlias} ON {sqlJoin}"; var sel = new JoinResultMapExpression(resultSelector, Map, rightTableAlias, dynamicParameters); StringBuilder sqlWhere = new StringBuilder(Where); var where = new WhereExpression(rightQuery.WhereExpression, rightTableAlias, dynamicParameters); if (!string.IsNullOrEmpty(where.SqlCmd)) { if (sqlWhere.Length > 0) { sqlWhere.Append(" AND "); } sqlWhere.Append(where.SqlCmd); } return new JoinQueryInfo<TResult>(joinStr, JoinTableCount + 1, sel.MapList, sqlWhere.ToString(), dynamicParameters); }
/// <summary> /// Renders a TSQL translated code for an "if-then-else" operator identifier. /// </summary> /// <param name="identifier">The idenfitier.</param> /// <returns>The TSQL translated code.</returns> private string RenderIfThenElseIdentifier(StructureComponent identifier) { // Get aliases of every "if-then-else" branch: IExpression[] ifExprAliases = this.joinExpr.Operands["ds"].OperandsCollection .Where(alias => alias.ParamSignature.In(this.joinExpr.Operands["apply"].Operands["if"].GetDescendantExprs("Alias").Select(a => a.ExpressionText).ToArray())).ToArray(); IExpression[] thenExprAliases = this.joinExpr.Operands["ds"].OperandsCollection .Where(alias => alias.ParamSignature.In(this.joinExpr.Operands["apply"].Operands["then"].GetDescendantExprs("Alias").Select(a => a.ExpressionText).ToArray())).ToArray(); IExpression[] elseExprAliases = this.joinExpr.Operands["ds"].OperandsCollection .Where(alias => alias.ParamSignature.In(this.joinExpr.Operands["apply"].Operands["else"].GetDescendantExprs("Alias").Select(a => a.ExpressionText).ToArray())).ToArray(); // Get subset alias of every "if-then-else" branch: IExpression ifExprAlias = JoinExpression.GetSubsetAlias(ifExprAliases); IExpression thenExprAlias = JoinExpression.GetSubsetAlias(thenExprAliases); IExpression elseExprAlias = JoinExpression.GetSubsetAlias(elseExprAliases); if (thenExprAlias != null && elseExprAlias != null) { IExpression ifSubExpr = this.joinExpr.Operands["apply"].Operands["if"].Operands["ds_1"]; string suffix = ifSubExpr.OperatorSymbol.In("ref", "const") ? " = 1" : string.Empty; return ($"IIF({this._opRendererResolver(ifSubExpr.OperatorSymbol).Render(ifSubExpr, ifExprAlias?.Structure.Measures[0] ?? this.joinExpr.Operands["apply"].Operands["then"].Structure.Measures[0])}{suffix}, " + $"{thenExprAlias.ParamSignature}.{identifier.ComponentName}, " + $"{elseExprAlias.ParamSignature}.{identifier.ComponentName}) AS {identifier.ComponentName},"); } else if (thenExprAlias != null) { return($"{thenExprAlias.ParamSignature}.{identifier.ComponentName},"); } else if (elseExprAlias != null) { return($"{elseExprAlias.ParamSignature}.{identifier.ComponentName},"); } else { return($"{ifExprAlias.ParamSignature}.{identifier.ComponentName},"); } }
private void VisitTableExpression(TableExpression table) { if (table is JoinExpression) { JoinExpression jt = (JoinExpression)table; sql.Append($"{Environment.NewLine}\t{jt.JoinType} {jt.Entity.MainTable.FullName} AS [{jt.Alias}]"); if (jt.Hint != HintTypes.NoneHint) { sql.Append($" WITH({jt.Hint})"); } sql.Append("\n\tON"); VisitBooleanFunction(jt.ON); } else if (table is TableExpression) { sql.Append($"{Environment.NewLine}\t{table.Entity.MainTable.FullName} AS [{table.Alias}]"); if (table.Hint != HintTypes.NoneHint) { sql.Append($" WITH({table.Hint})"); } } }
protected internal override Expression VisitJoin(JoinExpression join) { if (join.JoinType == JoinType.SingleRowLeftOuterJoin) { var source = (SourceWithAliasExpression)join.Right; var hs = allColumnsUsed.TryGetC(source.Alias); if (hs == null || hs.Count == 0) { return(Visit(join.Left)); } } if (join.JoinType == JoinType.OuterApply || join.JoinType == JoinType.LeftOuterJoin) { if (join.Right is SelectExpression sql && sql.IsOneRow()) { var hs = allColumnsUsed.TryGetC(sql.Alias); if (hs == null || hs.Count == 0) { return(Visit(join.Left)); } } } // visit join in reverse order Expression? condition = this.Visit(join.Condition); SourceExpression right = this.VisitSource(join.Right); SourceExpression left = this.VisitSource(join.Left); if (left != join.Left || right != join.Right || condition != join.Condition) { return(new JoinExpression(join.JoinType, left, right, condition)); } return(join); }
private Expression BindGroupJoin(MethodCallExpression call) { Expression outerSource = call.Arguments[0]; Expression innerSource = call.Arguments[1]; LambdaExpression outerKey = GetLambda(call.Arguments[2]); LambdaExpression innerKey = GetLambda(call.Arguments[3]); LambdaExpression resultSelector = GetLambda(call.Arguments[4]); ProjectionExpression outerProjection = VisitSequence(outerSource); ProjectionExpression innerProjection = VisitSequence(innerSource); _map[outerKey.Parameters[0]] = outerProjection.Projector; Expression outerKeyExpr = Visit(outerKey.Body); _map[innerKey.Parameters[0]] = innerProjection.Projector; Expression innerKeyExpr = Visit(innerKey.Body); LambdaExpression predicate = Expression.Lambda(Expression.Equal(innerKey.Body, outerKey.Body), innerKey.Parameters[0]); Expression subquery = Expression.Call(typeof(Queryable), nameof(Queryable.Where), new[] { innerKey.Parameters[0].Type }, innerSource, predicate); _map[resultSelector.Parameters[0]] = outerProjection.Projector; _map[resultSelector.Parameters[1]] = Visit(subquery); Expression resultExpr = Visit(resultSelector.Body); JoinExpression join = new JoinExpression(JoinType.InnerJoin, outerProjection.Source, innerProjection.Source, Expression.Equal(outerKeyExpr, innerKeyExpr)); var groupedColumns = ProjectColumns(outerKeyExpr, outerProjection.Source.Alias, outerProjection.Source.Alias); IEnumerable <Expression> groupExprs = groupedColumns.Columns.Select(c => c.Expression); string alias = GetNewAlias(); ProjectedColumns pc = ProjectColumns(resultExpr, alias, outerProjection.Source.Alias, innerProjection.Source.Alias); return(new ProjectionExpression( new SelectExpression(alias, pc.Columns, join, groupBy: groupExprs), pc.Projector )); }
protected override Expression VisitJoin(JoinExpression join) { this.VisitJoinLeft(join.Left); this.WriteLine(Indentation.Same); switch (join.Join) { case JoinType.CrossJoin: this.Write(", "); break; case JoinType.InnerJoin: this.Write("INNER JOIN "); break; case JoinType.CrossApply: this.Write("CROSS APPLY "); break; case JoinType.OuterApply: this.Write("OUTER APPLY "); break; case JoinType.LeftOuter: case JoinType.SingletonLeftOuter: this.Write("LEFT OUTER JOIN "); break; } this.VisitJoinRight(join.Right); if (join.Condition != null) { this.WriteLine(Indentation.Inner); this.Write("ON "); this.VisitPredicate(join.Condition); this.Indent(Indentation.Outer); } return(join); }
protected override Expression VisitMember(MemberExpression m) { var source = Visit(m.Expression); IProperty property; // **fix** 解决无法返回两级以上关联对象的问题 // var ex = source as EntityExpression // if (ex != null && if ((property = PropertyUnity.GetProperty(m.Expression.Type, m.Member.Name)) != null && property is RelationProperty) { var projection = (ProjectionExpression)Visit(QueryUtility.GetMemberExpression(source, property)); if (currentFrom != null && m.Member.GetMemberType().GetEnumerableType() == null) { // convert singleton associations directly to OUTER APPLY projection = projection.AddOuterJoinTest(); var newFrom = new JoinExpression(JoinType.OuterApply, currentFrom, projection.Select, null); currentFrom = newFrom; return(projection.Projector); } return(projection); } var result = QueryBinder.BindMember(source, m.Member); var mex = result as MemberExpression; if (mex != null && mex.Member == m.Member && mex.Expression == m.Expression) { return(m); } return(result); }
public void Constructor_JoinOperatorExpr_JoinExpr() { IExpression expr = TestExprFactory.GetExpression("join", ExpressionFactoryNameTarget.OperatorSymbol); IExpression refExpr = ModelResolvers.ExprResolver(); ITransformationSchema schema = ModelResolvers.SchemaResolver(); refExpr.AddOperand("ds", expr); expr.ContainingSchema = schema; expr.ReferenceExpression = refExpr; JoinExpression joinExpr = new JoinExpression(expr); Assert.Equal(expr.ParentExpression, joinExpr.ParentExpression); Assert.Equal(expr.ContainingSchema, joinExpr.ContainingSchema); Assert.Equal(expr.ExpressionText, joinExpr.ExpressionText); Assert.Equal(expr.LineNumber, joinExpr.LineNumber); Assert.Equal(expr.OperandsCollection, joinExpr.OperandsCollection); Assert.Equal(expr.OperatorDefinition, joinExpr.OperatorDefinition); Assert.Equal(expr.ParamSignature, joinExpr.ParamSignature); Assert.Equal(expr.ReferenceExpression, joinExpr.ReferenceExpression); Assert.Equal(expr.ResultName, joinExpr.ResultName); Assert.Equal(expr.Structure, joinExpr.Structure); Assert.Null(joinExpr.BasicStructure); }
protected virtual Expression BindSelectMany(Type resultType, Expression source, LambdaExpression collectionSelector, LambdaExpression resultSelector) { ProjectionExpression projection = this.VisitSequence(source); this.map[collectionSelector.Parameters[0]] = projection.Projector; Expression collection = collectionSelector.Body; // check for DefaultIfEmpty bool defaultIfEmpty = false; MethodCallExpression mcs = collection as MethodCallExpression; if (mcs != null && mcs.Method.Name == "DefaultIfEmpty" && mcs.Arguments.Count == 1 && (mcs.Method.DeclaringType == typeof(Queryable) || mcs.Method.DeclaringType == typeof(Enumerable))) { collection = mcs.Arguments[0]; defaultIfEmpty = true; } ProjectionExpression collectionProjection = (ProjectionExpression)this.VisitSequence(collection); bool isTable = collectionProjection.Select.From is TableExpression; JoinType joinType = isTable ? JoinType.CrossJoin : defaultIfEmpty ? JoinType.OuterApply : JoinType.CrossApply; if (joinType == JoinType.OuterApply) { collectionProjection = this.language.AddOuterJoinTest(collectionProjection); } JoinExpression join = new JoinExpression(joinType, projection.Select, collectionProjection.Select, null); var alias = this.GetNextAlias(); ProjectedColumns pc; if (resultSelector == null) { pc = this.ProjectColumns(collectionProjection.Projector, alias, projection.Select.Alias, collectionProjection.Select.Alias); } else { this.map[resultSelector.Parameters[0]] = projection.Projector; this.map[resultSelector.Parameters[1]] = collectionProjection.Projector; Expression result = this.Visit(resultSelector.Body); pc = this.ProjectColumns(result, alias, projection.Select.Alias, collectionProjection.Select.Alias); } return new ProjectionExpression( new SelectExpression(alias, pc.Columns, join, null), pc.Projector ); }
protected override Expression VisitJoin(JoinExpression join) { // make sure order by expressions lifted up from the left side are not lost // when visiting the right side Expression left = this.VisitSource(join.Left); IList<OrderExpression> leftOrders = this.gatheredOrderings; this.gatheredOrderings = null; // start on the right with a clean slate Expression right = this.VisitSource(join.Right); this.PrependOrderings(leftOrders); Expression condition = this.Visit(join.Condition); if (left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(join.Join, left, right, condition); } return join; }
/// <summary> /// Visits the projection. /// </summary> /// <param name="proj">The proj.</param> /// <returns></returns> 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)ColumnMapper.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; TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.language, newProjector, null, 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, 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 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 { 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; } }
protected override Expression GetInsertResult(MappingEntity entity, Expression instance, LambdaExpression selector, Dictionary<MemberInfo, Expression> map) { var tables = _mapping.GetTables(entity); if (tables.Count <= 1) { return base.GetInsertResult(entity, instance, selector, map); } var aliases = new Dictionary<string, TableAlias>(); MappingTable rootTable = tables.Single(ta => !_mapping.IsExtensionTable(ta)); var tableExpression = new TableExpression(new TableAlias(), entity, _mapping.GetTableName(rootTable)); var aggregator = Aggregator.GetAggregator(selector.Body.Type, typeof (IEnumerable<>).MakeGenericType(selector.Body.Type)); aliases.Add(_mapping.GetAlias(rootTable), tableExpression.Alias); Expression source = tableExpression; foreach (MappingTable table in tables.Where(t => _mapping.IsExtensionTable(t))) { TableAlias joinedTableAlias = new TableAlias(); string extensionAlias = _mapping.GetAlias(table); aliases.Add(extensionAlias, joinedTableAlias); List<string> keyColumns = _mapping.GetExtensionKeyColumnNames(table).ToList(); List<MemberInfo> relatedMembers = _mapping.GetExtensionRelatedMembers(table).ToList(); string relatedAlias = _mapping.GetExtensionRelatedAlias(table); TableAlias relatedTableAlias; aliases.TryGetValue(relatedAlias, out relatedTableAlias); TableExpression joinedTex = new TableExpression(joinedTableAlias, entity, _mapping.GetTableName(table)); Expression cond = null; for (int i = 0, n = keyColumns.Count; i < n; i++) { var memberType = TypeHelper.GetMemberType(relatedMembers[i]); var colType = GetColumnType(entity, relatedMembers[i]); var relatedColumn = new ColumnExpression(memberType, colType, relatedTableAlias, _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); } Expression where; DeclarationCommand genIdCommand = null; var generatedIds = _mapping.GetMappedMembers(entity).Where( m => _mapping.IsPrimaryKey(entity, m) && _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 = GetGeneratedIdCommand(entity, generatedIds.ToList(), localMap); map = localMap; } var mex = selector.Body as MemberExpression; if (mex != null && _mapping.IsPrimaryKey(entity, mex.Member) && _mapping.IsGenerated(entity, mex.Member)) { if (genIdCommand != null) { return new ProjectionExpression( genIdCommand.Source, new ColumnExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name), aggregator ); } TableAlias alias = new TableAlias(); var colType = 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) => GetMemberExpression(source, entity, m).Equal(map[m]) ).Aggregate((x, y) => x.And(y)); } else { where = GetIdentityCheck(tableExpression, entity, instance); } var columns = new List<ColumnDeclaration>(); GetColumns(entity, aliases, columns); SelectExpression root = new SelectExpression(new TableAlias(), columns, source, null); Expression typeProjector = GetEntityExpression(tableExpression, entity); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(Translator.Linguist.Language, selection, null, newAlias, tableExpression.Alias); var pe = new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, root, where), pc.Projector, aggregator ); if (genIdCommand != null) { return new BlockCommand(genIdCommand, pe); } return pe; }
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); }
private static IEnumerable<ColumnExpression> KeysJoin(JoinExpression join) { switch (join.JoinType) { case JoinType.SingleRowLeftOuterJoin: return Keys(join.Left); case JoinType.CrossJoin: case JoinType.InnerJoin: case JoinType.CrossApply: case JoinType.OuterApply: case JoinType.LeftOuterJoin: case JoinType.RightOuterJoin: case JoinType.FullOuterJoin: return Keys(join.Left).Concat(Keys(join.Right)); default: break; } throw new InvalidOperationException("Unexpected Join Type"); }
protected virtual Expression VisitJoin(JoinExpression join) { Expression left = this.VisitSource(join.Left); Expression right = this.VisitSource(join.Right); Expression condition = this.Visit(join.Condition); if (left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(join.Join, left, right, condition); } return join; }
public Expression Parse(string expr, CompileContext ctx = null, Dictionary <Expression, ExpressionSegment> segments = null) { if (expr == null) { throw new Exception("expr null"); } expr = expr.Trim(); if (string.IsNullOrEmpty(expr)) { throw new Exception("expr empty"); } Expression result; if (cachedExprs.TryGetValue(expr, out result)) { return(result); } Stack <Expression> s1 = new Stack <Expression>(); Stack <PartInfo> s2 = new Stack <PartInfo>(); Stack <string> variables = new Stack <string>(); Stack <CompileContext> ctxs = new Stack <CompileContext>(); ctxs.Push(ctx); PushScope(ctxs); foreach (var segment in ToParts(expr)) { if (segment.IsString) { s1.Push(Expression.Constant <string>(segment.Expr)); //s1.Push((Expression)part1); if (segments != null) { segments[s1.Peek()] = segment; } continue; } string exprPart = segment.Expr; Console.WriteLine("part:" + exprPart); if (kws.ContainsKey(exprPart)) // if(segment.IsKeyword) { var part = new PartInfo() { segment = segment, keywordInfo = kws[exprPart] }; var kw = part.keywordInfo; if (kw.Keyword == ")") { while (s2.Count > 0 && s2.Peek().keywordInfo.Keyword != "(") { var tmp = s2.Pop(); s1.Push(GetExpr(tmp, s1, s2)); if (s2.Peek().keywordInfo.Keyword == ",") { } } Expression contentNode; if (s1.Peek().ExpressionType != ExpressionType.Group) { contentNode = PopData(s1); } else { contentNode = null; } if (s1.Peek() is JoinExpression) { var join = s1.Pop() as JoinExpression; //join.List.Insert(0, contentNode); join.List.Add(contentNode); contentNode = join; } //pop group s1.Pop(); bool isGroup = true; if (s1.Count > 0 && (s1.Peek().ExpressionType == ExpressionType.Member || s1.Peek().ExpressionType == ExpressionType.Variable)) { Expression[] args = null; if (contentNode == null) { args = null; } else if (contentNode is JoinExpression) { args = ((JoinExpression)contentNode).List.ToArray(); } else { args = new Expression[] { contentNode }; } var d = s1.Peek() as MemberExpression; if (d != null) { if (d.Member.MemberType == MemberTypes.Method) { s1.Pop(); s1.Push(Expression.Call(d.Instance, d.Member.Name, args)); if (segments != null) { var seg = segments[d]; segments.Remove(d); segments[s1.Peek()] = seg; } } } else { var p = s1.Peek() as ParameterExpression; if (p.ValueType == typeof(MethodInfo)) { MethodInfo mInfo = ctx.Context.GetVariable(p.Name) as MethodInfo; s1.Pop(); s1.Push(Expression.Call(mInfo, args)); if (segments != null) { var seg = segments[p]; segments.Remove(p); segments[s1.Peek()] = seg; } } else if (p.ValueType.IsSubclassOf(typeof(Delegate))) { Type delType = p.ValueType; var mInfo = delType.GetMethod("Invoke"); s1.Push(Expression.Call(s1.Pop(), mInfo.ReturnType, args)); if (segments != null) { var seg = segments[p]; segments.Remove(p); segments[s1.Peek()] = seg; } } } isGroup = false; } if (isGroup) { GroupExpression g = new GroupExpression(contentNode); s1.Push(g); } s2.Pop(); } else if (kw.Keyword == ",") { while (s2.Count > 0 && s2.Peek().keywordInfo.Keyword != "(") { s1.Push(GetExpr(s2.Pop(), s1, s2)); } var left = PopData(s1); JoinExpression join; if (s1.Count > 0 && s1.Peek() is JoinExpression) { join = s1.Peek() as JoinExpression; } else { join = new JoinExpression(); s1.Push(join); } //join.List.Insert(0, left); join.List.Add(left); } else { if (kw.Keyword == "(") { s1.Push(Expression.Group(Expression.Null)); } while (s2.Count > 0 && kw.Priority != 0 && /* s2.Peek().Priority != 0 &&*/ s2.Peek().keywordInfo.Priority > kw.Priority) { var tmp = s2.Pop(); s1.Push(GetExpr(tmp, s1, s2)); } s2.Push(part); } } else { switch (exprPart.ToLower()) { case "true": s1.Push(Expression.True); if (segments != null) { segments[s1.Peek()] = segment; } continue; case "false": s1.Push(Expression.False); if (segments != null) { segments[s1.Peek()] = segment; } continue; case "null": s1.Push(Expression.Null); if (segments != null) { segments[s1.Peek()] = segment; } continue; //case "undefined": // s1.Push(Expression.Undefined); // continue; } if (segment.IsDigit) { if (segment.Expr.IndexOf('.') >= 0) { double f; if (double.TryParse(exprPart, out f)) { s1.Push(Expression.Constant(f)); if (segments != null) { segments[s1.Peek()] = segment; } continue; } } else { long l; if (long.TryParse(exprPart, out l)) { s1.Push(Expression.Constant(l)); if (segments != null) { segments[s1.Peek()] = segment; } continue; } } } if (s2.Count > 0 && s2.Peek().keywordInfo.Keyword == ".") { var variable = s1.Pop(); var member = GetMember(variable, null, exprPart, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.GetField | BindingFlags.GetProperty); if (member == null) { throw new Exception("not found Member :" + exprPart); } if (member.MemberType == MemberTypes.Method) { s1.Push(Expression.Member(variable, null, exprPart)); if (segments != null) { segments[s1.Peek()] = segment; } } else { s1.Push(Expression.PropertyOrField(variable, member.Name)); if (segments != null) { segments[s1.Peek()] = segment; } } s2.Pop(); } else { //variable s1.Push(Expression.Variable(GetVariableType(ctxs, exprPart), exprPart)); if (segments != null) { segments[s1.Peek()] = segment; } } // variables.Push(part); } } while (s2.Count > 0) { var tmp = s2.Pop(); s1.Push(GetExpr(tmp, s1, s2)); } result = PopData(s1); if (s1.Count > 1) { throw new Exception("expr stack error, count>1 count:" + s1.Count + ", expr:" + expr + " ,type:" + s1.Peek().ToString()); } PopScope(ctxs); //cachedExprs[expr] = result; return(result); }
protected internal override Expression VisitJoin(JoinExpression join) { if (join.JoinType == JoinType.SingleRowLeftOuterJoin) { var source = join.Right as SourceWithAliasExpression; var hs = allColumnsUsed.TryGetC(source.Alias); if (hs == null || hs.Count == 0) return Visit(join.Left); } if (join.JoinType == JoinType.OuterApply ||join.JoinType == JoinType.LeftOuterJoin) { var sql = join.Right as SelectExpression; if (sql != null && sql.IsOneRow()) { var hs = allColumnsUsed.TryGetC(sql.Alias); if (hs == null || hs.Count == 0) return Visit(join.Left); } } // visit join in reverse order Expression condition = this.Visit(join.Condition); SourceExpression right = this.VisitSource(join.Right); SourceExpression left = this.VisitSource(join.Left); if (left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(join.JoinType, left, right, condition); } return join; }
protected override Expression VisitJoin(JoinExpression join) { this.VisitSource(join.Left); this.AppendNewLine(Indentation.Same); switch (join.Join) { case JoinType.CrossJoin: sb.Append("CROSS JOIN "); break; case JoinType.InnerJoin: sb.Append("INNER JOIN "); break; case JoinType.CrossApply: sb.Append("CROSS APPLY "); break; case JoinType.OuterApply: sb.Append("OUTER APPLY "); break; case JoinType.LeftOuter: sb.Append("LEFT OUTER JOIN "); break; } this.VisitSource(join.Right); if (join.Condition != null) { this.AppendNewLine(Indentation.Inner); sb.Append("ON "); var binaryExpr = join.Condition as BinaryExpression; if (binaryExpr != null && binaryExpr.Left.NodeType == ExpressionType.New && binaryExpr.Right.NodeType == ExpressionType.New) { var leftNew = binaryExpr.Left as NewExpression; var rightNew = binaryExpr.Right as NewExpression; if (leftNew.Arguments.Count != rightNew.Arguments.Count) throw new Exception("Anonymous types in join clauses must have the same number of arguments."); for (int i = 0; i < leftNew.Arguments.Count; i++) { if (i != 0) sb.Append(" AND "); this.VisitPredicate(BinaryExpression.Equal(leftNew.Arguments[i], rightNew.Arguments[i])); sb.Append(" "); } } else { this.VisitPredicate(join.Condition); } this.Indent(Indentation.Outer); } return join; }
protected virtual Expression VisitJoin(JoinExpression join) { var left = this.VisitSource(join.Left); var right = this.VisitSource(join.Right); var condition = this.Visit(join.Condition); return this.UpdateJoin(join, join.Join, left, right, condition); }
protected JoinExpression UpdateJoin(JoinExpression join, JoinType joinType, Expression left, Expression right, Expression condition) { if (joinType != join.Join || left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(joinType, left, right, condition); } return join; }
protected virtual Expression BindJoin(Type resultType, Expression outerSource, Expression innerSource, LambdaExpression outerKey, LambdaExpression innerKey, LambdaExpression resultSelector) { ProjectionExpression outerProjection = this.VisitSequence(outerSource); ProjectionExpression innerProjection = this.VisitSequence(innerSource); this.map[outerKey.Parameters[0]] = outerProjection.Projector; Expression outerKeyExpr = this.Visit(outerKey.Body); this.map[innerKey.Parameters[0]] = innerProjection.Projector; Expression innerKeyExpr = this.Visit(innerKey.Body); this.map[resultSelector.Parameters[0]] = outerProjection.Projector; this.map[resultSelector.Parameters[1]] = innerProjection.Projector; Expression resultExpr = this.Visit(resultSelector.Body); JoinExpression join = new JoinExpression(JoinType.InnerJoin, outerProjection.Select, innerProjection.Select, outerKeyExpr.Equal(innerKeyExpr)); var alias = this.GetNextAlias(); ProjectedColumns pc = this.ProjectColumns(resultExpr, alias, outerProjection.Select.Alias, innerProjection.Select.Alias); return new ProjectionExpression( new SelectExpression(alias, pc.Columns, join, null), pc.Projector ); }
protected override Expression VisitJoin(JoinExpression join) { VisitSource(join.Left); switch (join.Join) { case JoinType.CrossJoin: sb.Append("CROSS JOIN "); break; case JoinType.InnerJoin: sb.Append("INNER JOIN "); break; case JoinType.CrossApply: sb.Append("CROSS APPLY "); break; case JoinType.OuterApply: sb.Append("OUTER APPLY "); break; case JoinType.LeftOuter: sb.Append("LEFT OUTER JOIN "); break; } VisitSource(join.Right); if (join.Condition == null) { return join; } sb.Append("ON "); VisitPredicate(join.Condition); return join; }
protected virtual bool CompareJoin(JoinExpression a, JoinExpression b) { if (a.Join != b.Join || !this.Compare(a.Left, b.Left)) return false; if (a.Join == JoinType.CrossApply || a.Join == JoinType.OuterApply) { var save = this.aliasScope; try { this.aliasScope = new ScopedDictionary<TableAlias, TableAlias>(this.aliasScope); this.MapAliases(a.Left, b.Left); return this.Compare(a.Right, b.Right) && this.Compare(a.Condition, b.Condition); } finally { this.aliasScope = save; } } else { return this.Compare(a.Right, b.Right) && this.Compare(a.Condition, b.Condition); } }
public Expression Bind(PipelineExpression pipeline, PipelineBindingContext bindingContext, MethodCallExpression node, IEnumerable <Expression> arguments) { var args = arguments.ToList(); var joined = bindingContext.Bind(args[0]) as CollectionExpression; if (joined == null) { throw new NotSupportedException("The joined collection cannot have any qualifiers."); } var sourceKeySelectorLambda = ExpressionHelper.GetLambda(args[1]); bindingContext.AddExpressionMapping(sourceKeySelectorLambda.Parameters[0], pipeline.Projector); var sourceKeySelector = bindingContext.Bind(sourceKeySelectorLambda.Body) as IFieldExpression; if (sourceKeySelector == null) { var message = string.Format("Unable to determine the serialization information for the outer key selector in the tree: {0}", node.ToString()); throw new NotSupportedException(message); } var joinedArraySerializer = joined.Serializer as IBsonArraySerializer; BsonSerializationInfo joinedItemSerializationInfo; if (joinedArraySerializer == null || !joinedArraySerializer.TryGetItemSerializationInfo(out joinedItemSerializationInfo)) { var message = string.Format("Unable to determine the serialization information for the inner collection: {0}", node.ToString()); throw new NotSupportedException(message); } var joinedKeySelectorLambda = ExpressionHelper.GetLambda(args[2]); var joinedDocument = new DocumentExpression(joinedItemSerializationInfo.Serializer); bindingContext.AddExpressionMapping(joinedKeySelectorLambda.Parameters[0], joinedDocument); var joinedKeySelector = bindingContext.Bind(joinedKeySelectorLambda.Body) as IFieldExpression; if (joinedKeySelector == null) { var message = string.Format("Unable to determine the serialization information for the inner key selector in the tree: {0}", node.ToString()); throw new NotSupportedException(message); } var resultSelectorLambda = ExpressionHelper.GetLambda(args[3]); var sourceSerializer = pipeline.Projector.Serializer; var joinedSerializer = node.Method.Name == "GroupJoin" ? joined.Serializer : joinedItemSerializationInfo.Serializer; var sourceDocument = new DocumentExpression(sourceSerializer); var joinedField = new FieldExpression( resultSelectorLambda.Parameters[1].Name, joinedSerializer); bindingContext.AddExpressionMapping( resultSelectorLambda.Parameters[0], sourceDocument); bindingContext.AddExpressionMapping( resultSelectorLambda.Parameters[1], joinedField); var resultSelector = bindingContext.Bind(resultSelectorLambda.Body); Expression source; if (node.Method.Name == "GroupJoin") { source = new GroupJoinExpression( node.Type, pipeline.Source, joined, (Expression)sourceKeySelector, (Expression)joinedKeySelector, resultSelectorLambda.Parameters[1].Name); } else { source = new JoinExpression( node.Type, pipeline.Source, joined, (Expression)sourceKeySelector, (Expression)joinedKeySelector, resultSelectorLambda.Parameters[1].Name); } SerializationExpression projector; var newResultSelector = resultSelector as NewExpression; if (newResultSelector != null && newResultSelector.Arguments[0] == sourceDocument && newResultSelector.Arguments[1] == joinedField) { Func <object, object, object> creator = (s, j) => Activator.CreateInstance(resultSelector.Type, s, j); var serializer = (IBsonSerializer)Activator.CreateInstance( typeof(JoinSerializer <>).MakeGenericType(resultSelector.Type), sourceSerializer, newResultSelector.Members[0].Name, joinedSerializer, newResultSelector.Members[1].Name, resultSelectorLambda.Parameters[1].Name, creator); projector = new DocumentExpression(serializer); } else { projector = bindingContext.BindProjector(ref resultSelector); source = new SelectExpression( source, "__i", // since this is a top-level pipeline, this doesn't matter resultSelector); } return(new PipelineExpression( source, projector)); }
private SelectExpression GetCountSelectExpression(SelectExpression select) { BinaryExpression binaryExpression = select.Where as BinaryExpression; if (binaryExpression != null) { ScalarExpression scalarExpression = binaryExpression.Left as ScalarExpression; if (scalarExpression != null) { SelectExpression selectCount = scalarExpression.Select as SelectExpression; if (selectCount != null && selectCount.Columns.Count == 1) { AggregateExpression aggregateExpression = (AggregateExpression)selectCount.Columns[0].Expression; if (aggregateExpression != null && aggregateExpression.AggregateName == "Count") { BinaryExpression where = selectCount.Where as BinaryExpression; if (where != null) { ColumnExpression columnExpression = where.Left as ColumnExpression; if (columnExpression != null) { TableAlias tableAlias = new TableAlias(); TableExpression tableExpression = (TableExpression)select.From; tableExpression = new TableExpression(tableAlias, tableExpression.Entity, tableExpression.Name); columnExpression = new ColumnExpression(columnExpression.Type, columnExpression.QueryType, tableAlias, columnExpression.Name); ColumnDeclaration columnDeclaration = new ColumnDeclaration(string.Empty, columnExpression, columnExpression.QueryType); BinaryExpression where2 = Expression.MakeBinary(where.NodeType, where.Left, columnExpression); selectCount = new SelectExpression(selectCount.Alias, selectCount.Columns, selectCount.From, where2); List <ColumnDeclaration> columns = new List <ColumnDeclaration> { new ColumnDeclaration("CountValue", new ScalarExpression(selectCount.Columns[0].Expression.Type, selectCount), selectCount.Columns[0].QueryType), columnDeclaration }; selectCount = new SelectExpression(tableAlias, columns.ToReadOnly(), tableExpression, null, selectCount.OrderBy, null, selectCount.IsDistinct, selectCount.Skip, selectCount.Take, selectCount.IsReverse); ColumnExpression countValueColumnExpression = new ColumnExpression(selectCount.Columns[0].Expression.Type, selectCount.Columns[0].QueryType, tableAlias, "CountValue"); SelectExpression newSelect = new SelectExpression(select.Alias, select.Columns, select.From, null, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take, select.IsReverse); JoinExpression joinExpression = new JoinExpression(JoinType.InnerJoin, newSelect, selectCount, Expression.MakeBinary(ExpressionType.Equal, columnExpression, where.Right)); select = new SelectExpression(newSelect.Alias, newSelect.Columns, joinExpression, Expression.MakeBinary(binaryExpression.NodeType, countValueColumnExpression, binaryExpression.Right), newSelect.OrderBy, newSelect.GroupBy, newSelect.IsDistinct, newSelect.Skip, newSelect.Take, newSelect.IsReverse); return(select); } } } } } } return(null); }
protected override Expression VisitJoin(JoinExpression join) { if (join.Join == JoinType.CrossJoin) { this.VisitJoinLeft(join.Left); this.Append(", "); this.VisitJoinRight(join.Right); return join; } return base.VisitJoin(join); }
public void Compile(JoinExpression query) { }
protected override Expression VisitJoin(JoinExpression join) { expressions.Add(join); return(base.VisitJoin(join)); }
public static ISelectStatement FullJoin(this ISelectStatement select, ITableExpression table, IFilterExpression on) { IJoinExpression join = new JoinExpression(Operator.FullJoin, table, on); return(Join(select, join)); }
public Expression VisitJoin(JoinExpression expression) { JoinVisited = true; return(expression); }
protected override Expression VisitJoin(JoinExpression join) { this.VisitJoinLeft(join.Left); this.WriteLine(Indentation.Same); switch (join.Join) { case JoinType.CrossJoin: this.Write("CROSS JOIN "); break; case JoinType.InnerJoin: this.Write("INNER JOIN "); break; case JoinType.CrossApply: this.Write("CROSS APPLY "); break; case JoinType.OuterApply: this.Write("OUTER APPLY "); break; case JoinType.LeftOuter: case JoinType.SingletonLeftOuter: this.Write("LEFT OUTER JOIN "); break; } this.VisitJoinRight(join.Right); if (join.Condition != null) { this.WriteLine(Indentation.Inner); this.Write("ON "); this.VisitPredicate(join.Condition); this.Indent(Indentation.Outer); } return join; }
protected override Expression VisitJoin(JoinExpression join) { SourceExpression left = this.VisitSource(join.Left); ReadOnlyCollection<OrderExpression> leftOrders = this.gatheredOrderings; this.gatheredOrderings = null; SourceExpression right = join.Right is TableExpression ? join.Right : this.VisitSource(join.Right); this.PrependOrderings(leftOrders); Expression condition = this.Visit(join.Condition); if (left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(join.JoinType, left, right, condition); } return join; }
public static ISelectStatement Join(this ISelectStatement select, ITableExpression table, IFilterExpression on, IJoinOperator joinOperator) { IJoinExpression join = new JoinExpression(joinOperator, table, on); return(Join(select, join)); }
protected internal override Expression VisitJoin(JoinExpression join) { SourceExpression left = this.VisitSource(join.Left); SourceExpression right = this.VisitSource(join.Right); Expression condition = MakeSqlCondition(this.Visit(join.Condition)); if (left != join.Left || right != join.Right || condition != join.Condition) { return new JoinExpression(join.JoinType, left, right, condition); } return join; }