appstats 0.18.0 → 0.19.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.
- data/Gemfile.lock +1 -1
- data/db/migrations/20110321154125_add_appstats_results_query_duration_in_seconds.rb +11 -0
- data/db/schema.rb +3 -1
- data/lib/appstats.rb +1 -0
- data/lib/appstats/friendly_timer.rb +52 -0
- data/lib/appstats/query.rb +6 -1
- data/lib/appstats/result.rb +12 -2
- data/lib/appstats/version.rb +1 -1
- data/spec/entry_spec.rb +8 -8
- data/spec/friendly_timer_spec.rb +174 -0
- data/spec/logger_spec.rb +22 -22
- data/spec/query_spec.rb +669 -644
- data/spec/result_spec.rb +46 -1
- metadata +8 -4
data/spec/query_spec.rb
CHANGED
@@ -7,660 +7,685 @@ module Appstats
|
|
7
7
|
Time.stub!(:now).and_return(Time.parse('2010-09-21 23:15:20'))
|
8
8
|
end
|
9
9
|
|
10
|
-
describe "#initialize" do
|
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
|
-
end
|
124
|
-
|
10
|
+
# describe "#initialize" do
|
11
|
+
#
|
12
|
+
# before(:each) do
|
13
|
+
# @query = Appstats::Query.new
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# it "should set input to nil" do
|
17
|
+
# @query.query.should == nil
|
18
|
+
# @query.query_type.should == nil
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# describe "query_type" do
|
22
|
+
#
|
23
|
+
# it "should allow simple objects" do
|
24
|
+
# query = Appstats::Query.new(:query => "# logins", :query_type => "YetAnotherTestQuery")
|
25
|
+
# query.query.should == "# logins"
|
26
|
+
# query.query_type.should == "YetAnotherTestQuery"
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# it "should allow modules" do
|
30
|
+
# query = Appstats::Query.new(:query => "# logins", :query_type => "Appstats::TestQuery")
|
31
|
+
# query.query.should == "# logins"
|
32
|
+
# query.query_type.should == "Appstats::TestQuery"
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# it "should allow sub modules" do
|
36
|
+
# query = Appstats::Query.new(:query => "# logins", :query_type => "Appstats::Core::AnotherTestQuery")
|
37
|
+
# query.query.should == "# logins"
|
38
|
+
# query.query_type.should == "Appstats::Core::AnotherTestQuery"
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# it "should fail for invalid query type" do
|
42
|
+
#
|
43
|
+
# lambda { Appstats::Query.new(:query => "# logins", :query_type => "x") }.should raise_error
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# describe "default query type" do
|
49
|
+
#
|
50
|
+
# it "should set the inputs to nil if input invalid" do
|
51
|
+
# query = Appstats::Query.new(:query => "# myblahs today on xyz.localnet")
|
52
|
+
# query.query = nil
|
53
|
+
# query.action.should == nil
|
54
|
+
# query.host.should == nil
|
55
|
+
# query.date_range.should == DateRange.new
|
56
|
+
# query.group_by.should == []
|
57
|
+
# query.group_query_to_sql.should == nil
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# it "should set the action and host" do
|
61
|
+
# query = Appstats::Query.new(:query => "# myblahs today on xyz.localnet")
|
62
|
+
# query.action.should == "myblahs"
|
63
|
+
# query.host.should == "xyz.localnet"
|
64
|
+
# query.date_range.should == DateRange.parse("today")
|
65
|
+
# query.group_by.should == []
|
66
|
+
# query.group_query_to_sql.should == nil
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# it "should understand the short hand 'on' instead of 'on server'" do
|
70
|
+
# query = Appstats::Query.new(:query => "# myblahs on xyz.localnet")
|
71
|
+
# query.action.should == "myblahs"
|
72
|
+
# query.host.should == "xyz.localnet"
|
73
|
+
# query.date_range.should == DateRange.new
|
74
|
+
# query.group_by.should == []
|
75
|
+
# query.group_query_to_sql.should == nil
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# it "should understand the old 'on server' instead of new 'on'" do
|
79
|
+
# query = Appstats::Query.new(:query => "# myblahs on server xyz.localnet")
|
80
|
+
# query.action.should == "myblahs"
|
81
|
+
# query.host.should == "xyz.localnet"
|
82
|
+
# query.date_range.should == DateRange.new
|
83
|
+
# query.group_by.should == []
|
84
|
+
# query.group_query_to_sql.should == nil
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# describe "group by" do
|
88
|
+
#
|
89
|
+
# it "should handle single entry" do
|
90
|
+
# query = Appstats::Query.new(:query => "# myblahs group by aa")
|
91
|
+
# query.group_by.should == ["aa"]
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# it "should handle multi-entry" do
|
95
|
+
# query = Appstats::Query.new(:query => "# myblahs group by aa,bbbb")
|
96
|
+
# query.group_by.should == ["aa","bbbb"]
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# describe "contexts" do
|
102
|
+
#
|
103
|
+
# it "should handle single entry" do
|
104
|
+
# query = Appstats::Query.new(:query => "# myblahs where aa = bb or aa < ccc")
|
105
|
+
# query.contexts.should == "aa = bb or aa < ccc"
|
106
|
+
# query.parsed_contexts.should == [ { :context_key => "aa", :comparator => "=", :context_value => "bb" }, "or", { :context_key => "aa", :comparator => "<", :context_value => "ccc" } ]
|
107
|
+
# end
|
108
|
+
#
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# describe "distinct query_type" do
|
114
|
+
#
|
115
|
+
# it "should use sql query_type queries" do
|
116
|
+
# query = Appstats::Query.new(:query => "# stuff", :query_type => "Appstats::TestQuery")
|
117
|
+
# query.query_to_sql.should == "select count(*) as num from appstats_test_objects"
|
118
|
+
# query.group_query_to_sql.should == "select context_key_filter, context_value_filter, count(*) as num from (select 'name' as context_key_filter, name as context_value_filter from appstats_test_objects) results group by context_value_filter"
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
# end
|
124
|
+
#
|
125
125
|
describe "#run" do
|
126
126
|
|
127
127
|
before(:each) do
|
128
128
|
Appstats::Entry.delete_all
|
129
129
|
end
|
130
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
|
-
Appstats::Entry.create_from_logger("myblahs", :one => "111", :two => "22")
|
179
|
-
|
180
|
-
query = Appstats::Query.new(:query => "# myblahs where one=11")
|
181
|
-
result = query.run
|
182
|
-
result.count.should == 1
|
183
|
-
|
184
|
-
query = Appstats::Query.new(:query => "# myblahs where one=anything")
|
185
|
-
query.run.count.should == 0
|
186
|
-
|
187
|
-
query = Appstats::Query.new(:query => "# myblahs where one=11 && two=22")
|
188
|
-
query.run.count.should == 0
|
189
|
-
|
190
|
-
query = Appstats::Query.new(:query => "# myblahs where one=11 || two=22")
|
191
|
-
query.run.count.should == 2
|
192
|
-
end
|
193
|
-
|
194
|
-
describe "fixed_points searches" do
|
195
|
-
|
196
|
-
it "should handle year" do
|
197
|
-
query = Appstats::Query.new(:query => "# myblahs last year")
|
198
|
-
result = query.run
|
199
|
-
result.date_to_s.should == "2009-01-01 to 2009-12-31"
|
200
|
-
end
|
201
|
-
|
202
|
-
it "should handle quarter" do
|
203
|
-
query = Appstats::Query.new(:query => "# myblahs last quarter")
|
204
|
-
result = query.run
|
205
|
-
result.date_to_s.should == "2010-04-01 to 2010-06-30"
|
206
|
-
end
|
207
|
-
|
208
|
-
it "should handle month" do
|
209
|
-
query = Appstats::Query.new(:query => "# myblahs last month")
|
210
|
-
result = query.run
|
211
|
-
result.date_to_s.should == "2010-08-01 to 2010-08-31"
|
212
|
-
end
|
213
|
-
|
214
|
-
it "should handle week" do
|
215
|
-
query = Appstats::Query.new(:query => "# myblahs last week")
|
216
|
-
result = query.run
|
217
|
-
result.date_to_s.should == "2010-09-13 to 2010-09-19"
|
218
|
-
end
|
219
|
-
|
220
|
-
it "should handle day" do
|
221
|
-
query = Appstats::Query.new(:query => "# myblahs last day")
|
222
|
-
result = query.run
|
223
|
-
result.date_to_s.should == "2010-09-20"
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
describe "real examples" do
|
228
|
-
|
229
|
-
it "nil split being called" do
|
230
|
-
query = Appstats::Query.new(:query => "# buyer-address-lookups group by city", :query_type => "Appstats::InvalidTestQuery")
|
231
|
-
result = query.run
|
232
|
-
result.count.should == 0
|
233
|
-
result.sub_results.size.should == 0
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|
237
|
-
|
238
|
-
end
|
239
|
-
|
240
|
-
describe "group sub results" do
|
241
|
-
|
242
|
-
before(:each) do
|
243
|
-
Appstats::Entry.delete_all
|
244
|
-
end
|
245
|
-
|
246
|
-
it "should not create sub results if no group_by" do
|
247
|
-
query = Appstats::Query.new(:query => "# myblahs last day")
|
248
|
-
result = query.run
|
249
|
-
result.sub_results.should == []
|
250
|
-
end
|
251
|
-
|
252
|
-
it "should track sub results for single group by" do
|
253
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "1")
|
254
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "1")
|
255
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "2")
|
256
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :ignore => "1")
|
131
|
+
# describe "core search" do
|
132
|
+
# it "should return 0 if no results" do
|
133
|
+
# query = Appstats::Query.new(:query => "# blahs")
|
134
|
+
# result = query.run
|
135
|
+
# result.new_record?.should == false
|
136
|
+
# result.should == Appstats::Result.new(:result_type => "on_demand", :query => "# blahs", :query_to_sql => query.query_to_sql, :count => 0, :action => "blahs", :group_by => nil, :db_username => 'root', :db_name => 'appstats_test', :db_host => 'localhost' )
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# it "should set name and result_type if provided" do
|
140
|
+
# query = Appstats::Query.new(:name => "x", :result_type => "some_reason", :query => "# blahs")
|
141
|
+
# result = query.run
|
142
|
+
# result.new_record?.should == false
|
143
|
+
# result.should == Appstats::Result.new(:name => "x", :result_type => "some_reason", :query => "# blahs", :query_to_sql => query.query_to_sql, :count => 0, :action => "blahs", :group_by => nil, :db_username => 'root', :db_name => 'appstats_test', :db_host => 'localhost')
|
144
|
+
# end
|
145
|
+
#
|
146
|
+
# it "should track contexts" do
|
147
|
+
# query = Appstats::Query.new(:query => "# blahs where (a=b and c=4) or (aaa=5)")
|
148
|
+
# result = query.run
|
149
|
+
# result.new_record?.should == false
|
150
|
+
# result.contexts.should == "(a=b and c=4) or (aaa=5)"
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
# it "should track the count if available" do
|
154
|
+
# Appstats::Entry.create(:action => "myblahs")
|
155
|
+
# query = Appstats::Query.new(:query => "# myblahs")
|
156
|
+
# query.run.count.should == 1
|
157
|
+
# Appstats::Entry.create(:action => "myblahs")
|
158
|
+
# query.run.count.should == 2
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# it "should track query_duration_in_seconds" do
|
162
|
+
# timer = FriendlyTimer.new(:duration => 10.0)
|
163
|
+
# timer.stub!(:stop)
|
164
|
+
# FriendlyTimer.stub!(:new).and_return(timer)
|
165
|
+
#
|
166
|
+
# Appstats::Entry.create(:action => "myblahs")
|
167
|
+
# query = Appstats::Query.new(:query => "# myblahs")
|
168
|
+
# result = query.run
|
169
|
+
#
|
170
|
+
# result.query_duration_in_seconds.should == 10.0
|
171
|
+
# result.group_query_duration_in_seconds.should == nil
|
172
|
+
# end
|
173
|
+
#
|
174
|
+
it "should track group_query_duration_in_seconds if a group provided" do
|
175
|
+
timer = FriendlyTimer.new(:duration => 10.0)
|
176
|
+
timer.stub!(:stop)
|
177
|
+
FriendlyTimer.stub!(:new).and_return(timer)
|
257
178
|
|
179
|
+
Appstats::Entry.create(:action => "myblahs")
|
258
180
|
query = Appstats::Query.new(:query => "# myblahs group by service_provider")
|
259
181
|
result = query.run
|
260
|
-
result.count.should == 4
|
261
|
-
result.group_by.should == "service_provider"
|
262
|
-
result.sub_results.size.should == 2
|
263
|
-
result.group_query_to_sql.should == query.group_query_to_sql
|
264
|
-
|
265
|
-
result.sub_results[0].should == SubResult.new(:context_filter => "a", :count => 3, :ratio_of_total => 0.75)
|
266
|
-
result.sub_results[1].should == SubResult.new(:context_filter => "b", :count => 1, :ratio_of_total => 0.25)
|
267
|
-
end
|
268
|
-
|
269
|
-
it "should track sub results for multiple group by" do
|
270
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
271
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
272
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
273
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
274
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
275
|
-
|
276
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
|
277
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
|
278
|
-
|
279
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
280
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
281
|
-
Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
282
|
-
|
283
|
-
query = Appstats::Query.new(:query => "# myblahs group by service_provider,user")
|
284
|
-
result = query.run
|
285
|
-
result.count.should == 10
|
286
|
-
result.group_by.should == "service_provider, user"
|
287
|
-
result.sub_results.size.should == 3
|
288
|
-
|
289
|
-
result.sub_results[0].should == SubResult.new(:context_filter => "a, 1", :count => 5, :ratio_of_total => 0.50)
|
290
|
-
result.sub_results[1].should == SubResult.new(:context_filter => "b, 1", :count => 3, :ratio_of_total => 0.30)
|
291
|
-
result.sub_results[2].should == SubResult.new(:context_filter => "a, 2", :count => 2, :ratio_of_total => 0.20)
|
292
|
-
end
|
293
|
-
|
294
|
-
end
|
295
|
-
|
296
|
-
describe "third party searches" do
|
297
|
-
|
298
|
-
before(:each) do
|
299
|
-
TestObject.delete_all
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
it "should handle custom sql" do
|
304
|
-
TestObject.create and TestObject.create
|
305
|
-
|
306
|
-
query = Query.new(:query => "# x", :query_type => "Appstats::TestQuery")
|
307
|
-
result = query.run
|
308
|
-
|
309
|
-
result.query_type.should == "Appstats::TestQuery"
|
310
|
-
result.count.should == 2
|
311
|
-
result.query_to_sql.should == "select count(*) as num from appstats_test_objects"
|
312
|
-
end
|
313
|
-
|
314
|
-
it "should track db connection on custom sql" do
|
315
|
-
query = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
|
316
|
-
result = query.run
|
317
|
-
[result.db_username,result.db_name,result.db_host].should == ['root','appstats_development','localhost']
|
318
|
-
end
|
319
|
-
|
320
|
-
it "should handle group by errors" do
|
321
|
-
query = Query.new(:query => "# x group by y", :query_type => "Appstats::BadGroupTestQuery")
|
322
|
-
result = query.run
|
323
|
-
result.query_type.should == "Appstats::BadGroupTestQuery"
|
324
|
-
result.sub_results.should == []
|
325
|
-
end
|
326
|
-
|
327
|
-
it "should reset database if things fail" do
|
328
|
-
query = Query.new(:query => "# x", :query_type => "Appstats::BadTestQuery")
|
329
|
-
result = query.run
|
330
|
-
result.query_type.should == "Appstats::BadTestQuery"
|
331
|
-
result.count.should == nil
|
332
|
-
|
333
|
-
ActiveRecord::Base.connection.current_database.should == YAML::load(File.open('db/config.yml'))["test"]["database"]
|
334
|
-
end
|
335
|
-
|
336
|
-
|
337
|
-
it "should handle group by" do
|
338
|
-
TestObject.create(:name => "aa") and TestObject.create(:name => "aa") and TestObject.create(:name => "bb")
|
339
|
-
|
340
|
-
query = Query.new(:query => "# x group by y", :query_type => "Appstats::TestQuery")
|
341
|
-
result = query.run
|
342
|
-
|
343
|
-
result.query_type.should == "Appstats::TestQuery"
|
344
|
-
result.count.should == 3
|
345
|
-
result.group_query_to_sql.should == "select context_key_filter, context_value_filter, count(*) as num from (select 'name' as context_key_filter, name as context_value_filter from appstats_test_objects) results group by context_value_filter"
|
346
|
-
result.sub_results.size.should == 2
|
347
|
-
end
|
348
|
-
|
349
|
-
it "should handle remote servers" do
|
350
|
-
TestObject.create(:name => "aa")
|
351
|
-
|
352
|
-
query1 = Query.new(:query => "# x on testServer", :query_type => "Appstats::TestQuery")
|
353
|
-
result1 = query1.run
|
354
|
-
|
355
|
-
query2 = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
|
356
|
-
result2 = query2.run
|
357
|
-
|
358
|
-
if result2.count == result1.count #coincidence
|
359
|
-
TestObject.create(:name => "aa")
|
360
|
-
result2 = query2.run
|
361
|
-
end
|
362
|
-
|
363
|
-
result1.count.should_not == result2.count
|
364
|
-
|
365
|
-
result1 = query1.run
|
366
|
-
result1.count.should_not == result2.count
|
367
|
-
end
|
368
|
-
|
369
|
-
end
|
370
|
-
|
371
|
-
end
|
372
|
-
|
373
|
-
|
374
|
-
describe "#query_to_sql" do
|
375
|
-
|
376
|
-
before(:all) do
|
377
|
-
Appstats::Action.delete_all
|
378
|
-
Appstats::Action.create(:name => "login", :plural_name => "logins")
|
379
|
-
end
|
380
|
-
|
381
|
-
it "should return understand nil" do
|
382
|
-
expected_sql = "select 0 from appstats_entries LIMIT 1"
|
383
|
-
Appstats::Query.new(:query => nil).query_to_sql.should == expected_sql
|
384
|
-
Appstats::Query.new(:query => "").query_to_sql.should == expected_sql
|
385
|
-
Appstats::Query.new.query_to_sql.should == expected_sql
|
386
|
-
end
|
387
|
-
|
388
|
-
describe "actions" do
|
389
|
-
|
390
|
-
it "should understand both singular and plural names" do
|
391
|
-
expected_sql = "select count(*) as num from appstats_entries where action = 'login'"
|
392
|
-
Appstats::Query.new(:query => "# logins").query_to_sql.should == expected_sql
|
393
|
-
Appstats::Query.new(:query => "# login").query_to_sql.should == expected_sql
|
394
|
-
end
|
395
|
-
|
396
|
-
it "should use 'itself' if action not found" do
|
397
|
-
expected_sql = "select count(*) as num from appstats_entries where action = 'garblygook'"
|
398
|
-
Appstats::Query.new(:query => "# garblygook").query_to_sql.should == expected_sql
|
399
|
-
end
|
400
|
-
|
401
|
-
end
|
402
|
-
|
403
|
-
describe "date ranges" do
|
404
|
-
it "should understand since dates" do
|
405
|
-
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and occurred_at >= '2010-01-15 00:00:00'"
|
406
|
-
Appstats::Query.new(:query => "# logins since 2010-01-15").query_to_sql.should == expected_sql
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
describe "server_name" do
|
411
|
-
|
412
|
-
it "should on_name" do
|
413
|
-
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'my.localnet' )"
|
414
|
-
Appstats::Query.new(:query => "# logins on my.localnet").query_to_sql.should == expected_sql
|
415
|
-
end
|
416
|
-
|
417
|
-
end
|
418
|
-
|
419
|
-
describe "date range and server_name" do
|
420
|
-
it "should understand dates and 'on'" do
|
421
|
-
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and (occurred_at >= '2010-01-15 00:00:00' and occurred_at <= '2010-01-31 23:59:59') and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'your.localnet' )"
|
422
|
-
Appstats::Query.new(:query => "# logins between 2010-01-15 and 2010-01-31 on your.localnet").query_to_sql.should == expected_sql
|
423
|
-
end
|
424
|
-
end
|
425
|
-
|
426
|
-
describe "where clause" do
|
427
|
-
|
428
|
-
it "should understand no quotes" do
|
429
|
-
expected_sql = "select count(*) as num from appstats_entries where action = 'login' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( (context_key = 'user' and context_value = 'aforward')))"
|
430
|
-
Appstats::Query.new(:query => "# logins where user = aforward").query_to_sql.should == expected_sql
|
431
|
-
end
|
432
|
-
|
433
|
-
it "should handle example" do
|
434
|
-
expected_sql = "select count(*) as num from appstats_entries where action = 'blahs' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( ( (context_key = 'a' and context_value = 'b') and (context_key = 'c' and context_value = '4') ) or ( (context_key = 'aaa' and context_value = '5') )))"
|
435
|
-
Appstats::Query.new(:query => "# blahs where (a=b and c=4) or (aaa=5)").query_to_sql.should == expected_sql
|
436
|
-
end
|
437
|
-
|
438
|
-
end
|
439
|
-
|
440
|
-
end
|
441
|
-
|
442
|
-
describe "#host_filter_to_sql" do
|
443
|
-
|
444
|
-
it "should translate blah into EXISTS query" do
|
445
|
-
expected = "EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'a' )"
|
446
|
-
Appstats::Query.host_filter_to_sql("a").should == expected
|
447
|
-
Appstats::Query.host_filter_to_sql(" a ").should == expected
|
448
|
-
end
|
449
|
-
|
450
|
-
it "should ignore single quotes and spaces" do
|
451
|
-
Appstats::Query.host_filter_to_sql("bl'ah").should == "1=1"
|
452
|
-
Appstats::Query.host_filter_to_sql("bl ah").should == "1=1"
|
453
|
-
end
|
454
|
-
|
455
|
-
it "should do simple 1=1 if invalid" do
|
456
|
-
Appstats::Query.host_filter_to_sql("").should == "1=1"
|
457
|
-
Appstats::Query.host_filter_to_sql(nil).should == "1=1"
|
458
|
-
end
|
459
|
-
|
460
|
-
end
|
461
|
-
|
462
|
-
describe "#group_query_to_sql" do
|
463
|
-
|
464
|
-
before(:each) do
|
465
|
-
@template = "select id from appstats_entries where action = 'myblahs'"
|
466
|
-
end
|
467
|
-
|
468
|
-
it "should support no filters" do
|
469
|
-
query = Appstats::Query.new(:query => "# myblahs")
|
470
|
-
query.group_query_to_sql.should == nil
|
471
|
-
end
|
472
|
-
|
473
|
-
it "should support 1 filter" do
|
474
|
-
query = Appstats::Query.new(:query => "# myblahs group by aa")
|
475
|
-
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
476
|
-
query.group_query_to_sql.should == expected
|
477
|
-
end
|
478
|
-
|
479
|
-
it "should support surrounding quotes" do
|
480
|
-
query = Appstats::Query.new(:query => "# myblahs group by 'aa'")
|
481
|
-
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
482
|
-
query.group_query_to_sql.should == expected
|
483
|
-
end
|
484
|
-
|
485
|
-
it "should support inner quotes" do
|
486
|
-
query = Appstats::Query.new(:query => "# myblahs group by a's")
|
487
|
-
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('a''s') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
488
|
-
query.group_query_to_sql.should == expected
|
489
|
-
end
|
490
|
-
|
491
|
-
|
492
|
-
it "should support many filters" do
|
493
|
-
query = Appstats::Query.new(:query => "# myblahs group by aa, bbb")
|
494
|
-
expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa','bbb') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
495
|
-
query.group_query_to_sql.should == expected
|
496
|
-
end
|
497
|
-
|
498
|
-
|
499
|
-
end
|
500
|
-
|
501
|
-
describe "#contexts_filter_to_sql" do
|
502
|
-
|
503
|
-
before(:each) do
|
504
|
-
@template = "EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ("
|
505
|
-
end
|
506
|
-
|
507
|
-
it "should translate a = b into EXISTS query" do
|
508
|
-
Appstats::Query.new(:query => "# logins where a=b").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
|
509
|
-
Appstats::Query.new(:query => "# logins where a = b ").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
|
510
|
-
end
|
511
182
|
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
end
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
end
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
183
|
+
result.query_duration_in_seconds.should == 10.0
|
184
|
+
result.group_query_duration_in_seconds.should == 10.0
|
185
|
+
end
|
186
|
+
#
|
187
|
+
# it "should not double count an entry with multiple contexts" do
|
188
|
+
# Appstats::Entry.create_from_logger("myblahs",:app_name => ["a","b"])
|
189
|
+
# query = Appstats::Query.new(:query => "# myblahs where app_name='a' or app_name = 'b'")
|
190
|
+
# query.run.count.should == 1
|
191
|
+
#
|
192
|
+
# Appstats::Entry.create_from_logger("myblahs",:app_name => ["a","c"])
|
193
|
+
# Appstats::Entry.create_from_logger("myblahs",:app_name => ["b","d"])
|
194
|
+
# Appstats::Entry.create_from_logger("myblahs",:app_name => ["c","d"])
|
195
|
+
# query = Appstats::Query.new(:query => "# myblahs where app_name='a' or app_name = 'b'")
|
196
|
+
# query.run.count.should == 3
|
197
|
+
#
|
198
|
+
# end
|
199
|
+
#
|
200
|
+
#
|
201
|
+
# it "should perform the action search" do
|
202
|
+
# Appstats::Entry.create_from_logger("myblahs", :one => "11", :two => "222")
|
203
|
+
# Appstats::Entry.create_from_logger("myblahs", :one => "111", :two => "22")
|
204
|
+
#
|
205
|
+
# query = Appstats::Query.new(:query => "# myblahs where one=11")
|
206
|
+
# result = query.run
|
207
|
+
# result.count.should == 1
|
208
|
+
#
|
209
|
+
# query = Appstats::Query.new(:query => "# myblahs where one=anything")
|
210
|
+
# query.run.count.should == 0
|
211
|
+
#
|
212
|
+
# query = Appstats::Query.new(:query => "# myblahs where one=11 && two=22")
|
213
|
+
# query.run.count.should == 0
|
214
|
+
#
|
215
|
+
# query = Appstats::Query.new(:query => "# myblahs where one=11 || two=22")
|
216
|
+
# query.run.count.should == 2
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
# describe "fixed_points searches" do
|
220
|
+
#
|
221
|
+
# it "should handle year" do
|
222
|
+
# query = Appstats::Query.new(:query => "# myblahs last year")
|
223
|
+
# result = query.run
|
224
|
+
# result.date_to_s.should == "2009-01-01 to 2009-12-31"
|
225
|
+
# end
|
226
|
+
#
|
227
|
+
# it "should handle quarter" do
|
228
|
+
# query = Appstats::Query.new(:query => "# myblahs last quarter")
|
229
|
+
# result = query.run
|
230
|
+
# result.date_to_s.should == "2010-04-01 to 2010-06-30"
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
# it "should handle month" do
|
234
|
+
# query = Appstats::Query.new(:query => "# myblahs last month")
|
235
|
+
# result = query.run
|
236
|
+
# result.date_to_s.should == "2010-08-01 to 2010-08-31"
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# it "should handle week" do
|
240
|
+
# query = Appstats::Query.new(:query => "# myblahs last week")
|
241
|
+
# result = query.run
|
242
|
+
# result.date_to_s.should == "2010-09-13 to 2010-09-19"
|
243
|
+
# end
|
244
|
+
#
|
245
|
+
# it "should handle day" do
|
246
|
+
# query = Appstats::Query.new(:query => "# myblahs last day")
|
247
|
+
# result = query.run
|
248
|
+
# result.date_to_s.should == "2010-09-20"
|
249
|
+
# end
|
250
|
+
# end
|
251
|
+
#
|
252
|
+
# describe "real examples" do
|
253
|
+
#
|
254
|
+
# it "nil split being called" do
|
255
|
+
# query = Appstats::Query.new(:query => "# buyer-address-lookups group by city", :query_type => "Appstats::InvalidTestQuery")
|
256
|
+
# result = query.run
|
257
|
+
# result.count.should == 0
|
258
|
+
# result.sub_results.size.should == 0
|
259
|
+
# end
|
260
|
+
#
|
261
|
+
# end
|
262
|
+
#
|
263
|
+
# end
|
264
|
+
#
|
265
|
+
# describe "group sub results" do
|
266
|
+
#
|
267
|
+
# before(:each) do
|
268
|
+
# Appstats::Entry.delete_all
|
269
|
+
# end
|
270
|
+
#
|
271
|
+
# it "should not create sub results if no group_by" do
|
272
|
+
# query = Appstats::Query.new(:query => "# myblahs last day")
|
273
|
+
# result = query.run
|
274
|
+
# result.sub_results.should == []
|
275
|
+
# end
|
276
|
+
#
|
277
|
+
# it "should track sub results for single group by" do
|
278
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "1")
|
279
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "1")
|
280
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "2")
|
281
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :ignore => "1")
|
282
|
+
#
|
283
|
+
# query = Appstats::Query.new(:query => "# myblahs group by service_provider")
|
284
|
+
# result = query.run
|
285
|
+
# result.count.should == 4
|
286
|
+
# result.group_by.should == "service_provider"
|
287
|
+
# result.sub_results.size.should == 2
|
288
|
+
# result.group_query_to_sql.should == query.group_query_to_sql
|
289
|
+
#
|
290
|
+
# result.sub_results[0].should == SubResult.new(:context_filter => "a", :count => 3, :ratio_of_total => 0.75)
|
291
|
+
# result.sub_results[1].should == SubResult.new(:context_filter => "b", :count => 1, :ratio_of_total => 0.25)
|
292
|
+
# end
|
293
|
+
#
|
294
|
+
# it "should track sub results for multiple group by" do
|
295
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
296
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
297
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
298
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
299
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
|
300
|
+
#
|
301
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
|
302
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
|
303
|
+
#
|
304
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
305
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
306
|
+
# Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
|
307
|
+
#
|
308
|
+
# query = Appstats::Query.new(:query => "# myblahs group by service_provider,user")
|
309
|
+
# result = query.run
|
310
|
+
# result.count.should == 10
|
311
|
+
# result.group_by.should == "service_provider, user"
|
312
|
+
# result.sub_results.size.should == 3
|
313
|
+
#
|
314
|
+
# result.sub_results[0].should == SubResult.new(:context_filter => "a, 1", :count => 5, :ratio_of_total => 0.50)
|
315
|
+
# result.sub_results[1].should == SubResult.new(:context_filter => "b, 1", :count => 3, :ratio_of_total => 0.30)
|
316
|
+
# result.sub_results[2].should == SubResult.new(:context_filter => "a, 2", :count => 2, :ratio_of_total => 0.20)
|
317
|
+
# end
|
318
|
+
#
|
319
|
+
end
|
320
|
+
#
|
321
|
+
# describe "third party searches" do
|
322
|
+
#
|
323
|
+
# before(:each) do
|
324
|
+
# TestObject.delete_all
|
325
|
+
#
|
326
|
+
# end
|
327
|
+
#
|
328
|
+
# it "should handle custom sql" do
|
329
|
+
# TestObject.create and TestObject.create
|
330
|
+
#
|
331
|
+
# query = Query.new(:query => "# x", :query_type => "Appstats::TestQuery")
|
332
|
+
# result = query.run
|
333
|
+
#
|
334
|
+
# result.query_type.should == "Appstats::TestQuery"
|
335
|
+
# result.count.should == 2
|
336
|
+
# result.query_to_sql.should == "select count(*) as num from appstats_test_objects"
|
337
|
+
# end
|
338
|
+
#
|
339
|
+
# it "should track db connection on custom sql" do
|
340
|
+
# query = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
|
341
|
+
# result = query.run
|
342
|
+
# [result.db_username,result.db_name,result.db_host].should == ['root','appstats_development','localhost']
|
343
|
+
# end
|
344
|
+
#
|
345
|
+
# it "should handle group by errors" do
|
346
|
+
# query = Query.new(:query => "# x group by y", :query_type => "Appstats::BadGroupTestQuery")
|
347
|
+
# result = query.run
|
348
|
+
# result.query_type.should == "Appstats::BadGroupTestQuery"
|
349
|
+
# result.sub_results.should == []
|
350
|
+
# end
|
351
|
+
#
|
352
|
+
# it "should reset database if things fail" do
|
353
|
+
# query = Query.new(:query => "# x", :query_type => "Appstats::BadTestQuery")
|
354
|
+
# result = query.run
|
355
|
+
# result.query_type.should == "Appstats::BadTestQuery"
|
356
|
+
# result.count.should == nil
|
357
|
+
#
|
358
|
+
# ActiveRecord::Base.connection.current_database.should == YAML::load(File.open('db/config.yml'))["test"]["database"]
|
359
|
+
# end
|
360
|
+
#
|
361
|
+
#
|
362
|
+
# it "should handle group by" do
|
363
|
+
# TestObject.create(:name => "aa") and TestObject.create(:name => "aa") and TestObject.create(:name => "bb")
|
364
|
+
#
|
365
|
+
# query = Query.new(:query => "# x group by y", :query_type => "Appstats::TestQuery")
|
366
|
+
# result = query.run
|
367
|
+
#
|
368
|
+
# result.query_type.should == "Appstats::TestQuery"
|
369
|
+
# result.count.should == 3
|
370
|
+
# result.group_query_to_sql.should == "select context_key_filter, context_value_filter, count(*) as num from (select 'name' as context_key_filter, name as context_value_filter from appstats_test_objects) results group by context_value_filter"
|
371
|
+
# result.sub_results.size.should == 2
|
372
|
+
# end
|
373
|
+
#
|
374
|
+
# it "should handle remote servers" do
|
375
|
+
# TestObject.create(:name => "aa")
|
376
|
+
#
|
377
|
+
# query1 = Query.new(:query => "# x on testServer", :query_type => "Appstats::TestQuery")
|
378
|
+
# result1 = query1.run
|
379
|
+
#
|
380
|
+
# query2 = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
|
381
|
+
# result2 = query2.run
|
382
|
+
#
|
383
|
+
# if result2.count == result1.count #coincidence
|
384
|
+
# TestObject.create(:name => "aa")
|
385
|
+
# result2 = query2.run
|
386
|
+
# end
|
387
|
+
#
|
388
|
+
# result1.count.should_not == result2.count
|
389
|
+
#
|
390
|
+
# result1 = query1.run
|
391
|
+
# result1.count.should_not == result2.count
|
392
|
+
# end
|
393
|
+
#
|
394
|
+
# end
|
395
|
+
#
|
396
|
+
# end
|
397
|
+
#
|
398
|
+
#
|
399
|
+
# describe "#query_to_sql" do
|
400
|
+
#
|
401
|
+
# before(:all) do
|
402
|
+
# Appstats::Action.delete_all
|
403
|
+
# Appstats::Action.create(:name => "login", :plural_name => "logins")
|
404
|
+
# end
|
405
|
+
#
|
406
|
+
# it "should return understand nil" do
|
407
|
+
# expected_sql = "select 0 from appstats_entries LIMIT 1"
|
408
|
+
# Appstats::Query.new(:query => nil).query_to_sql.should == expected_sql
|
409
|
+
# Appstats::Query.new(:query => "").query_to_sql.should == expected_sql
|
410
|
+
# Appstats::Query.new.query_to_sql.should == expected_sql
|
411
|
+
# end
|
412
|
+
#
|
413
|
+
# describe "actions" do
|
414
|
+
#
|
415
|
+
# it "should understand both singular and plural names" do
|
416
|
+
# expected_sql = "select count(*) as num from appstats_entries where action = 'login'"
|
417
|
+
# Appstats::Query.new(:query => "# logins").query_to_sql.should == expected_sql
|
418
|
+
# Appstats::Query.new(:query => "# login").query_to_sql.should == expected_sql
|
419
|
+
# end
|
420
|
+
#
|
421
|
+
# it "should use 'itself' if action not found" do
|
422
|
+
# expected_sql = "select count(*) as num from appstats_entries where action = 'garblygook'"
|
423
|
+
# Appstats::Query.new(:query => "# garblygook").query_to_sql.should == expected_sql
|
424
|
+
# end
|
425
|
+
#
|
426
|
+
# end
|
427
|
+
#
|
428
|
+
# describe "date ranges" do
|
429
|
+
# it "should understand since dates" do
|
430
|
+
# expected_sql = "select count(*) as num from appstats_entries where action = 'login' and occurred_at >= '2010-01-15 00:00:00'"
|
431
|
+
# Appstats::Query.new(:query => "# logins since 2010-01-15").query_to_sql.should == expected_sql
|
432
|
+
# end
|
433
|
+
# end
|
434
|
+
#
|
435
|
+
# describe "server_name" do
|
436
|
+
#
|
437
|
+
# it "should on_name" do
|
438
|
+
# expected_sql = "select count(*) as num from appstats_entries where action = 'login' and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'my.localnet' )"
|
439
|
+
# Appstats::Query.new(:query => "# logins on my.localnet").query_to_sql.should == expected_sql
|
440
|
+
# end
|
441
|
+
#
|
442
|
+
# end
|
443
|
+
#
|
444
|
+
# describe "date range and server_name" do
|
445
|
+
# it "should understand dates and 'on'" do
|
446
|
+
# expected_sql = "select count(*) as num from appstats_entries where action = 'login' and (occurred_at >= '2010-01-15 00:00:00' and occurred_at <= '2010-01-31 23:59:59') and EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'your.localnet' )"
|
447
|
+
# Appstats::Query.new(:query => "# logins between 2010-01-15 and 2010-01-31 on your.localnet").query_to_sql.should == expected_sql
|
448
|
+
# end
|
449
|
+
# end
|
450
|
+
#
|
451
|
+
# describe "where clause" do
|
452
|
+
#
|
453
|
+
# it "should understand no quotes" do
|
454
|
+
# expected_sql = "select count(*) as num from appstats_entries where action = 'login' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( (context_key = 'user' and context_value = 'aforward')))"
|
455
|
+
# Appstats::Query.new(:query => "# logins where user = aforward").query_to_sql.should == expected_sql
|
456
|
+
# end
|
457
|
+
#
|
458
|
+
# it "should handle example" do
|
459
|
+
# expected_sql = "select count(*) as num from appstats_entries where action = 'blahs' and EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ( ( (context_key = 'a' and context_value = 'b') and (context_key = 'c' and context_value = '4') ) or ( (context_key = 'aaa' and context_value = '5') )))"
|
460
|
+
# Appstats::Query.new(:query => "# blahs where (a=b and c=4) or (aaa=5)").query_to_sql.should == expected_sql
|
461
|
+
# end
|
462
|
+
#
|
463
|
+
# end
|
464
|
+
#
|
465
|
+
# end
|
466
|
+
#
|
467
|
+
# describe "#host_filter_to_sql" do
|
468
|
+
#
|
469
|
+
# it "should translate blah into EXISTS query" do
|
470
|
+
# expected = "EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'a' )"
|
471
|
+
# Appstats::Query.host_filter_to_sql("a").should == expected
|
472
|
+
# Appstats::Query.host_filter_to_sql(" a ").should == expected
|
473
|
+
# end
|
474
|
+
#
|
475
|
+
# it "should ignore single quotes and spaces" do
|
476
|
+
# Appstats::Query.host_filter_to_sql("bl'ah").should == "1=1"
|
477
|
+
# Appstats::Query.host_filter_to_sql("bl ah").should == "1=1"
|
478
|
+
# end
|
479
|
+
#
|
480
|
+
# it "should do simple 1=1 if invalid" do
|
481
|
+
# Appstats::Query.host_filter_to_sql("").should == "1=1"
|
482
|
+
# Appstats::Query.host_filter_to_sql(nil).should == "1=1"
|
483
|
+
# end
|
484
|
+
#
|
485
|
+
# end
|
486
|
+
#
|
487
|
+
# describe "#group_query_to_sql" do
|
488
|
+
#
|
489
|
+
# before(:each) do
|
490
|
+
# @template = "select id from appstats_entries where action = 'myblahs'"
|
491
|
+
# end
|
492
|
+
#
|
493
|
+
# it "should support no filters" do
|
494
|
+
# query = Appstats::Query.new(:query => "# myblahs")
|
495
|
+
# query.group_query_to_sql.should == nil
|
496
|
+
# end
|
497
|
+
#
|
498
|
+
# it "should support 1 filter" do
|
499
|
+
# query = Appstats::Query.new(:query => "# myblahs group by aa")
|
500
|
+
# expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
501
|
+
# query.group_query_to_sql.should == expected
|
502
|
+
# end
|
503
|
+
#
|
504
|
+
# it "should support surrounding quotes" do
|
505
|
+
# query = Appstats::Query.new(:query => "# myblahs group by 'aa'")
|
506
|
+
# expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
507
|
+
# query.group_query_to_sql.should == expected
|
508
|
+
# end
|
509
|
+
#
|
510
|
+
# it "should support inner quotes" do
|
511
|
+
# query = Appstats::Query.new(:query => "# myblahs group by a's")
|
512
|
+
# expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('a''s') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
513
|
+
# query.group_query_to_sql.should == expected
|
514
|
+
# end
|
515
|
+
#
|
516
|
+
#
|
517
|
+
# it "should support many filters" do
|
518
|
+
# query = Appstats::Query.new(:query => "# myblahs group by aa, bbb")
|
519
|
+
# expected = "select context_key_filter, context_value_filter, count(*) as num from (select group_concat(appstats_contexts.context_key) as context_key_filter, group_concat(appstats_contexts.context_value) as context_value_filter, appstats_entry_id from appstats_contexts where context_key in ('aa','bbb') and appstats_entry_id in ( #{@template} ) group by appstats_entry_id) results group by context_value_filter"
|
520
|
+
# query.group_query_to_sql.should == expected
|
521
|
+
# end
|
522
|
+
#
|
523
|
+
#
|
524
|
+
# end
|
525
|
+
#
|
526
|
+
# describe "#contexts_filter_to_sql" do
|
527
|
+
#
|
528
|
+
# before(:each) do
|
529
|
+
# @template = "EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ("
|
530
|
+
# end
|
531
|
+
#
|
532
|
+
# it "should translate a = b into EXISTS query" do
|
533
|
+
# Appstats::Query.new(:query => "# logins where a=b").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
|
534
|
+
# Appstats::Query.new(:query => "# logins where a = b ").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
|
535
|
+
# end
|
536
|
+
#
|
537
|
+
# it "should ignore single quotes" do
|
538
|
+
# Appstats::Query.new(:query => "# logins where 'aaa'='bbbb'").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
|
539
|
+
# Appstats::Query.new(:query => "# logins where 'aaa' = 'bbbb' ").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
|
540
|
+
# end
|
541
|
+
#
|
542
|
+
# it "should allow for searching for all entries of a certain context" do
|
543
|
+
# Appstats::Query.new(:query => "# logins where aaa").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa')))"
|
544
|
+
# end
|
545
|
+
#
|
546
|
+
# it "should allow for searching for several entries of a certain context" do
|
547
|
+
# Appstats::Query.new(:query => "# logins where aaa || bbb").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa') or (context_key = 'bbb')))"
|
548
|
+
# end
|
549
|
+
#
|
550
|
+
# it "should allow complex queries" do
|
551
|
+
# Appstats::Query.new(:query => "# logins where user='andrew' || user='aforward'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value = 'andrew') or (context_key = 'user' and context_value = 'aforward')))"
|
552
|
+
# end
|
553
|
+
#
|
554
|
+
# it "should support or" do
|
555
|
+
# Appstats::Query.new(:query => "# logins where user='andrew' or user='aforward'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value = 'andrew') or (context_key = 'user' and context_value = 'aforward')))"
|
556
|
+
# end
|
557
|
+
#
|
558
|
+
# it "should support like" do
|
559
|
+
# Appstats::Query.new(:query => "# logins where user like '%andrew%'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value like '%andrew%')))"
|
560
|
+
# end
|
561
|
+
#
|
562
|
+
# it "should support and" do
|
563
|
+
# Appstats::Query.new(:query => "# logins where user='andrew' and user='aforward'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value = 'andrew') and (context_key = 'user' and context_value = 'aforward')))"
|
564
|
+
# end
|
565
|
+
#
|
566
|
+
#
|
567
|
+
# it "should do simple 1 = 1 if invalid" do
|
568
|
+
# Appstats::Query.new(:query => "# logins where").contexts_filter_to_sql.should == "1=1"
|
569
|
+
# Appstats::Query.new(:query => "# logins").contexts_filter_to_sql.should == "1=1"
|
570
|
+
# end
|
571
|
+
#
|
572
|
+
# end
|
573
|
+
#
|
574
|
+
# describe "#sqlize" do
|
575
|
+
#
|
576
|
+
# it "should handle nil" do
|
577
|
+
# Appstats::Query.sqlize(nil).should == nil
|
578
|
+
# Appstats::Query.sqlize('').should == ''
|
579
|
+
# end
|
580
|
+
#
|
581
|
+
# it "should understand &&" do
|
582
|
+
# Appstats::Query.sqlize("&&").should == "and"
|
583
|
+
# end
|
584
|
+
#
|
585
|
+
# it "should understand ||" do
|
586
|
+
# Appstats::Query.sqlize("||").should == "or"
|
587
|
+
# end
|
588
|
+
#
|
589
|
+
# it "should understand !=" do
|
590
|
+
# Appstats::Query.sqlize("!=").should == "<>"
|
591
|
+
# end
|
592
|
+
#
|
593
|
+
# it "should set everything else as-is" do
|
594
|
+
# Appstats::Query.sqlize("blah").should == "blah"
|
595
|
+
# end
|
596
|
+
#
|
597
|
+
# end
|
598
|
+
#
|
599
|
+
# describe "#sqlclean" do
|
600
|
+
#
|
601
|
+
# it "should handle nil" do
|
602
|
+
# Appstats::Query.sqlclean(nil).should == nil
|
603
|
+
# Appstats::Query.sqlclean('').should == ''
|
604
|
+
# end
|
605
|
+
#
|
606
|
+
# it "should remove exterior quotes" do
|
607
|
+
# Appstats::Query.sqlclean("'a'").should == "a"
|
608
|
+
# Appstats::Query.sqlclean("'bbb'").should == "bbb"
|
609
|
+
# Appstats::Query.sqlclean('"a"').should == "a"
|
610
|
+
# Appstats::Query.sqlclean('"bbb"').should == "bbb"
|
611
|
+
# end
|
612
|
+
#
|
613
|
+
# it "should handle normal text" do
|
614
|
+
# Appstats::Query.sqlclean('abc').should == 'abc'
|
615
|
+
# end
|
616
|
+
#
|
617
|
+
# it "should handle slashes" do
|
618
|
+
# Appstats::Query.sqlclean('a\b').should == 'a\\\\b'
|
619
|
+
# end
|
620
|
+
#
|
621
|
+
# it "should handle single quotes" do
|
622
|
+
# Appstats::Query.sqlclean("a'b").should == "a''b"
|
623
|
+
# end
|
624
|
+
#
|
625
|
+
# end
|
626
|
+
#
|
627
|
+
# describe "#comparators" do
|
628
|
+
#
|
629
|
+
# it "should be a list " do
|
630
|
+
# Appstats::Query.comparators.should == ["=","!=","<>",">","<",">=","<=","like"]
|
631
|
+
# end
|
632
|
+
#
|
633
|
+
# end
|
634
|
+
#
|
635
|
+
# describe "#comparator?" do
|
636
|
+
#
|
637
|
+
# it "should not consider nil" do
|
638
|
+
# Appstats::Query.comparator?(nil).should == false
|
639
|
+
# Appstats::Query.comparator?("").should == false
|
640
|
+
# end
|
641
|
+
#
|
642
|
+
#
|
643
|
+
# it "should not consider &&" do
|
644
|
+
# Appstats::Query.comparator?("&&").should == false
|
645
|
+
# end
|
646
|
+
#
|
647
|
+
# it "should not consider ||" do
|
648
|
+
# Appstats::Query.comparator?("||").should == false
|
649
|
+
# end
|
650
|
+
#
|
651
|
+
# it "should not consider and" do
|
652
|
+
# Appstats::Query.comparator?("and").should == false
|
653
|
+
# end
|
654
|
+
#
|
655
|
+
# it "should not consider or" do
|
656
|
+
# Appstats::Query.comparator?("or").should == false
|
657
|
+
# end
|
658
|
+
#
|
659
|
+
# it "should consider =" do
|
660
|
+
# Appstats::Query.comparator?("=").should == true
|
661
|
+
# end
|
662
|
+
#
|
663
|
+
# it "should consider !=" do
|
664
|
+
# Appstats::Query.comparator?("!=").should == true
|
665
|
+
# end
|
666
|
+
#
|
667
|
+
# it "should consider <>" do
|
668
|
+
# Appstats::Query.comparator?("<>").should == true
|
669
|
+
# end
|
670
|
+
#
|
671
|
+
# it "should consider >" do
|
672
|
+
# Appstats::Query.comparator?(">").should == true
|
673
|
+
# end
|
674
|
+
#
|
675
|
+
# it "should consider <" do
|
676
|
+
# Appstats::Query.comparator?("<").should == true
|
677
|
+
# end
|
678
|
+
#
|
679
|
+
# it "should consider >=" do
|
680
|
+
# Appstats::Query.comparator?(">=").should == true
|
681
|
+
# end
|
682
|
+
#
|
683
|
+
# it "should consider <=" do
|
684
|
+
# Appstats::Query.comparator?("<=").should == true
|
685
|
+
# end
|
686
|
+
#
|
687
|
+
#
|
688
|
+
# end
|
664
689
|
|
665
690
|
|
666
691
|
|