Exemplo n.º 1
0
        /// <summary>
        /// Parses a method invocation.
        /// This method is used to implement the virtual extensions feature, including:
        /// <para>Argument level:</para>
        /// <para>- x.Not(...) => (NOT ...)</para>
        /// <para>- x.Distinct(expression) => DISTINCT expression</para>
        /// <para>Element level:</para>
        /// <para>- x.Element.As(name) => Element AS name</para>
        /// <para>- x.Element.In(arg, ...) => Element IN (arg, ...)</para>
        /// <para>- x.Element.NotIn(arg, ...) => NOT Element IN (arg, ...)</para>
        /// <para>- x.Element.InList(...) / .NotInList(...) => Interprets the single argument as a list</para>
        /// <para>- x.Element.Between(arg1, arg2) => Element BETWEEN arg1 AND arg2</para>
        /// <para>- x.Element.Like(arg) => Element LIKE arg</para>
        /// <para>- x.Element.NotLike(arg) => Element NOT LIKE arg</para>
        /// <para>Default case:</para>
        /// <para>- The default case where the name of the method and its arguments are parsed as-is.</para>
        /// </summary>
        protected virtual string OnParseMethod(DynamicNode.Method obj, IParameterCollection pc, bool nulls)
        {
            string        name   = obj.Name.ToUpper();
            string        parent = obj.Host == null ? null : Parse(obj.Host, pc, nulls);
            string        item   = null;
            StringBuilder sb     = new StringBuilder();
            string        str    = null;
            int           i      = 0;
            IEnumerable   iter   = null;

            // Root-level methods...
            if (parent == null)
            {
                switch (name)
                {
                case "NOT":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("NOT() argument list is null.");
                    }
                    if (obj.Arguments.Length != 1)
                    {
                        throw new ArgumentException("NOT() requires just one argument.");
                    }
                    item = Parse(obj.Arguments[0], pc, nulls);
                    return("(NOT {0})".FormatWith(item));

                case "DISTINCT":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("DISTINCT() argument list is null.");
                    }
                    if (obj.Arguments.Length != 1)
                    {
                        throw new ArgumentException("DISTINCT() requires just one argument.");
                    }
                    item = Parse(obj.Arguments[0], pc, nulls);
                    return("DISTINCT {0}".FormatWith(item));
                }
            }

            // Item-level methods...
            switch (name)
            {
            case "AS":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("AS() argument list is null.");
                }
                if (obj.Arguments.Length != 1)
                {
                    throw new ArgumentException("AS() requires just one argument.");
                }
                item = Parse(obj.Arguments[0], pc, nulls);
                return("{0} AS {1}".FormatWith(parent, item));

            case "IN":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("IN() argument list is null.");
                }
                if (obj.Arguments.Length == 0)
                {
                    throw new ArgumentException("IN() requires at least one argument.");
                }
                for (i = 0; i < obj.Arguments.Length; i++)
                {
                    str  = Parse(obj.Arguments[i], pc, nulls);
                    item = item == null ? str : "{0}, {1}".FormatWith(item, str);
                }
                return("{0} IN ({1})".FormatWith(parent, item));

            case "NOTIN":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("NOTIN() argument list is null.");
                }
                if (obj.Arguments.Length == 0)
                {
                    throw new ArgumentException("NOTIN() requires at least one argument.");
                }
                for (i = 0; i < obj.Arguments.Length; i++)
                {
                    str  = Parse(obj.Arguments[i], pc, nulls);
                    item = item == null ? str : "{0}, {1}".FormatWith(item, str);
                }
                return("NOT {0} IN ({1})".FormatWith(parent, item));

            case "INLIST":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("INLIST() argument list is null.");
                }
                if (obj.Arguments.Length != 1)
                {
                    throw new ArgumentException("INLIST() requires just one argument.");
                }
                iter = obj.Arguments[0] as IEnumerable; if (iter == null)
                {
                    throw new ArgumentException("Argument '{0}' is not an iterable one.".FormatWith(obj.Arguments[0].Sketch()));
                }
                foreach (var temp in iter)
                {
                    str  = Parse(temp, pc, nulls);
                    item = item == null ? str : "{0}, {1}".FormatWith(item, str);
                }
                return("{0} IN ({1})".FormatWith(parent, item));

            case "NOTINLIST":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("NOTINLIST() argument list is null.");
                }
                if (obj.Arguments.Length != 1)
                {
                    throw new ArgumentException("NOTINLIST() requires just one argument.");
                }
                iter = obj.Arguments[0] as IEnumerable; if (iter == null)
                {
                    throw new ArgumentException("Argument '{0}' is not an iterable one.".FormatWith(obj.Arguments[0].Sketch()));
                }
                foreach (var temp in iter)
                {
                    str  = Parse(temp, pc, nulls);
                    item = item == null ? str : "{0}, {1}".FormatWith(item, str);
                }
                return("NOT {0} IN ({1})".FormatWith(parent, item));

            case "BETWEEN":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("BETWEEN() argument list is null.");
                }
                if (obj.Arguments.Length != 2)
                {
                    throw new ArgumentException("BETWEEN() requires two arguments.");
                }
                item = Parse(obj.Arguments[0], pc, nulls);
                str  = Parse(obj.Arguments[1], pc, nulls);
                return("{0} BETWEEN ({1}) AND ({2})".FormatWith(parent, item, str));

            case "LIKE":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("LIKE() argument list is null.");
                }
                if (obj.Arguments.Length != 1)
                {
                    throw new ArgumentException("LIKE() requires just one argument.");
                }
                item = Parse(obj.Arguments[0], pc, nulls);
                return("{0} LIKE ({1})".FormatWith(parent, item));

            case "NOTLIKE":
                if (obj.Arguments == null)
                {
                    throw new ArgumentException("NOTLIKE() argument list is null.");
                }
                if (obj.Arguments.Length != 1)
                {
                    throw new ArgumentException("NOTLIKE() requires just one argument.");
                }
                item = Parse(obj.Arguments[0], pc, nulls);
                return("{0} NOT LIKE ({1})".FormatWith(parent, item));
            }

            // Intercepting "rounded" escape syntax because the "tag" is interpreted as a method name...
            DynamicNode node = obj; while (node.Host != null)

            {
                node = node.Host;
            }

            if (((DynamicNode.Argument)node).Name == obj.Name)
            {
                node = new DynamicNode.Invoke((DynamicNode.Argument)node, obj.Arguments);
                item = OnParseInvoke((DynamicNode.Invoke)node, pc, nulls);
                node.Dispose();

                string host = obj.Host == null ? null : Parse(obj.Host, pc, nulls);
                string temp = host == null ? item : "{0}{1}".FormatWith(host, item);
                return(temp);
            }

            // Default case...
            name = parent == null ? obj.Name : "{0}.{1}".FormatWith(parent, obj.Name);
            sb.AppendFormat("{0}(", name); if (obj.Arguments != null)
            {
                for (i = 0; i < obj.Arguments.Length; i++)
                {
                    if (i != 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(Parse(obj.Arguments[i], pc, nulls));
                }
            }
            sb.Append(")");
            return(sb.ToString());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Parses a method invocation.
        /// This method is used to implement the virtual extensions feature, including:
        /// <para>Argument level:</para>
        /// <para>- x.Not(...) => (NOT ...)</para>
        /// <para>- x.Distinct(expression) => DISTINCT expression</para>
        /// <para>Element level:</para>
        /// <para>- x.Element.As(name) => Element AS name</para>
        /// <para>- x.Element.In(arg, ...) => Element IN (arg, ...)</para>
        /// <para>- x.Element.NotIn(arg, ...) => NOT Element IN (arg, ...)</para>
        /// <para>- x.Element.Between(arg1, arg2) => Element BETWEEN arg1 AND arg2</para>
        /// <para>- x.Element.Like(arg) => Element LIKE arg</para>
        /// <para>- x.Element.NotLike(arg) => Element NOT LIKE arg</para>
        /// <para>Default case:</para>
        /// <para>- The default case where the name of the method and its arguments are parsed as-is.</para>
        /// <para>This overriden method adds the following ones:</para>
        /// <para>- x.Element.Cast(type)</para>
        /// <para>- x.Element.Left(n), x.Element.Right(n)</para>
        /// <para>- x.Element.Len(), x.Element.Lower(), x.Element.Upper()</para>
        /// <para>- x.Element.Year(), x.Element.Month(), x.Element.Day()</para>
        /// <para>- x.Element.Hour(), x.Element.Minute(), x.Element.Second(), x.Element.Millisecond()</para>
        /// <para>- x.Element.Offset()</para>
        /// <para>- x.Element.Contains(item), x.Element.Patindex(num), x.Element.Substring(start,len)</para>
        /// <para>- x.Element.Trim(), x.Element.Rtrim(), x.Element.Rtrim()</para>
        /// </summary>
        protected override string OnParseMethod(DynamicNode.Method obj, Core.IParameterCollection pars, bool nulls)
        {
            string name   = obj.Name.ToUpper();
            string parent = obj.Host == null ? null : Parse(obj.Host, pars, nulls);
            string item   = null;
            string extra  = null;

            // Root-level methods...
            if (obj.Host == null)
            {
                switch (name)
                {
                case "CAST":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("CAST() argument list is null.");
                    }
                    if (obj.Arguments.Length != 2)
                    {
                        throw new ArgumentException("CAST() requires two arguments.");
                    }
                    item  = Parse(obj.Arguments[0], pars, nulls);
                    extra = Parse(obj.Arguments[1], pars, nulls);
                    return(string.Format("CAST({0} AS {1})", item, extra));
                }
            }

            // Item-level methods...
            if (obj.Host != null)
            {
                switch (name)
                {
                case "LEFT":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("LEFT() argument list is null.");
                    }
                    if (obj.Arguments.Length != 1)
                    {
                        throw new ArgumentException("LEFT() requires one argument.");
                    }
                    item = Parse(obj.Arguments[0], pars, nulls);
                    return(string.Format("LEFT({0}, {1})", parent, item));

                case "RIGHT":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("RIGHT() argument list is null.");
                    }
                    if (obj.Arguments.Length != 1)
                    {
                        throw new ArgumentException("RIGHT() requires one argument.");
                    }
                    item = Parse(obj.Arguments[0], pars, nulls);
                    return(string.Format("RIGHT({0}, {1})", parent, item));

                case "LEN":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("LEN() shall be a parameterless method.");
                    }
                    return(string.Format("LEN({0})", parent));

                case "LOWER":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("LOWER() shall be a parameterless method.");
                    }
                    return(string.Format("LOWER({0})", parent));

                case "UPPER":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("UPPER() shall be a parameterless method.");
                    }
                    return(string.Format("UPPER({0})", parent));

                case "YEAR":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("YEAR() shall be a parameterless method.");
                    }
                    return(string.Format("DATEPART(YEAR, {0})", parent));

                case "MONTH":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("MONTH() shall be a parameterless method.");
                    }
                    return(string.Format("DATEPART(MONTH, {0})", parent));

                case "DAY":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("DAY() shall be a parameterless method.");
                    }
                    return(string.Format("DATEPART(DAY, {0})", parent));

                case "HOUR":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("HOUR() shall be a parameterless method.");
                    }
                    return(string.Format("DATEPART(HOUR, {0})", parent));

                case "MINUTE":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("MINUTE() shall be a parameterless method.");
                    }
                    return(string.Format("DATEPART(MINUTE, {0})", parent));

                case "SECOND":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("SECOND() shall be a parameterless method.");
                    }
                    return(string.Format("SECOND(DAY, {0})", parent));

                case "MILLISECOND":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("MILLISECOND() shall be a parameterless method.");
                    }
                    return(string.Format("DATEPART(MILLISECOND, {0})", parent));

                case "OFFSET":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("OFFSET() shall be a parameterless method.");
                    }
                    return(string.Format("DATEPART(TZ, {0})", parent));

                case "CONTAINS":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("CONTAINS() argument list is null.");
                    }
                    if (obj.Arguments.Length != 1)
                    {
                        throw new ArgumentException("CONTAINS() requires just one argument.");
                    }
                    item = Parse(obj.Arguments[0], pars, nulls);
                    return(string.Format("CONTAINS({0}, {1})", parent, item));

                case "PATINDEX":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("PATINDEX() argument list is null.");
                    }
                    if (obj.Arguments.Length != 1)
                    {
                        throw new ArgumentException("PATINDEX() requires just one argument.");
                    }
                    item = Parse(obj.Arguments[0], pars, nulls);
                    return(string.Format("PATINDEX({1}, {0})", parent, item));                            // Beware, indexes inverted!

                case "SUBSTRING":
                    if (obj.Arguments == null)
                    {
                        throw new ArgumentException("SUBSTRING() argument list is null.");
                    }
                    if (obj.Arguments.Length != 2)
                    {
                        throw new ArgumentException("SUBSTRING() requires two arguments.");
                    }
                    item  = Parse(obj.Arguments[0], pars, nulls);
                    extra = Parse(obj.Arguments[1], pars, nulls);
                    return(string.Format("SUBSTRING({0}, {1}, {2})", parent, item, extra));

                case "LTRIM":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("LTRIM() is a parameterless method.");
                    }
                    return(string.Format("LTRIM({0})", parent));

                case "RTRIM":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("RTRIM() is a parameterless method.");
                    }
                    return(string.Format("RTRIM({0})", parent));

                case "TRIM":
                    if (obj.Arguments != null)
                    {
                        throw new ArgumentException("TRIM() is a parameterless method.");
                    }
                    return(string.Format("LTRIM(RTRIM({0}))", parent));
                }
            }

            // Reverting to whatever the base class intercepts...
            return(base.OnParseMethod(obj, pars, nulls));
        }