appstats 0.15.1 → 0.16.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- appstats (0.15.1)
4
+ appstats (0.16.1)
5
5
  daemons
6
6
  net-scp
7
7
  rails (>= 2.3.0)
@@ -0,0 +1,11 @@
1
+ class AddAppstatsResultsQueryType < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :appstats_results, :query_type, :string
4
+ add_column :appstats_result_jobs, :query_type, :string
5
+ end
6
+
7
+ def self.down
8
+ remove_column :appstats_results, :query_type
9
+ remove_column :appstats_result_jobs, :query_type
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class RenameAppstatsResultsQueryAsSqlToQueryToSql < ActiveRecord::Migration
2
+ def self.up
3
+ rename_column :appstats_results, :query_as_sql, :query_to_sql
4
+ end
5
+
6
+ def self.down
7
+ rename_column :appstats_results, :query_to_sql, :query_as_sql
8
+ end
9
+ end
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended to check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(:version => 20110301195959) do
13
+ ActiveRecord::Schema.define(:version => 20110301230757) do
14
14
 
15
15
  create_table "appstats_actions", :force => true do |t|
16
16
  t.string "name"
@@ -102,13 +102,14 @@ ActiveRecord::Schema.define(:version => 20110301195959) do
102
102
  t.datetime "last_run_at"
103
103
  t.datetime "created_at"
104
104
  t.datetime "updated_at"
105
+ t.string "query_type"
105
106
  end
106
107
 
107
108
  create_table "appstats_results", :force => true do |t|
108
109
  t.string "name"
109
110
  t.string "result_type"
110
111
  t.text "query"
111
- t.text "query_as_sql"
112
+ t.text "query_to_sql"
112
113
  t.integer "count"
113
114
  t.string "action"
114
115
  t.string "host"
@@ -120,6 +121,7 @@ ActiveRecord::Schema.define(:version => 20110301195959) do
120
121
  t.text "contexts"
121
122
  t.text "group_query_to_sql"
122
123
  t.string "group_by"
124
+ t.string "query_type"
123
125
  end
124
126
 
125
127
  add_index "appstats_results", ["action"], :name => "index_appstats_results_on_action"
@@ -19,6 +19,7 @@ require "#{File.dirname(__FILE__)}/appstats/host"
19
19
  require "#{File.dirname(__FILE__)}/appstats/context_key"
20
20
  require "#{File.dirname(__FILE__)}/appstats/context_value"
21
21
  require "#{File.dirname(__FILE__)}/appstats/test_object"
22
+ require "#{File.dirname(__FILE__)}/appstats/test_query"
22
23
 
23
24
  # required in the appstats.gemspec
24
25
  unless Appstats.const_defined?(:VERSION)
@@ -3,15 +3,16 @@ 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")
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"
10
10
  @@default = "1=1"
11
- attr_accessor :name, :query, :action, :host, :date_range, :query_to_sql, :contexts, :group_by, :group_query_to_sql
11
+ attr_accessor :name, :query, :action, :host, :date_range, :query_to_sql, :contexts, :parsed_contexts, :group_by, :group_query_to_sql, :query_type
12
12
 
13
13
  def initialize(data = {})
14
14
  @name = data[:name]
15
+ @query_type = data[:query_type]
15
16
  @result_type = data[:result_type] || "on_demand"
16
17
  self.query=(data[:query])
17
18
  end
@@ -19,20 +20,34 @@ module Appstats
19
20
  def query=(value)
20
21
  @query = value
21
22
  parse_query
23
+
24
+ unless @query_type.nil?
25
+
26
+ all_names = @query_type.split("::")
27
+ if all_names.size == 1
28
+ @custom_query = Object::const_get(@query_type).new
29
+ else
30
+ @custom_query = eval(all_names[0...-1].join("::")).const_get(all_names.last).new
31
+ end
32
+ @custom_query.query = self
33
+ @custom_query.process_query
34
+ end
35
+
22
36
  end
23
37
 
24
38
  def run
25
- result = Appstats::Result.new(:name => @name, :result_type => @result_type, :query => @query, :query_as_sql => @query_to_sql, :action => @action, :host => @host, :from_date => @date_range.from_date, :to_date => @date_range.to_date, :contexts => @contexts)
39
+ 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)
26
40
  unless @group_by.empty?
27
41
  result.group_by = @group_by.join(", ")
28
42
  result.group_query_to_sql = @group_query_to_sql
29
43
  end
44
+
30
45
  result.group_by = @group_by.join(", ") unless @group_by.empty?
31
- result.count = ActiveRecord::Base.connection.select_one(@query_to_sql)["count(*)"].to_i
46
+ result.count = run_query { |conn| conn.select_one(@query_to_sql)["num"].to_i }
32
47
  result.save
33
-
48
+
34
49
  unless @group_by.empty?
35
- all_sub_results = ActiveRecord::Base.connection.select_all(@group_query_to_sql)
50
+ all_sub_results = run_query { |conn| conn.select_all(@group_query_to_sql) }
36
51
  all_sub_results.each do |data|
37
52
  keys = data["context_key_filter"].split(",")
38
53
  values = data["context_value_filter"].split(",")
@@ -57,32 +72,36 @@ module Appstats
57
72
  "EXISTS (select * from appstats_log_collectors where appstats_entries.appstats_log_collector_id = appstats_log_collectors.id and host = '#{host}' )"
58
73
  end
59
74
 
60
- def self.contexts_filter_to_sql(raw_input)
75
+ def contexts_filter_to_sql
61
76
  context_parser = @@contexts_parser_template.dup
62
- return @@default if (raw_input.blank? || !context_parser.parse(raw_input))
77
+ return @@default if @contexts.blank? || !context_parser.parse(@contexts)
63
78
  sql = "EXISTS (select * from appstats_contexts where appstats_entries.id = appstats_contexts.appstats_entry_id and ("
64
79
 
65
80
  status = :next
66
81
  comparator = "="
67
82
  context_parser.raw_results.each do |entry|
68
83
  if entry.kind_of?(String)
69
- sqlentry = sqlize(entry)
84
+ sqlentry = Query.sqlize(entry)
70
85
  if Query.comparator?(entry) && status == :waiting_comparator
71
- comparator = sqlize(entry)
86
+ comparator = Query.sqlize(entry)
72
87
  status = :waiting_operand
73
88
  else
74
89
  sql += ")" if status == :waiting_comparator
75
90
  sql += " #{sqlentry}"
91
+ @parsed_contexts<< sqlentry
76
92
  status = :next
77
93
  end
78
94
  next
79
95
  end
80
96
  if status == :next
81
97
  status = :waiting_comparator
82
- sql += " (context_key = '#{sqlclean(entry[:context])}'"
98
+ @parsed_contexts<< { :context_key => entry[:context] }
99
+ sql += " (context_key = '#{Query.sqlclean(entry[:context])}'"
83
100
  else
84
101
  status = :next
85
- sql += " and context_value #{comparator} '#{sqlclean(entry[:context])}')"
102
+ @parsed_contexts.last[:context_value] = entry[:context]
103
+ @parsed_contexts.last[:comparator] = comparator
104
+ sql += " and context_value #{comparator} '#{Query.sqlclean(entry[:context])}')"
86
105
  end
87
106
  end
88
107
  sql += ")" if status == :waiting_comparator
@@ -116,6 +135,25 @@ module Appstats
116
135
 
117
136
  private
118
137
 
138
+ def db_connection
139
+ return ActiveRecord::Base.connection if @custom_query.nil?
140
+ @backup_config = ActiveRecord::Base.connection.instance_variable_get(:@config)
141
+ custom_connection = @custom_query.db_connection
142
+ end
143
+
144
+ def restore_connection
145
+ return if @backup_config.nil?
146
+ ActiveRecord::Base.establish_connection @backup_config
147
+ @backup_config = nil
148
+ end
149
+
150
+ def run_query
151
+ results = yield db_connection
152
+ restore_connection
153
+ results
154
+ end
155
+
156
+
119
157
  def normalize_action_name(action_name)
120
158
  action = Appstats::Action.where("plural_name = ?",action_name).first
121
159
  action.nil? ? action_name : action.name
@@ -130,6 +168,12 @@ module Appstats
130
168
  end
131
169
  end
132
170
 
171
+ def parse_contexts(raw_input)
172
+ @contexts = raw_input
173
+ context_parser = @@contexts_parser_template.dup
174
+ return if (raw_input.blank? || !context_parser.parse(raw_input))
175
+ end
176
+
133
177
  def parse_query
134
178
  reset_query
135
179
  return nil_query if @query.nil?
@@ -142,21 +186,21 @@ module Appstats
142
186
  @action = normalize_action_name(parser.results[:action])
143
187
  @date_range = DateRange.parse(parser.results[:date])
144
188
  @host = parser.results[:host]
145
- @contexts = parser.results[:contexts]
189
+ parse_contexts(parser.results[:contexts])
146
190
  parse_group_by(parser.results[:group_by])
147
191
 
148
192
  if @operation == "#"
149
- @query_to_sql = "select count(*) from appstats_entries"
193
+ @query_to_sql = "select count(*) as num from appstats_entries"
150
194
  @query_to_sql += " where action = '#{@action}'" unless @action.blank?
151
195
  @query_to_sql += " and #{@date_range.to_sql}" unless @date_range.to_sql == "1=1"
152
196
  @query_to_sql += " and #{Query.host_filter_to_sql(@host)}" unless @host.nil?
153
- @query_to_sql += " and #{Query.contexts_filter_to_sql(@contexts)}" unless @contexts.nil?
197
+ @query_to_sql += " and #{contexts_filter_to_sql}" unless @contexts.nil?
154
198
  end
155
199
 
156
200
  unless @group_by.empty?
157
- query_to_sql_with_id = @query_to_sql.sub("count(*)","id")
201
+ query_to_sql_with_id = @query_to_sql.sub("count(*) as num","id")
158
202
  group_as_sql = @group_by.collect { |g| "'#{Query.sqlclean(g)}'" }.join(',')
159
- @group_query_to_sql = "select context_key_filter, context_value_filter, count(*) 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;"
203
+ @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"
160
204
  end
161
205
 
162
206
  @query_to_sql
@@ -183,6 +227,8 @@ module Appstats
183
227
  nil_query
184
228
  @date_range = DateRange.new
185
229
  @group_by = []
230
+ @contexts = nil
231
+ @parsed_contexts = []
186
232
  end
187
233
 
188
234
  end
@@ -2,7 +2,7 @@ module Appstats
2
2
  class Result < ActiveRecord::Base
3
3
  set_table_name "appstats_results"
4
4
 
5
- attr_accessible :name, :result_type, :query, :query_as_sql, :count, :action, :host, :from_date, :to_date, :contexts, :group_by
5
+ attr_accessible :name, :result_type, :query, :query_to_sql, :count, :action, :host, :from_date, :to_date, :contexts, :group_by, :query_type
6
6
  has_many :sub_results, :table_name => 'appstats_subresults', :foreign_key => 'appstats_result_id', :order => 'count DESC'
7
7
 
8
8
  def date_to_s
@@ -47,7 +47,7 @@ module Appstats
47
47
  private
48
48
 
49
49
  def state
50
- [name, result_type, query, query_as_sql, count, action, host, from_date, to_date,contexts,group_by]
50
+ [name, result_type, query, query_to_sql, count, action, host, from_date, to_date,contexts,group_by,query_type]
51
51
  end
52
52
 
53
53
 
@@ -2,7 +2,7 @@ module Appstats
2
2
  class ResultJob < ActiveRecord::Base
3
3
  set_table_name "appstats_result_jobs"
4
4
 
5
- attr_accessible :name, :frequency, :status, :query, :last_run_at
5
+ attr_accessible :name, :frequency, :status, :query, :last_run_at, :query_type
6
6
 
7
7
  @@frequency_methods =
8
8
 
@@ -0,0 +1,42 @@
1
+
2
+ module Appstats
3
+ class TestQuery
4
+
5
+ attr_accessor :query, :query_to_sql, :group_query_to_sql
6
+
7
+ def process_query
8
+ query.query_to_sql = "select count(*) as num from appstats_test_objects"
9
+ query.group_query_to_sql = "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"
10
+ end
11
+
12
+ def db_connection
13
+ if query.host == "otherServer"
14
+ dbconfig = YAML::load(File.open('db/config.yml'))
15
+ ActiveRecord::Base.establish_connection(dbconfig['development']).connection
16
+ else
17
+ ActiveRecord::Base.connection
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ module Core
24
+ class AnotherTestQuery
25
+ attr_accessor :query
26
+ def process_query; end
27
+ def db_connection
28
+ ActiveRecord::Base.connection
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ class YetAnotherTestQuery
37
+ attr_accessor :query
38
+ def process_query; end
39
+ def db_connection
40
+ ActiveRecord::Base.connection
41
+ end
42
+ end
@@ -1,3 +1,3 @@
1
1
  module Appstats
2
- VERSION = "0.15.1"
2
+ VERSION = "0.16.1"
3
3
  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.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
196
+ entry = Entry.create_from_logger_string("0.16.1 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.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
199
+ entry.raw_entry.should == "0.16.1 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.15.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.16.1 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.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
207
+ entry.raw_entry.should == "0.16.1 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.15.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.16.1 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.15.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
220
+ entry.raw_entry.should == "0.16.1 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.15.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.16.1 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.15.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
234
+ entry.raw_entry.should == "0.16.1 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"
@@ -115,12 +115,12 @@ module Appstats
115
115
 
116
116
  it "should accept numbers" do
117
117
  Appstats::Logger.entry(5, :blah => 6)
118
- Appstats::Logger.raw_read.should == ["0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
118
+ Appstats::Logger.raw_read.should == ["0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
119
119
  end
120
120
 
121
121
  it "should accept arrays" do
122
122
  Appstats::Logger.entry('search', :provider => [ 'one', 'two' ])
123
- Appstats::Logger.raw_read.should == ["0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
123
+ Appstats::Logger.raw_read.should == ["0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
124
124
  end
125
125
 
126
126
 
@@ -130,7 +130,7 @@ module Appstats
130
130
 
131
131
  it "should look similar to regular entry" do
132
132
  Appstats::Logger.exception_entry(RuntimeError.new("blah"),:on => "login")
133
- Appstats::Logger.raw_read.should == ["0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
133
+ Appstats::Logger.raw_read.should == ["0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
134
134
  end
135
135
 
136
136
  end
@@ -147,47 +147,47 @@ module Appstats
147
147
 
148
148
  it "should handle a statistics entry" do
149
149
  expected = { :action => "address_search", :timestamp => "2010-09-21 23:15:20" }
150
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
150
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
151
151
  actual.should == expected
152
152
  end
153
153
 
154
154
  it "should handle contexts" do
155
155
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
156
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
156
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
157
157
  actual.should == expected
158
158
  end
159
159
 
160
160
  it "should handle multiple actions" do
161
161
  expected = { :action => ["address_filter", "blah"], :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
162
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
162
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
163
163
  actual.should == expected
164
164
  end
165
165
 
166
166
  it "should handle multiple of same context" do
167
167
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => ['Sin','Market'] }
168
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
168
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
169
169
  actual.should == expected
170
170
  end
171
171
 
172
172
  it "should handle no actions" do
173
173
  expected = { :action => "UNKNOWN_ACTION", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
174
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
174
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
175
175
  actual.should == expected
176
176
  end
177
177
 
178
178
  it "should handle actions with the delimiter (and change the delimiter)" do
179
179
  expected = { :action => "address:=search-n", :timestamp => "2010-09-21 23:15:20" }
180
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
180
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
181
181
  actual.should == expected
182
182
 
183
183
  expected = { :action => "address::search==--n", :timestamp => "2010-09-21 23:15:20" }
184
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
184
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
185
185
  actual.should == expected
186
186
  end
187
187
 
188
188
  it "should handle contexts with the delimiter (and change the delimiter)" do
189
189
  expected = { :action => "address", :timestamp => "2010-09-21 23:15:20", :server => "market:eval=-n" }
190
- actual = Appstats::Logger.entry_to_hash("0.15.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
190
+ actual = Appstats::Logger.entry_to_hash("0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
191
191
  actual.should == expected
192
192
  end
193
193
 
@@ -196,66 +196,66 @@ module Appstats
196
196
  describe "#entry_to_s" do
197
197
 
198
198
  it "should handle a statistics entry" do
199
- expected = "0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
199
+ expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
200
200
  actual = Appstats::Logger.entry_to_s("address_search")
201
201
  actual.should == expected
202
202
  end
203
203
 
204
204
  it "should handle numbers" do
205
- expected = "0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
205
+ expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
206
206
  actual = Appstats::Logger.entry_to_s(1,:note => 2.2)
207
207
  actual.should == expected
208
208
  end
209
209
 
210
210
  it "should handle default contexts" do
211
211
  Appstats::Logger.default_contexts[:app_name] = "market"
212
- expected = "0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
212
+ expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
213
213
  actual = Appstats::Logger.entry_to_s("address_search")
214
214
  actual.should == expected
215
215
  end
216
216
 
217
217
  it "should handle contexts (and sort them by symbol)" do
218
- expected = "0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
218
+ expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
219
219
  actual = Appstats::Logger.entry_to_s("address_filter", { :server => "Live", :app_name => 'Market' })
220
220
  actual.should == expected
221
221
  end
222
222
 
223
223
  it "should handle actions with the delimiter (and change the delimiter)" do
224
- expected = "0.15.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
224
+ expected = "0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
225
225
  actual = Appstats::Logger.entry_to_s("address:=search-n")
226
226
  actual.should == expected
227
227
 
228
- expected = "0.15.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
228
+ expected = "0.16.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
229
229
  actual = Appstats::Logger.entry_to_s("address::search==--n")
230
230
  actual.should == expected
231
231
  end
232
232
 
233
233
  it "should handle contexts with the delimiter (and change the delimiter)" do
234
- expected = "0.15.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
234
+ expected = "0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
235
235
  actual = Appstats::Logger.entry_to_s("address", :server => 'market:eval=-n')
236
236
  actual.should == expected
237
237
  end
238
238
 
239
239
  it "should ignore spaces" do
240
- expected = "0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
240
+ expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
241
241
  actual = Appstats::Logger.entry_to_s("address search")
242
242
  actual.should == expected
243
243
  end
244
244
 
245
245
  it "should convert newlines in action" do
246
- expected = "0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
246
+ expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
247
247
  actual = Appstats::Logger.entry_to_s("address_\nsearch")
248
248
  actual.should == expected
249
249
  end
250
250
 
251
251
  it "should convert newlines in context" do
252
- expected = "0.15.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
252
+ expected = "0.16.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
253
253
  actual = Appstats::Logger.entry_to_s("address_search",:blah => "some\nlong\nstatement")
254
254
  actual.should == expected
255
255
  end
256
256
 
257
257
  it "should convert newlines based on the delimiter" do
258
- expected = "0.15.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
258
+ expected = "0.16.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
259
259
  actual = Appstats::Logger.entry_to_s("address:=\nsearch-n")
260
260
  actual.should == expected
261
261
  end
@@ -15,69 +15,111 @@ module Appstats
15
15
 
16
16
  it "should set input to nil" do
17
17
  @query.query.should == nil
18
+ @query.query_type.should == nil
18
19
  end
19
20
 
20
- it "should allow query on constructor" do
21
- query = Appstats::Query.new(:query => "# logins")
22
- query.query.should == "# logins"
23
- end
24
-
25
- end
26
-
27
- describe "#input" do
28
-
29
- it "should set the inputs to nil if input invalid" do
30
- query = Appstats::Query.new(:query => "# myblahs today on xyz.localnet")
31
- query.query = nil
32
- query.action.should == nil
33
- query.host.should == nil
34
- query.date_range.should == DateRange.new
35
- query.group_by.should == []
36
- query.group_query_to_sql.should == nil
37
- end
38
-
39
- it "should set the action and host" do
40
- query = Appstats::Query.new(:query => "# myblahs today on xyz.localnet")
41
- query.action.should == "myblahs"
42
- query.host.should == "xyz.localnet"
43
- query.date_range.should == DateRange.parse("today")
44
- query.group_by.should == []
45
- query.group_query_to_sql.should == nil
46
- end
47
-
48
- it "should understand the short hand 'on' instead of 'on server'" do
49
- query = Appstats::Query.new(:query => "# myblahs on xyz.localnet")
50
- query.action.should == "myblahs"
51
- query.host.should == "xyz.localnet"
52
- query.date_range.should == DateRange.new
53
- query.group_by.should == []
54
- query.group_query_to_sql.should == nil
55
- end
56
-
57
- it "should understand the old 'on server' instead of new 'on'" do
58
- query = Appstats::Query.new(:query => "# myblahs on server xyz.localnet")
59
- query.action.should == "myblahs"
60
- query.host.should == "xyz.localnet"
61
- query.date_range.should == DateRange.new
62
- query.group_by.should == []
63
- query.group_query_to_sql.should == nil
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
+
64
46
  end
65
47
 
66
- describe "group by" do
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
67
77
 
68
- it "should handle single entry" do
69
- query = Appstats::Query.new(:query => "# myblahs group by aa")
70
- query.group_by.should == ["aa"]
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
71
85
  end
72
86
 
73
- it "should handle multi-entry" do
74
- query = Appstats::Query.new(:query => "# myblahs group by aa,bbbb")
75
- query.group_by.should == ["aa","bbbb"]
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 delete sql to other 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"
76
119
  end
77
120
 
78
121
  end
79
122
 
80
-
81
123
  end
82
124
 
83
125
  describe "#run" do
@@ -91,14 +133,14 @@ module Appstats
91
133
  query = Appstats::Query.new(:query => "# blahs")
92
134
  result = query.run
93
135
  result.new_record?.should == false
94
- result.should == Appstats::Result.new(:result_type => "on_demand", :query => "# blahs", :query_as_sql => query.query_to_sql, :count => 0, :action => "blahs", :group_by => nil)
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)
95
137
  end
96
138
 
97
139
  it "should set name and result_type if provided" do
98
140
  query = Appstats::Query.new(:name => "x", :result_type => "some_reason", :query => "# blahs")
99
141
  result = query.run
100
142
  result.new_record?.should == false
101
- result.should == Appstats::Result.new(:name => "x", :result_type => "some_reason", :query => "# blahs", :query_as_sql => query.query_to_sql, :count => 0, :action => "blahs", :group_by => nil)
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)
102
144
  end
103
145
 
104
146
  it "should track contexts" do
@@ -211,21 +253,81 @@ module Appstats
211
253
  it "should track sub results for multiple group by" do
212
254
  Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
213
255
  Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
256
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
257
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
258
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "1")
259
+
214
260
  Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
261
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "a", :user => "2")
262
+
263
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
264
+ Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
215
265
  Appstats::Entry.create_from_logger("myblahs",:service_provider => "b", :user => "1")
216
266
 
217
267
  query = Appstats::Query.new(:query => "# myblahs group by service_provider,user")
218
268
  result = query.run
219
- result.count.should == 4
269
+ result.count.should == 10
220
270
  result.group_by.should == "service_provider, user"
221
271
  result.sub_results.size.should == 3
222
272
 
223
- result.sub_results[0].should == SubResult.new(:context_filter => "a, 1", :count => 2, :ratio_of_total => 0.50)
224
- result.sub_results[1].should == SubResult.new(:context_filter => "b, 1", :count => 1, :ratio_of_total => 0.25)
225
- result.sub_results[2].should == SubResult.new(:context_filter => "a, 2", :count => 1, :ratio_of_total => 0.25)
273
+ result.sub_results[0].should == SubResult.new(:context_filter => "a, 1", :count => 5, :ratio_of_total => 0.50)
274
+ result.sub_results[1].should == SubResult.new(:context_filter => "b, 1", :count => 3, :ratio_of_total => 0.30)
275
+ result.sub_results[2].should == SubResult.new(:context_filter => "a, 2", :count => 2, :ratio_of_total => 0.20)
226
276
  end
227
277
 
228
278
  end
279
+
280
+ describe "third party searches" do
281
+
282
+ before(:each) do
283
+ TestObject.delete_all
284
+
285
+ end
286
+
287
+ it "should handle custom sql" do
288
+ TestObject.create and TestObject.create
289
+
290
+ query = Query.new(:query => "# x", :query_type => "Appstats::TestQuery")
291
+ result = query.run
292
+
293
+ result.query_type.should == "Appstats::TestQuery"
294
+ result.count.should == 2
295
+ result.query_to_sql.should == "select count(*) as num from appstats_test_objects"
296
+ end
297
+
298
+ it "should handle group by" do
299
+ TestObject.create(:name => "aa") and TestObject.create(:name => "aa") and TestObject.create(:name => "bb")
300
+
301
+ query = Query.new(:query => "# x group by y", :query_type => "Appstats::TestQuery")
302
+ result = query.run
303
+
304
+ result.query_type.should == "Appstats::TestQuery"
305
+ result.count.should == 3
306
+ 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"
307
+ result.sub_results.size.should == 2
308
+ end
309
+
310
+ it "should handle remote servers" do
311
+ TestObject.create(:name => "aa")
312
+
313
+ query1 = Query.new(:query => "# x on testServer", :query_type => "Appstats::TestQuery")
314
+ result1 = query1.run
315
+
316
+ query2 = Query.new(:query => "# x on otherServer", :query_type => "Appstats::TestQuery")
317
+ result2 = query2.run
318
+
319
+ if result2.count == result1.count #coincidence
320
+ TestObject.create(:name => "aa")
321
+ result2 = query2.run
322
+ end
323
+
324
+ result1.count.should_not == result2.count
325
+
326
+ result1 = query1.run
327
+ result1.count.should_not == result2.count
328
+ end
329
+
330
+ end
229
331
 
230
332
  end
231
333
 
@@ -247,13 +349,13 @@ module Appstats
247
349
  describe "actions" do
248
350
 
249
351
  it "should understand both singular and plural names" do
250
- expected_sql = "select count(*) from appstats_entries where action = 'login'"
352
+ expected_sql = "select count(*) as num from appstats_entries where action = 'login'"
251
353
  Appstats::Query.new(:query => "# logins").query_to_sql.should == expected_sql
252
354
  Appstats::Query.new(:query => "# login").query_to_sql.should == expected_sql
253
355
  end
254
356
 
255
357
  it "should use 'itself' if action not found" do
256
- expected_sql = "select count(*) from appstats_entries where action = 'garblygook'"
358
+ expected_sql = "select count(*) as num from appstats_entries where action = 'garblygook'"
257
359
  Appstats::Query.new(:query => "# garblygook").query_to_sql.should == expected_sql
258
360
  end
259
361
 
@@ -261,7 +363,7 @@ module Appstats
261
363
 
262
364
  describe "date ranges" do
263
365
  it "should understand since dates" do
264
- expected_sql = "select count(*) from appstats_entries where action = 'login' and occurred_at >= '2010-01-15 00:00:00'"
366
+ expected_sql = "select count(*) as num from appstats_entries where action = 'login' and occurred_at >= '2010-01-15 00:00:00'"
265
367
  Appstats::Query.new(:query => "# logins since 2010-01-15").query_to_sql.should == expected_sql
266
368
  end
267
369
  end
@@ -269,7 +371,7 @@ module Appstats
269
371
  describe "server_name" do
270
372
 
271
373
  it "should on_name" do
272
- expected_sql = "select count(*) 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' )"
374
+ 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' )"
273
375
  Appstats::Query.new(:query => "# logins on my.localnet").query_to_sql.should == expected_sql
274
376
  end
275
377
 
@@ -277,7 +379,7 @@ module Appstats
277
379
 
278
380
  describe "date range and server_name" do
279
381
  it "should understand dates and 'on'" do
280
- expected_sql = "select count(*) 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' )"
382
+ 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' )"
281
383
  Appstats::Query.new(:query => "# logins between 2010-01-15 and 2010-01-31 on your.localnet").query_to_sql.should == expected_sql
282
384
  end
283
385
  end
@@ -285,12 +387,12 @@ module Appstats
285
387
  describe "where clause" do
286
388
 
287
389
  it "should understand no quotes" do
288
- expected_sql = "select count(*) 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')))"
390
+ 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')))"
289
391
  Appstats::Query.new(:query => "# logins where user = aforward").query_to_sql.should == expected_sql
290
392
  end
291
393
 
292
394
  it "should handle example" do
293
- expected_sql = "select count(*) 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') )))"
395
+ 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') )))"
294
396
  Appstats::Query.new(:query => "# blahs where (a=b and c=4) or (aaa=5)").query_to_sql.should == expected_sql
295
397
  end
296
398
 
@@ -331,26 +433,26 @@ module Appstats
331
433
 
332
434
  it "should support 1 filter" do
333
435
  query = Appstats::Query.new(:query => "# myblahs group by aa")
334
- expected = "select context_key_filter, context_value_filter, count(*) 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;"
436
+ 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"
335
437
  query.group_query_to_sql.should == expected
336
438
  end
337
439
 
338
440
  it "should support surrounding quotes" do
339
441
  query = Appstats::Query.new(:query => "# myblahs group by 'aa'")
340
- expected = "select context_key_filter, context_value_filter, count(*) 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;"
442
+ 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"
341
443
  query.group_query_to_sql.should == expected
342
444
  end
343
445
 
344
446
  it "should support inner quotes" do
345
447
  query = Appstats::Query.new(:query => "# myblahs group by a's")
346
- expected = "select context_key_filter, context_value_filter, count(*) 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;"
448
+ 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"
347
449
  query.group_query_to_sql.should == expected
348
450
  end
349
451
 
350
452
 
351
453
  it "should support many filters" do
352
454
  query = Appstats::Query.new(:query => "# myblahs group by aa, bbb")
353
- expected = "select context_key_filter, context_value_filter, count(*) 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;"
455
+ 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"
354
456
  query.group_query_to_sql.should == expected
355
457
  end
356
458
 
@@ -364,43 +466,43 @@ module Appstats
364
466
  end
365
467
 
366
468
  it "should translate a = b into EXISTS query" do
367
- Appstats::Query.contexts_filter_to_sql("a=b").should == "#{@template} (context_key = 'a' and context_value = 'b')))"
368
- Appstats::Query.contexts_filter_to_sql(" a = b ").should == "#{@template} (context_key = 'a' and context_value = 'b')))"
469
+ Appstats::Query.new(:query => "# logins where a=b").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
470
+ Appstats::Query.new(:query => "# logins where a = b ").contexts_filter_to_sql.should == "#{@template} (context_key = 'a' and context_value = 'b')))"
369
471
  end
370
472
 
371
473
  it "should ignore single quotes" do
372
- Appstats::Query.contexts_filter_to_sql("'aaa'='bbbb'").should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
373
- Appstats::Query.contexts_filter_to_sql(" 'aaa' = 'bbbb' ").should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
474
+ Appstats::Query.new(:query => "# logins where 'aaa'='bbbb'").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
475
+ Appstats::Query.new(:query => "# logins where 'aaa' = 'bbbb' ").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa' and context_value = 'bbbb')))"
374
476
  end
375
477
 
376
478
  it "should allow for searching for all entries of a certain context" do
377
- Appstats::Query.contexts_filter_to_sql("aaa").should == "#{@template} (context_key = 'aaa')))"
479
+ Appstats::Query.new(:query => "# logins where aaa").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa')))"
378
480
  end
379
481
 
380
482
  it "should allow for searching for several entries of a certain context" do
381
- Appstats::Query.contexts_filter_to_sql("aaa || bbb").should == "#{@template} (context_key = 'aaa') or (context_key = 'bbb')))"
483
+ Appstats::Query.new(:query => "# logins where aaa || bbb").contexts_filter_to_sql.should == "#{@template} (context_key = 'aaa') or (context_key = 'bbb')))"
382
484
  end
383
485
 
384
486
  it "should allow complex queries" do
385
- Appstats::Query.contexts_filter_to_sql("user='andrew' || user='aforward'").should == "#{@template} (context_key = 'user' and context_value = 'andrew') or (context_key = 'user' and context_value = 'aforward')))"
487
+ 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')))"
386
488
  end
387
489
 
388
490
  it "should support or" do
389
- Appstats::Query.contexts_filter_to_sql("user='andrew' or user='aforward'").should == "#{@template} (context_key = 'user' and context_value = 'andrew') or (context_key = 'user' and context_value = 'aforward')))"
491
+ 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')))"
390
492
  end
391
493
 
392
494
  it "should support like" do
393
- Appstats::Query.contexts_filter_to_sql("user like '%andrew%'").should == "#{@template} (context_key = 'user' and context_value like '%andrew%')))"
495
+ Appstats::Query.new(:query => "# logins where user like '%andrew%'").contexts_filter_to_sql.should == "#{@template} (context_key = 'user' and context_value like '%andrew%')))"
394
496
  end
395
497
 
396
498
  it "should support and" do
397
- Appstats::Query.contexts_filter_to_sql("user='andrew' and user='aforward'").should == "#{@template} (context_key = 'user' and context_value = 'andrew') and (context_key = 'user' and context_value = 'aforward')))"
499
+ 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')))"
398
500
  end
399
501
 
400
502
 
401
503
  it "should do simple 1 = 1 if invalid" do
402
- Appstats::Query.contexts_filter_to_sql("").should == "1=1"
403
- Appstats::Query.contexts_filter_to_sql(nil).should == "1=1"
504
+ Appstats::Query.new(:query => "# logins where").contexts_filter_to_sql.should == "1=1"
505
+ Appstats::Query.new(:query => "# logins").contexts_filter_to_sql.should == "1=1"
404
506
  end
405
507
 
406
508
  end
@@ -20,15 +20,17 @@ module Appstats
20
20
  @result_job.status.should == nil
21
21
  @result_job.query.should == nil
22
22
  @result_job.last_run_at.should == nil
23
+ @result_job.query_type.should == nil
23
24
  end
24
25
 
25
26
  it "should set on constructor" do
26
- result = Appstats::ResultJob.new(:name => 'a', :frequency => 'b', :status => 'c', :query => 'd', :last_run_at => Time.parse("2010-02-03"))
27
- result.name.should == 'a'
28
- result.frequency.should == 'b'
29
- result.status.should == 'c'
30
- result.query.should == 'd'
31
- result.last_run_at.to_s.should == Time.parse("2010-02-03").to_s
27
+ result_job = Appstats::ResultJob.new(:name => 'a', :frequency => 'b', :status => 'c', :query => 'd', :last_run_at => Time.parse("2010-02-03"), :query_type => 'e')
28
+ result_job.name.should == 'a'
29
+ result_job.frequency.should == 'b'
30
+ result_job.status.should == 'c'
31
+ result_job.query.should == 'd'
32
+ result_job.last_run_at.to_s.should == Time.parse("2010-02-03").to_s
33
+ result_job.query_type.should == 'e'
32
34
  end
33
35
 
34
36
  end
@@ -14,21 +14,22 @@ module Appstats
14
14
  @result.name.should == nil
15
15
  @result.result_type.should == nil
16
16
  @result.query.should == nil
17
- @result.query_as_sql.should == nil
17
+ @result.query_to_sql.should == nil
18
18
  @result.count.should == nil
19
19
  @result.action.should == nil
20
20
  @result.contexts.should == nil
21
21
  @result.from_date.should == nil
22
22
  @result.to_date.should == nil
23
23
  @result.group_by.should == nil
24
+ @result.query_type.should == nil
24
25
  end
25
26
 
26
27
  it "should set on constructor" do
27
- result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_as_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b")
28
+ result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
28
29
  result.name.should == 'a'
29
30
  result.result_type.should == 'b'
30
31
  result.query.should == 'c'
31
- result.query_as_sql.should == 'd'
32
+ result.query_to_sql.should == 'd'
32
33
  result.count.should == 10
33
34
  result.action.should == 'e'
34
35
  result.host.should == 'f'
@@ -36,6 +37,7 @@ module Appstats
36
37
  result.from_date_to_s.should == '2010-01-02'
37
38
  result.to_date_to_s.should == '2010-02-03'
38
39
  result.group_by.should == "a,b"
40
+ result.query_type.should == "h"
39
41
  end
40
42
 
41
43
  end
@@ -43,16 +45,16 @@ module Appstats
43
45
  describe "#==" do
44
46
 
45
47
  it "should be equal on all attributes" do
46
- result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_as_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b")
47
- same_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_as_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b")
48
+ result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
49
+ same_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
48
50
  (result == same_result).should == true
49
51
  end
50
52
 
51
53
  it "should be not equal if diferent attributes" do
52
- result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_as_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b")
54
+ result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
53
55
 
54
- [:name,:result_type,:query,:query_as_sql,:count,:action,:host,:contexts,:from_date,:to_date,:group_by].each do |attr|
55
- different_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_as_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b")
56
+ [:name,:result_type,:query,:query_to_sql,:count,:action,:host,:contexts,:from_date,:to_date,:group_by,:query_type].each do |attr|
57
+ different_result = Appstats::Result.new(:name => 'a', :result_type => 'b', :query => 'c', :query_to_sql => 'd', :count => 10, :action => 'e', :host => 'f', :contexts => 'g', :from_date => Time.parse("2010-01-02"), :to_date => Time.parse("2010-02-03"), :group_by => "a,b", :query_type => 'h')
56
58
 
57
59
  if [:from_date,:to_date].include?(attr)
58
60
  different_result.send("#{attr}=",Time.parse("2011-01-02"))
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: 33
4
+ hash: 93
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 15
8
+ - 16
9
9
  - 1
10
- version: 0.15.1
10
+ version: 0.16.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Forward
@@ -162,6 +162,8 @@ files:
162
162
  - db/migrations/20110301170733_add_appstats_results_group_query_to_sql.rb
163
163
  - db/migrations/20110301170947_create_appstats_sub_results.rb
164
164
  - db/migrations/20110301195959_add_appstats_results_groups.rb
165
+ - db/migrations/20110301212017_add_appstats_results_query_type.rb
166
+ - db/migrations/20110301230757_rename_appstats_results_query_as_sql_to_query_to_sql.rb
165
167
  - db/schema.rb
166
168
  - lib/appstats.rb
167
169
  - lib/appstats/action.rb
@@ -183,6 +185,7 @@ files:
183
185
  - lib/appstats/sub_result.rb
184
186
  - lib/appstats/tasks.rb
185
187
  - lib/appstats/test_object.rb
188
+ - lib/appstats/test_query.rb
186
189
  - lib/appstats/version.rb
187
190
  - lib/daemons/appstats_log_collector.rb
188
191
  - lib/daemons/appstats_log_collector_ctl