internal SqlExpression TranslateLinkIsNull(SqlUnary expr) { System.Diagnostics.Debug.Assert(expr.NodeType == SqlNodeType.IsNull || expr.NodeType == SqlNodeType.IsNotNull); SqlLink link = expr.Operand as SqlLink; if (!(link != null && link.Member.IsAssociation && link.Member.Association.IsForeignKey)) { return(expr); } List <SqlExpression> exprs = link.KeyExpressions; System.Diagnostics.Debug.Assert(exprs.Count > 0); SqlExpression exp = null; SqlNodeType combo = (expr.NodeType == SqlNodeType.IsNull) ? SqlNodeType.Or : SqlNodeType.And; for (int i = 0, n = exprs.Count; i < n; i++) { SqlExpression compare = sql.Unary(expr.NodeType, sql.DoNotVisitExpression(exprs[i]), expr.SourceExpression); if (exp == null) { exp = compare; } else { exp = sql.Binary(combo, exp, compare); } } return(exp); }
internal SqlNode TranslateLink(SqlLink link, List <SqlExpression> keyExpressions, bool asExpression) { var member = link.Member; if (member.IsAssociation) { var otherType = member.Association.OtherType; var type = otherType.InheritanceRoot.Type; var table = services.Context.GetTable(type); Expression otherSource = new LinkedTableExpression(link, table, typeof(IQueryable <>).MakeGenericType(otherType.Type)); var array = new Expression[keyExpressions.Count]; for (var i = 0; i < keyExpressions.Count; i++) { var metaDataMember = member.Association.OtherKey[i]; var memberType = TypeSystem.GetMemberType(metaDataMember.Member); array[i] = InternalExpression.Known(keyExpressions[i], memberType); } var thisInstance = (link.Expression != null) ? ((Expression)InternalExpression.Known(link.Expression)) : ((Expression)Expression.Constant(null, link.Member.Member.DeclaringType)); var node = TranslateAssociation(services.Context, member.Association, otherSource, array, thisInstance); var queryConverter = new QueryConverter(services, typeProvider, this, sql); var sqlSelect = (SqlSelect)queryConverter.ConvertInner(node, link.SourceExpression); SqlNode result = sqlSelect; if (asExpression) { result = ((!member.Association.IsMany) ? new SqlSubSelect(SqlNodeType.Element, link.ClrType, link.SqlType, sqlSelect) : new SqlSubSelect(SqlNodeType.Multiset, link.ClrType, link.SqlType, sqlSelect)); } return(result); } return(link.Expansion); }
internal override SqlNode VisitLink(SqlLink link) { // don't visit expansion... for (int i = 0, n = link.KeyExpressions.Count; i < n; i++) { link.KeyExpressions[i] = this.VisitExpression(link.KeyExpressions[i]); } return(link); }
internal virtual SqlNode VisitLink(SqlLink link) { // Don't visit the link's Expansion for (int i = 0, n = link.KeyExpressions.Count; i < n; i++) { link.KeyExpressions[i] = this.VisitExpression(link.KeyExpressions[i]); } return(link); }
internal override SqlNode VisitLink(SqlLink link) { SqlExpression expansion = this.VisitExpression(link.Expansion); SqlExpression[] exprs = new SqlExpression[link.KeyExpressions.Count]; for (int i = 0, n = exprs.Length; i < n; i++) { exprs[i] = this.VisitExpression(link.KeyExpressions[i]); } return(new SqlLink(link.Id, link.RowType, link.ClrType, link.SqlType, link.Expression, link.Member, exprs, expansion, link.SourceExpression)); }
internal SqlExpression TranslateLinkEquals(SqlBinary bo) { SqlLink link1 = bo.Left as SqlLink; SqlLink link2 = bo.Right as SqlLink; if ((link1 != null && link1.Member.IsAssociation && link1.Member.Association.IsForeignKey) || (link2 != null && link2.Member.IsAssociation && link2.Member.Association.IsForeignKey)) { return(this.TranslateEquals(bo)); } return(bo); }
internal override SqlNode VisitLink(SqlLink link) { // Don't visit the Expression/Expansion for this link. // Any additional external refs in these expressions // should be ignored SqlExpression[] exprs = new SqlExpression[link.KeyExpressions.Count]; for (int i = 0, n = exprs.Length; i < n; i++) { exprs[i] = this.VisitExpression(link.KeyExpressions[i]); } return(new SqlLink(new object(), link.RowType, link.ClrType, link.SqlType, null, link.Member, exprs, null, link.SourceExpression)); }
internal SqlSelect BuildDefaultQuery(MetaType rowType, bool allowDeferred, SqlLink link, Expression source) { if (rowType.HasInheritance && rowType.InheritanceRoot != rowType) { throw Error.ArgumentWrongValue("rowType"); } var sqlTable = sql.Table(rowType.Table, rowType, source); var sqlAlias = new SqlAlias(sqlTable); var item = new SqlAliasRef(sqlAlias); var selection = BuildProjection(item, sqlTable.RowType, allowDeferred, link, source); return(new SqlSelect(selection, sqlAlias, source)); }
internal SqlNode TranslateLink(SqlLink link, List <SqlExpression> keyExpressions, bool asExpression) { MetaDataMember mm = link.Member; if (mm.IsAssociation) { // Create the row source. MetaType otherType = mm.Association.OtherType; Type tableType = otherType.InheritanceRoot.Type; ITable table = this.services.Context.GetTable(tableType); Expression source = new LinkedTableExpression(link, table, typeof(IQueryable <>).MakeGenericType(otherType.Type)); // Build key expression nodes. Expression[] keyExprs = new Expression[keyExpressions.Count]; for (int i = 0; i < keyExpressions.Count; ++i) { MetaDataMember metaMember = mm.Association.OtherKey[i]; Type memberType = TypeSystem.GetMemberType(metaMember.Member); keyExprs[i] = InternalExpression.Known(keyExpressions[i], memberType); } Expression lex = link.Expression != null ? (Expression)InternalExpression.Known(link.Expression) : (Expression)Expression.Constant(null, link.Member.Member.DeclaringType); Expression expr = TranslateAssociation(this.services.Context, mm.Association, source, keyExprs, lex); // Convert QueryConverter qc = new QueryConverter(this.services, this.typeProvider, this, this.sql); SqlSelect sel = (SqlSelect)qc.ConvertInner(expr, link.SourceExpression); // Turn it into an expression is necessary SqlNode result = sel; if (asExpression) { if (mm.Association.IsMany) { result = new SqlSubSelect(SqlNodeType.Multiset, link.ClrType, link.SqlType, sel); } else { result = new SqlSubSelect(SqlNodeType.Element, link.ClrType, link.SqlType, sel); } } return(result); } else { System.Diagnostics.Debug.Assert(link.Expansion != null); System.Diagnostics.Debug.Assert(link.KeyExpressions == keyExpressions); // deferred expression already defined... return(link.Expansion); } }
internal override SqlNode VisitLink(SqlLink link) { SqlExpression[] exprs = new SqlExpression[link.KeyExpressions.Count]; for (int i = 0, n = exprs.Length; i < n; i++) { exprs[i] = this.VisitExpression(link.KeyExpressions[i]); } SqlLink newLink = new SqlLink(new object(), link.RowType, link.ClrType, link.SqlType, null, link.Member, exprs, null, link.SourceExpression); this.nodeMap[link] = newLink; // break the potential cyclic tree by visiting these after adding to the map newLink.Expression = this.VisitExpression(link.Expression); newLink.Expansion = this.VisitExpression(link.Expansion); return(newLink); }
internal SqlSelect BuildDefaultQuery(MetaType rowType, bool allowDeferred, SqlLink link, Expression source) { System.Diagnostics.Debug.Assert(rowType != null && rowType.Table != null); if (rowType.HasInheritance && rowType.InheritanceRoot != rowType) { // RowType is expected to be an inheritance root. throw Error.ArgumentWrongValue("rowType"); } SqlTable table = sql.Table(rowType.Table, rowType, source); SqlAlias tableAlias = new SqlAlias(table); SqlAliasRef tableAliasRef = new SqlAliasRef(tableAlias); SqlExpression projection = this.BuildProjection(tableAliasRef, table.RowType, allowDeferred, link, source); return(new SqlSelect(projection, tableAlias, source)); }
internal override SqlNode VisitLink(SqlLink link) { var array = new SqlExpression[link.KeyExpressions.Count]; var i = 0; for (var num = array.Length; i < num; i++) { array[i] = VisitExpression(link.KeyExpressions[i]); } var sqlLink = new SqlLink(new object(), link.RowType, link.ClrType, link.SqlType, null, link.Member, array, null, link.SourceExpression); nodeMap[link] = sqlLink; sqlLink.Expression = VisitExpression(link.Expression); sqlLink.Expansion = VisitExpression(link.Expansion); return(sqlLink); }
private SqlNew BuildProjectionInternal(SqlExpression item, MetaType rowType, IEnumerable <MetaDataMember> members, bool allowDeferred, SqlLink link, Expression source) { List <SqlMemberAssign> bindings = new List <SqlMemberAssign>(); foreach (MetaDataMember mm in members) { if (allowDeferred && (mm.IsAssociation || mm.IsDeferred)) { // check if this member is the reverse association to the supplied link if (link != null && mm != link.Member && mm.IsAssociation && mm.MappedName == link.Member.MappedName && !mm.Association.IsMany && !IsPreloaded(link.Member.Member)) { // place a new link here with an expansion that is previous link's root expression. // this will allow joins caused by reverse association references to 'melt' away. :-) SqlLink mlink = this.BuildLink(item, mm, source); mlink.Expansion = link.Expression; bindings.Add(new SqlMemberAssign(mm.Member, mlink)); } else { bindings.Add(new SqlMemberAssign(mm.Member, this.BuildLink(item, mm, source))); } } else if (!mm.IsAssociation) { bindings.Add(new SqlMemberAssign(mm.Member, sql.Member(item, mm))); } } ConstructorInfo cons = rowType.Type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, System.Type.EmptyTypes, null); if (cons == null) { throw Error.MappedTypeMustHaveDefaultConstructor(rowType.Type); } return(sql.New(rowType, cons, null, null, bindings, source)); }
internal static bool AreEqual(SqlNode node1, SqlNode node2) { if (node1 == node2) { return(true); } if (node1 == null || node2 == null) { return(false); } if (node1.NodeType == SqlNodeType.SimpleCase) { node1 = UnwrapTrivialCaseExpression((SqlSimpleCase)node1); } if (node2.NodeType == SqlNodeType.SimpleCase) { node2 = UnwrapTrivialCaseExpression((SqlSimpleCase)node2); } if (node1.NodeType != node2.NodeType) { // allow expression sets to compare against single expressions if (node1.NodeType == SqlNodeType.ExprSet) { SqlExprSet eset = (SqlExprSet)node1; for (int i = 0, n = eset.Expressions.Count; i < n; i++) { if (AreEqual(eset.Expressions[i], node2)) { return(true); } } } else if (node2.NodeType == SqlNodeType.ExprSet) { SqlExprSet eset = (SqlExprSet)node2; for (int i = 0, n = eset.Expressions.Count; i < n; i++) { if (AreEqual(node1, eset.Expressions[i])) { return(true); } } } return(false); } if (node1.Equals(node2)) { return(true); } switch (node1.NodeType) { case SqlNodeType.Not: case SqlNodeType.Not2V: case SqlNodeType.Negate: case SqlNodeType.BitNot: case SqlNodeType.IsNull: case SqlNodeType.IsNotNull: case SqlNodeType.Count: case SqlNodeType.Max: case SqlNodeType.Min: case SqlNodeType.Sum: case SqlNodeType.Avg: case SqlNodeType.Stddev: case SqlNodeType.ValueOf: case SqlNodeType.OuterJoinedValue: case SqlNodeType.ClrLength: return(AreEqual(((SqlUnary)node1).Operand, ((SqlUnary)node2).Operand)); case SqlNodeType.Add: case SqlNodeType.Sub: case SqlNodeType.Mul: case SqlNodeType.Div: case SqlNodeType.Mod: case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.And: case SqlNodeType.Or: case SqlNodeType.GE: case SqlNodeType.GT: case SqlNodeType.LE: case SqlNodeType.LT: case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: case SqlNodeType.Concat: SqlBinary firstNode = (SqlBinary)node1; SqlBinary secondNode = (SqlBinary)node2; return(AreEqual(firstNode.Left, secondNode.Left) && AreEqual(firstNode.Right, secondNode.Right)); case SqlNodeType.Convert: case SqlNodeType.Treat: { SqlUnary sun1 = (SqlUnary)node1; SqlUnary sun2 = (SqlUnary)node2; return(sun1.ClrType == sun2.ClrType && sun1.SqlType == sun2.SqlType && AreEqual(sun1.Operand, sun2.Operand)); } case SqlNodeType.Between: { SqlBetween b1 = (SqlBetween)node1; SqlBetween b2 = (SqlBetween)node1; return(AreEqual(b1.Expression, b2.Expression) && AreEqual(b1.Start, b2.Start) && AreEqual(b1.End, b2.End)); } case SqlNodeType.Parameter: return(node1 == node2); case SqlNodeType.Alias: return(AreEqual(((SqlAlias)node1).Node, ((SqlAlias)node2).Node)); case SqlNodeType.AliasRef: return(AreEqual(((SqlAliasRef)node1).Alias, ((SqlAliasRef)node2).Alias)); case SqlNodeType.Column: SqlColumn col1 = (SqlColumn)node1; SqlColumn col2 = (SqlColumn)node2; return(col1 == col2 || (col1.Expression != null && col2.Expression != null && AreEqual(col1.Expression, col2.Expression))); case SqlNodeType.Table: return(((SqlTable)node1).MetaTable == ((SqlTable)node2).MetaTable); case SqlNodeType.Member: return((((SqlMember)node1).Member == ((SqlMember)node2).Member) && AreEqual(((SqlMember)node1).Expression, ((SqlMember)node2).Expression)); case SqlNodeType.ColumnRef: SqlColumnRef cref1 = (SqlColumnRef)node1; SqlColumnRef cref2 = (SqlColumnRef)node2; return(GetBaseColumn(cref1) == GetBaseColumn(cref2)); case SqlNodeType.Value: return(Object.Equals(((SqlValue)node1).Value, ((SqlValue)node2).Value)); case SqlNodeType.TypeCase: { SqlTypeCase c1 = (SqlTypeCase)node1; SqlTypeCase c2 = (SqlTypeCase)node2; if (!AreEqual(c1.Discriminator, c2.Discriminator)) { return(false); } if (c1.Whens.Count != c2.Whens.Count) { return(false); } for (int i = 0, c = c1.Whens.Count; i < c; ++i) { if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match)) { return(false); } if (!AreEqual(c1.Whens[i].TypeBinding, c2.Whens[i].TypeBinding)) { return(false); } } return(true); } case SqlNodeType.SearchedCase: { SqlSearchedCase c1 = (SqlSearchedCase)node1; SqlSearchedCase c2 = (SqlSearchedCase)node2; if (c1.Whens.Count != c2.Whens.Count) { return(false); } for (int i = 0, n = c1.Whens.Count; i < n; i++) { if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match) || !AreEqual(c1.Whens[i].Value, c2.Whens[i].Value)) { return(false); } } return(AreEqual(c1.Else, c2.Else)); } case SqlNodeType.ClientCase: { SqlClientCase c1 = (SqlClientCase)node1; SqlClientCase c2 = (SqlClientCase)node2; if (c1.Whens.Count != c2.Whens.Count) { return(false); } for (int i = 0, n = c1.Whens.Count; i < n; i++) { if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match) || !AreEqual(c1.Whens[i].Value, c2.Whens[i].Value)) { return(false); } } return(true); } case SqlNodeType.DiscriminatedType: { SqlDiscriminatedType dt1 = (SqlDiscriminatedType)node1; SqlDiscriminatedType dt2 = (SqlDiscriminatedType)node2; return(AreEqual(dt1.Discriminator, dt2.Discriminator)); } case SqlNodeType.SimpleCase: { SqlSimpleCase c1 = (SqlSimpleCase)node1; SqlSimpleCase c2 = (SqlSimpleCase)node2; if (c1.Whens.Count != c2.Whens.Count) { return(false); } for (int i = 0, n = c1.Whens.Count; i < n; i++) { if (!AreEqual(c1.Whens[i].Match, c2.Whens[i].Match) || !AreEqual(c1.Whens[i].Value, c2.Whens[i].Value)) { return(false); } } return(true); } case SqlNodeType.Like: { SqlLike like1 = (SqlLike)node1; SqlLike like2 = (SqlLike)node2; return(AreEqual(like1.Expression, like2.Expression) && AreEqual(like1.Pattern, like2.Pattern) && AreEqual(like1.Escape, like2.Escape)); } case SqlNodeType.Variable: { SqlVariable v1 = (SqlVariable)node1; SqlVariable v2 = (SqlVariable)node2; return(v1.Name == v2.Name); } case SqlNodeType.FunctionCall: { SqlFunctionCall f1 = (SqlFunctionCall)node1; SqlFunctionCall f2 = (SqlFunctionCall)node2; if (f1.Name != f2.Name) { return(false); } if (f1.Arguments.Count != f2.Arguments.Count) { return(false); } for (int i = 0, n = f1.Arguments.Count; i < n; i++) { if (!AreEqual(f1.Arguments[i], f2.Arguments[i])) { return(false); } } return(true); } case SqlNodeType.Link: { SqlLink l1 = (SqlLink)node1; SqlLink l2 = (SqlLink)node2; if (!MetaPosition.AreSameMember(l1.Member.Member, l2.Member.Member)) { return(false); } if (!AreEqual(l1.Expansion, l2.Expansion)) { return(false); } if (l1.KeyExpressions.Count != l2.KeyExpressions.Count) { return(false); } for (int i = 0, c = l1.KeyExpressions.Count; i < c; ++i) { if (!AreEqual(l1.KeyExpressions[i], l2.KeyExpressions[i])) { return(false); } } return(true); } case SqlNodeType.ExprSet: SqlExprSet es1 = (SqlExprSet)node1; SqlExprSet es2 = (SqlExprSet)node2; if (es1.Expressions.Count != es2.Expressions.Count) { return(false); } for (int i = 0, n = es1.Expressions.Count; i < n; i++) { if (!AreEqual(es1.Expressions[i], es2.Expressions[i])) { return(false); } } return(true); case SqlNodeType.OptionalValue: SqlOptionalValue ov1 = (SqlOptionalValue)node1; SqlOptionalValue ov2 = (SqlOptionalValue)node2; return(AreEqual(ov1.Value, ov2.Value)); case SqlNodeType.Row: case SqlNodeType.UserQuery: case SqlNodeType.StoredProcedureCall: case SqlNodeType.UserRow: case SqlNodeType.UserColumn: case SqlNodeType.Multiset: case SqlNodeType.ScalarSubSelect: case SqlNodeType.Element: case SqlNodeType.Exists: case SqlNodeType.Join: case SqlNodeType.Select: case SqlNodeType.New: case SqlNodeType.ClientQuery: case SqlNodeType.ClientArray: case SqlNodeType.Insert: case SqlNodeType.Update: case SqlNodeType.Delete: case SqlNodeType.MemberAssign: case SqlNodeType.Assign: case SqlNodeType.Block: case SqlNodeType.Union: case SqlNodeType.DoNotVisit: case SqlNodeType.MethodCall: case SqlNodeType.Nop: default: return(false); } }
internal LinkedTableExpression(SqlLink link, ITable table, Type type) : base(InternalExpressionType.LinkedTable, type) { this.link = link; this.table = table; }
internal SqlExpression BuildProjection(SqlExpression item, MetaType rowType, bool allowDeferred, SqlLink link, Expression source) { if (!rowType.HasInheritance) { return(BuildProjectionInternal(item, rowType, (rowType.Table != null) ? rowType.PersistentDataMembers : rowType.DataMembers, allowDeferred, link, source)); } var list = new List <MetaType>(rowType.InheritanceTypes); var list2 = new List <SqlTypeCaseWhen>(); SqlTypeCaseWhen sqlTypeCaseWhen = null; var inheritanceRoot = rowType.InheritanceRoot; var discriminator = inheritanceRoot.Discriminator; var type = discriminator.Type; var sqlMember = sql.Member(item, discriminator.Member); foreach (var item2 in list) { if (item2.HasInheritanceCode) { var typeBinding = BuildProjectionInternal(item, item2, item2.PersistentDataMembers, allowDeferred, link, source); if (item2.IsInheritanceDefault) { sqlTypeCaseWhen = new SqlTypeCaseWhen(null, typeBinding); } object value = InheritanceRules.InheritanceCodeForClientCompare(item2.InheritanceCode, sqlMember.SqlType); var match = sql.Value(type, sql.Default(discriminator), value, true, source); list2.Add(new SqlTypeCaseWhen(match, typeBinding)); } } if (sqlTypeCaseWhen == null) { throw Error.EmptyCaseNotSupported(); } list2.Add(sqlTypeCaseWhen); return(sql.TypeCase(inheritanceRoot.Type, inheritanceRoot, sqlMember, list2.ToArray(), source)); }
internal SqlExpression BuildProjection(SqlExpression item, MetaType rowType, bool allowDeferred, SqlLink link, Expression source) { if (!rowType.HasInheritance) { return(this.BuildProjectionInternal(item, rowType, (rowType.Table != null) ? rowType.PersistentDataMembers : rowType.DataMembers, allowDeferred, link, source)); } else { // Build a type case that represents a switch between the various type. List <MetaType> mappedTypes = new List <MetaType>(rowType.InheritanceTypes); List <SqlTypeCaseWhen> whens = new List <SqlTypeCaseWhen>(); SqlTypeCaseWhen @else = null; MetaType root = rowType.InheritanceRoot; MetaDataMember discriminator = root.Discriminator; Type dt = discriminator.Type; SqlMember dm = sql.Member(item, discriminator.Member); foreach (MetaType type in mappedTypes) { if (type.HasInheritanceCode) { SqlNew defaultProjection = this.BuildProjectionInternal(item, type, type.PersistentDataMembers, allowDeferred, link, source); if (type.IsInheritanceDefault) { @else = new SqlTypeCaseWhen(null, defaultProjection); } // Add an explicit case even for the default. // Redundant results will be optimized out later. object code = InheritanceRules.InheritanceCodeForClientCompare(type.InheritanceCode, dm.SqlType); SqlExpression match = sql.Value(dt, sql.Default(discriminator), code, true, source); whens.Add(new SqlTypeCaseWhen(match, defaultProjection)); } } if (@else == null) { throw Error.EmptyCaseNotSupported(); } whens.Add(@else); // Add the else at the end. return(sql.TypeCase(root.Type, root, dm, whens.ToArray(), source)); } }
internal SqlExpression TranslateEquals(SqlBinary expr) { System.Diagnostics.Debug.Assert( expr.NodeType == SqlNodeType.EQ || expr.NodeType == SqlNodeType.NE || expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V); SqlExpression eLeft = expr.Left; SqlExpression eRight = expr.Right; if (eRight.NodeType == SqlNodeType.Element) { SqlSubSelect sub = (SqlSubSelect)eRight; SqlAlias alias = new SqlAlias(sub.Select); SqlAliasRef aref = new SqlAliasRef(alias); SqlSelect select = new SqlSelect(aref, alias, expr.SourceExpression); select.Where = sql.Binary(expr.NodeType, sql.DoNotVisitExpression(eLeft), aref); return(sql.SubSelect(SqlNodeType.Exists, select)); } else if (eLeft.NodeType == SqlNodeType.Element) { SqlSubSelect sub = (SqlSubSelect)eLeft; SqlAlias alias = new SqlAlias(sub.Select); SqlAliasRef aref = new SqlAliasRef(alias); SqlSelect select = new SqlSelect(aref, alias, expr.SourceExpression); select.Where = sql.Binary(expr.NodeType, sql.DoNotVisitExpression(eRight), aref); return(sql.SubSelect(SqlNodeType.Exists, select)); } MetaType mtLeft = TypeSource.GetSourceMetaType(eLeft, this.services.Model); MetaType mtRight = TypeSource.GetSourceMetaType(eRight, this.services.Model); if (eLeft.NodeType == SqlNodeType.TypeCase) { eLeft = BestIdentityNode((SqlTypeCase)eLeft); } if (eRight.NodeType == SqlNodeType.TypeCase) { eRight = BestIdentityNode((SqlTypeCase)eRight); } if (mtLeft.IsEntity && mtRight.IsEntity && mtLeft.Table != mtRight.Table) { throw Error.CannotCompareItemsAssociatedWithDifferentTable(); } // do simple or no translation for non-structural types if (!mtLeft.IsEntity && !mtRight.IsEntity && (eLeft.NodeType != SqlNodeType.New || eLeft.SqlType.CanBeColumn) && (eRight.NodeType != SqlNodeType.New || eRight.SqlType.CanBeColumn)) { if (expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V) { return(this.TranslateEqualsOp(expr.NodeType, sql.DoNotVisitExpression(expr.Left), sql.DoNotVisitExpression(expr.Right), false)); } return(expr); } // If the two types are not comparable, we return the predicate "1=0". if ((mtLeft != mtRight) && (mtLeft.InheritanceRoot != mtRight.InheritanceRoot)) { return(sql.Binary(SqlNodeType.EQ, sql.ValueFromObject(0, expr.SourceExpression), sql.ValueFromObject(1, expr.SourceExpression))); } List <SqlExpression> exprs1; List <SqlExpression> exprs2; SqlLink link1 = eLeft as SqlLink; if (link1 != null && link1.Member.IsAssociation && link1.Member.Association.IsForeignKey) { exprs1 = link1.KeyExpressions; } else { exprs1 = this.GetIdentityExpressions(mtLeft, sql.DoNotVisitExpression(eLeft)); } SqlLink link2 = eRight as SqlLink; if (link2 != null && link2.Member.IsAssociation && link2.Member.Association.IsForeignKey) { exprs2 = link2.KeyExpressions; } else { exprs2 = this.GetIdentityExpressions(mtRight, sql.DoNotVisitExpression(eRight)); } System.Diagnostics.Debug.Assert(exprs1.Count > 0); System.Diagnostics.Debug.Assert(exprs2.Count > 0); System.Diagnostics.Debug.Assert(exprs1.Count == exprs2.Count); SqlExpression exp = null; SqlNodeType eqKind = (expr.NodeType == SqlNodeType.EQ2V || expr.NodeType == SqlNodeType.NE2V) ? SqlNodeType.EQ2V : SqlNodeType.EQ; for (int i = 0, n = exprs1.Count; i < n; i++) { SqlExpression eq = this.TranslateEqualsOp(eqKind, exprs1[i], exprs2[i], !mtLeft.IsEntity); if (exp == null) { exp = eq; } else { exp = sql.Binary(SqlNodeType.And, exp, eq); } } if (expr.NodeType == SqlNodeType.NE || expr.NodeType == SqlNodeType.NE2V) { exp = sql.Unary(SqlNodeType.Not, exp, exp.SourceExpression); } return(exp); }
private SqlExpression ExpandTogether(List <SqlExpression> exprs) { switch (exprs[0].NodeType) { case SqlNodeType.MethodCall: { SqlMethodCall[] mcs = new SqlMethodCall[exprs.Count]; for (int i = 0; i < mcs.Length; ++i) { mcs[i] = (SqlMethodCall)exprs[i]; } List <SqlExpression> expandedArgs = new List <SqlExpression>(); for (int i = 0; i < mcs[0].Arguments.Count; ++i) { List <SqlExpression> args = new List <SqlExpression>(); for (int j = 0; j < mcs.Length; ++j) { args.Add(mcs[j].Arguments[i]); } SqlExpression expanded = this.ExpandTogether(args); expandedArgs.Add(expanded); } return(factory.MethodCall(mcs[0].Method, mcs[0].Object, expandedArgs.ToArray(), mcs[0].SourceExpression)); } case SqlNodeType.ClientCase: { // Are they all the same? SqlClientCase[] scs = new SqlClientCase[exprs.Count]; scs[0] = (SqlClientCase)exprs[0]; for (int i = 1; i < scs.Length; ++i) { scs[i] = (SqlClientCase)exprs[i]; } // Expand expressions together. List <SqlExpression> expressions = new List <SqlExpression>(); for (int i = 0; i < scs.Length; ++i) { expressions.Add(scs[i].Expression); } SqlExpression expression = this.ExpandTogether(expressions); // Expand individual expressions together. List <SqlClientWhen> whens = new List <SqlClientWhen>(); for (int i = 0; i < scs[0].Whens.Count; ++i) { List <SqlExpression> scos = new List <SqlExpression>(); for (int j = 0; j < scs.Length; ++j) { SqlClientWhen when = scs[j].Whens[i]; scos.Add(when.Value); } whens.Add(new SqlClientWhen(scs[0].Whens[i].Match, this.ExpandTogether(scos))); } return(new SqlClientCase(scs[0].ClrType, expression, whens, scs[0].SourceExpression)); } case SqlNodeType.TypeCase: { // Are they all the same? SqlTypeCase[] tcs = new SqlTypeCase[exprs.Count]; tcs[0] = (SqlTypeCase)exprs[0]; for (int i = 1; i < tcs.Length; ++i) { tcs[i] = (SqlTypeCase)exprs[i]; } // Expand discriminators together. List <SqlExpression> discriminators = new List <SqlExpression>(); for (int i = 0; i < tcs.Length; ++i) { discriminators.Add(tcs[i].Discriminator); } SqlExpression discriminator = this.ExpandTogether(discriminators); // Write expanded discriminators back in. for (int i = 0; i < tcs.Length; ++i) { tcs[i].Discriminator = discriminators[i]; } // Expand individual type bindings together. List <SqlTypeCaseWhen> whens = new List <SqlTypeCaseWhen>(); for (int i = 0; i < tcs[0].Whens.Count; ++i) { List <SqlExpression> scos = new List <SqlExpression>(); for (int j = 0; j < tcs.Length; ++j) { SqlTypeCaseWhen when = tcs[j].Whens[i]; scos.Add(when.TypeBinding); } SqlExpression expanded = this.ExpandTogether(scos); whens.Add(new SqlTypeCaseWhen(tcs[0].Whens[i].Match, expanded)); } return(factory.TypeCase(tcs[0].ClrType, tcs[0].RowType, discriminator, whens, tcs[0].SourceExpression)); } case SqlNodeType.New: { // first verify all are similar client objects... SqlNew[] cobs = new SqlNew[exprs.Count]; cobs[0] = (SqlNew)exprs[0]; for (int i = 1, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.New) { throw Error.UnionIncompatibleConstruction(); } cobs[i] = (SqlNew)exprs[1]; if (cobs[i].Members.Count != cobs[0].Members.Count) { throw Error.UnionDifferentMembers(); } for (int m = 0, mn = cobs[0].Members.Count; m < mn; m++) { if (cobs[i].Members[m].Member != cobs[0].Members[m].Member) { throw Error.UnionDifferentMemberOrder(); } } } SqlMemberAssign[] bindings = new SqlMemberAssign[cobs[0].Members.Count]; for (int m = 0, mn = bindings.Length; m < mn; m++) { List <SqlExpression> mexprs = new List <SqlExpression>(); for (int i = 0, n = exprs.Count; i < n; i++) { mexprs.Add(cobs[i].Members[m].Expression); } bindings[m] = new SqlMemberAssign(cobs[0].Members[m].Member, this.ExpandTogether(mexprs)); for (int i = 0, n = exprs.Count; i < n; i++) { cobs[i].Members[m].Expression = mexprs[i]; } } SqlExpression[] arguments = new SqlExpression[cobs[0].Args.Count]; for (int m = 0, mn = arguments.Length; m < mn; ++m) { List <SqlExpression> mexprs = new List <SqlExpression>(); for (int i = 0, n = exprs.Count; i < n; i++) { mexprs.Add(cobs[i].Args[m]); } arguments[m] = ExpandTogether(mexprs); } return(factory.New(cobs[0].MetaType, cobs[0].Constructor, arguments, cobs[0].ArgMembers, bindings, exprs[0].SourceExpression)); } case SqlNodeType.Link: { SqlLink[] links = new SqlLink[exprs.Count]; links[0] = (SqlLink)exprs[0]; for (int i = 1, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.Link) { throw Error.UnionIncompatibleConstruction(); } links[i] = (SqlLink)exprs[i]; if (links[i].KeyExpressions.Count != links[0].KeyExpressions.Count || links[i].Member != links[0].Member || (links[i].Expansion != null) != (links[0].Expansion != null)) { throw Error.UnionIncompatibleConstruction(); } } SqlExpression[] kexprs = new SqlExpression[links[0].KeyExpressions.Count]; List <SqlExpression> lexprs = new List <SqlExpression>(); for (int k = 0, nk = links[0].KeyExpressions.Count; k < nk; k++) { lexprs.Clear(); for (int i = 0, n = exprs.Count; i < n; i++) { lexprs.Add(links[i].KeyExpressions[k]); } kexprs[k] = this.ExpandTogether(lexprs); for (int i = 0, n = exprs.Count; i < n; i++) { links[i].KeyExpressions[k] = lexprs[i]; } } SqlExpression expansion = null; if (links[0].Expansion != null) { lexprs.Clear(); for (int i = 0, n = exprs.Count; i < n; i++) { lexprs.Add(links[i].Expansion); } expansion = this.ExpandTogether(lexprs); for (int i = 0, n = exprs.Count; i < n; i++) { links[i].Expansion = lexprs[i]; } } return(new SqlLink(links[0].Id, links[0].RowType, links[0].ClrType, links[0].SqlType, links[0].Expression, links[0].Member, kexprs, expansion, links[0].SourceExpression)); } case SqlNodeType.Value: { /* * ExprSet of all literals of the same value reduce to just a single literal. */ SqlValue val0 = (SqlValue)exprs[0]; for (int i = 1; i < exprs.Count; ++i) { SqlValue val = (SqlValue)exprs[i]; if (!object.Equals(val.Value, val0.Value)) { return(this.ExpandIntoExprSet(exprs)); } } return(val0); } case SqlNodeType.OptionalValue: { if (exprs[0].SqlType.CanBeColumn) { goto default; } List <SqlExpression> hvals = new List <SqlExpression>(exprs.Count); List <SqlExpression> vals = new List <SqlExpression>(exprs.Count); for (int i = 0, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.OptionalValue) { throw Error.UnionIncompatibleConstruction(); } SqlOptionalValue sov = (SqlOptionalValue)exprs[i]; hvals.Add(sov.HasValue); vals.Add(sov.Value); } return(new SqlOptionalValue(this.ExpandTogether(hvals), this.ExpandTogether(vals))); } case SqlNodeType.OuterJoinedValue: { if (exprs[0].SqlType.CanBeColumn) { goto default; } List <SqlExpression> values = new List <SqlExpression>(exprs.Count); for (int i = 0, n = exprs.Count; i < n; i++) { if (exprs[i] == null || exprs[i].NodeType != SqlNodeType.OuterJoinedValue) { throw Error.UnionIncompatibleConstruction(); } SqlUnary su = (SqlUnary)exprs[i]; values.Add(su.Operand); } return(factory.Unary(SqlNodeType.OuterJoinedValue, this.ExpandTogether(values))); } case SqlNodeType.DiscriminatedType: { SqlDiscriminatedType sdt0 = (SqlDiscriminatedType)exprs[0]; List <SqlExpression> foos = new List <SqlExpression>(exprs.Count); foos.Add(sdt0.Discriminator); for (int i = 1, n = exprs.Count; i < n; i++) { SqlDiscriminatedType sdtN = (SqlDiscriminatedType)exprs[i]; if (sdtN.TargetType != sdt0.TargetType) { throw Error.UnionIncompatibleConstruction(); } foos.Add(sdtN.Discriminator); } return(factory.DiscriminatedType(this.ExpandTogether(foos), ((SqlDiscriminatedType)exprs[0]).TargetType)); } case SqlNodeType.ClientQuery: case SqlNodeType.Multiset: case SqlNodeType.Element: case SqlNodeType.Grouping: throw Error.UnionWithHierarchy(); default: return(this.ExpandIntoExprSet(exprs)); } }
internal SqlNode TranslateLink(SqlLink link, bool asExpression) => TranslateLink(link, link.KeyExpressions, asExpression);
internal SqlNode TranslateLink(SqlLink link, bool asExpression) { return(this.TranslateLink(link, link.KeyExpressions, asExpression)); }
private void FlattenGroupByExpression(List <SqlExpression> exprs, SqlExpression expr) { SqlNew sn = expr as SqlNew; if (sn != null) { foreach (SqlMemberAssign ma in sn.Members) { this.FlattenGroupByExpression(exprs, ma.Expression); } foreach (SqlExpression arg in sn.Args) { this.FlattenGroupByExpression(exprs, arg); } } else if (expr.NodeType == SqlNodeType.TypeCase) { SqlTypeCase tc = (SqlTypeCase)expr; this.FlattenGroupByExpression(exprs, tc.Discriminator); foreach (SqlTypeCaseWhen when in tc.Whens) { this.FlattenGroupByExpression(exprs, when.TypeBinding); } } else if (expr.NodeType == SqlNodeType.Link) { SqlLink link = (SqlLink)expr; if (link.Expansion != null) { this.FlattenGroupByExpression(exprs, link.Expansion); } else { foreach (SqlExpression key in link.KeyExpressions) { this.FlattenGroupByExpression(exprs, key); } } } else if (expr.NodeType == SqlNodeType.OptionalValue) { SqlOptionalValue sop = (SqlOptionalValue)expr; this.FlattenGroupByExpression(exprs, sop.HasValue); this.FlattenGroupByExpression(exprs, sop.Value); } else if (expr.NodeType == SqlNodeType.OuterJoinedValue) { this.FlattenGroupByExpression(exprs, ((SqlUnary)expr).Operand); } else if (expr.NodeType == SqlNodeType.DiscriminatedType) { SqlDiscriminatedType dt = (SqlDiscriminatedType)expr; this.FlattenGroupByExpression(exprs, dt.Discriminator); } else { // this expression should have been 'pushed-down' in SqlBinder, so we // should only find column-references & expr-sets unless the expression could not // be columnized (in which case it was a bad group-by expression.) if (expr.NodeType != SqlNodeType.ColumnRef && expr.NodeType != SqlNodeType.ExprSet) { if (!expr.SqlType.CanBeColumn) { throw Error.InvalidGroupByExpressionType(expr.SqlType.ToQueryString()); } throw Error.InvalidGroupByExpression(); } exprs.Add(expr); } }
private SqlNew BuildProjectionInternal(SqlExpression item, MetaType rowType, IEnumerable <MetaDataMember> members, bool allowDeferred, SqlLink link, Expression source) { var list = new List <SqlMemberAssign>(); foreach (var member in members) { if (allowDeferred && (member.IsAssociation || member.IsDeferred)) { if (link != null && member != link.Member && member.IsAssociation && member.MappedName == link.Member.MappedName && !member.Association.IsMany && !IsPreloaded(link.Member.Member)) { var sqlLink = BuildLink(item, member, source); sqlLink.Expansion = link.Expression; list.Add(new SqlMemberAssign(member.Member, sqlLink)); } else { list.Add(new SqlMemberAssign(member.Member, BuildLink(item, member, source))); } } else if (!member.IsAssociation) { list.Add(new SqlMemberAssign(member.Member, sql.Member(item, member))); } } var constructor = rowType.Type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (constructor == null) { throw Error.MappedTypeMustHaveDefaultConstructor(rowType.Type); } return(sql.New(rowType, constructor, null, null, list, source)); }