예제 #1
0
        /// <summary>
        /// Parsers an invocation operation.
        /// </summary>
        protected virtual string OnParseInvoke(DynamicNode.Invoke obj, IParameterCollection pc, bool nulls)
        {
            if (obj.Arguments == null || obj.Arguments.Length == 0)
            {
                return(string.Empty);
            }

            StringBuilder sb = new StringBuilder(); foreach (var arg in obj.Arguments)
            {
                if (arg is string)
                {
                    sb.Append((string)arg);
                }
                else
                {
                    sb.Append(Parse(arg, pc, nulls));
                }
            }

            string host = obj.Host == null ? null : Parse(obj.Host, pc, nulls);
            string name = host == null?sb.ToString() : "{0}{1}".FormatWith(host, sb.ToString());

            return(name);
        }
예제 #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.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());
        }
예제 #3
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();
		}