sequel 4.16.0 → 4.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +22 -0
- data/README.rdoc +6 -1
- data/doc/active_record.rdoc +1 -1
- data/doc/model_hooks.rdoc +1 -1
- data/doc/querying.rdoc +1 -1
- data/doc/release_notes/4.16.0.txt +1 -1
- data/doc/release_notes/4.17.0.txt +38 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +13 -0
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +1 -1
- data/lib/sequel/connection_pool.rb +5 -0
- data/lib/sequel/connection_pool/sharded_single.rb +10 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +6 -1
- data/lib/sequel/connection_pool/single.rb +19 -7
- data/lib/sequel/connection_pool/threaded.rb +15 -8
- data/lib/sequel/database/misc.rb +16 -7
- data/lib/sequel/dataset/query.rb +12 -1
- data/lib/sequel/model/base.rb +3 -2
- data/lib/sequel/plugins/sharding.rb +2 -2
- data/lib/sequel/plugins/update_or_create.rb +5 -3
- data/lib/sequel/version.rb +1 -1
- data/spec/core/connection_pool_spec.rb +33 -0
- data/spec/core/database_spec.rb +11 -0
- data/spec/core/dataset_spec.rb +1 -1
- data/spec/core/expression_filters_spec.rb +2 -2
- data/spec/extensions/dataset_associations_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +2 -2
- data/spec/extensions/update_or_create_spec.rb +6 -0
- data/spec/integration/prepared_statement_test.rb +7 -0
- data/spec/model/record_spec.rb +6 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d6fa8ec8783c8834b984323d9e1c73bef006df5
|
4
|
+
data.tar.gz: 40e551bc46ec90be6a411ca2eec0e4114394b03d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06d6af6daccc3ae11f55e17d6b39472509c3ddd90af821e0e6e353dfab49b6b30ea4c213b4596f46f048a6ff3807bcfc9257a13d08d8ccdc9a52d18478e59e6a
|
7
|
+
data.tar.gz: 6c31bed38421bb9acf75235b01229fe777baeb311fef31554c4b6070454147d37b4a249650e4c6c788602d5550c0db373546af9066a398aa9d01b2882568b810
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
=== 4.17.0 (2014-12-01)
|
2
|
+
|
3
|
+
* Fix handling of Sequel::SQL::Blob instances in bound variables in the postgres adapter (jeremyevans) (#917)
|
4
|
+
|
5
|
+
* Add :preconnect Database option for immediately creating the maximum number of connections (jeremyevans)
|
6
|
+
|
7
|
+
* Support DB.pool.max_size for the single connection pools (jeremyevans)
|
8
|
+
|
9
|
+
* Work around regression in jdbc-sqlite3 3.8.7 where empty blobs are returned as nil (jeremyevans)
|
10
|
+
|
11
|
+
* Work around regression in jdbc-sqlite3 3.8.7 when using JDBC getDate method for date parsing (jeremyevans)
|
12
|
+
|
13
|
+
* Make Model#update_or_create return object if existing object exists but updates are not necessary (contentfree) (#916)
|
14
|
+
|
15
|
+
* Add Dataset#server? for conditionally setting a default server to use if no default is present (jeremyevans)
|
16
|
+
|
17
|
+
* Add Database#sharded? for determining if database uses sharding (jeremyevans)
|
18
|
+
|
19
|
+
* Fix server used by Dataset#insert_select on PostgreSQL (jeremyevans)
|
20
|
+
|
21
|
+
* Fix server used for deleting model instances when using sharding (jeremyevans)
|
22
|
+
|
1
23
|
=== 4.16.0 (2014-11-01)
|
2
24
|
|
3
25
|
* Make Database#create_table? and #create_join_table? not use IF NOT EXISTS if indexes are being added (jeremyevans) (#904)
|
data/README.rdoc
CHANGED
@@ -20,10 +20,15 @@ toolkit for Ruby.
|
|
20
20
|
|
21
21
|
* {Website}[http://sequel.jeremyevans.net]
|
22
22
|
* {Source code}[http://github.com/jeremyevans/sequel]
|
23
|
-
* {Bug tracking}[http://github.com/jeremyevans/sequel/issues]
|
24
23
|
* {Google group}[http://groups.google.com/group/sequel-talk]
|
24
|
+
* {IRC}[irc://irc.freenode.net/sequel]
|
25
|
+
* {Bug tracking}[http://github.com/jeremyevans/sequel/issues]
|
25
26
|
* {RDoc}[http://sequel.jeremyevans.net/rdoc]
|
26
27
|
|
28
|
+
If you have questions about how to use Sequel, please ask on the
|
29
|
+
Google Group or IRC. Only use the the bug tracker to report
|
30
|
+
bugs in Sequel, not to ask for help on using Sequel.
|
31
|
+
|
27
32
|
To check out the source code:
|
28
33
|
|
29
34
|
git clone git://github.com/jeremyevans/sequel.git
|
data/doc/active_record.rdoc
CHANGED
@@ -756,7 +756,7 @@ ActiveRecord Method :: Notes, Workarounds
|
|
756
756
|
+silence+ :: No equivalent. Because the logger is handled at the <tt>Sequel::Database</tt> level, there is no thread-safe way to turn it off for specific blocks.
|
757
757
|
+scopes+ :: No equivalent
|
758
758
|
+sti_name+ :: No equivalent.
|
759
|
-
+update_counters+ :: <tt>Album.where(:id=>:id).update(:counter_name
|
759
|
+
+update_counters+ :: <tt>Album.where(:id=>:id).update(:counter_name=>Sequel.+(:counter_name, 1), :other_counter=>Sequel.-(:other_counter, 1))</tt>
|
760
760
|
+uncached+ :: No equivalent
|
761
761
|
|
762
762
|
=== Instance Methods with Significantly Different Behavior
|
data/doc/model_hooks.rdoc
CHANGED
@@ -96,7 +96,7 @@ Sequel does not provide a simple way to turn off the running of save/create/upda
|
|
96
96
|
|
97
97
|
However, you should note that there are plenty of ways to modify the database without saving a model object. One example is by using plain datasets, or one of the model's dataset methods:
|
98
98
|
|
99
|
-
Album.where(:name=>'RF').update(:copies_sold
|
99
|
+
Album.where(:name=>'RF').update(:copies_sold=>Sequel.+(:copies_sold, 1))
|
100
100
|
# UPDATE albums SET copies_sold = copies_sold + 1 WHERE name = 'RF'
|
101
101
|
|
102
102
|
In this case, the +update+ method is called on the dataset returned by <tt>Album.where</tt>. Even if there is only a single object with the name RF, this will not call any hooks. If you want model hooks to be called, you need to make sure to operate on a model object:
|
data/doc/querying.rdoc
CHANGED
@@ -292,7 +292,7 @@ in another place. This is what is meant by a functional style API.
|
|
292
292
|
Let's say we only want to select the id and name columns, and that
|
293
293
|
we want to order by name:
|
294
294
|
|
295
|
-
ds3 =
|
295
|
+
ds3 = ds2.order(:name).select(:id, :name)
|
296
296
|
# SELECT id, name FROM artists WHERE name LIKE 'A%' ESCAPE '\' ORDER BY name
|
297
297
|
|
298
298
|
Note how you don't need to assign the returned value of order to a variable,
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
* Dataset#distinct now accepts a virtual row block.
|
7
7
|
|
8
|
-
* Database#
|
8
|
+
* Database#drop_table with :foreign=>true option now drops foreign
|
9
9
|
tables on PostgreSQL. Database#create_table with :foreign option
|
10
10
|
is now reversible on PostgreSQL.
|
11
11
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A :preconnect Database option has been added, for automatically
|
4
|
+
creating the maximum number of connections to the database on
|
5
|
+
instantiation. This is useful when there is high latency for
|
6
|
+
initial connection setup, where Sequel's usual approach of
|
7
|
+
connecting as needed can cause pauses at runtime.
|
8
|
+
|
9
|
+
* Database#sharded? has been added for checking whether the Database
|
10
|
+
object uses multiple servers.
|
11
|
+
|
12
|
+
* Dataset#server? has been added, for returning a cloned dataset
|
13
|
+
associated with the given server/shard if the dataset does not
|
14
|
+
already have a server set. This returns the receiver if the
|
15
|
+
server has already been set or the Database is not sharded.
|
16
|
+
|
17
|
+
= Other Improvements
|
18
|
+
|
19
|
+
* Sequel now uses the correct shard when deleting model instances.
|
20
|
+
Previously, the correct shard was only used in the unoptimized
|
21
|
+
case, not in the optimized case.
|
22
|
+
|
23
|
+
* Sequel now uses the correct shard when using Dataset#insert_select
|
24
|
+
on PostgreSQL. This was first broken in the 4.13.0 release.
|
25
|
+
|
26
|
+
* Sequel now correctly handles Sequel::SQL::Blob instances used in
|
27
|
+
bound variables in the postgres adapter. Previously this resulted
|
28
|
+
in duplicate apostrophes being used.
|
29
|
+
|
30
|
+
* When using the jdbc/sqlite3 adapter with jdbc-sqlite3 3.8.7, Sequel
|
31
|
+
now handles date objects and empty blobs correctly, working around
|
32
|
+
bugs in the driver.
|
33
|
+
|
34
|
+
= Backwards Compatibility
|
35
|
+
|
36
|
+
* In the update_or_create plugin, Model.update_or_create now always
|
37
|
+
returns the object. Previously it would not return the object if
|
38
|
+
the object already existed but no updates were necessary.
|
@@ -71,10 +71,23 @@ module Sequel
|
|
71
71
|
end
|
72
72
|
|
73
73
|
# Use getLong instead of getInt for converting integers on SQLite, since SQLite does not enforce a limit of 2**32.
|
74
|
+
# Work around regressions in jdbc-sqlite 3.8.7 for date and blob types.
|
74
75
|
def setup_type_convertor_map
|
75
76
|
super
|
76
77
|
@type_convertor_map[Java::JavaSQL::Types::INTEGER] = @type_convertor_map[Java::JavaSQL::Types::BIGINT]
|
77
78
|
@basic_type_convertor_map[Java::JavaSQL::Types::INTEGER] = @basic_type_convertor_map[Java::JavaSQL::Types::BIGINT]
|
79
|
+
@type_convertor_map[Java::JavaSQL::Types::DATE] = lambda do |r, i|
|
80
|
+
if v = r.getString(i)
|
81
|
+
Sequel.string_to_date(v)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
@type_convertor_map[Java::JavaSQL::Types::BLOB] = lambda do |r, i|
|
85
|
+
if v = r.getBytes(i)
|
86
|
+
Sequel::SQL::Blob.new(String.from_java_bytes(v))
|
87
|
+
elsif !r.wasNull
|
88
|
+
Sequel::SQL::Blob.new('')
|
89
|
+
end
|
90
|
+
end
|
78
91
|
end
|
79
92
|
end
|
80
93
|
end
|
@@ -1329,7 +1329,7 @@ module Sequel
|
|
1329
1329
|
# inserting a query if disable_insert_returning is used.
|
1330
1330
|
def insert_select(*values)
|
1331
1331
|
return unless supports_insert_select?
|
1332
|
-
with_sql_first(insert_select_sql(*values))
|
1332
|
+
server?(:default).with_sql_first(insert_select_sql(*values))
|
1333
1333
|
end
|
1334
1334
|
|
1335
1335
|
# The SQL to use for an insert_select, adds a RETURNING clause to the insert
|
@@ -13,6 +13,8 @@
|
|
13
13
|
# connection pool recognizes.
|
14
14
|
# size :: an integer representing the total number of connections in the pool,
|
15
15
|
# or for the given shard/server if sharding is supported.
|
16
|
+
# max_size :: an integer representing the maximum size of the connection pool,
|
17
|
+
# or the maximum size per shard/server if sharding is supported.
|
16
18
|
#
|
17
19
|
# For sharded connection pools, the sharded API adds the following methods:
|
18
20
|
#
|
@@ -72,6 +74,9 @@ class Sequel::ConnectionPool
|
|
72
74
|
# :after_connect :: A callable object called after each new connection is made, with the
|
73
75
|
# connection object (and server argument if the callable accepts 2 arguments),
|
74
76
|
# useful for customizations that you want to apply to all connections.
|
77
|
+
# :preconnect :: Automatically create the maximum number of connections, so that they don't
|
78
|
+
# need to be created as needed. This is useful when connecting takes a long time
|
79
|
+
# and you want to avoid possible latency during runtime.
|
75
80
|
def initialize(db, opts=OPTS)
|
76
81
|
@db = db
|
77
82
|
@after_connect = opts[:after_connect]
|
@@ -54,6 +54,11 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
# The ShardedSingleConnectionPool always has a maximum size of 1.
|
58
|
+
def max_size
|
59
|
+
1
|
60
|
+
end
|
61
|
+
|
57
62
|
# Remove servers from the connection pool. Primarily used in conjunction with master/slave
|
58
63
|
# or shard configurations. Similar to disconnecting from all given servers,
|
59
64
|
# except that after it is used, future requests for the server will use the
|
@@ -94,5 +99,10 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
94
99
|
@servers[server]
|
95
100
|
end
|
96
101
|
|
102
|
+
# Make sure there is a valid connection for each server.
|
103
|
+
def preconnect
|
104
|
+
servers.each{|s| hold(s){}}
|
105
|
+
end
|
106
|
+
|
97
107
|
CONNECTION_POOL_MAP[[true, true]] = self
|
98
108
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'sequel/connection_pool/threaded'
|
2
2
|
|
3
3
|
# The slowest and most advanced connection, dealing with both multi-threaded
|
4
4
|
# access and configurations with multiple shards/servers.
|
@@ -235,6 +235,11 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
|
|
235
235
|
sync{@servers[server]}
|
236
236
|
end
|
237
237
|
|
238
|
+
# Create the maximum number of connections to each server immediately.
|
239
|
+
def preconnect
|
240
|
+
servers.each{|s| (max_size - size(s)).times{checkin_connection(s, make_new(s))}}
|
241
|
+
end
|
242
|
+
|
238
243
|
# Releases the connection assigned to the supplied thread and server. If the
|
239
244
|
# server or connection given is scheduled for disconnection, remove the
|
240
245
|
# connection instead of releasing it back to the pool.
|
@@ -2,17 +2,11 @@
|
|
2
2
|
# It is just a wrapper around a single connection that uses the connection pool
|
3
3
|
# API.
|
4
4
|
class Sequel::SingleConnectionPool < Sequel::ConnectionPool
|
5
|
-
# The SingleConnectionPool always has a size of 1 if connected
|
6
|
-
# and 0 if not.
|
7
|
-
def size
|
8
|
-
@conn ? 1 : 0
|
9
|
-
end
|
10
|
-
|
11
5
|
# Yield the connection if one has been made.
|
12
6
|
def all_connections
|
13
7
|
yield @conn if @conn
|
14
8
|
end
|
15
|
-
|
9
|
+
|
16
10
|
# Disconnect the connection from the database.
|
17
11
|
def disconnect(opts=nil)
|
18
12
|
return unless @conn
|
@@ -30,9 +24,27 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
|
|
30
24
|
end
|
31
25
|
end
|
32
26
|
|
27
|
+
# The SingleConnectionPool always has a maximum size of 1.
|
28
|
+
def max_size
|
29
|
+
1
|
30
|
+
end
|
31
|
+
|
33
32
|
def pool_type
|
34
33
|
:single
|
35
34
|
end
|
36
35
|
|
36
|
+
# The SingleConnectionPool always has a size of 1 if connected
|
37
|
+
# and 0 if not.
|
38
|
+
def size
|
39
|
+
@conn ? 1 : 0
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Make sure there is a valid connection.
|
45
|
+
def preconnect
|
46
|
+
hold{}
|
47
|
+
end
|
48
|
+
|
37
49
|
CONNECTION_POOL_MAP[[true, false]] = self
|
38
50
|
end
|
@@ -34,12 +34,6 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
34
34
|
@sleep_time = Float(opts[:pool_sleep_time] || 0.001)
|
35
35
|
end
|
36
36
|
|
37
|
-
# The total number of connections opened, either available or allocated.
|
38
|
-
# This may not be completely accurate as it isn't protected by the mutex.
|
39
|
-
def size
|
40
|
-
@allocated.length + @available_connections.length
|
41
|
-
end
|
42
|
-
|
43
37
|
# Yield all of the available connections, and the one currently allocated to
|
44
38
|
# this thread. This will not yield connections currently allocated to other
|
45
39
|
# threads, as it is not safe to operate on them. This holds the mutex while
|
@@ -117,6 +111,12 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
117
111
|
:threaded
|
118
112
|
end
|
119
113
|
|
114
|
+
# The total number of connections opened, either available or allocated.
|
115
|
+
# This may not be completely accurate as it isn't protected by the mutex.
|
116
|
+
def size
|
117
|
+
@allocated.length + @available_connections.length
|
118
|
+
end
|
119
|
+
|
120
120
|
private
|
121
121
|
|
122
122
|
# Assigns a connection to the supplied thread, if one
|
@@ -144,8 +144,10 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
144
144
|
conn
|
145
145
|
end
|
146
146
|
|
147
|
-
|
148
|
-
|
147
|
+
unless method_defined?(:default_make_new)
|
148
|
+
# Alias the default make_new method, so subclasses can call it directly.
|
149
|
+
alias default_make_new make_new
|
150
|
+
end
|
149
151
|
|
150
152
|
# Creates a new connection to the given server if the size of the pool for
|
151
153
|
# the server is less than the maximum size of the pool. The calling code
|
@@ -176,6 +178,11 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
|
|
176
178
|
sync{@allocated[thread]}
|
177
179
|
end
|
178
180
|
|
181
|
+
# Create the maximum number of connections immediately.
|
182
|
+
def preconnect
|
183
|
+
(max_size - size).times{checkin_connection(make_new(nil))}
|
184
|
+
end
|
185
|
+
|
179
186
|
# Releases the connection assigned to the supplied thread back to the pool.
|
180
187
|
# The calling code should already have the mutex before calling this.
|
181
188
|
def release(thread)
|
data/lib/sequel/database/misc.rb
CHANGED
@@ -100,13 +100,14 @@ module Sequel
|
|
100
100
|
#
|
101
101
|
# Accepts the following options:
|
102
102
|
# :default_string_column_size :: The default size of string columns, 255 by default.
|
103
|
-
# :identifier_input_method :: A string method symbol to call on identifiers going into the database
|
104
|
-
# :identifier_output_method :: A string method symbol to call on identifiers coming from the database
|
105
|
-
# :logger :: A specific logger to use
|
106
|
-
# :loggers :: An array of loggers to use
|
107
|
-
# :
|
108
|
-
# :
|
109
|
-
# :
|
103
|
+
# :identifier_input_method :: A string method symbol to call on identifiers going into the database.
|
104
|
+
# :identifier_output_method :: A string method symbol to call on identifiers coming from the database.
|
105
|
+
# :logger :: A specific logger to use.
|
106
|
+
# :loggers :: An array of loggers to use.
|
107
|
+
# :preconnect :: Whether to automatically connect to the maximum number of servers.
|
108
|
+
# :quote_identifiers :: Whether to quote identifiers.
|
109
|
+
# :servers :: A hash specifying a server/shard specific options, keyed by shard symbol .
|
110
|
+
# :single_threaded :: Whether to use a single-threaded connection pool.
|
110
111
|
# :sql_log_level :: Method to use to log SQL to a logger, :info by default.
|
111
112
|
#
|
112
113
|
# All options given are also passed to the connection pool.
|
@@ -117,6 +118,7 @@ module Sequel
|
|
117
118
|
self.log_warn_duration = @opts[:log_warn_duration]
|
118
119
|
block ||= proc{|server| connect(server)}
|
119
120
|
@opts[:servers] = {} if @opts[:servers].is_a?(String)
|
121
|
+
@sharded = !!@opts[:servers]
|
120
122
|
@opts[:adapter_class] = self.class
|
121
123
|
|
122
124
|
@opts[:single_threaded] = @single_threaded = typecast_value_boolean(@opts.fetch(:single_threaded, Database.single_threaded))
|
@@ -143,6 +145,7 @@ module Sequel
|
|
143
145
|
Sequel.synchronize{::Sequel::DATABASES.push(self)}
|
144
146
|
end
|
145
147
|
Sequel::Database.run_after_initialize(self)
|
148
|
+
@pool.send(:preconnect) if typecast_value_boolean(@opts[:preconnect]) && @pool.respond_to?(:preconnect, true)
|
146
149
|
end
|
147
150
|
|
148
151
|
# If a transaction is not currently in process, yield to the block immediately.
|
@@ -276,6 +279,12 @@ module Sequel
|
|
276
279
|
Sequel.synchronize{prepared_statements[name] = ps}
|
277
280
|
end
|
278
281
|
|
282
|
+
# Whether this database instance uses multiple servers, either for sharding
|
283
|
+
# or for master/slave.
|
284
|
+
def sharded?
|
285
|
+
@sharded
|
286
|
+
end
|
287
|
+
|
279
288
|
# The timezone to use for this database, defaulting to <tt>Sequel.database_timezone</tt>.
|
280
289
|
def timezone
|
281
290
|
@timezone || Sequel.database_timezone
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -794,6 +794,17 @@ module Sequel
|
|
794
794
|
clone(:server=>servr)
|
795
795
|
end
|
796
796
|
|
797
|
+
# If the database uses sharding and the current dataset has not had a
|
798
|
+
# server set, return a cloned dataset that uses the given server.
|
799
|
+
# Otherwise, return the receiver directly instead of returning a clone.
|
800
|
+
def server?(server)
|
801
|
+
if db.sharded? && !opts[:server]
|
802
|
+
server(server)
|
803
|
+
else
|
804
|
+
self
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
797
808
|
# Unbind bound variables from this dataset's filter and return an array of two
|
798
809
|
# objects. The first object is a modified dataset where the filter has been
|
799
810
|
# replaced with one that uses bound variable placeholders. The second object
|
@@ -1119,7 +1130,7 @@ module Sequel
|
|
1119
1130
|
# Return self if the dataset already has a server, or a cloned dataset with the
|
1120
1131
|
# default server otherwise.
|
1121
1132
|
def default_server
|
1122
|
-
|
1133
|
+
server?(:default)
|
1123
1134
|
end
|
1124
1135
|
|
1125
1136
|
# Treat the +block+ as a virtual_row block if not +nil+ and
|
data/lib/sequel/model/base.rb
CHANGED
@@ -1752,7 +1752,8 @@ module Sequel
|
|
1752
1752
|
def _delete_without_checking
|
1753
1753
|
if sql = (m = model).fast_instance_delete_sql
|
1754
1754
|
sql = sql.dup
|
1755
|
-
|
1755
|
+
ds = use_server(m.dataset)
|
1756
|
+
ds.literal_append(sql, pk)
|
1756
1757
|
ds.with_sql_delete(sql)
|
1757
1758
|
else
|
1758
1759
|
_delete_dataset.delete
|
@@ -1903,7 +1904,7 @@ module Sequel
|
|
1903
1904
|
# default values of all columns. Separated from _save so it
|
1904
1905
|
# can be overridden to avoid the refresh.
|
1905
1906
|
def _save_refresh
|
1906
|
-
_save_set_values(_refresh_get(this.
|
1907
|
+
_save_set_values(_refresh_get(this.server?(:default)) || raise(Error, "Record not found"))
|
1907
1908
|
changed_columns.clear
|
1908
1909
|
end
|
1909
1910
|
|
@@ -30,7 +30,7 @@ module Sequel
|
|
30
30
|
eb = eo[:eager_block]
|
31
31
|
set_server = proc do |ds|
|
32
32
|
ds = eb.call(ds) if eb
|
33
|
-
ds = ds.server(server)
|
33
|
+
ds = ds.server?(server)
|
34
34
|
ds
|
35
35
|
end
|
36
36
|
eo = eo.merge(:eager_block=>set_server)
|
@@ -53,7 +53,7 @@ module Sequel
|
|
53
53
|
def eager_graph_dataset(opts, eager_options)
|
54
54
|
ds = super
|
55
55
|
if s = eager_options[:self].opts[:server]
|
56
|
-
ds = ds.server(s)
|
56
|
+
ds = ds.server?(s)
|
57
57
|
end
|
58
58
|
ds
|
59
59
|
end
|
@@ -41,14 +41,16 @@ module Sequel
|
|
41
41
|
# create a new record with the columns specified by both +attrs+ and
|
42
42
|
# +set_attrs+, with the ones in +set_attrs+ taking priority. If
|
43
43
|
# a block is given, the object is yielded to the block before the
|
44
|
-
# object is saved.
|
44
|
+
# object is saved. Returns the new or updated object.
|
45
45
|
def update_or_create(attrs, set_attrs=nil, &block)
|
46
|
-
find_or_new(attrs, set_attrs, &block)
|
46
|
+
obj = find_or_new(attrs, set_attrs, &block)
|
47
|
+
obj.save_changes
|
48
|
+
obj
|
47
49
|
end
|
48
50
|
|
49
51
|
# Operates the same as +update_or_create+, but returns the objects
|
50
52
|
# without persisting changes (no UPDATE/INSERT queries).
|
51
|
-
def find_or_new(attrs, set_attrs=nil
|
53
|
+
def find_or_new(attrs, set_attrs=nil)
|
52
54
|
obj = find(attrs) || new(attrs)
|
53
55
|
obj.set(set_attrs) if set_attrs
|
54
56
|
yield obj if block_given?
|
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sequel
|
|
3
3
|
MAJOR = 4
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
5
5
|
# release, generally around once a month.
|
6
|
-
MINOR =
|
6
|
+
MINOR = 17
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
9
|
TINY = 0
|
@@ -488,6 +488,13 @@ describe "A connection pool with multiple servers" do
|
|
488
488
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call{|server| "#{server}#{ic[server] += 1}"}, CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}}))
|
489
489
|
end
|
490
490
|
|
491
|
+
specify "should support preconnect method that immediately creates the maximum number of connections" do
|
492
|
+
@pool.send(:preconnect)
|
493
|
+
i = 0
|
494
|
+
@pool.all_connections{|c1| i+=1}
|
495
|
+
i.should == @pool.max_size * 2
|
496
|
+
end
|
497
|
+
|
491
498
|
specify "#all_connections should return connections for all servers" do
|
492
499
|
@pool.hold{}
|
493
500
|
@pool.all_connections{|c1| c1.should == "default1"}
|
@@ -755,6 +762,13 @@ describe "A single threaded pool with multiple servers" do
|
|
755
762
|
@pool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){|c| c}, ST_CONNECTION_POOL_DEFAULTS.merge(:servers=>{:read_only=>{}}))
|
756
763
|
end
|
757
764
|
|
765
|
+
specify "should support preconnect method that immediately creates the maximum number of connections" do
|
766
|
+
@pool.send(:preconnect)
|
767
|
+
i = 0
|
768
|
+
@pool.all_connections{|c1| i+=1}
|
769
|
+
i.should == 2
|
770
|
+
end
|
771
|
+
|
758
772
|
specify "#all_connections should return connections for all servers" do
|
759
773
|
@pool.hold{}
|
760
774
|
@pool.all_connections{|c1| c1.should == :default}
|
@@ -879,6 +893,25 @@ shared_examples_for "All connection pools classes" do
|
|
879
893
|
p.hold{|c| p.all_connections{|c1| c.should == c1}}
|
880
894
|
end
|
881
895
|
|
896
|
+
specify "should have a size method that gives the current size of the pool" do
|
897
|
+
p = @class.new(mock_db.call{123}, {})
|
898
|
+
p.size.should == 0
|
899
|
+
p.hold{}
|
900
|
+
p.size.should == 1
|
901
|
+
end
|
902
|
+
|
903
|
+
specify "should have a max_size method that gives the maximum size of the pool" do
|
904
|
+
@class.new(mock_db.call{123}, {}).max_size.should >= 1
|
905
|
+
end
|
906
|
+
|
907
|
+
specify "should support preconnect method that immediately creates the maximum number of connections" do
|
908
|
+
p = @class.new(mock_db.call{123}, {})
|
909
|
+
p.send(:preconnect)
|
910
|
+
i = 0
|
911
|
+
p.all_connections{|c1| i+=1}
|
912
|
+
i.should == p.max_size
|
913
|
+
end
|
914
|
+
|
882
915
|
specify "should be able to modify after_connect proc after the pool is created" do
|
883
916
|
a = []
|
884
917
|
p = @class.new(mock_db.call{123}, {})
|
data/spec/core/database_spec.rb
CHANGED
@@ -23,6 +23,17 @@ describe "A new Database" do
|
|
23
23
|
Sequel::Database.new(1 => 2, :logger => [4], :loggers => [3]).loggers.should == [4,3]
|
24
24
|
end
|
25
25
|
|
26
|
+
specify "should support :preconnect option to preconnect to database" do
|
27
|
+
@db.pool.size.should == 0
|
28
|
+
c = Class.new(Sequel::Database) do
|
29
|
+
def connect(_)
|
30
|
+
:connect
|
31
|
+
end
|
32
|
+
end
|
33
|
+
db = c.new(1 => 2, :logger => 3, :preconnect=>true)
|
34
|
+
db.pool.size.should == db.pool.max_size
|
35
|
+
end
|
36
|
+
|
26
37
|
specify "should handle the default string column size" do
|
27
38
|
@db.default_string_column_size.should == 255
|
28
39
|
db = Sequel::Database.new(:default_string_column_size=>50)
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -3723,7 +3723,7 @@ describe "Sequel::Dataset#qualify" do
|
|
3723
3723
|
end
|
3724
3724
|
|
3725
3725
|
specify "should handle SQL::DelayedEvaluations that take dataset arguments" do
|
3726
|
-
ds = @ds.filter(Sequel.delay{|
|
3726
|
+
ds = @ds.filter(Sequel.delay{|x| x.first_source}).qualify
|
3727
3727
|
ds.sql.should == 'SELECT t.* FROM t WHERE t.t'
|
3728
3728
|
end
|
3729
3729
|
|
@@ -1117,7 +1117,7 @@ describe "Sequel.delay" do
|
|
1117
1117
|
end
|
1118
1118
|
|
1119
1119
|
specify "should call the block with the current dataset if it accepts one argument" do
|
1120
|
-
ds = Sequel.mock[:b].where(Sequel.delay{|
|
1120
|
+
ds = Sequel.mock[:b].where(Sequel.delay{|x| x.first_source})
|
1121
1121
|
ds.sql.should == "SELECT * FROM b WHERE b"
|
1122
1122
|
ds.from(:c).sql.should == "SELECT * FROM c WHERE c"
|
1123
1123
|
end
|
@@ -1132,7 +1132,7 @@ describe "Sequel.delay" do
|
|
1132
1132
|
end
|
1133
1133
|
|
1134
1134
|
specify "should have the condition specifier handling call block with the current dataset if it accepts one argument" do
|
1135
|
-
ds = Sequel.mock[:b].where(:a=>Sequel.delay{|
|
1135
|
+
ds = Sequel.mock[:b].where(:a=>Sequel.delay{|x| x.first_source})
|
1136
1136
|
ds.sql.should == "SELECT * FROM b WHERE (a = b)"
|
1137
1137
|
ds.from(:c).sql.should == "SELECT * FROM c WHERE (a = c)"
|
1138
1138
|
end
|
@@ -196,7 +196,7 @@ describe "Sequel::Plugins::DatasetAssociations" do
|
|
196
196
|
end
|
197
197
|
|
198
198
|
it "should deal correctly with :order option for one_through_many associations" do
|
199
|
-
@Artist.one_through_many :otag, :clone=>:otag, :order=>:
|
199
|
+
@Artist.one_through_many :otag, :clone=>:otag, :order=>:tags__name
|
200
200
|
@Artist.otags.sql.should == 'SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM artists INNER JOIN albums ON (albums.artist_id = artists.id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) INNER JOIN tags ON (tags.id = albums_tags.tag_id) WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND ((albums.artist_id, tags.id) IN (SELECT DISTINCT ON (albums.artist_id) albums.artist_id, tags.id FROM tags INNER JOIN albums_tags ON (albums_tags.tag_id = tags.id) INNER JOIN albums ON (albums.id = albums_tags.album_id) ORDER BY albums.artist_id, tags.name))))) ORDER BY tags.name'
|
201
201
|
end
|
202
202
|
|
@@ -367,7 +367,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
367
367
|
|
368
368
|
it "should eagerly load descendants to a given level" do
|
369
369
|
@c.plugin :rcte_tree, :key=>[:parent_id, :parent_id2]
|
370
|
-
@ds._fetch = [[{:id=>2, :id2=>3, :parent_id=>1, :
|
370
|
+
@ds._fetch = [[{:id=>2, :id2=>3, :parent_id=>1, :parent_id2=>2, :name=>'AA'}, {:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'}, {:id=>7, :id2=>8, :parent_id=>1, :parent_id2=>2, :name=>'D'}],
|
371
371
|
[{:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C', :x_root_x_0=>2, :x_root_x_1=>3, :x_level_x=>0}, {:id=>9, :id2=>10, :parent_id=>2, :parent_id2=>3, :name=>'E', :x_root_x_0=>2, :x_root_x_1=>3, :x_level_x=>0},
|
372
372
|
{:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7, :x_root_x_0=>6, :x_root_x_1=>7, :x_level_x=>0}, {:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7, :x_root_x_0=>2, :x_root_x_1=>3, :x_level_x=>1},
|
373
373
|
{:id=>4, :id2=>5, :name=>'?', :parent_id=>7, :parent_id2=>8, :x_root_x_0=>7, :x_root_x_1=>8, :x_level_x=>0}, {:id=>5, :id2=>6, :name=>'?', :parent_id=>4, :parent_id2=>5, :x_root_x_0=>7, :x_root_x_1=>8, :x_level_x=>1}]]
|
@@ -375,7 +375,7 @@ describe Sequel::Model, "rcte_tree with composite keys" do
|
|
375
375
|
sqls = @db.sqls
|
376
376
|
sqls.first.should == "SELECT * FROM nodes"
|
377
377
|
sqls.last.should =~ /WITH t AS \(SELECT parent_id AS x_root_x_0, parent_id2 AS x_root_x_1, nodes\.\*, CAST\(0 AS integer\) AS x_level_x FROM nodes WHERE \(\(parent_id, parent_id2\) IN \(\([267], [378]\), \([267], [378]\), \([267], [378]\)\)\) UNION ALL SELECT t\.x_root_x_0, t\.x_root_x_1, nodes\.\*, \(t\.x_level_x \+ 1\) AS x_level_x FROM nodes INNER JOIN t ON \(\(t\.id = nodes\.parent_id\) AND \(t\.id2 = nodes\.parent_id2\)\) WHERE \(t\.x_level_x < 1\)\) SELECT \* FROM t AS nodes/
|
378
|
-
os.should == [@c.load(:id=>2, :id2=>3, :parent_id=>1, :
|
378
|
+
os.should == [@c.load(:id=>2, :id2=>3, :parent_id=>1, :parent_id2=>2, :name=>'AA'), @c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>7, :id2=>8, :parent_id=>1, :parent_id2=>2, :name=>'D')]
|
379
379
|
os.map{|o| o.descendants}.should == [[@c.load(:id=>6, :id2=>7, :parent_id=>2, :parent_id2=>3, :name=>'C'), @c.load(:id=>9, :id2=>10, :parent_id=>2, :parent_id2=>3, :name=>'E'), @c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)],
|
380
380
|
[@c.load(:id=>3, :id2=>4, :name=>'00', :parent_id=>6, :parent_id2=>7)],
|
381
381
|
[@c.load(:id=>4, :id2=>5, :name=>'?', :parent_id=>7, :parent_id2=>8), @c.load(:id=>5, :id2=>6, :name=>'?', :parent_id=>4, :parent_id2=>5)]]
|
@@ -48,6 +48,12 @@ describe "Sequel::Plugins::UpdateOrCreate" do
|
|
48
48
|
sqls.shift.should == "SELECT * FROM test WHERE (id = 1) LIMIT 1"
|
49
49
|
end
|
50
50
|
|
51
|
+
it ".update_or_create should return an existing record even if no changes necessary" do
|
52
|
+
@db.fetch = [[{:id=>1, :a=>2, :b=>3}]]
|
53
|
+
@c.update_or_create(:a=>2){|t| t.b = 3}.should == @c.load(:id=>1, :a=>2, :b=>3)
|
54
|
+
@db.sqls.should == ["SELECT * FROM test WHERE (a = 2) LIMIT 1"]
|
55
|
+
end
|
56
|
+
|
51
57
|
it ".find_or_new should return an existing record" do
|
52
58
|
@db.fetch = [[{:id=>1, :a=>2, :b=>3}]]
|
53
59
|
@c.find_or_new(:a=>2){|t| t.b = 4}.should == @c.load(:id=>1, :a=>2, :b=>4)
|
@@ -327,6 +327,13 @@ describe "Bound Argument Types" do
|
|
327
327
|
@ds.get(:file).should == @vs[:file]
|
328
328
|
end
|
329
329
|
|
330
|
+
cspecify "should handle blob type with special characters", [:odbc], [:oracle] do
|
331
|
+
@ds.delete
|
332
|
+
blob = Sequel.blob("\"'[]`a0 ")
|
333
|
+
@ds.prepare(:insert, :ps_blob, {:file=>:$x}).call(:x=>blob)
|
334
|
+
@ds.get(:file).should == blob
|
335
|
+
end
|
336
|
+
|
330
337
|
cspecify "should handle blob type with nil values", [:oracle], [:tinytds], [:jdbc, proc{|db| defined?(Sequel::JDBC::SQLServer::DatabaseMethods) && db.is_a?(Sequel::JDBC::SQLServer::DatabaseMethods)}] do
|
331
338
|
@ds.delete
|
332
339
|
@ds.prepare(:insert, :ps_blob, {:file=>:$x}).call(:x=>nil)
|
data/spec/model/record_spec.rb
CHANGED
@@ -346,6 +346,12 @@ describe "Model#set_server" do
|
|
346
346
|
@db.sqls.should == ["DELETE FROM items WHERE (id = 13) -- s1"]
|
347
347
|
end
|
348
348
|
|
349
|
+
it "should set the server to use when deleting when using optimized delete" do
|
350
|
+
@c.set_primary_key :id
|
351
|
+
@c.load(:id=>13).set_server(:s1).delete
|
352
|
+
@db.sqls.should == ["DELETE FROM items WHERE id = 13 -- s1"]
|
353
|
+
end
|
354
|
+
|
349
355
|
it "should set the server to use for transactions when destroying" do
|
350
356
|
o = @c.load(:id=>13).set_server(:s1)
|
351
357
|
o.use_transactions = true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: The Database Toolkit for Ruby
|
14
14
|
email: code@jeremyevans.net
|
@@ -133,6 +133,7 @@ extra_rdoc_files:
|
|
133
133
|
- doc/release_notes/4.14.0.txt
|
134
134
|
- doc/release_notes/4.15.0.txt
|
135
135
|
- doc/release_notes/4.16.0.txt
|
136
|
+
- doc/release_notes/4.17.0.txt
|
136
137
|
files:
|
137
138
|
- CHANGELOG
|
138
139
|
- MIT-LICENSE
|
@@ -236,6 +237,7 @@ files:
|
|
236
237
|
- doc/release_notes/4.14.0.txt
|
237
238
|
- doc/release_notes/4.15.0.txt
|
238
239
|
- doc/release_notes/4.16.0.txt
|
240
|
+
- doc/release_notes/4.17.0.txt
|
239
241
|
- doc/release_notes/4.2.0.txt
|
240
242
|
- doc/release_notes/4.3.0.txt
|
241
243
|
- doc/release_notes/4.4.0.txt
|
@@ -734,7 +736,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
734
736
|
version: '0'
|
735
737
|
requirements: []
|
736
738
|
rubyforge_project:
|
737
|
-
rubygems_version: 2.
|
739
|
+
rubygems_version: 2.4.4
|
738
740
|
signing_key:
|
739
741
|
specification_version: 4
|
740
742
|
summary: The Database Toolkit for Ruby
|