simple-sql 0.4.41 → 0.5.0
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.
- checksums.yaml +4 -4
- data/lib/simple/sql.rb +1 -6
- data/lib/simple/sql/connection_adapter.rb +0 -10
- data/lib/simple/sql/logging.rb +1 -1
- data/lib/simple/sql/result.rb +20 -49
- data/lib/simple/sql/scope.rb +2 -4
- data/lib/simple/sql/version.rb +1 -1
- data/spec/spec_helper.rb +1 -3
- data/tasks/release.rake +4 -22
- metadata +4 -13
- data/lib/simple/sql/scope/count.rb +0 -33
- data/lib/simple/sql/scope/count_by_groups.rb +0 -79
- data/spec/simple/sql/count_by_groups_spec.rb +0 -44
- data/spec/simple/sql/count_spec.rb +0 -29
- data/spec/simple/sql/logging_spec.rb +0 -16
- data/spec/simple/sql/result_count_spec.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7a208873c084434a4267d43cfd76ccae14aa249e7ce2cd40de78e76fe4d0df8
|
4
|
+
data.tar.gz: c6c961737c2ebd4b57b5ab7946b872f229e63a8c22c275177825a8bcb5301cef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c5c053640e50ba398acf014f855fb28ea369bdd7806ae7a564f69ce87f1d7323dd58ced4ca9a77bd6e7a595266f16754a5de5d0ce6efc0f24fd29b2ea2acb39
|
7
|
+
data.tar.gz: af48f5add33e6330a526ec2d6486579f84f2e1b2fb7ee0d03aff0a0d65723da07ea8c5932978c26db6cf005aee2627c02ebb7c2b4ba273ad909c95fd0fa8b4bb
|
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
|
24
|
+
delegate [:ask, :all, :each, :exec, :locked, :print, :transaction, :wait_for_notify] => :default_connection
|
25
25
|
|
26
26
|
delegate [:logger, :logger=] => ::Simple::SQL::Logging
|
27
27
|
|
@@ -35,11 +35,6 @@ module Simple
|
|
35
35
|
Connection.create(database_url)
|
36
36
|
end
|
37
37
|
|
38
|
-
# deprecated
|
39
|
-
def configuration
|
40
|
-
Config.parse_url(Config.determine_url)
|
41
|
-
end
|
42
|
-
|
43
38
|
# -- default connection ---------------------------------------------------
|
44
39
|
|
45
40
|
DEFAULT_CONNECTION_KEY = :"Simple::SQL.default_connection"
|
@@ -90,16 +90,6 @@ 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
|
-
|
103
93
|
# Executes a block, usually of db insert code, while holding an
|
104
94
|
# advisory lock.
|
105
95
|
#
|
data/lib/simple/sql/logging.rb
CHANGED
data/lib/simple/sql/result.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
+
# rubocop:disable Metrics/AbcSize
|
1
2
|
# rubocop:disable Naming/AccessorMethodName
|
2
|
-
# rubocop:disable Style/DoubleNegation
|
3
|
-
# rubocop:disable Style/GuardClause
|
4
3
|
|
5
4
|
require_relative "helpers"
|
6
5
|
|
@@ -32,67 +31,39 @@ class ::Simple::SQL::Result < Array
|
|
32
31
|
replace(records)
|
33
32
|
end
|
34
33
|
|
35
|
-
# returns the
|
34
|
+
# returns the total_count of search hits
|
36
35
|
#
|
37
|
-
# This is
|
38
|
-
|
39
|
-
@total_fast_count ||= pagination_scope.fast_count
|
40
|
-
end
|
41
|
-
|
42
|
-
# returns the (potentialy estimated) total number of pages
|
43
|
-
#
|
44
|
-
# This is only available for paginated scopes
|
45
|
-
def total_fast_pages
|
46
|
-
@total_fast_pages ||= (total_fast_count * 1.0 / pagination_scope.per).ceil
|
47
|
-
end
|
48
|
-
|
49
|
-
# returns the (potentialy slow) exact total count of results
|
50
|
-
#
|
51
|
-
# This is only available for paginated scopes
|
52
|
-
def total_count
|
53
|
-
@total_count ||= pagination_scope.count
|
54
|
-
end
|
36
|
+
# This is filled in when resolving a paginated scope.
|
37
|
+
attr_reader :total_count
|
55
38
|
|
56
|
-
# returns the
|
39
|
+
# returns the total number of pages of search hits
|
57
40
|
#
|
58
|
-
# This is
|
59
|
-
|
60
|
-
|
61
|
-
end
|
41
|
+
# This is filled in when resolving a paginated scope. It takes
|
42
|
+
# into account the scope's "per" option.
|
43
|
+
attr_reader :total_pages
|
62
44
|
|
63
45
|
# returns the current page number in a paginated search
|
64
46
|
#
|
65
|
-
# This is
|
66
|
-
|
67
|
-
@current_page ||= pagination_scope.page
|
68
|
-
end
|
69
|
-
|
70
|
-
def paginated?
|
71
|
-
!!@pagination_scope
|
72
|
-
end
|
47
|
+
# This is filled in when resolving a paginated scope.
|
48
|
+
attr_reader :current_page
|
73
49
|
|
74
50
|
private
|
75
51
|
|
76
|
-
def pagination_scope
|
77
|
-
raise "Only available only for paginated scopes" unless paginated?
|
78
|
-
|
79
|
-
@pagination_scope
|
80
|
-
end
|
81
|
-
|
82
52
|
def set_pagination_info(scope)
|
83
53
|
raise ArgumentError, "per must be > 0" unless scope.per > 0
|
84
54
|
|
85
|
-
@pagination_scope = scope
|
86
|
-
|
87
|
-
# This branch is an optimization: the call to the database to count is
|
88
|
-
# not necessary if we know that there are not even any results on the
|
89
|
-
# first page.
|
90
55
|
if scope.page <= 1 && empty?
|
91
|
-
|
56
|
+
# This branch is an optimization: the call to the database to count is
|
57
|
+
# not necessary if we know that there are not even any results on the
|
58
|
+
# first page.
|
92
59
|
@total_count = 0
|
93
|
-
@
|
94
|
-
|
95
|
-
|
60
|
+
@current_page = 1
|
61
|
+
else
|
62
|
+
sql = "SELECT COUNT(*) FROM (#{scope.order_by(nil).to_sql(pagination: false)}) simple_sql_count"
|
63
|
+
@total_count = ::Simple::SQL.ask(sql, *scope.args)
|
64
|
+
@current_page = scope.page
|
96
65
|
end
|
66
|
+
|
67
|
+
@total_pages = (@total_count * 1.0 / scope.per).ceil
|
97
68
|
end
|
98
69
|
end
|
data/lib/simple/sql/scope.rb
CHANGED
@@ -3,8 +3,6 @@
|
|
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"
|
8
6
|
|
9
7
|
# The Simple::SQL::Scope class helps building scopes; i.e. objects
|
10
8
|
# that start as a quite basic SQL query, and allow one to add
|
@@ -26,11 +24,11 @@ class Simple::SQL::Scope
|
|
26
24
|
#
|
27
25
|
# Simple::SQL::Scope.new(table: "mytable", select: "*", where: { id: 1, foo: "bar" }, order_by: "id desc")
|
28
26
|
#
|
29
|
-
def initialize(sql
|
27
|
+
def initialize(sql)
|
30
28
|
expect! sql => [String, Hash]
|
31
29
|
|
32
30
|
@sql = nil
|
33
|
-
@args =
|
31
|
+
@args = []
|
34
32
|
@filters = []
|
35
33
|
|
36
34
|
case sql
|
data/lib/simple/sql/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -14,9 +14,7 @@ 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
|
-
|
18
|
-
|
19
|
-
Simple::SQL.connect! database_url
|
17
|
+
Simple::SQL.connect!
|
20
18
|
Simple::SQL.ask "DELETE FROM users"
|
21
19
|
end
|
22
20
|
|
data/tasks/release.rake
CHANGED
@@ -61,7 +61,7 @@ namespace :release do
|
|
61
61
|
|
62
62
|
desc "Push code and tags"
|
63
63
|
task :push do
|
64
|
-
sh(
|
64
|
+
sh('git push origin master')
|
65
65
|
sh('git push --tags')
|
66
66
|
end
|
67
67
|
|
@@ -71,37 +71,19 @@ namespace :release do
|
|
71
71
|
end
|
72
72
|
|
73
73
|
desc "Push Gem to gemfury"
|
74
|
-
task :
|
74
|
+
task :push_to_rubygems do
|
75
75
|
Dir.chdir(GEM_ROOT) { sh("gem push #{Dir.glob('*.gem').first}") }
|
76
76
|
end
|
77
77
|
|
78
|
-
task :target_master do
|
79
|
-
$TARGET_BRANCH = 'master'
|
80
|
-
end
|
81
|
-
|
82
|
-
task :target_stable do
|
83
|
-
$TARGET_BRANCH = 'stable'
|
84
|
-
end
|
85
|
-
|
86
|
-
task :checkout do
|
87
|
-
sh "git status --untracked-files=no --porcelain > /dev/null || (echo '*** working dir not clean' && false)"
|
88
|
-
sh "git checkout #{$TARGET_BRANCH}"
|
89
|
-
sh "git pull"
|
90
|
-
end
|
91
|
-
|
92
78
|
task default: [
|
93
|
-
'checkout',
|
94
79
|
'version',
|
95
80
|
'clean',
|
96
81
|
'build',
|
97
82
|
'commit',
|
98
83
|
'push',
|
99
|
-
'
|
84
|
+
'push_to_rubygems'
|
100
85
|
]
|
101
|
-
|
102
|
-
task master: %w(target_master default)
|
103
|
-
task stable: %w(target_stable default)
|
104
86
|
end
|
105
87
|
|
106
88
|
desc "Clean, build, commit and push"
|
107
|
-
task release: 'release:
|
89
|
+
task release: 'release:default'
|
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
|
+
version: 0.5.0
|
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-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pg_array_parser
|
@@ -218,8 +218,6 @@ 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
|
223
221
|
- lib/simple/sql/scope/filters.rb
|
224
222
|
- lib/simple/sql/scope/order.rb
|
225
223
|
- lib/simple/sql/scope/pagination.rb
|
@@ -234,15 +232,11 @@ files:
|
|
234
232
|
- spec/simple/sql/associations_spec.rb
|
235
233
|
- spec/simple/sql/config_spec.rb
|
236
234
|
- spec/simple/sql/conversion_spec.rb
|
237
|
-
- spec/simple/sql/count_by_groups_spec.rb
|
238
|
-
- spec/simple/sql/count_spec.rb
|
239
235
|
- spec/simple/sql/duplicate_spec.rb
|
240
236
|
- spec/simple/sql/duplicate_unique_spec.rb
|
241
237
|
- spec/simple/sql/each_spec.rb
|
242
238
|
- spec/simple/sql/insert_spec.rb
|
243
|
-
- spec/simple/sql/logging_spec.rb
|
244
239
|
- spec/simple/sql/reflection_spec.rb
|
245
|
-
- spec/simple/sql/result_count_spec.rb
|
246
240
|
- spec/simple/sql/scope_spec.rb
|
247
241
|
- spec/simple/sql/version_spec.rb
|
248
242
|
- spec/simple/sql_locked_spec.rb
|
@@ -273,7 +267,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
273
267
|
- !ruby/object:Gem::Version
|
274
268
|
version: '0'
|
275
269
|
requirements: []
|
276
|
-
|
270
|
+
rubyforge_project:
|
271
|
+
rubygems_version: 2.7.6
|
277
272
|
signing_key:
|
278
273
|
specification_version: 4
|
279
274
|
summary: SQL with a simple interface
|
@@ -284,15 +279,11 @@ test_files:
|
|
284
279
|
- spec/simple/sql/associations_spec.rb
|
285
280
|
- spec/simple/sql/config_spec.rb
|
286
281
|
- spec/simple/sql/conversion_spec.rb
|
287
|
-
- spec/simple/sql/count_by_groups_spec.rb
|
288
|
-
- spec/simple/sql/count_spec.rb
|
289
282
|
- spec/simple/sql/duplicate_spec.rb
|
290
283
|
- spec/simple/sql/duplicate_unique_spec.rb
|
291
284
|
- spec/simple/sql/each_spec.rb
|
292
285
|
- spec/simple/sql/insert_spec.rb
|
293
|
-
- spec/simple/sql/logging_spec.rb
|
294
286
|
- spec/simple/sql/reflection_spec.rb
|
295
|
-
- spec/simple/sql/result_count_spec.rb
|
296
287
|
- spec/simple/sql/scope_spec.rb
|
297
288
|
- spec/simple/sql/version_spec.rb
|
298
289
|
- spec/simple/sql_locked_spec.rb
|
@@ -1,33 +0,0 @@
|
|
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
|
@@ -1,79 +0,0 @@
|
|
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
|
@@ -1,44 +0,0 @@
|
|
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
|
@@ -1,29 +0,0 @@
|
|
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
|
@@ -1,16 +0,0 @@
|
|
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
|
@@ -1,57 +0,0 @@
|
|
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
|