thinking-sphinx 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +29 -20
  4. data/Appraisals +9 -5
  5. data/Gemfile +8 -3
  6. data/HISTORY +24 -0
  7. data/README.textile +5 -4
  8. data/bin/console +14 -0
  9. data/bin/literals +9 -0
  10. data/bin/loadsphinx +38 -0
  11. data/lib/thinking_sphinx.rb +15 -2
  12. data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +2 -3
  13. data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +11 -1
  14. data/lib/thinking_sphinx/active_record/index.rb +1 -1
  15. data/lib/thinking_sphinx/active_record/join_association.rb +3 -1
  16. data/lib/thinking_sphinx/active_record/log_subscriber.rb +5 -0
  17. data/lib/thinking_sphinx/active_record/sql_source.rb +1 -1
  18. data/lib/thinking_sphinx/attribute_types.rb +70 -0
  19. data/lib/thinking_sphinx/commands/base.rb +41 -0
  20. data/lib/thinking_sphinx/commands/configure.rb +13 -0
  21. data/lib/thinking_sphinx/commands/index.rb +11 -0
  22. data/lib/thinking_sphinx/commands/start_attached.rb +20 -0
  23. data/lib/thinking_sphinx/commands/start_detached.rb +19 -0
  24. data/lib/thinking_sphinx/commands/stop.rb +22 -0
  25. data/lib/thinking_sphinx/configuration.rb +36 -28
  26. data/lib/thinking_sphinx/configuration/minimum_fields.rb +11 -8
  27. data/lib/thinking_sphinx/connection.rb +5 -122
  28. data/lib/thinking_sphinx/connection/client.rb +48 -0
  29. data/lib/thinking_sphinx/connection/jruby.rb +53 -0
  30. data/lib/thinking_sphinx/connection/mri.rb +28 -0
  31. data/lib/thinking_sphinx/core/index.rb +11 -0
  32. data/lib/thinking_sphinx/deletion.rb +6 -2
  33. data/lib/thinking_sphinx/deltas/default_delta.rb +1 -1
  34. data/lib/thinking_sphinx/deltas/delete_job.rb +14 -4
  35. data/lib/thinking_sphinx/distributed/index.rb +10 -0
  36. data/lib/thinking_sphinx/errors.rb +1 -1
  37. data/lib/thinking_sphinx/index_set.rb +14 -2
  38. data/lib/thinking_sphinx/interfaces/daemon.rb +32 -0
  39. data/lib/thinking_sphinx/interfaces/real_time.rb +41 -0
  40. data/lib/thinking_sphinx/interfaces/sql.rb +41 -0
  41. data/lib/thinking_sphinx/middlewares.rb +5 -3
  42. data/lib/thinking_sphinx/middlewares/active_record_translator.rb +13 -6
  43. data/lib/thinking_sphinx/middlewares/attribute_typer.rb +48 -0
  44. data/lib/thinking_sphinx/middlewares/valid_options.rb +23 -0
  45. data/lib/thinking_sphinx/rake_interface.rb +10 -124
  46. data/lib/thinking_sphinx/search.rb +11 -0
  47. data/lib/thinking_sphinx/search/query.rb +7 -1
  48. data/lib/thinking_sphinx/tasks.rb +80 -21
  49. data/lib/thinking_sphinx/with_output.rb +11 -0
  50. data/spec/acceptance/connection_spec.rb +4 -4
  51. data/spec/acceptance/searching_within_a_model_spec.rb +7 -0
  52. data/spec/acceptance/specifying_sql_spec.rb +26 -8
  53. data/spec/acceptance/sql_deltas_spec.rb +12 -0
  54. data/spec/internal/app/indices/album_index.rb +3 -0
  55. data/spec/internal/app/models/album.rb +19 -0
  56. data/spec/internal/db/schema.rb +8 -0
  57. data/spec/spec_helper.rb +4 -0
  58. data/spec/support/json_column.rb +5 -1
  59. data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +5 -1
  60. data/spec/thinking_sphinx/active_record/sql_source_spec.rb +6 -0
  61. data/spec/thinking_sphinx/attribute_types_spec.rb +50 -0
  62. data/spec/thinking_sphinx/commands/configure_spec.rb +29 -0
  63. data/spec/thinking_sphinx/commands/index_spec.rb +26 -0
  64. data/spec/thinking_sphinx/commands/start_detached_spec.rb +55 -0
  65. data/spec/thinking_sphinx/commands/stop_spec.rb +54 -0
  66. data/spec/thinking_sphinx/configuration/minimum_fields_spec.rb +36 -0
  67. data/spec/thinking_sphinx/deletion_spec.rb +2 -5
  68. data/spec/thinking_sphinx/deltas/default_delta_spec.rb +1 -1
  69. data/spec/thinking_sphinx/errors_spec.rb +7 -0
  70. data/spec/thinking_sphinx/index_set_spec.rb +30 -7
  71. data/spec/thinking_sphinx/interfaces/daemon_spec.rb +52 -0
  72. data/spec/thinking_sphinx/interfaces/real_time_spec.rb +109 -0
  73. data/spec/thinking_sphinx/interfaces/sql_spec.rb +98 -0
  74. data/spec/thinking_sphinx/middlewares/attribute_typer_spec.rb +42 -0
  75. data/spec/thinking_sphinx/middlewares/valid_options_spec.rb +49 -0
  76. data/spec/thinking_sphinx/rake_interface_spec.rb +13 -246
  77. data/spec/thinking_sphinx/search/query_spec.rb +7 -0
  78. data/thinking-sphinx.gemspec +5 -4
  79. metadata +72 -16
  80. data/gemfiles/.gitignore +0 -1
  81. data/gemfiles/rails_3_2.gemfile +0 -13
  82. data/gemfiles/rails_4_0.gemfile +0 -13
  83. data/gemfiles/rails_4_1.gemfile +0 -13
  84. data/gemfiles/rails_4_2.gemfile +0 -13
  85. data/gemfiles/rails_5_0.gemfile +0 -12
@@ -0,0 +1,23 @@
1
+ class ThinkingSphinx::Middlewares::ValidOptions <
2
+ ThinkingSphinx::Middlewares::Middleware
3
+
4
+ def call(contexts)
5
+ contexts.each { |context| check_options context.search.options }
6
+
7
+ app.call contexts
8
+ end
9
+
10
+ private
11
+
12
+ def check_options(options)
13
+ unknown = invalid_keys options.keys
14
+ return if unknown.empty?
15
+
16
+ ThinkingSphinx::Logger.log :warn,
17
+ "Unexpected search options: #{unknown.inspect}"
18
+ end
19
+
20
+ def invalid_keys(keys)
21
+ keys - ThinkingSphinx::Search.valid_options
22
+ end
23
+ end
@@ -1,146 +1,32 @@
1
1
  class ThinkingSphinx::RakeInterface
2
+ DEFAULT_OPTIONS = {:verbose => true}
3
+
2
4
  def initialize(options = {})
3
- @options = options
5
+ @options = DEFAULT_OPTIONS.merge options
4
6
  @options[:verbose] = false if @options[:silent]
5
7
  end
6
8
 
7
- def clear_all
8
- [
9
- configuration.indices_location,
10
- configuration.searchd.binlog_path
11
- ].each do |path|
12
- FileUtils.rm_r(path) if File.exists?(path)
13
- end
14
- end
15
-
16
- def clear_real_time
17
- configuration.preload_indices
18
- indices = configuration.indices.select { |index| index.type == 'rt' }
19
- indices.each do |index|
20
- index.render
21
- Dir["#{index.path}.*"].each { |path| FileUtils.rm path }
22
- end
23
-
24
- path = configuration.searchd.binlog_path
25
- FileUtils.rm_r(path) if File.exists?(path)
26
- end
27
-
28
9
  def configure
29
- log "Generating configuration to #{configuration.configuration_file}"
30
- configuration.render_to_file
31
- end
32
-
33
- def generate
34
- indices = configuration.indices.select { |index| index.type == 'rt' }
35
- indices.each do |index|
36
- ThinkingSphinx::RealTime::Populator.populate index
37
- end
10
+ ThinkingSphinx::Commands::Configure.call configuration, options
38
11
  end
39
12
 
40
- def index(reconfigure = true, verbose = true)
41
- configure if reconfigure
42
- FileUtils.mkdir_p configuration.indices_location
43
- ThinkingSphinx.before_index_hooks.each { |hook| hook.call }
44
- controller.index :verbose => verbose
45
- rescue Riddle::CommandFailedError => error
46
- handle_command_failure 'indexing', error.command_result
13
+ def daemon
14
+ @daemon ||= ThinkingSphinx::Interfaces::Daemon.new configuration, options
47
15
  end
48
16
 
49
- def prepare
50
- configuration.preload_indices
51
- configuration.render
52
-
53
- FileUtils.mkdir_p configuration.indices_location
17
+ def rt
18
+ @rt ||= ThinkingSphinx::Interfaces::RealTime.new configuration, options
54
19
  end
55
20
 
56
- def start
57
- if running?
58
- raise ThinkingSphinx::SphinxAlreadyRunning, 'searchd is already running'
59
- end
60
-
61
- FileUtils.mkdir_p configuration.indices_location
62
-
63
- options[:nodetach] ? start_attached : start_detached
64
- end
65
-
66
- def status
67
- if running?
68
- puts "The Sphinx daemon searchd is currently running."
69
- else
70
- puts "The Sphinx daemon searchd is not currently running."
71
- end
72
- end
73
-
74
- def stop
75
- unless running?
76
- log 'searchd is not currently running.' and return
77
- end
78
-
79
- pid = controller.pid
80
- until !running? do
81
- controller.stop options
82
- sleep(0.5)
83
- end
84
-
85
- log "Stopped searchd daemon (pid: #{pid})."
86
- rescue Riddle::CommandFailedError => error
87
- handle_command_failure 'stop', error.command_result
21
+ def sql
22
+ @sql ||= ThinkingSphinx::Interfaces::SQL.new configuration, options
88
23
  end
89
24
 
90
25
  private
91
26
 
92
27
  attr_reader :options
93
28
 
94
- delegate :controller, :to => :configuration
95
- delegate :running?, :to => :controller
96
-
97
- def command_output(output)
98
- return "See above\n" if output.nil?
99
-
100
- "\n\t" + output.gsub("\n", "\n\t")
101
- end
102
-
103
29
  def configuration
104
30
  ThinkingSphinx::Configuration.instance
105
31
  end
106
-
107
- def handle_command_failure(type, result)
108
- puts <<-TXT
109
-
110
- The Sphinx #{type} command failed:
111
- Command: #{result.command}
112
- Status: #{result.status}
113
- Output: #{command_output result.output}
114
- There may be more information about the failure in #{configuration.searchd.log}.
115
- TXT
116
- exit result.status
117
- end
118
-
119
- def log(message)
120
- return if options[:silent]
121
-
122
- puts message
123
- end
124
-
125
- def start_attached
126
- unless pid = fork
127
- controller.start :verbose => options[:verbose]
128
- end
129
-
130
- Signal.trap('TERM') { Process.kill(:TERM, pid); }
131
- Signal.trap('INT') { Process.kill(:TERM, pid); }
132
- Process.wait(pid)
133
- end
134
-
135
- def start_detached
136
- result = controller.start :verbose => options[:verbose]
137
-
138
- if running?
139
- log "Started searchd successfully (pid: #{controller.pid})."
140
- else
141
- handle_command_failure 'start', result
142
- end
143
- rescue Riddle::CommandFailedError => error
144
- handle_command_failure 'start', error.command_result
145
- end
146
32
  end
@@ -21,6 +21,17 @@ class ThinkingSphinx::Search < Array
21
21
  attr_reader :options
22
22
  attr_accessor :query
23
23
 
24
+ def self.valid_options
25
+ @valid_options
26
+ end
27
+
28
+ @valid_options = [
29
+ :classes, :conditions, :geo, :group_by, :ids_only, :ignore_scopes, :indices,
30
+ :limit, :masks, :max_matches, :middleware, :offset, :order, :order_group_by,
31
+ :page, :per_page, :populate, :retry_stale, :select, :skip_sti, :sql, :star,
32
+ :with, :with_all, :without, :without_ids
33
+ ]
34
+
24
35
  def initialize(query = nil, options = {})
25
36
  query, options = nil, query if query.is_a?(Hash)
26
37
  @query, @options = query, options
@@ -10,12 +10,18 @@ class ThinkingSphinx::Search::Query
10
10
  (star_keyword(keywords || '') + ' ' + conditions.keys.collect { |key|
11
11
  next if conditions[key].blank?
12
12
 
13
- "@#{key} #{star_keyword conditions[key], key}"
13
+ "#{expand_key key} #{star_keyword conditions[key], key}"
14
14
  }.join(' ')).strip
15
15
  end
16
16
 
17
17
  private
18
18
 
19
+ def expand_key(key)
20
+ return "@#{key}" unless key.is_a?(Array)
21
+
22
+ "@(#{key.join(',')})"
23
+ end
24
+
19
25
  def star_keyword(keyword, key = nil)
20
26
  return keyword.to_s unless star
21
27
  return keyword.to_s if key.to_s == 'sphinx_internal_class_name'
@@ -5,55 +5,114 @@ namespace :ts do
5
5
  end
6
6
 
7
7
  desc 'Generate the Sphinx configuration file and process all indices'
8
- task :index => :environment do
9
- interface.index(ENV['INDEX_ONLY'] != 'true')
10
- end
8
+ task :index => ['ts:sql:index', 'ts:rt:index']
11
9
 
12
10
  desc 'Clear out Sphinx files'
13
- task :clear => :environment do
14
- interface.clear_all
15
- end
11
+ task :clear => ['ts:sql:clear', 'ts:rt:clear']
16
12
 
17
- desc 'Clear out real-time index files'
13
+ desc 'DEPRECATED: Clear out real-time index files'
18
14
  task :clear_rt => :environment do
19
- interface.clear_real_time
15
+ puts <<-TXT
16
+ The ts:clear_rt task is now deprecated due to the unified task approach, and
17
+ invokes ts:rt:clear.
18
+ * To delete all indices (both SQL-backed and real-time), use ts:clear.
19
+ * To delete just real-time indices, use ts:rt:clear.
20
+ * To delete just SQL-backed indices, use ts:sql:clear.
21
+
22
+ TXT
23
+
24
+ Rake::Task['ts:rt:clear'].invoke
20
25
  end
21
26
 
22
- desc 'Generate fresh index files for real-time indices'
27
+ desc 'DEPRECATED: Generate fresh index files for all indices'
23
28
  task :generate => :environment do
24
- interface.prepare
25
- interface.generate
29
+ puts <<-TXT
30
+ The ts:generate task is now deprecated due to the unified task approach, and
31
+ invokes ts:index.
32
+ * To process all indices (both SQL-backed and real-time), use ts:index.
33
+ * To process just real-time indices, use ts:rt:index.
34
+ * To process just SQL-backed indices, use ts:sql:index.
35
+
36
+ TXT
37
+
38
+ Rake::Task['ts:index'].invoke
26
39
  end
27
40
 
28
- desc 'Stop Sphinx, index and then restart Sphinx'
29
- task :rebuild => [:stop, :clear, :index, :start]
41
+ desc 'Delete and regenerate Sphinx files, restart the daemon'
42
+ task :rebuild => [
43
+ :stop, :clear, :configure, 'ts:sql:index', :start, 'ts:rt:index'
44
+ ]
45
+
46
+ desc 'DEPRECATED: Delete and regenerate Sphinx files, restart the daemon'
47
+ task :regenerate do
48
+ puts <<-TXT
49
+ The ts:regenerate task is now deprecated due to the unified task approach, and
50
+ invokes ts:rebuild.
51
+ * To rebuild all indices (both SQL-backed and real-time), use ts:rebuild.
52
+ * To rebuild just real-time indices, use ts:rt:rebuild.
53
+ * To rebuild just SQL-backed indices, use ts:sql:rebuild.
30
54
 
31
- desc 'Stop Sphinx, clear files, reconfigure, start Sphinx, generate files'
32
- task :regenerate => [:stop, :clear_rt, :configure, :start, :generate]
55
+ TXT
56
+
57
+ Rake::Task['ts:rebuild'].invoke
58
+ end
33
59
 
34
60
  desc 'Restart the Sphinx daemon'
35
61
  task :restart => [:stop, :start]
36
62
 
37
63
  desc 'Start the Sphinx daemon'
38
64
  task :start => :environment do
39
- interface.start
65
+ interface.daemon.start
40
66
  end
41
67
 
42
68
  desc 'Stop the Sphinx daemon'
43
69
  task :stop => :environment do
44
- interface.stop
70
+ interface.daemon.stop
45
71
  end
46
72
 
47
73
  desc 'Determine whether Sphinx is running'
48
74
  task :status => :environment do
49
- interface.status
75
+ interface.daemon.status
76
+ end
77
+
78
+ namespace :sql do
79
+ desc 'Delete SQL-backed Sphinx files'
80
+ task :clear => :environment do
81
+ interface.sql.clear
82
+ end
83
+
84
+ desc 'Generate fresh index files for SQL-backed indices'
85
+ task :index => :environment do
86
+ interface.sql.index(ENV['INDEX_ONLY'] != 'true')
87
+ end
88
+
89
+ desc 'Delete and regenerate SQL-backed Sphinx files, restart the daemon'
90
+ task :rebuild => ['ts:stop', 'ts:sql:clear', 'ts:sql:index', 'ts:start']
91
+ end
92
+
93
+ namespace :rt do
94
+ desc 'Delete real-time Sphinx files'
95
+ task :clear => :environment do
96
+ interface.rt.clear
97
+ end
98
+
99
+ desc 'Generate fresh index files for real-time indices'
100
+ task :index => :environment do
101
+ interface.rt.index
102
+ end
103
+
104
+ desc 'Delete and regenerate real-time Sphinx files, restart the daemon'
105
+ task :rebuild => [
106
+ 'ts:stop', 'ts:rt:clear', 'ts:configure', 'ts:start', 'ts:rt:index'
107
+ ]
50
108
  end
51
109
 
52
110
  def interface
53
111
  @interface ||= ThinkingSphinx::RakeInterface.new(
54
- :verbose => Rake::FileUtilsExt.verbose_flag,
55
- :silent => Rake.application.options.silent,
56
- :nodetach => (ENV['NODETACH'] == 'true')
112
+ :verbose => Rake::FileUtilsExt.verbose_flag,
113
+ :silent => Rake.application.options.silent,
114
+ :nodetach => (ENV['NODETACH'] == 'true'),
115
+ :index_filter => ENV['INDEX_FILTER']
57
116
  )
58
117
  end
59
118
  end
@@ -0,0 +1,11 @@
1
+ module ThinkingSphinx::WithOutput
2
+ def initialize(configuration, options = {}, stream = STDOUT)
3
+ @configuration = configuration
4
+ @options = options
5
+ @stream = stream
6
+ end
7
+
8
+ private
9
+
10
+ attr_reader :configuration, :options, :stream
11
+ end
@@ -1,8 +1,8 @@
1
1
  require 'acceptance/spec_helper'
2
2
 
3
3
  RSpec.describe 'Connections', :live => true do
4
- let(:maximum) { (2 ** 23) - 1 }
5
- let(:query) { "SELECT * FROM book_core WHERE MATCH('')" }
4
+ let(:maximum) { (2 ** 23) - 5 }
5
+ let(:query) { String.new "SELECT * FROM book_core WHERE MATCH('')" }
6
6
  let(:difference) { maximum - query.length }
7
7
 
8
8
  it 'allows normal length queries through' do
@@ -10,13 +10,13 @@ RSpec.describe 'Connections', :live => true do
10
10
  ThinkingSphinx::Connection.take do |connection|
11
11
  connection.execute query.insert(-3, 'a' * difference)
12
12
  end
13
- }.to_not raise_error#(ThinkingSphinx::QueryLengthError)
13
+ }.to_not raise_error
14
14
  end
15
15
 
16
16
  it 'does not allow overly long queries' do
17
17
  expect {
18
18
  ThinkingSphinx::Connection.take do |connection|
19
- connection.execute query.insert(-3, 'a' * (difference + 1))
19
+ connection.execute query.insert(-3, 'a' * (difference + 5))
20
20
  end
21
21
  }.to raise_error(ThinkingSphinx::QueryLengthError)
22
22
  end
@@ -79,6 +79,13 @@ describe 'Searching within a model', :live => true do
79
79
  Category.search.to_a
80
80
  }.to raise_error(ThinkingSphinx::NoIndicesError)
81
81
  end
82
+
83
+ it "handles models with alternative id columns" do
84
+ album = Album.create! :name => 'The Seldom Seen Kid', :artist => 'Elbow'
85
+ index
86
+
87
+ expect(Album.search.first).to eq(album)
88
+ end
82
89
  end
83
90
 
84
91
  describe 'Searching within a model with a realtime index', :live => true do
@@ -155,9 +155,27 @@ describe 'specifying SQL for index definitions' do
155
155
  expect(query).to match(/LEFT OUTER JOIN .users. ON .users.\..id. = .articles.\..user_id./)
156
156
  expect(query).to match(/.users.\..name./)
157
157
  end
158
+
159
+ it "allows for STI mixed with polymorphic joins" do
160
+ index = ThinkingSphinx::ActiveRecord::Index.new(:event)
161
+ index.definition_block = Proc.new {
162
+ indexes eventable.name, :as => :name
163
+ polymorphs eventable, :to => %w(Bird Car)
164
+ }
165
+ index.render
166
+
167
+ query = index.sources.first.sql_query
168
+ expect(query).to match(/LEFT OUTER JOIN .animals. ON .animals.\..id. = .events.\..eventable_id. .* AND .events.\..eventable_type. = 'Animal'/)
169
+ expect(query).to match(/LEFT OUTER JOIN .cars. ON .cars.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Car'/)
170
+ expect(query).to match(/.animals.\..name., .cars.\..name./)
171
+ end
158
172
  end if ActiveRecord::VERSION::MAJOR > 3
159
173
 
160
174
  describe 'separate queries for MVAs' do
175
+ def id_type
176
+ ActiveRecord::VERSION::STRING.to_f > 5.0 ? 'bigint' : 'uint'
177
+ end
178
+
161
179
  let(:index) { ThinkingSphinx::ActiveRecord::Index.new(:article) }
162
180
  let(:count) { ThinkingSphinx::Configuration.instance.indices.count }
163
181
  let(:source) { index.sources.first }
@@ -174,7 +192,7 @@ describe 'separate queries for MVAs' do
174
192
  }
175
193
  declaration, query = attribute.split(/;\s+/)
176
194
 
177
- expect(declaration).to eq('uint tag_ids from query')
195
+ expect(declaration).to eq("uint tag_ids from query")
178
196
  expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)$/)
179
197
  end
180
198
 
@@ -190,7 +208,7 @@ describe 'separate queries for MVAs' do
190
208
  }
191
209
  declaration, query = attribute.split(/;\s+/)
192
210
 
193
- expect(declaration).to eq('uint tag_ids from query')
211
+ expect(declaration).to eq("#{id_type} tag_ids from query")
194
212
  expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
195
213
  end
196
214
 
@@ -206,7 +224,7 @@ describe 'separate queries for MVAs' do
206
224
  }
207
225
  declaration, query = attribute.split(/;\s+/)
208
226
 
209
- expect(declaration).to eq('uint tag_ids from query')
227
+ expect(declaration).to eq("#{id_type} tag_ids from query")
210
228
  expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
211
229
  end
212
230
 
@@ -224,7 +242,7 @@ describe 'separate queries for MVAs' do
224
242
  }
225
243
  declaration, query = attribute.split(/;\s+/)
226
244
 
227
- expect(declaration).to eq('uint tag_ids from query')
245
+ expect(declaration).to eq("#{id_type} tag_ids from query")
228
246
  expect(query).to match(/^SELECT .articles.\..user_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .articles. INNER JOIN .taggings. ON .taggings.\..article_id. = .articles.\..id. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.articles.\..user_id. IS NOT NULL\)\s?$/)
229
247
  end
230
248
 
@@ -242,7 +260,7 @@ describe 'separate queries for MVAs' do
242
260
  }
243
261
  declaration, query = attribute.split(/;\s+/)
244
262
 
245
- expect(declaration).to eq('uint genre_ids from query')
263
+ expect(declaration).to eq("#{id_type} genre_ids from query")
246
264
  expect(query).to match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres.\s?$/)
247
265
  end if ActiveRecord::VERSION::MAJOR > 3
248
266
 
@@ -258,7 +276,7 @@ describe 'separate queries for MVAs' do
258
276
  }
259
277
  declaration, query, range = attribute.split(/;\s+/)
260
278
 
261
- expect(declaration).to eq('uint tag_ids from ranged-query')
279
+ expect(declaration).to eq("uint tag_ids from ranged-query")
262
280
  expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
263
281
  expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
264
282
  end
@@ -275,7 +293,7 @@ describe 'separate queries for MVAs' do
275
293
  }
276
294
  declaration, query, range = attribute.split(/;\s+/)
277
295
 
278
- expect(declaration).to eq('uint tag_ids from ranged-query')
296
+ expect(declaration).to eq("#{id_type} tag_ids from ranged-query")
279
297
  expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
280
298
  expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
281
299
  end
@@ -294,7 +312,7 @@ describe 'separate queries for MVAs' do
294
312
  }
295
313
  declaration, query, range = attribute.split(/;\s+/)
296
314
 
297
- expect(declaration).to eq('uint genre_ids from ranged-query')
315
+ expect(declaration).to eq("#{id_type} genre_ids from ranged-query")
298
316
  expect(query).to match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres. WHERE \(.books_genres.\..book_id. BETWEEN \$start AND \$end\)$/)
299
317
  expect(range).to match(/^SELECT MIN\(.books_genres.\..book_id.\), MAX\(.books_genres.\..book_id.\) FROM .books_genres.$/)
300
318
  end if ActiveRecord::VERSION::MAJOR > 3