sphinx 0.9.10.2094 → 0.9.10.2122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +24 -4
 - data/VERSION.yml +1 -1
 - data/lib/sphinx.rb +28 -7
 - data/lib/sphinx/client.rb +61 -223
 - data/lib/sphinx/constants.rb +189 -0
 - data/lib/sphinx/indifferent_access.rb +152 -0
 - data/spec/client_response_spec.rb +4 -4
 - data/spec/client_spec.rb +31 -21
 - data/spec/client_validations_spec.rb +12 -3
 - data/sphinx.gemspec +4 -2
 - metadata +4 -2
 
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            = Sphinx Client API 
     | 
| 
      
 1 
     | 
    
         
            +
            = Sphinx Client API
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            This document gives an overview of what is Sphinx itself and how to use it 
         
     | 
| 
       4 
4 
     | 
    
         
             
            from your Ruby on Rails application. For more information or documentation, 
         
     | 
| 
         @@ -138,10 +138,10 @@ will be finally executed successfully. 
     | 
|
| 
       138 
138 
     | 
    
         
             
            Most Sphinx API methods expecting for special constants will be passed.
         
     | 
| 
       139 
139 
     | 
    
         
             
            For example:
         
     | 
| 
       140 
140 
     | 
    
         | 
| 
       141 
     | 
    
         
            -
              sphinx.set_match_mode(Sphinx:: 
     | 
| 
      
 141 
     | 
    
         
            +
              sphinx.set_match_mode(Sphinx::SPH_MATCH_ANY)
         
     | 
| 
       142 
142 
     | 
    
         | 
| 
       143 
     | 
    
         
            -
            Please note that these constants defined in a <tt>Sphinx 
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
      
 143 
     | 
    
         
            +
            Please note that these constants defined in a <tt>Sphinx</tt>
         
     | 
| 
      
 144 
     | 
    
         
            +
            module. You can use symbols or strings instead of these awful
         
     | 
| 
       145 
145 
     | 
    
         
             
            constants:
         
     | 
| 
       146 
146 
     | 
    
         | 
| 
       147 
147 
     | 
    
         
             
              sphinx.set_match_mode(:any)
         
     | 
| 
         @@ -195,6 +195,26 @@ save the order of records established by Sphinx. 
     | 
|
| 
       195 
195 
     | 
    
         
             
              docs = posts.map(&:body)
         
     | 
| 
       196 
196 
     | 
    
         
             
              excerpts = sphinx.build_excerpts(docs, 'index', 'test')
         
     | 
| 
       197 
197 
     | 
    
         | 
| 
      
 198 
     | 
    
         
            +
            == Logging
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
            You can ask Sphinx client API to log it's activity to some log. In
         
     | 
| 
      
 201 
     | 
    
         
            +
            order to do that you can pass a logger object into the <tt>Sphinx::Client</tt>
         
     | 
| 
      
 202 
     | 
    
         
            +
            constructor:
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
              require 'logger'
         
     | 
| 
      
 205 
     | 
    
         
            +
              Sphinx::Client.new(Logger.new(STDOUT)).query('test')
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
            Logger object should respond to methods :debug, :info, and :warn, and
         
     | 
| 
      
 208 
     | 
    
         
            +
            accept blocks (this is what standard Ruby <tt>Logger</tt> class does).
         
     | 
| 
      
 209 
     | 
    
         
            +
            Here is what you will see in your log:
         
     | 
| 
      
 210 
     | 
    
         
            +
             
     | 
| 
      
 211 
     | 
    
         
            +
            * <tt>DEBUG</tt> -- <tt>query</tt>, <tt>add_query</tt>, <tt>run_queries</tt>
         
     | 
| 
      
 212 
     | 
    
         
            +
              method calls with configured filters.
         
     | 
| 
      
 213 
     | 
    
         
            +
            * <tt>INFO</tt> -- initialization with Sphinx version, servers change,
         
     | 
| 
      
 214 
     | 
    
         
            +
              attempts to re-connect, and all attempts to do an API call with server
         
     | 
| 
      
 215 
     | 
    
         
            +
              where request being performed.
         
     | 
| 
      
 216 
     | 
    
         
            +
            * <tt>WARN</tt> -- various connection and socket errors.
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
       198 
218 
     | 
    
         
             
            == Support
         
     | 
| 
       199 
219 
     | 
    
         | 
| 
       200 
220 
     | 
    
         
             
            Source code:
         
     | 
    
        data/VERSION.yml
    CHANGED
    
    
    
        data/lib/sphinx.rb
    CHANGED
    
    | 
         @@ -3,7 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            # Author::    Dmytro Shteflyuk <mailto:kpumuk@kpumuk.info>.
         
     | 
| 
       4 
4 
     | 
    
         
             
            # Copyright:: Copyright (c) 2006 — 2009 Dmytro Shteflyuk
         
     | 
| 
       5 
5 
     | 
    
         
             
            # License::   Distributes under the same terms as Ruby
         
     | 
| 
       6 
     | 
    
         
            -
            # Version::   0.9.10- 
     | 
| 
      
 6 
     | 
    
         
            +
            # Version::   0.9.10-r2122
         
     | 
| 
       7 
7 
     | 
    
         
             
            # Website::   http://kpumuk.info/projects/ror-plugins/sphinx
         
     | 
| 
       8 
8 
     | 
    
         
             
            # Sources::   http://github.com/kpumuk/sphinx
         
     | 
| 
       9 
9 
     | 
    
         
             
            #
         
     | 
| 
         @@ -15,15 +15,36 @@ module Sphinx 
     | 
|
| 
       15 
15 
     | 
    
         
             
                config = YAML.load(File.read(File.dirname(__FILE__) + '/../VERSION.yml'))
         
     | 
| 
       16 
16 
     | 
    
         
             
                "#{config[:major]}.#{config[:minor]}.#{config[:patch]}.#{config[:build]}"
         
     | 
| 
       17 
17 
     | 
    
         
             
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              # Base class for all Sphinx errors
         
     | 
| 
      
 20 
     | 
    
         
            +
              class SphinxError < StandardError; end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              # Connect error occurred on the API side.
         
     | 
| 
      
 23 
     | 
    
         
            +
              class SphinxConnectError < SphinxError; end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              # Request error occurred on the API side.
         
     | 
| 
      
 26 
     | 
    
         
            +
              class SphinxResponseError < SphinxError; end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              # Internal error occurred inside searchd.
         
     | 
| 
      
 29 
     | 
    
         
            +
              class SphinxInternalError < SphinxError; end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              # Temporary error occurred inside searchd.
         
     | 
| 
      
 32 
     | 
    
         
            +
              class SphinxTemporaryError < SphinxError; end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              # Unknown error occurred inside searchd.
         
     | 
| 
      
 35 
     | 
    
         
            +
              class SphinxUnknownError < SphinxError; end
         
     | 
| 
       18 
36 
     | 
    
         
             
            end
         
     | 
| 
       19 
37 
     | 
    
         | 
| 
       20 
38 
     | 
    
         
             
            require 'net/protocol'
         
     | 
| 
       21 
39 
     | 
    
         
             
            require 'socket'
         
     | 
| 
       22 
40 
     | 
    
         
             
            require 'zlib'
         
     | 
| 
       23 
41 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
            require  
     | 
| 
       26 
     | 
    
         
            -
            require  
     | 
| 
       27 
     | 
    
         
            -
            require  
     | 
| 
       28 
     | 
    
         
            -
            require  
     | 
| 
       29 
     | 
    
         
            -
            require  
     | 
| 
      
 42 
     | 
    
         
            +
            path = File.dirname(__FILE__)
         
     | 
| 
      
 43 
     | 
    
         
            +
            require "#{path}/sphinx/constants"
         
     | 
| 
      
 44 
     | 
    
         
            +
            require "#{path}/sphinx/indifferent_access"
         
     | 
| 
      
 45 
     | 
    
         
            +
            require "#{path}/sphinx/request"
         
     | 
| 
      
 46 
     | 
    
         
            +
            require "#{path}/sphinx/response"
         
     | 
| 
      
 47 
     | 
    
         
            +
            require "#{path}/sphinx/timeout"
         
     | 
| 
      
 48 
     | 
    
         
            +
            require "#{path}/sphinx/buffered_io"
         
     | 
| 
      
 49 
     | 
    
         
            +
            require "#{path}/sphinx/server"
         
     | 
| 
      
 50 
     | 
    
         
            +
            require "#{path}/sphinx/client"
         
     | 
    
        data/lib/sphinx/client.rb
    CHANGED
    
    | 
         @@ -1,17 +1,4 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Sphinx
         
     | 
| 
       2 
     | 
    
         
            -
              # Base class for all Sphinx errors
         
     | 
| 
       3 
     | 
    
         
            -
              class SphinxError < StandardError; end
         
     | 
| 
       4 
     | 
    
         
            -
              # Connect error occurred on the API side.
         
     | 
| 
       5 
     | 
    
         
            -
              class SphinxConnectError < SphinxError; end
         
     | 
| 
       6 
     | 
    
         
            -
              # Request error occurred on the API side.
         
     | 
| 
       7 
     | 
    
         
            -
              class SphinxResponseError < SphinxError; end
         
     | 
| 
       8 
     | 
    
         
            -
              # Internal error occurred inside searchd.
         
     | 
| 
       9 
     | 
    
         
            -
              class SphinxInternalError < SphinxError; end
         
     | 
| 
       10 
     | 
    
         
            -
              # Temporary error occurred inside searchd.
         
     | 
| 
       11 
     | 
    
         
            -
              class SphinxTemporaryError < SphinxError; end
         
     | 
| 
       12 
     | 
    
         
            -
              # Unknown error occurred inside searchd.
         
     | 
| 
       13 
     | 
    
         
            -
              class SphinxUnknownError < SphinxError; end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
2 
     | 
    
         
             
              # The Sphinx Client API is used to communicate with <tt>searchd</tt>
         
     | 
| 
       16 
3 
     | 
    
         
             
              # daemon and perform requests.
         
     | 
| 
       17 
4 
     | 
    
         
             
              #
         
     | 
| 
         @@ -26,81 +13,8 @@ module Sphinx 
     | 
|
| 
       26 
13 
     | 
    
         
             
              #   excerpts = sphinx.build_excerpts(docs, 'index', 'test')
         
     | 
| 
       27 
14 
     | 
    
         
             
              #
         
     | 
| 
       28 
15 
     | 
    
         
             
              class Client
         
     | 
| 
       29 
     | 
    
         
            -
                 
     | 
| 
       30 
     | 
    
         
            -
                 
     | 
| 
       31 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                # search command
         
     | 
| 
       34 
     | 
    
         
            -
                # @private
         
     | 
| 
       35 
     | 
    
         
            -
                SEARCHD_COMMAND_SEARCH     = 0
         
     | 
| 
       36 
     | 
    
         
            -
                # excerpt command
         
     | 
| 
       37 
     | 
    
         
            -
                # @private
         
     | 
| 
       38 
     | 
    
         
            -
                SEARCHD_COMMAND_EXCERPT    = 1
         
     | 
| 
       39 
     | 
    
         
            -
                # update command
         
     | 
| 
       40 
     | 
    
         
            -
                # @private
         
     | 
| 
       41 
     | 
    
         
            -
                SEARCHD_COMMAND_UPDATE     = 2
         
     | 
| 
       42 
     | 
    
         
            -
                # keywords command
         
     | 
| 
       43 
     | 
    
         
            -
                # @private
         
     | 
| 
       44 
     | 
    
         
            -
                SEARCHD_COMMAND_KEYWORDS   = 3
         
     | 
| 
       45 
     | 
    
         
            -
                # persist command
         
     | 
| 
       46 
     | 
    
         
            -
                # @private
         
     | 
| 
       47 
     | 
    
         
            -
                SEARCHD_COMMAND_PERSIST    = 4
         
     | 
| 
       48 
     | 
    
         
            -
                # status command
         
     | 
| 
       49 
     | 
    
         
            -
                # @private
         
     | 
| 
       50 
     | 
    
         
            -
                SEARCHD_COMMAND_STATUS     = 5
         
     | 
| 
       51 
     | 
    
         
            -
                # query command
         
     | 
| 
       52 
     | 
    
         
            -
                # @private
         
     | 
| 
       53 
     | 
    
         
            -
                SEARCHD_COMMAND_QUERY      = 6
         
     | 
| 
       54 
     | 
    
         
            -
                # flushattrs command
         
     | 
| 
       55 
     | 
    
         
            -
                # @private
         
     | 
| 
       56 
     | 
    
         
            -
                SEARCHD_COMMAND_FLUSHATTRS = 7
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       59 
     | 
    
         
            -
                # Current client-side command implementation versions
         
     | 
| 
       60 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
                # search command version
         
     | 
| 
       63 
     | 
    
         
            -
                # @private
         
     | 
| 
       64 
     | 
    
         
            -
                VER_COMMAND_SEARCH     = 0x117
         
     | 
| 
       65 
     | 
    
         
            -
                # excerpt command version
         
     | 
| 
       66 
     | 
    
         
            -
                # @private
         
     | 
| 
       67 
     | 
    
         
            -
                VER_COMMAND_EXCERPT    = 0x100
         
     | 
| 
       68 
     | 
    
         
            -
                # update command version
         
     | 
| 
       69 
     | 
    
         
            -
                # @private
         
     | 
| 
       70 
     | 
    
         
            -
                VER_COMMAND_UPDATE     = 0x102
         
     | 
| 
       71 
     | 
    
         
            -
                # keywords command version
         
     | 
| 
       72 
     | 
    
         
            -
                # @private
         
     | 
| 
       73 
     | 
    
         
            -
                VER_COMMAND_KEYWORDS   = 0x100
         
     | 
| 
       74 
     | 
    
         
            -
                # persist command version
         
     | 
| 
       75 
     | 
    
         
            -
                # @private
         
     | 
| 
       76 
     | 
    
         
            -
                VER_COMMAND_PERSIST    = 0x000
         
     | 
| 
       77 
     | 
    
         
            -
                # status command version
         
     | 
| 
       78 
     | 
    
         
            -
                # @private
         
     | 
| 
       79 
     | 
    
         
            -
                VER_COMMAND_STATUS     = 0x100
         
     | 
| 
       80 
     | 
    
         
            -
                # query command version
         
     | 
| 
       81 
     | 
    
         
            -
                # @private
         
     | 
| 
       82 
     | 
    
         
            -
                VER_COMMAND_QUERY      = 0x100
         
     | 
| 
       83 
     | 
    
         
            -
                # flushattrs command version
         
     | 
| 
       84 
     | 
    
         
            -
                # @private
         
     | 
| 
       85 
     | 
    
         
            -
                VER_COMMAND_FLUSHATTRS = 0x100
         
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       88 
     | 
    
         
            -
                # Known searchd status codes
         
     | 
| 
       89 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
                # general success, command-specific reply follows
         
     | 
| 
       92 
     | 
    
         
            -
                # @private
         
     | 
| 
       93 
     | 
    
         
            -
                SEARCHD_OK      = 0
         
     | 
| 
       94 
     | 
    
         
            -
                # general failure, command-specific reply may follow
         
     | 
| 
       95 
     | 
    
         
            -
                # @private
         
     | 
| 
       96 
     | 
    
         
            -
                SEARCHD_ERROR   = 1
         
     | 
| 
       97 
     | 
    
         
            -
                # temporaty failure, client should retry later
         
     | 
| 
       98 
     | 
    
         
            -
                # @private
         
     | 
| 
       99 
     | 
    
         
            -
                SEARCHD_RETRY   = 2
         
     | 
| 
       100 
     | 
    
         
            -
                # general success, warning message and command-specific reply follow
         
     | 
| 
       101 
     | 
    
         
            -
                # @private
         
     | 
| 
       102 
     | 
    
         
            -
                SEARCHD_WARNING = 3
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
                include Sphinx::Constants
         
     | 
| 
      
 17 
     | 
    
         
            +
                
         
     | 
| 
       104 
18 
     | 
    
         
             
                #=================================================================
         
     | 
| 
       105 
19 
     | 
    
         
             
                # Some internal attributes to use inside client API
         
     | 
| 
       106 
20 
     | 
    
         
             
                #=================================================================
         
     | 
| 
         @@ -120,118 +34,16 @@ module Sphinx 
     | 
|
| 
       120 
34 
     | 
    
         
             
                # Number of request retries.
         
     | 
| 
       121 
35 
     | 
    
         
             
                # @private
         
     | 
| 
       122 
36 
     | 
    
         
             
                attr_reader :reqretries
         
     | 
| 
       123 
     | 
    
         
            -
                # Log debug/info/warn 
     | 
| 
      
 37 
     | 
    
         
            +
                # Log debug/info/warn to the given Logger, defaults to nil.
         
     | 
| 
       124 
38 
     | 
    
         
             
                # @private
         
     | 
| 
       125 
39 
     | 
    
         
             
                attr_reader :logger
         
     | 
| 
       126 
40 
     | 
    
         | 
| 
       127 
     | 
    
         
            -
                 
     | 
| 
       128 
     | 
    
         
            -
                #  
     | 
| 
       129 
     | 
    
         
            -
                 
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
                #  
     | 
| 
       132 
     | 
    
         
            -
                 
     | 
| 
       133 
     | 
    
         
            -
                # match any query word
         
     | 
| 
       134 
     | 
    
         
            -
                SPH_MATCH_ANY       = 1
         
     | 
| 
       135 
     | 
    
         
            -
                # match this exact phrase
         
     | 
| 
       136 
     | 
    
         
            -
                SPH_MATCH_PHRASE    = 2
         
     | 
| 
       137 
     | 
    
         
            -
                # match this boolean query
         
     | 
| 
       138 
     | 
    
         
            -
                SPH_MATCH_BOOLEAN   = 3
         
     | 
| 
       139 
     | 
    
         
            -
                # match this extended query
         
     | 
| 
       140 
     | 
    
         
            -
                SPH_MATCH_EXTENDED  = 4
         
     | 
| 
       141 
     | 
    
         
            -
                # match all document IDs w/o fulltext query, apply filters
         
     | 
| 
       142 
     | 
    
         
            -
                SPH_MATCH_FULLSCAN  = 5
         
     | 
| 
       143 
     | 
    
         
            -
                # extended engine V2 (TEMPORARY, WILL BE REMOVED IN 0.9.8-RELEASE)
         
     | 
| 
       144 
     | 
    
         
            -
                SPH_MATCH_EXTENDED2 = 6
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       147 
     | 
    
         
            -
                # Known ranking modes (ext2 only)
         
     | 
| 
       148 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
                # default mode, phrase proximity major factor and BM25 minor one
         
     | 
| 
       151 
     | 
    
         
            -
                SPH_RANK_PROXIMITY_BM25 = 0
         
     | 
| 
       152 
     | 
    
         
            -
                # statistical mode, BM25 ranking only (faster but worse quality)
         
     | 
| 
       153 
     | 
    
         
            -
                SPH_RANK_BM25           = 1
         
     | 
| 
       154 
     | 
    
         
            -
                # no ranking, all matches get a weight of 1
         
     | 
| 
       155 
     | 
    
         
            -
                SPH_RANK_NONE           = 2
         
     | 
| 
       156 
     | 
    
         
            -
                # simple word-count weighting, rank is a weighted sum of per-field keyword occurence counts
         
     | 
| 
       157 
     | 
    
         
            -
                SPH_RANK_WORDCOUNT      = 3
         
     | 
| 
       158 
     | 
    
         
            -
                # phrase proximity
         
     | 
| 
       159 
     | 
    
         
            -
                SPH_RANK_PROXIMITY      = 4
         
     | 
| 
       160 
     | 
    
         
            -
                # emulate old match-any weighting
         
     | 
| 
       161 
     | 
    
         
            -
                SPH_RANK_MATCHANY       = 5
         
     | 
| 
       162 
     | 
    
         
            -
                # sets bits where there were matches
         
     | 
| 
       163 
     | 
    
         
            -
                SPH_RANK_FIELDMASK      = 6
         
     | 
| 
       164 
     | 
    
         
            -
                # codename SPH04, phrase proximity + bm25 + head/exact boost
         
     | 
| 
       165 
     | 
    
         
            -
                SPH_RANK_SPH04          = 7
         
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       168 
     | 
    
         
            -
                # Known sort modes
         
     | 
| 
       169 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
                # sort by document relevance desc, then by date
         
     | 
| 
       172 
     | 
    
         
            -
                SPH_SORT_RELEVANCE     = 0
         
     | 
| 
       173 
     | 
    
         
            -
                # sort by document date desc, then by relevance desc
         
     | 
| 
       174 
     | 
    
         
            -
                SPH_SORT_ATTR_DESC     = 1
         
     | 
| 
       175 
     | 
    
         
            -
                # sort by document date asc, then by relevance desc
         
     | 
| 
       176 
     | 
    
         
            -
                SPH_SORT_ATTR_ASC      = 2
         
     | 
| 
       177 
     | 
    
         
            -
                # sort by time segments (hour/day/week/etc) desc, then by relevance desc
         
     | 
| 
       178 
     | 
    
         
            -
                SPH_SORT_TIME_SEGMENTS = 3
         
     | 
| 
       179 
     | 
    
         
            -
                # sort by SQL-like expression (eg. "@relevance DESC, price ASC, @id DESC")
         
     | 
| 
       180 
     | 
    
         
            -
                SPH_SORT_EXTENDED      = 4
         
     | 
| 
       181 
     | 
    
         
            -
                # sort by arithmetic expression in descending order (eg. "@id + max(@weight,1000)*boost + log(price)")
         
     | 
| 
       182 
     | 
    
         
            -
                SPH_SORT_EXPR          = 5
         
     | 
| 
       183 
     | 
    
         
            -
             
     | 
| 
       184 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       185 
     | 
    
         
            -
                # Known filter types
         
     | 
| 
       186 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
                # filter by integer values set
         
     | 
| 
       189 
     | 
    
         
            -
                SPH_FILTER_VALUES      = 0
         
     | 
| 
       190 
     | 
    
         
            -
                # filter by integer range
         
     | 
| 
       191 
     | 
    
         
            -
                SPH_FILTER_RANGE       = 1
         
     | 
| 
       192 
     | 
    
         
            -
                # filter by float range
         
     | 
| 
       193 
     | 
    
         
            -
                SPH_FILTER_FLOATRANGE  = 2
         
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       196 
     | 
    
         
            -
                # Known attribute types
         
     | 
| 
       197 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       198 
     | 
    
         
            -
             
     | 
| 
       199 
     | 
    
         
            -
                # this attr is just an integer
         
     | 
| 
       200 
     | 
    
         
            -
                SPH_ATTR_INTEGER   = 1
         
     | 
| 
       201 
     | 
    
         
            -
                # this attr is a timestamp
         
     | 
| 
       202 
     | 
    
         
            -
                SPH_ATTR_TIMESTAMP = 2
         
     | 
| 
       203 
     | 
    
         
            -
                # this attr is an ordinal string number (integer at search time,
         
     | 
| 
       204 
     | 
    
         
            -
                # specially handled at indexing time)
         
     | 
| 
       205 
     | 
    
         
            -
                SPH_ATTR_ORDINAL   = 3
         
     | 
| 
       206 
     | 
    
         
            -
                # this attr is a boolean bit field
         
     | 
| 
       207 
     | 
    
         
            -
                SPH_ATTR_BOOL      = 4
         
     | 
| 
       208 
     | 
    
         
            -
                # this attr is a float
         
     | 
| 
       209 
     | 
    
         
            -
                SPH_ATTR_FLOAT     = 5
         
     | 
| 
       210 
     | 
    
         
            -
                # signed 64-bit integer
         
     | 
| 
       211 
     | 
    
         
            -
                SPH_ATTR_BIGINT    = 6
         
     | 
| 
       212 
     | 
    
         
            -
                # string (binary; in-memory)
         
     | 
| 
       213 
     | 
    
         
            -
                SPH_ATTR_STRING    = 7
         
     | 
| 
       214 
     | 
    
         
            -
                # this attr has multiple values (0 or more)
         
     | 
| 
       215 
     | 
    
         
            -
                SPH_ATTR_MULTI     = 0x40000000
         
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       218 
     | 
    
         
            -
                # Known grouping functions
         
     | 
| 
       219 
     | 
    
         
            -
                #=================================================================
         
     | 
| 
       220 
     | 
    
         
            -
             
     | 
| 
       221 
     | 
    
         
            -
                # group by day
         
     | 
| 
       222 
     | 
    
         
            -
                SPH_GROUPBY_DAY      = 0
         
     | 
| 
       223 
     | 
    
         
            -
                # group by week
         
     | 
| 
       224 
     | 
    
         
            -
                SPH_GROUPBY_WEEK     = 1
         
     | 
| 
       225 
     | 
    
         
            -
                # group by month
         
     | 
| 
       226 
     | 
    
         
            -
                SPH_GROUPBY_MONTH    = 2
         
     | 
| 
       227 
     | 
    
         
            -
                # group by year
         
     | 
| 
       228 
     | 
    
         
            -
                SPH_GROUPBY_YEAR     = 3
         
     | 
| 
       229 
     | 
    
         
            -
                # group by attribute value
         
     | 
| 
       230 
     | 
    
         
            -
                SPH_GROUPBY_ATTR     = 4
         
     | 
| 
       231 
     | 
    
         
            -
                # group by sequential attrs pair
         
     | 
| 
       232 
     | 
    
         
            -
                SPH_GROUPBY_ATTRPAIR = 5
         
     | 
| 
       233 
     | 
    
         
            -
             
     | 
| 
       234 
     | 
    
         
            -
                # Constructs the <tt>Sphinx::Client</tt> object and sets options to their default values.
         
     | 
| 
      
 41 
     | 
    
         
            +
                # Constructs the <tt>Sphinx::Client</tt> object and sets options
         
     | 
| 
      
 42 
     | 
    
         
            +
                # to their default values.
         
     | 
| 
      
 43 
     | 
    
         
            +
                #
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @param [Logger] logger a logger object to put logs to. No logging
         
     | 
| 
      
 45 
     | 
    
         
            +
                #   will be performed when not set.
         
     | 
| 
      
 46 
     | 
    
         
            +
                #
         
     | 
| 
       235 
47 
     | 
    
         
             
                def initialize(logger = nil)
         
     | 
| 
       236 
48 
     | 
    
         
             
                  # per-query settings
         
     | 
| 
       237 
49 
     | 
    
         
             
                  @offset        = 0                       # how many records to seek from result-set start (default is 0)
         
     | 
| 
         @@ -458,8 +270,10 @@ module Sphinx 
     | 
|
| 
       458 
270 
     | 
    
         
             
                  @servers = servers.map do |server|
         
     | 
| 
       459 
271 
     | 
    
         
             
                    raise ArgumentError, '"servers" argument must be Array of Hashes' unless server.kind_of?(Hash)
         
     | 
| 
       460 
272 
     | 
    
         | 
| 
       461 
     | 
    
         
            -
                     
     | 
| 
       462 
     | 
    
         
            -
             
     | 
| 
      
 273 
     | 
    
         
            +
                    server = server.with_indifferent_access
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
                    host = server[:path] || server[:host]
         
     | 
| 
      
 276 
     | 
    
         
            +
                    port = server[:port] || 9312
         
     | 
| 
       463 
277 
     | 
    
         
             
                    path = nil
         
     | 
| 
       464 
278 
     | 
    
         
             
                    raise ArgumentError, '"host" argument must be String' unless host.kind_of?(String)
         
     | 
| 
       465 
279 
     | 
    
         | 
| 
         @@ -809,7 +623,7 @@ module Sphinx 
     | 
|
| 
       809 
623 
     | 
    
         
             
                # @return [Sphinx::Client] self.
         
     | 
| 
       810 
624 
     | 
    
         
             
                #
         
     | 
| 
       811 
625 
     | 
    
         
             
                # @example
         
     | 
| 
       812 
     | 
    
         
            -
                #   sphinx.set_match_mode(Sphinx:: 
     | 
| 
      
 626 
     | 
    
         
            +
                #   sphinx.set_match_mode(Sphinx::SPH_MATCH_ALL)
         
     | 
| 
       813 
627 
     | 
    
         
             
                #   sphinx.set_match_mode(:all)
         
     | 
| 
       814 
628 
     | 
    
         
             
                #   sphinx.set_match_mode('all')
         
     | 
| 
       815 
629 
     | 
    
         
             
                #
         
     | 
| 
         @@ -849,7 +663,7 @@ module Sphinx 
     | 
|
| 
       849 
663 
     | 
    
         
             
                # @return [Sphinx::Client] self.
         
     | 
| 
       850 
664 
     | 
    
         
             
                #
         
     | 
| 
       851 
665 
     | 
    
         
             
                # @example
         
     | 
| 
       852 
     | 
    
         
            -
                #   sphinx.set_ranking_mode(Sphinx:: 
     | 
| 
      
 666 
     | 
    
         
            +
                #   sphinx.set_ranking_mode(Sphinx::SPH_RANK_BM25)
         
     | 
| 
       853 
667 
     | 
    
         
             
                #   sphinx.set_ranking_mode(:bm25)
         
     | 
| 
       854 
668 
     | 
    
         
             
                #   sphinx.set_ranking_mode('bm25')
         
     | 
| 
       855 
669 
     | 
    
         
             
                #
         
     | 
| 
         @@ -891,7 +705,7 @@ module Sphinx 
     | 
|
| 
       891 
705 
     | 
    
         
             
                # @return [Sphinx::Client] self.
         
     | 
| 
       892 
706 
     | 
    
         
             
                #
         
     | 
| 
       893 
707 
     | 
    
         
             
                # @example
         
     | 
| 
       894 
     | 
    
         
            -
                #   sphinx.set_sort_mode(Sphinx:: 
     | 
| 
      
 708 
     | 
    
         
            +
                #   sphinx.set_sort_mode(Sphinx::SPH_SORT_ATTR_ASC, 'attr')
         
     | 
| 
       895 
709 
     | 
    
         
             
                #   sphinx.set_sort_mode(:attr_asc, 'attr')
         
     | 
| 
       896 
710 
     | 
    
         
             
                #   sphinx.set_sort_mode('attr_asc', 'attr')
         
     | 
| 
       897 
711 
     | 
    
         
             
                #
         
     | 
| 
         @@ -1087,7 +901,8 @@ module Sphinx 
     | 
|
| 
       1087 
901 
     | 
    
         
             
                # be matched (or rejected, if +exclude+ is +true+).
         
     | 
| 
       1088 
902 
     | 
    
         
             
                #
         
     | 
| 
       1089 
903 
     | 
    
         
             
                # @param [String, Symbol] attribute an attribute name to filter by.
         
     | 
| 
       1090 
     | 
    
         
            -
                # @param [Array<Integer 
     | 
| 
      
 904 
     | 
    
         
            +
                # @param [Array<Integer>, Integer] values an +Array+ of integers or
         
     | 
| 
      
 905 
     | 
    
         
            +
                #   single Integer with given attribute values.
         
     | 
| 
       1091 
906 
     | 
    
         
             
                # @param [Boolean] exclude indicating whether documents with given attribute
         
     | 
| 
       1092 
907 
     | 
    
         
             
                #   matching specified values should be excluded from search results.
         
     | 
| 
       1093 
908 
     | 
    
         
             
                # @return [Sphinx::Client] self.
         
     | 
| 
         @@ -1104,15 +919,14 @@ module Sphinx 
     | 
|
| 
       1104 
919 
     | 
    
         
             
                #
         
     | 
| 
       1105 
920 
     | 
    
         
             
                def set_filter(attribute, values, exclude = false)
         
     | 
| 
       1106 
921 
     | 
    
         
             
                  raise ArgumentError, '"attribute" argument must be String or Symbol' unless attribute.kind_of?(String) or attribute.kind_of?(Symbol)
         
     | 
| 
      
 922 
     | 
    
         
            +
                  values = [values] if values.kind_of?(Integer)
         
     | 
| 
       1107 
923 
     | 
    
         
             
                  raise ArgumentError, '"values" argument must be Array'               unless values.kind_of?(Array)
         
     | 
| 
       1108 
     | 
    
         
            -
                  raise ArgumentError, '"values" argument must  
     | 
| 
       1109 
     | 
    
         
            -
                  raise ArgumentError, '"exclude" argument must be Boolean'            unless  
     | 
| 
      
 924 
     | 
    
         
            +
                  raise ArgumentError, '"values" argument must be Array of Integers'   unless values.all? { |v| v.kind_of?(Integer) }
         
     | 
| 
      
 925 
     | 
    
         
            +
                  raise ArgumentError, '"exclude" argument must be Boolean'            unless [TrueClass, FalseClass].include?(exclude.class)
         
     | 
| 
       1110 
926 
     | 
    
         | 
| 
       1111 
     | 
    
         
            -
                  values. 
     | 
| 
       1112 
     | 
    
         
            -
                     
     | 
| 
      
 927 
     | 
    
         
            +
                  if values.any?
         
     | 
| 
      
 928 
     | 
    
         
            +
                    @filters << { 'type' => SPH_FILTER_VALUES, 'attr' => attribute.to_s, 'exclude' => exclude, 'values' => values }
         
     | 
| 
       1113 
929 
     | 
    
         
             
                  end
         
     | 
| 
       1114 
     | 
    
         
            -
             
     | 
| 
       1115 
     | 
    
         
            -
                  @filters << { 'type' => SPH_FILTER_VALUES, 'attr' => attribute.to_s, 'exclude' => exclude, 'values' => values }
         
     | 
| 
       1116 
930 
     | 
    
         
             
                  self
         
     | 
| 
       1117 
931 
     | 
    
         
             
                end
         
     | 
| 
       1118 
932 
     | 
    
         
             
                alias :SetFilter :set_filter
         
     | 
| 
         @@ -1502,6 +1316,8 @@ module Sphinx 
     | 
|
| 
       1502 
1316 
     | 
    
         
             
                #   Query warning message reported by searchd (string, human readable).
         
     | 
| 
       1503 
1317 
     | 
    
         
             
                #   Empty if there were no warnings.
         
     | 
| 
       1504 
1318 
     | 
    
         
             
                #
         
     | 
| 
      
 1319 
     | 
    
         
            +
                # Please note: you can use both strings and symbols as <tt>Hash</tt> keys.
         
     | 
| 
      
 1320 
     | 
    
         
            +
                #
         
     | 
| 
       1505 
1321 
     | 
    
         
             
                # It should be noted that {#query} carries out the same actions as
         
     | 
| 
       1506 
1322 
     | 
    
         
             
                # {#add_query} and {#run_queries} without the intermediate steps; it
         
     | 
| 
       1507 
1323 
     | 
    
         
             
                # is analoguous to a single {#add_query} call, followed by a
         
     | 
| 
         @@ -1799,7 +1615,7 @@ module Sphinx 
     | 
|
| 
       1799 
1615 
     | 
    
         | 
| 
       1800 
1616 
     | 
    
         
             
                  # parse response
         
     | 
| 
       1801 
1617 
     | 
    
         
             
                  (1..nreqs).map do
         
     | 
| 
       1802 
     | 
    
         
            -
                    result =  
     | 
| 
      
 1618 
     | 
    
         
            +
                    result = HashWithIndifferentAccess.new('error' => '', 'warning' => '')
         
     | 
| 
       1803 
1619 
     | 
    
         | 
| 
       1804 
1620 
     | 
    
         
             
                    # extract status
         
     | 
| 
       1805 
1621 
     | 
    
         
             
                    status = result['status'] = response.get_int
         
     | 
| 
         @@ -1944,16 +1760,18 @@ module Sphinx 
     | 
|
| 
       1944 
1760 
     | 
    
         
             
                  end
         
     | 
| 
       1945 
1761 
     | 
    
         | 
| 
       1946 
1762 
     | 
    
         
             
                  # fixup options
         
     | 
| 
       1947 
     | 
    
         
            -
                  opts 
     | 
| 
       1948 
     | 
    
         
            -
             
     | 
| 
       1949 
     | 
    
         
            -
             
     | 
| 
       1950 
     | 
    
         
            -
             
     | 
| 
       1951 
     | 
    
         
            -
             
     | 
| 
       1952 
     | 
    
         
            -
             
     | 
| 
       1953 
     | 
    
         
            -
             
     | 
| 
       1954 
     | 
    
         
            -
             
     | 
| 
       1955 
     | 
    
         
            -
             
     | 
| 
       1956 
     | 
    
         
            -
             
     | 
| 
      
 1763 
     | 
    
         
            +
                  opts = HashWithIndifferentAccess.new(
         
     | 
| 
      
 1764 
     | 
    
         
            +
                    'before_match'    => '<b>',
         
     | 
| 
      
 1765 
     | 
    
         
            +
                    'after_match'     => '</b>',
         
     | 
| 
      
 1766 
     | 
    
         
            +
                    'chunk_separator' => ' ... ',
         
     | 
| 
      
 1767 
     | 
    
         
            +
                    'limit'           => 256,
         
     | 
| 
      
 1768 
     | 
    
         
            +
                    'around'          => 5,
         
     | 
| 
      
 1769 
     | 
    
         
            +
                    'exact_phrase'    => false,
         
     | 
| 
      
 1770 
     | 
    
         
            +
                    'single_passage'  => false,
         
     | 
| 
      
 1771 
     | 
    
         
            +
                    'use_boundaries'  => false,
         
     | 
| 
      
 1772 
     | 
    
         
            +
                    'weight_order'    => false,
         
     | 
| 
      
 1773 
     | 
    
         
            +
                    'query_mode'      => false
         
     | 
| 
      
 1774 
     | 
    
         
            +
                  ).update(opts)
         
     | 
| 
       1957 
1775 
     | 
    
         | 
| 
       1958 
1776 
     | 
    
         
             
                  # build request
         
     | 
| 
       1959 
1777 
     | 
    
         | 
| 
         @@ -2044,7 +1862,7 @@ module Sphinx 
     | 
|
| 
       2044 
1862 
     | 
    
         
             
                    tokenized = response.get_string
         
     | 
| 
       2045 
1863 
     | 
    
         
             
                    normalized = response.get_string
         
     | 
| 
       2046 
1864 
     | 
    
         | 
| 
       2047 
     | 
    
         
            -
                    entry =  
     | 
| 
      
 1865 
     | 
    
         
            +
                    entry = HashWithIndifferentAccess.new('tokenized' => tokenized, 'normalized' => normalized)
         
     | 
| 
       2048 
1866 
     | 
    
         
             
                    entry['docs'], entry['hits'] = response.get_ints(2) if hits
         
     | 
| 
       2049 
1867 
     | 
    
         | 
| 
       2050 
1868 
     | 
    
         
             
                    entry
         
     | 
| 
         @@ -2154,6 +1972,26 @@ module Sphinx 
     | 
|
| 
       2154 
1972 
     | 
    
         
             
                end
         
     | 
| 
       2155 
1973 
     | 
    
         
             
                alias :UpdateAttributes :update_attributes
         
     | 
| 
       2156 
1974 
     | 
    
         | 
| 
      
 1975 
     | 
    
         
            +
                # Escapes characters that are treated as special operators by the
         
     | 
| 
      
 1976 
     | 
    
         
            +
                # query language parser.
         
     | 
| 
      
 1977 
     | 
    
         
            +
                #
         
     | 
| 
      
 1978 
     | 
    
         
            +
                # This function might seem redundant because it's trivial to
         
     | 
| 
      
 1979 
     | 
    
         
            +
                # implement in any calling application. However, as the set of
         
     | 
| 
      
 1980 
     | 
    
         
            +
                # special characters might change over time, it makes sense to
         
     | 
| 
      
 1981 
     | 
    
         
            +
                # have an API call that is guaranteed to escape all such
         
     | 
| 
      
 1982 
     | 
    
         
            +
                # characters at all times.
         
     | 
| 
      
 1983 
     | 
    
         
            +
                #
         
     | 
| 
      
 1984 
     | 
    
         
            +
                # @param [String] string is a string to escape.
         
     | 
| 
      
 1985 
     | 
    
         
            +
                # @return [String] an escaped string.
         
     | 
| 
      
 1986 
     | 
    
         
            +
                #
         
     | 
| 
      
 1987 
     | 
    
         
            +
                # @example:
         
     | 
| 
      
 1988 
     | 
    
         
            +
                #   escaped = sphinx.escape_string "escaping-sample@query/string"
         
     | 
| 
      
 1989 
     | 
    
         
            +
                #
         
     | 
| 
      
 1990 
     | 
    
         
            +
                def escape_string(string)
         
     | 
| 
      
 1991 
     | 
    
         
            +
                  string.to_s.gsub(/([\\()|\-!@~"&\/\^\$=])/, '\\\\\\1')
         
     | 
| 
      
 1992 
     | 
    
         
            +
                end
         
     | 
| 
      
 1993 
     | 
    
         
            +
                alias :EscapeString :escape_string
         
     | 
| 
      
 1994 
     | 
    
         
            +
             
     | 
| 
       2157 
1995 
     | 
    
         
             
                # Queries searchd status, and returns an array of status variable name
         
     | 
| 
       2158 
1996 
     | 
    
         
             
                # and value pairs.
         
     | 
| 
       2159 
1997 
     | 
    
         
             
                #
         
     | 
| 
         @@ -2194,11 +2032,11 @@ module Sphinx 
     | 
|
| 
       2194 
2032 
     | 
    
         
             
                      status = (0...rows).map do
         
     | 
| 
       2195 
2033 
     | 
    
         
             
                        (0...cols).map { response.get_string }
         
     | 
| 
       2196 
2034 
     | 
    
         
             
                      end
         
     | 
| 
       2197 
     | 
    
         
            -
                       
     | 
| 
      
 2035 
     | 
    
         
            +
                      HashWithIndifferentAccess.new(:server => server.to_s, :status => status)
         
     | 
| 
       2198 
2036 
     | 
    
         
             
                    rescue SphinxError
         
     | 
| 
       2199 
2037 
     | 
    
         
             
                      # Re-raise error when a single server configured
         
     | 
| 
       2200 
2038 
     | 
    
         
             
                      raise if @servers.size == 1
         
     | 
| 
       2201 
     | 
    
         
            -
                       
     | 
| 
      
 2039 
     | 
    
         
            +
                      HashWithIndifferentAccess.new(:server => server.to_s, :error => self.last_error)
         
     | 
| 
       2202 
2040 
     | 
    
         
             
                    end
         
     | 
| 
       2203 
2041 
     | 
    
         
             
                  end
         
     | 
| 
       2204 
2042 
     | 
    
         | 
| 
         @@ -0,0 +1,189 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Sphinx
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Contains all constants need by Sphinx API.
         
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Constants
         
     | 
| 
      
 5 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 6 
     | 
    
         
            +
                # Known searchd commands
         
     | 
| 
      
 7 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # search command
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 11 
     | 
    
         
            +
                SEARCHD_COMMAND_SEARCH     = 0
         
     | 
| 
      
 12 
     | 
    
         
            +
                # excerpt command
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 14 
     | 
    
         
            +
                SEARCHD_COMMAND_EXCERPT    = 1
         
     | 
| 
      
 15 
     | 
    
         
            +
                # update command
         
     | 
| 
      
 16 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 17 
     | 
    
         
            +
                SEARCHD_COMMAND_UPDATE     = 2
         
     | 
| 
      
 18 
     | 
    
         
            +
                # keywords command
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 20 
     | 
    
         
            +
                SEARCHD_COMMAND_KEYWORDS   = 3
         
     | 
| 
      
 21 
     | 
    
         
            +
                # persist command
         
     | 
| 
      
 22 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 23 
     | 
    
         
            +
                SEARCHD_COMMAND_PERSIST    = 4
         
     | 
| 
      
 24 
     | 
    
         
            +
                # status command
         
     | 
| 
      
 25 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 26 
     | 
    
         
            +
                SEARCHD_COMMAND_STATUS     = 5
         
     | 
| 
      
 27 
     | 
    
         
            +
                # query command
         
     | 
| 
      
 28 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 29 
     | 
    
         
            +
                SEARCHD_COMMAND_QUERY      = 6
         
     | 
| 
      
 30 
     | 
    
         
            +
                # flushattrs command
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 32 
     | 
    
         
            +
                SEARCHD_COMMAND_FLUSHATTRS = 7
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 35 
     | 
    
         
            +
                # Current client-side command implementation versions
         
     | 
| 
      
 36 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                # search command version
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 40 
     | 
    
         
            +
                VER_COMMAND_SEARCH     = 0x117
         
     | 
| 
      
 41 
     | 
    
         
            +
                # excerpt command version
         
     | 
| 
      
 42 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 43 
     | 
    
         
            +
                VER_COMMAND_EXCERPT    = 0x100
         
     | 
| 
      
 44 
     | 
    
         
            +
                # update command version
         
     | 
| 
      
 45 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 46 
     | 
    
         
            +
                VER_COMMAND_UPDATE     = 0x102
         
     | 
| 
      
 47 
     | 
    
         
            +
                # keywords command version
         
     | 
| 
      
 48 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 49 
     | 
    
         
            +
                VER_COMMAND_KEYWORDS   = 0x100
         
     | 
| 
      
 50 
     | 
    
         
            +
                # persist command version
         
     | 
| 
      
 51 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 52 
     | 
    
         
            +
                VER_COMMAND_PERSIST    = 0x000
         
     | 
| 
      
 53 
     | 
    
         
            +
                # status command version
         
     | 
| 
      
 54 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 55 
     | 
    
         
            +
                VER_COMMAND_STATUS     = 0x100
         
     | 
| 
      
 56 
     | 
    
         
            +
                # query command version
         
     | 
| 
      
 57 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 58 
     | 
    
         
            +
                VER_COMMAND_QUERY      = 0x100
         
     | 
| 
      
 59 
     | 
    
         
            +
                # flushattrs command version
         
     | 
| 
      
 60 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 61 
     | 
    
         
            +
                VER_COMMAND_FLUSHATTRS = 0x100
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 64 
     | 
    
         
            +
                # Known searchd status codes
         
     | 
| 
      
 65 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                # general success, command-specific reply follows
         
     | 
| 
      
 68 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 69 
     | 
    
         
            +
                SEARCHD_OK      = 0
         
     | 
| 
      
 70 
     | 
    
         
            +
                # general failure, command-specific reply may follow
         
     | 
| 
      
 71 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 72 
     | 
    
         
            +
                SEARCHD_ERROR   = 1
         
     | 
| 
      
 73 
     | 
    
         
            +
                # temporaty failure, client should retry later
         
     | 
| 
      
 74 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 75 
     | 
    
         
            +
                SEARCHD_RETRY   = 2
         
     | 
| 
      
 76 
     | 
    
         
            +
                # general success, warning message and command-specific reply follow
         
     | 
| 
      
 77 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 78 
     | 
    
         
            +
                SEARCHD_WARNING = 3
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 81 
     | 
    
         
            +
                # Known match modes
         
     | 
| 
      
 82 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                # match all query words
         
     | 
| 
      
 85 
     | 
    
         
            +
                SPH_MATCH_ALL       = 0
         
     | 
| 
      
 86 
     | 
    
         
            +
                # match any query word
         
     | 
| 
      
 87 
     | 
    
         
            +
                SPH_MATCH_ANY       = 1
         
     | 
| 
      
 88 
     | 
    
         
            +
                # match this exact phrase
         
     | 
| 
      
 89 
     | 
    
         
            +
                SPH_MATCH_PHRASE    = 2
         
     | 
| 
      
 90 
     | 
    
         
            +
                # match this boolean query
         
     | 
| 
      
 91 
     | 
    
         
            +
                SPH_MATCH_BOOLEAN   = 3
         
     | 
| 
      
 92 
     | 
    
         
            +
                # match this extended query
         
     | 
| 
      
 93 
     | 
    
         
            +
                SPH_MATCH_EXTENDED  = 4
         
     | 
| 
      
 94 
     | 
    
         
            +
                # match all document IDs w/o fulltext query, apply filters
         
     | 
| 
      
 95 
     | 
    
         
            +
                SPH_MATCH_FULLSCAN  = 5
         
     | 
| 
      
 96 
     | 
    
         
            +
                # extended engine V2 (TEMPORARY, WILL BE REMOVED IN 0.9.8-RELEASE)
         
     | 
| 
      
 97 
     | 
    
         
            +
                SPH_MATCH_EXTENDED2 = 6
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 100 
     | 
    
         
            +
                # Known ranking modes (ext2 only)
         
     | 
| 
      
 101 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                # default mode, phrase proximity major factor and BM25 minor one
         
     | 
| 
      
 104 
     | 
    
         
            +
                SPH_RANK_PROXIMITY_BM25 = 0
         
     | 
| 
      
 105 
     | 
    
         
            +
                # statistical mode, BM25 ranking only (faster but worse quality)
         
     | 
| 
      
 106 
     | 
    
         
            +
                SPH_RANK_BM25           = 1
         
     | 
| 
      
 107 
     | 
    
         
            +
                # no ranking, all matches get a weight of 1
         
     | 
| 
      
 108 
     | 
    
         
            +
                SPH_RANK_NONE           = 2
         
     | 
| 
      
 109 
     | 
    
         
            +
                # simple word-count weighting, rank is a weighted sum of per-field keyword occurence counts
         
     | 
| 
      
 110 
     | 
    
         
            +
                SPH_RANK_WORDCOUNT      = 3
         
     | 
| 
      
 111 
     | 
    
         
            +
                # phrase proximity
         
     | 
| 
      
 112 
     | 
    
         
            +
                SPH_RANK_PROXIMITY      = 4
         
     | 
| 
      
 113 
     | 
    
         
            +
                # emulate old match-any weighting
         
     | 
| 
      
 114 
     | 
    
         
            +
                SPH_RANK_MATCHANY       = 5
         
     | 
| 
      
 115 
     | 
    
         
            +
                # sets bits where there were matches
         
     | 
| 
      
 116 
     | 
    
         
            +
                SPH_RANK_FIELDMASK      = 6
         
     | 
| 
      
 117 
     | 
    
         
            +
                # codename SPH04, phrase proximity + bm25 + head/exact boost
         
     | 
| 
      
 118 
     | 
    
         
            +
                SPH_RANK_SPH04          = 7
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 121 
     | 
    
         
            +
                # Known sort modes
         
     | 
| 
      
 122 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                # sort by document relevance desc, then by date
         
     | 
| 
      
 125 
     | 
    
         
            +
                SPH_SORT_RELEVANCE     = 0
         
     | 
| 
      
 126 
     | 
    
         
            +
                # sort by document date desc, then by relevance desc
         
     | 
| 
      
 127 
     | 
    
         
            +
                SPH_SORT_ATTR_DESC     = 1
         
     | 
| 
      
 128 
     | 
    
         
            +
                # sort by document date asc, then by relevance desc
         
     | 
| 
      
 129 
     | 
    
         
            +
                SPH_SORT_ATTR_ASC      = 2
         
     | 
| 
      
 130 
     | 
    
         
            +
                # sort by time segments (hour/day/week/etc) desc, then by relevance desc
         
     | 
| 
      
 131 
     | 
    
         
            +
                SPH_SORT_TIME_SEGMENTS = 3
         
     | 
| 
      
 132 
     | 
    
         
            +
                # sort by SQL-like expression (eg. "@relevance DESC, price ASC, @id DESC")
         
     | 
| 
      
 133 
     | 
    
         
            +
                SPH_SORT_EXTENDED      = 4
         
     | 
| 
      
 134 
     | 
    
         
            +
                # sort by arithmetic expression in descending order (eg. "@id + max(@weight,1000)*boost + log(price)")
         
     | 
| 
      
 135 
     | 
    
         
            +
                SPH_SORT_EXPR          = 5
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 138 
     | 
    
         
            +
                # Known filter types
         
     | 
| 
      
 139 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                # filter by integer values set
         
     | 
| 
      
 142 
     | 
    
         
            +
                SPH_FILTER_VALUES      = 0
         
     | 
| 
      
 143 
     | 
    
         
            +
                # filter by integer range
         
     | 
| 
      
 144 
     | 
    
         
            +
                SPH_FILTER_RANGE       = 1
         
     | 
| 
      
 145 
     | 
    
         
            +
                # filter by float range
         
     | 
| 
      
 146 
     | 
    
         
            +
                SPH_FILTER_FLOATRANGE  = 2
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 149 
     | 
    
         
            +
                # Known attribute types
         
     | 
| 
      
 150 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                # this attr is just an integer
         
     | 
| 
      
 153 
     | 
    
         
            +
                SPH_ATTR_INTEGER   = 1
         
     | 
| 
      
 154 
     | 
    
         
            +
                # this attr is a timestamp
         
     | 
| 
      
 155 
     | 
    
         
            +
                SPH_ATTR_TIMESTAMP = 2
         
     | 
| 
      
 156 
     | 
    
         
            +
                # this attr is an ordinal string number (integer at search time,
         
     | 
| 
      
 157 
     | 
    
         
            +
                # specially handled at indexing time)
         
     | 
| 
      
 158 
     | 
    
         
            +
                SPH_ATTR_ORDINAL   = 3
         
     | 
| 
      
 159 
     | 
    
         
            +
                # this attr is a boolean bit field
         
     | 
| 
      
 160 
     | 
    
         
            +
                SPH_ATTR_BOOL      = 4
         
     | 
| 
      
 161 
     | 
    
         
            +
                # this attr is a float
         
     | 
| 
      
 162 
     | 
    
         
            +
                SPH_ATTR_FLOAT     = 5
         
     | 
| 
      
 163 
     | 
    
         
            +
                # signed 64-bit integer
         
     | 
| 
      
 164 
     | 
    
         
            +
                SPH_ATTR_BIGINT    = 6
         
     | 
| 
      
 165 
     | 
    
         
            +
                # string (binary; in-memory)
         
     | 
| 
      
 166 
     | 
    
         
            +
                SPH_ATTR_STRING    = 7
         
     | 
| 
      
 167 
     | 
    
         
            +
                # this attr has multiple values (0 or more)
         
     | 
| 
      
 168 
     | 
    
         
            +
                SPH_ATTR_MULTI     = 0x40000000
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 171 
     | 
    
         
            +
                # Known grouping functions
         
     | 
| 
      
 172 
     | 
    
         
            +
                #=================================================================
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                # group by day
         
     | 
| 
      
 175 
     | 
    
         
            +
                SPH_GROUPBY_DAY      = 0
         
     | 
| 
      
 176 
     | 
    
         
            +
                # group by week
         
     | 
| 
      
 177 
     | 
    
         
            +
                SPH_GROUPBY_WEEK     = 1
         
     | 
| 
      
 178 
     | 
    
         
            +
                # group by month
         
     | 
| 
      
 179 
     | 
    
         
            +
                SPH_GROUPBY_MONTH    = 2
         
     | 
| 
      
 180 
     | 
    
         
            +
                # group by year
         
     | 
| 
      
 181 
     | 
    
         
            +
                SPH_GROUPBY_YEAR     = 3
         
     | 
| 
      
 182 
     | 
    
         
            +
                # group by attribute value
         
     | 
| 
      
 183 
     | 
    
         
            +
                SPH_GROUPBY_ATTR     = 4
         
     | 
| 
      
 184 
     | 
    
         
            +
                # group by sequential attrs pair
         
     | 
| 
      
 185 
     | 
    
         
            +
                SPH_GROUPBY_ATTRPAIR = 5
         
     | 
| 
      
 186 
     | 
    
         
            +
              end
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
      
 188 
     | 
    
         
            +
              include Constants
         
     | 
| 
      
 189 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,152 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Sphinx
         
     | 
| 
      
 2 
     | 
    
         
            +
              begin
         
     | 
| 
      
 3 
     | 
    
         
            +
                HashWithIndifferentAccess = ::HashWithIndifferentAccess
         
     | 
| 
      
 4 
     | 
    
         
            +
              rescue NameError
         
     | 
| 
      
 5 
     | 
    
         
            +
                # This class has dubious semantics and we only have it so that
         
     | 
| 
      
 6 
     | 
    
         
            +
                # people can write params[:key] instead of params['key']
         
     | 
| 
      
 7 
     | 
    
         
            +
                # and they get the same value for both keys.
         
     | 
| 
      
 8 
     | 
    
         
            +
                #
         
     | 
| 
      
 9 
     | 
    
         
            +
                # This is part of Rails' ActiveSupport project. If you are
         
     | 
| 
      
 10 
     | 
    
         
            +
                # using Rails, this class will not be used.
         
     | 
| 
      
 11 
     | 
    
         
            +
                #
         
     | 
| 
      
 12 
     | 
    
         
            +
                class HashWithIndifferentAccess < Hash
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(constructor = {})
         
     | 
| 
      
 14 
     | 
    
         
            +
                    if constructor.is_a?(Hash)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      super()
         
     | 
| 
      
 16 
     | 
    
         
            +
                      update(constructor)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    else
         
     | 
| 
      
 18 
     | 
    
         
            +
                      super(constructor)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def default(key = nil)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    if key.is_a?(Symbol) && include?(key = key.to_s)
         
     | 
| 
      
 24 
     | 
    
         
            +
                      self[key]
         
     | 
| 
      
 25 
     | 
    
         
            +
                    else
         
     | 
| 
      
 26 
     | 
    
         
            +
                      super
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  alias_method :regular_update, :update unless method_defined?(:regular_update)
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  # Assigns a new value to the hash:
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #   hash = HashWithIndifferentAccess.new
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #   hash[:key] = "value"
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def []=(key, value)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    regular_writer(convert_key(key), convert_value(value))
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  # Updates the instantized hash with values from the second:
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # 
         
     | 
| 
      
 44 
     | 
    
         
            +
                  #   hash_1 = HashWithIndifferentAccess.new
         
     | 
| 
      
 45 
     | 
    
         
            +
                  #   hash_1[:key] = "value"
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # 
         
     | 
| 
      
 47 
     | 
    
         
            +
                  #   hash_2 = HashWithIndifferentAccess.new
         
     | 
| 
      
 48 
     | 
    
         
            +
                  #   hash_2[:key] = "New Value!"
         
     | 
| 
      
 49 
     | 
    
         
            +
                  # 
         
     | 
| 
      
 50 
     | 
    
         
            +
                  #   hash_1.update(hash_2) # => {"key"=>"New Value!"}
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # 
         
     | 
| 
      
 52 
     | 
    
         
            +
                  def update(other_hash)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
         
     | 
| 
      
 54 
     | 
    
         
            +
                    self
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  alias_method :merge!, :update
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  # Checks the hash for a key matching the argument passed in:
         
     | 
| 
      
 60 
     | 
    
         
            +
                  #
         
     | 
| 
      
 61 
     | 
    
         
            +
                  #   hash = HashWithIndifferentAccess.new
         
     | 
| 
      
 62 
     | 
    
         
            +
                  #   hash["key"] = "value"
         
     | 
| 
      
 63 
     | 
    
         
            +
                  #   hash.key? :key  # => true
         
     | 
| 
      
 64 
     | 
    
         
            +
                  #   hash.key? "key" # => true
         
     | 
| 
      
 65 
     | 
    
         
            +
                  #
         
     | 
| 
      
 66 
     | 
    
         
            +
                  def key?(key)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    super(convert_key(key))
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  alias_method :include?, :key?
         
     | 
| 
      
 71 
     | 
    
         
            +
                  alias_method :has_key?, :key?
         
     | 
| 
      
 72 
     | 
    
         
            +
                  alias_method :member?, :key?
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  # Fetches the value for the specified key, same as doing hash[key]
         
     | 
| 
      
 75 
     | 
    
         
            +
                  def fetch(key, *extras)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    super(convert_key(key), *extras)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  # Returns an array of the values at the specified indices:
         
     | 
| 
      
 80 
     | 
    
         
            +
                  #
         
     | 
| 
      
 81 
     | 
    
         
            +
                  #   hash = HashWithIndifferentAccess.new
         
     | 
| 
      
 82 
     | 
    
         
            +
                  #   hash[:a] = "x"
         
     | 
| 
      
 83 
     | 
    
         
            +
                  #   hash[:b] = "y"
         
     | 
| 
      
 84 
     | 
    
         
            +
                  #   hash.values_at("a", "b") # => ["x", "y"]
         
     | 
| 
      
 85 
     | 
    
         
            +
                  #
         
     | 
| 
      
 86 
     | 
    
         
            +
                  def values_at(*indices)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    indices.collect {|key| self[convert_key(key)]}
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  # Returns an exact copy of the hash.
         
     | 
| 
      
 91 
     | 
    
         
            +
                  def dup
         
     | 
| 
      
 92 
     | 
    
         
            +
                    HashWithIndifferentAccess.new(self)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
         
     | 
| 
      
 96 
     | 
    
         
            +
                  # Does not overwrite the existing hash.
         
     | 
| 
      
 97 
     | 
    
         
            +
                  def merge(hash)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    self.dup.update(hash)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
         
     | 
| 
      
 102 
     | 
    
         
            +
                  # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
         
     | 
| 
      
 103 
     | 
    
         
            +
                  def reverse_merge(other_hash)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    super other_hash.with_indifferent_access
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                  # Removes a specified key from the hash.
         
     | 
| 
      
 108 
     | 
    
         
            +
                  def delete(key)
         
     | 
| 
      
 109 
     | 
    
         
            +
                    super(convert_key(key))
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  def stringify_keys!; self end
         
     | 
| 
      
 113 
     | 
    
         
            +
                  def symbolize_keys!; self end
         
     | 
| 
      
 114 
     | 
    
         
            +
                  def to_options!; self end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  # Convert to a Hash with String keys.
         
     | 
| 
      
 117 
     | 
    
         
            +
                  def to_hash
         
     | 
| 
      
 118 
     | 
    
         
            +
                    Hash.new(default).merge(self)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 122 
     | 
    
         
            +
                    def convert_key(key)
         
     | 
| 
      
 123 
     | 
    
         
            +
                      key.kind_of?(Symbol) ? key.to_s : key
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                    def convert_value(value)
         
     | 
| 
      
 127 
     | 
    
         
            +
                      case value
         
     | 
| 
      
 128 
     | 
    
         
            +
                      when Hash
         
     | 
| 
      
 129 
     | 
    
         
            +
                        value.with_indifferent_access
         
     | 
| 
      
 130 
     | 
    
         
            +
                      when Array
         
     | 
| 
      
 131 
     | 
    
         
            +
                        value.collect { |e| e.is_a?(Hash) ? e.with_indifferent_access : e }
         
     | 
| 
      
 132 
     | 
    
         
            +
                      else
         
     | 
| 
      
 133 
     | 
    
         
            +
                        value
         
     | 
| 
      
 134 
     | 
    
         
            +
                      end
         
     | 
| 
      
 135 
     | 
    
         
            +
                    end
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                module HashIndifferentAccess #:nodoc:
         
     | 
| 
      
 139 
     | 
    
         
            +
                  def with_indifferent_access
         
     | 
| 
      
 140 
     | 
    
         
            +
                    hash = HashWithIndifferentAccess.new(self)
         
     | 
| 
      
 141 
     | 
    
         
            +
                    hash.default = self.default
         
     | 
| 
      
 142 
     | 
    
         
            +
                    hash
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                class ::Hash #:nodoc:
         
     | 
| 
      
 147 
     | 
    
         
            +
                  unless respond_to?(:with_indifferent_access)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    include Sphinx::HashIndifferentAccess
         
     | 
| 
      
 149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 150 
     | 
    
         
            +
                end
         
     | 
| 
      
 151 
     | 
    
         
            +
              end
         
     | 
| 
      
 152 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -143,10 +143,10 @@ describe Sphinx::Client, 'connected' do 
     | 
|
| 
       143 
143 
     | 
    
         
             
                result['matches'].length.should == 3
         
     | 
| 
       144 
144 
     | 
    
         
             
                result['time'].should_not be_nil
         
     | 
| 
       145 
145 
     | 
    
         
             
                result['attrs'].should == {
         
     | 
| 
       146 
     | 
    
         
            -
                  'group_id' => Sphinx:: 
     | 
| 
       147 
     | 
    
         
            -
                  'created_at' => Sphinx:: 
     | 
| 
       148 
     | 
    
         
            -
                  'rating' => Sphinx:: 
     | 
| 
       149 
     | 
    
         
            -
                  'tags' => Sphinx:: 
     | 
| 
      
 146 
     | 
    
         
            +
                  'group_id' => Sphinx::SPH_ATTR_INTEGER,
         
     | 
| 
      
 147 
     | 
    
         
            +
                  'created_at' => Sphinx::SPH_ATTR_TIMESTAMP,
         
     | 
| 
      
 148 
     | 
    
         
            +
                  'rating' => Sphinx::SPH_ATTR_FLOAT,
         
     | 
| 
      
 149 
     | 
    
         
            +
                  'tags' => Sphinx::SPH_ATTR_MULTI | Sphinx::SPH_ATTR_INTEGER
         
     | 
| 
       150 
150 
     | 
    
         
             
                }
         
     | 
| 
       151 
151 
     | 
    
         
             
                result['fields'].should == [ 'name', 'description' ]
         
     | 
| 
       152 
152 
     | 
    
         
             
                result['total'].should == 3
         
     | 
    
        data/spec/client_spec.rb
    CHANGED
    
    | 
         @@ -15,7 +15,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       15 
15 
     | 
    
         
             
                      cnt.should == 1
         
     | 
| 
       16 
16 
     | 
    
         
             
                    end
         
     | 
| 
       17 
17 
     | 
    
         
             
                  end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       19 
19 
     | 
    
         
             
                  it 'should raise an exception on error' do
         
     | 
| 
       20 
20 
     | 
    
         
             
                    2.times do
         
     | 
| 
       21 
21 
     | 
    
         
             
                      cnt = 0
         
     | 
| 
         @@ -91,20 +91,20 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       91 
91 
     | 
    
         
             
                  end
         
     | 
| 
       92 
92 
     | 
    
         
             
                end
         
     | 
| 
       93 
93 
     | 
    
         
             
              end
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
       95 
95 
     | 
    
         
             
              context 'in with_socket method' do
         
     | 
| 
       96 
96 
     | 
    
         
             
                before :each do
         
     | 
| 
       97 
97 
     | 
    
         
             
                  @sphinx = Sphinx::Client.new
         
     | 
| 
       98 
98 
     | 
    
         
             
                  @socket = mock('TCPSocket')
         
     | 
| 
       99 
99 
     | 
    
         
             
                end
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
       101 
101 
     | 
    
         
             
                context 'without retries' do
         
     | 
| 
       102 
102 
     | 
    
         
             
                  before :each do
         
     | 
| 
       103 
103 
     | 
    
         
             
                    @server = mock('Server')
         
     | 
| 
       104 
104 
     | 
    
         
             
                    @server.should_receive(:get_socket).and_yield(@socket).and_return(@socket)
         
     | 
| 
       105 
105 
     | 
    
         
             
                    @server.should_receive(:free_socket).with(@socket).at_least(1)
         
     | 
| 
       106 
106 
     | 
    
         
             
                  end
         
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
       108 
108 
     | 
    
         
             
                  it 'should initialize session' do
         
     | 
| 
       109 
109 
     | 
    
         
             
                    @socket.should_receive(:write).with([1].pack('N'))
         
     | 
| 
       110 
110 
     | 
    
         
             
                    @socket.should_receive(:read).with(4).and_return([1].pack('N'))
         
     | 
| 
         @@ -159,7 +159,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       159 
159 
     | 
    
         
             
                    @server.should_receive(:get_socket).at_least(1).times.and_yield(@socket).and_return(@socket)
         
     | 
| 
       160 
160 
     | 
    
         
             
                    @server.should_receive(:free_socket).with(@socket).at_least(1)
         
     | 
| 
       161 
161 
     | 
    
         
             
                  end
         
     | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
       163 
163 
     | 
    
         
             
                  it 'should raise an exception on error' do
         
     | 
| 
       164 
164 
     | 
    
         
             
                    @socket.should_receive(:write).exactly(3).times.with([1].pack('N'))
         
     | 
| 
       165 
165 
     | 
    
         
             
                    @socket.should_receive(:read).exactly(3).times.with(4).and_return([1].pack('N'))
         
     | 
| 
         @@ -174,7 +174,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       174 
174 
     | 
    
         
             
                  end
         
     | 
| 
       175 
175 
     | 
    
         
             
                end
         
     | 
| 
       176 
176 
     | 
    
         
             
              end
         
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
       178 
178 
     | 
    
         
             
              context 'in parse_response method' do
         
     | 
| 
       179 
179 
     | 
    
         
             
                before :each do
         
     | 
| 
       180 
180 
     | 
    
         
             
                  @sphinx = Sphinx::Client.new
         
     | 
| 
         @@ -182,20 +182,20 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       182 
182 
     | 
    
         
             
                end
         
     | 
| 
       183 
183 
     | 
    
         | 
| 
       184 
184 
     | 
    
         
             
                it 'should receive response' do
         
     | 
| 
       185 
     | 
    
         
            -
                  @socket.should_receive(:read).with(8).and_return([Sphinx:: 
     | 
| 
      
 185 
     | 
    
         
            +
                  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_OK, 1, 4].pack('n2N'))
         
     | 
| 
       186 
186 
     | 
    
         
             
                  @socket.should_receive(:read).with(4).and_return([0].pack('N'))
         
     | 
| 
       187 
187 
     | 
    
         
             
                  @sphinx.send(:parse_response, @socket, 1)
         
     | 
| 
       188 
188 
     | 
    
         
             
                end
         
     | 
| 
       189 
189 
     | 
    
         | 
| 
       190 
190 
     | 
    
         
             
                it 'should raise exception on zero-sized response' do
         
     | 
| 
       191 
     | 
    
         
            -
                  @socket.should_receive(:read).with(8).and_return([Sphinx:: 
     | 
| 
      
 191 
     | 
    
         
            +
                  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_OK, 1, 0].pack('n2N'))
         
     | 
| 
       192 
192 
     | 
    
         
             
                  expect {
         
     | 
| 
       193 
193 
     | 
    
         
             
                    @sphinx.send(:parse_response, @socket, 1)
         
     | 
| 
       194 
194 
     | 
    
         
             
                  }.to raise_error(Sphinx::SphinxResponseError, 'received zero-sized searchd response')
         
     | 
| 
       195 
195 
     | 
    
         
             
                end
         
     | 
| 
       196 
196 
     | 
    
         | 
| 
       197 
197 
     | 
    
         
             
                it 'should raise exception when response is incomplete' do
         
     | 
| 
       198 
     | 
    
         
            -
                  @socket.should_receive(:read).with(8).and_return([Sphinx:: 
     | 
| 
      
 198 
     | 
    
         
            +
                  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_OK, 1, 4].pack('n2N'))
         
     | 
| 
       199 
199 
     | 
    
         
             
                  @socket.should_receive(:read).with(4).and_return('')
         
     | 
| 
       200 
200 
     | 
    
         
             
                  expect {
         
     | 
| 
       201 
201 
     | 
    
         
             
                    @sphinx.send(:parse_response, @socket, 1)
         
     | 
| 
         @@ -203,14 +203,14 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       203 
203 
     | 
    
         
             
                end
         
     | 
| 
       204 
204 
     | 
    
         | 
| 
       205 
205 
     | 
    
         
             
                it 'should set warning message when SEARCHD_WARNING received' do
         
     | 
| 
       206 
     | 
    
         
            -
                  @socket.should_receive(:read).with(8).and_return([Sphinx:: 
     | 
| 
      
 206 
     | 
    
         
            +
                  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_WARNING, 1, 14].pack('n2N'))
         
     | 
| 
       207 
207 
     | 
    
         
             
                  @socket.should_receive(:read).with(14).and_return([5].pack('N') + 'helloworld')
         
     | 
| 
       208 
208 
     | 
    
         
             
                  @sphinx.send(:parse_response, @socket, 1).should == 'world'
         
     | 
| 
       209 
209 
     | 
    
         
             
                  @sphinx.GetLastWarning.should == 'hello'
         
     | 
| 
       210 
210 
     | 
    
         
             
                end
         
     | 
| 
       211 
211 
     | 
    
         | 
| 
       212 
212 
     | 
    
         
             
                it 'should raise exception when SEARCHD_ERROR received' do
         
     | 
| 
       213 
     | 
    
         
            -
                  @socket.should_receive(:read).with(8).and_return([Sphinx:: 
     | 
| 
      
 213 
     | 
    
         
            +
                  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_ERROR, 1, 9].pack('n2N'))
         
     | 
| 
       214 
214 
     | 
    
         
             
                  @socket.should_receive(:read).with(9).and_return([1].pack('N') + 'hello')
         
     | 
| 
       215 
215 
     | 
    
         
             
                  expect {
         
     | 
| 
       216 
216 
     | 
    
         
             
                    @sphinx.send(:parse_response, @socket, 1)
         
     | 
| 
         @@ -218,7 +218,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       218 
218 
     | 
    
         
             
                end
         
     | 
| 
       219 
219 
     | 
    
         | 
| 
       220 
220 
     | 
    
         
             
                it 'should raise exception when SEARCHD_RETRY received' do
         
     | 
| 
       221 
     | 
    
         
            -
                  @socket.should_receive(:read).with(8).and_return([Sphinx:: 
     | 
| 
      
 221 
     | 
    
         
            +
                  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_RETRY, 1, 9].pack('n2N'))
         
     | 
| 
       222 
222 
     | 
    
         
             
                  @socket.should_receive(:read).with(9).and_return([1].pack('N') + 'hello')
         
     | 
| 
       223 
223 
     | 
    
         
             
                  expect {
         
     | 
| 
       224 
224 
     | 
    
         
             
                    @sphinx.send(:parse_response, @socket, 1)
         
     | 
| 
         @@ -234,7 +234,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       234 
234 
     | 
    
         
             
                end
         
     | 
| 
       235 
235 
     | 
    
         | 
| 
       236 
236 
     | 
    
         
             
                it 'should set warning when server is older than client' do
         
     | 
| 
       237 
     | 
    
         
            -
                  @socket.should_receive(:read).with(8).and_return([Sphinx:: 
     | 
| 
      
 237 
     | 
    
         
            +
                  @socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_OK, 1, 9].pack('n2N'))
         
     | 
| 
       238 
238 
     | 
    
         
             
                  @socket.should_receive(:read).with(9).and_return([1].pack('N') + 'hello')
         
     | 
| 
       239 
239 
     | 
    
         
             
                  @sphinx.send(:parse_response, @socket, 5)
         
     | 
| 
       240 
240 
     | 
    
         
             
                  @sphinx.GetLastWarning.should == 'searchd command v.0.1 older than client\'s v.0.5, some options might not work'
         
     | 
| 
         @@ -291,7 +291,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       291 
291 
     | 
    
         
             
                    it "should generate valid request for SPH_MATCH_#{match.to_s.upcase}" do
         
     | 
| 
       292 
292 
     | 
    
         
             
                      expected = sphinx_fixture("match_#{match}")
         
     | 
| 
       293 
293 
     | 
    
         
             
                      @sock.should_receive(:write).with(expected)
         
     | 
| 
       294 
     | 
    
         
            -
                      @sphinx.SetMatchMode(Sphinx:: 
     | 
| 
      
 294 
     | 
    
         
            +
                      @sphinx.SetMatchMode(Sphinx::const_get("SPH_MATCH_#{match.to_s.upcase}"))
         
     | 
| 
       295 
295 
     | 
    
         
             
                      sphinx_safe_call { @sphinx.Query('query') }
         
     | 
| 
       296 
296 
     | 
    
         
             
                    end
         
     | 
| 
       297 
297 
     | 
    
         | 
| 
         @@ -485,7 +485,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       485 
485 
     | 
    
         
             
                    it "should generate valid request for SPH_GROUPBY_#{groupby.to_s.upcase}" do
         
     | 
| 
       486 
486 
     | 
    
         
             
                      expected = sphinx_fixture("group_by_#{groupby}")
         
     | 
| 
       487 
487 
     | 
    
         
             
                      @sock.should_receive(:write).with(expected)
         
     | 
| 
       488 
     | 
    
         
            -
                      @sphinx.SetGroupBy('attr', Sphinx:: 
     | 
| 
      
 488 
     | 
    
         
            +
                      @sphinx.SetGroupBy('attr', Sphinx::const_get("SPH_GROUPBY_#{groupby.to_s.upcase}"))
         
     | 
| 
       489 
489 
     | 
    
         
             
                      sphinx_safe_call { @sphinx.Query('query') }
         
     | 
| 
       490 
490 
     | 
    
         
             
                    end
         
     | 
| 
       491 
491 
     | 
    
         | 
| 
         @@ -507,14 +507,14 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       507 
507 
     | 
    
         
             
                  it 'should generate valid request for SPH_GROUPBY_DAY with sort' do
         
     | 
| 
       508 
508 
     | 
    
         
             
                    expected = sphinx_fixture('group_by_day_sort')
         
     | 
| 
       509 
509 
     | 
    
         
             
                    @sock.should_receive(:write).with(expected)
         
     | 
| 
       510 
     | 
    
         
            -
                    @sphinx.SetGroupBy('attr', Sphinx:: 
     | 
| 
      
 510 
     | 
    
         
            +
                    @sphinx.SetGroupBy('attr', Sphinx::SPH_GROUPBY_DAY, 'somesort')
         
     | 
| 
       511 
511 
     | 
    
         
             
                    sphinx_safe_call { @sphinx.Query('query') }
         
     | 
| 
       512 
512 
     | 
    
         
             
                  end
         
     | 
| 
       513 
513 
     | 
    
         | 
| 
       514 
514 
     | 
    
         
             
                  it 'should generate valid request with count-distinct attribute' do
         
     | 
| 
       515 
515 
     | 
    
         
             
                    expected = sphinx_fixture('group_distinct')
         
     | 
| 
       516 
516 
     | 
    
         
             
                    @sock.should_receive(:write).with(expected)
         
     | 
| 
       517 
     | 
    
         
            -
                    @sphinx.SetGroupBy('attr', Sphinx:: 
     | 
| 
      
 517 
     | 
    
         
            +
                    @sphinx.SetGroupBy('attr', Sphinx::SPH_GROUPBY_DAY)
         
     | 
| 
       518 
518 
     | 
    
         
             
                    @sphinx.SetGroupDistinct('attr')
         
     | 
| 
       519 
519 
     | 
    
         
             
                    sphinx_safe_call { @sphinx.Query('query') }
         
     | 
| 
       520 
520 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -537,9 +537,9 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       537 
537 
     | 
    
         
             
                it 'should generate valid request for SetOverride' do
         
     | 
| 
       538 
538 
     | 
    
         
             
                  expected = sphinx_fixture('set_override')
         
     | 
| 
       539 
539 
     | 
    
         
             
                  @sock.should_receive(:write).with(expected)
         
     | 
| 
       540 
     | 
    
         
            -
                  @sphinx.SetOverride('attr1', Sphinx:: 
     | 
| 
       541 
     | 
    
         
            -
                  @sphinx.SetOverride('attr2', Sphinx:: 
     | 
| 
       542 
     | 
    
         
            -
                  @sphinx.SetOverride('attr3', Sphinx:: 
     | 
| 
      
 540 
     | 
    
         
            +
                  @sphinx.SetOverride('attr1', Sphinx::SPH_ATTR_INTEGER, { 10 => 20 })
         
     | 
| 
      
 541 
     | 
    
         
            +
                  @sphinx.SetOverride('attr2', Sphinx::SPH_ATTR_FLOAT, { 11 => 30.3 })
         
     | 
| 
      
 542 
     | 
    
         
            +
                  @sphinx.SetOverride('attr3', Sphinx::SPH_ATTR_BIGINT, { 12 => 1099511627780 })
         
     | 
| 
       543 
543 
     | 
    
         
             
                  sphinx_safe_call { @sphinx.Query('query') }
         
     | 
| 
       544 
544 
     | 
    
         
             
                end
         
     | 
| 
       545 
545 
     | 
    
         | 
| 
         @@ -562,7 +562,7 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       562 
562 
     | 
    
         | 
| 
       563 
563 
     | 
    
         
             
                  @sphinx.SetRetries(10, 20)
         
     | 
| 
       564 
564 
     | 
    
         
             
                  @sphinx.AddQuery('test1')
         
     | 
| 
       565 
     | 
    
         
            -
                  @sphinx.SetGroupBy('attr', Sphinx:: 
     | 
| 
      
 565 
     | 
    
         
            +
                  @sphinx.SetGroupBy('attr', Sphinx::SPH_GROUPBY_DAY)
         
     | 
| 
       566 
566 
     | 
    
         
             
                  @sphinx.AddQuery('test2')
         
     | 
| 
       567 
567 
     | 
    
         | 
| 
       568 
568 
     | 
    
         
             
                  sphinx_safe_call { @sphinx.RunQueries }
         
     | 
| 
         @@ -656,4 +656,14 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       656 
656 
     | 
    
         
             
                  sphinx_safe_call { @sphinx.UpdateAttributes('index', ['group', 'category'], { 123 => [ [456, 789], [1, 2, 3] ] }, true) }
         
     | 
| 
       657 
657 
     | 
    
         
             
                end
         
     | 
| 
       658 
658 
     | 
    
         
             
              end
         
     | 
| 
      
 659 
     | 
    
         
            +
             
     | 
| 
      
 660 
     | 
    
         
            +
              context 'in EscapeString method' do
         
     | 
| 
      
 661 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 662 
     | 
    
         
            +
                  @sphinx = Sphinx::Client.new
         
     | 
| 
      
 663 
     | 
    
         
            +
                end
         
     | 
| 
      
 664 
     | 
    
         
            +
             
     | 
| 
      
 665 
     | 
    
         
            +
                it 'should escape special characters' do
         
     | 
| 
      
 666 
     | 
    
         
            +
                  @sphinx.escape_string("escaping-sample@query/string").should == "escaping\\-sample\\@query\\/string"
         
     | 
| 
      
 667 
     | 
    
         
            +
                end
         
     | 
| 
      
 668 
     | 
    
         
            +
              end
         
     | 
| 
       659 
669 
     | 
    
         
             
            end
         
     | 
| 
         @@ -327,10 +327,18 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       327 
327 
     | 
    
         
             
                  }.to_not raise_error(ArgumentError)
         
     | 
| 
       328 
328 
     | 
    
         
             
                end
         
     | 
| 
       329 
329 
     | 
    
         | 
| 
       330 
     | 
    
         
            -
                it 'should raise an error when values is not Array' do
         
     | 
| 
      
 330 
     | 
    
         
            +
                it 'should raise an error when values is not Array or Integer' do
         
     | 
| 
       331 
331 
     | 
    
         
             
                  expect {
         
     | 
| 
       332 
332 
     | 
    
         
             
                    @sphinx.SetFilter(:attr, {})
         
     | 
| 
       333 
333 
     | 
    
         
             
                  }.to raise_error(ArgumentError)
         
     | 
| 
      
 334 
     | 
    
         
            +
             
     | 
| 
      
 335 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 336 
     | 
    
         
            +
                    @sphinx.SetFilter(:attr, 1)
         
     | 
| 
      
 337 
     | 
    
         
            +
                  }.to_not raise_error(ArgumentError)
         
     | 
| 
      
 338 
     | 
    
         
            +
             
     | 
| 
      
 339 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 340 
     | 
    
         
            +
                    @sphinx.SetFilter(:attr, [1])
         
     | 
| 
      
 341 
     | 
    
         
            +
                  }.to_not raise_error(ArgumentError)
         
     | 
| 
       334 
342 
     | 
    
         
             
                end
         
     | 
| 
       335 
343 
     | 
    
         | 
| 
       336 
344 
     | 
    
         
             
                it 'should raise an error when values is not Array of Integers' do
         
     | 
| 
         @@ -339,10 +347,11 @@ describe Sphinx::Client, 'disconnected' do 
     | 
|
| 
       339 
347 
     | 
    
         
             
                  }.to raise_error(ArgumentError)
         
     | 
| 
       340 
348 
     | 
    
         
             
                end
         
     | 
| 
       341 
349 
     | 
    
         | 
| 
       342 
     | 
    
         
            -
                it 'should raise an error when values is empty Array' do
         
     | 
| 
      
 350 
     | 
    
         
            +
                it 'should not raise an error when values is empty Array' do
         
     | 
| 
       343 
351 
     | 
    
         
             
                  expect {
         
     | 
| 
       344 
352 
     | 
    
         
             
                    @sphinx.SetFilter(:attr, [])
         
     | 
| 
       345 
     | 
    
         
            -
                  }. 
     | 
| 
      
 353 
     | 
    
         
            +
                  }.to_not raise_error(ArgumentError)
         
     | 
| 
      
 354 
     | 
    
         
            +
                  @sphinx.instance_variable_get(:@filters).should be_empty
         
     | 
| 
       346 
355 
     | 
    
         
             
                end
         
     | 
| 
       347 
356 
     | 
    
         | 
| 
       348 
357 
     | 
    
         
             
                it 'should raise an error when exclude is not Boolean' do
         
     | 
    
        data/sphinx.gemspec
    CHANGED
    
    | 
         @@ -5,11 +5,11 @@ 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            Gem::Specification.new do |s|
         
     | 
| 
       7 
7 
     | 
    
         
             
              s.name = %q{sphinx}
         
     | 
| 
       8 
     | 
    
         
            -
              s.version = "0.9.10. 
     | 
| 
      
 8 
     | 
    
         
            +
              s.version = "0.9.10.2122"
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         
     | 
| 
       11 
11 
     | 
    
         
             
              s.authors = ["Dmytro Shteflyuk"]
         
     | 
| 
       12 
     | 
    
         
            -
              s.date = %q{2009- 
     | 
| 
      
 12 
     | 
    
         
            +
              s.date = %q{2009-12-04}
         
     | 
| 
       13 
13 
     | 
    
         
             
              s.description = %q{An easy interface to Sphinx standalone full-text search engine. It is implemented as plugin for Ruby on Rails, but can be easily used as standalone library.}
         
     | 
| 
       14 
14 
     | 
    
         
             
              s.email = %q{kpumuk@kpumuk.info}
         
     | 
| 
       15 
15 
     | 
    
         
             
              s.extra_rdoc_files = [
         
     | 
| 
         @@ -24,6 +24,8 @@ Gem::Specification.new do |s| 
     | 
|
| 
       24 
24 
     | 
    
         
             
                 "lib/sphinx.rb",
         
     | 
| 
       25 
25 
     | 
    
         
             
                 "lib/sphinx/buffered_io.rb",
         
     | 
| 
       26 
26 
     | 
    
         
             
                 "lib/sphinx/client.rb",
         
     | 
| 
      
 27 
     | 
    
         
            +
                 "lib/sphinx/constants.rb",
         
     | 
| 
      
 28 
     | 
    
         
            +
                 "lib/sphinx/indifferent_access.rb",
         
     | 
| 
       27 
29 
     | 
    
         
             
                 "lib/sphinx/request.rb",
         
     | 
| 
       28 
30 
     | 
    
         
             
                 "lib/sphinx/response.rb",
         
     | 
| 
       29 
31 
     | 
    
         
             
                 "lib/sphinx/server.rb",
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification 
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: sphinx
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.9.10. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.9.10.2122
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors: 
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Dmytro Shteflyuk
         
     | 
| 
         @@ -9,7 +9,7 @@ autorequire: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
            date: 2009- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2009-12-04 00:00:00 +02:00
         
     | 
| 
       13 
13 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       14 
14 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
         @@ -30,6 +30,8 @@ files: 
     | 
|
| 
       30 
30 
     | 
    
         
             
            - lib/sphinx.rb
         
     | 
| 
       31 
31 
     | 
    
         
             
            - lib/sphinx/buffered_io.rb
         
     | 
| 
       32 
32 
     | 
    
         
             
            - lib/sphinx/client.rb
         
     | 
| 
      
 33 
     | 
    
         
            +
            - lib/sphinx/constants.rb
         
     | 
| 
      
 34 
     | 
    
         
            +
            - lib/sphinx/indifferent_access.rb
         
     | 
| 
       33 
35 
     | 
    
         
             
            - lib/sphinx/request.rb
         
     | 
| 
       34 
36 
     | 
    
         
             
            - lib/sphinx/response.rb
         
     | 
| 
       35 
37 
     | 
    
         
             
            - lib/sphinx/server.rb
         
     |