appstats 0.15.1 → 0.16.1

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.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