Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
 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);
 }
Beispiel #4
0
 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);
 }
Beispiel #5
0
            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));
            }
Beispiel #6
0
        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);
        }
Beispiel #7
0
 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));
 }
Beispiel #8
0
        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));
        }
Beispiel #9
0
        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);
            }
Beispiel #11
0
        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));
        }
Beispiel #12
0
            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);
            }
Beispiel #13
0
        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));
        }
Beispiel #14
0
        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);
            }
        }
Beispiel #15
0
 internal LinkedTableExpression(SqlLink link, ITable table, Type type)
     : base(InternalExpressionType.LinkedTable, type)
 {
     this.link  = link;
     this.table = table;
 }
Beispiel #16
0
        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));
        }
Beispiel #17
0
        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));
            }
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
            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));
                }
            }
Beispiel #20
0
 internal SqlNode TranslateLink(SqlLink link, bool asExpression) => TranslateLink(link, link.KeyExpressions, asExpression);
Beispiel #21
0
 internal SqlNode TranslateLink(SqlLink link, bool asExpression)
 {
     return(this.TranslateLink(link, link.KeyExpressions, asExpression));
 }
Beispiel #22
0
            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);
                }
            }
Beispiel #23
0
        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));
        }