appstats 0.20.2 → 0.20.6

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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- appstats (0.20.2)
4
+ appstats (0.20.6)
5
5
  daemons
6
6
  net-scp
7
7
  rails (>= 2.3.0)
@@ -4,6 +4,18 @@ module Appstats
4
4
 
5
5
  attr_accessible :name, :status
6
6
 
7
+ def self.rename(old_key,new_key)
8
+ sql = ["update appstats_context_keys set name = ?, updated_at = ? where name = ?",new_key,Time.now,old_key]
9
+ ActiveRecord::Base.connection.update(ActiveRecord::Base.send(:sanitize_sql_array, sql))
10
+
11
+ sql = ["update appstats_contexts set context_key = ?, updated_at = ? where context_key = ?",new_key,Time.now,old_key]
12
+ ActiveRecord::Base.connection.update(ActiveRecord::Base.send(:sanitize_sql_array, sql))
13
+
14
+ sql = ["update appstats_action_context_keys set context_key = ?, updated_at = ? where context_key = ?",new_key,Time.now,old_key]
15
+ ActiveRecord::Base.connection.update(ActiveRecord::Base.send(:sanitize_sql_array, sql))
16
+
17
+ end
18
+
7
19
  def self.update_context_keys
8
20
  sql = "select distinct(context_key) from appstats_contexts where context_key not in (select name from appstats_context_keys)"
9
21
  count = 0
@@ -194,14 +194,40 @@ module Appstats
194
194
  @tokenize_regex = nil
195
195
  @tokenize_regex_no_spaces = nil
196
196
  return if @raw_tokenize.blank?
197
+ is_multi_work_token = false
198
+ current_token = nil
197
199
  @raw_tokenize.split(" ").each do |token|
198
- current_token = token.upcase
200
+
201
+ start_token = token.starts_with?("'")
202
+ end_token = is_multi_work_token and token.ends_with?("'")
203
+ mid_token = !start_token && !end_token && is_multi_work_token
204
+ add_token = false
205
+
206
+ if start_token
207
+ current_token = token.upcase[1..-1]
208
+ is_multi_work_token = true
209
+ elsif mid_token
210
+ current_token = "#{current_token}#{token.upcase}"
211
+ elsif end_token
212
+ current_token = "#{current_token}#{token.upcase.chop}"
213
+ is_multi_work_token = false
214
+ add_token = true
215
+ else
216
+ current_token = token.upcase
217
+ add_token = true
218
+ end
219
+
199
220
  current_token.gsub!("(",'\(')
200
221
  current_token.gsub!(")",'\)')
201
222
  current_token.gsub!("|",'\|')
202
- @tokenize_no_spaces<< current_token
203
- current_token = "\\s+#{current_token}(\\s|$)" unless current_token.match(/.*[a-z].*/i).nil?
204
- @tokenize<< current_token
223
+
224
+ if add_token
225
+ @tokenize_no_spaces<< current_token
226
+ current_token = "\\s+#{current_token}(\\s|$)" unless current_token.match(/.*[a-z].*/i).nil?
227
+ @tokenize<< current_token
228
+ else is_multi_work_token
229
+ current_token = "#{current_token}\\s+"
230
+ end
205
231
  end
206
232
  @tokenize_regex_no_spaces = @tokenize_no_spaces.join("|")
207
233
  @tokenize_regex = @tokenize.join("|")
@@ -3,7 +3,7 @@ module Appstats
3
3
  class Query
4
4
 
5
5
  @@parser_template = Appstats::Parser.new(:rules => ":operation :action :date on :host where :contexts group by :group_by")
6
- @@contexts_parser_template = Appstats::Parser.new(:rules => ":context", :repeating => true, :tokenize => "and or || && = <= >= <> < > != ( ) like")
6
+ @@contexts_parser_template = Appstats::Parser.new(:rules => ":context", :repeating => true, :tokenize => "( ) and or || && = <= >= <> < > != like 'not like' in")
7
7
  @@group_by_parser_template = Appstats::Parser.new(:rules => ":filter", :repeating => true, :tokenize => ",")
8
8
 
9
9
  @@nill_query = "select 0 from appstats_entries LIMIT 1"
@@ -35,6 +35,19 @@ module Appstats
35
35
 
36
36
  end
37
37
 
38
+ def find(job_frequency_if_not_available = 'once')
39
+ result = Appstats::Result.where("query = ? and is_latest = 1",@query).first
40
+ if result.nil?
41
+ if job_frequency_if_not_available.nil?
42
+ result = run
43
+ else
44
+ job_frequency_if_not_available = "once" if job_frequency_if_not_available == true
45
+ Appstats::ResultJob.create(:name => "Missing Query#find requested", :frequency => job_frequency_if_not_available, :query => @query, :query_type => @query_type)
46
+ end
47
+ end
48
+ result
49
+ end
50
+
38
51
  def run
39
52
  result = Appstats::Result.new(:name => @name, :result_type => @result_type, :query => @query, :query_to_sql => @query_to_sql, :action => @action, :host => @host, :from_date => @date_range.from_date, :to_date => @date_range.to_date, :contexts => @contexts, :query_type => @query_type)
40
53
  unless @group_by.empty?
@@ -130,12 +143,12 @@ module Appstats
130
143
  if status == :next
131
144
  status = :waiting_comparator
132
145
  @parsed_contexts<< { :context_key => entry[:context] }
133
- sql += " (context_key = '#{Query.sqlclean(entry[:context])}'"
146
+ sql += " (context_key = #{Query.sqlquote(entry[:context])}"
134
147
  else
135
148
  status = :next
136
149
  @parsed_contexts.last[:context_value] = entry[:context]
137
150
  @parsed_contexts.last[:comparator] = comparator
138
- sql += " and context_value #{comparator} '#{Query.sqlclean(entry[:context])}')"
151
+ sql += " and context_value #{comparator} #{Query.sqlquote(entry[:context],comparator)})"
139
152
  end
140
153
  end
141
154
  sql += ")" if status == :waiting_comparator
@@ -150,6 +163,15 @@ module Appstats
150
163
  input
151
164
  end
152
165
 
166
+ def self.sqlquote(raw_input,comparator = '=')
167
+ return "NULL" if raw_input.nil?
168
+ if ["in"].include?(comparator)
169
+ return "(" + raw_input.split(",").collect { |x| sqlquote(x) }.join (",") + ")"
170
+ else
171
+ return "'#{sqlclean(raw_input)}'"
172
+ end
173
+ end
174
+
153
175
  def self.sqlclean(raw_input)
154
176
  return raw_input if raw_input.blank?
155
177
  m = raw_input.match(/^['"](.*)['"]$/)
@@ -164,7 +186,7 @@ module Appstats
164
186
  end
165
187
 
166
188
  def self.comparators
167
- ["=","!=","<>",">","<",">=","<=","like"]
189
+ ["=","!=","<>",">","<",">=","<=","like","not like","in"]
168
190
  end
169
191
 
170
192
  private
@@ -243,7 +265,7 @@ module Appstats
243
265
 
244
266
  unless @group_by.empty?
245
267
  query_to_sql_with_id = @query_to_sql.sub("count(*) as num","id")
246
- group_as_sql = @group_by.collect { |g| "'#{Query.sqlclean(g)}'" }.join(',')
268
+ group_as_sql = @group_by.collect { |g| "#{Query.sqlquote(g)}" }.join(',')
247
269
  @group_query_to_sql = "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 (#{group_as_sql}) and appstats_entry_id in ( #{query_to_sql_with_id} ) group by appstats_entry_id) results group by context_value_filter"
248
270
  end
249
271
 
@@ -1,3 +1,3 @@
1
1
  module Appstats
2
- VERSION = "0.20.2"
2
+ VERSION = "0.20.6"
3
3
  end
@@ -46,6 +46,39 @@ module Appstats
46
46
 
47
47
  end
48
48
 
49
+ describe "#rename" do
50
+
51
+ it "should update the ContextKey" do
52
+ context_key = Appstats::ContextKey.create(:name => 'a', :status => 'c')
53
+ Appstats::ContextKey.rename('a','aaa')
54
+ context_key.reload
55
+ context_key.name.should == 'aaa'
56
+ end
57
+
58
+ it "should update all Contexts" do
59
+ context = Appstats::Context.create(:context_key => 'b')
60
+ context2 = Appstats::Context.create(:context_key => 'notb')
61
+ Appstats::ContextKey.rename('b','bbb')
62
+ context.reload and context2.reload
63
+
64
+ context.context_key.should == 'bbb'
65
+ context2.context_key.should == 'notb'
66
+ end
67
+
68
+ it "should update ActionContextKeys" do
69
+ action = Appstats::ActionContextKey.create(:action_name => 'a', :context_key => 'b', :status => 'c')
70
+ action2 = Appstats::ActionContextKey.create(:action_name => 'a', :context_key => 'notb', :status => 'c')
71
+
72
+ Appstats::ContextKey.rename('b','bbb')
73
+ action.reload and action2.reload
74
+
75
+ action.context_key.should == 'bbb'
76
+ action2.context_key.should == 'notb'
77
+ end
78
+
79
+
80
+ end
81
+
49
82
 
50
83
  end
51
84
  end
@@ -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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
196
+ entry = Entry.create_from_logger_string("0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
199
+ entry.raw_entry.should == "0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
204
+ entry = Entry.create_from_logger_string("0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
207
+ entry.raw_entry.should == "0.20.6 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.20.2 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.20.6 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.20.2 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
220
+ entry.raw_entry.should == "0.20.6 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.20.2 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.20.6 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.20.2 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
234
+ entry.raw_entry.should == "0.20.6 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"
@@ -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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
125
+ Appstats::Logger.raw_read.should == ["0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
130
+ Appstats::Logger.raw_read.should == ["0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
140
+ Appstats::Logger.raw_read.should == ["0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
157
+ actual = Appstats::Logger.entry_to_hash("0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
163
+ actual = Appstats::Logger.entry_to_hash("0.20.6 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.20.2 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.20.6 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.20.2 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.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
181
+ actual = Appstats::Logger.entry_to_hash("0.20.6 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.20.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
187
+ actual = Appstats::Logger.entry_to_hash("0.20.6 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.20.2 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
191
+ actual = Appstats::Logger.entry_to_hash("0.20.6 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.20.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
197
+ actual = Appstats::Logger.entry_to_hash("0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
206
+ expected = "0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
212
+ expected = "0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
219
+ expected = "0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
225
+ expected = "0.20.6 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.20.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
231
+ expected = "0.20.6 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.20.2 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
235
+ expected = "0.20.6 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.20.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
241
+ expected = "0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
247
+ expected = "0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
253
+ expected = "0.20.6 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.20.2 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
259
+ expected = "0.20.6 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.20.2 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
265
+ expected = "0.20.6 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
@@ -19,7 +19,7 @@ module Appstats
19
19
  @parser.constants.should == []
20
20
  @parser.constants_no_spaces.should == []
21
21
  end
22
-
22
+
23
23
  it "should set rules from constructor" do
24
24
  parser = Parser.new(:rules => ":name or :bust", :tokenize => "a bb c", :repeating => true)
25
25
  parser.raw_rules.should == ":name or :bust"
@@ -31,6 +31,13 @@ module Appstats
31
31
  parser.constants.should == ["\\s+OR(\\s|$)"]
32
32
  parser.constants_no_spaces.should == ["OR"]
33
33
  end
34
+
35
+ it "should tokenize multi words" do
36
+ parser = Parser.new(:rules => ":name or :bust", :tokenize => "a 'not a'", :repeating => true)
37
+ parser.tokenize.should == ["\\s+A(\\s|$)","\\s+NOT\\s+A(\\s|$)"]
38
+ parser.tokenize_no_spaces.should == ["A","NOT\\s+A"]
39
+ end
40
+
34
41
 
35
42
  it "should espace tokens as required" do
36
43
  parser = Parser.new(:tokenize => "( ) abc |")
@@ -48,8 +55,7 @@ module Appstats
48
55
  it "should end on constant if tokens present" do
49
56
  Parser.new(:rules => ":name", :tokenize => ")").rules.should == [ { :rule => :name, :stop => :end } ]
50
57
  end
51
-
52
-
58
+
53
59
  it "should handle one variable" do
54
60
  Parser.new(:rules => ":name").rules.should == [ { :rule => :name, :stop => :end } ]
55
61
  end
@@ -355,6 +361,19 @@ module Appstats
355
361
  parser.parse("( ( a = b ) )").should == true
356
362
  parser.raw_results.should == [ "(", "(", { :context_key => "a"}, "=", { :context_value => "b"}, ")", ")" ]
357
363
  end
364
+
365
+ it "should handle tokens with spaces" do
366
+ parser = Parser.new(:rules => ":context", :repeating => true, :tokenize => "like 'not like'")
367
+ parser.parse("a not like b").should == true
368
+ parser.raw_results.should == [ { :context => "a"}, "not like", { :context => "b"} ]
369
+ end
370
+
371
+ it "should handle tokens with many spaces" do
372
+ parser = Parser.new(:rules => ":context", :repeating => true, :tokenize => "like 'not like'")
373
+ parser.parse("a not like b").should == true
374
+ parser.raw_results.should == [ { :context => "a"}, "not like", { :context => "b"} ]
375
+ end
376
+
358
377
 
359
378
  it "should tokenize letters only if spaces between them" do
360
379
  parser = Appstats::Parser.new(:rules => ":one :two", :tokenize => "( aa a1 )")
@@ -120,13 +120,105 @@ module Appstats
120
120
 
121
121
  end
122
122
 
123
+ end
124
+
125
+ describe "#find" do
126
+
127
+ before(:each) do
128
+ Appstats::Entry.delete_all
129
+ Appstats::Result.delete_all
130
+ end
131
+
132
+ describe "run right away" do
133
+
134
+ it "should run the query if it has not been run yet" do
135
+ Appstats::Entry.create(:action => "myblahs")
136
+
137
+ Time.stub!(:now).and_return(Time.parse("2010-09-20"))
138
+ query = Appstats::Query.new(:query => "# myblahs")
139
+ query.find(nil).count.should == 1
140
+
141
+ Appstats::Entry.create(:action => "myblahs")
142
+ query.find(nil).count.should == 1
143
+
144
+ Time.stub!(:now).and_return(Time.parse("2010-09-21"))
145
+ query = Appstats::Query.new(:query => "# myblahs")
146
+ query.run.count.should == 2
147
+
148
+ query = Appstats::Query.new(:query => "# myblahs")
149
+ query.find(nil).count.should == 2
150
+ end
151
+
152
+ end
153
+
154
+ describe "do not run right away" do
155
+
156
+ it "should return nil no result available" do
157
+ Appstats::Entry.create(:action => "myblahs")
158
+
159
+ query = Appstats::Query.new(:query => "# myblahs")
160
+ query.find.should == nil
161
+
162
+ query = Appstats::Query.new(:query => "# myblahs")
163
+ query.run.count.should == 1
164
+
165
+ query = Appstats::Query.new(:query => "# myblahs")
166
+ query.find.count.should == 1
167
+ end
168
+
169
+ it "should schedule the query to be run" do
170
+
171
+ query = Query.new(:query => "# x", :query_type => "Appstats::TestQuery")
172
+ query.find.should == nil
173
+
174
+ job = Appstats::ResultJob.last
175
+ job.name.should == "Missing Query#find requested"
176
+ job.frequency.should == 'once'
177
+ job.query.should == "# x"
178
+ job.query_type.should == "Appstats::TestQuery"
179
+ end
180
+
181
+ it "should allow scheduling to be set" do
182
+
183
+ query = Query.new(:query => "# myblahs")
184
+ query.find('daily').should == nil
185
+
186
+ job = Appstats::ResultJob.last
187
+ job.name.should == "Missing Query#find requested"
188
+ job.frequency.should == 'daily'
189
+ job.query.should == "# myblahs"
190
+ job.query_type.should == nil
191
+ end
192
+
193
+ end
194
+
195
+
196
+
123
197
  end
124
198
 
125
199
  describe "#run" do
126
200
 
127
201
  before(:each) do
128
202
  Appstats::Entry.delete_all
203
+ Appstats::Result.delete_all
129
204
  end
205
+
206
+ it "should update is_latest accordingly" do
207
+ Appstats::Entry.create(:action => "myblahs")
208
+
209
+ Time.stub!(:now).and_return(Time.parse("2010-09-20"))
210
+ query = Appstats::Query.new(:query => "# myblahs")
211
+ result = query.run
212
+ result.is_latest.should == true
213
+
214
+ Time.stub!(:now).and_return(Time.parse("2010-09-21"))
215
+ query = Appstats::Query.new(:query => "# myblahs")
216
+ result2 = query.run
217
+ result.reload
218
+ result.is_latest.should == false
219
+ result2.is_latest.should == true
220
+ end
221
+
130
222
 
131
223
  describe "core search" do
132
224
  it "should return 0 if no results" do
@@ -267,6 +359,8 @@ module Appstats
267
359
  before(:each) do
268
360
  Appstats::Entry.delete_all
269
361
  Appstats::Context.delete_all
362
+ Appstats::Result.delete_all
363
+ Appstats::SubResult.delete_all
270
364
  end
271
365
 
272
366
  it "should not create sub results if no group_by" do
@@ -600,6 +694,14 @@ module Appstats
600
694
  it "should support like" do
601
695
  Appstats::Query.new(:query => "# logins where user like '%andrew%'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value like '%andrew%')))"
602
696
  end
697
+
698
+ it "should support not like" do
699
+ Appstats::Query.new(:query => "# logins where user not like '%andrew%'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value not like '%andrew%')))"
700
+ end
701
+
702
+ it "should support in" do
703
+ Appstats::Query.new(:query => "# logins where user_id in 1,2,3").contexts_filter_to_sql.should == "#{@template} (context_key = 'user_id' and context_value in ('1','2','3'))))"
704
+ end
603
705
 
604
706
  it "should support and" do
605
707
  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')))"
@@ -613,6 +715,23 @@ module Appstats
613
715
 
614
716
  end
615
717
 
718
+ describe "#sqlquote" do
719
+
720
+ it "should handle nil" do
721
+ Appstats::Query.sqlquote(nil).should == "NULL"
722
+ Appstats::Query.sqlquote('').should == "''"
723
+ end
724
+
725
+ it "should handle simple data" do
726
+ Appstats::Query.sqlquote("blah").should == "'blah'"
727
+ end
728
+
729
+ it "should handle IN comparator" do
730
+ Appstats::Query.sqlquote("1,2,3","in").should == "('1','2','3')"
731
+ end
732
+
733
+ end
734
+
616
735
  describe "#sqlize" do
617
736
 
618
737
  it "should handle nil" do
@@ -669,7 +788,7 @@ module Appstats
669
788
  describe "#comparators" do
670
789
 
671
790
  it "should be a list " do
672
- Appstats::Query.comparators.should == ["=","!=","<>",">","<",">=","<=","like"]
791
+ Appstats::Query.comparators.should == ["=","!=","<>",">","<",">=","<=","like","not like","in"]
673
792
  end
674
793
 
675
794
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appstats
3
3
  version: !ruby/object:Gem::Version
4
- hash: 75
4
+ hash: 67
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 20
9
- - 2
10
- version: 0.20.2
9
+ - 6
10
+ version: 0.20.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Forward
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-30 00:00:00 -04:00
18
+ date: 2011-04-06 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency