riddle 0.9.8.1533.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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