appstats 0.19.1 → 0.19.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- appstats (0.19.1)
4
+ appstats (0.19.2)
5
5
  daemons
6
6
  net-scp
7
7
  rails (>= 2.3.0)
@@ -55,25 +55,43 @@ module Appstats
55
55
  result.save
56
56
 
57
57
  unless @group_by.empty?
58
+ running_total = 0
58
59
  data = run_query { |conn| conn.select_all(@group_query_to_sql) }
59
60
  result.group_query_duration_in_seconds = data[:duration] unless data.nil?
60
61
  all_sub_results = data.nil? ? [] : data[:results]
61
62
  all_sub_results.each do |data|
62
- if data["context_key_filter"].nil? || data["context_value_filter"].nil? || data["num"].nil?
63
- Appstats.log(:error,"Missing context_key_filter, context_value_filter, or num in #{data.inspect}")
63
+ if data["context_key_filter"].nil? || data["num"].nil?
64
+ Appstats.log(:error,"Missing context_key_filter, or num in #{data.inspect}")
64
65
  next
65
66
  end
67
+
68
+ if data["context_value_filter"].nil?
69
+ Appstats.log(:error,"Missing context_value_filter, setting to empty string ''")
70
+ data["context_value_filter"] = ""
71
+ end
66
72
 
67
73
  keys = data["context_key_filter"].split(",")
68
74
  values = data["context_value_filter"].split(",")
69
75
  key_values = {} and keys.each_with_index { |k,i| key_values[k] = values[i] }
70
- ratio_of_total = data["num"].to_f / result.count
71
- sub_result = Appstats::SubResult.new(:context_filter => @group_by.collect { |k| key_values[k] }.join(", "), :count => data["num"], :ratio_of_total => ratio_of_total)
76
+ current_count = data["num"].to_i
77
+ ratio_of_total = current_count.to_f / result.count
78
+ running_total += current_count
79
+ sub_result = Appstats::SubResult.new(:context_filter => @group_by.collect { |k| key_values[k] }.join(", "), :count => current_count, :ratio_of_total => ratio_of_total)
80
+ sub_result.result = result
81
+ sub_result.save
82
+ end
83
+
84
+ if running_total < result.count
85
+ remaining_total = result.count - running_total
86
+ ratio_of_total = remaining_total.to_f / result.count
87
+ sub_result = Appstats::SubResult.new(:context_filter => nil, :count => remaining_total, :ratio_of_total => ratio_of_total)
72
88
  sub_result.result = result
73
89
  sub_result.save
74
90
  end
91
+
75
92
  result.save
76
93
  end
94
+
77
95
  result.reload
78
96
  result
79
97
  end
@@ -17,6 +17,12 @@ module Appstats
17
17
  def total_count_to_s(data = {})
18
18
  Appstats::Result.calculate_count_to_s(total_count,data)
19
19
  end
20
+
21
+ def context_filter_to_s
22
+ return "-- N/A --" if context_filter.nil?
23
+ return "-- No Value --" if context_filter.empty?
24
+ context_filter
25
+ end
20
26
 
21
27
 
22
28
  def ==(o)
@@ -1,3 +1,3 @@
1
1
  module Appstats
2
- VERSION = "0.19.1"
2
+ VERSION = "0.19.2"
3
3
  end
data/spec/entry_spec.rb CHANGED
@@ -193,18 +193,18 @@ module Appstats
193
193
  end
194
194
 
195
195
  it "should understand an entry without contexts" do
196
- entry = Entry.create_from_logger_string("0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
196
+ entry = Entry.create_from_logger_string("0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
197
197
  Entry.count.should == @before_count + 1
198
198
  entry.action.should == "address_search"
199
- entry.raw_entry.should == "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
199
+ entry.raw_entry.should == "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
200
200
  entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
201
201
  end
202
202
 
203
203
  it "should understand contexts" do
204
- entry = Entry.create_from_logger_string("0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
204
+ entry = Entry.create_from_logger_string("0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
205
205
  Entry.count.should == @before_count + 1
206
206
  entry.action.should == "address_filter"
207
- entry.raw_entry.should == "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
207
+ entry.raw_entry.should == "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
208
208
  entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
209
209
  entry.contexts.size.should == 2
210
210
  entry.contexts[0].context_key = "app_name"
@@ -214,10 +214,10 @@ module Appstats
214
214
  end
215
215
 
216
216
  it "should handle 'action' as a context" do
217
- entry = Entry.create_from_logger_string('0.19.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb')
217
+ entry = Entry.create_from_logger_string('0.19.2 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb')
218
218
  Entry.count.should == @before_count + 1
219
219
  entry.action.should == "page-view"
220
- entry.raw_entry.should == "0.19.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
220
+ entry.raw_entry.should == "0.19.2 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
221
221
  entry.occurred_at.should == Time.parse("2011-02-24 12:59:57")
222
222
  entry.contexts.size.should == 2
223
223
  entry.contexts[0].context_key = "action"
@@ -228,10 +228,10 @@ module Appstats
228
228
  end
229
229
 
230
230
  it "should handle multiple of the same 'context'" do
231
- entry = Entry.create_from_logger_string('0.19.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb')
231
+ entry = Entry.create_from_logger_string('0.19.2 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb')
232
232
  Entry.count.should == @before_count + 1
233
233
  entry.action.should == "page-view"
234
- entry.raw_entry.should == "0.19.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
234
+ entry.raw_entry.should == "0.19.2 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
235
235
  entry.occurred_at.should == Time.parse("2011-02-24 12:59:57")
236
236
  entry.contexts.size.should == 2
237
237
  entry.contexts[0].context_key = "app_name"
data/spec/logger_spec.rb CHANGED
@@ -122,12 +122,12 @@ module Appstats
122
122
 
123
123
  it "should accept numbers" do
124
124
  Appstats::Logger.entry(5, :blah => 6)
125
- Appstats::Logger.raw_read.should == ["0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
125
+ Appstats::Logger.raw_read.should == ["0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
126
126
  end
127
127
 
128
128
  it "should accept arrays" do
129
129
  Appstats::Logger.entry('search', :provider => [ 'one', 'two' ])
130
- Appstats::Logger.raw_read.should == ["0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
130
+ Appstats::Logger.raw_read.should == ["0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
131
131
  end
132
132
 
133
133
 
@@ -137,7 +137,7 @@ module Appstats
137
137
 
138
138
  it "should look similar to regular entry" do
139
139
  Appstats::Logger.exception_entry(RuntimeError.new("blah"),:on => "login")
140
- Appstats::Logger.raw_read.should == ["0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
140
+ Appstats::Logger.raw_read.should == ["0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
141
141
  end
142
142
 
143
143
  end
@@ -154,47 +154,47 @@ module Appstats
154
154
 
155
155
  it "should handle a statistics entry" do
156
156
  expected = { :action => "address_search", :timestamp => "2010-09-21 23:15:20" }
157
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
157
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
158
158
  actual.should == expected
159
159
  end
160
160
 
161
161
  it "should handle contexts" do
162
162
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
163
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
163
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
164
164
  actual.should == expected
165
165
  end
166
166
 
167
167
  it "should handle multiple actions" do
168
168
  expected = { :action => ["address_filter", "blah"], :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
169
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
169
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
170
170
  actual.should == expected
171
171
  end
172
172
 
173
173
  it "should handle multiple of same context" do
174
174
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => ['Sin','Market'] }
175
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
175
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
176
176
  actual.should == expected
177
177
  end
178
178
 
179
179
  it "should handle no actions" do
180
180
  expected = { :action => "UNKNOWN_ACTION", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
181
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
181
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
182
182
  actual.should == expected
183
183
  end
184
184
 
185
185
  it "should handle actions with the delimiter (and change the delimiter)" do
186
186
  expected = { :action => "address:=search-n", :timestamp => "2010-09-21 23:15:20" }
187
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
187
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
188
188
  actual.should == expected
189
189
 
190
190
  expected = { :action => "address::search==--n", :timestamp => "2010-09-21 23:15:20" }
191
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
191
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
192
192
  actual.should == expected
193
193
  end
194
194
 
195
195
  it "should handle contexts with the delimiter (and change the delimiter)" do
196
196
  expected = { :action => "address", :timestamp => "2010-09-21 23:15:20", :server => "market:eval=-n" }
197
- actual = Appstats::Logger.entry_to_hash("0.19.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
197
+ actual = Appstats::Logger.entry_to_hash("0.19.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
198
198
  actual.should == expected
199
199
  end
200
200
 
@@ -203,66 +203,66 @@ module Appstats
203
203
  describe "#entry_to_s" do
204
204
 
205
205
  it "should handle a statistics entry" do
206
- expected = "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
206
+ expected = "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
207
207
  actual = Appstats::Logger.entry_to_s("address_search")
208
208
  actual.should == expected
209
209
  end
210
210
 
211
211
  it "should handle numbers" do
212
- expected = "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
212
+ expected = "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
213
213
  actual = Appstats::Logger.entry_to_s(1,:note => 2.2)
214
214
  actual.should == expected
215
215
  end
216
216
 
217
217
  it "should handle default contexts" do
218
218
  Appstats::Logger.default_contexts[:app_name] = "market"
219
- expected = "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
219
+ expected = "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
220
220
  actual = Appstats::Logger.entry_to_s("address_search")
221
221
  actual.should == expected
222
222
  end
223
223
 
224
224
  it "should handle contexts (and sort them by symbol)" do
225
- expected = "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
225
+ expected = "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
226
226
  actual = Appstats::Logger.entry_to_s("address_filter", { :server => "Live", :app_name => 'Market' })
227
227
  actual.should == expected
228
228
  end
229
229
 
230
230
  it "should handle actions with the delimiter (and change the delimiter)" do
231
- expected = "0.19.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
231
+ expected = "0.19.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
232
232
  actual = Appstats::Logger.entry_to_s("address:=search-n")
233
233
  actual.should == expected
234
234
 
235
- expected = "0.19.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
235
+ expected = "0.19.2 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
236
236
  actual = Appstats::Logger.entry_to_s("address::search==--n")
237
237
  actual.should == expected
238
238
  end
239
239
 
240
240
  it "should handle contexts with the delimiter (and change the delimiter)" do
241
- expected = "0.19.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
241
+ expected = "0.19.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
242
242
  actual = Appstats::Logger.entry_to_s("address", :server => 'market:eval=-n')
243
243
  actual.should == expected
244
244
  end
245
245
 
246
246
  it "should ignore spaces" do
247
- expected = "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
247
+ expected = "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
248
248
  actual = Appstats::Logger.entry_to_s("address search")
249
249
  actual.should == expected
250
250
  end
251
251
 
252
252
  it "should convert newlines in action" do
253
- expected = "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
253
+ expected = "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
254
254
  actual = Appstats::Logger.entry_to_s("address_\nsearch")
255
255
  actual.should == expected
256
256
  end
257
257
 
258
258
  it "should convert newlines in context" do
259
- expected = "0.19.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
259
+ expected = "0.19.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
260
260
  actual = Appstats::Logger.entry_to_s("address_search",:blah => "some\nlong\nstatement")
261
261
  actual.should == expected
262
262
  end
263
263
 
264
264
  it "should convert newlines based on the delimiter" do
265
- expected = "0.19.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
265
+ expected = "0.19.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
266
266
  actual = Appstats::Logger.entry_to_s("address:=\nsearch-n")
267
267
  actual.should == expected
268
268
  end
data/spec/query_spec.rb CHANGED
@@ -7,170 +7,170 @@ 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
- # 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
- #
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
- # 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
- #
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
174
  it "should track group_query_duration_in_seconds if a group provided" do
175
175
  timer = FriendlyTimer.new(:duration => 10.0)
176
176
  timer.stub!(:stop)
@@ -183,509 +183,538 @@ module Appstats
183
183
  result.query_duration_in_seconds.should == 10.0
184
184
  result.group_query_duration_in_seconds.should == 10.0
185
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
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 elements outside of the context" do
278
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a")
279
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a")
280
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a")
281
+ Appstats::Entry.create_from_logger("myblahs")
282
+
283
+ query = Appstats::Query.new(:query => "# myblahs group by service_provider")
284
+ result = query.run
285
+ result.count.should == 4
286
+ result.sub_results.size.should == 2
287
+ result.sub_results[0].should == SubResult.new(:context_filter => "a", :count => 3, :ratio_of_total => 0.75)
288
+ result.sub_results[1].should == SubResult.new(:context_filter => nil, :count => 1, :ratio_of_total => 0.25)
289
+ end
290
+
291
+ it "should track empty and nil contexts" do
292
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a")
293
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a")
294
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "")
295
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => nil)
296
+
297
+ query = Appstats::Query.new(:query => "# myblahs group by service_provider")
298
+ result = query.run
299
+ result.count.should == 4
300
+ result.sub_results.size.should == 2
301
+ result.sub_results[0].should == SubResult.new(:context_filter => "", :count => 2, :ratio_of_total => 0.5)
302
+ result.sub_results[1].should == SubResult.new(:context_filter => "a", :count => 2, :ratio_of_total => 0.5)
303
+ end
304
+
305
+
306
+ it "should track sub results for single group by" do
307
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "1")
308
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "1")
309
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :ignore => "2")
310
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :ignore => "1")
311
+
312
+ query = Appstats::Query.new(:query => "# myblahs group by service_provider")
313
+ result = query.run
314
+ result.count.should == 4
315
+ result.group_by.should == "service_provider"
316
+ result.sub_results.size.should == 2
317
+ result.group_query_to_sql.should == query.group_query_to_sql
318
+
319
+ result.sub_results[0].should == SubResult.new(:context_filter => "a", :count => 3, :ratio_of_total => 0.75)
320
+ result.sub_results[1].should == SubResult.new(:context_filter => "b", :count => 1, :ratio_of_total => 0.25)
321
+ end
322
+
323
+ it "should track sub results for multiple group by" do
324
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
325
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
326
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
327
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
328
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
329
+
330
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
331
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
332
+
333
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
334
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
335
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
336
+
337
+ query = Appstats::Query.new(:query => "# myblahs group by service_provider,user")
338
+ result = query.run
339
+ result.count.should == 10
340
+ result.group_by.should == "service_provider, user"
341
+ result.sub_results.size.should == 3
342
+
343
+ result.sub_results[0].should == SubResult.new(:context_filter => "a, 1", :count => 5, :ratio_of_total => 0.50)
344
+ result.sub_results[1].should == SubResult.new(:context_filter => "b, 1", :count => 3, :ratio_of_total => 0.30)
345
+ result.sub_results[2].should == SubResult.new(:context_filter => "a, 2", :count => 2, :ratio_of_total => 0.20)
346
+ end
347
+
348
+ end
349
+
350
+ describe "third party searches" do
351
+
352
+ before(:each) do
353
+ TestObject.delete_all
354
+
355
+ end
356
+
357
+ it "should handle custom sql" do
358
+ TestObject.create and TestObject.create
359
+
360
+ query = Query.new(:query => "# x", :query_type => "Appstats::TestQuery")
361
+ result = query.run
362
+
363
+ result.query_type.should == "Appstats::TestQuery"
364
+ result.count.should == 2
365
+ result.query_to_sql.should == "select count(*) as num from appstats_test_objects"
366
+ end
367
+
368
+ it "should track db connection on custom sql" do
369
+ query = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
370
+ result = query.run
371
+ [result.db_username,result.db_name,result.db_host].should == ['root','appstats_development','localhost']
372
+ end
373
+
374
+ it "should handle group by errors" do
375
+ query = Query.new(:query => "# x group by y", :query_type => "Appstats::BadGroupTestQuery")
376
+ result = query.run
377
+ result.query_type.should == "Appstats::BadGroupTestQuery"
378
+ result.sub_results.should == [ Appstats::SubResult.new(:context_filter => nil, :count => 2, :ratio_of_total => 1.0) ]
379
+ end
380
+
381
+ it "should reset database if things fail" do
382
+ query = Query.new(:query => "# x", :query_type => "Appstats::BadTestQuery")
383
+ result = query.run
384
+ result.query_type.should == "Appstats::BadTestQuery"
385
+ result.count.should == nil
386
+
387
+ ActiveRecord::Base.connection.current_database.should == YAML::load(File.open('db/config.yml'))["test"]["database"]
388
+ end
389
+
390
+
391
+ it "should handle group by" do
392
+ TestObject.create(:name => "aa") and TestObject.create(:name => "aa") and TestObject.create(:name => "bb")
393
+
394
+ query = Query.new(:query => "# x group by y", :query_type => "Appstats::TestQuery")
395
+ result = query.run
396
+
397
+ result.query_type.should == "Appstats::TestQuery"
398
+ result.count.should == 3
399
+ 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"
400
+ result.sub_results.size.should == 2
401
+ end
402
+
403
+ it "should handle remote servers" do
404
+ TestObject.create(:name => "aa")
405
+
406
+ query1 = Query.new(:query => "# x on testServer", :query_type => "Appstats::TestQuery")
407
+ result1 = query1.run
408
+
409
+ query2 = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
410
+ result2 = query2.run
411
+
412
+ if result2.count == result1.count #coincidence
413
+ TestObject.create(:name => "aa")
414
+ result2 = query2.run
415
+ end
416
+
417
+ result1.count.should_not == result2.count
418
+
419
+ result1 = query1.run
420
+ result1.count.should_not == result2.count
421
+ end
422
+
423
+ end
424
+
425
+ end
426
+
427
+
428
+ describe "#query_to_sql" do
429
+
430
+ before(:all) do
431
+ Appstats::Action.delete_all
432
+ Appstats::Action.create(:name => "login", :plural_name => "logins")
433
+ end
434
+
435
+ it "should return understand nil" do
436
+ expected_sql = "select 0 from appstats_entries LIMIT 1"
437
+ Appstats::Query.new(:query => nil).query_to_sql.should == expected_sql
438
+ Appstats::Query.new(:query => "").query_to_sql.should == expected_sql
439
+ Appstats::Query.new.query_to_sql.should == expected_sql
440
+ end
441
+
442
+ describe "actions" do
443
+
444
+ it "should understand both singular and plural names" do
445
+ expected_sql = "select count(*) as num from appstats_entries where action = 'login'"
446
+ Appstats::Query.new(:query => "# logins").query_to_sql.should == expected_sql
447
+ Appstats::Query.new(:query => "# login").query_to_sql.should == expected_sql
448
+ end
449
+
450
+ it "should use 'itself' if action not found" do
451
+ expected_sql = "select count(*) as num from appstats_entries where action = 'garblygook'"
452
+ Appstats::Query.new(:query => "# garblygook").query_to_sql.should == expected_sql
453
+ end
454
+
455
+ end
456
+
457
+ describe "date ranges" do
458
+ it "should understand since dates" do
459
+ expected_sql = "select count(*) as num from appstats_entries where action = 'login' and occurred_at >= '2010-01-15 00:00:00'"
460
+ Appstats::Query.new(:query => "# logins since 2010-01-15").query_to_sql.should == expected_sql
461
+ end
462
+ end
463
+
464
+ describe "server_name" do
465
+
466
+ it "should on_name" do
467
+ 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' )"
468
+ Appstats::Query.new(:query => "# logins on my.localnet").query_to_sql.should == expected_sql
469
+ end
470
+
471
+ end
472
+
473
+ describe "date range and server_name" do
474
+ it "should understand dates and 'on'" do
475
+ 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' )"
476
+ Appstats::Query.new(:query => "# logins between 2010-01-15 and 2010-01-31 on your.localnet").query_to_sql.should == expected_sql
477
+ end
478
+ end
479
+
480
+ describe "where clause" do
481
+
482
+ it "should understand no quotes" do
483
+ 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')))"
484
+ Appstats::Query.new(:query => "# logins where user = aforward").query_to_sql.should == expected_sql
485
+ end
486
+
487
+ it "should handle example" do
488
+ 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') )))"
489
+ Appstats::Query.new(:query => "# blahs where (a=b and c=4) or (aaa=5)").query_to_sql.should == expected_sql
490
+ end
491
+
492
+ end
493
+
494
+ end
495
+
496
+ describe "#host_filter_to_sql" do
497
+
498
+ it "should translate blah into EXISTS query" do
499
+ expected = "EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = 'a' )"
500
+ Appstats::Query.host_filter_to_sql("a").should == expected
501
+ Appstats::Query.host_filter_to_sql(" a ").should == expected
502
+ end
503
+
504
+ it "should ignore single quotes and spaces" do
505
+ Appstats::Query.host_filter_to_sql("bl'ah").should == "1=1"
506
+ Appstats::Query.host_filter_to_sql("bl ah").should == "1=1"
507
+ end
508
+
509
+ it "should do simple 1=1 if invalid" do
510
+ Appstats::Query.host_filter_to_sql("").should == "1=1"
511
+ Appstats::Query.host_filter_to_sql(nil).should == "1=1"
512
+ end
513
+
514
+ end
515
+
516
+ describe "#group_query_to_sql" do
517
+
518
+ before(:each) do
519
+ @template = "select id from appstats_entries where action = 'myblahs'"
520
+ end
521
+
522
+ it "should support no filters" do
523
+ query = Appstats::Query.new(:query => "# myblahs")
524
+ query.group_query_to_sql.should == nil
525
+ end
526
+
527
+ it "should support 1 filter" do
528
+ query = Appstats::Query.new(:query => "# myblahs group by aa")
529
+ 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"
530
+ query.group_query_to_sql.should == expected
531
+ end
532
+
533
+ it "should support surrounding quotes" do
534
+ query = Appstats::Query.new(:query => "# myblahs group by 'aa'")
535
+ 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"
536
+ query.group_query_to_sql.should == expected
537
+ end
538
+
539
+ it "should support inner quotes" do
540
+ query = Appstats::Query.new(:query => "# myblahs group by a's")
541
+ 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"
542
+ query.group_query_to_sql.should == expected
543
+ end
544
+
545
+
546
+ it "should support many filters" do
547
+ query = Appstats::Query.new(:query => "# myblahs group by aa, bbb")
548
+ 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"
549
+ query.group_query_to_sql.should == expected
550
+ end
551
+
552
+
553
+ end
554
+
555
+ describe "#contexts_filter_to_sql" do
556
+
557
+ before(:each) do
558
+ @template = "EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ("
559
+ end
560
+
561
+ it "should translate a = b into EXISTS query" do
562
+ Appstats::Query.new(:query => "# logins where a=b").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
563
+ Appstats::Query.new(:query => "# logins where a = b ").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
564
+ end
565
+
566
+ it "should ignore single quotes" do
567
+ Appstats::Query.new(:query => "# logins where 'aaa'='bbbb'").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
568
+ Appstats::Query.new(:query => "# logins where 'aaa' = 'bbbb' ").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
569
+ end
570
+
571
+ it "should allow for searching for all entries of a certain context" do
572
+ Appstats::Query.new(:query => "# logins where aaa").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa')))"
573
+ end
574
+
575
+ it "should allow for searching for several entries of a certain context" do
576
+ Appstats::Query.new(:query => "# logins where aaa || bbb").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa') or (context_key = 'bbb')))"
577
+ end
578
+
579
+ it "should allow complex queries" do
580
+ 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')))"
581
+ end
582
+
583
+ it "should support or" do
584
+ 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')))"
585
+ end
586
+
587
+ it "should support like" do
588
+ Appstats::Query.new(:query => "# logins where user like '%andrew%'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value like '%andrew%')))"
589
+ end
590
+
591
+ it "should support and" do
592
+ 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')))"
593
+ end
594
+
595
+
596
+ it "should do simple 1 = 1 if invalid" do
597
+ Appstats::Query.new(:query => "# logins where").contexts_filter_to_sql.should == "1=1"
598
+ Appstats::Query.new(:query => "# logins").contexts_filter_to_sql.should == "1=1"
599
+ end
600
+
601
+ end
602
+
603
+ describe "#sqlize" do
604
+
605
+ it "should handle nil" do
606
+ Appstats::Query.sqlize(nil).should == nil
607
+ Appstats::Query.sqlize('').should == ''
608
+ end
609
+
610
+ it "should understand &&" do
611
+ Appstats::Query.sqlize("&&").should == "and"
612
+ end
613
+
614
+ it "should understand ||" do
615
+ Appstats::Query.sqlize("||").should == "or"
616
+ end
617
+
618
+ it "should understand !=" do
619
+ Appstats::Query.sqlize("!=").should == "<>"
620
+ end
621
+
622
+ it "should set everything else as-is" do
623
+ Appstats::Query.sqlize("blah").should == "blah"
624
+ end
625
+
626
+ end
627
+
628
+ describe "#sqlclean" do
629
+
630
+ it "should handle nil" do
631
+ Appstats::Query.sqlclean(nil).should == nil
632
+ Appstats::Query.sqlclean('').should == ''
633
+ end
634
+
635
+ it "should remove exterior quotes" do
636
+ Appstats::Query.sqlclean("'a'").should == "a"
637
+ Appstats::Query.sqlclean("'bbb'").should == "bbb"
638
+ Appstats::Query.sqlclean('"a"').should == "a"
639
+ Appstats::Query.sqlclean('"bbb"').should == "bbb"
640
+ end
641
+
642
+ it "should handle normal text" do
643
+ Appstats::Query.sqlclean('abc').should == 'abc'
644
+ end
645
+
646
+ it "should handle slashes" do
647
+ Appstats::Query.sqlclean('a\b').should == 'a\\\\b'
648
+ end
649
+
650
+ it "should handle single quotes" do
651
+ Appstats::Query.sqlclean("a'b").should == "a''b"
652
+ end
653
+
654
+ end
655
+
656
+ describe "#comparators" do
657
+
658
+ it "should be a list " do
659
+ Appstats::Query.comparators.should == ["=","!=","<>",">","<",">=","<=","like"]
660
+ end
661
+
662
+ end
663
+
664
+ describe "#comparator?" do
665
+
666
+ it "should not consider nil" do
667
+ Appstats::Query.comparator?(nil).should == false
668
+ Appstats::Query.comparator?("").should == false
669
+ end
670
+
671
+
672
+ it "should not consider &&" do
673
+ Appstats::Query.comparator?("&&").should == false
674
+ end
675
+
676
+ it "should not consider ||" do
677
+ Appstats::Query.comparator?("||").should == false
678
+ end
679
+
680
+ it "should not consider and" do
681
+ Appstats::Query.comparator?("and").should == false
682
+ end
683
+
684
+ it "should not consider or" do
685
+ Appstats::Query.comparator?("or").should == false
686
+ end
687
+
688
+ it "should consider =" do
689
+ Appstats::Query.comparator?("=").should == true
690
+ end
691
+
692
+ it "should consider !=" do
693
+ Appstats::Query.comparator?("!=").should == true
694
+ end
695
+
696
+ it "should consider <>" do
697
+ Appstats::Query.comparator?("<>").should == true
698
+ end
699
+
700
+ it "should consider >" do
701
+ Appstats::Query.comparator?(">").should == true
702
+ end
703
+
704
+ it "should consider <" do
705
+ Appstats::Query.comparator?("<").should == true
706
+ end
707
+
708
+ it "should consider >=" do
709
+ Appstats::Query.comparator?(">=").should == true
710
+ end
711
+
712
+ it "should consider <=" do
713
+ Appstats::Query.comparator?("<=").should == true
714
+ end
715
+
716
+
717
+ end
689
718
 
690
719
 
691
720