riddle 1.3.2 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -85,3 +85,4 @@ Thanks to the following people who have contributed to Riddle in some shape or f
85
85
  * Matt Todd
86
86
  * Paco Guzmán
87
87
  * Greg Weber
88
+ * Enrico Thierbach
@@ -57,6 +57,7 @@ require 'riddle/auto_version'
57
57
  require 'riddle/client'
58
58
  require 'riddle/configuration'
59
59
  require 'riddle/controller'
60
+ require 'riddle/query'
60
61
 
61
62
  Riddle.loaded_version = nil
62
63
  Riddle::AutoVersion.configure
@@ -8,7 +8,7 @@ class Riddle::AutoVersion
8
8
  require "riddle/#{version}"
9
9
  when /1.10/
10
10
  require 'riddle/1.10'
11
- when /2.0.1/
11
+ when /2.0.\d/
12
12
  require 'riddle/2.0.1'
13
13
  end
14
14
  end
@@ -254,18 +254,23 @@ module Riddle
254
254
  result[:attribute_names] << attribute_name
255
255
  end
256
256
 
257
+ result_attribute_names_and_types = result[:attribute_names].
258
+ inject([]) { |array, attr| array.push([ attr, result[:attributes][attr] ]) }
259
+
257
260
  matches = response.next_int
258
261
  is_64_bit = response.next_int
259
- for i in 0...matches
262
+
263
+ result[:matches] = (0...matches).map do |i|
260
264
  doc = is_64_bit > 0 ? response.next_64bit_int : response.next_int
261
265
  weight = response.next_int
262
266
 
263
- result[:matches] << {:doc => doc, :weight => weight, :index => i, :attributes => {}}
264
- result[:attribute_names].each do |attr|
265
- result[:matches].last[:attributes][attr] = attribute_from_type(
266
- result[:attributes][attr], response
267
- )
267
+ current_match_attributes = {}
268
+
269
+ result_attribute_names_and_types.each do |attr, type|
270
+ current_match_attributes[attr] = attribute_from_type(type, response)
268
271
  end
272
+
273
+ {:doc => doc, :weight => weight, :index => i, :attributes => current_match_attributes}
269
274
  end
270
275
 
271
276
  result[:total] = response.next_int.to_i || 0
@@ -621,7 +626,7 @@ module Riddle
621
626
  when :search
622
627
  if Versions[command] >= 0x118
623
628
  socket.send request_header(command, message.length) +
624
- [messages.length, 0].pack('NN') + message, 0
629
+ [0, messages.length].pack('NN') + message, 0
625
630
  else
626
631
  socket.send request_header(command, message.length) +
627
632
  [messages.length].pack('N') + message, 0
@@ -803,20 +808,28 @@ module Riddle
803
808
 
804
809
  message.to_s
805
810
  end
811
+
812
+ AttributeHandlers = {
813
+ AttributeTypes[:integer] => :next_int,
814
+ AttributeTypes[:timestamp] => :next_int,
815
+ AttributeTypes[:ordinal] => :next_int,
816
+ AttributeTypes[:bool] => :next_int,
817
+ AttributeTypes[:float] => :next_float,
818
+ AttributeTypes[:bigint] => :next_64bit_int,
819
+ AttributeTypes[:string] => :next,
820
+
821
+ AttributeTypes[:multi] + AttributeTypes[:integer] => :next_int_array,
822
+ AttributeTypes[:multi] + AttributeTypes[:timestamp] => :next_int_array,
823
+ AttributeTypes[:multi] + AttributeTypes[:ordinal] => :next_int_array,
824
+ AttributeTypes[:multi] + AttributeTypes[:bool] => :next_int_array,
825
+ AttributeTypes[:multi] + AttributeTypes[:float] => :next_float_array,
826
+ AttributeTypes[:multi] + AttributeTypes[:bigint] => :next_64bit_int_array,
827
+ AttributeTypes[:multi] + AttributeTypes[:string] => :next_array
828
+ }
806
829
 
807
830
  def attribute_from_type(type, response)
808
- type -= AttributeTypes[:multi] if is_multi = type > AttributeTypes[:multi]
809
-
810
- case type
811
- when AttributeTypes[:float]
812
- is_multi ? response.next_float_array : response.next_float
813
- when AttributeTypes[:bigint]
814
- is_multi ? response.next_64bit_int_arry : response.next_64bit_int
815
- when AttributeTypes[:string]
816
- is_multi ? response.next_array : response.next
817
- else
818
- is_multi ? response.next_int_array : response.next_int
819
- end
831
+ handler = AttributeHandlers[type]
832
+ response.send handler
820
833
  end
821
834
 
822
835
  def excerpt_flags(options)
@@ -2,23 +2,25 @@ module Riddle
2
2
  class Configuration
3
3
  class Index < Riddle::Configuration::Section
4
4
  self.settings = [:type, :source, :path, :docinfo, :mlock, :morphology,
5
- :min_stemming_len, :stopwords, :wordforms, :exceptions, :min_word_len,
6
- :charset_dictpath, :charset_type, :charset_table, :ignore_chars,
7
- :min_prefix_len, :min_infix_len, :prefix_fields, :infix_fields,
8
- :enable_star, :expand_keywords, :ngram_len, :ngram_chars,
9
- :phrase_boundary, :phrase_boundary_step, :blend_chars, :html_strip,
5
+ :dict, :index_sp, :index_zones, :min_stemming_len, :stopwords,
6
+ :wordforms, :exceptions, :min_word_len, :charset_dictpath,
7
+ :charset_type, :charset_table, :ignore_chars, :min_prefix_len,
8
+ :min_infix_len, :prefix_fields, :infix_fields, :enable_star,
9
+ :expand_keywords, :ngram_len, :ngram_chars, :phrase_boundary,
10
+ :phrase_boundary_step, :blend_chars, :blend_mode, :html_strip,
10
11
  :html_index_attrs, :html_remove_elements, :preopen, :ondisk_dict,
11
12
  :inplace_enable, :inplace_hit_gap, :inplace_docinfo_gap,
12
13
  :inplace_reloc_factor, :inplace_write_factor, :index_exact_words,
13
14
  :overshort_step, :stopwords_step, :hitless_words]
14
15
 
15
16
  attr_accessor :name, :parent, :type, :sources, :path, :docinfo, :mlock,
16
- :morphologies, :min_stemming_len, :stopword_files, :wordform_files,
17
- :exception_files, :min_word_len, :charset_dictpath, :charset_type,
18
- :charset_table, :ignore_characters, :min_prefix_len, :min_infix_len,
19
- :prefix_field_names, :infix_field_names, :enable_star, :expand_keywords,
20
- :ngram_len, :ngram_characters, :phrase_boundaries,
21
- :phrase_boundary_step, :blend_chars, :html_strip, :html_index_attrs,
17
+ :morphologies, :dict, :index_sp, :index_zones, :min_stemming_len,
18
+ :stopword_files, :wordform_files, :exception_files, :min_word_len,
19
+ :charset_dictpath, :charset_type, :charset_table, :ignore_characters,
20
+ :min_prefix_len, :min_infix_len, :prefix_field_names,
21
+ :infix_field_names, :enable_star, :expand_keywords, :ngram_len,
22
+ :ngram_characters, :phrase_boundaries, :phrase_boundary_step,
23
+ :blend_chars, :blend_mode, :html_strip, :html_index_attrs,
22
24
  :html_remove_element_tags, :preopen, :ondisk_dict, :inplace_enable,
23
25
  :inplace_hit_gap, :inplace_docinfo_gap, :inplace_reloc_factor,
24
26
  :inplace_write_factor, :index_exact_words, :overshort_step,
@@ -2,13 +2,16 @@ module Riddle
2
2
  class Configuration
3
3
  class Searchd < Riddle::Configuration::Section
4
4
  self.settings = [:listen, :address, :port, :log, :query_log,
5
- :read_timeout, :client_timeout, :max_children, :pid_file, :max_matches,
6
- :seamless_rotate, :preopen_indexes, :unlink_old, :attr_flush_period,
7
- :ondisk_dict_default, :max_packet_size, :mva_updates_pool,
8
- :crash_log_path, :max_filters, :max_filter_values, :listen_backlog,
9
- :read_buffer, :read_unhinted, :max_batch_queries, :subtree_docs_cache,
10
- :subtree_hits_cache, :workers, :dist_threads, :binlog_path,
11
- :binlog_flush, :binlog_max_log_size, :client_key]
5
+ :query_log_format, :read_timeout, :client_timeout, :max_children,
6
+ :pid_file, :max_matches, :seamless_rotate, :preopen_indexes,
7
+ :unlink_old, :attr_flush_period, :ondisk_dict_default, :max_packet_size,
8
+ :mva_updates_pool, :crash_log_path, :max_filters, :max_filter_values,
9
+ :listen_backlog, :read_buffer, :read_unhinted, :max_batch_queries,
10
+ :subtree_docs_cache, :subtree_hits_cache, :workers, :dist_threads,
11
+ :binlog_path, :binlog_flush, :binlog_max_log_size, :collation_server,
12
+ :collation_libc_locale, :plugin_dir, :mysql_version_string,
13
+ :rt_flush_period, :thread_stack, :expansion_limit,
14
+ :compat_sphinxql_magics, :watchdog, :client_key]
12
15
 
13
16
  attr_accessor *self.settings
14
17
 
@@ -8,10 +8,10 @@ module Riddle
8
8
  :sql_query_killlist, :sql_attr_uint, :sql_attr_bool, :sql_attr_bigint,
9
9
  :sql_attr_timestamp, :sql_attr_str2ordinal, :sql_attr_float,
10
10
  :sql_attr_multi, :sql_attr_string, :sql_attr_str2wordcount,
11
- :sql_field_string, :sql_field_str2wordcount, :sql_query_post,
12
- :sql_query_post_index, :sql_ranged_throttle, :sql_query_info,
13
- :mssql_winauth, :mssql_unicode, :unpack_zlib, :unpack_mysqlcompress,
14
- :unpack_mysqlcompress_maxsize]
11
+ :sql_column_buffers, :sql_field_string, :sql_field_str2wordcount,
12
+ :sql_query_post, :sql_query_post_index, :sql_ranged_throttle,
13
+ :sql_query_info, :mssql_winauth, :mssql_unicode, :unpack_zlib,
14
+ :unpack_mysqlcompress, :unpack_mysqlcompress_maxsize]
15
15
 
16
16
  attr_accessor *self.settings
17
17
 
@@ -0,0 +1,88 @@
1
+ module Riddle::Query
2
+ def self.connection(address = '127.0.0.1', port = 9312)
3
+ require 'mysql2'
4
+
5
+ # If you use localhost, MySQL insists on a socket connection, but Sphinx
6
+ # requires a TCP connection. Using 127.0.0.1 fixes that.
7
+ address = '127.0.0.1' if address == 'localhost'
8
+
9
+ Mysql2::Client.new(
10
+ :host => address,
11
+ :port => port
12
+ )
13
+ end
14
+
15
+ def self.meta
16
+ 'SHOW META'
17
+ end
18
+
19
+ def self.warnings
20
+ 'SHOW WARNINGS'
21
+ end
22
+
23
+ def self.status
24
+ 'SHOW STATUS'
25
+ end
26
+
27
+ def self.tables
28
+ 'SHOW TABLES'
29
+ end
30
+
31
+ def self.variables
32
+ 'SHOW VARIABLES'
33
+ end
34
+
35
+ def self.collation
36
+ 'SHOW COLLATION'
37
+ end
38
+
39
+ def self.describe(index)
40
+ "DESCRIBE #{index}"
41
+ end
42
+
43
+ def self.begin
44
+ 'BEGIN'
45
+ end
46
+
47
+ def self.commit
48
+ 'COMMIT'
49
+ end
50
+
51
+ def self.rollback
52
+ 'ROLLBACK'
53
+ end
54
+
55
+ def self.set(variable, values, global = true)
56
+ values = "(#{values.join(', ')})" if values.is_a?(Array)
57
+ "SET#{ ' GLOBAL' if global } #{variable} = #{values}"
58
+ end
59
+
60
+ def self.snippets(data, index, query, options = nil)
61
+ options = ', ' + options.keys.collect { |key|
62
+ "#{options[key]} AS #{key}"
63
+ }.join(', ') unless options.nil?
64
+
65
+ "CALL SNIPPETS('#{data}', '#{index}', '#{query}'#{options})"
66
+ end
67
+
68
+ def self.create_function(name, type, file)
69
+ type = type.to_s.upcase
70
+ "CREATE FUNCTION #{name} RETURNS #{type} SONAME '#{file}'"
71
+ end
72
+
73
+ def self.drop_function(name)
74
+ "DROP FUNCTION #{name}"
75
+ end
76
+
77
+ def self.update(index, id, values = {})
78
+ values = values.keys.collect { |key|
79
+ "#{key} = #{values[key]}"
80
+ }.join(', ')
81
+
82
+ "UPDATE #{index} SET #{values} WHERE id = #{id}"
83
+ end
84
+ end
85
+
86
+ require 'riddle/query/delete'
87
+ require 'riddle/query/insert'
88
+ require 'riddle/query/select'
@@ -0,0 +1,14 @@
1
+ class Riddle::Query::Delete
2
+ def initialize(index, *ids)
3
+ @index = index
4
+ @ids = ids.flatten
5
+ end
6
+
7
+ def to_sql
8
+ if @ids.length > 1
9
+ "DELETE FROM #{@index} WHERE id IN (#{@ids.join(', ')})"
10
+ else
11
+ "DELETE FROM #{@index} WHERE id = #{@ids.first}"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,48 @@
1
+ class Riddle::Query::Insert
2
+ attr_reader :columns, :values
3
+
4
+ def initialize(index, columns = [], values = [])
5
+ @index = index
6
+ @columns = columns
7
+ @values = values.first.is_a?(Array) ? values : [values]
8
+ @replace = false
9
+ end
10
+
11
+ def replace!
12
+ @replace = true
13
+ self
14
+ end
15
+
16
+ def to_sql
17
+ "#{command} INTO #{@index} (#{columns_to_s}) VALUES (#{values_to_s})"
18
+ end
19
+
20
+ private
21
+
22
+ def command
23
+ @replace ? 'REPLACE' : 'INSERT'
24
+ end
25
+
26
+ def columns_to_s
27
+ columns.join(', ')
28
+ end
29
+
30
+ def values_to_s
31
+ values.collect { |value_set|
32
+ value_set.collect { |value|
33
+ translated_value(value)
34
+ }.join(', ')
35
+ }.join('), (')
36
+ end
37
+
38
+ def translated_value(value)
39
+ case value
40
+ when String
41
+ "'#{value}'"
42
+ when TrueClass, FalseClass
43
+ value ? 1 : 0
44
+ else
45
+ value
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,108 @@
1
+ class Riddle::Query::Select
2
+ def initialize
3
+ @indices = []
4
+ @matching = nil
5
+ @wheres = {}
6
+ @group_by = nil
7
+ @order_by = nil
8
+ @order_within_group_by = nil
9
+ @offset = nil
10
+ @limit = nil
11
+ @options = {}
12
+ end
13
+
14
+ def from(*indices)
15
+ @indices += indices
16
+ self
17
+ end
18
+
19
+ def matching(match)
20
+ @matching = match
21
+ self
22
+ end
23
+
24
+ def where(filters = {})
25
+ @wheres.merge!(filters)
26
+ self
27
+ end
28
+
29
+ def group_by(attribute)
30
+ @group_by = attribute
31
+ self
32
+ end
33
+
34
+ def order_by(order)
35
+ @order_by = order
36
+ self
37
+ end
38
+
39
+ def order_within_group_by(order)
40
+ @order_within_group_by = order
41
+ self
42
+ end
43
+
44
+ def limit(limit)
45
+ @limit = limit
46
+ self
47
+ end
48
+
49
+ def offset(offset)
50
+ @offset = offset
51
+ self
52
+ end
53
+
54
+ def with_options(options = {})
55
+ @options.merge! options
56
+ self
57
+ end
58
+
59
+ def to_sql
60
+ sql = "SELECT * FROM #{ @indices.join(', ') }"
61
+ sql << " WHERE #{ combined_wheres }" if wheres?
62
+ sql << " GROUP BY #{@group_by}" if !@group_by.nil?
63
+ sql << " ORDER BY #{@order_by}" if !@order_by.nil?
64
+ unless @order_within_group_by.nil?
65
+ sql << " WITHIN GROUP ORDER BY #{@order_within_group_by}"
66
+ end
67
+ sql << " #{limit_clause}" unless @limit.nil? && @offset.nil?
68
+ sql << " #{options_clause}" unless @options.empty?
69
+
70
+ sql
71
+ end
72
+
73
+ private
74
+
75
+ def wheres?
76
+ !(@wheres.empty? && @matching.nil?)
77
+ end
78
+
79
+ def combined_wheres
80
+ if @matching.nil?
81
+ wheres_to_s
82
+ elsif @wheres.empty?
83
+ "MATCH('#{@matching}')"
84
+ else
85
+ "MATCH('#{@matching}') AND #{wheres_to_s}"
86
+ end
87
+ end
88
+
89
+ def wheres_to_s
90
+ @wheres.keys.collect { |key|
91
+ "#{key} = #{@wheres[key]}"
92
+ }.join(' AND ')
93
+ end
94
+
95
+ def limit_clause
96
+ if @offset.nil?
97
+ "LIMIT #{@limit}"
98
+ else
99
+ "LIMIT #{@offset}, #{@limit || 20}"
100
+ end
101
+ end
102
+
103
+ def options_clause
104
+ 'OPTION ' + @options.keys.collect { |key|
105
+ "#{key}=#{@options[key]}"
106
+ }.join(', ')
107
+ end
108
+ end
@@ -60,6 +60,8 @@ not. It's just my name: <em>Pat</em>.
60
60
  ]
61
61
  when '1.10'
62
62
  excerpts.should == [" &#8230; really long sentence written by <em>Pat</em>. It has to be over &#8230; . This keyword, however, is\nnot. It's just my name: <em>Pat</em> &#8230; "]
63
+ when '2.0.1'
64
+ excerpts.should == [" &#8230; really long sentence written by <em>Pat</em>. It has to be over &#8230; . It's just my name: <em>Pat</em>.\n"]
63
65
  else
64
66
  excerpts.should == [
65
67
  <<-SENTENCE
@@ -105,6 +107,8 @@ not. It's just my name: <em>Pat</em>.
105
107
  ]
106
108
  when '1.10'
107
109
  excerpts.should == [" --- really long sentence written by <em>Pat</em>. It has to be over --- . This keyword, however, is\nnot. It's just my name: <em>Pat</em> --- "]
110
+ when '2.0.1'
111
+ excerpts.should == [" --- really long sentence written by <em>Pat</em>. It has to be over --- . It's just my name: <em>Pat</em>.\n"]
108
112
  else
109
113
  excerpts.should == [
110
114
  <<-SENTENCE
@@ -1,42 +1,40 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Sphinx Searches" do
4
- before :each do
5
- @client = Riddle::Client.new("localhost", 9313)
6
- end
4
+ let(:client) { Riddle::Client.new 'localhost', 9313 }
7
5
 
8
6
  it "should return a single hash if a single query" do
9
- @client.query("smith").should be_kind_of(Hash)
7
+ client.query("smith").should be_kind_of(Hash)
10
8
  end
11
9
 
12
10
  it "should return an array of hashs if multiple queries are run" do
13
- @client.append_query "smith"
14
- @client.append_query "jones"
15
- results = @client.run
11
+ client.append_query "smith"
12
+ client.append_query "jones"
13
+ results = client.run
16
14
  results.should be_kind_of(Array)
17
15
  results.each { |result| result.should be_kind_of(Hash) }
18
16
  end
19
17
 
20
18
  it "should return an array of matches" do
21
- matches = @client.query("smith")[:matches]
19
+ matches = client.query("smith")[:matches]
22
20
  matches.should be_kind_of(Array)
23
21
  matches.each { |match| match.should be_kind_of(Hash) }
24
22
  end
25
23
 
26
24
  it "should return an array of string fields" do
27
- fields = @client.query("smith")[:fields]
25
+ fields = client.query("smith")[:fields]
28
26
  fields.should be_kind_of(Array)
29
27
  fields.each { |field| field.should be_kind_of(String) }
30
28
  end
31
29
 
32
30
  it "should return an array of attribute names" do
33
- attributes = @client.query("smith")[:attribute_names]
31
+ attributes = client.query("smith")[:attribute_names]
34
32
  attributes.should be_kind_of(Array)
35
33
  attributes.each { |a| a.should be_kind_of(String) }
36
34
  end
37
35
 
38
36
  it "should return a hash of attributes" do
39
- attributes = @client.query("smith")[:attributes]
37
+ attributes = client.query("smith")[:attributes]
40
38
  attributes.should be_kind_of(Hash)
41
39
  attributes.each do |key,value|
42
40
  key.should be_kind_of(String)
@@ -45,19 +43,19 @@ describe "Sphinx Searches" do
45
43
  end
46
44
 
47
45
  it "should return the total number of results returned" do
48
- @client.query("smith")[:total].should be_kind_of(Integer)
46
+ client.query("smith")[:total].should be_kind_of(Integer)
49
47
  end
50
48
 
51
49
  it "should return the total number of results available" do
52
- @client.query("smith")[:total_found].should be_kind_of(Integer)
50
+ client.query("smith")[:total_found].should be_kind_of(Integer)
53
51
  end
54
52
 
55
53
  it "should return the time taken for the query as a float" do
56
- @client.query("smith")[:time].should be_kind_of(Float)
54
+ client.query("smith")[:time].should be_kind_of(Float)
57
55
  end
58
56
 
59
57
  it "should return a hash of the words from the query, with the number of documents and the number of hits" do
60
- words = @client.query("smith victoria")[:words]
58
+ words = client.query("smith victoria")[:words]
61
59
  words.should be_kind_of(Hash)
62
60
  words.each do |word,hash|
63
61
  word.should be_kind_of(String)
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddle::Query::Delete do
4
+ it 'handles a single id' do
5
+ query = Riddle::Query::Delete.new 'foo_core', 5
6
+ query.to_sql.should == 'DELETE FROM foo_core WHERE id = 5'
7
+ end
8
+
9
+ it 'handles multiple ids' do
10
+ query = Riddle::Query::Delete.new 'foo_core', 5, 6, 7
11
+ query.to_sql.should == 'DELETE FROM foo_core WHERE id IN (5, 6, 7)'
12
+ end
13
+
14
+ it 'handles multiple ids in an explicit array' do
15
+ query = Riddle::Query::Delete.new 'foo_core', [5, 6, 7]
16
+ query.to_sql.should == 'DELETE FROM foo_core WHERE id IN (5, 6, 7)'
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddle::Query::Insert do
4
+ it 'handles inserts' do
5
+ query = Riddle::Query::Insert.new('foo_core', [:id, :deleted], [4, false])
6
+ query.to_sql.should == 'INSERT INTO foo_core (id, deleted) VALUES (4, 0)'
7
+ end
8
+
9
+ it 'handles replaces' do
10
+ query = Riddle::Query::Insert.new('foo_core', [:id, :deleted], [4, false])
11
+ query.replace!
12
+ query.to_sql.should == 'REPLACE INTO foo_core (id, deleted) VALUES (4, 0)'
13
+ end
14
+
15
+ it 'encloses strings in single quotes' do
16
+ query = Riddle::Query::Insert.new('foo_core', [:id, :name], [4, 'bar'])
17
+ query.to_sql.should == "INSERT INTO foo_core (id, name) VALUES (4, 'bar')"
18
+ end
19
+
20
+ it 'handles inserts with more than one set of values' do
21
+ query = Riddle::Query::Insert.new 'foo_core', [:id, :name], [[4, 'bar'], [5, 'baz']]
22
+ query.to_sql.
23
+ should == "INSERT INTO foo_core (id, name) VALUES (4, 'bar'), (5, 'baz')"
24
+ end
25
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddle::Query::Select do
4
+ let(:query) { Riddle::Query::Select.new }
5
+
6
+ it 'handles basic queries on a specific index' do
7
+ query.from('foo_core').to_sql.should == 'SELECT * FROM foo_core'
8
+ end
9
+
10
+ it 'handles queries on multiple indices' do
11
+ query.from('foo_core').from('foo_delta').to_sql.
12
+ should == 'SELECT * FROM foo_core, foo_delta'
13
+ end
14
+
15
+ it 'accepts multiple arguments for indices' do
16
+ query.from('foo_core', 'foo_delta').to_sql.
17
+ should == 'SELECT * FROM foo_core, foo_delta'
18
+ end
19
+
20
+ it 'handles basic queries with a search term' do
21
+ query.from('foo_core').matching('foo').to_sql.
22
+ should == "SELECT * FROM foo_core WHERE MATCH('foo')"
23
+ end
24
+
25
+ it 'handles filters with integers' do
26
+ query.from('foo_core').matching('foo').where(:bar_id => 10).to_sql.
27
+ should == "SELECT * FROM foo_core WHERE MATCH('foo') AND bar_id = 10"
28
+ end
29
+
30
+ it 'handles grouping' do
31
+ query.from('foo_core').group_by('bar_id').to_sql.
32
+ should == "SELECT * FROM foo_core GROUP BY bar_id"
33
+ end
34
+
35
+ it 'handles ordering' do
36
+ query.from('foo_core').order_by('bar_id ASC').to_sql.
37
+ should == 'SELECT * FROM foo_core ORDER BY bar_id ASC'
38
+ end
39
+
40
+ it 'handles group ordering' do
41
+ query.from('foo_core').order_within_group_by('bar_id ASC').to_sql.
42
+ should == 'SELECT * FROM foo_core WITHIN GROUP ORDER BY bar_id ASC'
43
+ end
44
+
45
+ it 'handles a limit' do
46
+ query.from('foo_core').limit(10).to_sql.
47
+ should == 'SELECT * FROM foo_core LIMIT 10'
48
+ end
49
+
50
+ it 'handles an offset' do
51
+ query.from('foo_core').offset(20).to_sql.
52
+ should == 'SELECT * FROM foo_core LIMIT 20, 20'
53
+ end
54
+
55
+ it 'handles an option' do
56
+ query.from('foo_core').with_options(:bar => :baz).to_sql.
57
+ should == 'SELECT * FROM foo_core OPTION bar=baz'
58
+ end
59
+
60
+ it 'handles multiple options' do
61
+ query.from('foo_core').with_options(:bar => :baz, :qux => :quux).to_sql.
62
+ should == 'SELECT * FROM foo_core OPTION bar=baz, qux=quux'
63
+ end
64
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Riddle::Query do
4
+ describe '.connection' do
5
+ let(:connection) { Riddle::Query.connection 'localhost', 9306 }
6
+
7
+ it "returns a MySQL Client" do
8
+ connection.should be_a(Mysql2::Client)
9
+ end
10
+
11
+ it "should handle search requests" do
12
+ connection.query(Riddle::Query.tables).first.should == {
13
+ 'Index' => 'people', 'Type' => 'local'
14
+ }
15
+ end
16
+ end
17
+
18
+ describe '.set' do
19
+ it 'handles a single value' do
20
+ Riddle::Query.set('foo', 'bar').should == 'SET GLOBAL foo = bar'
21
+ end
22
+
23
+ it 'handles multiple values' do
24
+ Riddle::Query.set('foo', [1, 2, 3]).should == 'SET GLOBAL foo = (1, 2, 3)'
25
+ end
26
+
27
+ it 'handles non-global settings' do
28
+ Riddle::Query.set('foo', 'bar', false).should == 'SET foo = bar'
29
+ end
30
+ end
31
+
32
+ describe '.snippets' do
33
+ it 'handles a basic request' do
34
+ Riddle::Query.snippets('foo bar baz', 'foo_core', 'foo').
35
+ should == "CALL SNIPPETS('foo bar baz', 'foo_core', 'foo')"
36
+ end
37
+
38
+ it 'handles a request with options' do
39
+ Riddle::Query.snippets('foo bar baz', 'foo_core', 'foo', :around => 5).
40
+ should == "CALL SNIPPETS('foo bar baz', 'foo_core', 'foo', 5 AS around)"
41
+ end
42
+ end
43
+
44
+ describe '.create_function' do
45
+ it 'handles a basic create request' do
46
+ Riddle::Query.create_function('foo', :bigint, 'foo.sh').
47
+ should == "CREATE FUNCTION foo RETURNS BIGINT SONAME 'foo.sh'"
48
+ end
49
+ end
50
+
51
+ describe '.update' do
52
+ it 'handles a basic update request' do
53
+ Riddle::Query.update('foo_core', 5, :deleted => 1).
54
+ should == 'UPDATE foo_core SET deleted = 1 WHERE id = 5'
55
+ end
56
+ end
57
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Riddle::Configuration::Searchd do
4
- if Riddle.loaded_version == '0.9.9' || Riddle.loaded_version == '1.10'
4
+ if Riddle.loaded_version.to_f >= 0.9
5
5
  it "should be invalid without a listen or pid_file" do
6
6
  searchd = Riddle::Configuration::Searchd.new
7
7
  searchd.should_not be_valid
@@ -60,7 +60,7 @@ describe Riddle::Configuration::Searchd do
60
60
  searchd.port = 3312
61
61
  searchd.pid_file = "file.pid"
62
62
 
63
- if Riddle.loaded_version == '0.9.9' || Riddle.loaded_version == '1.10'
63
+ if Riddle.loaded_version.to_f >= 0.9
64
64
  searchd.render.should == <<-SEARCHD
65
65
  searchd
66
66
  {
@@ -85,7 +85,7 @@ searchd
85
85
  searchd.pid_file = 'file.pid'
86
86
  searchd.client_key = 'secret'
87
87
 
88
- if Riddle.loaded_version == '0.9.9' || Riddle.loaded_version == '1.10'
88
+ if Riddle.loaded_version.to_f >= 0.9
89
89
  searchd.render.should == <<-SEARCHD
90
90
  searchd
91
91
  {
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: riddle
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.3.2
5
+ version: 1.3.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Pat Allan
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-12 00:00:00 +10:00
13
+ date: 2011-05-25 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -94,6 +94,10 @@ files:
94
94
  - lib/riddle/configuration/sql_source.rb
95
95
  - lib/riddle/configuration/xml_source.rb
96
96
  - lib/riddle/controller.rb
97
+ - lib/riddle/query.rb
98
+ - lib/riddle/query/delete.rb
99
+ - lib/riddle/query/insert.rb
100
+ - lib/riddle/query/select.rb
97
101
  - spec/functional/connection_spec.rb
98
102
  - spec/functional/excerpt_spec.rb
99
103
  - spec/functional/keywords_spec.rb
@@ -105,6 +109,10 @@ files:
105
109
  - spec/riddle/client_spec.rb
106
110
  - spec/riddle/configuration_spec.rb
107
111
  - spec/riddle/controller_spec.rb
112
+ - spec/riddle/query/delete_spec.rb
113
+ - spec/riddle/query/insert_spec.rb
114
+ - spec/riddle/query/select_spec.rb
115
+ - spec/riddle/query_spec.rb
108
116
  - spec/riddle_spec.rb
109
117
  - spec/spec_helper.rb
110
118
  - spec/sphinx_helper.rb
@@ -136,7 +144,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
144
  requirements:
137
145
  - - ">="
138
146
  - !ruby/object:Gem::Version
139
- hash: -2415930395284714044
147
+ hash: -3668127680877211237
140
148
  segments:
141
149
  - 0
142
150
  version: "0"
@@ -165,6 +173,10 @@ test_files:
165
173
  - spec/riddle/client_spec.rb
166
174
  - spec/riddle/configuration_spec.rb
167
175
  - spec/riddle/controller_spec.rb
176
+ - spec/riddle/query/delete_spec.rb
177
+ - spec/riddle/query/insert_spec.rb
178
+ - spec/riddle/query/select_spec.rb
179
+ - spec/riddle/query_spec.rb
168
180
  - spec/riddle_spec.rb
169
181
  - spec/spec_helper.rb
170
182
  - spec/sphinx_helper.rb