appstats 0.19.1 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
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