simple-sql 0.5.18 → 0.5.19

Sign up to get free protection for your applications and to get access to all the features.
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