pax_global_header 0000666 0000000 0000000 00000000064 13255650766 0014531 g ustar 00root root 0000000 0000000 52 comment=57065afa98446ec93cb8c1fdc0770313d7067c4d
riddle-2.3.1/ 0000775 0000000 0000000 00000000000 13255650766 0012777 5 ustar 00root root 0000000 0000000 riddle-2.3.1/.gitignore 0000664 0000000 0000000 00000000061 13255650766 0014764 0 ustar 00root root 0000000 0000000 *.gem
*.rbc
*.swp
*.tmproj
coverage
Gemfile.lock
riddle-2.3.1/.travis.yml 0000664 0000000 0000000 00000001106 13255650766 0015106 0 ustar 00root root 0000000 0000000 language: ruby
rvm:
- 2.2.9
- 2.3.6
- 2.4.3
- 2.5.0
- jruby-9.1.14.0
env:
global:
- SPHINX_BIN=ext/sphinx/bin/
- secure: aP3wCZnnqim/yBWbO8+N2DAJIDVuqewUayK3nBphR/Jt1POIMbqCIuHwk/SG/JfMc6pJIlH0QOX8wI3fF3y5GO6aIrN8xKAX0DoDm+Gkvk/YEk3cK/2fJUwvocR89M99EoV8ctLPaR03B3dm3h2Dh2oe8NQRBfcrL3WtiHHq3d0=
matrix:
- SPHINX_VERSION=2.0.10
- SPHINX_VERSION=2.1.9
- SPHINX_VERSION=2.2.11
- SPHINX_VERSION=3.0.2
before_script:
- killall searchd; echo ''
- "./bin/loadsphinx $SPHINX_VERSION"
before_install:
- gem update --system
after_script:
- killall searchd; echo ''
sudo: false
riddle-2.3.1/Gemfile 0000664 0000000 0000000 00000000245 13255650766 0014273 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
source 'http://rubygems.org'
gemspec
gem 'mysql2', '0.5.0', :platform => :ruby
gem 'jdbc-mysql', '5.1.35', :platform => :jruby
riddle-2.3.1/HISTORY 0000664 0000000 0000000 00000020244 13255650766 0014065 0 ustar 00root root 0000000 0000000 2.3.1 - March 25th 2018
- Handle parsing of invalid configuration files without endlessly looping.
- Test against mysql2 0.5.
- Test against Sphinx 3.0.
2.3.0 - January 14th 2018
- Add controller method for merging indices.
- Add support for sockets in searchd configuration.
- Fix handling of command errors when executed via backticks (verbose).
2.2.2 - December 2nd 2017
- Fix frozen string concatenation for searchd/indexer commands.
2.2.1 - December 2nd 2017
- Check if Mysql2::Client is defined before using it (not just Mysql2).
2.2.0 - June 20th 2017
- Add compatibility for MRI's frozen string literals setting.
- Stop packaging test files with gem releases (@dimko).
2.1.0 - January 5th 2017
- Wrap string attribute filter values in single quotes.
- Remove direct references to FixNum to avoid MRI 2.4 warnings.
- Remove escaped line-endings while parsing.
- Escape word-operators like MAYBE, NEAR etc (Jonathan del Strother)
2.0.0 - September 25th 2016
- Start and stop commands now accept a verbose option.
- Failed commands (as determined by a non-zero status code) raise a Riddle::CommandFailedError exception.
- A missing configuration file when running the start and stop commands now raises a Riddle::NoConfigurationFileError instance instead of a generic RuntimeError instance.
- Riddle::Controller now returns Riddle::CommandResult instances for indexing, start and stop commands, which includes status code and (non-verbose) output.
- Handle group_concat attribute types (@crazyshot, @bibendi).
- Additional searchd settings: query_log_min_msec, agent_conect_timeout, agent_query_timeout, agent_retry_count, agent_retry_delay.
- Default to 2.1.0 or newer support.
- Move plugin_dir option from searchd to common.
1.5.12 - June 1st 2015
- Adding ? as an escaped character (Alexey Nikitin).
- Adding contributor code of conduct.
- Spec fixes, and updating escape_column to not escape JSON expressions that make use of dot or bracket notation (Daniel Vandersluis).
- Fix stop action to allow exception propagation (Dejan Simic).
1.5.11 - April 19th 2014
- Riddle::Query.escape covers = and & characters.
- Hold onto address and port settings when crafting the equivalent listen setting, but don't render them.
- Allow for Sphinx's common settings section (Trevor Smith). Optional and initially disabled.
- Allow for multiple attributes in GROUP BY clauses (J. Garcia).
- Riddle::Query.escape covers < and > characters.
- The parser should not presume indexer and searchd sections exist.
1.5.10 - January 11th 2014
- SELECT values can be prepended as well as the existing append support.
- New settings for Sphinx 2.2.1.
- Template index type for Sphinx 2.2.1.
- TSV source types for Sphinx 2.2.1.
- Support for HAVING, GROUP-n-BEST in SELECT statements.
- Dates in filters are converted to (UTC) timestamp integers.
- Default to * in SELECT queries only if nothing else is supplied.
- Fix licence, URL in gemspec (Ken Dreyer).
- Handle empty arrays for filter elegantly (Bryan Ricker).
- Add a contributing section to the README (Ken Dreyer).
- Don't automatically escape function references in SphinxQL ORDER clauses.
1.5.9 - October 20th 2013
- Adding all known Sphinx settings to configuration classes as of Sphinx 2.1.2, including JSON settings.
- Convert date objects in INSERT/REPLACE queries to timestamps, just like time objects.
- Don't escape references to id in SphinxQL INSERT/REPLACE queries.
1.5.8 - August 26th 2013
- Reworked escaping to be consistent and always query-safe (Demian Ferreiro).
- Escape column names in SphinxQL WHERE, INSERT, ORDER BY and GROUP BY clauses and statements (Jason Rust).
1.5.7 - July 9th 2013
- Respect Riddle::OutOfBoundsError instances, instead of wrapping them in ResponseError.
- Handle boolean values for snippets options.
- Don't modify snippets parameters (Demian Ferreiro).
- rt_attr_multi and rt_attr_multi_64 settings for real-time indices.
- Arrays in INSERT/REPLACE statements are wrapped in parentheses with values separated by commas. Required for MVA values in real-time indices.
- Clear out the query queue before running a single query.
1.5.6 - May 7th 2013
- Wrap underlying parse errors within Riddle::ResponseError instances when parsing responses.
- Add lemmatization options (Kirill Lazarev).
- Ignore configuration lines that are only comments when parsing configurations.
- Construct GROUP ORDER and ORDER in SphinxQL in the correct order (Grzegorz Derebecki).
1.5.5 - February 23rd 2013
- Added Riddle::Query.escape for SphinxQL queries.
- Fixed failover handling (Ngan Pham).
- Improved encoding default check (Darcy Brown).
- Removing REE support (as it is no longer supported either).
- Client key is used for binary protocol persistent connections (if set).
- Escaping single quotes in SphinxQL snippets calls.
- Regex fix for matching {'s (Rob Golkosky).
1.5.4 - January 2nd 2013
- RT indices get most of the same settings as SQL indices.
- Escape single quotes in SphinxQL match queries, given we're wrapping them in single quotes.
- Remove unnecessary characters from string values for SphinxQL inserts.
- Convert time objects to integers for SphinxQL inserts.
- Include 'orphan' sources (which aren't used directly by indices, but could be parents of sources that are used) when generating configuration files.
- Use parent source type if child source has no type supplied.
- Ignore comments when parsing Sphinx configuration files.
1.5.3 - August 10th 2012
- Sphinx 2.0.5 support.
- :with_all and :without_all support for SphinxQL.
- Allow setting of prefix and infix fields directly.
- Configuration parser
- Adding rotate command to the controller.
1.5.2 - May 14th 2012
- Fixing 64-bit MVA support.
- Grouped searches now sort by weight instead of by group as a default. You can change this setting via Riddle::Client#group_clause.
- Use a local array of servers - don't clear the main set (S. Christoffer Eliesen).
- Fixing VersionError reference for Sphinx 0.9.9 or better (S. Christoffer Eliesen).
- Consistent documentation for default port: 9312 (Aleksey Morozov).
- Sphinx 2.0.4 support (Ilia Lobsanov).
- Handle single-value float filters (by translating them to a range) (Steven Bristol).
- Sphinx 2.0.2-dev handled as Sphinx 2.0.1.
- Sphinx 2.0.3 support.
- String options handled appropriately for SphinxQL excerpts calls.
1.5.1 - January 2nd 2012
- If no known servers work, raise an appropriate error.
- Sphinx 2.1.0-dev support.
1.5.0 - November 4th 2011
- Handle exclusive filters in SphinxQL SELECT commands.
- Allow for native Ruby objects in SphinxQL UPDATE commands.
- Handle options of hashes in SphinxQL SELECT commands.
- Allow for SphinxQL select clauses.
- Improving SphinxQL filter handling of native Ruby objects.
- Switch plural index references from indexes to indices, to distinguish beside indexes (the action).
- Rescue against timeouts and connection resets.
- Fixing reference to TCPSocket.
- Handle port numbers as integers for listen setting (Ngan Pham).
- Provide the option to start searchd with the nodetach flag (Aaron Gilbralter).
- Don't shuffle servers (if there's more than one) - let developers (or Thinking Sphinx) manage that (Ngan Pham).
1.4.0 - August 2nd 2011
- Checking against both Windows platforms for Ruby (Paul Gibler)
- Encoding improvements (Alexey Artamonov)
- More Rubyish syntax (James Cook)
- Handling Ruby encodings (James Cook)
- Coreseek support (saberma)
- Section restructure for better inheritance (Alexey Artamonov)
- MySQL41 connection support
- requiring 'thread' for Mutex use
1.3.3 - May 25th 2011
- Using MySQL2 library for SphinxQL interface
- Adding Sphinx 2.0.x settings
- SphinxQL support
- Speed improvements for hash lookups (Enrico Thierbach)
- Handle race conditions of segfaults while returning responses (Jason Lambert)
- 2.0.x support
1.3.2 - May 12th 2011
- client_key support
1.3.1 - May 9th 2011
- Don't output warnings or exit when version isn't detected - presume Thinking Sphinx will handle that.
- Confirm configuration file exists before attempting to start/stop Sphinx.
- Use a Mutex instead of the current Thread.
1.3.0 - May 7th 2011
- Attempts at untested 2.0.x and client_key support
- Using Bundler, MySQL2 and Ruby 1.9.2 in development
- Allow for Sphinx versions compiled from source and SVN (Greg Weber)
1.2.2 - December 22nd 2011
riddle-2.3.1/LICENCE 0000664 0000000 0000000 00000002042 13255650766 0013762 0 ustar 00root root 0000000 0000000 Copyright (c) 2008-2010 Pat Allan
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
riddle-2.3.1/README.markdown 0000664 0000000 0000000 00000021052 13255650766 0015500 0 ustar 00root root 0000000 0000000 # Riddle
[](https://travis-ci.org/pat/riddle)
Riddle is a Ruby library interfacing with the [Sphinx](http://sphinxsearch.com/) full-text search tool. It is written by [Pat Allan](http://freelancing-gods.com), and has been influenced by both Dmytro Shteflyuk's Ruby client and the original PHP client. It can be used for interactions with Sphinx's command-line tools `searchd` and `indexer`, sending search queries via the binary protocol, and programmatically generating Sphinx configuration files.
The syntax here, while closer to a usual Ruby approach than the PHP client, is quite old (Riddle was first published in 2007). While it would be nice to re-work things, it's really not a priority, given the bulk of Riddle's code is for Sphinx's deprecated binary protocol.
## Installation
Riddle is available as a gem, so you can install it directly:
gem install riddle
Or include it in a Gemfile:
gem 'riddle', '~> 2.3.1'
## Usage
As of version 1.0.0, Riddle supports multiple versions of Sphinx in the one gem - you'll need to require your specific version after a normal require, though. The latest distinct version is `2.1.0`:
require 'riddle'
require 'riddle/2.1.0'
The full list of versions available are `0.9.8` (the initial base), `0.9.9`, `1.10`, `2.0.1`, and `2.1.0`. If you're using something more modern than 2.1.0, then just require that, and the rest should be fine (changes to the binary protocol since then are minimal).
### Configuration
Riddle's structure for generating Sphinx configuration is very direct mapping to Sphinx's configuration options. First, create an instance of `Riddle::Configuration`:
config = Riddle::Configuration.new
This configuration instance has methods `indexer`, `searchd` and `common`, which return separate inner-configuration objects with methods mapping to the equivalent [Sphinx settings](http://sphinxsearch.com/docs/current.html#conf-reference). So, you may want to do the following:
config.indexer.mem_limit = '128M'
config.searchd.log = '/my/log/file.log'
Similarly, there are two further methods `indices` and `sources`, which are arrays meant to hold instances of index and source inner-configuration objects respectively (all of which have methods matching their Sphinx settings). The available index classes are:
* `Riddle::Configuration::DistributedIndex`
* `Riddle::Configuration::Index`
* `Riddle::Configuration::RealtimeIndex`
* `Riddle::Configuration::RemoteIndex`
* `Riddle::Configuration::TemplateIndex`
All of these index classes should be initialised with their name, and in the case of plain indices, their source objects. Remote indices take an address, port and name as their initialiser parameters.
index = Riddle::Configuration::Index.new 'articles', article_source_a, article_source_b
index.path = '/path/to/index/files"
index.docinfo = 'external'
The available source classes are:
* `Riddle::Configuration::SQLSource`
* `Riddle::Configuration::TSVSource`
* `Riddle::Configuration::XMLSource`
The initialising parameters are the name of the source, and the type of source:
source = Riddle::Configuration::SQLSource.new 'article_source', 'mysql'
source.sql_query = "SELECT id, title, body FROM articles"
source.sql_host = "127.0.0.1"
Once you have created your configuration object tree, you can then generate the string representation and perhaps save it to a file:
File.write "sphinx.conf", configuration.render
It's also possible to parse an existing Sphinx configuration file into a configuration option tree:
configuration = Riddle::Configuration.parse! File.read('sphinx.conf')
### Indexing and Starting/Stopping the Daemon
using Sphinx's command-line tools `indexer` and `searchd` via Riddle is all done via an instance of `Riddle::Controller`:
configuration_file = "/path/to/sphinx.conf"
configuration = Riddle::Configuration.parse! File.read(configuration_file)
controller = Riddle::Controller.new configuration, configuration_file
# set the path where the indexer and searchd binaries are located:
controller.bin_path = '/usr/local/bin'
# set different binary names if you're running a custom Sphinx installation:
controller.searchd_binary_name = 'sphinxsearchd'
controller.indexer_binary_name = 'sphinxindexer'
# process all indices:
controller.index
# process specific indices:
controller.index 'articles', 'books'
# rotate old index files out for the new ones:
controller.rotate
# start the daemon:
controller.start
# start the daemon and do not detach the process:
controller.start :nodetach => true
# stop the daemon:
controller.stop
The index, start and stop methods all accept a hash of options, and the :verbose option is respected in each case.
Each of these methods will return an instance of `Riddle::CommandResult` - or, if the command fails (as judged by the process status code), a `Riddle::CommandFailedError` exception is raised. These exceptions respond to the `command_result` method with the corresponding details.
### SphinxQL Queries
Riddle does not have any code to send SphinxQL queries and commands to Sphinx. Because Sphinx uses the mysql41 protocol (thus, mimicing a MySQL database server), I recommend using the [mysql2](https://github.com/brianmario/mysql2) gem instead. The [connection code](https://github.com/pat/thinking-sphinx/blob/develop/lib/thinking_sphinx/connection.rb) in Thinking Sphinx may provide some inspiration on this.
### Binary Protocol Searching
Sphinx's legacy binary protocol does not have many of the more recent Sphinx features - such as real-time indices - as these are only available in the SphinxQL/mysql41 protocol. However, Riddle can still be used for the binary protocol if you wish.
To get started, just instantiate a Client object:
client = Riddle::Client.new # defaults to localhost and port 9312
client = Riddle::Client.new "sphinxserver.domain.tld", 3333 # custom settings
And then set the parameters to what you want, before running a query:
client.match_mode = :extended
client.query "Pat Allan @state Victoria"
The results from a query are similar to the other clients - but here's the details. It's a hash with
the following keys:
* `:matches`
* `:fields`
* `:attributes`
* `:attribute_names`
* `:words`
* `:total`
* `:total_found`
* `:time`
* `:status`
* `:warning` (if appropriate)
* `:error` (if appropriate)
The key `:matches` returns an array of hashes - the actual search results. Each hash has the document id (`:doc`), the result weighting (`:weight`), and a hash of the attributes for the document (`:attributes`).
The `:fields` and `:attribute_names` keys return list of fields and attributes for the documents. The key `:attributes` will return a hash of attribute name and type pairs, and `:words` returns a hash of hashes representing the words from the search, with the number of documents and hits for each, along the lines of:
results[:words]["Pat"] #=> {:docs => 12, :hits => 15}
`:total`, `:total_found` and `:time` return the number of matches available, the total number of matches (which may be greater than the maximum available), and the time in milliseconds that the query took to run.
`:status` is the error code for the query - and if there was a related warning, it will be under the `:warning` key. Fatal errors will be described under `:error`.
## Contributing
Please note that this project has a [Contributor Code of Conduct](http://contributor-covenant.org/version/1/0/0/). By participating in this project you agree to abide by its terms.
Riddle uses the [git-flow](http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/) process for development. The `master` branch is the latest released code (in a gem). The `develop` branch is what's coming in the next release. (There may be occasional feature and hotfix branches, although these are generally not pushed to GitHub.)
When submitting a patch to Riddle, please submit your pull request against the `develop` branch.
## Contributors
Thanks to the following people who have contributed to Riddle in some shape or form:
* Andrew Aksyonoff
* Brad Greenlee
* Lachie Cox
* Jeremy Seitz
* Mark Lane
* Xavier Noria
* Henrik Nye
* Kristopher Chambers
* Rob Anderton
* Dylan Egan
* Jerry Vos
* Piotr Sarnacki
* Tim Preston
* Amir Yalon
* Sam Goldstein
* Matt Todd
* Paco Guzmán
* Greg Weber
* Enrico Thierbach
* Jason Lambert
* Saberma
* James Cook
* Alexey Artamonov
* Paul Gibler
* Ngan Pham
* Aaron Gilbralter
* Steven Bristol
* Ilia Lobsanov
* Aleksey Morozov
* S\. Christoffer Eliesen
* Rob Golkosky
* Darcy Brown
riddle-2.3.1/Rakefile 0000664 0000000 0000000 00000000730 13255650766 0014444 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'rubygems'
require 'bundler'
Bundler::GemHelper.install_tasks
Bundler.require :default, :development
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new
RSpec::Core::RakeTask.new(:rcov) do |spec|
spec.rcov_opts = ['--exclude', 'spec', '--exclude', 'gems']
spec.rcov = true
end
YARD::Rake::YardocTask.new
task :default => :spec
task :fixtures do
require './spec/spec_helper'
BinaryFixtures.build_fixtures
end
riddle-2.3.1/bin/ 0000775 0000000 0000000 00000000000 13255650766 0013547 5 ustar 00root root 0000000 0000000 riddle-2.3.1/bin/loadsphinx 0000775 0000000 0000000 00000001515 13255650766 0015650 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
version=$1
name="sphinx-$version"
url="http://sphinxsearch.com/files/$name-release.tar.gz"
bucket="thinking-sphinx"
directory="ext/sphinx"
prefix="`pwd`/$directory"
file="ext/$name.tar.gz"
download_and_compile_source () {
curl -O $url
tar -zxf $name-release.tar.gz
cd $name-release
./configure --with-mysql --with-pgsql --enable-id64 --prefix=$prefix
make
make install
cd ..
rm -rf $name-release.tar.gz $name-release
}
load_cache () {
mkdir ext
curl -o $file http://$bucket.s3.amazonaws.com/bincaches/$name.tar.gz
tar -zxf $file
}
push_cache () {
tar -czf $file $directory
aws s3 cp $file s3://$bucket/bincaches/$name.tar.gz --acl public-read
}
if curl -i --head --fail http://$bucket.s3.amazonaws.com/bincaches/$name.tar.gz
then
load_cache
else
download_and_compile_source
push_cache
fi
riddle-2.3.1/lib/ 0000775 0000000 0000000 00000000000 13255650766 0013545 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle.rb 0000664 0000000 0000000 00000003161 13255650766 0015336 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'thread'
require 'socket'
require 'stringio'
require 'timeout'
module Riddle #:nodoc:
@@mutex = Mutex.new
@@escape_pattern = /[\(\)\|\-!@~"&\/\?]/
@@use_encoding = defined?(::Encoding) &&
::Encoding.respond_to?(:default_external)
class ConnectionError < StandardError #:nodoc:
#
end
def self.encode(data, encoding = @@use_encoding && ::Encoding.default_external)
if @@use_encoding
data.force_encoding(encoding)
else
data
end
end
def self.mutex
@@mutex
end
def self.escape_pattern
@@escape_pattern
end
def self.escape_pattern=(pattern)
mutex.synchronize do
@@escape_pattern = pattern
end
end
def self.escape(string)
string.gsub(escape_pattern) { |char| "\\#{char}" }
end
def self.loaded_version
@@sphinx_version
end
def self.loaded_version=(version)
@@sphinx_version = version
end
def self.version_warning
return if loaded_version
STDERR.puts %Q{
Riddle cannot detect Sphinx on your machine, and so can't determine which
version of Sphinx you are planning on using. Please use one of the following
lines after "require 'riddle'" to avoid this warning.
require 'riddle/0.9.8'
# or
require 'riddle/0.9.9'
# or
require 'riddle/1.10'
}
end
end
require 'riddle/auto_version'
require 'riddle/client'
require 'riddle/command_failed_error'
require 'riddle/command_result'
require 'riddle/configuration'
require 'riddle/controller'
require 'riddle/execute_command'
require 'riddle/query'
Riddle.loaded_version = nil
Riddle::AutoVersion.configure
riddle-2.3.1/lib/riddle/ 0000775 0000000 0000000 00000000000 13255650766 0015010 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/0.9.8.rb 0000664 0000000 0000000 00000000077 13255650766 0016015 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
Riddle.loaded_version = '0.9.8'
riddle-2.3.1/lib/riddle/0.9.9.rb 0000664 0000000 0000000 00000000344 13255650766 0016013 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
Riddle.loaded_version = '0.9.9'
require 'riddle/0.9.9/client'
require 'riddle/0.9.9/client/filter'
require 'riddle/0.9.9/configuration/searchd'
Riddle.escape_pattern = /[\(\)\|\-!@~"&\/\\\^\$=]/
riddle-2.3.1/lib/riddle/0.9.9/ 0000775 0000000 0000000 00000000000 13255650766 0015465 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/0.9.9/client.rb 0000664 0000000 0000000 00000002352 13255650766 0017272 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
Riddle::Client::Versions[:search] = 0x116
Riddle::Client::Versions[:update] = 0x102
class Riddle::Client
private
def initialise_connection(available_server)
socket = initialise_socket(available_server)
# Send version
socket.send [1].pack('N'), 0
# Checking version
version = socket.recv(4).unpack('N*').first
if version < 1
socket.close
raise Riddle::VersionError, "Can only connect to searchd version 1.0 or better, not version #{version}"
end
socket
end
def update_message(index, attributes, values_by_doc)
message = Message.new
message.append_string index
message.append_int attributes.length
attributes.each_with_index do |attribute, index|
message.append_string attribute
message.append_boolean values_by_doc.values.first[index].is_a?(Array)
end
message.append_int values_by_doc.length
values_by_doc.each do |key,values|
message.append_64bit_int key # document ID
values.each do |value|
case value
when Array
message.append_int value.length
message.append_ints *value
else
message.append_int value
end
end
end
message.to_s
end
end
riddle-2.3.1/lib/riddle/0.9.9/client/ 0000775 0000000 0000000 00000000000 13255650766 0016743 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/0.9.9/client/filter.rb 0000664 0000000 0000000 00000000635 13255650766 0020561 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::Client::Filter
#
private
def append_integer_range(message, range)
message.append_64bit_ints self.values.first, self.values.last
end
def append_array(message, array)
message.append_64bit_ints *array.collect { |val|
case val
when TrueClass
1
when FalseClass
0
else
val
end
}
end
end
riddle-2.3.1/lib/riddle/0.9.9/configuration/ 0000775 0000000 0000000 00000000000 13255650766 0020334 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/0.9.9/configuration/searchd.rb 0000664 0000000 0000000 00000001574 13255650766 0022301 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class Searchd
NUMBER = 1.class
def valid?
set_listen
!( @listen.nil? || @listen.empty? || @pid_file.nil? )
end
private
def set_listen
@listen = @listen.to_s if @listen.is_a?(NUMBER)
return unless @listen.nil? || @listen.empty?
@listen = []
@listen << @port.to_s if @port
@listen << "9306:mysql41" if @mysql41.is_a?(TrueClass)
@listen << "#{@mysql41}:mysql41" if @mysql41.is_a?(NUMBER)
if @listen.empty? && @address
@listen << @address
else
@listen = @listen.collect { |line| "#{@address}:#{line}" } if @address
end
@listen += Array(@socket) if @socket
end
def settings
@listen.nil? ? super : super - [:address, :port]
end
end
end
end
riddle-2.3.1/lib/riddle/1.10.rb 0000664 0000000 0000000 00000000163 13255650766 0015714 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'riddle/0.9.9'
Riddle.loaded_version = '1.10'
require 'riddle/1.10/client' riddle-2.3.1/lib/riddle/1.10/ 0000775 0000000 0000000 00000000000 13255650766 0015367 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/1.10/client.rb 0000664 0000000 0000000 00000001775 13255650766 0017204 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
Riddle::Client::Versions[:search] = 0x117
Riddle::Client::Versions[:excerpt] = 0x102
class Riddle::Client
private
# Generation of the message to send to Sphinx for an excerpts request.
def excerpts_message(options)
message = Message.new
message.append [0, excerpt_flags(options)].pack('N2') # 0 = mode
message.append_string options[:index]
message.append_string options[:words]
# options
message.append_string options[:before_match]
message.append_string options[:after_match]
message.append_string options[:chunk_separator]
message.append_ints options[:limit], options[:around]
message.append_ints options[:limit_passages], options[:limit_words]
message.append_ints options[:start_passage_id]
message.append_string options[:html_strip_mode]
if Versions[:excerpt] >= 0x103
message.append_string options[:passage_boundary]
end
message.append_array options[:docs]
message.to_s
end
end riddle-2.3.1/lib/riddle/2.0.1.rb 0000664 0000000 0000000 00000000214 13255650766 0015770 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'riddle/0.9.9'
require 'riddle/1.10'
Riddle.loaded_version = '2.0.1'
require 'riddle/2.0.1/client'
riddle-2.3.1/lib/riddle/2.0.1/ 0000775 0000000 0000000 00000000000 13255650766 0015446 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/2.0.1/client.rb 0000664 0000000 0000000 00000000164 13255650766 0017252 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
Riddle::Client::Versions[:search] = 0x118
Riddle::Client::Versions[:excerpt] = 0x103 riddle-2.3.1/lib/riddle/2.1.0.rb 0000664 0000000 0000000 00000000775 13255650766 0016004 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'riddle/0.9.9'
require 'riddle/1.10'
require 'riddle/2.0.1'
Riddle.loaded_version = '2.1.0'
Riddle::Client::Versions[:search] = 0x119
Riddle::Client::Versions[:excerpt] = 0x104
Riddle::Client::RankModes[:expr] = 8
Riddle::Client::RankModes[:total] = 9
Riddle::Client::AttributeTypes[:multi] = 0x40000001
Riddle::Client::AttributeTypes[:multi_64] = 0x40000002
Riddle::Client::AttributeHandlers[Riddle::Client::AttributeTypes[:multi_64]] = :next_64bit_int_array
riddle-2.3.1/lib/riddle/auto_version.rb 0000664 0000000 0000000 00000000645 13255650766 0020057 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::AutoVersion
def self.configure
controller = Riddle::Controller.new nil, ''
version = ENV['SPHINX_VERSION'] || controller.sphinx_version
case version
when '0.9.8', '0.9.9'
require "riddle/#{version}"
when /1.10/
require 'riddle/1.10'
when /2.0.[12]/
require 'riddle/2.0.1'
else
require 'riddle/2.1.0'
end
end
end
riddle-2.3.1/lib/riddle/client.rb 0000664 0000000 0000000 00000066524 13255650766 0016630 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'riddle/client/filter'
require 'riddle/client/message'
require 'riddle/client/response'
module Riddle
class VersionError < StandardError; end
class ResponseError < StandardError
attr_accessor :original
end
class OutOfBoundsError < StandardError; end
# This class was heavily based on the existing Client API by Dmytro Shteflyuk
# and Alexy Kovyrin. Their code worked fine, I just wanted something a bit
# more Ruby-ish (ie. lowercase and underscored method names). I also have
# used a few helper classes, just to neaten things up.
#
# Feel free to use it wherever. Send bug reports, patches, comments and
# suggestions to pat at freelancing-gods dot com.
#
# Most properties of the client are accessible through attribute accessors,
# and where relevant use symboles instead of the long constants common in
# other clients.
# Some examples:
#
# client.sort_mode = :extended
# client.sort_by = "birthday DESC"
# client.match_mode = :extended
#
# To add a filter, you will need to create a Filter object:
#
# client.filters << Riddle::Client::Filter.new("birthday",
# Time.at(1975, 1, 1).to_i..Time.at(1985, 1, 1).to_i, false)
#
class Client
Commands = {
:search => 0, # SEARCHD_COMMAND_SEARCH
:excerpt => 1, # SEARCHD_COMMAND_EXCERPT
:update => 2, # SEARCHD_COMMAND_UPDATE
:keywords => 3, # SEARCHD_COMMAND_KEYWORDS
:persist => 4, # SEARCHD_COMMAND_PERSIST
:status => 5, # SEARCHD_COMMAND_STATUS
:query => 6, # SEARCHD_COMMAND_QUERY
:flushattrs => 7 # SEARCHD_COMMAND_FLUSHATTRS
}
Versions = {
:search => 0x113, # VER_COMMAND_SEARCH
:excerpt => 0x100, # VER_COMMAND_EXCERPT
:update => 0x101, # VER_COMMAND_UPDATE
:keywords => 0x100, # VER_COMMAND_KEYWORDS
:status => 0x100, # VER_COMMAND_STATUS
:query => 0x100, # VER_COMMAND_QUERY
:flushattrs => 0x100 # VER_COMMAND_FLUSHATTRS
}
Statuses = {
:ok => 0, # SEARCHD_OK
:error => 1, # SEARCHD_ERROR
:retry => 2, # SEARCHD_RETRY
:warning => 3 # SEARCHD_WARNING
}
MatchModes = {
:all => 0, # SPH_MATCH_ALL
:any => 1, # SPH_MATCH_ANY
:phrase => 2, # SPH_MATCH_PHRASE
:boolean => 3, # SPH_MATCH_BOOLEAN
:extended => 4, # SPH_MATCH_EXTENDED
:fullscan => 5, # SPH_MATCH_FULLSCAN
:extended2 => 6 # SPH_MATCH_EXTENDED2
}
RankModes = {
:proximity_bm25 => 0, # SPH_RANK_PROXIMITY_BM25
:bm25 => 1, # SPH_RANK_BM25
:none => 2, # SPH_RANK_NONE
:wordcount => 3, # SPH_RANK_WORDCOUNT
:proximity => 4, # SPH_RANK_PROXIMITY
:match_any => 5, # SPH_RANK_MATCHANY
:fieldmask => 6, # SPH_RANK_FIELDMASK
:sph04 => 7, # SPH_RANK_SPH04
:total => 8 # SPH_RANK_TOTAL
}
SortModes = {
:relevance => 0, # SPH_SORT_RELEVANCE
:attr_desc => 1, # SPH_SORT_ATTR_DESC
:attr_asc => 2, # SPH_SORT_ATTR_ASC
:time_segments => 3, # SPH_SORT_TIME_SEGMENTS
:extended => 4, # SPH_SORT_EXTENDED
:expr => 5 # SPH_SORT_EXPR
}
AttributeTypes = {
:integer => 1, # SPH_ATTR_INTEGER
:timestamp => 2, # SPH_ATTR_TIMESTAMP
:ordinal => 3, # SPH_ATTR_ORDINAL
:bool => 4, # SPH_ATTR_BOOL
:float => 5, # SPH_ATTR_FLOAT
:bigint => 6, # SPH_ATTR_BIGINT
:string => 7, # SPH_ATTR_STRING
:group_concat => 10,
:multi => 0x40000000 # SPH_ATTR_MULTI
}
GroupFunctions = {
:day => 0, # SPH_GROUPBY_DAY
:week => 1, # SPH_GROUPBY_WEEK
:month => 2, # SPH_GROUPBY_MONTH
:year => 3, # SPH_GROUPBY_YEAR
:attr => 4, # SPH_GROUPBY_ATTR
:attrpair => 5 # SPH_GROUPBY_ATTRPAIR
}
FilterTypes = {
:values => 0, # SPH_FILTER_VALUES
:range => 1, # SPH_FILTER_RANGE
:float_range => 2 # SPH_FILTER_FLOATRANGE
}
attr_accessor :servers, :port, :offset, :limit, :max_matches,
:match_mode, :sort_mode, :sort_by, :weights, :id_range, :filters,
:group_by, :group_function, :group_clause, :group_distinct, :cut_off,
:retry_count, :retry_delay, :anchor, :index_weights, :rank_mode,
:rank_expr, :max_query_time, :field_weights, :timeout, :overrides,
:select, :connection, :key
attr_reader :queue
@@connection = nil
def self.connection=(value)
Riddle.mutex.synchronize do
@@connection = value
end
end
def self.connection
@@connection
end
# Can instantiate with a specific server and port - otherwise it assumes
# defaults of localhost and 9312 respectively. All other settings can be
# accessed and changed via the attribute accessors.
def initialize(servers = nil, port = nil, key = nil)
Riddle.version_warning
@servers = Array(servers || "localhost")
@port = port || 9312
@socket = nil
@key = key
reset
@queue = []
end
# Reset attributes and settings to defaults.
def reset
# defaults
@offset = 0
@limit = 20
@max_matches = 1000
@match_mode = :all
@sort_mode = :relevance
@sort_by = ''
@weights = []
@id_range = 0..0
@filters = []
@group_by = ''
@group_function = :day
@group_clause = '@weight DESC'
@group_distinct = ''
@cut_off = 0
@retry_count = 0
@retry_delay = 0
@anchor = {}
# string keys are index names, integer values are weightings
@index_weights = {}
@rank_mode = :proximity_bm25
@rank_expr = ''
@max_query_time = 0
# string keys are field names, integer values are weightings
@field_weights = {}
@timeout = 0
@overrides = {}
@select = "*"
end
# The searchd server to query. Servers are removed from @server after a
# Timeout::Error is hit to allow for fail-over.
def server
@servers.first
end
# Backwards compatible writer to the @servers array.
def server=(server)
@servers = server.to_a
end
# Set the geo-anchor point - with the names of the attributes that contain
# the latitude and longitude (in radians), and the reference position.
# Note that for geocoding to work properly, you must also set
# match_mode to :extended. To sort results by distance, you will
# need to set sort_by to '@geodist asc', and sort_mode to extended (as an
# example). Sphinx expects latitude and longitude to be returned from you
# SQL source in radians.
#
# Example:
# client.set_anchor('lat', -0.6591741, 'long', 2.530770)
#
def set_anchor(lat_attr, lat, long_attr, long)
@anchor = {
:latitude_attribute => lat_attr,
:latitude => lat,
:longitude_attribute => long_attr,
:longitude => long
}
end
# Append a query to the queue. This uses the same parameters as the query
# method.
def append_query(search, index = '*', comments = '')
@queue << query_message(search, index, comments)
end
# Run all the queries currently in the queue. This will return an array of
# results hashes.
def run
response = Response.new request(:search, @queue)
results = @queue.collect do
result = {
:matches => [],
:fields => [],
:attributes => {},
:attribute_names => [],
:words => {}
}
result[:status] = response.next_int
case result[:status]
when Statuses[:warning]
result[:warning] = response.next
when Statuses[:error]
result[:error] = response.next
next result
end
result[:fields] = response.next_array
attributes = response.next_int
attributes.times do
attribute_name = response.next
type = response.next_int
result[:attributes][attribute_name] = type
result[:attribute_names] << attribute_name
end
result_attribute_names_and_types = result[:attribute_names].
inject([]) { |array, attr| array.push([ attr, result[:attributes][attr] ]) }
matches = response.next_int
is_64_bit = response.next_int
result[:matches] = (0...matches).map do |i|
doc = is_64_bit > 0 ? response.next_64bit_int : response.next_int
weight = response.next_int
current_match_attributes = {}
result_attribute_names_and_types.each do |attr, type|
current_match_attributes[attr] = attribute_from_type(type, response)
end
{:doc => doc, :weight => weight, :index => i, :attributes => current_match_attributes}
end
result[:total] = response.next_int.to_i || 0
result[:total_found] = response.next_int.to_i || 0
result[:time] = ('%.3f' % (response.next_int / 1000.0)).to_f || 0.0
words = response.next_int
words.times do
word = response.next
docs = response.next_int
hits = response.next_int
result[:words][word] = {:docs => docs, :hits => hits}
end
result
end
@queue.clear
results
rescue Riddle::OutOfBoundsError => error
raise error
rescue => original
error = ResponseError.new original.message
error.original = original
raise error
end
# Query the Sphinx daemon - defaulting to all indices, but you can specify
# a specific one if you wish. The search parameter should be a string
# following Sphinx's expectations.
#
# The object returned from this method is a hash with the following keys:
#
# * :matches
# * :fields
# * :attributes
# * :attribute_names
# * :words
# * :total
# * :total_found
# * :time
# * :status
# * :warning (if appropriate)
# * :error (if appropriate)
#
# The key :matches returns an array of hashes - the actual search
# results. Each hash has the document id (:doc), the result
# weighting (:weight), and a hash of the attributes for the
# document (:attributes).
#
# The :fields and :attribute_names keys return list of
# fields and attributes for the documents. The key :attributes
# will return a hash of attribute name and type pairs, and :words
# returns a hash of hashes representing the words from the search, with the
# number of documents and hits for each, along the lines of:
#
# results[:words]["Pat"] #=> {:docs => 12, :hits => 15}
#
# :total, :total_found and :time return the
# number of matches available, the total number of matches (which may be
# greater than the maximum available, depending on the number of matches
# and your sphinx configuration), and the time in milliseconds that the
# query took to run.
#
# :status is the error code for the query - and if there was a
# related warning, it will be under the :warning key. Fatal errors
# will be described under :error.
#
def query(search, index = '*', comments = '')
@queue.clear
@queue << query_message(search, index, comments)
self.run.first
end
# Build excerpts from search terms (the +words+) and the text of documents. Excerpts are bodies of text that have the +words+ highlighted.
# They may also be abbreviated to fit within a word limit.
#
# As part of the options hash, you will need to
# define:
# * :docs
# * :words
# * :index
#
# Optional settings include:
# * :before_match (defaults to )
# * :after_match (defaults to )
# * :chunk_separator (defaults to ' … ' - which is an HTML ellipsis)
# * :limit (defaults to 256)
# * :around (defaults to 5)
# * :exact_phrase (defaults to false)
# * :single_passage (defaults to false)
#
# The defaults differ from the official PHP client, as I've opted for
# semantic HTML markup.
#
# Example:
#
# client.excerpts(:docs => ["Pat Allan, Pat Cash"], :words => 'Pat', :index => 'pats')
# #=> ["Pat Allan, Pat Cash"]
#
# lorem_lipsum = "Lorem ipsum dolor..."
#
# client.excerpts(:docs => ["Pat Allan, #{lorem_lipsum} Pat Cash"], :words => 'Pat', :index => 'pats')
# #=> ["Pat Allan, Lorem ipsum dolor sit amet, consectetur adipisicing
# elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua … . Excepteur
# sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
# laborum. Pat Cash"]
#
# Workflow:
#
# Excerpt creation is completely isolated from searching the index. The nominated index is only used to
# discover encoding and charset information.
#
# Therefore, the workflow goes:
#
# 1. Do the sphinx query.
# 2. Fetch the documents found by sphinx from their repositories.
# 3. Pass the documents' text to +excerpts+ for marking up of matched terms.
#
def excerpts(options = {})
options[:index] ||= '*'
options[:before_match] ||= ''
options[:after_match] ||= ''
options[:chunk_separator] ||= ' … ' # ellipsis
options[:limit] ||= 256
options[:limit_passages] ||= 0
options[:limit_words] ||= 0
options[:around] ||= 5
options[:exact_phrase] ||= false
options[:single_passage] ||= false
options[:query_mode] ||= false
options[:force_all_words] ||= false
options[:start_passage_id] ||= 1
options[:load_files] ||= false
options[:html_strip_mode] ||= 'index'
options[:allow_empty] ||= false
options[:passage_boundary] ||= 'none'
options[:emit_zones] ||= false
options[:load_files_scattered] ||= false
response = Response.new request(:excerpt, excerpts_message(options))
options[:docs].collect { response.next }
end
# Update attributes - first parameter is the relevant index, second is an
# array of attributes to be updated, and the third is a hash, where the
# keys are the document ids, and the values are arrays with the attribute
# values - in the same order as the second parameter.
#
# Example:
#
# client.update('people', ['birthday'], {1 => [Time.at(1982, 20, 8).to_i]})
#
def update(index, attributes, values_by_doc)
response = Response.new request(
:update,
update_message(index, attributes, values_by_doc)
)
response.next_int
end
# Generates a keyword list for a given query. Each keyword is represented
# by a hash, with keys :tokenised and :normalised. If return_hits is set to
# true it will also report on the number of hits and documents for each
# keyword (see :hits and :docs keys respectively).
def keywords(query, index, return_hits = false)
response = Response.new request(
:keywords,
keywords_message(query, index, return_hits)
)
(0...response.next_int).collect do
hash = {}
hash[:tokenised] = response.next
hash[:normalised] = response.next
if return_hits
hash[:docs] = response.next_int
hash[:hits] = response.next_int
end
hash
end
end
def status
response = Response.new request(
:status, Message.new
)
rows, cols = response.next_int, response.next_int
(0...rows).inject({}) do |hash, row|
hash[response.next.to_sym] = response.next
hash
end
end
def flush_attributes
response = Response.new request(
:flushattrs, Message.new
)
response.next_int
end
def add_override(attribute, type, values)
@overrides[attribute] = {:type => type, :values => values}
end
def open
open_socket
return if Versions[:search] < 0x116
@socket.send request_header(:persist) + [1].pack('N'), 0
end
def close
close_socket
end
private
def open_socket
raise "Already Connected" unless @socket.nil?
available_servers = servers.dup
if @timeout == 0
@socket = initialise_connection(available_servers.first)
else
begin
Timeout.timeout(@timeout) { @socket = initialise_connection(available_servers.first) }
rescue Timeout::Error, Riddle::ConnectionError => e
failed_servers ||= []
failed_servers << available_servers.shift
retry if !available_servers.empty?
case e
when Timeout::Error
raise Riddle::ConnectionError,
"Connection to #{failed_servers.inspect} on #{@port} timed out after #{@timeout} seconds"
else
raise e
end
end
end
true
end
def close_socket
raise "Not Connected" if @socket.nil?
@socket.close
@socket = nil
true
end
# If there's an active connection to the Sphinx daemon, this will yield the
# socket. If there's no active connection, then it will connect, yield the
# new socket, then close it.
def connect(&block)
if @socket.nil? || @socket.closed?
@socket = nil
open_socket
begin
yield @socket
ensure
close_socket
end
else
yield @socket
end
end
def initialise_connection(available_server)
socket = initialise_socket(available_server)
# Checking version
version = socket.recv(4).unpack('N*').first
if version < 1
socket.close
raise VersionError, "Can only connect to searchd version 1.0 or better, not version #{version}"
end
# Send version
socket.send [1].pack('N'), 0
socket
end
def initialise_socket(available_server)
tries = 0
begin
socket = if self.connection
self.connection.call(self)
elsif self.class.connection
self.class.connection.call(self)
elsif available_server && available_server.index('/') == 0
UNIXSocket.new available_server
elsif available_server
TCPSocket.new available_server, @port
else
raise "Server not set."
end
rescue Errno::ETIMEDOUT, Errno::ECONNRESET, Errno::ECONNREFUSED => e
retry if (tries += 1) < 5
raise Riddle::ConnectionError,
"Connection to #{available_server} on #{@port} failed. #{e.message}"
end
socket
end
def request_header(command, length = 0)
length += key_message.length if key
core_header = case command
when :search
# Message length is +4/+8 to account for the following count value for
# the number of messages.
if Versions[command] >= 0x118
[Commands[command], Versions[command], 8 + length].pack("nnN")
else
[Commands[command], Versions[command], 4 + length].pack("nnN")
end
when :status
[Commands[command], Versions[command], 4, 1].pack("nnNN")
when :persist
[Commands[command], 0, 4 + length].pack("nnN")
else
[Commands[command], Versions[command], length].pack("nnN")
end
key ? core_header + key_message : core_header
end
def key_message
@key_message ||= begin
message = Message.new
message.append_string key
message.to_s
end
end
# Send a collection of messages, for a command type (eg, search, excerpts,
# update), to the Sphinx daemon.
def request(command, messages)
response = StringIO.new String.new(""), "w"
response.set_encoding "ASCII-8BIT"
status = -1
version = 0
length = 0
message = Riddle.encode(Array(messages).join(""), 'ASCII-8BIT')
connect do |socket|
case command
when :search
if Versions[command] >= 0x118
socket.send request_header(command, message.length) +
[0, messages.length].pack('NN') + message, 0
else
socket.send request_header(command, message.length) +
[messages.length].pack('N') + message, 0
end
when :status
socket.send request_header(command, message.length), 0
else
socket.send request_header(command, message.length) + message, 0
end
header = socket.recv(8)
status, version, length = header.unpack('n2N')
while response.length < (length || 0)
part = socket.recv(length - response.length)
# will return 0 bytes if remote side closed TCP connection, e.g, searchd segfaulted.
break if part.length == 0 && socket.is_a?(TCPSocket)
response << part if part
end
end
response = response.string
if response.empty? || response.length != length
raise ResponseError, "No response from searchd (status: #{status}, version: #{version})"
end
case status
when Statuses[:ok]
if version < Versions[command]
puts format("searchd command v.%d.%d older than client (v.%d.%d)",
version >> 8, version & 0xff,
Versions[command] >> 8, Versions[command] & 0xff)
end
response
when Statuses[:warning]
length = response[0, 4].unpack('N*').first
puts response[4, length]
response[4 + length, response.length - 4 - length]
when Statuses[:error], Statuses[:retry]
message = response[4, response.length - 4]
klass = message[/out of bounds/] ? OutOfBoundsError : ResponseError
raise klass, "searchd error (status: #{status}): #{message}"
else
raise ResponseError, "Unknown searchd error (status: #{status})"
end
end
# Generation of the message to send to Sphinx for a search.
def query_message(search, index, comments = '')
message = Message.new
# Mode, Limits
message.append_ints @offset, @limit, MatchModes[@match_mode]
# Ranking
message.append_int RankModes[@rank_mode]
message.append_string @rank_expr if @rank_mode == :expr
# Sort Mode
message.append_int SortModes[@sort_mode]
message.append_string @sort_by
# Query
message.append_string search
# Weights
message.append_int @weights.length
message.append_ints *@weights
# Index
message.append_string index
# ID Range
message.append_int 1
message.append_64bit_ints @id_range.first, @id_range.last
# Filters
message.append_int @filters.length
@filters.each { |filter| message.append filter.query_message }
# Grouping
message.append_int GroupFunctions[@group_function]
message.append_string @group_by
message.append_int @max_matches
message.append_string @group_clause
message.append_ints @cut_off, @retry_count, @retry_delay
message.append_string @group_distinct
# Anchor Point
if @anchor.empty?
message.append_int 0
else
message.append_int 1
message.append_string @anchor[:latitude_attribute]
message.append_string @anchor[:longitude_attribute]
message.append_floats @anchor[:latitude], @anchor[:longitude]
end
# Per Index Weights
message.append_int @index_weights.length
@index_weights.each do |key,val|
message.append_string key.to_s
message.append_int val
end
# Max Query Time
message.append_int @max_query_time
# Per Field Weights
message.append_int @field_weights.length
@field_weights.each do |key,val|
message.append_string key.to_s
message.append_int val
end
message.append_string comments
return message.to_s if Versions[:search] < 0x116
# Overrides
message.append_int @overrides.length
@overrides.each do |key,val|
message.append_string key.to_s
message.append_int AttributeTypes[val[:type]]
message.append_int val[:values].length
val[:values].each do |id,map|
message.append_64bit_int id
method = case val[:type]
when :float
:append_float
when :bigint
:append_64bit_int
else
:append_int
end
message.send method, map
end
end
message.append_string @select
message.to_s
end
# Generation of the message to send to Sphinx for an excerpts request.
def excerpts_message(options)
message = Message.new
message.append [0, excerpt_flags(options)].pack('N2') # 0 = mode
message.append_string options[:index]
message.append_string options[:words]
# options
message.append_string options[:before_match]
message.append_string options[:after_match]
message.append_string options[:chunk_separator]
message.append_ints options[:limit], options[:around]
message.append_array options[:docs]
message.to_s
end
# Generation of the message to send to Sphinx to update attributes of a
# document.
def update_message(index, attributes, values_by_doc)
message = Message.new
message.append_string index
message.append_array attributes
message.append_int values_by_doc.length
values_by_doc.each do |key,values|
message.append_64bit_int key # document ID
message.append_ints *values # array of new values (integers)
end
message.to_s
end
# Generates the simple message to send to the daemon for a keywords request.
def keywords_message(query, index, return_hits)
message = Message.new
message.append_string query
message.append_string index
message.append_int return_hits ? 1 : 0
message.to_s
end
AttributeHandlers = {
AttributeTypes[:integer] => :next_int,
AttributeTypes[:timestamp] => :next_int,
AttributeTypes[:ordinal] => :next_int,
AttributeTypes[:bool] => :next_int,
AttributeTypes[:float] => :next_float,
AttributeTypes[:bigint] => :next_64bit_int,
AttributeTypes[:string] => :next,
AttributeTypes[:group_concat] => :next,
AttributeTypes[:multi] + AttributeTypes[:integer] => :next_int_array
}
def attribute_from_type(type, response)
handler = AttributeHandlers[type]
response.send handler
end
def excerpt_flags(options)
flags = 1
flags |= 2 if options[:exact_phrase]
flags |= 4 if options[:single_passage]
flags |= 8 if options[:use_boundaries]
flags |= 16 if options[:weight_order]
flags |= 32 if options[:query_mode]
flags |= 64 if options[:force_all_words]
flags |= 128 if options[:load_files]
flags |= 256 if options[:allow_empty]
flags |= 512 if options[:emit_zones]
flags |= 1024 if options[:load_files_scattered]
flags
end
end
end
riddle-2.3.1/lib/riddle/client/ 0000775 0000000 0000000 00000000000 13255650766 0016266 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/client/filter.rb 0000664 0000000 0000000 00000003726 13255650766 0020110 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Client
class Filter
attr_accessor :attribute, :values, :exclude
# Attribute name, values (which can be an array or a range), and whether
# the filter should be exclusive.
def initialize(attribute, values, exclude=false)
@attribute, @values, @exclude = attribute, values, exclude
end
def exclude?
self.exclude
end
# Returns the message for this filter to send to the Sphinx service
def query_message
message = Message.new
message.append_string self.attribute.to_s
case self.values
when Range
if self.values.first.is_a?(Float) && self.values.last.is_a?(Float)
message.append_int FilterTypes[:float_range]
message.append_floats self.values.first, self.values.last
else
message.append_int FilterTypes[:range]
append_integer_range message, self.values
end
when Array
if self.values.first.is_a?(Float) && self.values.length == 1
message.append_int FilterTypes[:float_range]
message.append_floats self.values.first, self.values.first
else
message.append_int FilterTypes[:values]
message.append_int self.values.length
append_array message, self.values
end
end
message.append_int self.exclude? ? 1 : 0
message.to_s
end
private
def append_integer_range(message, range)
message.append_ints self.values.first, self.values.last
end
# Using to_f is a hack from the PHP client - to workaround 32bit signed
# ints on x32 platforms
def append_array(message, array)
message.append_ints *array.collect { |val|
case val
when TrueClass
1.0
when FalseClass
0.0
else
val.to_f
end
}
end
end
end
end
riddle-2.3.1/lib/riddle/client/message.rb 0000664 0000000 0000000 00000003523 13255650766 0020242 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Client
# This class takes care of the translation of ints, strings and arrays to
# the format required by the Sphinx service.
class Message
def initialize
@message = StringIO.new String.new(""), "w"
@message.set_encoding 'ASCII-8BIT'
@size_method = @message.respond_to?(:bytesize) ? :bytesize : :length
end
# Append raw data (only use if you know what you're doing)
def append(*args)
args.each { |arg| @message << arg }
end
# Append a string's length, then the string itself
def append_string(str)
string = Riddle.encode(str.dup, 'ASCII-8BIT')
@message << [string.send(@size_method)].pack('N') + string
end
# Append an integer
def append_int(int)
@message << [int.to_i].pack('N')
end
def append_64bit_int(int)
@message << [int.to_i >> 32, int.to_i & 0xFFFFFFFF].pack('NN')
end
# Append a float
def append_float(float)
@message << [float].pack('f').unpack('L*').pack("N")
end
def append_boolean(bool)
append_int(bool ? 1 : 0)
end
# Append multiple integers
def append_ints(*ints)
ints.each { |int| append_int(int) }
end
def append_64bit_ints(*ints)
ints.each { |int| append_64bit_int(int) }
end
# Append multiple floats
def append_floats(*floats)
floats.each { |float| append_float(float) }
end
# Append an array of strings - first appends the length of the array,
# then each item's length and value.
def append_array(array)
append_int(array.length)
array.each { |item| append_string(item) }
end
# Returns the entire message
def to_s
@message.string
end
end
end
end
riddle-2.3.1/lib/riddle/client/response.rb 0000664 0000000 0000000 00000003734 13255650766 0020460 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Client
# Used to interrogate responses from the Sphinx daemon. Keep in mind none
# of the methods here check whether the data they're grabbing are what the
# user expects - it just assumes the user knows what the data stream is
# made up of.
class Response
# Create with the data to interpret
def initialize(str)
@str = str
@marker = 0
end
# Return the next string value in the stream
def next
len = next_int
result = @str[@marker, len]
@marker += len
Riddle.encode(result)
end
# Return the next integer value from the stream
def next_int
int = @str[@marker, 4].unpack('N*').first
@marker += 4
int
end
def next_64bit_int
high, low = @str[@marker, 8].unpack('N*N*')[0..1]
@marker += 8
(high << 32) + low
end
# Return the next float value from the stream
def next_float
float = @str[@marker, 4].unpack('N*').pack('L').unpack('f*').first
@marker += 4
float
end
# Returns an array of string items
def next_array
count = next_int
items = []
count.times do
items << self.next
end
items
end
# Returns an array of int items
def next_int_array
count = next_int
items = []
count.times do
items << self.next_int
end
items
end
def next_float_array
count = next_int
items = []
count.times do
items << self.next_float
end
items
end
def next_64bit_int_array
byte_count = next_int
items = []
(byte_count / 2).times do
items << self.next_64bit_int
end
items
end
# Returns the length of the streamed data
def length
@str.length
end
end
end
end
riddle-2.3.1/lib/riddle/command_failed_error.rb 0000664 0000000 0000000 00000000164 13255650766 0021471 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::CommandFailedError < StandardError
attr_accessor :command_result
end
riddle-2.3.1/lib/riddle/command_result.rb 0000664 0000000 0000000 00000000563 13255650766 0020355 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::CommandResult
attr_reader :command, :status, :output
attr_accessor :successful
def initialize(command, status, output = nil, successful = nil)
@command, @status, @output = command, status, output
if successful.nil?
@successful = (@status == 0)
else
@successful = successful
end
end
end
riddle-2.3.1/lib/riddle/configuration.rb 0000664 0000000 0000000 00000002542 13255650766 0020207 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'riddle/configuration/section'
require 'riddle/configuration/index_settings'
require 'riddle/configuration/common'
require 'riddle/configuration/distributed_index'
require 'riddle/configuration/index'
require 'riddle/configuration/indexer'
require 'riddle/configuration/realtime_index'
require 'riddle/configuration/remote_index'
require 'riddle/configuration/searchd'
require 'riddle/configuration/source'
require 'riddle/configuration/sql_source'
require 'riddle/configuration/template_index'
require 'riddle/configuration/tsv_source'
require 'riddle/configuration/xml_source'
require 'riddle/configuration/parser'
module Riddle
class Configuration
class ConfigurationError < StandardError #:nodoc:
end
attr_reader :common, :indices, :searchd, :sources
attr_accessor :indexer
def self.parse!(input)
Riddle::Configuration::Parser.new(input).parse!
end
def initialize
@common = Riddle::Configuration::Common.new
@indexer = Riddle::Configuration::Indexer.new
@searchd = Riddle::Configuration::Searchd.new
@indices = []
@sources = []
end
def render
(
[@common.render, @indexer.render, @searchd.render] +
@sources.collect { |source| source.render } +
@indices.collect { |index| index.render }
).join("\n")
end
end
end
riddle-2.3.1/lib/riddle/configuration/ 0000775 0000000 0000000 00000000000 13255650766 0017657 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/configuration/common.rb 0000664 0000000 0000000 00000001252 13255650766 0021474 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class Common < Riddle::Configuration::Section
def self.settings
[
:lemmatizer_base, :json_autoconv_numbers, :json_autoconv_keynames,
:on_json_attr_error, :rlp_root, :rlp_environment, :rlp_max_batch_size,
:rlp_max_batch_docs, :plugin_dir
]
end
attr_accessor :common_sphinx_configuration, *settings
def render
return unless common_sphinx_configuration
raise ConfigurationError unless valid?
(
["common", "{"] +
settings_body +
["}", ""]
).join("\n")
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/distributed_index.rb 0000664 0000000 0000000 00000002362 13255650766 0023720 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class DistributedIndex < Riddle::Configuration::Section
def self.settings
[
:type, :local, :agent, :agent_blackhole,
:agent_connect_timeout, :agent_query_timeout
]
end
attr_accessor :name, :local_indices, :remote_indices, :agent_blackhole,
:agent_connect_timeout, :agent_query_timeout
def initialize(name)
@name = name
@local_indices = []
@remote_indices = []
@agent_blackhole = []
end
def type
"distributed"
end
def local
self.local_indices
end
def agent
agents = remote_indices.collect { |index| index.remote }.uniq
agents.collect { |agent|
agent + ":" + remote_indices.select { |index|
index.remote == agent
}.collect { |index| index.name }.join(",")
}
end
def render
raise ConfigurationError unless valid?
(
["index #{name}", "{"] +
settings_body +
["}", ""]
).join("\n")
end
def valid?
@local_indices.length > 0 || @remote_indices.length > 0
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/index.rb 0000664 0000000 0000000 00000002031 13255650766 0021307 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class Index < Riddle::Configuration::Section
include Riddle::Configuration::IndexSettings
def self.settings
Riddle::Configuration::IndexSettings.settings + [:source]
end
attr_accessor :parent, :sources
def initialize(name, *sources)
@name = name
@sources = sources
initialize_settings
end
def source
@sources.collect { |s| s.name }
end
def render
raise ConfigurationError, "#{@name} #{@sources.inspect} #{@path} #{@parent}" unless valid?
inherited_name = "#{name}"
inherited_name << " : #{parent}" if parent
(
@sources.collect { |s| s.render } +
["index #{inherited_name}", "{"] +
settings_body +
["}", ""]
).join("\n")
end
def valid?
(!@name.nil?) && (!( @sources.length == 0 || @path.nil? ) || !@parent.nil?)
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/index_settings.rb 0000664 0000000 0000000 00000011275 13255650766 0023241 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
module IndexSettings
def self.settings
[
:type, :path, :docinfo, :mlock, :morphology,
:dict, :index_sp, :index_zones, :min_stemming_len, :stopwords,
:wordforms, :exceptions, :min_word_len, :charset_dictpath,
:charset_type, :charset_table, :ignore_chars, :min_prefix_len,
:min_infix_len, :prefix_fields, :infix_fields, :enable_star,
:expand_keywords, :ngram_len, :ngram_chars, :phrase_boundary,
:phrase_boundary_step, :blend_chars, :blend_mode, :html_strip,
:html_index_attrs, :html_remove_elements, :preopen, :ondisk_dict,
:inplace_enable, :inplace_hit_gap, :inplace_docinfo_gap,
:inplace_reloc_factor, :inplace_write_factor, :index_exact_words,
:overshort_step, :stopwords_step, :hitless_words, :ha_strategy,
:bigram_freq_words, :bigram_index, :index_field_lengths,
:regexp_filter, :stopwords_unstemmed, :global_idf, :rlp_context,
:ondisk_attrs
]
end
attr_accessor :name, :type, :path, :docinfo, :mlock,
:morphologies, :dict, :index_sp, :index_zones, :min_stemming_len,
:stopword_files, :wordform_files, :exception_files, :min_word_len,
:charset_dictpath, :charset_type, :charset_table, :ignore_characters,
:min_prefix_len, :min_infix_len, :prefix_field_names,
:infix_field_names, :enable_star, :expand_keywords, :ngram_len,
:ngram_characters, :phrase_boundaries, :phrase_boundary_step,
:blend_chars, :blend_mode, :html_strip, :html_index_attrs,
:html_remove_element_tags, :preopen, :ondisk_dict, :inplace_enable,
:inplace_hit_gap, :inplace_docinfo_gap, :inplace_reloc_factor,
:inplace_write_factor, :index_exact_words, :overshort_step,
:stopwords_step, :hitless_words, :ha_strategy, :bigram_freq_words,
:bigram_index, :index_field_lengths, :regexp_filter,
:stopwords_unstemmed, :global_idf, :rlp_context, :ondisk_attrs
def initialize_settings
@morphologies = []
@stopword_files = []
@wordform_files = []
@exception_files = []
@ignore_characters = []
@prefix_field_names = []
@infix_field_names = []
@ngram_characters = []
@phrase_boundaries = []
@html_remove_element_tags = []
@regexp_filter = []
end
def morphology
nil_join @morphologies, ", "
end
def morphology=(morphology)
@morphologies = nil_split morphology, /,\s?/
end
def stopwords
nil_join @stopword_files, " "
end
def stopwords=(stopwords)
@stopword_files = nil_split stopwords, ' '
end
def wordforms
nil_join @wordform_files, " "
end
def wordforms=(wordforms)
@wordform_files = nil_split wordforms, ' '
end
def exceptions
nil_join @exception_files, " "
end
def exceptions=(exceptions)
@exception_files = nil_split exceptions, ' '
end
def ignore_chars
nil_join @ignore_characters, ", "
end
def ignore_chars=(ignore_chars)
@ignore_characters = nil_split ignore_chars, /,\s?/
end
def prefix_fields
nil_join @prefix_field_names, ", "
end
def prefix_fields=(fields)
if fields.is_a?(Array)
@prefix_field_names = fields
else
@prefix_field_names = fields.split(/,\s*/)
end
end
def infix_fields
nil_join @infix_field_names, ", "
end
def infix_fields=(fields)
if fields.is_a?(Array)
@infix_field_names = fields
else
@infix_field_names = fields.split(/,\s*/)
end
end
def ngram_chars
nil_join @ngram_characters, ", "
end
def ngram_chars=(ngram_chars)
@ngram_characters = nil_split ngram_chars, /,\s?/
end
def phrase_boundary
nil_join @phrase_boundaries, ", "
end
def phrase_boundary=(phrase_boundary)
@phrase_boundaries = nil_split phrase_boundary, /,\s?/
end
def html_remove_elements
nil_join @html_remove_element_tags, ", "
end
def html_remove_elements=(html_remove_elements)
@html_remove_element_tags = nil_split html_remove_elements, /,\s?/
end
private
def nil_split(string, pattern)
(string || "").split(pattern)
end
def nil_join(array, delimiter)
if array.length == 0
nil
else
array.join(delimiter)
end
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/indexer.rb 0000664 0000000 0000000 00000002027 13255650766 0021643 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class Indexer < Riddle::Configuration::Section
def self.settings
[
:mem_limit, :max_iops, :max_iosize, :max_xmlpipe2_field,
:write_buffer, :max_file_field_buffer, :on_file_field_error,
:lemmatizer_cache
] + shared_settings
end
def self.shared_settings
[
:lemmatizer_base, :json_autoconv_numbers, :json_autoconv_keynames,
:on_json_attr_error, :rlp_root, :rlp_environment, :rlp_max_batch_size,
:rlp_max_batch_docs
]
end
attr_accessor :common_sphinx_configuration, *settings
def render
raise ConfigurationError unless valid?
(
["indexer", "{"] +
settings_body +
["}", ""]
).join("\n")
end
private
def settings
settings = self.class.settings
settings -= self.class.shared_settings if common_sphinx_configuration
settings
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/parser.rb 0000664 0000000 0000000 00000010556 13255650766 0021507 0 ustar 00root root 0000000 0000000 # encoding: UTF-8
# frozen_string_literal: true
require 'stringio'
class Riddle::Configuration::Parser
SOURCE_CLASSES = {
'mysql' => Riddle::Configuration::SQLSource,
'pgsql' => Riddle::Configuration::SQLSource,
'mssql' => Riddle::Configuration::SQLSource,
'xmlpipe' => Riddle::Configuration::XMLSource,
'xmlpipe2' => Riddle::Configuration::XMLSource,
'odbc' => Riddle::Configuration::SQLSource,
'tsvpipe' => Riddle::Configuration::TSVSource
}
INDEX_CLASSES = {
'plain' => Riddle::Configuration::Index,
'distributed' => Riddle::Configuration::DistributedIndex,
'rt' => Riddle::Configuration::RealtimeIndex,
'template' => Riddle::Configuration::TemplateIndex
}
def initialize(input)
@input = input
end
def parse!
set_common
set_indexer
set_searchd
set_sources
set_indices
add_orphan_sources
configuration
end
private
def add_orphan_sources
all_names = sources.keys
attached_names = configuration.indices.collect { |index|
index.respond_to?(:sources) ? index.sources.collect(&:name) : []
}.flatten
(all_names - attached_names).each do |name|
configuration.sources << sources[name]
end
end
def inner
@inner ||= InnerParser.new(@input).parse!
end
def configuration
@configuration ||= Riddle::Configuration.new
end
def sources
@sources ||= {}
end
def each_with_prefix(prefix)
inner.keys.select { |key| key[/^#{prefix}\s+/] }.each do |key|
yield key.gsub(/^#{prefix}\s+/, '').gsub(/\s*\{$/, ''), inner[key]
end
end
def set_common
set_settings configuration.common, inner['common'] || {}
end
def set_indexer
set_settings configuration.indexer, inner['indexer'] || {}
end
def set_searchd
set_settings configuration.searchd, inner['searchd'] || {}
end
def set_sources
each_with_prefix 'source' do |name, settings|
names = name.split(/\s*:\s*/)
types = settings.delete('type')
parent = names.length > 1 ? names.last : nil
types ||= [sources[parent].type] if parent
type = types.first
source = SOURCE_CLASSES[type].new names.first, type
source.parent = parent
set_settings source, settings
sources[source.name] = source
end
end
def set_indices
each_with_prefix 'index' do |name, settings|
names = name.split(/\s*:\s*/)
type = (settings.delete('type') || ['plain']).first
index = INDEX_CLASSES[type].new names.first
index.parent = names.last if names.length > 1
(settings.delete('source') || []).each do |source_name|
index.sources << sources[source_name]
end
set_settings index, settings
configuration.indices << index
end
end
def set_settings(object, hash)
hash.each do |key, values|
values.each do |value|
set_setting object, key, value
end
end
end
def set_setting(object, key, value)
if object.send(key).is_a?(Array)
object.send(key) << value
else
object.send "#{key}=", value
end
end
class InnerParser
SETTING_PATTERN = /^(\w+)\s*=\s*(.*)$/
EndOfFileError = Class.new StandardError
def initialize(input)
@stream = StringIO.new(input.gsub("\\\n", ''))
@sections = {}
end
def parse!
while label = next_line do
@sections[label] = next_settings
end
@sections
rescue EndOfFileError
@sections
end
private
def next_line
line = @stream.gets
raise EndOfFileError if line.nil?
line = line.strip
(line.empty? || line[/^#/]) ? next_line : line
end
def next_settings
settings = Hash.new { |hash, key| hash[key] = [] }
line = ''
while line.empty? || line == '{' do
line = next_line
end
while line != '}' do
begin
match = SETTING_PATTERN.match(line)
unless match.nil?
key, value = *match.captures
settings[key] << value
while value[/\\$/] do
value = next_line
settings[key].last << "\n" << value
end
end
rescue => error
raise error, "Error handling line '#{line}': #{error.message}",
error.backtrace
end
line = next_line
end
settings
end
end
end
riddle-2.3.1/lib/riddle/configuration/realtime_index.rb 0000664 0000000 0000000 00000002634 13255650766 0023202 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class RealtimeIndex < Riddle::Configuration::Section
include Riddle::Configuration::IndexSettings
def self.settings
Riddle::Configuration::IndexSettings.settings + [
:rt_mem_limit, :rt_field, :rt_attr_uint, :rt_attr_bigint,
:rt_attr_float, :rt_attr_timestamp, :rt_attr_string, :rt_attr_multi,
:rt_attr_multi_64, :rt_attr_bool, :rt_attr_json
]
end
attr_accessor :rt_mem_limit, :rt_field, :rt_attr_uint, :rt_attr_bigint,
:rt_attr_float, :rt_attr_timestamp, :rt_attr_string, :rt_attr_multi,
:rt_attr_multi_64, :rt_attr_bool, :rt_attr_json
def initialize(name)
@name = name
@rt_field = []
@rt_attr_uint = []
@rt_attr_bigint = []
@rt_attr_float = []
@rt_attr_timestamp = []
@rt_attr_string = []
@rt_attr_multi = []
@rt_attr_multi_64 = []
@rt_attr_bool = []
@rt_attr_json = []
initialize_settings
end
def type
"rt"
end
def valid?
!(@name.nil? || @path.nil?)
end
def render
raise ConfigurationError unless valid?
(
["index #{name}", "{"] +
settings_body +
["}", ""]
).join("\n")
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/remote_index.rb 0000664 0000000 0000000 00000000535 13255650766 0022671 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class RemoteIndex
attr_accessor :address, :port, :name
def initialize(address, port, name)
@address = address
@port = port
@name = name
end
def remote
"#{address}:#{port}"
end
end
end
end riddle-2.3.1/lib/riddle/configuration/searchd.rb 0000664 0000000 0000000 00000003301 13255650766 0021612 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class Searchd < Riddle::Configuration::Section
def self.settings
[
:listen, :address, :port, :log, :query_log,
:query_log_format, :read_timeout, :client_timeout, :max_children,
:pid_file, :max_matches, :seamless_rotate, :preopen_indexes,
:unlink_old, :attr_flush_period, :ondisk_dict_default,
:max_packet_size, :mva_updates_pool, :crash_log_path, :max_filters,
:max_filter_values, :listen_backlog, :read_buffer, :read_unhinted,
:max_batch_queries, :subtree_docs_cache, :subtree_hits_cache,
:workers, :dist_threads, :binlog_path, :binlog_flush,
:binlog_max_log_size, :snippets_file_prefix, :collation_server,
:collation_libc_locale, :mysql_version_string,
:rt_flush_period, :thread_stack, :expansion_limit,
:compat_sphinxql_magics, :watchdog, :prefork_rotation_throttle,
:sphinxql_state, :ha_ping_interval, :ha_period_karma,
:persistent_connections_limit, :rt_merge_iops, :rt_merge_maxiosize,
:predicted_time_costs, :snippets_file_prefix, :shutdown_timeout,
:ondisk_attrs_default, :query_log_min_msec, :agent_connect_timeout,
:agent_query_timeout, :agent_retry_count, :agenty_retry_delay,
:client_key
]
end
attr_accessor *self.settings
attr_accessor :mysql41, :socket
def render
raise ConfigurationError unless valid?
(
["searchd", "{"] +
settings_body +
["}", ""]
).join("\n")
end
def valid?
!( @port.nil? || @pid_file.nil? )
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/section.rb 0000664 0000000 0000000 00000002277 13255650766 0021660 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class Section
def self.settings
[]
end
def valid?
true
end
private
def settings_body
settings.select { |setting|
!send(setting).nil?
}.collect { |setting|
if send(setting) == ""
conf = " #{setting} = "
else
conf = setting_to_array(setting).collect { |set|
" #{setting} = #{rendered_setting set}"
}
end
conf.length == 0 ? nil : conf
}.flatten.compact
end
def setting_to_array(setting)
value = send(setting)
case value
when Array then value
when TrueClass then [1]
when FalseClass then [0]
else
[value]
end
end
def rendered_setting(setting)
return setting unless setting.is_a?(String)
index = 8100
output = String.new(setting)
while index < output.length
output.insert(index, "\\\n")
index += 8100
end
output
end
def settings
self.class.settings
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/source.rb 0000664 0000000 0000000 00000001020 13255650766 0021475 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class Source < Riddle::Configuration::Section
attr_accessor :name, :parent, :type
def render
raise ConfigurationError unless valid?
inherited_name = "#{name}"
inherited_name += " : #{parent}" if parent
(
["source #{inherited_name}", "{"] +
settings_body +
["}", ""]
).join("\n")
end
def valid?
!( @name.nil? || @type.nil? )
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/sql_source.rb 0000664 0000000 0000000 00000003751 13255650766 0022371 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class SQLSource < Riddle::Configuration::Source
def self.settings
[
:type, :sql_host, :sql_user, :sql_pass, :sql_db,
:sql_port, :sql_sock, :mysql_connect_flags, :mysql_ssl_cert,
:mysql_ssl_key, :mysql_ssl_ca, :odbc_dsn, :sql_query_pre, :sql_query,
:sql_joined_field, :sql_file_field, :sql_query_range,
:sql_range_step, :sql_query_killlist, :sql_attr_uint, :sql_attr_bool,
:sql_attr_bigint, :sql_attr_timestamp, :sql_attr_str2ordinal,
:sql_attr_float, :sql_attr_multi, :sql_attr_string,
:sql_attr_str2wordcount, :sql_attr_json,
:sql_column_buffers, :sql_field_string, :sql_field_str2wordcount,
:sql_query_post, :sql_query_post_index, :sql_ranged_throttle,
:sql_query_info, :mssql_winauth, :mssql_unicode, :unpack_zlib,
:unpack_mysqlcompress, :unpack_mysqlcompress_maxsize
]
end
attr_accessor *self.settings
def initialize(name, type)
@name = name
@type = type
@sql_query_pre = []
@sql_joined_field = []
@sql_file_field = []
@sql_attr_uint = []
@sql_attr_bool = []
@sql_attr_bigint = []
@sql_attr_timestamp = []
@sql_attr_str2ordinal = []
@sql_attr_float = []
@sql_attr_multi = []
@sql_attr_string = []
@sql_attr_str2wordcount = []
@sql_attr_json = []
@sql_field_string = []
@sql_field_str2wordcount = []
@sql_query_post = []
@sql_query_post_index = []
@unpack_zlib = []
@unpack_mysqlcompress = []
end
def valid?
super && (!( @sql_host.nil? || @sql_user.nil? || @sql_db.nil? ||
@sql_query.nil? ) || !@parent.nil?)
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/template_index.rb 0000664 0000000 0000000 00000001407 13255650766 0023210 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class TemplateIndex < Riddle::Configuration::Section
include Riddle::Configuration::IndexSettings
def self.settings
Riddle::Configuration::IndexSettings.settings
end
attr_accessor :parent
def initialize(name)
@name = name
@type = 'template'
initialize_settings
end
def render
raise ConfigurationError, "#{@name} #{@parent}" unless valid?
inherited_name = "#{name}"
inherited_name << " : #{parent}" if parent
(
["index #{inherited_name}", "{"] +
settings_body +
["}", ""]
).join("\n")
end
def valid?
@name
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/tsv_source.rb 0000664 0000000 0000000 00000000700 13255650766 0022375 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class TSVSource < Riddle::Configuration::Source
def self.settings
[:type, :tsvpipe_command, :tsvpipe_attr_field, :tsvpipe_attr_multi]
end
attr_accessor *self.settings
def initialize(name, type = 'tsvpipe')
@name, @type = name, type
end
def valid?
super && (@tsvpipe_command || @parent)
end
end
end
end
riddle-2.3.1/lib/riddle/configuration/xml_source.rb 0000664 0000000 0000000 00000001657 13255650766 0022375 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
class Configuration
class XMLSource < Riddle::Configuration::Source
def self.settings
[
:type, :xmlpipe_command, :xmlpipe_field,
:xmlpipe_attr_uint, :xmlpipe_attr_bool, :xmlpipe_attr_timestamp,
:xmlpipe_attr_str2ordinal, :xmlpipe_attr_float, :xmlpipe_attr_multi,
:xmlpipe_fixup_utf8
]
end
attr_accessor *self.settings
def initialize(name, type)
@name = name
@type = type
@xmlpipe_field = []
@xmlpipe_attr_uint = []
@xmlpipe_attr_bool = []
@xmlpipe_attr_timestamp = []
@xmlpipe_attr_str2ordinal = []
@xmlpipe_attr_float = []
@xmlpipe_attr_multi = []
end
def valid?
super && ( !@xmlpipe_command.nil? || !parent.nil? )
end
end
end
end
riddle-2.3.1/lib/riddle/controller.rb 0000664 0000000 0000000 00000005522 13255650766 0017524 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle
NoConfigurationFileError = Class.new StandardError
class Controller
DEFAULT_MERGE_OPTIONS = {:filters => {}}.freeze
attr_accessor :path, :bin_path, :searchd_binary_name, :indexer_binary_name
def initialize(configuration, path)
@configuration = configuration
@path = path
@bin_path = ''
@searchd_binary_name = 'searchd'
@indexer_binary_name = 'indexer'
end
def sphinx_version
`#{indexer} 2>&1`[/Sphinx (\d+\.\d+(\.\d+|(?:-dev|(\-id64)?\-beta)))/, 1]
rescue
nil
end
def index(*indices)
options = indices.last.is_a?(Hash) ? indices.pop : {}
indices << '--all' if indices.empty?
command = "#{indexer} --config \"#{@path}\" #{indices.join(' ')}"
command = "#{command} --rotate" if running?
Riddle::ExecuteCommand.call command, options[:verbose]
end
def merge(destination, source, options = {})
options = DEFAULT_MERGE_OPTIONS.merge options
command = "#{indexer} --config \"#{@path}\"".dup
command << " --merge #{destination} #{source}"
options[:filters].each do |attribute, value|
value = value..value unless value.is_a?(Range)
command << " --merge-dst-range #{attribute} #{value.min} #{value.max}"
end
command << " --rotate" if running?
Riddle::ExecuteCommand.call command, options[:verbose]
end
def start(options = {})
return if running?
check_for_configuration_file
command = "#{searchd} --pidfile --config \"#{@path}\""
command = "#{command} --nodetach" if options[:nodetach]
exec(command) if options[:nodetach]
# Code does not get here if nodetach is true.
Riddle::ExecuteCommand.call command, options[:verbose]
end
def stop(options = {})
return true unless running?
check_for_configuration_file
stop_flag = 'stopwait'
stop_flag = 'stop' if Riddle.loaded_version.split('.').first == '0'
command = %(#{searchd} --pidfile --config "#{@path}" --#{stop_flag})
result = Riddle::ExecuteCommand.call command, options[:verbose]
result.successful = !running?
result
end
def pid
if File.exists?(configuration.searchd.pid_file)
File.read(configuration.searchd.pid_file)[/\d+/]
else
nil
end
end
def rotate
pid && Process.kill(:HUP, pid.to_i)
end
def running?
!!pid && !!Process.kill(0, pid.to_i)
rescue
false
end
private
attr_reader :configuration
def indexer
"#{bin_path}#{indexer_binary_name}"
end
def searchd
"#{bin_path}#{searchd_binary_name}"
end
def check_for_configuration_file
return if File.exist?(@path)
raise Riddle::NoConfigurationFileError, "'#{@path}' does not exist"
end
end
end
riddle-2.3.1/lib/riddle/execute_command.rb 0000664 0000000 0000000 00000001770 13255650766 0020502 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::ExecuteCommand
WINDOWS = (RUBY_PLATFORM =~ /mswin|mingw/)
def self.call(command, verbose = true)
new(command, verbose).call
end
def initialize(command, verbose)
@command, @verbose = command, verbose
return unless WINDOWS
@command = "start /B #{@command} 1> NUL 2>&1"
@verbose = true
end
def call
result = verbose? ? result_from_system : result_from_backticks
return result if result.status == 0
error = Riddle::CommandFailedError.new "Sphinx command failed to execute"
error.command_result = result
raise error
end
private
attr_reader :command, :verbose
def result_from_backticks
begin
output = `#{command}`
rescue SystemCallError => error
output = error.message
end
Riddle::CommandResult.new command, $?.exitstatus, output
end
def result_from_system
system command
Riddle::CommandResult.new command, $?.exitstatus
end
def verbose?
verbose
end
end
riddle-2.3.1/lib/riddle/query.rb 0000664 0000000 0000000 00000005172 13255650766 0016507 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Riddle::Query
ESCAPE_CHARACTERS = /[\(\)\|\-!@~\/"\/\^\$\\><&=\?]/
# http://sphinxsearch.com/docs/current/extended-syntax.html
ESCAPE_WORDS = /\b(?:MAYBE|NEAR|PARAGRAPH|SENTENCE|ZONE|ZONESPAN)\b/
MYSQL2_ESCAPE = defined?(Mysql2) && defined?(Mysql::Client)
def self.connection(address = '127.0.0.1', port = 9312)
require 'mysql2'
# If you use localhost, MySQL insists on a socket connection, but Sphinx
# requires a TCP connection. Using 127.0.0.1 fixes that.
address = '127.0.0.1' if address == 'localhost'
Mysql2::Client.new(
:host => address,
:port => port
)
end
def self.meta
'SHOW META'
end
def self.warnings
'SHOW WARNINGS'
end
def self.status
'SHOW STATUS'
end
def self.tables
'SHOW TABLES'
end
def self.variables
'SHOW VARIABLES'
end
def self.collation
'SHOW COLLATION'
end
def self.describe(index)
"DESCRIBE #{index}"
end
def self.begin
'BEGIN'
end
def self.commit
'COMMIT'
end
def self.rollback
'ROLLBACK'
end
def self.set(variable, values, global = true)
values = "(#{values.join(', ')})" if values.is_a?(Array)
"SET#{ ' GLOBAL' if global } #{variable} = #{values}"
end
def self.snippets(data, index, query, options = nil)
data, index, query = quote(data), quote(index), quote(query)
options = ', ' + options.keys.collect { |key|
value = translate_value options[key]
value = quote value if value.is_a?(String)
"#{value} AS #{key}"
}.join(', ') unless options.nil?
"CALL SNIPPETS(#{data}, #{index}, #{query}#{options})"
end
def self.create_function(name, type, file)
type = type.to_s.upcase
"CREATE FUNCTION #{name} RETURNS #{type} SONAME #{quote file}"
end
def self.drop_function(name)
"DROP FUNCTION #{name}"
end
def self.update(index, id, values = {})
values = values.keys.collect { |key|
"#{key} = #{translate_value values[key]}"
}.join(', ')
"UPDATE #{index} SET #{values} WHERE id = #{id}"
end
def self.translate_value(value)
case value
when TrueClass
1
when FalseClass
0
else
value
end
end
def self.escape(string)
string.gsub(ESCAPE_CHARACTERS) { |match| "\\#{match}" }
.gsub(ESCAPE_WORDS) { |word| "\\#{word}" }
end
def self.quote(string)
"'#{sql_escape string}'"
end
def self.sql_escape(string)
return Mysql2::Client.escape(string) if MYSQL2_ESCAPE
string.gsub(/['"\\]/) { |character| "\\#{character}" }
end
end
require 'riddle/query/delete'
require 'riddle/query/insert'
require 'riddle/query/select'
riddle-2.3.1/lib/riddle/query/ 0000775 0000000 0000000 00000000000 13255650766 0016155 5 ustar 00root root 0000000 0000000 riddle-2.3.1/lib/riddle/query/delete.rb 0000664 0000000 0000000 00000000503 13255650766 0017742 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::Query::Delete
def initialize(index, *ids)
@index = index
@ids = ids.flatten
end
def to_sql
if @ids.length > 1
"DELETE FROM #{@index} WHERE id IN (#{@ids.join(', ')})"
else
"DELETE FROM #{@index} WHERE id = #{@ids.first}"
end
end
end
riddle-2.3.1/lib/riddle/query/insert.rb 0000664 0000000 0000000 00000002106 13255650766 0020005 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::Query::Insert
attr_reader :columns, :values
def initialize(index, columns = [], values = [])
@index = index
@columns = columns
@values = values.first.is_a?(Array) ? values : [values]
@replace = false
end
def replace!
@replace = true
self
end
def to_sql
"#{command} INTO #{@index} (#{columns_to_s}) VALUES (#{values_to_s})"
end
private
def command
@replace ? 'REPLACE' : 'INSERT'
end
def columns_to_s
columns.collect { |column|
column.to_s == 'id' ? 'id' : "`#{column}`"
}.join(', ')
end
def values_to_s
values.collect { |value_set|
value_set.collect { |value|
translated_value(value)
}.join(', ')
}.join('), (')
end
def translated_value(value)
case value
when String
"'#{value.gsub(/['\\]/, '').gsub(/\s+/, ' ')}'"
when TrueClass, FalseClass
value ? 1 : 0
when Time
value.to_i
when Date
value.to_time.to_i
when Array
"(#{value.join(',')})"
else
value
end
end
end
riddle-2.3.1/lib/riddle/query/select.rb 0000664 0000000 0000000 00000012542 13255650766 0017765 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Riddle::Query::Select
def initialize
@values = []
@indices = []
@matching = nil
@wheres = {}
@where_alls = {}
@where_nots = {}
@where_not_alls = {}
@group_by = nil
@group_best = nil
@having = []
@order_by = nil
@order_within_group_by = nil
@offset = nil
@limit = nil
@options = {}
end
def values(*values)
@values += values
self
end
def prepend_values(*values)
@values.insert 0, *values
self
end
def from(*indices)
@indices += indices
self
end
def matching(match)
@matching = match
self
end
def where(filters = {})
@wheres.merge!(filters)
self
end
def where_all(filters = {})
@where_alls.merge!(filters)
self
end
def where_not(filters = {})
@where_nots.merge!(filters)
self
end
def where_not_all(filters = {})
@where_not_alls.merge!(filters)
self
end
def group_by(attribute)
@group_by = attribute
self
end
def group_best(count)
@group_best = count
self
end
def having(*conditions)
@having += conditions
self
end
def order_by(order)
@order_by = order
self
end
def order_within_group_by(order)
@order_within_group_by = order
self
end
def limit(limit)
@limit = limit
self
end
def offset(offset)
@offset = offset
self
end
def with_options(options = {})
@options.merge! options
self
end
def to_sql
sql = StringIO.new String.new(""), "w"
sql << "SELECT #{ extended_values } FROM #{ @indices.join(', ') }"
sql << " WHERE #{ combined_wheres }" if wheres?
sql << " #{group_prefix} #{escape_columns(@group_by)}" if !@group_by.nil?
unless @order_within_group_by.nil?
sql << " WITHIN GROUP ORDER BY #{escape_columns(@order_within_group_by)}"
end
sql << " HAVING #{@having.join(' AND ')}" unless @having.empty?
sql << " ORDER BY #{escape_columns(@order_by)}" if !@order_by.nil?
sql << " #{limit_clause}" unless @limit.nil? && @offset.nil?
sql << " #{options_clause}" unless @options.empty?
sql.string
end
private
def extended_values
@values.empty? ? '*' : @values.join(', ')
end
def group_prefix
['GROUP', @group_best, 'BY'].compact.join(' ')
end
def wheres?
!(@wheres.empty? && @where_alls.empty? && @where_nots.empty? && @where_not_alls.empty? && @matching.nil?)
end
def combined_wheres
wheres = wheres_to_s
if @matching.nil?
wheres
elsif wheres.empty?
"MATCH(#{Riddle::Query.quote @matching})"
else
"MATCH(#{Riddle::Query.quote @matching}) AND #{wheres}"
end
end
def wheres_to_s
(
@wheres.keys.collect { |key|
filter_comparison_and_value key, @wheres[key]
} +
@where_alls.collect { |key, values|
values.collect { |value|
filter_comparison_and_value key, value
}
} +
@where_nots.keys.collect { |key|
exclusive_filter_comparison_and_value key, @where_nots[key]
} +
@where_not_alls.collect { |key, values|
'(' + values.collect { |value|
exclusive_filter_comparison_and_value key, value
}.join(' OR ') + ')'
}
).flatten.compact.join(' AND ')
end
def filter_comparison_and_value(attribute, value)
case value
when Array
if !value.flatten.empty?
"#{escape_column(attribute)} IN (#{value.collect { |val| filter_value(val) }.join(', ')})"
end
when Range
"#{escape_column(attribute)} BETWEEN #{filter_value(value.first)} AND #{filter_value(value.last)}"
else
"#{escape_column(attribute)} = #{filter_value(value)}"
end
end
def exclusive_filter_comparison_and_value(attribute, value)
case value
when Array
if !value.flatten.empty?
"#{escape_column(attribute)} NOT IN (#{value.collect { |val| filter_value(val) }.join(', ')})"
end
when Range
"#{escape_column(attribute)} < #{filter_value(value.first)} OR #{attribute} > #{filter_value(value.last)}"
else
"#{escape_column(attribute)} <> #{filter_value(value)}"
end
end
def filter_value(value)
case value
when TrueClass
1
when FalseClass
0
when Time
value.to_i
when Date
Time.utc(value.year, value.month, value.day).to_i
when String
"'#{value.gsub("'", "\\'")}'"
else
value
end
end
def limit_clause
if @offset.nil?
"LIMIT #{@limit}"
else
"LIMIT #{@offset}, #{@limit || 20}"
end
end
def options_clause
'OPTION ' + @options.keys.collect { |key|
"#{key}=#{option_value @options[key]}"
}.join(', ')
end
def option_value(value)
case value
when Hash
'(' + value.collect { |key, value| "#{key}=#{value}" }.join(', ') + ')'
else
value
end
end
def escape_column(column)
if column.to_s[/\A[`@]/] || column.to_s[/\A\w+\(/] || column.to_s[/\A\w+[.\[]/]
column
else
column_name, *extra = column.to_s.split(' ')
extra.unshift("`#{column_name}`").compact.join(' ')
end
end
def escape_columns(columns)
columns.to_s.split(/,\s*/).collect { |column|
escape_column(column)
}.join(', ')
end
end
riddle-2.3.1/riddle.gemspec 0000664 0000000 0000000 00000001531 13255650766 0015607 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
# -*- encoding: utf-8 -*-
$:.push File.expand_path('../lib', __FILE__)
Gem::Specification.new do |s|
s.name = 'riddle'
s.version = '2.3.1'
s.platform = Gem::Platform::RUBY
s.authors = ['Pat Allan']
s.email = ['pat@freelancing-gods.com']
s.homepage = 'http://pat.github.io/riddle/'
s.summary = %q{An API for Sphinx, written in and for Ruby.}
s.description = %q{A Ruby API and configuration helper for the Sphinx search service.}
s.license = 'MIT'
s.rubyforge_project = 'riddle'
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
s.require_paths = ['lib']
s.add_development_dependency 'rake', '>= 0.9.2'
s.add_development_dependency 'rspec', '>= 2.5.0'
s.add_development_dependency 'yard', '>= 0.7.2'
end
riddle-2.3.1/spec/ 0000775 0000000 0000000 00000000000 13255650766 0013731 5 ustar 00root root 0000000 0000000 riddle-2.3.1/spec/fixtures/ 0000775 0000000 0000000 00000000000 13255650766 0015602 5 ustar 00root root 0000000 0000000 riddle-2.3.1/spec/fixtures/.gitignore 0000664 0000000 0000000 00000000024 13255650766 0017566 0 ustar 00root root 0000000 0000000 sql/conf.yml
sphinx
riddle-2.3.1/spec/fixtures/data/ 0000775 0000000 0000000 00000000000 13255650766 0016513 5 ustar 00root root 0000000 0000000 riddle-2.3.1/spec/fixtures/data/0.9.9/ 0000775 0000000 0000000 00000000000 13255650766 0017170 5 ustar 00root root 0000000 0000000 riddle-2.3.1/spec/fixtures/data/0.9.9/anchor.bin 0000664 0000000 0000000 00000000254 13255650766 0021135 0 ustar 00root root 0000000 0000000 test * è @weight DESC latitude longitudeA B¾ * riddle-2.3.1/spec/fixtures/data/0.9.9/any.bin 0000664 0000000 0000000 00000000220 13255650766 0020443 0 ustar 00root root 0000000 0000000
test this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/boolean.bin 0000664 0000000 0000000 00000000213 13255650766 0021275 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/comment.bin 0000664 0000000 0000000 00000000225 13255650766 0021323 0 ustar 00root root 0000000 0000000 test * è @weight DESC
commenting * riddle-2.3.1/spec/fixtures/data/0.9.9/distinct.bin 0000664 0000000 0000000 00000000215 13255650766 0021501 0 ustar 00root root 0000000 0000000 test * è @weight DESC id * riddle-2.3.1/spec/fixtures/data/0.9.9/field_weights.bin 0000664 0000000 0000000 00000000227 13255650766 0022500 0 ustar 00root root 0000000 0000000 test * è @weight DESC city e * riddle-2.3.1/spec/fixtures/data/0.9.9/filter.bin 0000664 0000000 0000000 00000000265 13255650766 0021152 0 ustar 00root root 0000000 0000000 test * id
d è è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/filter_array.bin 0000664 0000000 0000000 00000000055 13255650766 0022345 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/0.9.9/filter_array_exclude.bin 0000664 0000000 0000000 00000000055 13255650766 0024056 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/0.9.9/filter_boolean.bin 0000664 0000000 0000000 00000000045 13255650766 0022645 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/0.9.9/filter_floats.bin 0000664 0000000 0000000 00000000031 13255650766 0022511 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/0.9.9/filter_floats_exclude.bin 0000664 0000000 0000000 00000000031 13255650766 0024222 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/0.9.9/filter_range.bin 0000664 0000000 0000000 00000000041 13255650766 0022316 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/0.9.9/filter_range_exclude.bin 0000664 0000000 0000000 00000000041 13255650766 0024027 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/0.9.9/group.bin 0000664 0000000 0000000 00000000203 13255650766 0021011 0 ustar 00root root 0000000 0000000 test * id è id * riddle-2.3.1/spec/fixtures/data/0.9.9/index.bin 0000664 0000000 0000000 00000000221 13255650766 0020764 0 ustar 00root root 0000000 0000000 test edition è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/index_weights.bin 0000664 0000000 0000000 00000000231 13255650766 0022517 0 ustar 00root root 0000000 0000000 test * è @weight DESC people e * riddle-2.3.1/spec/fixtures/data/0.9.9/keywords_with_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0023610 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/0.9.9/keywords_without_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0024340 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/0.9.9/overrides.bin 0000664 0000000 0000000 00000000251 13255650766 0021662 0 ustar 00root root 0000000 0000000 test * è @weight DESC rating A * riddle-2.3.1/spec/fixtures/data/0.9.9/phrase.bin 0000664 0000000 0000000 00000000223 13255650766 0021141 0 ustar 00root root 0000000 0000000
testing this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/rank_mode.bin 0000664 0000000 0000000 00000000213 13255650766 0021615 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/select.bin 0000664 0000000 0000000 00000000223 13255650766 0021136 0 ustar 00root root 0000000 0000000 test * è @weight DESC selecting riddle-2.3.1/spec/fixtures/data/0.9.9/simple.bin 0000664 0000000 0000000 00000000213 13255650766 0021147 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/sort.bin 0000664 0000000 0000000 00000000220 13255650766 0020643 0 ustar 00root root 0000000 0000000 id testing * è @weight DESC * riddle-2.3.1/spec/fixtures/data/0.9.9/update_simple.bin 0000664 0000000 0000000 00000000056 13255650766 0022516 0 ustar 00root root 0000000 0000000 people birthday dìÐ riddle-2.3.1/spec/fixtures/data/0.9.9/weights.bin 0000664 0000000 0000000 00000000223 13255650766 0021331 0 ustar 00root root 0000000 0000000 test d * è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/ 0000775 0000000 0000000 00000000000 13255650766 0017072 5 ustar 00root root 0000000 0000000 riddle-2.3.1/spec/fixtures/data/1.10/anchor.bin 0000664 0000000 0000000 00000000254 13255650766 0021037 0 ustar 00root root 0000000 0000000 test * è @weight DESC latitude longitudeA B¾ * riddle-2.3.1/spec/fixtures/data/1.10/any.bin 0000664 0000000 0000000 00000000220 13255650766 0020345 0 ustar 00root root 0000000 0000000
test this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/boolean.bin 0000664 0000000 0000000 00000000213 13255650766 0021177 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/comment.bin 0000664 0000000 0000000 00000000225 13255650766 0021225 0 ustar 00root root 0000000 0000000 test * è @weight DESC
commenting * riddle-2.3.1/spec/fixtures/data/1.10/distinct.bin 0000664 0000000 0000000 00000000215 13255650766 0021403 0 ustar 00root root 0000000 0000000 test * è @weight DESC id * riddle-2.3.1/spec/fixtures/data/1.10/field_weights.bin 0000664 0000000 0000000 00000000227 13255650766 0022402 0 ustar 00root root 0000000 0000000 test * è @weight DESC city e * riddle-2.3.1/spec/fixtures/data/1.10/filter.bin 0000664 0000000 0000000 00000000265 13255650766 0021054 0 ustar 00root root 0000000 0000000 test * id
d è è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/filter_array.bin 0000664 0000000 0000000 00000000055 13255650766 0022247 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/1.10/filter_array_exclude.bin 0000664 0000000 0000000 00000000055 13255650766 0023760 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/1.10/filter_boolean.bin 0000664 0000000 0000000 00000000045 13255650766 0022547 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/1.10/filter_floats.bin 0000664 0000000 0000000 00000000031 13255650766 0022413 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/1.10/filter_floats_exclude.bin 0000664 0000000 0000000 00000000031 13255650766 0024124 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/1.10/filter_range.bin 0000664 0000000 0000000 00000000041 13255650766 0022220 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/1.10/filter_range_exclude.bin 0000664 0000000 0000000 00000000041 13255650766 0023731 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/1.10/group.bin 0000664 0000000 0000000 00000000203 13255650766 0020713 0 ustar 00root root 0000000 0000000 test * id è id * riddle-2.3.1/spec/fixtures/data/1.10/index.bin 0000664 0000000 0000000 00000000221 13255650766 0020666 0 ustar 00root root 0000000 0000000 test edition è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/index_weights.bin 0000664 0000000 0000000 00000000231 13255650766 0022421 0 ustar 00root root 0000000 0000000 test * è @weight DESC people e * riddle-2.3.1/spec/fixtures/data/1.10/keywords_with_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0023512 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/1.10/keywords_without_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0024242 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/1.10/overrides.bin 0000664 0000000 0000000 00000000251 13255650766 0021564 0 ustar 00root root 0000000 0000000 test * è @weight DESC rating A * riddle-2.3.1/spec/fixtures/data/1.10/phrase.bin 0000664 0000000 0000000 00000000223 13255650766 0021043 0 ustar 00root root 0000000 0000000
testing this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/rank_mode.bin 0000664 0000000 0000000 00000000213 13255650766 0021517 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/select.bin 0000664 0000000 0000000 00000000223 13255650766 0021040 0 ustar 00root root 0000000 0000000 test * è @weight DESC selecting riddle-2.3.1/spec/fixtures/data/1.10/simple.bin 0000664 0000000 0000000 00000000213 13255650766 0021051 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/sort.bin 0000664 0000000 0000000 00000000220 13255650766 0020545 0 ustar 00root root 0000000 0000000 id testing * è @weight DESC * riddle-2.3.1/spec/fixtures/data/1.10/update_simple.bin 0000664 0000000 0000000 00000000056 13255650766 0022420 0 ustar 00root root 0000000 0000000 people birthday dìÐ riddle-2.3.1/spec/fixtures/data/1.10/weights.bin 0000664 0000000 0000000 00000000223 13255650766 0021233 0 ustar 00root root 0000000 0000000 test d * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/ 0000775 0000000 0000000 00000000000 13255650766 0017151 5 ustar 00root root 0000000 0000000 riddle-2.3.1/spec/fixtures/data/2.0.1/anchor.bin 0000664 0000000 0000000 00000000254 13255650766 0021116 0 ustar 00root root 0000000 0000000 test * è @weight DESC latitude longitudeA B¾ * riddle-2.3.1/spec/fixtures/data/2.0.1/any.bin 0000664 0000000 0000000 00000000220 13255650766 0020424 0 ustar 00root root 0000000 0000000
test this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/boolean.bin 0000664 0000000 0000000 00000000213 13255650766 0021256 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/comment.bin 0000664 0000000 0000000 00000000225 13255650766 0021304 0 ustar 00root root 0000000 0000000 test * è @weight DESC
commenting * riddle-2.3.1/spec/fixtures/data/2.0.1/distinct.bin 0000664 0000000 0000000 00000000215 13255650766 0021462 0 ustar 00root root 0000000 0000000 test * è @weight DESC id * riddle-2.3.1/spec/fixtures/data/2.0.1/field_weights.bin 0000664 0000000 0000000 00000000227 13255650766 0022461 0 ustar 00root root 0000000 0000000 test * è @weight DESC city e * riddle-2.3.1/spec/fixtures/data/2.0.1/filter.bin 0000664 0000000 0000000 00000000265 13255650766 0021133 0 ustar 00root root 0000000 0000000 test * id
d è è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/filter_array.bin 0000664 0000000 0000000 00000000055 13255650766 0022326 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.0.1/filter_array_exclude.bin 0000664 0000000 0000000 00000000055 13255650766 0024037 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.0.1/filter_boolean.bin 0000664 0000000 0000000 00000000045 13255650766 0022626 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.0.1/filter_floats.bin 0000664 0000000 0000000 00000000031 13255650766 0022472 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/2.0.1/filter_floats_exclude.bin 0000664 0000000 0000000 00000000031 13255650766 0024203 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/2.0.1/filter_range.bin 0000664 0000000 0000000 00000000041 13255650766 0022277 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.0.1/filter_range_exclude.bin 0000664 0000000 0000000 00000000041 13255650766 0024010 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.0.1/group.bin 0000664 0000000 0000000 00000000203 13255650766 0020772 0 ustar 00root root 0000000 0000000 test * id è id * riddle-2.3.1/spec/fixtures/data/2.0.1/index.bin 0000664 0000000 0000000 00000000221 13255650766 0020745 0 ustar 00root root 0000000 0000000 test edition è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/index_weights.bin 0000664 0000000 0000000 00000000231 13255650766 0022500 0 ustar 00root root 0000000 0000000 test * è @weight DESC people e * riddle-2.3.1/spec/fixtures/data/2.0.1/keywords_with_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0023571 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/2.0.1/keywords_without_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0024321 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/2.0.1/overrides.bin 0000664 0000000 0000000 00000000251 13255650766 0021643 0 ustar 00root root 0000000 0000000 test * è @weight DESC rating A * riddle-2.3.1/spec/fixtures/data/2.0.1/phrase.bin 0000664 0000000 0000000 00000000223 13255650766 0021122 0 ustar 00root root 0000000 0000000
testing this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/rank_mode.bin 0000664 0000000 0000000 00000000213 13255650766 0021576 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/select.bin 0000664 0000000 0000000 00000000223 13255650766 0021117 0 ustar 00root root 0000000 0000000 test * è @weight DESC selecting riddle-2.3.1/spec/fixtures/data/2.0.1/simple.bin 0000664 0000000 0000000 00000000213 13255650766 0021130 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/sort.bin 0000664 0000000 0000000 00000000220 13255650766 0020624 0 ustar 00root root 0000000 0000000 id testing * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.0.1/update_simple.bin 0000664 0000000 0000000 00000000056 13255650766 0022477 0 ustar 00root root 0000000 0000000 people birthday dìÐ riddle-2.3.1/spec/fixtures/data/2.0.1/weights.bin 0000664 0000000 0000000 00000000223 13255650766 0021312 0 ustar 00root root 0000000 0000000 test d * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/ 0000775 0000000 0000000 00000000000 13255650766 0017151 5 ustar 00root root 0000000 0000000 riddle-2.3.1/spec/fixtures/data/2.1.0/anchor.bin 0000664 0000000 0000000 00000000254 13255650766 0021116 0 ustar 00root root 0000000 0000000 test * è @weight DESC latitude longitudeA B¾ * riddle-2.3.1/spec/fixtures/data/2.1.0/any.bin 0000664 0000000 0000000 00000000220 13255650766 0020424 0 ustar 00root root 0000000 0000000
test this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/boolean.bin 0000664 0000000 0000000 00000000213 13255650766 0021256 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/comment.bin 0000664 0000000 0000000 00000000225 13255650766 0021304 0 ustar 00root root 0000000 0000000 test * è @weight DESC
commenting * riddle-2.3.1/spec/fixtures/data/2.1.0/distinct.bin 0000664 0000000 0000000 00000000215 13255650766 0021462 0 ustar 00root root 0000000 0000000 test * è @weight DESC id * riddle-2.3.1/spec/fixtures/data/2.1.0/field_weights.bin 0000664 0000000 0000000 00000000227 13255650766 0022461 0 ustar 00root root 0000000 0000000 test * è @weight DESC city e * riddle-2.3.1/spec/fixtures/data/2.1.0/filter.bin 0000664 0000000 0000000 00000000265 13255650766 0021133 0 ustar 00root root 0000000 0000000 test * id
d è è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/filter_array.bin 0000664 0000000 0000000 00000000055 13255650766 0022326 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.1.0/filter_array_exclude.bin 0000664 0000000 0000000 00000000055 13255650766 0024037 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.1.0/filter_boolean.bin 0000664 0000000 0000000 00000000045 13255650766 0022626 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.1.0/filter_floats.bin 0000664 0000000 0000000 00000000031 13255650766 0022472 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/2.1.0/filter_floats_exclude.bin 0000664 0000000 0000000 00000000031 13255650766 0024203 0 ustar 00root root 0000000 0000000 field @¬ÌÍAX riddle-2.3.1/spec/fixtures/data/2.1.0/filter_range.bin 0000664 0000000 0000000 00000000041 13255650766 0022277 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.1.0/filter_range_exclude.bin 0000664 0000000 0000000 00000000041 13255650766 0024010 0 ustar 00root root 0000000 0000000 field riddle-2.3.1/spec/fixtures/data/2.1.0/group.bin 0000664 0000000 0000000 00000000203 13255650766 0020772 0 ustar 00root root 0000000 0000000 test * id è id * riddle-2.3.1/spec/fixtures/data/2.1.0/index.bin 0000664 0000000 0000000 00000000221 13255650766 0020745 0 ustar 00root root 0000000 0000000 test edition è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/index_weights.bin 0000664 0000000 0000000 00000000231 13255650766 0022500 0 ustar 00root root 0000000 0000000 test * è @weight DESC people e * riddle-2.3.1/spec/fixtures/data/2.1.0/keywords_with_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0023571 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/2.1.0/keywords_without_hits.bin 0000664 0000000 0000000 00000000025 13255650766 0024321 0 ustar 00root root 0000000 0000000 pat people riddle-2.3.1/spec/fixtures/data/2.1.0/overrides.bin 0000664 0000000 0000000 00000000251 13255650766 0021643 0 ustar 00root root 0000000 0000000 test * è @weight DESC rating A * riddle-2.3.1/spec/fixtures/data/2.1.0/phrase.bin 0000664 0000000 0000000 00000000223 13255650766 0021122 0 ustar 00root root 0000000 0000000
testing this * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/rank_mode.bin 0000664 0000000 0000000 00000000213 13255650766 0021576 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/select.bin 0000664 0000000 0000000 00000000223 13255650766 0021117 0 ustar 00root root 0000000 0000000 test * è @weight DESC selecting riddle-2.3.1/spec/fixtures/data/2.1.0/simple.bin 0000664 0000000 0000000 00000000213 13255650766 0021130 0 ustar 00root root 0000000 0000000 test * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/sort.bin 0000664 0000000 0000000 00000000220 13255650766 0020624 0 ustar 00root root 0000000 0000000 id testing * è @weight DESC * riddle-2.3.1/spec/fixtures/data/2.1.0/update_simple.bin 0000664 0000000 0000000 00000000056 13255650766 0022477 0 ustar 00root root 0000000 0000000 people birthday dìÐ riddle-2.3.1/spec/fixtures/data/2.1.0/weights.bin 0000664 0000000 0000000 00000000223 13255650766 0021312 0 ustar 00root root 0000000 0000000 test d * è @weight DESC * riddle-2.3.1/spec/fixtures/data_generator.0.9.8.php 0000664 0000000 0000000 00000012204 13255650766 0021744 0 ustar 00root root 0000000 0000000 SetServer("localhost", 3312);
// simple
$file = fopen("spec/fixtures/data/simple.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
// index
$file = fopen("spec/fixtures/data/index.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ", "edition")]);
fclose($file);
// any
$client->SetMatchMode(SPH_MATCH_ANY);
$file = fopen("spec/fixtures/data/any.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test this ")]);
fclose($file);
$client->SetMatchMode(SPH_MATCH_ALL);
// sort
$client->SetSortMode(SPH_SORT_EXTENDED, "id");
$file = fopen("spec/fixtures/data/sort.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("testing ")]);
fclose($file);
$client->SetSortMode(SPH_SORT_RELEVANCE, "");
// boolean
$client->SetMatchMode(SPH_MATCH_BOOLEAN);
$file = fopen("spec/fixtures/data/boolean.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->SetMatchMode(SPH_MATCH_ALL);
// phrase
$client->SetMatchMode(SPH_MATCH_PHRASE);
$file = fopen("spec/fixtures/data/phrase.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("testing this ")]);
fclose($file);
$client->SetMatchMode(SPH_MATCH_ALL);
// filter
$client->SetFilter("id", array(10, 100, 1000));
$file = fopen("spec/fixtures/data/filter.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->ResetFilters();
// group
$client->SetGroupBy("id", SPH_GROUPBY_ATTR, "id");
$file = fopen("spec/fixtures/data/group.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->ResetGroupBy();
// distinct
$client->SetGroupDistinct("id");
$file = fopen("spec/fixtures/data/distinct.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->ResetGroupBy();
// weights
$client->SetWeights(array(100, 1));
$file = fopen("spec/fixtures/data/weights.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->SetWeights(array());
// anchor
$client->SetGeoAnchor("latitude", "longitude", 10.0, 95.0);
$file = fopen("spec/fixtures/data/anchor.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->ResetFilters();
// rank_mode
$client->SetRankingMode(SPH_RANK_WORDCOUNT);
$file = fopen("spec/fixtures/data/rank_mode.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->SetRankingMode(SPH_RANK_PROXIMITY_BM25);
// index_weights
$client->SetIndexWeights(array("people" => 101));
$file = fopen("spec/fixtures/data/index_weights.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->SetIndexWeights(array());
// index_weights
$client->SetFieldWeights(array("city" => 101));
$file = fopen("spec/fixtures/data/field_weights.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ")]);
fclose($file);
$client->SetFieldWeights(array());
// comment
$file = fopen("spec/fixtures/data/comment.bin", "w");
fwrite($file, $client->_reqs[$client->AddQuery("test ", "*", "commenting")]);
fclose($file);
// update_simple
$file = fopen("spec/fixtures/data/update_simple.bin", "w");
fwrite($file, $client->UpdateAttributes("people", array("birthday"), array(1 => array(191163600))));
fclose($file);
// keywords_without_hits
$file = fopen("spec/fixtures/data/keywords_without_hits.bin", "w");
fwrite($file, $client->BuildKeywords("pat", "people", false));
fclose($file);
// keywords_with_hits
$file = fopen("spec/fixtures/data/keywords_with_hits.bin", "w");
fwrite($file, $client->BuildKeywords("pat", "people", true));
fclose($file);
// filter_array
$client->SetFilter("field", array(1, 2, 3));
$file = fopen("spec/fixtures/data/filter_array.bin", "w");
fwrite($file, $client->FilterOutput());
fclose($file);
$client->ResetFilters();
// filter_array_exclude
$client->SetFilter("field", array(1, 2, 3), true);
$file = fopen("spec/fixtures/data/filter_array_exclude.bin", "w");
fwrite($file, $client->FilterOutput());
fclose($file);
$client->ResetFilters();
// filter_range
$client->SetFilterRange("field", 1, 3);
$file = fopen("spec/fixtures/data/filter_range.bin", "w");
fwrite($file, $client->FilterOutput());
fclose($file);
$client->ResetFilters();
// filter_range_exclude
$client->SetFilterRange("field", 1, 3, true);
$file = fopen("spec/fixtures/data/filter_range_exclude.bin", "w");
fwrite($file, $client->FilterOutput());
fclose($file);
$client->ResetFilters();
// filter_floats
$client->SetFilterFloatRange("field", 5.4, 13.5);
$file = fopen("spec/fixtures/data/filter_floats.bin", "w");
fwrite($file, $client->FilterOutput());
fclose($file);
$client->ResetFilters();
// filter_floats_exclude
$client->SetFilterFloatRange("field", 5.4, 13.5, true);
$file = fopen("spec/fixtures/data/filter_floats_exclude.bin", "w");
fwrite($file, $client->FilterOutput());
fclose($file);
$client->ResetFilters();
// filter_boolean
$client->SetFilter("field", array(0, 1));
$file = fopen("spec/fixtures/data/filter_boolean.bin", "w");
fwrite($file, $client->FilterOutput());
fclose($file);
$client->ResetFilters();
?> riddle-2.3.1/spec/fixtures/data_generator.0.9.9.php 0000664 0000000 0000000 00000000134 13255650766 0021744 0 ustar 00root root 0000000 0000000