qreport 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/ChangeLog +11 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +97 -0
- data/Rakefile +13 -0
- data/lib/qreport.rb +8 -0
- data/lib/qreport/connection.rb +378 -0
- data/lib/qreport/initialization.rb +14 -0
- data/lib/qreport/main.rb +9 -0
- data/lib/qreport/model.rb +8 -0
- data/lib/qreport/report_run.rb +191 -0
- data/lib/qreport/report_runner.rb +123 -0
- data/lib/qreport/version.rb +3 -0
- data/qreport.gemspec +25 -0
- data/spec/connection_spec.rb +118 -0
- data/spec/report_runner_spec.rb +159 -0
- data/spec/spec_helper.rb +16 -0
- metadata +137 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Qreport::ReportRunner do
|
4
|
+
attr :reports, :now
|
5
|
+
|
6
|
+
it "should generate two reports" do
|
7
|
+
# conn.verbose = conn.verbose_result = true
|
8
|
+
run_reports!
|
9
|
+
reports.size.should == 4
|
10
|
+
|
11
|
+
r = reports['1 days']
|
12
|
+
r.select.rows.map{|x| x["user_id"]}.should == [ 2 ]
|
13
|
+
|
14
|
+
r = reports['2 days']
|
15
|
+
r.select.rows.map{|x| x["user_id"]}.should == [ 2, 3 ]
|
16
|
+
|
17
|
+
r = reports['30 days']
|
18
|
+
r.select.rows.map{|x| x["user_id"]}.should == (1..10).to_a
|
19
|
+
r.select(:limit => 2).rows.map{|x| x["user_id"]}.should == [ 1, 2 ]
|
20
|
+
r.select(:limit => [ 2, 2 ]).rows.map{|x| x["user_id"]}.should == [ 3, 4 ]
|
21
|
+
r.select(:limit => [ 4, 2 ]).rows.map{|x| x["user_id"]}.should == [ 3, 4, 5, 6 ]
|
22
|
+
|
23
|
+
r = reports['60 days']
|
24
|
+
r.select.rows.map{|x| x["user_id"]}.should == (1..10).to_a
|
25
|
+
|
26
|
+
reports.values.each do | r |
|
27
|
+
r.delete!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should DROP TABLE after all report runs are deleted." do
|
32
|
+
run_reports!
|
33
|
+
reports.values.each do | r |
|
34
|
+
r.delete!
|
35
|
+
end
|
36
|
+
conn.run("SELECT COUNT(*) AS c FROM qr_report_runs").rows[0]["c"].should == 0
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should capture errors into ReportRun#error." do
|
40
|
+
# conn.verbose = true
|
41
|
+
report_run = Qreport::ReportRun.new(:name => :users_with_articles, :description => '10 days')
|
42
|
+
report_run.arguments = {
|
43
|
+
:now => conn.safe_sql("unknown_column"),
|
44
|
+
:interval => '10 days',
|
45
|
+
}
|
46
|
+
report_run.sql = <<"END"
|
47
|
+
SELECT u.id AS "user_id"
|
48
|
+
FROM users u
|
49
|
+
WHERE
|
50
|
+
EXISTS(SELECT * FROM articles a WHERE a.user_id = u.id AND a.created_on >= :now - INTERVAL :interval)
|
51
|
+
END
|
52
|
+
report_run.run! conn
|
53
|
+
report_run.error.class.should == Hash
|
54
|
+
report_run.error[:error_class].should == 'PG::Error'
|
55
|
+
report_run.error[:error_message].should =~ /column "unknown_column" does not exist/
|
56
|
+
|
57
|
+
report_run.delete!
|
58
|
+
end
|
59
|
+
|
60
|
+
def run_reports!
|
61
|
+
@reports = { }
|
62
|
+
|
63
|
+
sql = <<"END"
|
64
|
+
SELECT u.id AS "user_id"
|
65
|
+
FROM users u
|
66
|
+
WHERE
|
67
|
+
EXISTS(SELECT * FROM articles a WHERE a.user_id = u.id AND a.created_on >= :now - INTERVAL :interval)
|
68
|
+
;
|
69
|
+
END
|
70
|
+
|
71
|
+
[ '1 days', '2 days', '30 days', '60 days' ].each do | interval |
|
72
|
+
report_run = Qreport::ReportRun.new(:name => :users_with_articles, :description => interval)
|
73
|
+
report_run.arguments = {
|
74
|
+
:now => now,
|
75
|
+
:interval => interval,
|
76
|
+
}
|
77
|
+
report_run.sql = sql
|
78
|
+
report_run.additional_columns = [
|
79
|
+
[ 'qr_processing_status_id', "integer", 1 ],
|
80
|
+
[ 'qr_processed_at', "timestamp with time zone", nil ],
|
81
|
+
[ 'qr_processing_error', "text", nil ],
|
82
|
+
]
|
83
|
+
report_run.run! conn
|
84
|
+
|
85
|
+
# puts "\n ReportRun #{report_run.id}"
|
86
|
+
# pp report_run
|
87
|
+
# pp report_run.select(:limit => [10, 2]).rows
|
88
|
+
|
89
|
+
reports[interval] = report_run
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
attr :conn, :now
|
94
|
+
|
95
|
+
before :all do
|
96
|
+
@conn = Qreport::Connection.new
|
97
|
+
# conn.verbose = true
|
98
|
+
|
99
|
+
if conn.table_exists? "qr_report_runs"
|
100
|
+
conn.run "DROP TABLE qr_report_runs"
|
101
|
+
conn.run "DROP SEQUENCE qr_report_runs_pkey"
|
102
|
+
end
|
103
|
+
|
104
|
+
conn.transaction do
|
105
|
+
Qreport::ReportRun.schema! conn
|
106
|
+
end
|
107
|
+
|
108
|
+
if conn.table_exists? "users"
|
109
|
+
conn.run "DROP TABLE users"
|
110
|
+
conn.run "DROP SEQUENCE users_pkey"
|
111
|
+
conn.run "DROP TABLE articles"
|
112
|
+
conn.run "DROP SEQUENCE articles_pkey"
|
113
|
+
end
|
114
|
+
|
115
|
+
conn.run <<"END"
|
116
|
+
CREATE SEQUENCE users_pkey;
|
117
|
+
CREATE TABLE users (
|
118
|
+
id INTEGER PRIMARY KEY DEFAULT nextval('users_pkey')
|
119
|
+
, name VARCHAR(255) NOT NULL
|
120
|
+
);
|
121
|
+
CREATE SEQUENCE articles_pkey;
|
122
|
+
CREATE TABLE articles (
|
123
|
+
id INTEGER PRIMARY KEY DEFAULT nextval('articles_pkey')
|
124
|
+
, user_id INTEGER
|
125
|
+
, name VARCHAR(255) NOT NULL
|
126
|
+
, body TEXT
|
127
|
+
, created_on TIMESTAMP WITH TIME ZONE NOT NULL
|
128
|
+
);
|
129
|
+
END
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
before :each do
|
134
|
+
@conn = Qreport::Connection.new
|
135
|
+
@now = Time.now
|
136
|
+
|
137
|
+
conn.run "DELETE FROM qr_report_runs"
|
138
|
+
conn.run "DELETE FROM articles"
|
139
|
+
conn.run "DELETE FROM users"
|
140
|
+
|
141
|
+
(1 .. 10).each do | i |
|
142
|
+
conn.run "INSERT INTO users :NAMES_AND_VALUES",
|
143
|
+
:arguments => { :names_and_values => {
|
144
|
+
:id => i,
|
145
|
+
:name => "user#{i}",
|
146
|
+
} }
|
147
|
+
end
|
148
|
+
(1 .. 100).each do | i |
|
149
|
+
user_id = (i % 10) + 1
|
150
|
+
conn.run "INSERT INTO articles :NAMES_AND_VALUES",
|
151
|
+
:arguments => { :names_and_values => {
|
152
|
+
:id => i,
|
153
|
+
:user_id => user_id,
|
154
|
+
:name => "Article #{i}",
|
155
|
+
:created_on => now - i * 86000,
|
156
|
+
} }
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
gem 'simplecov'
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter "spec/"
|
7
|
+
end
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.order = "random"
|
11
|
+
end
|
12
|
+
|
13
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
14
|
+
|
15
|
+
require 'qreport/report_runner'
|
16
|
+
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: qreport
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kurt Stephens
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-26 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.9.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.12.0
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.12.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: simplecov
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.7.1
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.1
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: pg
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.14'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0.14'
|
78
|
+
description: Automatically creates materialized report tables from a SQL query.
|
79
|
+
email:
|
80
|
+
- ks.github@kurtstephens.com
|
81
|
+
executables: []
|
82
|
+
extensions: []
|
83
|
+
extra_rdoc_files: []
|
84
|
+
files:
|
85
|
+
- .gitignore
|
86
|
+
- .rspec
|
87
|
+
- ChangeLog
|
88
|
+
- Gemfile
|
89
|
+
- LICENSE.txt
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- lib/qreport.rb
|
93
|
+
- lib/qreport/connection.rb
|
94
|
+
- lib/qreport/initialization.rb
|
95
|
+
- lib/qreport/main.rb
|
96
|
+
- lib/qreport/model.rb
|
97
|
+
- lib/qreport/report_run.rb
|
98
|
+
- lib/qreport/report_runner.rb
|
99
|
+
- lib/qreport/version.rb
|
100
|
+
- qreport.gemspec
|
101
|
+
- spec/connection_spec.rb
|
102
|
+
- spec/report_runner_spec.rb
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
homepage: http://github.com/kstephens/qreport
|
105
|
+
licenses: []
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
hash: -4571312096483828013
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
segments:
|
126
|
+
- 0
|
127
|
+
hash: -4571312096483828013
|
128
|
+
requirements: []
|
129
|
+
rubyforge_project:
|
130
|
+
rubygems_version: 1.8.25
|
131
|
+
signing_key:
|
132
|
+
specification_version: 3
|
133
|
+
summary: Automatically creates materialized report tables from a SQL query.
|
134
|
+
test_files:
|
135
|
+
- spec/connection_spec.rb
|
136
|
+
- spec/report_runner_spec.rb
|
137
|
+
- spec/spec_helper.rb
|