qreport 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,11 @@
1
+ 2013-07-08 Kurt A. Stephens <ks.github@kurtstephens.com>
2
+
3
+ * v0.0.6: New Version: New Functionality.
4
+ * ReportRun#variant additional key.
5
+ * ReportRun#data returns all rows of from its report table.
6
+ * ReportRun.find(id) returns a ReportRun object.
7
+ * ReportRun#reload! reloads a ReportRun object.
8
+
1
9
  2013-06-26 Kurt A. Stephens <ks.github@kurtstephens.com>
2
10
 
3
11
  * v0.0.3: New Version: New Functionality.
@@ -0,0 +1,8 @@
1
+ # -*- ruby -*-
2
+ guard 'rspec' do
3
+ watch(%r{^spec/.+_spec\.rb$})
4
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ watch(%r{^lib/.*/connection.rb$}) { "spec" }
7
+ end
8
+
data/README.md CHANGED
@@ -86,8 +86,45 @@ Subsequent queries with the same column signature will use "INSERT INTO users_wi
86
86
 
87
87
  ## Parameterizing Reports
88
88
 
89
+ Report queries can be parameterized using embedded ":word" tags.
90
+ Parameter arguments are saved in the report run table.
91
+
92
+ report_run.arguments = {
93
+ :interval => '30 days',
94
+ }
95
+ report_run.run! <<"END"
96
+ SELECT u.id AS "user_id"
97
+ FROM users u
98
+ WHERE
99
+ EXISTS(SELECT * FROM articles a
100
+ WHERE a.user_id = u.id AND a.created_on >= NOW() - INTERVAL :interval)
101
+ END
102
+
103
+ Arguments can also represent "matching" patterns using a ":~" tag.
104
+ Example: a Range of Time values matching a.created_on:
105
+
106
+ t = Time.now
107
+ report_run.arguments = {
108
+ :interval => (t - 86400) ... t,
109
+ }
110
+ report_run.run! <<"END"
111
+ SELECT * FROM articles a WHERe :~ {{:interval}} {{a.created_on}}
112
+ END
113
+
89
114
  ## Batch Processing
90
115
 
116
+ ## Running Tests
117
+
118
+ Example setup:
119
+
120
+ $ sudo -u postgresql psql
121
+ postgres=# create role test login password 'test';
122
+ CREATE ROLE
123
+ postgres=# create database test owner test;
124
+ CREATE DATABASE
125
+ postgres=# \q
126
+ $ PGHOST=localhost PGUSER=test PGDATABSE=test PGPASSWORD=... rake
127
+
91
128
  ## Contributing
92
129
 
93
130
  1. Fork it
@@ -4,5 +4,5 @@ module Qreport
4
4
  EMPTY_Hash = {}.freeze
5
5
  EMPTY_Array = [].freeze
6
6
  EMPTY_String = ''.freeze
7
- class Error < ::Exception; end
7
+ class Error < ::StandardError; end
8
8
  end
@@ -89,7 +89,7 @@ module Qreport
89
89
  begin
90
90
  transaction_begin
91
91
  yield
92
- rescue ::Exception => exc
92
+ rescue ::StandardError => exc
93
93
  abort = @abort_transaction = exc
94
94
  raise exc
95
95
  ensure
@@ -135,10 +135,13 @@ module Qreport
135
135
  end
136
136
 
137
137
  def table_exists? name, schemaname = nil
138
- schemaname ||= self.schemaname
138
+ schema_name = name.split('.', 2)
139
+ schema = schema_name.shift if schema_name.size > 1
140
+ name = schema_name.first
141
+ schema ||= schemaname || self.schemaname || 'public'
139
142
  result =
140
143
  run "SELECT EXISTS(SELECT * FROM pg_catalog.pg_tables WHERE tablename = :tablename AND schemaname = :schemaname) as \"exists\"",
141
- :arguments => { :tablename => name, :schemaname => schemaname }
144
+ :arguments => { :tablename => name, :schemaname => schema }
142
145
  # result.rows; pp result
143
146
  result.rows[0]["exists"]
144
147
  end
@@ -190,6 +193,8 @@ module Qreport
190
193
  "'" << conn.escape_string(val.to_s) << QUOTE
191
194
  when Time
192
195
  escape_value(val.iso8601(6)) << "::timestamp"
196
+ when Range
197
+ "BETWEEN #{escape_value(val.first)} AND #{escape_value(val.last)}"
193
198
  when Hash, Array
194
199
  escape_value(val.to_json)
195
200
  else
@@ -258,7 +263,7 @@ module Qreport
258
263
  # $stderr.puts " ERROR: #{exc.inspect}\n #{exc.backtrace * "\n "}"
259
264
  query.error = exc.inspect
260
265
  raise exc unless options[:capture_error]
261
- rescue ::Exception => exc
266
+ rescue ::StandardError => exc
262
267
  @invalid = true
263
268
  query.error = exc.inspect
264
269
  raise exc unless options[:capture_error]
@@ -268,6 +273,7 @@ module Qreport
268
273
 
269
274
  class Query
270
275
  attr_accessor :conn, :sql, :options
276
+ attr_accessor :sql_prepared
271
277
  attr_accessor :error, :cmd_status_raw, :cmd_status, :cmd_tuples
272
278
  attr_accessor :nfields, :fields, :ftypes, :fmods
273
279
  attr_accessor :type_names
@@ -324,6 +330,22 @@ module Qreport
324
330
  $1
325
331
  end
326
332
  end
333
+ sql = sql_replace_match sql
334
+ end
335
+
336
+ def sql_replace_match sql
337
+ sql = sql.gsub(/:~\s*\{\{([^\}]+?)\}\}\s*\{\{([^\}]+?)\}\}/) do | m |
338
+ expr = $1
339
+ val = $2
340
+ case expr
341
+ when /\A\s*BETWEEN\b/
342
+ "(#{val} #{expr})"
343
+ when "NULL"
344
+ "(#{val} IS NULL)"
345
+ else
346
+ "(#{val} = #{expr})"
347
+ end
348
+ end
327
349
  sql
328
350
  end
329
351
 
@@ -5,10 +5,17 @@ module Qreport
5
5
  def initialize opts = nil
6
6
  opts ||= EMPTY_Hash
7
7
  initialize_before_opts if respond_to? :initialize_before_opts
8
- opts.each do | k, v |
9
- send(:"#{k}=", v)
10
- end
8
+ initialize_from_hash! opts
11
9
  initialize_after_opts if respond_to? :initialize_after_opts
12
10
  end
11
+
12
+ def initialize_from_hash! opts
13
+ if opts
14
+ opts.each do | k, v |
15
+ send(:"#{k}=", v)
16
+ end
17
+ end
18
+ self
19
+ end
13
20
  end
14
21
  end
@@ -7,15 +7,16 @@ module Qreport
7
7
  include Model, Initialization
8
8
 
9
9
  attr_accessor :id
10
- attr_accessor :name, :sql, :additional_columns
10
+ attr_accessor :name, :variant, :sql, :additional_columns
11
11
  attr_accessor :description
12
12
  attr_accessor :arguments
13
13
  attr_accessor :report_id
14
- attr_accessor :report_sql
14
+ attr_accessor :report_sql, :raw_sql
15
15
  attr_accessor :columns, :base_columns, :column_signature
16
16
  attr_accessor :report_table
17
17
  attr_accessor :nrows
18
18
  attr_accessor :created_at, :started_at, :finished_at
19
+ attr_accessor :verbose
19
20
 
20
21
  # Construct report_table name from column names and types.
21
22
  def report_table
@@ -41,10 +42,18 @@ module Qreport
41
42
  def base_columns
42
43
  @base_columns ||= EMPTY_Array
43
44
  end
45
+ def base_columns= x
46
+ @base_columns = x
47
+ @columns = nil
48
+ end
44
49
 
45
50
  def additional_columns
46
51
  @additional_columns ||= EMPTY_Array
47
52
  end
53
+ def additional_columns= x
54
+ @additional_columns ||= EMPTY_Array
55
+ @columns = nil
56
+ end
48
57
 
49
58
  def columns
50
59
  @columns ||=
@@ -84,6 +93,7 @@ CREATE TABLE -- IF NOT EXISTS
84
93
  qr_report_runs (
85
94
  id INTEGER PRIMARY KEY DEFAULT nextval('qr_report_runs_pkey')
86
95
  , name VARCHAR(255) NOT NULL
96
+ , variant VARCHAR(255)
87
97
  , sql TEXT NOT NULL
88
98
  , description TEXT NOT NULL
89
99
  , arguments TEXT NOT NULL
@@ -97,6 +107,7 @@ qr_report_runs (
97
107
  , nrows INTEGER
98
108
  );
99
109
  CREATE INDEX qr_report_runs__name ON qr_report_runs (name);
110
+ CREATE INDEX qr_report_runs__variant ON qr_report_runs (variant);
100
111
  CREATE INDEX qr_report_runs__report_table ON qr_report_runs (report_table);
101
112
  CREATE INDEX qr_report_runs__created_at ON qr_report_runs (created_at);
102
113
  END
@@ -105,6 +116,7 @@ END
105
116
  def insert!
106
117
  values = {
107
118
  :name => name,
119
+ :variant => variant,
108
120
  :sql => sql,
109
121
  :description => description,
110
122
  :arguments => (arguments || { }),
@@ -150,6 +162,27 @@ WHERE id = :qr_run_id
150
162
  END
151
163
  end
152
164
 
165
+ def self.find id
166
+ obj = new
167
+ obj.id = id
168
+ obj.reload!
169
+ end
170
+
171
+ def reload!
172
+ result = conn.run("SELECT * FROM qr_report_runs WHERE id = :id LIMIT 1", :arguments => { :id => id })
173
+ result = result.rows.first
174
+ initialize_from_hash! result
175
+ @base_columns = JSON.parse(@base_columns)
176
+ @data = nil
177
+ self
178
+ end
179
+
180
+ # Return rows from this report run's report table.
181
+ def data
182
+ @data ||=
183
+ _select
184
+ end
185
+
153
186
  def select options = nil
154
187
  options = _options options
155
188
  _select({:order_by => 'ORDER BY qr_run_row'}.merge(options))
@@ -176,10 +209,14 @@ END
176
209
  conn.run "SELECT COUNT(*) AS \"count\" from qr_report_runs WHERE report_table = :report_table",
177
210
  :arguments => { :report_table => report_table }, :capture_error => true # , :verbose => true
178
211
  if result.rows[0]["count"] <= 0
179
- conn.run "-- DROP TABLE #{report_table}", :capture_error => true # , :verbose => true
212
+ # drop_table!
180
213
  end
181
214
  end
182
215
 
216
+ def drop_table! options = nil
217
+ conn.run "DROP TABLE #{report_table}", :capture_error => true # , :verbose => true
218
+ end
219
+
183
220
  # Deletes the actual rows for this report run.
184
221
  def truncate! options = nil
185
222
  options = _options options
@@ -8,53 +8,53 @@ require 'pp'
8
8
  module Qreport
9
9
  class ReportRunner
10
10
  attr_accessor :connection, :verbose
11
+ attr_accessor :report_run, :sql, :arguments
12
+ attr_accessor :error, :error_1, :error_2
11
13
 
12
14
  def run! report_run
15
+ @verbose ||= report_run.verbose
16
+ @report_run = report_run
13
17
  report_run.created_at ||=
14
18
  report_run.started_at = Time.now.utc
15
19
  name = report_run.name
16
- sql = report_run.sql.strip
20
+ @sql = report_run.sql.strip
17
21
 
18
- arguments = report_run.arguments || { }
19
- error = error_1 = error_2 = nrows = nil
22
+ @arguments = report_run.arguments || { }
23
+ @error = @error_1 = @error_2 = nrows = nil
20
24
 
21
25
  Connection.current = connection
22
26
 
23
- begin
24
- conn.transaction do
25
-
26
- # Create a report row sequence:
27
- run "CREATE TEMPORARY SEQUENCE qr_row_seq"
27
+ conn.transaction do
28
+ # Create a report row sequence:
29
+ run "CREATE TEMPORARY SEQUENCE qr_row_seq"
30
+ end
28
31
 
29
- # Rewrite query to create result table rows:
30
- arguments = arguments.merge(:qr_run_id => conn.safe_sql("nextval('qr_row_seq')"))
31
- report_run.report_sql = report_sql(sql)
32
+ # Rewrite query to create result table rows:
33
+ self.arguments = arguments.merge(:qr_run_id => conn.safe_sql("nextval('qr_row_seq')"))
34
+ report_run.report_sql = report_sql(sql)
32
35
 
33
- # Proof query to infer base columns:
34
- result = run report_run.report_sql, :limit => 0, :arguments => arguments, :verbose => @verbose
35
- report_run.base_columns = result.columns
36
- result = nil
37
- end # transaction
38
- rescue ::Exception => exc
39
- error = error_1 = exc
36
+ # Infer base columns, if not specified.
37
+ if report_run.base_columns.empty?
38
+ infer_base_columns!
40
39
  end
41
40
 
42
41
  # Construct report_table name from column names and types:
43
42
  report_table = report_run.report_table
44
43
 
45
- conn.transaction do
46
- # Create new ReportRun row:
47
- report_run.insert!
48
- report_run_id = report_run.id
49
- arguments[:qr_run_id] = report_run_id
50
- report_run.report_sql = report_sql(sql)
51
- end # transaction
44
+ unless report_run.id
45
+ conn.transaction do
46
+ # Create new ReportRun row:
47
+ report_run.insert!
48
+ end # transaction
49
+ end
50
+ arguments[:qr_run_id] = report_run.id
52
51
 
53
52
  unless error
54
53
  # Run query into report table:
55
54
  begin
56
55
  conn.transaction do
57
56
  unless conn.table_exists? report_table
57
+ result =
58
58
  run "CREATE TABLE #{report_table} AS #{report_run.report_sql}", :arguments => arguments, :verbose => @verbose
59
59
  run "CREATE INDEX #{report_table}_i1 ON #{report_table} (qr_run_id)"
60
60
  run "CREATE INDEX #{report_table}_i2 ON #{report_table} (qr_run_row)"
@@ -65,12 +65,13 @@ module Qreport
65
65
  else
66
66
  result =
67
67
  run "INSERT INTO #{report_table} #{report_run.report_sql}", :arguments => arguments, :verbose => @verbose
68
-
69
68
  # Get the number of report run rows from cmd_status:
70
69
  unless cs = result.cmd_status and cs[0] == 'INSERT' and cs[1] == 0 and nrows = cs[2]
71
70
  raise Error, "cannot determine nrows"
72
71
  end
73
72
  end
73
+ report_run.raw_sql = result.sql_prepared
74
+ # $stderr.puts ">>>>>>>>>>>>>>>>>>> #{result.sql_prepared}"
74
75
  # Get the number of report run rows:
75
76
  unless nrows || error
76
77
  result = report_run._select :COLUMNS => 'COUNT(*) AS "nrows"' #, :verbose => true
@@ -79,8 +80,8 @@ module Qreport
79
80
  # pp result
80
81
  result = nil
81
82
  end # transaction
82
- rescue ::Exception => exc
83
- error = error_2 = exc
83
+ rescue ::StandardError => exc
84
+ @error = @error_2 = exc
84
85
  end # transaction
85
86
  end
86
87
 
@@ -97,8 +98,22 @@ module Qreport
97
98
  report_run
98
99
  end
99
100
 
101
+ def infer_base_columns!
102
+ base_columns = nil
103
+ begin
104
+ conn.transaction do
105
+ # Proof query to infer base columns:
106
+ result = run report_run.report_sql, :limit => 0, :arguments => arguments, :verbose => @verbose
107
+ base_columns = report_run.base_columns = result.columns
108
+ end # transaction
109
+ rescue ::StandardError => exc
110
+ @error = @error_1 = exc
111
+ end
112
+ base_columns
113
+ end
114
+
100
115
  def report_sql sql
101
- sql = sql.sub(/\ASELECT\s+/im, <<"END"
116
+ sql = sql.sub(/\A\s*SELECT\s+/im, <<"END"
102
117
  SELECT
103
118
  :qr_run_id
104
119
  AS "qr_run_id"
@@ -1,3 +1,3 @@
1
1
  module Qreport
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -18,8 +18,11 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_development_dependency 'rake', '>= 0.9.0'
21
- gem.add_development_dependency 'rspec', '~> 2.12.0'
21
+ gem.add_development_dependency 'rspec', '~> 2.12'
22
22
  gem.add_development_dependency 'simplecov', '~> 0.7.1'
23
+ gem.add_development_dependency "guard", "~> 1.8.0"
24
+ gem.add_development_dependency "guard-rspec", "~> 3.0.2"
25
+ gem.add_development_dependency "cassava", "~> 0.0.1"
23
26
 
24
27
  gem.add_dependency 'pg', '~> 0.14'
25
28
  end
@@ -97,6 +97,7 @@ describe Qreport::Connection do
97
97
  [ "string with \", \\, and \'", "'string with \", \\, and '''" ],
98
98
  [ :a_symbol!, "'a_symbol!'", :a_symbol!.to_s ],
99
99
  [ Time.parse('2011-04-27T13:23:00.000000Z'), "'2011-04-27T13:23:00.000000Z'::timestamp", Time.parse('2011-04-27T13:23:00.000000') ],
100
+ [ Time.parse('2011-04-27 13:23:00 -0500'), "'2011-04-27T13:23:00.000000-05:00'::timestamp", Time.parse('2011-04-27 13:23:00 -0500') ],
100
101
  ].each do | value, sql, return_value |
101
102
  it "can handle encoding #{value.class.name} value #{value.inspect} as #{sql.inspect}." do
102
103
  conn.escape_value(value).should == sql
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Qreport::ReportRunner do
4
4
  attr :reports, :now
5
5
 
6
- it "should generate two reports" do
6
+ it "should generate reports" do
7
7
  # conn.verbose = conn.verbose_result = true
8
8
  run_reports!
9
9
  reports.size.should == 4
@@ -28,6 +28,32 @@ describe Qreport::ReportRunner do
28
28
  end
29
29
  end
30
30
 
31
+ it "should store relevant data in qr_report_runs table" do
32
+ run_reports!
33
+ reports.values.each do | r |
34
+ r2 = r.class.find(r.id)
35
+ r2.name.should == r.name.to_s
36
+ r2.description.should == r.description
37
+ r2.variant.should == r.variant
38
+ r2.sql.should == r.sql
39
+ r2.report_table.should == r.report_table
40
+ r2.base_columns.should == r.base_columns
41
+ r2.additional_columns.should == r.additional_columns
42
+ r2.columns.should == r.columns
43
+ r2.column_signature == r.column_signature
44
+ r2.error.should == r.error
45
+ #pending "Time/timestamp timezones" do
46
+ #r2.created_at.should == r.created_at
47
+ #r2.started_at.should == r.started_at
48
+ #r2.finished_at.should == r.finished_at
49
+ #end
50
+ r2.nrows.should == r.nrows
51
+ r2.data.columns.should == r.data.columns
52
+ r2.data.rows.should == r.data.rows
53
+ r2.data.rows.size.should == r.nrows
54
+ end
55
+ end
56
+
31
57
  it "should DROP TABLE after all report runs are deleted." do
32
58
  run_reports!
33
59
  reports.values.each do | r |
@@ -38,7 +64,7 @@ describe Qreport::ReportRunner do
38
64
 
39
65
  it "should capture errors into ReportRun#error." do
40
66
  # conn.verbose = true
41
- report_run = Qreport::ReportRun.new(:name => :users_with_articles, :description => '10 days')
67
+ report_run = Qreport::ReportRun.new(:name => :users_with_articles, :variant => '10 days', :description => '10 days')
42
68
  report_run.arguments = {
43
69
  :now => conn.safe_sql("unknown_column"),
44
70
  :interval => '10 days',
@@ -57,6 +83,24 @@ END
57
83
  report_run.delete!
58
84
  end
59
85
 
86
+ it "should support :~ {{PATTERN}} {{EXPR}}." do
87
+ report_run = Qreport::ReportRun.new(:name => :users_with_articles, :description => 'last 24 hours')
88
+ now = Time.now
89
+ report_run.arguments = {
90
+ :interval => (now - 86400 ... now),
91
+ }
92
+ report_run.sql = <<"END"
93
+ SELECT u.id AS "user_id"
94
+ FROM users u
95
+ WHERE
96
+ EXISTS(SELECT * FROM articles a WHERE a.user_id = u.id AND :~ {{:interval}} {{a.created_on}});
97
+ END
98
+ # report_run.verbose = true
99
+ report_run.run! conn
100
+ # report_run.raw_sql.should == ''
101
+ report_run.error.should == nil
102
+ end
103
+
60
104
  def run_reports!
61
105
  @reports = { }
62
106
 
@@ -69,7 +113,7 @@ END
69
113
  END
70
114
 
71
115
  [ '1 days', '2 days', '30 days', '60 days' ].each do | interval |
72
- report_run = Qreport::ReportRun.new(:name => :users_with_articles, :description => interval)
116
+ report_run = Qreport::ReportRun.new(:name => :users_with_articles, :description => interval, :variant => interval)
73
117
  report_run.arguments = {
74
118
  :now => now,
75
119
  :interval => interval,
@@ -156,4 +200,12 @@ END
156
200
  } }
157
201
  end
158
202
  end
203
+
204
+ after :each do
205
+ if reports
206
+ reports.values.each do | r |
207
+ r.drop_table!
208
+ end
209
+ end
210
+ end
159
211
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qreport
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-26 00:00:00.000000000 Z
12
+ date: 2013-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 2.12.0
37
+ version: '2.12'
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 2.12.0
45
+ version: '2.12'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: simplecov
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -59,6 +59,54 @@ dependencies:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.7.1
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.8.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.8.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: guard-rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 3.0.2
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 3.0.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: cassava
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 0.0.1
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 0.0.1
62
110
  - !ruby/object:Gem::Dependency
63
111
  name: pg
64
112
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +134,7 @@ files:
86
134
  - .rspec
87
135
  - ChangeLog
88
136
  - Gemfile
137
+ - Guardfile
89
138
  - LICENSE.txt
90
139
  - README.md
91
140
  - Rakefile
@@ -98,8 +147,8 @@ files:
98
147
  - lib/qreport/report_runner.rb
99
148
  - lib/qreport/version.rb
100
149
  - qreport.gemspec
101
- - spec/connection_spec.rb
102
- - spec/report_runner_spec.rb
150
+ - spec/lib/qreport/connection_spec.rb
151
+ - spec/lib/qreport/report_runner_spec.rb
103
152
  - spec/spec_helper.rb
104
153
  homepage: http://github.com/kstephens/qreport
105
154
  licenses: []
@@ -113,18 +162,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
162
  - - ! '>='
114
163
  - !ruby/object:Gem::Version
115
164
  version: '0'
116
- segments:
117
- - 0
118
- hash: 1042479240824554319
119
165
  required_rubygems_version: !ruby/object:Gem::Requirement
120
166
  none: false
121
167
  requirements:
122
168
  - - ! '>='
123
169
  - !ruby/object:Gem::Version
124
170
  version: '0'
125
- segments:
126
- - 0
127
- hash: 1042479240824554319
128
171
  requirements: []
129
172
  rubyforge_project:
130
173
  rubygems_version: 1.8.25
@@ -132,6 +175,6 @@ signing_key:
132
175
  specification_version: 3
133
176
  summary: Automatically creates materialized report tables from a SQL query.
134
177
  test_files:
135
- - spec/connection_spec.rb
136
- - spec/report_runner_spec.rb
178
+ - spec/lib/qreport/connection_spec.rb
179
+ - spec/lib/qreport/report_runner_spec.rb
137
180
  - spec/spec_helper.rb