internal override SqlExpression VisitNew(SqlNew sox)
 {
     if (sox.Constructor != null)
     {
         Reflection.ParameterInfo[] pis = sox.Constructor.GetParameters();
         for (int i = 0, n = sox.Args.Count; i < n; i++)
         {
             sox.Args[i] = this.VisitNamedExpression(sox.Args[i], pis[i].Name);
         }
     }
     else
     {
         for (int i = 0, n = sox.Args.Count; i < n; i++)
         {
             sox.Args[i] = this.VisitExpression(sox.Args[i]);
         }
     }
     foreach (SqlMemberAssign ma in sox.Members)
     {
         string n = ma.Member.Name;
         if (this.useMappedNames)
         {
             n = sox.MetaType.GetDataMember(ma.Member).MappedName;
         }
         ma.Expression = this.VisitNamedExpression(ma.Expression, n);
     }
     return(sox);
 }
Beispiel #2
0
 internal virtual SqlExpression VisitNew(SqlNew sox) {
     for (int i = 0, n = sox.Args.Count; i < n; i++) {
         sox.Args[i] = this.VisitExpression(sox.Args[i]);
     }
     for (int i = 0, n = sox.Members.Count; i < n; i++) {
         sox.Members[i].Expression = this.VisitExpression(sox.Members[i].Expression);
     }
     return sox;
 }
 private static bool IsSupportedNew(SqlNew snew) {
     if (snew.ClrType == typeof(string)) {
         return IsSupportedStringNew(snew);
     }
     else if (snew.ClrType == typeof(TimeSpan)) {
         return IsSupportedTimeSpanNew(snew);
     }
     else if (snew.ClrType == typeof(DateTime)) {
         return IsSupportedDateTimeNew(snew);
     }
     return false;
 }
 internal override SqlExpression VisitNew(SqlNew sox)
 {
     SqlExpression[]   args     = new SqlExpression[sox.Args.Count];
     SqlMemberAssign[] bindings = new SqlMemberAssign[sox.Members.Count];
     for (int i = 0, n = args.Length; i < n; i++)
     {
         args[i] = this.VisitExpression(sox.Args[i]);
     }
     for (int i = 0, n = bindings.Length; i < n; i++)
     {
         bindings[i] = this.VisitMemberAssign(sox.Members[i]);
     }
     return(new SqlNew(sox.MetaType, sox.SqlType, sox.Constructor, args, sox.ArgMembers, bindings, sox.SourceExpression));
 }
Beispiel #5
0
        internal override SqlExpression VisitNew(SqlNew sox)
        {
            // check the args for the PKs
            foreach (MemberInfo column in _identityMembers)
            {
                // assume we're invalid unless we find a matching argument which is
                // a bare column/columnRef to the PK
                bool isMatch = false;

                // find a matching arg
                foreach (SqlExpression expr in sox.Args)
                {
                    isMatch = IsColumnMatch(column, expr);

                    if (isMatch)
                    {
                        break;
                    }
                }

                if (!isMatch)
                {
                    foreach (SqlMemberAssign ma in sox.Members)
                    {
                        SqlExpression expr = ma.Expression;

                        isMatch = IsColumnMatch(column, expr);

                        if (isMatch)
                        {
                            break;
                        }
                    }
                }

                _isValid &= isMatch;
                if (!_isValid)
                {
                    break;
                }
            }

            return(sox);
        }
Beispiel #6
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));
            }
        }
 private static bool IsSupportedDateTimeNew(SqlNew sox) {
     if (sox.ClrType == typeof(DateTime)
         && sox.Args.Count >= 3
         && sox.Args[0].ClrType == typeof(int)
         && sox.Args[1].ClrType == typeof(int)
         && sox.Args[2].ClrType == typeof(int)) {
         if (sox.Args.Count == 3) {
             return true;
         }
         if (sox.Args.Count >= 6 &&
             sox.Args[3].ClrType == typeof(int) && sox.Args[4].ClrType == typeof(int) && sox.Args[5].ClrType == typeof(int)) {
             if (sox.Args.Count == 6) {
                 return true;
             }
             if ((sox.Args.Count == 7) && (sox.Args[6].ClrType == typeof(int))) {
                 return true;
             }
         }
     }
     return false;
 }
 internal override SqlExpression VisitNew(SqlNew sox) {
     if (sox.Constructor != null) {
         System.Reflection.ParameterInfo[] pis = sox.Constructor.GetParameters();
         for (int i = 0, n = sox.Args.Count; i < n; i++) {
             sox.Args[i] = this.VisitNamedExpression(sox.Args[i], pis[i].Name);
         }
     }
     else {
         for (int i = 0, n = sox.Args.Count; i < n; i++) {
             sox.Args[i] = this.VisitExpression(sox.Args[i]);
         }
     }
     foreach (SqlMemberAssign ma in sox.Members) {
         string n = ma.Member.Name;
         if (this.useMappedNames) {
             n = sox.MetaType.GetDataMember(ma.Member).MappedName;
         }
         ma.Expression = this.VisitNamedExpression(ma.Expression, n);
     }
     return sox;
 }
 private static bool IsSupportedTimeSpanNew(SqlNew sox) {
     if (sox.Args.Count == 1) {
         return true;
     }
     else if (sox.Args.Count == 3) {
         return true;
     }
     else {
         if (sox.Args.Count == 4) {
             return true;
         }
         else if (sox.Args.Count == 5) {
             return true;
         }
     }
     return false;
 }
        internal static bool CanBeCompared(SqlExpression node)
        {
            if (node == null)
            {
                return(true);
            }
            switch (node.NodeType)
            {
            case SqlNodeType.New:
            {
                SqlNew new1 = (SqlNew)node;
                for (int i = 0, n = new1.Args.Count; i < n; i++)
                {
                    if (!CanBeCompared(new1.Args[i]))
                    {
                        return(false);
                    }
                }
                for (int i = 0, n = new1.Members.Count; i < n; i++)
                {
                    if (!CanBeCompared(new1.Members[i].Expression))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ColumnRef:
            case SqlNodeType.Value:
            case SqlNodeType.UserColumn:
                return(true);

            case SqlNodeType.Link:
            {
                SqlLink l1 = (SqlLink)node;
                for (int i = 0, c = l1.KeyExpressions.Count; i < c; ++i)
                {
                    if (!CanBeCompared(l1.KeyExpressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.OptionalValue:
                return(CanBeCompared(((SqlOptionalValue)node).Value));

            case SqlNodeType.ValueOf:
            case SqlNodeType.OuterJoinedValue:
                return(CanBeCompared(((SqlUnary)node).Operand));

            case SqlNodeType.Lift:
                return(CanBeCompared(((SqlLift)node).Expression));

            case SqlNodeType.Grouping:
            {
                SqlGrouping g1 = (SqlGrouping)node;
                return(CanBeCompared(g1.Key) && CanBeCompared(g1.Group));
            }

            case SqlNodeType.ClientArray:
            {
                if (node.SourceExpression.NodeType != ExpressionType.NewArrayInit &&
                    node.SourceExpression.NodeType != ExpressionType.NewArrayBounds)
                {
                    return(false);
                }
                SqlClientArray a1 = (SqlClientArray)node;
                for (int i = 0, n = a1.Expressions.Count; i < n; i++)
                {
                    if (!CanBeCompared(a1.Expressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ClientCase:
            {
                SqlClientCase c1 = (SqlClientCase)node;
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!CanBeCompared(c1.Whens[i].Match) ||
                        !CanBeCompared(c1.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.SearchedCase:
            {
                SqlSearchedCase c1 = (SqlSearchedCase)node;
                for (int i = 0, n = c1.Whens.Count; i < n; i++)
                {
                    if (!CanBeCompared(c1.Whens[i].Match) ||
                        !CanBeCompared(c1.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(CanBeCompared(c1.Else));
            }

            case SqlNodeType.TypeCase:
            {
                SqlTypeCase c1 = (SqlTypeCase)node;
                if (!CanBeCompared(c1.Discriminator))
                {
                    return(false);
                }
                for (int i = 0, c = c1.Whens.Count; i < c; ++i)
                {
                    if (!CanBeCompared(c1.Whens[i].Match))
                    {
                        return(false);
                    }
                    if (!CanBeCompared(c1.Whens[i].TypeBinding))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.DiscriminatedType:
                return(CanBeCompared(((SqlDiscriminatedType)node).Discriminator));

            case SqlNodeType.JoinedCollection:
            {
                SqlJoinedCollection j1 = (SqlJoinedCollection)node;
                return(CanBeCompared(j1.Count) && CanBeCompared(j1.Expression));
            }

            case SqlNodeType.Member:
                return(CanBeCompared(((SqlMember)node).Expression));

            case SqlNodeType.MethodCall:
            {
                SqlMethodCall mc = (SqlMethodCall)node;
                if (mc.Object != null && !CanBeCompared(mc.Object))
                {
                    return(false);
                }
                for (int i = 0, n = mc.Arguments.Count; i < n; i++)
                {
                    if (!CanBeCompared(mc.Arguments[0]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ClientQuery:
                return(true);

            case SqlNodeType.ClientParameter:
            default:
                return(false);
            }
        }
 internal override SqlExpression VisitNew(SqlNew sox) {
     this.isNew = true;
     return base.VisitNew(sox);
 }
 internal override SqlExpression VisitNew(SqlNew sox) {
     SqlExpression[] args = new SqlExpression[sox.Args.Count];
     SqlMemberAssign[] bindings = new SqlMemberAssign[sox.Members.Count];
     for (int i = 0, n = args.Length; i < n; i++) {
         args[i] = this.VisitExpression(sox.Args[i]);
     }
     for (int i = 0, n = bindings.Length; i < n; i++) {
         bindings[i] = this.VisitMemberAssign(sox.Members[i]);
     }
     return new SqlNew(sox.MetaType, sox.SqlType, sox.Constructor, args, sox.ArgMembers, bindings, sox.SourceExpression);
 }
 internal override SqlExpression VisitNew(SqlNew sox) {
     for (int i = 0, n = sox.Args.Count; i < n; i++) {
         if (inGroupBy) {
             // we don't want to fetch expressions for group by,
             // since we want links to remain links so SqlFlattener
             // can deal with them properly
             sox.Args[i] = this.VisitExpression(sox.Args[i]);
         }
         else {
             sox.Args[i] = this.FetchExpression(sox.Args[i]);
         }
     }
     for (int i = 0, n = sox.Members.Count; i < n; i++) {
         SqlMemberAssign ma = sox.Members[i];
         MetaDataMember mm = sox.MetaType.GetDataMember(ma.Member);
         MetaType otherType = mm.DeclaringType.InheritanceRoot;
         if (mm.IsAssociation && ma.Expression != null && ma.Expression.NodeType != SqlNodeType.Link
             && this.shape != null && this.shape.IsPreloaded(mm.Member) && mm.LoadMethod == null
             && this.alreadyIncluded != null && !this.alreadyIncluded.Contains(otherType)) {
             // The expression is already fetched, add it to the alreadyIncluded set.
             this.alreadyIncluded.Add(otherType);
             ma.Expression = this.VisitExpression(ma.Expression);
             this.alreadyIncluded.Remove(otherType);
         }
         else if (mm.IsAssociation || mm.IsDeferred) {
             ma.Expression = this.VisitExpression(ma.Expression);
         }
         else {
             ma.Expression = this.FetchExpression(ma.Expression);
         }
     }
     return sox;
 }
            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);
                }
            }
 private static bool IsSupportedStringNew(SqlNew snew) {
     return snew.Args.Count == 2 && snew.Args[0].ClrType == typeof(char) && snew.Args[1].ClrType == typeof(int);
 }
Beispiel #16
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 (!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 SqlNew New(MetaType type, ConstructorInfo cons, IEnumerable<SqlExpression> args, IEnumerable<MemberInfo> argMembers, IEnumerable<SqlMemberAssign> bindings, Expression sourceExpression) {
     SqlNew tb = new SqlNew(type, typeProvider.From(type.Type), cons, args, argMembers, bindings, sourceExpression);
     return tb;
 }
 internal virtual SqlExpression VisitNew(SqlNew sox) {
     for (int i = 0, n = sox.Args.Count; i < n; i++) {
         sox.Args[i] = this.VisitExpression(sox.Args[i]);
     }
     for (int i = 0, n = sox.Members.Count; i < n; i++) {
         sox.Members[i].Expression = this.VisitExpression(sox.Members[i].Expression);
     }
     return sox;
 }
 // transform constructors if necessary
 internal override SqlExpression VisitNew(SqlNew sox) {
     sox = (SqlNew)base.VisitNew(sox);
     if (sox.ClrType == typeof(string)) {
         return TranslateNewString(sox);
     }
     else if (sox.ClrType == typeof(TimeSpan)) {
         return TranslateNewTimeSpan(sox);
     }
     else if (sox.ClrType == typeof(DateTime)) {
         return TranslateNewDateTime(sox);
     }
     else if (sox.ClrType == typeof(DateTimeOffset)) {
         return TranslateNewDateTimeOffset(sox);
     }
     return sox;
 }
Beispiel #20
0
        internal SqlNew New(MetaType type, ConstructorInfo cons, IEnumerable <SqlExpression> args, IEnumerable <MemberInfo> argMembers, IEnumerable <SqlMemberAssign> bindings, Expression sourceExpression)
        {
            SqlNew tb = new SqlNew(type, typeProvider.From(type.Type), cons, args, argMembers, bindings, sourceExpression);

            return(tb);
        }
 private SqlExpression TranslateNewString(SqlNew sox) {
     // string(char c, int i) 
     // --> REPLICATE(@c,@i)
     if (sox.ClrType == typeof(string) && sox.Args.Count == 2
         && sox.Args[0].ClrType == typeof(char) && sox.Args[1].ClrType == typeof(int)) {
         return sql.FunctionCall(typeof(string), "REPLICATE", new SqlExpression[] { sox.Args[0], sox.Args[1] }, sox.SourceExpression);
     }
     throw Error.UnsupportedStringConstructorForm();
 }
Beispiel #22
0
        // 
        //
        //
        //
        //

        internal override SqlExpression VisitNew(SqlNew sox) {
            // check the args for the PKs
            foreach (MemberInfo column in this.IdentityMembers) {
                // assume we're invalid unless we find a matching argument which is
                // a bare column/columnRef to the PK
                bool isMatch = false;

                // find a matching arg
                foreach (SqlExpression expr in sox.Args) {
                    isMatch = IsColumnMatch(column, expr);

                    if (isMatch) {
                        break;
                    }
                }

                if (!isMatch) {
                    foreach (SqlMemberAssign ma in sox.Members) {
                        SqlExpression expr = ma.Expression;

                        isMatch = IsColumnMatch(column, expr);

                        if (isMatch) {
                            break;
                        }
                    }
                }

                this.IsValid &= isMatch;
                if (!this.IsValid) {
                    break;
                }
            }

            return sox;
        }
            private SqlExpression TranslateNewDateTime(SqlNew sox) {
                Expression source = sox.SourceExpression;

                // DateTime(int year, int month, int day) 
                // --> CONVERT(DATETIME, CONVERT(nchar(2),@month) + '/' + CONVERT(nchar(2),@day) + '/' + CONVERT(nchar(4),@year),101)
                if (sox.ClrType == typeof(DateTime) && sox.Args.Count >= 3 &&
                    sox.Args[0].ClrType == typeof(int) && sox.Args[1].ClrType == typeof(int) && sox.Args[2].ClrType == typeof(int)) {
                    SqlExpression char2 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(2, false, source) }, source);
                    SqlExpression char4 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(4, false, source) }, source);
                    SqlExpression year = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char4, sox.Args[0] }, source);
                    SqlExpression month = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[1] }, source);
                    SqlExpression day = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[2] }, source);
                    SqlExpression datetime = new SqlVariable(typeof(void), null, "DATETIME", source);
                    if (sox.Args.Count == 3) {
                        SqlExpression date = sql.Concat(month, sql.ValueFromObject("/", false, source), day, sql.ValueFromObject("/", false, source), year);
                        return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[3] { datetime, date, sql.ValueFromObject(101, false, source) }, source);
                    }
                    if (sox.Args.Count >= 6 &&
                        sox.Args[3].ClrType == typeof(int) && sox.Args[4].ClrType == typeof(int) && sox.Args[5].ClrType == typeof(int)) {
                        // DateTime(year, month, day, hour, minute, second ) 
                        // --> CONVERT(DATETIME, CONVERT(nchar(2),@month) + '-' + CONVERT(nchar(2),@day) + '-' + CONVERT(nchar(4),@year) +
                        //                 ' ' + CONVERT(nchar(2),@hour) + ':' + CONVERT(nchar(2),@minute) + ':' + CONVERT(nchar(2),@second)  ,120)
                        SqlExpression hour = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[3] }, source);
                        SqlExpression minute = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[4] }, source);
                        SqlExpression second = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[5] }, source);
                        SqlExpression date = sql.Concat(year, sql.ValueFromObject("-", false, source), month, sql.ValueFromObject("-", false, source), day);
                        SqlExpression time = sql.Concat(hour, sql.ValueFromObject(":", false, source), minute, sql.ValueFromObject(":", false, source), second);
                        SqlExpression dateAndTime = sql.Concat(date, sql.ValueFromObject(' ', false, source), time);
                        if (sox.Args.Count == 6) {
                            return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[3] { datetime, dateAndTime, sql.ValueFromObject(120, false, source) }, source);
                        }
                        if ((sox.Args.Count == 7) && (sox.Args[6].ClrType == typeof(int))) {
                            // DateTime(year, month, day, hour, minute, second, millisecond ) 
                            // add leading zeros to milliseconds by RIGHT(CONVERT(NCHAR(4),1000+@ms),3) 
                            SqlExpression msRaw = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] {char4,
                                       sql.Add(sql.ValueFromObject(1000, false, source),sox.Args[6])}, source);
                            SqlExpression ms;
                            if (this.providerMode == SqlProvider.ProviderMode.SqlCE) {
                                //SqlCE doesn't have "RIGHT", so need to use "SUBSTRING"
                                SqlExpression len = sql.FunctionCall(typeof(int), "LEN", new SqlExpression[1] { msRaw }, source);
                                SqlExpression startIndex = sql.Binary(SqlNodeType.Sub, len, sql.ValueFromObject(2, false, source));
                                ms = sql.FunctionCall(typeof(string), "SUBSTRING", new SqlExpression[3] { msRaw, startIndex, sql.ValueFromObject(3, false, source) }, source);
                            }
                            else {
                                ms = sql.FunctionCall(typeof(string), "RIGHT", new SqlExpression[2] { msRaw, sql.ValueFromObject(3, false, source) }, source);
                            }
                            dateAndTime = sql.Concat(dateAndTime, sql.ValueFromObject('.', false, source), ms);
                            return sql.FunctionCall(typeof(DateTime), "CONVERT", new SqlExpression[3] { datetime, dateAndTime, sql.ValueFromObject(121, false, source) }, source);
                        }
                    }
                }
                throw Error.UnsupportedDateTimeConstructorForm();
            }
 internal override SqlExpression VisitNew(SqlNew sox)
 {
     this.isNew = true;
     return(base.VisitNew(sox));
 }
Beispiel #25
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);
            }
        }
            private SqlExpression TranslateNewDateTimeOffset(SqlNew sox) {
                Expression source = sox.SourceExpression;
                if (sox.ClrType == typeof(DateTimeOffset)) {
                    // DateTimeOffset(DateTime dateTime)
                    // --> CONVERT(DATETIMEOFFSET, @dateTime)
                    if (sox.Args.Count == 1 && sox.Args[0].ClrType == typeof(DateTime)) {
                        return sql.FunctionCall(typeof(DateTimeOffset), "TODATETIMEOFFSET", 
                                                new SqlExpression[2] { sox.Args[0], sql.ValueFromObject(0, false, source) }, 
                                                source);
                    }
                    // DateTimeOffset(DateTime dateTime, TimeSpan timeSpan)
                    // --> DATEADD(DATETIMEOFFSET, @dateTimePart)
                    if (sox.Args.Count == 2 && sox.Args[0].ClrType == typeof(DateTime) && sox.Args[1].ClrType == typeof(TimeSpan)) {
                        return sql.FunctionCall(typeof(DateTimeOffset), "TODATETIMEOFFSET",
                                                new SqlExpression[2] 
                                                { 
                                                    sox.Args[0], 
                                                    sql.ConvertToInt(sql.ConvertToBigint(sql.Divide(sql.ConvertTimeToDouble(sox.Args[1]), TimeSpan.TicksPerMinute)))
                                                },
                                                source);
                    }
                    // DateTimeOffset(year, month, day, hour, minute, second, [millisecond,] timeSpan) 
                    //
                    if (sox.Args.Count >= 7 &&
                        sox.Args[0].ClrType == typeof(int) && sox.Args[1].ClrType == typeof(int) && sox.Args[2].ClrType == typeof(int) &&
                        sox.Args[3].ClrType == typeof(int) && sox.Args[4].ClrType == typeof(int) && sox.Args[5].ClrType == typeof(int)) {

                        SqlExpression char2 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(2, false, source) }, source);
                        SqlExpression char4 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(4, false, source) }, source);
                        SqlExpression char5 = sql.FunctionCall(typeof(void), "NCHAR", new SqlExpression[1] { sql.ValueFromObject(5, false, source) }, source);

                        // add leading zeros to year by RIGHT(CONVERT(NCHAR(5),10000+@ms),4) 
                        SqlExpression yyRaw = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] {char5,
                                       sql.Add(sql.ValueFromObject(10000, false, source),sox.Args[0])}, source);
                        SqlExpression year = sql.FunctionCall(typeof(string), "RIGHT", new SqlExpression[2] { yyRaw, sql.ValueFromObject(4, false, source) }, source);

                        SqlExpression month = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[1] }, source);
                        SqlExpression day = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[2] }, source);

                        SqlExpression hour = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[3] }, source);
                        SqlExpression minute = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[4] }, source);
                        SqlExpression second = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] { char2, sox.Args[5] }, source);
                        SqlExpression date = sql.Concat(year, sql.ValueFromObject("-", false, source), month, sql.ValueFromObject("-", false, source), day);
                        SqlExpression time = sql.Concat(hour, sql.ValueFromObject(":", false, source), minute, sql.ValueFromObject(":", false, source), second);

                        SqlExpression datetimeoffset = new SqlVariable(typeof(void), null, "DATETIMEOFFSET", source);
                        SqlExpression result, dateAndTime;
                        int timeSpanIndex;

                        if (sox.Args.Count == 7 && sox.Args[6].ClrType == typeof(TimeSpan)) {
                            timeSpanIndex = 6;
                            dateAndTime = sql.Concat(date, sql.ValueFromObject(' ', false, source), time);
                            result = sql.FunctionCall(typeof(DateTimeOffset), "CONVERT", new SqlExpression[3] { datetimeoffset, dateAndTime, sql.ValueFromObject(120, false, source) }, source);
                        }
                        else if (sox.Args.Count == 8 && sox.Args[6].ClrType == typeof(int) && sox.Args[7].ClrType == typeof(TimeSpan)) {
                            timeSpanIndex = 7;
                            // add leading zeros to milliseconds by RIGHT(CONVERT(NCHAR(4),1000+@ms),3) 
                            SqlExpression msRaw = sql.FunctionCall(typeof(string), "CONVERT", new SqlExpression[2] {char4,
                                       sql.Add(sql.ValueFromObject(1000, false, source),sox.Args[6])}, source);
                            SqlExpression ms = sql.FunctionCall(typeof(string), "RIGHT", new SqlExpression[2] { msRaw, sql.ValueFromObject(3, false, source) }, source);
                            dateAndTime = sql.Concat(date, sql.ValueFromObject(' ', false, source), time, sql.ValueFromObject('.', false, source), ms);
                            result = sql.FunctionCall(typeof(DateTimeOffset), "CONVERT", new SqlExpression[3] { datetimeoffset, dateAndTime, sql.ValueFromObject(121, false, source) }, source);
                        }
                        else {
                            throw Error.UnsupportedDateTimeOffsetConstructorForm();
                        }

                        return sql.FunctionCall(typeof(DateTimeOffset), "TODATETIMEOFFSET",
                                                new SqlExpression[2] 
                                                { 
                                                    result, 
                                                    sql.ConvertToInt(sql.ConvertToBigint(sql.Divide(sql.ConvertTimeToDouble(sox.Args[timeSpanIndex]), TimeSpan.TicksPerMinute)))
                                                },
                                                source);
                    }
                }
                throw Error.UnsupportedDateTimeOffsetConstructorForm();
            }
        internal static bool AreSimilar(SqlExpression node1, SqlExpression node2)
        {
            if (node1 == node2)
            {
                return(true);
            }
            if (node1 == null || node2 == null)
            {
                return(false);
            }
            if (node1.NodeType != node2.NodeType ||
                node1.ClrType != node2.ClrType ||
                node1.SqlType != node2.SqlType)
            {
                return(false);
            }
            switch (node1.NodeType)
            {
            case SqlNodeType.New:
            {
                SqlNew new1 = (SqlNew)node1;
                SqlNew new2 = (SqlNew)node2;
                if (new1.Args.Count != new2.Args.Count ||
                    new1.Members.Count != new2.Members.Count)
                {
                    return(false);
                }
                for (int i = 0, n = new1.Args.Count; i < n; i++)
                {
                    if (!AreSimilar(new1.Args[i], new2.Args[i]))
                    {
                        return(false);
                    }
                }
                for (int i = 0, n = new1.Members.Count; i < n; i++)
                {
                    if (!MetaPosition.AreSameMember(new1.Members[i].Member, new2.Members[i].Member) ||
                        !AreSimilar(new1.Members[i].Expression, new2.Members[i].Expression))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ColumnRef:
            {
                SqlColumnRef cref1 = (SqlColumnRef)node1;
                SqlColumnRef cref2 = (SqlColumnRef)node2;
                return(cref1.Column.Ordinal == cref2.Column.Ordinal);
            }

            case SqlNodeType.Link:
            {
                SqlLink l1 = (SqlLink)node1;
                SqlLink l2 = (SqlLink)node2;
                if (!MetaPosition.AreSameMember(l1.Member.Member, l2.Member.Member))
                {
                    return(false);
                }
                if (l1.KeyExpressions.Count != l2.KeyExpressions.Count)
                {
                    return(false);
                }
                for (int i = 0, c = l1.KeyExpressions.Count; i < c; ++i)
                {
                    if (!AreSimilar(l1.KeyExpressions[i], l2.KeyExpressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.Value:
                return(Object.Equals(((SqlValue)node1).Value, ((SqlValue)node2).Value));

            case SqlNodeType.OptionalValue:
            {
                SqlOptionalValue ov1 = (SqlOptionalValue)node1;
                SqlOptionalValue ov2 = (SqlOptionalValue)node2;
                return(AreSimilar(ov1.Value, ov2.Value));
            }

            case SqlNodeType.ValueOf:
            case SqlNodeType.OuterJoinedValue:
                return(AreSimilar(((SqlUnary)node1).Operand, ((SqlUnary)node2).Operand));

            case SqlNodeType.Lift:
                return(AreSimilar(((SqlLift)node1).Expression, ((SqlLift)node2).Expression));

            case SqlNodeType.Grouping:
            {
                SqlGrouping g1 = (SqlGrouping)node1;
                SqlGrouping g2 = (SqlGrouping)node2;
                return(AreSimilar(g1.Key, g2.Key) && AreSimilar(g1.Group, g2.Group));
            }

            case SqlNodeType.ClientArray:
            {
                SqlClientArray a1 = (SqlClientArray)node1;
                SqlClientArray a2 = (SqlClientArray)node2;
                if (a1.Expressions.Count != a2.Expressions.Count)
                {
                    return(false);
                }
                for (int i = 0, n = a1.Expressions.Count; i < n; i++)
                {
                    if (!AreSimilar(a1.Expressions[i], a2.Expressions[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.UserColumn:
                return(((SqlUserColumn)node1).Name == ((SqlUserColumn)node2).Name);

            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 (!AreSimilar(c1.Whens[i].Match, c2.Whens[i].Match) ||
                        !AreSimilar(c1.Whens[i].Value, c2.Whens[i].Value))
                    {
                        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 (!AreSimilar(c1.Whens[i].Match, c2.Whens[i].Match) ||
                        !AreSimilar(c1.Whens[i].Value, c2.Whens[i].Value))
                    {
                        return(false);
                    }
                }
                return(AreSimilar(c1.Else, c2.Else));
            }

            case SqlNodeType.TypeCase:
            {
                SqlTypeCase c1 = (SqlTypeCase)node1;
                SqlTypeCase c2 = (SqlTypeCase)node2;
                if (!AreSimilar(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 (!AreSimilar(c1.Whens[i].Match, c2.Whens[i].Match))
                    {
                        return(false);
                    }
                    if (!AreSimilar(c1.Whens[i].TypeBinding, c2.Whens[i].TypeBinding))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.DiscriminatedType:
            {
                SqlDiscriminatedType dt1 = (SqlDiscriminatedType)node1;
                SqlDiscriminatedType dt2 = (SqlDiscriminatedType)node2;
                return(AreSimilar(dt1.Discriminator, dt2.Discriminator));
            }

            case SqlNodeType.JoinedCollection:
            {
                SqlJoinedCollection j1 = (SqlJoinedCollection)node1;
                SqlJoinedCollection j2 = (SqlJoinedCollection)node2;
                return(AreSimilar(j1.Count, j2.Count) && AreSimilar(j1.Expression, j2.Expression));
            }

            case SqlNodeType.Member:
            {
                SqlMember m1 = (SqlMember)node1;
                SqlMember m2 = (SqlMember)node2;
                return(m1.Member == m2.Member && AreSimilar(m1.Expression, m2.Expression));
            }

            case SqlNodeType.ClientQuery:
            {
                SqlClientQuery cq1 = (SqlClientQuery)node1;
                SqlClientQuery cq2 = (SqlClientQuery)node2;
                if (cq1.Arguments.Count != cq2.Arguments.Count)
                {
                    return(false);
                }
                for (int i = 0, n = cq1.Arguments.Count; i < n; i++)
                {
                    if (!AreSimilar(cq1.Arguments[i], cq2.Arguments[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.MethodCall:
            {
                SqlMethodCall mc1 = (SqlMethodCall)node1;
                SqlMethodCall mc2 = (SqlMethodCall)node2;
                if (mc1.Method != mc2.Method || !AreSimilar(mc1.Object, mc2.Object))
                {
                    return(false);
                }
                if (mc1.Arguments.Count != mc2.Arguments.Count)
                {
                    return(false);
                }
                for (int i = 0, n = mc1.Arguments.Count; i < n; i++)
                {
                    if (!AreSimilar(mc1.Arguments[i], mc2.Arguments[i]))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            case SqlNodeType.ClientParameter:
            default:
                return(false);
            }
        }
 internal override SqlExpression VisitNew(SqlNew sox) {
     if (!this.isDebugMode) {
         throw Error.InvalidFormatNode("New");
     }
     sb.Append("new ");
     sb.Append(sox.ClrType.Name);
     sb.Append("{ ");
     // Visit Args
     for (int i = 0, n = sox.Args.Count; i < n; i++)
     {
         SqlExpression argExpr = sox.Args[i];
         if (i > 0) sb.Append(", ");
         sb.Append(sox.ArgMembers[i].Name);
         sb.Append(" = ");
         this.Visit(argExpr);
     }
     // Visit Members
     for (int i = 0, n = sox.Members.Count; i < n; i++) {
         SqlMemberAssign ma = sox.Members[i];
         if (i > 0) sb.Append(", ");
         string ename = this.InferName(ma.Expression, null);
         if (ename != ma.Member.Name) {
             sb.Append(ma.Member.Name);
             sb.Append(" = ");
         }
         this.Visit(ma.Expression);
     }
     sb.Append(" }");
     return sox;
 }
 private SqlExpression TranslateNewTimeSpan(SqlNew sox) {
     if (sox.Args.Count == 1) {
         return sql.ConvertTo(typeof(TimeSpan), sox.Args[0]);
     }
     else if (sox.Args.Count == 3) {
         // TimeSpan(hours, minutes, seconds)
         SqlExpression hours = sql.ConvertToBigint(sox.Args[0]);
         SqlExpression minutes = sql.ConvertToBigint(sox.Args[1]);
         SqlExpression seconds = sql.ConvertToBigint(sox.Args[2]);
         SqlExpression TicksFromHours = sql.Multiply(hours, TimeSpan.TicksPerHour);
         SqlExpression TicksFromMinutes = sql.Multiply(minutes, TimeSpan.TicksPerMinute);
         SqlExpression TicksFromSeconds = sql.Multiply(seconds, TimeSpan.TicksPerSecond);
         return sql.ConvertTo(typeof(TimeSpan), sql.Add(TicksFromHours, TicksFromMinutes, TicksFromSeconds));
     }
     else {
         SqlExpression days = sql.ConvertToBigint(sox.Args[0]);
         SqlExpression hours = sql.ConvertToBigint(sox.Args[1]);
         SqlExpression minutes = sql.ConvertToBigint(sox.Args[2]);
         SqlExpression seconds = sql.ConvertToBigint(sox.Args[3]);
         SqlExpression TicksFromDays = sql.Multiply(days, TimeSpan.TicksPerDay);
         SqlExpression TicksFromHours = sql.Multiply(hours, TimeSpan.TicksPerHour);
         SqlExpression TicksFromMinutes = sql.Multiply(minutes, TimeSpan.TicksPerMinute);
         SqlExpression TicksFromSeconds = sql.Multiply(seconds, TimeSpan.TicksPerSecond);
         SqlExpression totalTicks = sql.Add(TicksFromDays, TicksFromHours, TicksFromMinutes, TicksFromSeconds);
         if (sox.Args.Count == 4) {
             // TimeSpan(days, hours, minutes, seconds)
             return sql.ConvertTo(typeof(TimeSpan), totalTicks);
         }
         else if (sox.Args.Count == 5) {
             // TimeSpan(days, hours, minutes, seconds, milliseconds)
             SqlExpression milliseconds = sql.ConvertToBigint(sox.Args[4]);
             SqlExpression ticksFromMs = sql.Multiply(milliseconds, TimeSpan.TicksPerMillisecond);
             return sql.ConvertTo(typeof(TimeSpan), sql.Add(totalTicks, ticksFromMs));
         }
     }
     throw Error.UnsupportedTimeSpanConstructorForm();
 }