forked from pat/thinking-sphinx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
source_spec.rb
267 lines (217 loc) · 8.17 KB
/
source_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
require 'spec_helper'
describe ThinkingSphinx::Source do
before :each do
@index = ThinkingSphinx::Index.new(Person)
@source = ThinkingSphinx::Source.new(@index, :sql_range_step => 1000)
end
describe '#initialize' do
it "should store the current connection details" do
config = Person.connection.instance_variable_get(:@config)
@source.database_configuration.should == config
end
end
it "should generate the name from the model" do
@source.name.should == "person"
end
it "should handle namespaced models for name generation" do
index = ThinkingSphinx::Index.new(Admin::Person)
source = ThinkingSphinx::Source.new(index)
source.name.should == "admin_person"
end
describe "#to_riddle_for_core" do
before :each do
config = ThinkingSphinx::Configuration.instance
config.source_options[:sql_ranged_throttle] = 100
ThinkingSphinx::Field.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:first_name)
)
ThinkingSphinx::Field.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:last_name)
)
ThinkingSphinx::Attribute.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:id), :as => :internal_id
)
ThinkingSphinx::Attribute.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:birthday)
)
ThinkingSphinx::Attribute.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:tags, :id), :as => :tag_ids
)
ThinkingSphinx::Attribute.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:contacts, :id),
:as => :contact_ids, :source => :query
)
ThinkingSphinx::Attribute.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:source, :id),
:as => :source_id, :type => :integer
)
ThinkingSphinx::Join.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:links)
)
@source.conditions << "`birthday` <= NOW()"
@source.groupings << "`first_name`"
@index.local_options[:group_concat_max_len] = 1024
@riddle = @source.to_riddle_for_core(1, 0)
end
it "should generate a Riddle Source object" do
@riddle.should be_a_kind_of(Riddle::Configuration::SQLSource)
end
it "should use the index and name its own name" do
@riddle.name.should == "person_core_0"
end
it "should use the model's database connection to determine type" do
@riddle.type.should == "mysql"
end
it "should match the model's database settings" do
config = Person.connection.instance_variable_get(:@config)
@riddle.sql_db.should == config[:database]
@riddle.sql_user.should == config[:username]
@riddle.sql_pass.should == config[:password].to_s
@riddle.sql_host.should == config[:host]
@riddle.sql_port.should == config[:port]
@riddle.sql_sock.should == config[:socket]
@riddle.mysql_ssl_ca.should == config[:sslca]
@riddle.mysql_ssl_cert.should == config[:sslcert]
@riddle.mysql_ssl_key.should == config[:sslkey]
end
it "should use a environment user if nothing else is provided" do
Person.connection.stub!(:instance_variable_get => {
:user => nil,
:username => nil
})
@source = ThinkingSphinx::Source.new(@index)
riddle = @source.to_riddle_for_core(1, 0)
riddle.sql_user.should == ENV['USER']
end
it "should assign attributes" do
# 3 internal attributes plus the one requested
@riddle.sql_attr_uint.length.should == 4
@riddle.sql_attr_uint.last.should == :internal_id
@riddle.sql_attr_timestamp.length.should == 1
@riddle.sql_attr_timestamp.first.should == :birthday
end
it "should not include an attribute definition for polymorphic references without data" do
@riddle.sql_attr_uint.select { |uint|
uint == :source_id
}.should be_empty
end
it "should set Sphinx Source options" do
@riddle.sql_range_step.should == 1000
@riddle.sql_ranged_throttle.should == 100
end
describe "#sql_query" do
before :each do
@query = @riddle.sql_query
end
it "should select data from the model table" do
@query.should match(/FROM\s+`people`/)
end
it "should select each of the fields" do
@query.should match(/`first_name`.+FROM/)
@query.should match(/`last_name`.+FROM/)
end
it "should select each of the attributes" do
@query.should match(/`id` AS `internal_id`.+FROM/)
@query.should match(/`birthday`.+FROM/)
@query.should match(/`tags`.`id`.+ AS `tag_ids`.+FROM/)
end
it "should not match the sourced MVA attribute" do
@query.should_not match(/contact_ids/)
end
it "should include joins for required associations" do
@query.should match(/LEFT OUTER JOIN `tags`/)
end
it "should not include joins for the sourced MVA attribute" do
@query.should_not match(/LEFT OUTER JOIN `contacts`/)
end
it "should include explicitly requested joins" do
@query.should match(/LEFT OUTER JOIN `links`/)
end
it "should include any defined conditions" do
@query.should match(/WHERE.+`birthday` <= NOW()/)
end
it "should include any defined groupings" do
@query.should match(/GROUP BY.+`first_name`/)
end
it "should include descendants" do
index = ThinkingSphinx::Index.new(Child)
source = ThinkingSphinx::Source.new(index, :sql_range_step => 1000)
riddle = source.to_riddle_for_core(1, 0)
query = riddle.sql_query
query.should match(/WHERE.+`people`\.`type`.+'Child'.+ 'Teenager'\)/)
query.should_not match(/WHERE.+"users"."type" = 'Employee'/)
end
end
describe "#sql_query_range" do
before :each do
@query = @riddle.sql_query_range
end
it "should select data from the model table" do
@query.should match(/FROM `people`/)
end
it "should select the minimum and the maximum ids" do
@query.should match(/SELECT.+MIN.+MAX.+FROM/)
end
end
describe "#sql_query_info" do
before :each do
@query = @riddle.sql_query_info
end
it "should select all fields from the model table" do
@query.should match(/SELECT \* FROM `people`/)
end
it "should filter the primary key with the offset" do
model_count = ThinkingSphinx.context.indexed_models.size
@query.should match(/WHERE `id` = \(\(\$id - 1\) \/ #{model_count}\)/)
end
end
describe "#sql_query_pre" do
before :each do
@queries = @riddle.sql_query_pre
end
it "should default to just the UTF8 statement" do
@queries.detect { |query|
query == "SET NAMES utf8"
}.should_not be_nil
end
it "should set the group_concat_max_len session value for MySQL if requested" do
@queries.detect { |query|
query == "SET SESSION group_concat_max_len = 1024"
}.should_not be_nil
end
end
end
describe "#to_riddle_for_core with range disabled" do
before :each do
ThinkingSphinx::Field.new(
@source, ThinkingSphinx::Index::FauxColumn.new(:first_name)
)
end
describe "set per-index" do
before :each do
@index.local_options[:disable_range] = true
@riddle = @source.to_riddle_for_core(1, 0)
end
it "should not have the range in the sql_query" do
@riddle.sql_query.should_not match(/`people`.`id` >= \$start/)
@riddle.sql_query.should_not match(/`people`.`id` <= \$end/)
end
it "should not have a sql_query_range" do
@riddle.sql_query_range.should be_nil
end
end
describe "set globally" do
before :each do
ThinkingSphinx::Configuration.instance.index_options[:disable_range] = true
@riddle = @source.to_riddle_for_core(1, 0)
end
it "should not have the range in the sql_query" do
@riddle.sql_query.should_not match(/`people`.`id` >= \$start/)
@riddle.sql_query.should_not match(/`people`.`id` <= \$end/)
end
it "should not have a sql_query_range" do
@riddle.sql_query_range.should be_nil
end
end
end
end