simple-sql 0.4.37 → 0.4.38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/simple/sql.rb +1 -1
- data/lib/simple/sql/connection_adapter.rb +10 -0
- data/lib/simple/sql/logging.rb +1 -1
- data/lib/simple/sql/result.rb +24 -46
- data/lib/simple/sql/scope.rb +2 -0
- data/lib/simple/sql/scope/count.rb +33 -0
- data/lib/simple/sql/scope/count_by_groups.rb +79 -0
- data/lib/simple/sql/version.rb +1 -1
- data/spec/simple/sql/count_by_groups_spec.rb +44 -0
- data/spec/simple/sql/count_spec.rb +29 -0
- data/spec/simple/sql/logging_spec.rb +16 -0
- data/spec/simple/sql/result_count_spec.rb +57 -0
- data/spec/spec_helper.rb +3 -1
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c46da1c022c4c166ffa76a597ab2c2357de1f93ab2c62f979a9dbac983d763f
|
4
|
+
data.tar.gz: e2b1af9258ad35e64fa845c233e0c8fac11e19d5be3d715255c7b4d56eaf980c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 235ff8fa9d55221c93d347c4c0f497f75cac530f49ef74f58697fbb9e9c056a5befad61a7cf365ebeae49c7895f06ef5bb01150950cfa0140bf1d35bb4d35191
|
7
|
+
data.tar.gz: 849232ea61c8478088977240e8d2cc7c987ead8bcbd9e909b14084bc566e55caa6b6d423e642be3f46d5b5a6240f470fe28bdd90e33389e141c00cdcda05e1a5
|
data/lib/simple/sql.rb
CHANGED
@@ -21,7 +21,7 @@ module Simple
|
|
21
21
|
extend self
|
22
22
|
|
23
23
|
extend Forwardable
|
24
|
-
delegate [:ask, :all, :each, :exec, :locked, :print, :transaction, :wait_for_notify] => :default_connection
|
24
|
+
delegate [:ask, :all, :each, :exec, :locked, :print, :transaction, :wait_for_notify, :costs] => :default_connection
|
25
25
|
|
26
26
|
delegate [:logger, :logger=] => ::Simple::SQL::Logging
|
27
27
|
|
@@ -90,6 +90,16 @@ module Simple::SQL::ConnectionAdapter
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
+
# returns an Array [min_cost, max_cost] based on the database's estimation
|
94
|
+
def costs(sql, *args)
|
95
|
+
explanation_first = Simple::SQL.ask "EXPLAIN #{sql}", *args
|
96
|
+
unless explanation_first =~ /cost=(\d+(\.\d+))\.+(\d+(\.\d+))/
|
97
|
+
raise "Cannot determine cost"
|
98
|
+
end
|
99
|
+
|
100
|
+
[Float($1), Float($3)]
|
101
|
+
end
|
102
|
+
|
93
103
|
# Executes a block, usually of db insert code, while holding an
|
94
104
|
# advisory lock.
|
95
105
|
#
|
data/lib/simple/sql/logging.rb
CHANGED
data/lib/simple/sql/result.rb
CHANGED
@@ -30,52 +30,49 @@ class ::Simple::SQL::Result < Array
|
|
30
30
|
replace(records)
|
31
31
|
end
|
32
32
|
|
33
|
-
# returns
|
33
|
+
# returns the (potentialy estimated) total count of results
|
34
34
|
#
|
35
|
-
# This is
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
@total_count_estimate = _total_count_estimate
|
35
|
+
# This is only available for paginated scopes
|
36
|
+
def total_fast_count
|
37
|
+
@total_fast_count ||= pagination_scope.fast_count
|
40
38
|
end
|
41
39
|
|
42
|
-
# returns the estimated total number of pages
|
40
|
+
# returns the (potentialy estimated) total number of pages
|
43
41
|
#
|
44
|
-
# This is
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
@total_pages_estimate = (total_count_estimate * 1.0 / @pagination_scope.per).ceil if @pagination_scope
|
42
|
+
# This is only available for paginated scopes
|
43
|
+
def total_fast_pages
|
44
|
+
@total_fast_pages ||= (total_fast_count * 1.0 / pagination_scope.per).ceil
|
49
45
|
end
|
50
46
|
|
51
|
-
# returns the
|
47
|
+
# returns the (potentialy slow) exact total count of results
|
52
48
|
#
|
53
|
-
# This is
|
49
|
+
# This is only available for paginated scopes
|
54
50
|
def total_count
|
55
|
-
|
56
|
-
|
57
|
-
@total_count = _total_count
|
51
|
+
@total_count ||= pagination_scope.count
|
58
52
|
end
|
59
53
|
|
60
|
-
# returns the total number of pages
|
54
|
+
# returns the (potentialy estimated) total number of pages
|
61
55
|
#
|
62
|
-
# This is
|
63
|
-
# into account the scope's "per" option.
|
56
|
+
# This is only available for paginated scopes
|
64
57
|
def total_pages
|
65
|
-
|
66
|
-
|
67
|
-
@total_pages = (total_count * 1.0 / @pagination_scope.per).ceil if @pagination_scope
|
58
|
+
@total_pages ||= (total_count * 1.0 / pagination_scope.per).ceil
|
68
59
|
end
|
69
60
|
|
70
61
|
# returns the current page number in a paginated search
|
71
62
|
#
|
72
|
-
# This is
|
63
|
+
# This is only available for paginated scopes
|
73
64
|
def current_page
|
74
|
-
@current_page ||=
|
65
|
+
@current_page ||= pagination_scope.page
|
75
66
|
end
|
76
67
|
|
77
68
|
private
|
78
69
|
|
70
|
+
def pagination_scope
|
71
|
+
return @pagination_scope if @pagination_scope
|
72
|
+
|
73
|
+
raise "Only available only for paginated scopes"
|
74
|
+
end
|
75
|
+
|
79
76
|
def set_pagination_info(scope)
|
80
77
|
raise ArgumentError, "per must be > 0" unless scope.per > 0
|
81
78
|
|
@@ -86,29 +83,10 @@ class ::Simple::SQL::Result < Array
|
|
86
83
|
@current_page = 1
|
87
84
|
@total_count = 0
|
88
85
|
@total_pages = 1
|
89
|
-
@
|
90
|
-
@
|
86
|
+
@total_fast_count = 0
|
87
|
+
@total_fast_pages = 1
|
91
88
|
else
|
92
89
|
@pagination_scope = scope
|
93
90
|
end
|
94
91
|
end
|
95
|
-
|
96
|
-
def _total_count_estimate
|
97
|
-
return unless @pagination_scope
|
98
|
-
|
99
|
-
sql = @pagination_scope.order_by(nil).to_sql(pagination: false)
|
100
|
-
::Simple::SQL.each("EXPLAIN #{sql}", *@pagination_scope.args) do |line|
|
101
|
-
next unless line =~ /\brows=(\d+)/
|
102
|
-
return Integer($1)
|
103
|
-
end
|
104
|
-
|
105
|
-
-1
|
106
|
-
end
|
107
|
-
|
108
|
-
def _total_count
|
109
|
-
return unless @pagination_scope
|
110
|
-
|
111
|
-
sql = @pagination_scope.order_by(nil).to_sql(pagination: false)
|
112
|
-
::Simple::SQL.ask("SELECT COUNT(*) FROM (#{sql}) _total_count", *@pagination_scope.args)
|
113
|
-
end
|
114
92
|
end
|
data/lib/simple/sql/scope.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
require_relative "scope/filters.rb"
|
4
4
|
require_relative "scope/order.rb"
|
5
5
|
require_relative "scope/pagination.rb"
|
6
|
+
require_relative "scope/count.rb"
|
7
|
+
require_relative "scope/count_by_groups.rb"
|
6
8
|
|
7
9
|
# The Simple::SQL::Scope class helps building scopes; i.e. objects
|
8
10
|
# that start as a quite basic SQL query, and allow one to add
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Simple::SQL::Scope
|
2
|
+
EXACT_COUNT_THRESHOLD = 10_000
|
3
|
+
|
4
|
+
# Returns the exact count of matching records
|
5
|
+
def count
|
6
|
+
sql = order_by(nil).to_sql(pagination: false)
|
7
|
+
::Simple::SQL.ask("SELECT COUNT(*) FROM (#{sql}) _total_count", *args)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns the fast count of matching records
|
11
|
+
#
|
12
|
+
# For counts larger than EXACT_COUNT_THRESHOLD this returns an estimate
|
13
|
+
def fast_count
|
14
|
+
estimate = estimated_count
|
15
|
+
return estimate if estimate > EXACT_COUNT_THRESHOLD
|
16
|
+
|
17
|
+
sql = order_by(nil).to_sql(pagination: false)
|
18
|
+
::Simple::SQL.ask("SELECT COUNT(*) FROM (#{sql}) _total_count", *args)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def estimated_count
|
24
|
+
sql = order_by(nil).to_sql(pagination: false)
|
25
|
+
::Simple::SQL.each("EXPLAIN #{sql}", *args) do |line|
|
26
|
+
next unless line =~ /\brows=(\d+)/
|
27
|
+
|
28
|
+
return Integer($1)
|
29
|
+
end
|
30
|
+
|
31
|
+
-1
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# rubocop:disable Metrics/AbcSize
|
2
|
+
# rubocop:disable Metrics/MethodLength
|
3
|
+
|
4
|
+
class Simple::SQL::Scope
|
5
|
+
# Potentially fast implementation of returning all different values for a specific group.
|
6
|
+
#
|
7
|
+
# For example:
|
8
|
+
#
|
9
|
+
# Scope.new("SELECT * FROM users").enumerate_groups("gender") -> [ "female", "male" ]
|
10
|
+
#
|
11
|
+
# It is possible to enumerate over multiple attributes, for example:
|
12
|
+
#
|
13
|
+
# scope.enumerate_groups fragment: "ARRAY[workflow, queue]"
|
14
|
+
#
|
15
|
+
# In any case it is important that an index exists that the database can use to group
|
16
|
+
# by the +sql_fragment+, for example:
|
17
|
+
#
|
18
|
+
# CREATE INDEX ix3 ON table((ARRAY[workflow, queue]));
|
19
|
+
#
|
20
|
+
def enumerate_groups(sql_fragment)
|
21
|
+
sql = order_by(nil).to_sql(pagination: false)
|
22
|
+
|
23
|
+
_, max_cost = ::Simple::SQL.costs "SELECT MIN(#{sql_fragment}) FROM (#{sql}) sq", *args
|
24
|
+
raise "enumerate_groups: takes too much time. Make sure to create a suitable index" if max_cost > 10_000
|
25
|
+
|
26
|
+
groups = []
|
27
|
+
var_name = "$#{@args.count + 1}"
|
28
|
+
cur = ::Simple::SQL.ask "SELECT MIN(#{sql_fragment}) FROM (#{sql}) sq", *args
|
29
|
+
|
30
|
+
while cur
|
31
|
+
groups << cur
|
32
|
+
cur = ::Simple::SQL.ask "SELECT MIN(#{sql_fragment}) FROM (#{sql}) sq"" WHERE #{sql_fragment} > #{var_name}", *args, cur
|
33
|
+
end
|
34
|
+
|
35
|
+
groups
|
36
|
+
end
|
37
|
+
|
38
|
+
def count_by(sql_fragment)
|
39
|
+
sql = order_by(nil).to_sql(pagination: false)
|
40
|
+
|
41
|
+
recs = ::Simple::SQL.all "SELECT #{sql_fragment} AS group, COUNT(*) AS count FROM (#{sql}) sq GROUP BY #{sql_fragment}", *args
|
42
|
+
Hash[recs]
|
43
|
+
end
|
44
|
+
|
45
|
+
def fast_count_by(sql_fragment)
|
46
|
+
sql = order_by(nil).to_sql(pagination: false)
|
47
|
+
|
48
|
+
_, max_cost = ::Simple::SQL.costs "SELECT COUNT(*) FROM (#{sql}) sq GROUP BY #{sql_fragment}", *args
|
49
|
+
|
50
|
+
return count_by(sql_fragment) if max_cost < 10_000
|
51
|
+
|
52
|
+
# iterate over all groups, estimating the count for each. If the count is
|
53
|
+
# less than EXACT_COUNT_THRESHOLD we ask for the exact count in that and
|
54
|
+
# similarily sparse groups.
|
55
|
+
var_name = "$#{@args.count + 1}"
|
56
|
+
|
57
|
+
counts = {}
|
58
|
+
sparse_groups = []
|
59
|
+
enumerate_groups(sql_fragment).each do |group|
|
60
|
+
scope = ::Simple::SQL::Scope.new("SELECT * FROM (#{sql}) sq WHERE #{sql_fragment}=#{var_name}", *args, group)
|
61
|
+
counts[group] = scope.send(:estimated_count)
|
62
|
+
sparse_groups << group if estimated_count < EXACT_COUNT_THRESHOLD
|
63
|
+
end
|
64
|
+
|
65
|
+
# fetch exact counts in all sparse_groups
|
66
|
+
unless sparse_groups.empty?
|
67
|
+
sparse_counts = ::Simple::SQL.all <<~SQL, *args, sparse_groups
|
68
|
+
SELECT #{sql_fragment} AS group, COUNT(*) AS count
|
69
|
+
FROM (#{sql}) sq
|
70
|
+
WHERE #{sql_fragment} = ANY(#{var_name})
|
71
|
+
GROUP BY #{sql_fragment}
|
72
|
+
SQL
|
73
|
+
|
74
|
+
counts.update Hash[sparse_counts]
|
75
|
+
end
|
76
|
+
|
77
|
+
counts
|
78
|
+
end
|
79
|
+
end
|
data/lib/simple/sql/version.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Simple::SQL::Scope#count_by" do
|
4
|
+
let!(:users) { 1.upto(10).map { |i| create(:user, role_id: i) } }
|
5
|
+
let(:all_role_ids) { SQL.all("SELECT DISTINCT role_id FROM users") }
|
6
|
+
let(:scope) { SQL::Scope.new("SELECT * FROM users") }
|
7
|
+
|
8
|
+
describe "enumerate_groups" do
|
9
|
+
it "returns all groups" do
|
10
|
+
expect(scope.enumerate_groups("role_id")).to contain_exactly(*all_role_ids)
|
11
|
+
expect(scope.where("role_id < 4").enumerate_groups("role_id")).to contain_exactly(*(1.upto(3).to_a))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "count_by" do
|
16
|
+
it "counts all groups" do
|
17
|
+
create(:user, role_id: 1)
|
18
|
+
create(:user, role_id: 1)
|
19
|
+
create(:user, role_id: 1)
|
20
|
+
|
21
|
+
expect(scope.count_by("role_id")).to include(1 => 4)
|
22
|
+
expect(scope.count_by("role_id")).to include(2 => 1)
|
23
|
+
expect(scope.count_by("role_id").keys).to contain_exactly(*all_role_ids)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "fast_count_by" do
|
28
|
+
before do
|
29
|
+
# 10_000 is chosen "magically". It is large enough to switch to the fast algorithm,
|
30
|
+
# but
|
31
|
+
allow(::Simple::SQL).to receive(:costs).and_return([0, 10_000])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "counts all groups" do
|
35
|
+
create(:user, role_id: 1)
|
36
|
+
create(:user, role_id: 1)
|
37
|
+
create(:user, role_id: 1)
|
38
|
+
|
39
|
+
expect(scope.fast_count_by("role_id")).to include(1 => 4)
|
40
|
+
expect(scope.fast_count_by("role_id")).to include(2 => 1)
|
41
|
+
expect(scope.fast_count_by("role_id").keys).to contain_exactly(*all_role_ids)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Simple::SQL::Scope#count" do
|
4
|
+
let!(:users) { 1.upto(USER_COUNT).map { create(:user) } }
|
5
|
+
let(:min_user_id) { SQL.ask "SELECT min(id) FROM users" }
|
6
|
+
let(:scope) { SQL::Scope.new("SELECT * FROM users") }
|
7
|
+
|
8
|
+
describe "exact count" do
|
9
|
+
it "counts" do
|
10
|
+
expect(scope.count).to eq(USER_COUNT)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "evaluates conditions" do
|
14
|
+
expect(scope.where("id < $1", min_user_id).count).to eq(0)
|
15
|
+
expect(scope.where("id <= $1", min_user_id).count).to eq(1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "fast count" do
|
20
|
+
it "counts" do
|
21
|
+
expect(scope.fast_count).to eq(USER_COUNT)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "evaluates conditions" do
|
25
|
+
expect(scope.where("id < $1", min_user_id).fast_count).to eq(0)
|
26
|
+
expect(scope.where("id <= $1", min_user_id).fast_count).to eq(1)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Simple::SQL logging" do
|
4
|
+
context 'when running a slow query' do
|
5
|
+
before do
|
6
|
+
SQL::Logging.slow_query_treshold = 0.05
|
7
|
+
end
|
8
|
+
after do
|
9
|
+
SQL::Logging.slow_query_treshold = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "does not crash" do
|
13
|
+
SQL.ask "SELECT pg_sleep(0.1)"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Simple::SQL::Result counts" do
|
4
|
+
let!(:users) { 1.upto(USER_COUNT).map { create(:user) } }
|
5
|
+
let(:min_user_id) { SQL.ask "SELECT min(id) FROM users" }
|
6
|
+
let(:scope) { SQL::Scope.new("SELECT * FROM users") }
|
7
|
+
let(:paginated_scope) { scope.paginate(per: 1, page: 1) }
|
8
|
+
|
9
|
+
describe "exact counting" do
|
10
|
+
it "counts" do
|
11
|
+
result = SQL.all(paginated_scope)
|
12
|
+
expect(result.total_count).to eq(USER_COUNT)
|
13
|
+
expect(result.total_pages).to eq(USER_COUNT)
|
14
|
+
expect(result.current_page).to eq(1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "fast counting" do
|
19
|
+
it "counts fast" do
|
20
|
+
result = SQL.all(paginated_scope)
|
21
|
+
|
22
|
+
expect(result.total_fast_count).to eq(USER_COUNT)
|
23
|
+
expect(result.total_fast_pages).to eq(USER_COUNT)
|
24
|
+
expect(result.current_page).to eq(1)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when running with a non-paginated paginated_scope' do
|
29
|
+
it "raises errors" do
|
30
|
+
result = SQL.all(scope)
|
31
|
+
|
32
|
+
expect { result.total_count }.to raise_error(RuntimeError)
|
33
|
+
expect { result.total_pages }.to raise_error(RuntimeError)
|
34
|
+
expect { result.current_page }.to raise_error(RuntimeError)
|
35
|
+
expect { result.total_fast_count }.to raise_error(RuntimeError)
|
36
|
+
expect { result.total_fast_pages }.to raise_error(RuntimeError)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
context 'when running with an empty, paginated paginated_scope' do
|
42
|
+
let(:scope) { SQL::Scope.new("SELECT * FROM users WHERE FALSE") }
|
43
|
+
let(:paginated_scope) { scope.paginate(per: 1, page: 1) }
|
44
|
+
|
45
|
+
it "returns correct results" do
|
46
|
+
result = SQL.all(paginated_scope)
|
47
|
+
|
48
|
+
expect(result.total_count).to eq(0)
|
49
|
+
expect(result.total_pages).to eq(1)
|
50
|
+
|
51
|
+
expect(result.total_fast_count).to eq(0)
|
52
|
+
expect(result.total_fast_pages).to eq(1)
|
53
|
+
|
54
|
+
expect(result.current_page).to eq(1)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -14,7 +14,9 @@ Dir.glob("./spec/support/**/*.rb").sort.each { |path| load path }
|
|
14
14
|
require "simple/sql"
|
15
15
|
|
16
16
|
unless ENV["USE_ACTIVE_RECORD"]
|
17
|
-
Simple::SQL.
|
17
|
+
database_url = Simple::SQL::Config.determine_url
|
18
|
+
|
19
|
+
Simple::SQL.connect! database_url
|
18
20
|
Simple::SQL.ask "DELETE FROM users"
|
19
21
|
end
|
20
22
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple-sql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.38
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- radiospiel
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-03-
|
12
|
+
date: 2019-03-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pg_array_parser
|
@@ -218,6 +218,8 @@ files:
|
|
218
218
|
- lib/simple/sql/result/association_loader.rb
|
219
219
|
- lib/simple/sql/result/records.rb
|
220
220
|
- lib/simple/sql/scope.rb
|
221
|
+
- lib/simple/sql/scope/count.rb
|
222
|
+
- lib/simple/sql/scope/count_by_groups.rb
|
221
223
|
- lib/simple/sql/scope/filters.rb
|
222
224
|
- lib/simple/sql/scope/order.rb
|
223
225
|
- lib/simple/sql/scope/pagination.rb
|
@@ -232,11 +234,15 @@ files:
|
|
232
234
|
- spec/simple/sql/associations_spec.rb
|
233
235
|
- spec/simple/sql/config_spec.rb
|
234
236
|
- spec/simple/sql/conversion_spec.rb
|
237
|
+
- spec/simple/sql/count_by_groups_spec.rb
|
238
|
+
- spec/simple/sql/count_spec.rb
|
235
239
|
- spec/simple/sql/duplicate_spec.rb
|
236
240
|
- spec/simple/sql/duplicate_unique_spec.rb
|
237
241
|
- spec/simple/sql/each_spec.rb
|
238
242
|
- spec/simple/sql/insert_spec.rb
|
243
|
+
- spec/simple/sql/logging_spec.rb
|
239
244
|
- spec/simple/sql/reflection_spec.rb
|
245
|
+
- spec/simple/sql/result_count_spec.rb
|
240
246
|
- spec/simple/sql/scope_spec.rb
|
241
247
|
- spec/simple/sql/version_spec.rb
|
242
248
|
- spec/simple/sql_locked_spec.rb
|
@@ -278,11 +284,15 @@ test_files:
|
|
278
284
|
- spec/simple/sql/associations_spec.rb
|
279
285
|
- spec/simple/sql/config_spec.rb
|
280
286
|
- spec/simple/sql/conversion_spec.rb
|
287
|
+
- spec/simple/sql/count_by_groups_spec.rb
|
288
|
+
- spec/simple/sql/count_spec.rb
|
281
289
|
- spec/simple/sql/duplicate_spec.rb
|
282
290
|
- spec/simple/sql/duplicate_unique_spec.rb
|
283
291
|
- spec/simple/sql/each_spec.rb
|
284
292
|
- spec/simple/sql/insert_spec.rb
|
293
|
+
- spec/simple/sql/logging_spec.rb
|
285
294
|
- spec/simple/sql/reflection_spec.rb
|
295
|
+
- spec/simple/sql/result_count_spec.rb
|
286
296
|
- spec/simple/sql/scope_spec.rb
|
287
297
|
- spec/simple/sql/version_spec.rb
|
288
298
|
- spec/simple/sql_locked_spec.rb
|