riddle 0.9.8.1533.10 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/README.textile +1 -0
  2. data/lib/riddle.rb +9 -15
  3. data/lib/riddle/0.9.8.rb +0 -0
  4. data/lib/riddle/0.9.9.rb +5 -0
  5. data/lib/riddle/0.9.9/client.rb +49 -0
  6. data/lib/riddle/0.9.9/client/filter.rb +22 -0
  7. data/lib/riddle/0.9.9/configuration/searchd.rb +28 -0
  8. data/lib/riddle/client.rb +110 -18
  9. data/lib/riddle/client/filter.rb +29 -20
  10. data/lib/riddle/client/message.rb +4 -0
  11. data/lib/riddle/client/response.rb +10 -0
  12. data/lib/riddle/configuration/distributed_index.rb +8 -7
  13. data/lib/riddle/configuration/index.rb +15 -11
  14. data/lib/riddle/configuration/searchd.rb +6 -4
  15. data/lib/riddle/configuration/sql_source.rb +9 -4
  16. data/lib/riddle/controller.rb +5 -3
  17. data/spec/fixtures/data_generator.0.9.8.php +208 -0
  18. data/spec/fixtures/data_generator.0.9.9.php +225 -0
  19. data/spec/fixtures/sphinx/configuration.erb +38 -0
  20. data/spec/fixtures/sphinx/people.spa +0 -0
  21. data/spec/fixtures/sphinx/people.spd +0 -0
  22. data/spec/fixtures/sphinx/people.sph +0 -0
  23. data/spec/fixtures/sphinx/people.spi +0 -0
  24. data/spec/fixtures/sphinx/people.spk +0 -0
  25. data/spec/fixtures/sphinx/people.spm +0 -0
  26. data/spec/fixtures/sphinx/people.spp +0 -0
  27. data/spec/fixtures/sphinx/searchd.log +3731 -0
  28. data/spec/fixtures/sphinx/searchd.query.log +1032 -0
  29. data/spec/fixtures/sphinx/spec.conf +38 -0
  30. data/spec/fixtures/sphinxapi.0.9.8.php +1228 -0
  31. data/spec/fixtures/sphinxapi.0.9.9.php +1646 -0
  32. data/spec/fixtures/sql/conf.example.yml +3 -0
  33. data/spec/fixtures/sql/conf.yml +3 -0
  34. data/spec/fixtures/sql/data.sql +25000 -0
  35. data/spec/fixtures/sql/structure.sql +16 -0
  36. data/spec/functional/excerpt_spec.rb +37 -10
  37. data/spec/functional/persistance_spec.rb +17 -0
  38. data/spec/functional/status_spec.rb +21 -0
  39. data/spec/functional/update_spec.rb +3 -3
  40. data/spec/spec_helper.rb +30 -0
  41. data/spec/sphinx_helper.rb +93 -0
  42. data/spec/unit/client_spec.rb +20 -3
  43. data/spec/unit/configuration/distributed_index_spec.rb +2 -0
  44. data/spec/unit/configuration/index_spec.rb +16 -0
  45. data/spec/unit/configuration/searchd_spec.rb +46 -13
  46. data/spec/unit/configuration/sql_source_spec.rb +15 -0
  47. metadata +61 -37
  48. data/MIT-LICENCE +0 -20
  49. data/lib/tabtab_definitions.rb +0 -15
@@ -0,0 +1,16 @@
1
+ DROP TABLE IF EXISTS `people`;
2
+
3
+ CREATE TABLE `people` (
4
+ `id` int(11) NOT NULL auto_increment,
5
+ `first_name` varchar(50) NOT NULL,
6
+ `middle_initial` varchar(10) NOT NULL,
7
+ `last_name` varchar(50) NOT NULL,
8
+ `gender` varchar(10) NOT NULL,
9
+ `street_address` varchar(200) NOT NULL,
10
+ `city` varchar(100) NOT NULL,
11
+ `state` varchar(100) NOT NULL,
12
+ `postcode` varchar(10) NOT NULL,
13
+ `email` varchar(100) NOT NULL,
14
+ `birthday` datetime NOT NULL,
15
+ PRIMARY KEY (`id`)
16
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -28,7 +28,7 @@ describe "Sphinx Excepts" do
28
28
  end
29
29
 
30
30
  it "should separate matches that are far apart by an ellipsis by default" do
31
- @client.excerpts(
31
+ excerpts = @client.excerpts(
32
32
  :index => "people",
33
33
  :words => "Pat",
34
34
  :docs => [
@@ -45,18 +45,32 @@ not. It's just my name: Pat.
45
45
  ],
46
46
  :before_match => "<em>",
47
47
  :after_match => "</em>"
48
- ).should == [
49
- <<-SENTENCE
48
+ )
49
+
50
+
51
+ if SphinxVersion == '0.9.9'
52
+ excerpts.should == [
53
+ <<-SENTENCE
54
+ This is a really long sentence written by <em>Pat</em>. It has to be over 256
55
+ characters long, between keywords. But what is the &#8230; 're really interested in finding out,
56
+ yeah? Excerpts are particularly riveting. This keyword, however, is
57
+ not. It's just my name: <em>Pat</em>.
58
+ SENTENCE
59
+ ]
60
+ else
61
+ excerpts.should == [
62
+ <<-SENTENCE
50
63
  This is a really long sentence written by <em>Pat</em>. It has to be over 256
51
64
  characters long, between keywords. But what is the keyword? &#8230; interested in finding out,
52
65
  yeah? Excerpts are particularly riveting. This keyword, however, is
53
66
  not. It's just my name: <em>Pat</em>.
54
- SENTENCE
55
- ]
67
+ SENTENCE
68
+ ]
69
+ end
56
70
  end
57
71
 
58
72
  it "should use the provided separator" do
59
- @client.excerpts(
73
+ excerpts = @client.excerpts(
60
74
  :index => "people",
61
75
  :words => "Pat",
62
76
  :docs => [
@@ -74,14 +88,27 @@ not. It's just my name: Pat.
74
88
  :before_match => "<em>",
75
89
  :after_match => "</em>",
76
90
  :chunk_separator => " --- "
77
- ).should == [
78
- <<-SENTENCE
91
+ )
92
+
93
+ if SphinxVersion == '0.9.9'
94
+ excerpts.should == [
95
+ <<-SENTENCE
96
+ This is a really long sentence written by <em>Pat</em>. It has to be over 256
97
+ characters long, between keywords. But what is the --- 're really interested in finding out,
98
+ yeah? Excerpts are particularly riveting. This keyword, however, is
99
+ not. It's just my name: <em>Pat</em>.
100
+ SENTENCE
101
+ ]
102
+ else
103
+ excerpts.should == [
104
+ <<-SENTENCE
79
105
  This is a really long sentence written by <em>Pat</em>. It has to be over 256
80
106
  characters long, between keywords. But what is the keyword? --- interested in finding out,
81
107
  yeah? Excerpts are particularly riveting. This keyword, however, is
82
108
  not. It's just my name: <em>Pat</em>.
83
- SENTENCE
84
- ]
109
+ SENTENCE
110
+ ]
111
+ end
85
112
  end
86
113
 
87
114
  it "should return multiple results for multiple documents" do
@@ -0,0 +1,17 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe "Sphinx Persistance Connection" do
4
+ before :each do
5
+ @client = Riddle::Client.new("localhost", 3313)
6
+ end
7
+
8
+ it "should raise errors once already opened" do
9
+ @client.open
10
+ lambda { @client.open }.should raise_error
11
+ @client.close
12
+ end
13
+
14
+ it "should raise errors if closing when already closed" do
15
+ lambda { @client.close }.should raise_error
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec/spec_helper'
2
+
3
+ if SphinxVersion == '0.9.9'
4
+ describe "Sphinx Status" do
5
+ before :each do
6
+ @client = Riddle::Client.new("localhost", 3313)
7
+ @status = @client.status
8
+ end
9
+
10
+ it "should return a hash" do
11
+ @status.should be_a(Hash)
12
+ end
13
+
14
+ it "should include the uptime, connections, and command_search keys" do
15
+ # Not checking all values, but ensuring keys are being set correctly
16
+ @status[:uptime].should_not be_nil
17
+ @status[:connections].should_not be_nil
18
+ @status[:command_search].should_not be_nil
19
+ end
20
+ end
21
+ end
@@ -11,17 +11,17 @@ describe "Sphinx Updates" do
11
11
  result[:matches].should_not be_empty
12
12
  result[:matches].length.should == 1
13
13
  ellie = result[:matches].first
14
- ellie[:attributes]["birthday"].should == Time.local(1970, 1, 23).to_i
14
+ ellie[:attributes]["birthday"].should == Time.utc(1970, 1, 23).to_i
15
15
 
16
16
  # make Ellie younger by 6 years
17
- @client.update("people", ["birthday"], {ellie[:doc] => [Time.local(1976, 1, 23).to_i]})
17
+ @client.update("people", ["birthday"], {ellie[:doc] => [Time.utc(1976, 1, 23).to_i]})
18
18
 
19
19
  # check attribute's value
20
20
  result = @client.query("Ellie K Ford")
21
21
  result[:matches].should_not be_empty
22
22
  result[:matches].length.should == 1
23
23
  ellie = result[:matches].first
24
- ellie[:attributes]["birthday"].should == Time.local(1976, 1, 23).to_i
24
+ ellie[:attributes]["birthday"].should == Time.utc(1976, 1, 23).to_i
25
25
  end
26
26
 
27
27
  it "should update multiple records appropriately" do
@@ -0,0 +1,30 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../lib'
2
+
3
+ SphinxVersion = ENV['VERSION'] || '0.9.8'
4
+
5
+ require 'riddle'
6
+ require "riddle/#{SphinxVersion}"
7
+ require 'spec'
8
+ require 'spec/sphinx_helper'
9
+
10
+ Spec::Runner.configure do |config|
11
+ sphinx = SphinxHelper.new
12
+ sphinx.setup_mysql
13
+ sphinx.generate_configuration
14
+ sphinx.index
15
+
16
+ config.before :all do
17
+ `php -f spec/fixtures/data_generator.#{SphinxVersion}.php`
18
+ sphinx.start
19
+ end
20
+
21
+ config.after :all do
22
+ sphinx.stop
23
+ end
24
+ end
25
+
26
+ def query_contents(key)
27
+ contents = open("spec/fixtures/data/#{key.to_s}.bin") { |f| f.read }
28
+ contents.respond_to?(:encoding) ?
29
+ contents.force_encoding('ASCII-8BIT') : contents
30
+ end
@@ -0,0 +1,93 @@
1
+ require 'mysql'
2
+ require 'erb'
3
+ require 'yaml'
4
+
5
+ class SphinxHelper
6
+ attr_accessor :host, :username, :password
7
+ attr_reader :path
8
+
9
+ def initialize
10
+ @host = "localhost"
11
+ @username = "anonymous"
12
+ @password = ""
13
+
14
+ if File.exist?("spec/fixtures/sql/conf.yml")
15
+ config = YAML.load(File.open("spec/fixtures/sql/conf.yml"))
16
+ @host = config["host"]
17
+ @username = config["username"]
18
+ @password = config["password"]
19
+ end
20
+
21
+ @path = File.expand_path(File.dirname(__FILE__))
22
+ end
23
+
24
+ def setup_mysql
25
+ server = Mysql.new @host, @username, @password
26
+ server.set_server_option(Mysql::OPTION_MULTI_STATEMENTS_ON)
27
+
28
+ unless server.list_dbs.include?("riddle")
29
+ server.create_db "riddle"
30
+ end
31
+
32
+ server.query "USE riddle;"
33
+
34
+ structure = File.open("spec/fixtures/sql/structure.sql") { |f| f.read }
35
+ # Block ensures multiple statement transaction is closed.
36
+ server.query(structure) { |response| }
37
+ data = File.open("spec/fixtures/sql/data.sql") { |f|
38
+ while line = f.gets
39
+ server.query line
40
+ end
41
+ }
42
+
43
+ server.close
44
+ end
45
+
46
+ def reset
47
+ setup_mysql
48
+ index
49
+ end
50
+
51
+ def generate_configuration
52
+ template = File.open("spec/fixtures/sphinx/configuration.erb") { |f| f.read }
53
+ File.open("spec/fixtures/sphinx/spec.conf", "w") { |f|
54
+ f.puts ERB.new(template).result(binding)
55
+ }
56
+ end
57
+
58
+ def index
59
+ cmd = "indexer --config #{@path}/fixtures/sphinx/spec.conf --all"
60
+ cmd << " --rotate" if running?
61
+ `#{cmd}`
62
+ end
63
+
64
+ def start
65
+ return if running?
66
+
67
+ cmd = "searchd --config #{@path}/fixtures/sphinx/spec.conf"
68
+ `#{cmd}`
69
+
70
+ sleep(1)
71
+
72
+ unless running?
73
+ puts "Failed to start searchd daemon. Check fixtures/sphinx/searchd.log."
74
+ end
75
+ end
76
+
77
+ def stop
78
+ return unless running?
79
+ `kill #{pid}`
80
+ end
81
+
82
+ def pid
83
+ if File.exists?("#{@path}/fixtures/sphinx/searchd.pid")
84
+ `cat #{@path}/fixtures/sphinx/searchd.pid`[/\d+/]
85
+ else
86
+ nil
87
+ end
88
+ end
89
+
90
+ def running?
91
+ pid && `ps #{pid} | wc -l`.to_i > 1
92
+ end
93
+ end
@@ -1,8 +1,9 @@
1
1
  require 'spec/spec_helper'
2
2
 
3
3
  describe Riddle::Client do
4
- it "should have the same keys for both commands and versions" do
5
- Riddle::Client::Commands.keys.should == Riddle::Client::Versions.keys
4
+ it "should have the same keys for both commands and versions, except persist" do
5
+
6
+ (Riddle::Client::Commands.keys - [:persist]).should == Riddle::Client::Versions.keys
6
7
  end
7
8
 
8
9
  it "should default to localhost as the server" do
@@ -123,12 +124,28 @@ describe Riddle::Client do
123
124
  client.queue.first.should == query_contents(:field_weights)
124
125
  end
125
126
 
126
- it "should build a message with acomment correctly" do
127
+ it "should build a message with a comment correctly" do
127
128
  client = Riddle::Client.new
128
129
  client.append_query "test ", "*", "commenting"
129
130
  client.queue.first.should == query_contents(:comment)
130
131
  end
131
132
 
133
+ if SphinxVersion == '0.9.9'
134
+ it "should build a message with overrides correctly" do
135
+ client = Riddle::Client.new
136
+ client.add_override("rating", :float, {1 => 10.0})
137
+ client.append_query "test "
138
+ client.queue.first.should == query_contents(:overrides)
139
+ end
140
+
141
+ it "should build a message with selects correctly" do
142
+ client = Riddle::Client.new
143
+ client.select = "selecting"
144
+ client.append_query "test "
145
+ client.queue.first.should == query_contents(:select)
146
+ end
147
+ end
148
+
132
149
  it "should keep multiple messages in the queue" do
133
150
  client = Riddle::Client.new
134
151
  client.weights = [100, 1]
@@ -36,6 +36,7 @@ describe Riddle::Configuration::DistributedIndex do
36
36
  Riddle::Configuration::RemoteIndex.new("localhost", 3313, "remote1") <<
37
37
  Riddle::Configuration::RemoteIndex.new("localhost", 3314, "remote2") <<
38
38
  Riddle::Configuration::RemoteIndex.new("localhost", 3314, "remote3")
39
+ index.agent_blackhole << "testbox:3312:testindex1,testindex2"
39
40
 
40
41
  index.agent_connect_timeout = 1000
41
42
  index.agent_query_timeout = 3000
@@ -48,6 +49,7 @@ index dist1
48
49
  local = test1stemmed
49
50
  agent = localhost:3313:remote1
50
51
  agent = localhost:3314:remote2,remote3
52
+ agent_blackhole = testbox:3312:testindex1,testindex2
51
53
  agent_connect_timeout = 1000
52
54
  agent_query_timeout = 3000
53
55
  }
@@ -47,6 +47,7 @@ describe Riddle::Configuration::DistributedIndex do
47
47
  index.docinfo = "extern"
48
48
  index.mlock = 0
49
49
  index.morphologies << "stem_en" << "stem_ru" << "soundex"
50
+ index.min_stemming_len = 1
50
51
  index.stopword_files << "/var/data/stopwords.txt" << "/var/data/stopwords2.txt"
51
52
  index.wordform_files << "/var/data/wordforms.txt"
52
53
  index.exception_files << "/var/data/exceptions.txt"
@@ -67,6 +68,13 @@ describe Riddle::Configuration::DistributedIndex do
67
68
  index.html_index_attrs = "img=alt,title; a=title"
68
69
  index.html_remove_element_tags << "style" << "script"
69
70
  index.preopen = 1
71
+ index.ondisk_dict = 1
72
+ index.inplace_enable = 1
73
+ index.inplace_hit_gap = 0
74
+ index.inplace_docinfo_gap = 0
75
+ index.inplace_reloc_factor = 0.1
76
+ index.inplace_write_factor = 0.1
77
+ index.index_exact_words = 1
70
78
 
71
79
  index.render.should == <<-INDEX
72
80
  source src1
@@ -82,6 +90,7 @@ index test1
82
90
  docinfo = extern
83
91
  mlock = 0
84
92
  morphology = stem_en, stem_ru, soundex
93
+ min_stemming_len = 1
85
94
  stopwords = /var/data/stopwords.txt /var/data/stopwords2.txt
86
95
  wordforms = /var/data/wordforms.txt
87
96
  exceptions = /var/data/exceptions.txt
@@ -102,6 +111,13 @@ index test1
102
111
  html_index_attrs = img=alt,title; a=title
103
112
  html_remove_elements = style, script
104
113
  preopen = 1
114
+ ondisk_dict = 1
115
+ inplace_enable = 1
116
+ inplace_hit_gap = 0
117
+ inplace_docinfo_gap = 0
118
+ inplace_reloc_factor = 0.1
119
+ inplace_write_factor = 0.1
120
+ index_exact_words = 1
105
121
  }
106
122
  INDEX
107
123
  end
@@ -1,18 +1,38 @@
1
1
  require 'spec/spec_helper'
2
2
 
3
3
  describe Riddle::Configuration::Searchd do
4
- it "should be invalid without a port or pid_file" do
5
- searchd = Riddle::Configuration::Searchd.new
6
- searchd.should_not be_valid
4
+ if SphinxVersion == '0.9.9'
5
+ it "should be invalid without a listen or pid_file" do
6
+ searchd = Riddle::Configuration::Searchd.new
7
+ searchd.should_not be_valid
7
8
 
8
- searchd.port = 3312
9
- searchd.should_not be_valid
9
+ searchd.port = 3312
10
+ searchd.should_not be_valid
10
11
 
11
- searchd.pid_file = "file.pid"
12
- searchd.should be_valid
12
+ searchd.pid_file = "file.pid"
13
+ searchd.should be_valid
13
14
 
14
- searchd.port = nil
15
- searchd.should_not be_valid
15
+ searchd.port = nil
16
+ searchd.listen = nil
17
+ searchd.should_not be_valid
18
+
19
+ searchd.listen = "localhost:3312"
20
+ searchd.should be_valid
21
+ end
22
+ else
23
+ it "should be invalid without a port or pid_file" do
24
+ searchd = Riddle::Configuration::Searchd.new
25
+ searchd.should_not be_valid
26
+
27
+ searchd.port = 3312
28
+ searchd.should_not be_valid
29
+
30
+ searchd.pid_file = "file.pid"
31
+ searchd.should be_valid
32
+
33
+ searchd.port = nil
34
+ searchd.should_not be_valid
35
+ end
16
36
  end
17
37
 
18
38
  it "should raise a ConfigurationError if rendering but not valid" do
@@ -22,8 +42,11 @@ describe Riddle::Configuration::Searchd do
22
42
  end
23
43
 
24
44
  it "should support Sphinx's searchd settings" do
25
- settings = %w( address port log query_log read_timeout max_children
26
- pid_file max_matches seamless_rotate preopen_indexes unlink_old )
45
+ settings = %w( listen address port log query_log read_timeout
46
+ client_timeout max_children pid_file max_matches seamless_rotate
47
+ preopen_indexes unlink_old attr_flush_period ondisk_dict_default
48
+ max_packet_size mva_updates_pool crash_log_path max_filters
49
+ max_filter_values )
27
50
  searchd = Riddle::Configuration::Searchd.new
28
51
 
29
52
  settings.each do |setting|
@@ -37,12 +60,22 @@ describe Riddle::Configuration::Searchd do
37
60
  searchd.port = 3312
38
61
  searchd.pid_file = "file.pid"
39
62
 
40
- searchd.render.should == <<-SEARCHD
63
+ if SphinxVersion == '0.9.9'
64
+ searchd.render.should == <<-SEARCHD
65
+ searchd
66
+ {
67
+ listen = 3312
68
+ pid_file = file.pid
69
+ }
70
+ SEARCHD
71
+ else
72
+ searchd.render.should == <<-SEARCHD
41
73
  searchd
42
74
  {
43
75
  port = 3312
44
76
  pid_file = file.pid
45
77
  }
46
- SEARCHD
78
+ SEARCHD
79
+ end
47
80
  end
48
81
  end