simple-sql 0.5.18 → 0.5.19

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 539c668c59391992ee22ef86ddc7c6d9a20030cbbcf473ddba4d4c8eccdf2a4f
4
- data.tar.gz: 28ab53f413beff60ad5bf3ab55769c5fb526ace82419e2bd695bc4cbd81bba82
3
+ metadata.gz: 8f07bda4a766c4847fdb1b6ff5b2ffbb46aadf64e57ae72ae0e033027aba2d13
4
+ data.tar.gz: 8637da9a4e8de6f7a57c8003db0fb27e0d479005730e88e14476f3c5e7edc6ca
5
5
  SHA512:
6
- metadata.gz: d518fb85eeb923e61f75d4d51a52330e2a22cbf730a51238d0f7df389903cea13aad48a1c49b52fb54d2b083b300637aea282a3ca77f902d28845a0e1d3d28cd
7
- data.tar.gz: 4e18e1e40a62e1b2b4231ddb342a978b7d04df7deddfa9f410d81ab14d0c30a548b3976b8b1e25f04b984f8e0123c33eec9fc9ccedab512c76db4934b5af86fd
6
+ metadata.gz: 35b8dec9461128d4c1250c6ab3451431aa6defc442afb03cbbeb2fdb5247b9b4258aebcfb86014cf4d6bcad8313320ae028d6d65519a66cddd3dbb35524feb9c
7
+ data.tar.gz: b087a97ff95ec6f848bde598625ceaf4fd3864cfb3e37a17d7001edab4eabaffcaf5b124e7b401108fbd5622f25bc02eb019bb428d071f7d4bcbb37345cc1cb4
@@ -59,11 +59,9 @@ module Simple
59
59
 
60
60
  # -- default connection ---------------------------------------------------
61
61
 
62
- DEFAULT_CONNECTION_KEY = :"Simple::SQL.default_connection"
63
-
64
62
  # returns the default connection.
65
63
  def default_connection
66
- Thread.current[DEFAULT_CONNECTION_KEY] ||= connect(:auto)
64
+ @default_connection ||= connect(:auto)
67
65
  end
68
66
 
69
67
  # connects to the database specified via the url parameter, and sets
@@ -72,16 +70,13 @@ module Simple
72
70
  # \see connect, default_connection
73
71
  def connect!(database_url = :auto)
74
72
  disconnect!
75
- Thread.current[DEFAULT_CONNECTION_KEY] ||= connect(database_url)
73
+ @default_connection = connect(database_url)
76
74
  end
77
75
 
78
76
  # disconnects the current default connection.
79
77
  def disconnect!
80
- connection = Thread.current[DEFAULT_CONNECTION_KEY]
81
- return unless connection
82
-
83
- connection.disconnect!
84
- Thread.current[DEFAULT_CONNECTION_KEY] = nil
78
+ ::Simple::SQL::ConnectionManager.disconnect_all!
79
+ @default_connection = nil
85
80
  end
86
81
  end
87
82
  end
@@ -4,6 +4,8 @@ end
4
4
  require "pg"
5
5
  require "active_record"
6
6
 
7
+ require_relative "connection_manager"
8
+
7
9
  require_relative "connection/base"
8
10
  require_relative "connection/lock"
9
11
  require_relative "connection/scope"
@@ -17,80 +19,49 @@ require_relative "connection/type_info"
17
19
  # It Method.includes the ConnectionAdapter, which implements ask, all, + friends
18
20
  #
19
21
  class Simple::SQL::Connection
22
+ ConnectionManager = ::Simple::SQL::ConnectionManager
23
+
20
24
  def self.create(database_url = :auto)
21
- case database_url
22
- when nil then DefaultConnection.new
23
- when String then ExplicitConnection.new(database_url)
24
- when :auto
25
- if ::ActiveRecord::Base.connected?
26
- DefaultConnection.new
27
- else
28
- ExplicitConnection.new(::Simple::SQL::Config.determine_url)
29
- end
25
+ expect! database_url => [nil, :auto, String]
26
+ new connection_class(database_url)
27
+ end
28
+
29
+ def self.connection_class(database_url)
30
+ if database_url.nil?
31
+ ::ActiveRecord::Base
32
+ elsif database_url.is_a?(String)
33
+ ConnectionManager.connection_class(database_url)
34
+ elsif ::ActiveRecord::Base.connected?
35
+ # database_url is :auto, and we are connected. This happens, for example,
36
+ # within a rails controller. IT IS IMPORTANT NOT TO CONNECT AGAINST THE
37
+ # ::Simple::SQL::Config.determine_url! Only so we can make sure that
38
+ # simple-sql and ActiveRecord can be mixed freely together, i.e. they are
39
+ # sharing the same connection.
40
+ ::ActiveRecord::Base
30
41
  else
31
- expect! database_url => [nil, :auto, String]
42
+ ConnectionManager.connection_class(::Simple::SQL::Config.determine_url)
32
43
  end
33
44
  end
34
45
 
35
- def initialize(active_record_class)
36
- @active_record_class = active_record_class
46
+ def initialize(connection_class)
47
+ @connection_class = connection_class
37
48
  end
38
49
 
39
50
  def raw_connection
40
- @active_record_class.connection.raw_connection
51
+ @connection_class.connection.raw_connection
41
52
  end
42
53
 
43
54
  def transaction(&block)
44
- @active_record_class.connection.transaction(&block)
55
+ @connection_class.connection.transaction(&block)
45
56
  end
46
57
 
47
- extend Forwardable
48
- delegate [:wait_for_notify] => :raw_connection
49
-
50
- # -- specific connection classes --------------------------------------------
51
-
52
- class DefaultConnection < self
53
- def initialize
54
- @active_record_class = ::ActiveRecord::Base
55
- end
56
-
57
- def disconnect!; end
58
+ def disconnect!
59
+ return unless @connection_class && @connection_class != ::ActiveRecord::Base
60
+ @connection_class.remove_connection
58
61
  end
59
62
 
60
- class ExplicitConnection < self
61
- def initialize(url)
62
- super create_active_record_class(url)
63
- end
64
-
65
- def disconnect!
66
- return unless @active_record_class
67
-
68
- @active_record_class.remove_connection
69
- end
70
-
71
- private
72
-
73
- # ActiveRecord needs a class name in order to connect.
74
- module WritableClassName
75
- attr_accessor :name
76
- end
77
-
78
- # create_active_record_class builds a ActiveRecord::Base class, whose
79
- # ConnectionPool we are going to use for this connection.
80
- def create_active_record_class(url)
81
- Class.new(ActiveRecord::Base).tap do |klass|
82
- klass.extend WritableClassName
83
- klass.name = "Simple::SQL::Connection::ExplicitConnection::Adapter"
84
- klass.establish_connection url
85
-
86
- connection_pool = klass.connection_pool
87
- connection_pool_stats = {
88
- size: connection_pool.size,
89
- automatic_reconnect: connection_pool.automatic_reconnect,
90
- checkout_timeout: connection_pool.checkout_timeout
91
- }
92
- ::Simple::SQL.logger.info "#{url}: connected to connection pool w/#{connection_pool_stats.inspect}"
93
- end
94
- end
95
- end
63
+ extend Forwardable
64
+ delegate [:wait_for_notify] => :raw_connection
96
65
  end
66
+
67
+ # TODO disconnect! reconnect!
@@ -0,0 +1,50 @@
1
+ # The ConnectionManager manages a pool of ActiveRecord::Base classes.
2
+ #
3
+ # ActiveRecord assigns a connection_pool to a class. If you want to connect to
4
+ # multiple detabases you must inherit from ActiveRecord::Base. This is what
5
+ # we do dynamically in this ConnectionManager.
6
+ #
7
+ # Note that connections to the same database are always shared within a single
8
+ # ConnectionPool.
9
+ module Simple::SQL
10
+ module ConnectionManager
11
+ extend self
12
+
13
+ def disconnect_all!
14
+ ActiveRecord::Base.connection_pool.disconnect!
15
+ connection_classes.values.map(&:connection_pool).each(&:disconnect!)
16
+ connection_classes.clear
17
+ end
18
+
19
+ def connection_class(url)
20
+ connection_classes[url] ||= create_connection_class(url)
21
+ end
22
+
23
+ private
24
+
25
+ def connection_classes
26
+ @connection_classes ||= {}
27
+ end
28
+
29
+ # ActiveRecord needs a class name in order to connect.
30
+ module WritableClassName
31
+ attr_accessor :name
32
+ end
33
+
34
+ def create_connection_class(url)
35
+ Class.new(ActiveRecord::Base).tap do |klass|
36
+ klass.extend WritableClassName
37
+ klass.name = "Simple::SQL::Connection::ExplicitConnection::Adapter/#{url}"
38
+
39
+ klass.establish_connection url
40
+ connection_pool = klass.connection_pool
41
+ connection_pool_stats = {
42
+ size: connection_pool.size,
43
+ automatic_reconnect: connection_pool.automatic_reconnect,
44
+ checkout_timeout: connection_pool.checkout_timeout
45
+ }
46
+ ::Simple::SQL.logger.info "#{url}: connected to connection pool w/#{connection_pool_stats.inspect}"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -24,12 +24,7 @@ module Simple
24
24
 
25
25
  def default_logger
26
26
  # return the ActiveRecord logger, if it exists.
27
- if defined?(ActiveRecord)
28
- logger = ActiveRecord::Base.logger
29
- return logger if logger
30
- end
31
-
32
- stderr_logger
27
+ ::ActiveRecord::Base.logger || stderr_logger
33
28
  end
34
29
 
35
30
  def stderr_logger
@@ -1,5 +1,5 @@
1
1
  module Simple
2
2
  module SQL
3
- VERSION = "0.5.18"
3
+ VERSION = "0.5.19"
4
4
  end
5
5
  end
@@ -1,78 +1,66 @@
1
1
  require "spec_helper"
2
2
 
3
- describe "Simple::SQL.connect" do
4
- let!(:default_pg_backend_pid) { Simple::SQL.ask "SELECT pg_backend_pid()" }
5
-
6
- def connection_count(db: nil)
7
- db ||= ::Simple::SQL
8
- db.ask("SELECT sum(numbackends) FROM pg_stat_database")
9
- end
10
-
11
- context 'without an argument' do
12
- let(:params) { [] }
13
-
14
- it 'is reusing the existing ActiveRecord connection' do
15
- Simple::SQL.with_connection(*params) do |db|
16
- expect(default_pg_backend_pid).to eq(db.ask("SELECT pg_backend_pid()"))
17
- expect(db).not_to be_a(Simple::SQL::Connection::ExplicitConnection)
18
- end
3
+ describe "Connections" do
4
+ describe "Simple::SQL.connect" do
5
+ before do
6
+ org = create(:organization)
7
+ 2.times { create(:user, organization_id: org.id) }
8
+ end
19
9
 
20
- expect(::Simple::SQL.ask("SELECT sum(numbackends) FROM pg_stat_database")).to eq(1)
10
+ after do
11
+ expect(User.count).to eq(2)
21
12
  end
22
13
 
23
- it 'is not estabishing a new connection' do
24
- initial_connection_count = connection_count
14
+ describe 'automatic connections' do
15
+ let(:db) { Simple::SQL.connect }
25
16
 
26
- Simple::SQL.with_connection(*params) do |db|
27
- db.ask("SELECT 1")
28
- expect(connection_count).to eq(initial_connection_count)
29
- end
17
+ it 'can mix Simple::SQL inside ActiveRecord' do
18
+ User.transaction do
19
+ User.delete_all
20
+ expect(db.ask("SELECT count(*) FROM users")).to eq(0)
30
21
 
31
- expect(connection_count).to eq(initial_connection_count)
32
- end
33
- end
22
+ raise ActiveRecord::Rollback
23
+ end
24
+
25
+ db.transaction do
26
+ db.ask("DELETE FROM users")
34
27
 
35
- context 'with an :auto argument' do
36
- let(:params) { [:auto] }
28
+ expect(User.count).to eq(0)
37
29
 
38
- it 'is reusing the existing ActiveRecord connection' do
39
- Simple::SQL.with_connection(*params) do |db|
40
- expect(default_pg_backend_pid).to eq(db.ask("SELECT pg_backend_pid()"))
41
- expect(db).not_to be_a(Simple::SQL::Connection::ExplicitConnection)
30
+ raise ActiveRecord::Rollback
31
+ end
42
32
  end
43
33
  end
44
34
 
45
- it 'is not estabishing a new connection' do
46
- initial_connection_count = connection_count
35
+ describe 'explizit connections' do
36
+ let(:db) { Simple::SQL.connect(::Simple::SQL::Config.determine_url) }
47
37
 
48
- Simple::SQL.with_connection(*params) do |db|
49
- db.ask("SELECT 1")
50
- expect(connection_count).to eq(initial_connection_count)
51
- end
38
+ it 'runs in separate transactions' do
39
+ User.transaction do
40
+ User.delete_all
41
+ expect(db.ask("SELECT count(*) FROM users")).to eq(2)
52
42
 
53
- expect(connection_count).to eq(initial_connection_count)
54
- end
55
- end
43
+ raise ActiveRecord::Rollback
44
+ end
45
+
46
+ db.transaction do
47
+ db.ask("DELETE FROM users")
56
48
 
57
- context 'with an explicit URL' do
58
- let(:params) { [Simple::SQL::Config.determine_url] }
49
+ expect(User.count).to eq(2)
59
50
 
60
- it 'is reconnecting using the passed in URL' do
61
- Simple::SQL.with_connection(*params) do |db|
62
- expect(default_pg_backend_pid).not_to eq(db.ask("SELECT pg_backend_pid()"))
63
- expect(db).to be_a(Simple::SQL::Connection::ExplicitConnection)
51
+ raise ActiveRecord::Rollback
52
+ end
64
53
  end
65
54
  end
55
+ end
66
56
 
67
- it 'is estabishing a new connection' do
68
- initial_connection_count = connection_count
69
-
70
- Simple::SQL.with_connection(*params) do |db|
71
- db.ask("SELECT 1")
72
- expect(connection_count).to be > initial_connection_count
73
- end
57
+ describe "Simple::SQL.disconnect!" do
58
+ let(:default_db) { Simple::SQL.connect }
59
+ let(:db) { Simple::SQL.connect(::Simple::SQL::Config.determine_url) }
74
60
 
75
- expect(connection_count).to eq(initial_connection_count)
61
+ it 'disconnects everything' do
62
+ Simple::SQL.disconnect!
63
+ expect(ActiveRecord::Base.connection_pool.connections.length).to eq(0)
76
64
  end
77
65
  end
78
66
  end
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.5.18
4
+ version: 0.5.19
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-07-06 00:00:00.000000000 Z
12
+ date: 2019-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: pg_array_parser
@@ -203,6 +203,7 @@ files:
203
203
  - lib/simple/sql/connection/scope/pagination.rb
204
204
  - lib/simple/sql/connection/scope/shorthand.rb
205
205
  - lib/simple/sql/connection/type_info.rb
206
+ - lib/simple/sql/connection_manager.rb
206
207
  - lib/simple/sql/formatting.rb
207
208
  - lib/simple/sql/fragment.rb
208
209
  - lib/simple/sql/helpers.rb
@@ -268,7 +269,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
268
269
  - !ruby/object:Gem::Version
269
270
  version: '0'
270
271
  requirements: []
271
- rubygems_version: 3.0.2
272
+ rubygems_version: 3.0.4
272
273
  signing_key:
273
274
  specification_version: 4
274
275
  summary: SQL with a simple interface