sequel 4.35.0 → 4.36.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/doc/association_basics.rdoc +27 -4
  4. data/doc/migration.rdoc +24 -0
  5. data/doc/release_notes/4.36.0.txt +116 -0
  6. data/lib/sequel/adapters/jdbc/h2.rb +1 -1
  7. data/lib/sequel/adapters/mysql2.rb +11 -1
  8. data/lib/sequel/adapters/oracle.rb +3 -5
  9. data/lib/sequel/adapters/postgres.rb +2 -2
  10. data/lib/sequel/adapters/shared/access.rb +1 -1
  11. data/lib/sequel/adapters/shared/oracle.rb +1 -1
  12. data/lib/sequel/adapters/shared/postgres.rb +1 -1
  13. data/lib/sequel/adapters/shared/sqlite.rb +1 -1
  14. data/lib/sequel/connection_pool.rb +5 -0
  15. data/lib/sequel/connection_pool/sharded_single.rb +1 -1
  16. data/lib/sequel/connection_pool/sharded_threaded.rb +29 -14
  17. data/lib/sequel/connection_pool/single.rb +1 -1
  18. data/lib/sequel/connection_pool/threaded.rb +5 -3
  19. data/lib/sequel/database/schema_methods.rb +7 -1
  20. data/lib/sequel/dataset/sql.rb +4 -0
  21. data/lib/sequel/extensions/arbitrary_servers.rb +1 -1
  22. data/lib/sequel/extensions/connection_expiration.rb +89 -0
  23. data/lib/sequel/extensions/connection_validator.rb +11 -3
  24. data/lib/sequel/extensions/constraint_validations.rb +28 -0
  25. data/lib/sequel/extensions/string_agg.rb +178 -0
  26. data/lib/sequel/model.rb +13 -56
  27. data/lib/sequel/model/associations.rb +3 -1
  28. data/lib/sequel/model/base.rb +104 -7
  29. data/lib/sequel/plugins/constraint_validations.rb +17 -3
  30. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  31. data/lib/sequel/sql.rb +8 -0
  32. data/lib/sequel/version.rb +1 -1
  33. data/spec/adapters/postgres_spec.rb +4 -0
  34. data/spec/core/dataset_spec.rb +4 -0
  35. data/spec/core/expression_filters_spec.rb +4 -0
  36. data/spec/extensions/connection_expiration_spec.rb +121 -0
  37. data/spec/extensions/connection_validator_spec.rb +7 -0
  38. data/spec/extensions/constraint_validations_plugin_spec.rb +14 -0
  39. data/spec/extensions/constraint_validations_spec.rb +64 -0
  40. data/spec/extensions/string_agg_spec.rb +85 -0
  41. data/spec/extensions/validation_helpers_spec.rb +2 -0
  42. data/spec/integration/plugin_test.rb +37 -2
  43. data/spec/model/association_reflection_spec.rb +10 -0
  44. data/spec/model/model_spec.rb +49 -0
  45. metadata +8 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29e8963c69c4f6e3b0af0840e6cc881934ca608f
4
- data.tar.gz: 30d2fa8ead89124fa8a4e8a4582a11a78bf7a5c8
3
+ metadata.gz: bb4a5a3794c2842c41482c01c74e82c2eed2f548
4
+ data.tar.gz: b4e04bef12f7580b1fa3857a9a6d820ce5e977df
5
5
  SHA512:
6
- metadata.gz: 2961452f5e6b3f1ab7e32da5e4a4dd92e9362a13bb561999ebd493ab8877132d803b7c3e22206ded6a9c2e8336a9bde344c3e2707cbe81732a115d45383d4186
7
- data.tar.gz: 72c885ba7219f83ac043bf213045f7b67ebbf213c4aa8380224c9c9d76fd1cd446f043e77ba0765e34684cf0fd35300b6b966a688f6e631e83b4b556ecb25b76
6
+ metadata.gz: b35ce656b26c851e5b5e2bf19c4ce5a40e83f6d79d939561a6e2d584b5210f91cbef788dbbb0a6c47154baa91f039eea6fb81053bdb03f016bf2a40a0da0f5eb
7
+ data.tar.gz: 829169bda7ea5e43e8ef6d6b9726ba950adb033e6a4f992a3fb677cded90ca1ec842bb90632ba21aa15b4c6184db0fb45d3ce37b908e9d8fcd4f1591e13a7954
data/CHANGELOG CHANGED
@@ -1,3 +1,35 @@
1
+ === 4.36.0 (2016-07-01)
2
+
3
+ * Deprecate use of Bignum class as generic type, since the behavior will change in ruby 2.4 (jeremyevans)
4
+
5
+ * Don't hold connection pool mutex while disconnecting connections (jeremyevans)
6
+
7
+ * Don't hold references to disconnected connections in the connection_validator extension (jeremyevans)
8
+
9
+ * Don't overwrite existing connection_validation_timeout when loading connection_validator extension multiple times (jeremyevans)
10
+
11
+ * Add connection_expiration extension, for automatically removing connections open for too long (pdrakeweb) (#1208, #1209)
12
+
13
+ * Handle disconnection errors raised during string literalization in mysql2 and postgres adapters (jeremyevans)
14
+
15
+ * Add string_agg extension for aggregate string concatenation support on many databases (jeremyevans)
16
+
17
+ * Add SQL::Function#order for ordered aggregate functions (jeremyevans)
18
+
19
+ * Support operator validation in constraint_validations for <, <=, >, and >= operators with string and integer arguments (jeremyevans)
20
+
21
+ * Make validates_operator validation consider nil values invalid unless :allow_nil or similar option is used (jeremyevans)
22
+
23
+ * Close cursors for non-SELECT queries in the oracle adapter after execution, instead of waiting until GC (jeremyevans) (#1203)
24
+
25
+ * Add :class_namespace association option for setting default namespace for :class option given as symbol/string (jeremyevans)
26
+
27
+ * Add Sequel::Model.cache_anonymous_models accessor for changing caching on a per-model basis (jeremyevans)
28
+
29
+ * Add Sequel::Model.def_Model for adding a Model() method to a module, for easier use of namespaced models (jeremyevans)
30
+
31
+ * Add Sequel::Model::Model() for creating subclasses of Sequel::Model subclasses, instead of just Sequel::Model itself (jeremyevans)
32
+
1
33
  === 4.35.0 (2016-06-01)
2
34
 
3
35
  * Add :headline option to PostgreSQL Dataset#full_text_search for adding an extract of the matched text to the SELECT list (jeremyevans)
@@ -907,11 +907,13 @@ you need to setup a delayed evaluation:
907
907
 
908
908
  This is the class of the associated objects that will be used. It's
909
909
  one of the most commonly used options. If it is not given, it guesses
910
- based on the name of the association. If a *_to_many association is
911
- used, uses the singular form of the association name. For example:
910
+ based on the name of the association, including considering the namespace
911
+ of the current model. If a *_to_many association is used, uses the
912
+ singular form of the association name. For example:
912
913
 
913
914
  Album.many_to_one :artist # guesses Artist
914
915
  Artist.one_to_many :albums # guesses Album
916
+ Foo::Artist.one_to_many :albums # guesses Foo::Album
915
917
 
916
918
  However, for more complex associations, especially ones that add
917
919
  additional filters beyond the foreign/primary key relationships, the
@@ -925,10 +927,18 @@ default class guessed will be wrong:
925
927
  You can specify the :class option using the class itself, a Symbol,
926
928
  or a String:
927
929
 
928
- Album.many_to_one :artist, :class=>Artist # Class
929
- Album.many_to_one :artist, :class=>:Artist # Symbol
930
+ Album.many_to_one :artist, :class=>Artist # Class
931
+ Album.many_to_one :artist, :class=>:Artist # Symbol
930
932
  Album.many_to_one :artist, :class=>"Artist" # String
931
933
 
934
+ If you are namespacing your models, and you need to specify the :class
935
+ option, the path you give to the :class option should be the full path
936
+ to the associated class including any namespaces:
937
+
938
+ Foo::Album.many_to_one :artist # Uses Foo::Artist
939
+ Foo::Album.many_to_one :artist, :class=>"Artist" # Uses Artist
940
+ Foo::Album.many_to_one :artist, :class=>"Foo::Artist" # Uses Foo::Artist
941
+
932
942
  ==== :key
933
943
 
934
944
  For +many_to_one+ associations, this is the foreign_key in the current model's
@@ -1758,6 +1768,19 @@ a many_to_many association where there is a unique index in the join table
1758
1768
  so that you know only one object will ever be associated through the
1759
1769
  association.
1760
1770
 
1771
+ ==== :class_namespace
1772
+
1773
+ If the :class option is specified as a symbol or string, the default namespace
1774
+ in which to look up the class. If the :class option is not specified as a
1775
+ symbol or string, this option is ignored. This namespace can be overridden
1776
+ by starting the string or symbol with <tt>::</tt>:
1777
+
1778
+ Foo::Album.many_to_one :artist, :class=>"Artist" # Uses Artist
1779
+ Foo::Album.many_to_one :artist, :class=>"Artist", :class_namespace=>'Foo' # Uses Foo::Artist
1780
+ Foo::Album.many_to_one :artist, :class=>"Foo::Artist", :class_namespace=>'Foo' # Uses Foo::Foo::Artist
1781
+ Foo::Album.many_to_one :artist, :class=>"::Artist", :class_namespace=>'Foo' # Uses Artist
1782
+ Foo::Album.many_to_one :artist, :class=>"::Foo::Artist", :class_namespace=>'Foo' # Uses Foo::Artist
1783
+
1761
1784
  ==== :methods_module
1762
1785
 
1763
1786
  The module that the methods created by the association will be placed
@@ -611,3 +611,27 @@ or:
611
611
  This usage is discouraged in new code, but will continue to be supported indefinitely.
612
612
  It is not recommended to convert old-style migration classes to the <tt>Sequel.migration</tt>
613
613
  DSL, but it is recommended to use the <tt>Sequel.migration</tt> DSL for all new migrations.
614
+
615
+ == Database-specific migrations
616
+
617
+ While not a recommended practice, it is sometimes necessary to have parts of migrations be
618
+ database-specific . You can use the Sequel::Database#database_type method to check which
619
+ database the migration is being run on, and operate accordingly:
620
+
621
+ Sequel.migration do
622
+ up do
623
+ if database_type == :mysql
624
+ run 'MySQL specific code'
625
+ else
626
+ run 'Generic SQL code'
627
+ end
628
+ end
629
+
630
+ down do
631
+ if database_type == :mysql
632
+ run 'MySQL specific code'
633
+ else
634
+ run 'Generic SQL code'
635
+ end
636
+ end
637
+ end
@@ -0,0 +1,116 @@
1
+ = New Features
2
+
3
+ * Sequel::Model::Model() has been added, which allows for
4
+ Sequel::Model() like behavior where the base class used is a
5
+ subclass of Sequel::Model. To make it easier to use,
6
+ Sequel::Model.def_Model has also been added, which takes a module
7
+ and adds a Model() method to the module that calls Model() on the
8
+ receiver.
9
+
10
+ A :class_namespace association option has been added to make it
11
+ possible to set a default namespace for the :class option if given
12
+ as a symbol or string.
13
+
14
+ Sequel::Model.Model.cache_anonymous_models has been added and
15
+ controls whether to cache anonymous model subclasses created by
16
+ Sequel::Model::Model() on a per-class basis.
17
+
18
+ These changes are designed to make it easier to use namespaced
19
+ models, for example:
20
+
21
+ module Foo
22
+ Model = Class.new(Sequel::Model)
23
+ Model.def_Model(self)
24
+ DB = Model.db = Sequel.connect(ENV['FOO_DATABASE_URL'])
25
+ Model.plugin :prepared_statements
26
+ Model.default_association_options[:class_namespace] = 'Foo'
27
+
28
+ class Bar < Model
29
+ # Uses Foo::DB[:bars] as dataset
30
+
31
+ # Implicitly uses Foo::Baz as associated class
32
+ one_to_many :bazes
33
+
34
+ # Uses Foo::Baz due to :class_namespace option
35
+ one_to_many :oldest_bazes, :class=>:Baz, :order=>:id
36
+ end
37
+
38
+ class Baz < Model(:my_baz)
39
+ # Uses Foo::DB[:my_baz] as dataset
40
+
41
+ # Implicitly uses Foo::Bar as associated class
42
+ one_to_many :bars
43
+
44
+ # Uses Foo::Bar due to :class_namespace option
45
+ one_to_many :oldest_bars, :class=>:Bar, :order=>:id
46
+ end
47
+ end
48
+
49
+ * A string_agg extension has been added for aggregate string
50
+ concatentation support on PostgreSQL 9+, SQLAnywhere 12+,
51
+ Oracle11g+, DB 9.7+, MySQL, HSQLDB, H2, and CUBRID:
52
+
53
+ DB.extension :string_agg
54
+ ds = DB[:table]
55
+ ds.get(Sequel.string_agg(:c)) # ',' default separator
56
+ ds.get(Sequel.string_agg(:c, ' - ')) # custom separator
57
+ ds.get(Sequel.string_agg(:c).order(:bar)) # force order
58
+ ds.get(Sequel.string_agg(:c).distinct) # remove duplicates
59
+
60
+ * A connection_expiration extension has been added, for automatically
61
+ removing connections from the connection pool after they have been
62
+ open for a given amount of time (4 hours by default).
63
+
64
+ * Support for <, <=, >, and >= operator validations when using integer
65
+ and string arguments has been added to the constraint_validations
66
+ extension and plugin.
67
+
68
+ * Sequel::SQL::Function#order has been added to support ordered
69
+ aggregate functions:
70
+
71
+ Sequel.function(:foo, :bar).order(:baz)
72
+ # foo(bar ORDER BY baz)
73
+
74
+ = Other Improvements
75
+
76
+ * The validates_operator validation in validation_helpers now
77
+ considers nil values as invalid unless :allow_nil or a similar
78
+ option is used. Previously, using validates_operator with a nil
79
+ value would probably raise a NoMethodError. This makes
80
+ validates_operator more similar to other validations.
81
+
82
+ * The threaded connection pools no longer hold the pool mutex when
83
+ disconnecting connections, which is useful if the driver blocks
84
+ when disconnecting connections.
85
+
86
+ * The connection_validator extension no longer holds a reference
87
+ to connections that have been disconnected.
88
+
89
+ * The connection_validator extension no longer overwrites the
90
+ connection_validation_timeout if loaded a second time.
91
+
92
+ * Sequel now closes cursors as soon as it is done using them in the
93
+ oracle adapter, instead of waiting for GC to clean them up.
94
+
95
+ * Sequel now handles disconnect errors that occur when literalizing
96
+ strings in the mysql2 and postgres adapters.
97
+
98
+ = Backwards Compatibility
99
+
100
+ * Using the Bignum class as a generic type is now deprecated. As
101
+ announced in the 4.35.0 release notes, ruby 2.4 is unifying the
102
+ Fixnum and Bignum classes into Integer, which results in the
103
+ behavior of the Bignum class changing. 4.35.0 added support for
104
+ using the :Bignum symbol as a generic 64-bit integer type, and
105
+ Sequel users now need to switch to that to avoid the deprecation
106
+ warning.
107
+
108
+ Sequel 4.41.0 (to be released in December), will drop support
109
+ for using the Bignum class as a generic type. This is being done
110
+ before the release of ruby 2.4 to hopefully make it unlikely that
111
+ users will be subject to a behavior changes when upgrading ruby
112
+ versions.
113
+
114
+ Related to this change, external adapters need to switch from
115
+ overriding Database#type_literal_generic_bignum to
116
+ Database#type_literal_generic_bignum_symbol.
@@ -147,7 +147,7 @@ module Sequel
147
147
 
148
148
  # Use BIGINT IDENTITY for identity columns that use bigint, fixes
149
149
  # the case where primary_key :column, :type=>:Bignum is used.
150
- def type_literal_generic_bignum(column)
150
+ def type_literal_generic_bignum_symbol(column)
151
151
  column[:identity] ? 'BIGINT IDENTITY' : super
152
152
  end
153
153
  end
@@ -199,7 +199,17 @@ module Sequel
199
199
 
200
200
  # Handle correct quoting of strings using ::Mysql2::Client#escape.
201
201
  def literal_string_append(sql, v)
202
- sql << APOS << db.synchronize(@opts[:server]){|c| c.escape(v)} << APOS
202
+ s = begin
203
+ db.synchronize(@opts[:server]) do |c|
204
+ begin
205
+ c.escape(v)
206
+ rescue ::Mysql2::Error => e
207
+ db.send(:raise_error, e)
208
+ end
209
+ end
210
+ end
211
+
212
+ sql << APOS << s << APOS
203
213
  end
204
214
  end
205
215
  end
@@ -86,11 +86,7 @@ module Sequel
86
86
  r = log_connection_yield(sql, conn){conn.exec(sql)}
87
87
  end
88
88
  if block_given?
89
- begin
90
- yield(r)
91
- ensure
92
- r.close
93
- end
89
+ yield(r)
94
90
  elsif type == :insert
95
91
  last_insert_id(conn, opts)
96
92
  else
@@ -99,6 +95,8 @@ module Sequel
99
95
  rescue OCIException, RuntimeError => e
100
96
  # ruby-oci8 is naughty and raises strings in some places
101
97
  raise_error(e)
98
+ ensure
99
+ r.close if r.is_a?(::OCI8::Cursor)
102
100
  end
103
101
  end
104
102
  end
@@ -841,12 +841,12 @@ module Sequel
841
841
 
842
842
  # Use the driver's escape_bytea
843
843
  def literal_blob_append(sql, v)
844
- sql << APOS << db.synchronize(@opts[:server]){|c| c.escape_bytea(v)} << APOS
844
+ sql << APOS << db.synchronize(@opts[:server]){|c| c.check_disconnect_errors{c.escape_bytea(v)}} << APOS
845
845
  end
846
846
 
847
847
  # Use the driver's escape_string
848
848
  def literal_string_append(sql, v)
849
- sql << APOS << db.synchronize(@opts[:server]){|c| c.escape_string(v)} << APOS
849
+ sql << APOS << db.synchronize(@opts[:server]){|c| c.check_disconnect_errors{c.escape_string(v)}} << APOS
850
850
  end
851
851
 
852
852
  # For each row in the result set, yield a hash with column name symbol
@@ -69,7 +69,7 @@ module Sequel
69
69
 
70
70
  # Access doesn't have a 64-bit integer type, so use integer and hope
71
71
  # the user isn't using more than 32 bits.
72
- def type_literal_generic_bignum(column)
72
+ def type_literal_generic_bignum_symbol(column)
73
73
  :integer
74
74
  end
75
75
 
@@ -241,7 +241,7 @@ module Sequel
241
241
  # Oracle's integer/:number type handles larger values than
242
242
  # most other databases's bigint types, so it should be
243
243
  # safe to use for Bignum.
244
- def type_literal_generic_bignum(column)
244
+ def type_literal_generic_bignum_symbol(column)
245
245
  :integer
246
246
  end
247
247
 
@@ -1142,7 +1142,7 @@ module Sequel
1142
1142
  end
1143
1143
 
1144
1144
  # Handle bigserial type if :serial option is present
1145
- def type_literal_generic_bignum(column)
1145
+ def type_literal_generic_bignum_symbol(column)
1146
1146
  column[:serial] ? :bigserial : super
1147
1147
  end
1148
1148
 
@@ -487,7 +487,7 @@ module Sequel
487
487
  # SQLite only supports AUTOINCREMENT on integer columns, not
488
488
  # bigint columns, so use integer instead of bigint for those
489
489
  # columns.
490
- def type_literal_generic_bignum(column)
490
+ def type_literal_generic_bignum_symbol(column)
491
491
  column[:auto_increment] ? :integer : super
492
492
  end
493
493
  end
@@ -97,6 +97,11 @@ class Sequel::ConnectionPool
97
97
  end
98
98
 
99
99
  private
100
+
101
+ # Remove the connection from the pool.
102
+ def disconnect_connection(conn)
103
+ db.disconnect_connection(conn)
104
+ end
100
105
 
101
106
  # Return a new connection by calling the connection proc with the given server name,
102
107
  # and checking for connection errors.
@@ -92,7 +92,7 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
92
92
  # Disconnect from the given server, if connected.
93
93
  def disconnect_server(server)
94
94
  if conn = @conns.delete(server)
95
- db.disconnect_connection(conn)
95
+ disconnect_connection(conn)
96
96
  end
97
97
  end
98
98
 
@@ -96,9 +96,9 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
96
96
  # :server :: Should be a symbol specifing the server to disconnect from,
97
97
  # or an array of symbols to specify multiple servers.
98
98
  def disconnect(opts=OPTS)
99
- sync do
100
- (opts[:server] ? Array(opts[:server]) : @servers.keys).each do |s|
101
- disconnect_server(s)
99
+ (opts[:server] ? Array(opts[:server]) : sync{@servers.keys}).each do |s|
100
+ if conns = sync{disconnect_server_connections(s)}
101
+ disconnect_connections(conns)
102
102
  end
103
103
  end
104
104
  end
@@ -139,11 +139,12 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
139
139
  # except that after it is used, future requests for the server will use the
140
140
  # :default server instead.
141
141
  def remove_servers(servers)
142
+ conns = nil
142
143
  sync do
143
144
  raise(Sequel::Error, "cannot remove default server") if servers.include?(:default)
144
145
  servers.each do |server|
145
146
  if @servers.include?(server)
146
- disconnect_server(server)
147
+ conns = disconnect_server_connections(server)
147
148
  @waiters.delete(server) if USE_WAITER
148
149
  @available_connections.delete(server)
149
150
  @allocated.delete(server)
@@ -151,6 +152,10 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
151
152
  end
152
153
  end
153
154
  end
155
+
156
+ if conns
157
+ disconnect_connections(conns)
158
+ end
154
159
  end
155
160
 
156
161
  # Return an array of symbols for servers in the connection pool.
@@ -243,16 +248,26 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
243
248
  conn
244
249
  end
245
250
 
246
- # Disconnect from the given server. Disconnects available connections
251
+ # Clear the array of available connections for the server, returning an array
252
+ # of previous available connections that should be disconnected (or nil if none should be).
253
+ # Mark any allocated connections to be removed when they are checked back in. The calling
254
+ # code should already have the mutex before calling this.
255
+ def disconnect_server_connections(server)
256
+ @connections_to_remove.concat(allocated(server).values)
257
+
258
+ if dis_conns = available_connections(server)
259
+ conns = dis_conns.dup
260
+ dis_conns.clear
261
+ end
262
+ conns
263
+ end
264
+
265
+ # Disconnect all given connections.
247
266
  # immediately, and schedules currently allocated connections for disconnection
248
- # as soon as they are returned to the pool. The calling code should already
267
+ # as soon as they are returned to the pool. The calling code should not
249
268
  # have the mutex before calling this.
250
- def disconnect_server(server)
251
- if conns = available_connections(server)
252
- conns.each{|conn| db.disconnect_connection(conn)}
253
- conns.clear
254
- end
255
- @connections_to_remove.concat(allocated(server).values)
269
+ def disconnect_connections(conns)
270
+ conns.each{|conn| disconnect_connection(conn)}
256
271
  end
257
272
 
258
273
  # Creates a new connection to the given server if the size of the pool for
@@ -318,7 +333,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
318
333
  conn = allocated(server).delete(thread)
319
334
 
320
335
  if @connection_handling == :disconnect
321
- db.disconnect_connection(conn)
336
+ disconnect_connection(conn)
322
337
  else
323
338
  checkin_connection(server, conn)
324
339
  end
@@ -330,7 +345,7 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
330
345
  def remove(thread, conn, server)
331
346
  @connections_to_remove.delete(conn)
332
347
  allocated(server).delete(thread) if @servers.include?(server)
333
- db.disconnect_connection(conn)
348
+ disconnect_connection(conn)
334
349
  end
335
350
 
336
351
  CONNECTION_POOL_MAP[[false, true]] = self