simple-sql 0.4.41 → 0.5.0
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 -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
|