//[SqlFunction(Name = "Final SQL(Custom)", DataAccess = DataAccessKind.None, IsDeterministic = true)]
    // EXEC [A].[B] :Param1, :[Param2], :[$Params;Param2]
    public static String FinalSQLEx(String ASQL, UDT.TParams AParams, Boolean AOnlyQuoted)
    {
        if(String.IsNullOrEmpty(ASQL)) return ASQL;

        StringBuilder Result = new StringBuilder(ASQL.Length);

        Sql.ParamsParser Parser =
          new Sql.ParamsParser
          (
            ASQL,
            ':',
            TCommentMethods.DoubleMinus | TCommentMethods.SlashRange,
            new char[] { '[' },
            new char[] { '\'', '"', '[' }
          );

        while (Parser.MoveNext())
        {
          Result.Append(Parser.Current.Gap);
          Object LParamValue;
          if (!String.IsNullOrEmpty(Parser.Current.Value))
        if (AOnlyQuoted && (Parser.Current.Quote == (Char)0))
        {
          Result.Append(':');
          Result.Append(Parser.Current.Value);
        }
        else if (AParams == null)
          Result.Append("NULL");
        else if(Parser.Current.Value[0] == '$')
        {
          String LValues = (Parser.Current.Value.Length == 1 ? AParams.CastAsString() : AParams.CastAsStringCustom(Parser.Current.Value.Substring(1)));
          Result.Append(LValues == null ? "NULL" : Strings.QuoteString(LValues));
        }
        else if(AParams.TryGetValue(Parser.Current.Value, out LParamValue))
        {
          Result.Append(Sql.ValueToText(LParamValue, Sql.ValueDbStyle.SQL, '\''));
        }
        else
          Result.Append("NULL");
        }

        return Result.ToString();
    }