static void BuildTake(ExpressionBuilder builder, IBuildContext sequence, ISqlExpression expr) { var sql = sequence.SelectQuery; sql.Select.Take(expr); if (sql.Select.SkipValue != null && builder.DataContextInfo.SqlProviderFlags.IsTakeSupported && !builder.DataContextInfo.SqlProviderFlags.GetIsSkipSupportedFlag(sql)) { if (sql.Select.SkipValue is SqlParameter && sql.Select.TakeValue is SqlValue) { var skip = (SqlParameter)sql.Select.SkipValue; var parm = (SqlParameter)sql.Select.SkipValue.Clone(new Dictionary <ICloneableElement, ICloneableElement>(), _ => true); parm.SetTakeConverter((int)((SqlValue)sql.Select.TakeValue).Value); sql.Select.Take(parm); var ep = (from pm in builder.CurrentSqlParameters where pm.SqlParameter == skip select pm).First(); ep = new ParameterAccessor { Expression = ep.Expression, Accessor = ep.Accessor, SqlParameter = parm }; builder.CurrentSqlParameters.Add(ep); } else { sql.Select.Take(builder.Convert( sequence, new SqlBinaryExpression(typeof(int), sql.Select.SkipValue, "+", sql.Select.TakeValue, Precedence.Additive))); } } if (!builder.DataContextInfo.SqlProviderFlags.GetAcceptsTakeAsParameterFlag(sql)) { var p = sql.Select.TakeValue as SqlParameter; if (p != null) { p.IsQueryParameter = false; } } }
private void BuildAssociationCondition(ExpressionBuilder builder, TableContext parent, AssociationDescriptor association, SqlSearchCondition condition) { for (var i = 0; i < association.ThisKey.Length; i++) { if (!parent.SqlTable.Fields.TryGetValue(association.ThisKey[i], out var field1)) { throw new LinqException("Association key '{0}' not found for type '{1}.", association.ThisKey[i], parent.ObjectType); } if (!SqlTable.Fields.TryGetValue(association.OtherKey[i], out var field2)) { throw new LinqException("Association key '{0}' not found for type '{1}.", association.OtherKey[i], ObjectType); } ISqlPredicate predicate = new SqlPredicate.ExprExpr( field1, SqlPredicate.Operator.Equal, field2); predicate = builder.Convert(parent, predicate); condition.Conditions.Add(new SqlCondition(false, predicate)); } if (ObjectType != OriginalType) { var predicate = Builder.MakeIsPredicate(this, OriginalType); if (predicate.GetType() != typeof(SqlPredicate.Expr)) { condition.Conditions.Add(new SqlCondition(false, predicate)); } } RegularConditionCount = condition.Conditions.Count; ExpressionPredicate = Association.GetPredicate(parent.ObjectType, ObjectType); if (ExpressionPredicate != null) { ExpressionPredicate = (LambdaExpression)Builder.ConvertExpressionTree(ExpressionPredicate); var expr = Builder.ConvertExpression(ExpressionPredicate.Body.Unwrap()); Builder.BuildSearchCondition( new ExpressionContext(parent.Parent, new IBuildContext[] { parent, this }, ExpressionPredicate), expr, condition.Conditions, false); } }
static void BuildSubQueryJoin( ExpressionBuilder builder, IBuildContext outerKeyContext, Expression outerKeySelector, Expression innerKeySelector, IBuildContext subQueryKeyContext, SelectQuery subQuerySelect) { var predicate = builder.ConvertObjectComparison( ExpressionType.Equal, outerKeyContext, outerKeySelector, subQueryKeyContext, innerKeySelector); if (predicate == null) { predicate = new SqlPredicate.ExprExpr( builder.ConvertToSql(outerKeyContext, outerKeySelector), SqlPredicate.Operator.Equal, builder.ConvertToSql(subQueryKeyContext, innerKeySelector)); predicate = builder.Convert(outerKeyContext, predicate); } subQuerySelect.Where.SearchCondition.Conditions.Add(new SqlCondition(false, predicate)); }
internal static void BuildJoin( ExpressionBuilder builder, SqlSearchCondition condition, IBuildContext outerKeyContext, Expression outerKeySelector, IBuildContext innerKeyContext, Expression innerKeySelector) { var predicate = builder.ConvertObjectComparison( ExpressionType.Equal, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector); if (predicate == null) { predicate = new SqlPredicate.ExprExpr( builder.ConvertToSql(outerKeyContext, outerKeySelector), SqlPredicate.Operator.Equal, builder.ConvertToSql(innerKeyContext, innerKeySelector)); predicate = builder.Convert(outerKeyContext, predicate); } condition.Conditions.Add(new SqlCondition(false, predicate)); }
static void BuildJoin( ExpressionBuilder builder, SelectQuery.FromClause.Join join, IBuildContext outerKeyContext, Expression outerKeySelector, IBuildContext innerKeyContext, Expression innerKeySelector) { var predicate = builder.ConvertObjectComparison( ExpressionType.Equal, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector); if (predicate == null) { predicate = new SelectQuery.Predicate.ExprExpr( builder.ConvertToSql(outerKeyContext, outerKeySelector), SelectQuery.Predicate.Operator.Equal, builder.ConvertToSql(innerKeyContext, innerKeySelector)); predicate = builder.Convert(outerKeyContext, predicate); } join.JoinedTable.Condition.Conditions.Add(new SelectQuery.Condition(false, predicate)); }
public AssociatedTableContext( [JetBrains.Annotations.NotNull] ExpressionBuilder builder, [JetBrains.Annotations.NotNull] TableContext parent, [JetBrains.Annotations.NotNull] AssociationDescriptor association ) : base(builder, parent.SelectQuery) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (parent == null) { throw new ArgumentNullException(nameof(parent)); } if (association == null) { throw new ArgumentNullException(nameof(association)); } var type = association.MemberInfo.GetMemberType(); var left = association.CanBeNull; if (typeof(IEnumerable).IsSameOrParentOf(type)) { var eTypes = type.GetGenericArguments(typeof(IEnumerable <>)); type = eTypes != null && eTypes.Length > 0 ? eTypes[0] : type.GetListItemType(); IsList = true; } OriginalType = type; ObjectType = GetObjectType(); EntityDescriptor = Builder.MappingSchema.GetEntityDescriptor(ObjectType); InheritanceMapping = EntityDescriptor.InheritanceMapping; SqlTable = new SqlTable(builder.MappingSchema, ObjectType); Association = association; ParentAssociation = parent; SqlJoinedTable join; var queryMethod = Association.GetQueryMethod(parent.ObjectType, ObjectType); if (queryMethod != null) { var dcParam = queryMethod.Parameters[1]; var resultParam = Expression.Parameter(ObjectType); Expression dcConst = Expression.Constant(builder.DataContext); if (dcParam.Type != typeof(IDataContext)) { dcConst = Expression.Convert(dcConst, dcParam.Type); } var body = queryMethod.Body.Transform(e => e == dcParam ? dcConst : e); body = Expression.Convert(body, typeof(IEnumerable <>).MakeGenericType(ObjectType)); queryMethod = Expression.Lambda(body, queryMethod.Parameters[0]); var selectManyMethodInfo = _selectManyMethodInfo.MakeGenericMethod(parent.ObjectType, ObjectType, ObjectType); var resultLamba = Expression.Lambda(resultParam, Expression.Parameter(parent.ObjectType), resultParam); var selectManyMethod = Expression.Call(null, selectManyMethodInfo, parent.Expression, queryMethod, resultLamba); var ownerTableSource = SelectQuery.From.Tables[0]; _innerContext = builder.BuildSequence(new BuildInfo(this, selectManyMethod, new SelectQuery()) { IsAssociationBuilt = true }); var associationQuery = _innerContext.SelectQuery; if (associationQuery.Select.From.Tables.Count < 1) { throw new LinqToDBException("Invalid association query. It is not possible to inline query."); } var foundIndex = associationQuery.Select.From.Tables.FindIndex(t => t.Source is SqlTable sqlTable && QueryHelper.IsEqualTables(sqlTable, parent.SqlTable)); if (foundIndex < 0) { throw new LinqToDBException("Invalid association query. It is not possible to inline query. Can not find owner table."); } var sourceToReplace = associationQuery.Select.From.Tables[foundIndex]; if (left) { foreach (var joinedTable in sourceToReplace.Joins) { if (joinedTable.JoinType == JoinType.Inner) { joinedTable.JoinType = JoinType.Left; } else if (joinedTable.JoinType == JoinType.CrossApply) { joinedTable.JoinType = JoinType.OuterApply; } joinedTable.IsWeak = true; } } ownerTableSource.Joins.AddRange(sourceToReplace.Joins); // prepare fields mapping to replace fields that will be generated by association query _replaceMap = ((SqlTable)sourceToReplace.Source).Fields.Values.ToDictionary(f => (ISqlExpression)f, f => parent.SqlTable.Fields[f.Name]); ownerTableSource.Walk(false, e => { if (_replaceMap.TryGetValue(e, out var newField)) { return(newField); } return(e); }); ParentAssociationJoin = sourceToReplace.Joins.FirstOrDefault(); join = ParentAssociationJoin; // add rest of tables SelectQuery.From.Tables.AddRange(associationQuery.Select.From.Tables.Where(t => t != sourceToReplace)); } else { var psrc = parent.SelectQuery.From[parent.SqlTable]; join = left ? SqlTable.WeakLeftJoin().JoinedTable : SqlTable.WeakInnerJoin().JoinedTable; ParentAssociationJoin = join; psrc.Joins.Add(join); for (var i = 0; i < association.ThisKey.Length; i++) { if (!parent.SqlTable.Fields.TryGetValue(association.ThisKey[i], out var field1)) { throw new LinqException("Association key '{0}' not found for type '{1}.", association.ThisKey[i], parent.ObjectType); } if (!SqlTable.Fields.TryGetValue(association.OtherKey[i], out var field2)) { throw new LinqException("Association key '{0}' not found for type '{1}.", association.OtherKey[i], ObjectType); } // join.Field(field1).Equal.Field(field2); ISqlPredicate predicate = new SqlPredicate.ExprExpr( field1, SqlPredicate.Operator.Equal, field2); predicate = builder.Convert(parent, predicate); join.Condition.Conditions.Add(new SqlCondition(false, predicate)); } if (ObjectType != OriginalType) { var predicate = Builder.MakeIsPredicate(this, OriginalType); if (predicate.GetType() != typeof(SqlPredicate.Expr)) { join.Condition.Conditions.Add(new SqlCondition(false, predicate)); } } RegularConditionCount = join.Condition.Conditions.Count; ExpressionPredicate = Association.GetPredicate(parent.ObjectType, ObjectType); if (ExpressionPredicate != null) { ExpressionPredicate = (LambdaExpression)Builder.ConvertExpressionTree(ExpressionPredicate); var expr = Builder.ConvertExpression(ExpressionPredicate.Body.Unwrap()); Builder.BuildSearchCondition( new ExpressionContext(parent.Parent, new IBuildContext[] { parent, this }, ExpressionPredicate), expr, join.Condition.Conditions, false); } } if (!association.AliasName.IsNullOrEmpty() && join != null) { join.Table.Alias = association.AliasName; } else { if (!Common.Configuration.Sql.AssociationAlias.IsNullOrEmpty() && join != null) { join.Table.Alias = string.Format(Common.Configuration.Sql.AssociationAlias, association.MemberInfo.Name); } } Init(false); }
public AssociatedTableContext( [JetBrains.Annotations.NotNull] ExpressionBuilder builder, [JetBrains.Annotations.NotNull] TableContext parent, [JetBrains.Annotations.NotNull] AssociationDescriptor association ) : base(builder, parent.SelectQuery) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (parent == null) { throw new ArgumentNullException(nameof(parent)); } if (association == null) { throw new ArgumentNullException(nameof(association)); } var type = association.MemberInfo.GetMemberType(); var left = association.CanBeNull; if (typeof(IEnumerable).IsSameOrParentOf(type)) { var eTypes = type.GetGenericArguments(typeof(IEnumerable <>)); type = eTypes != null && eTypes.Length > 0 ? eTypes[0] : type.GetListItemType(); IsList = true; } OriginalType = type; ObjectType = GetObjectType(); EntityDescriptor = Builder.MappingSchema.GetEntityDescriptor(ObjectType); InheritanceMapping = EntityDescriptor.InheritanceMapping; SqlTable = new SqlTable(builder.MappingSchema, ObjectType); var psrc = parent.SelectQuery.From[parent.SqlTable]; var join = left ? SqlTable.WeakLeftJoin() : SqlTable.WeakInnerJoin(); if (!association.AliasName.IsNullOrEmpty()) { join.JoinedTable.Table.Alias = association.AliasName; } else { if (!Common.Configuration.Sql.AssociationAlias.IsNullOrEmpty()) { join.JoinedTable.Table.Alias = string.Format(Common.Configuration.Sql.AssociationAlias, association.MemberInfo.Name); } } Association = association; ParentAssociation = parent; ParentAssociationJoin = join.JoinedTable; psrc.Joins.Add(join.JoinedTable); for (var i = 0; i < association.ThisKey.Length; i++) { if (!parent.SqlTable.Fields.TryGetValue(association.ThisKey[i], out var field1)) { throw new LinqException("Association key '{0}' not found for type '{1}.", association.ThisKey[i], parent.ObjectType); } if (!SqlTable.Fields.TryGetValue(association.OtherKey[i], out var field2)) { throw new LinqException("Association key '{0}' not found for type '{1}.", association.OtherKey[i], ObjectType); } // join.Field(field1).Equal.Field(field2); ISqlPredicate predicate = new SqlPredicate.ExprExpr( field1, SqlPredicate.Operator.Equal, field2); predicate = builder.Convert(parent, predicate); join.JoinedTable.Condition.Conditions.Add(new SqlCondition(false, predicate)); } if (ObjectType != OriginalType) { var predicate = Builder.MakeIsPredicate(this, OriginalType); if (predicate.GetType() != typeof(SqlPredicate.Expr)) { join.JoinedTable.Condition.Conditions.Add(new SqlCondition(false, predicate)); } } RegularConditionCount = join.JoinedTable.Condition.Conditions.Count; ExpressionPredicate = Association.GetPredicate(parent.ObjectType, ObjectType); if (ExpressionPredicate != null) { ExpressionPredicate = (LambdaExpression)Builder.ConvertExpressionTree(ExpressionPredicate); var expr = Builder.ConvertExpression(ExpressionPredicate.Body.Unwrap()); Builder.BuildSearchCondition( new ExpressionContext(parent.Parent, new IBuildContext[] { parent, this }, ExpressionPredicate), expr, join.JoinedTable.Condition.Conditions, false); } Init(false); }