private void SqlReplace(string query, TextWriter builder)
        {
            SqlReplace(query, '@', builder, p =>
            {
                object value;

                if (TryGetParamValue(p, out value))
                {
                    Func <string, string> finalAction = s => s;
                    var inClause = false;

                    if (builder.ToString().EndsWith(" in "))
                    {
                        finalAction = s => "(" + s + ")";
                        inClause    = true;
                    }
                    else if (builder.ToString().EndsWith(" in ("))
                    {
                        inClause = true;
                    }


                    IFormattable num;
                    if (value == null
#if DBDATA
                        || value == DBNull.Value
#endif
                        )
                    {
                        return(finalAction("null"));
                    }
                    else if (ServerContext.TryCastNumber(value, out num))
                    {
                        return(finalAction(_sqlFormatter.Format(num)));
                    }
                    else if (value is string)
                    {
                        return(finalAction(SqlFormatter.Quote(ServerContext.RenderSqlEnum(value, false, o => _sqlFormatter.Format(o)))));
                    }
                    else if (inClause && value is IEnumerable)
                    {
                        return(finalAction(ServerContext.RenderSqlEnum(value, true, o => _sqlFormatter.Format(o))));
                    }
                    else if (value is DateTime || value is bool || value is Guid)
                    {
                        return(finalAction("'" + ServerContext.RenderSqlEnum(value, false, o => _sqlFormatter.Format(o)) + "'"));
                    }
                    else
                    {
                        return(finalAction(SqlFormatter.Quote(ServerContext.RenderSqlEnum(value, false, o => _sqlFormatter.Format(o)))));
                    }
                }
                else
                {
                    return("@" + p);
                }
            });
        }
        internal static string RenderSqlEnum(object value, bool quoteStrings, Func <IFormattable, string> numberRenderer, Func <object, string> stringRenderer, Func <string> emptyEnumRenderer)
        {
            if (value is string)
            {
                return(stringRenderer(value));
            }

            var first   = true;
            var builder = new StringBuilder();

            if (TryGetNumericEnumerable(value, out var enumerable))
            {
                foreach (var item in enumerable)
                {
                    if (!first)
                    {
                        builder.Append(",");
                    }
                    builder.Append(numberRenderer((IFormattable)item));
                    first = false;
                }

                if (first)
                {
                    return(emptyEnumRenderer?.Invoke());
                }
            }
            else
            {
                enumerable = value as IEnumerable;
                if (enumerable != null)
                {
                    foreach (var item in enumerable)
                    {
                        if (!first)
                        {
                            builder.Append(",");
                        }
                        if (quoteStrings)
                        {
                            builder.Append(SqlFormatter.Quote(stringRenderer(item).Replace("'", "''")));
                        }
                        else
                        {
                            builder.Append(stringRenderer(item));
                        }
                        first = false;
                    }

                    // Nothing was written as there were not values in the IEnumerable
                    // Therefore, write a bogus value to match zero results
                    if (first)
                    {
                        var empty = emptyEnumRenderer?.Invoke();
                        if (empty == null)
                        {
                            return(null);
                        }
                        return(quoteStrings
              ? "N'" + emptyEnumRenderer?.Invoke() + "'"
              : emptyEnumRenderer?.Invoke());
                    }
                }
                else
                {
                    return(stringRenderer(value));
                }
            }

            return(builder.ToString());
        }