sequel 3.7.0 → 3.8.0
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.
- data/CHANGELOG +50 -0
- data/doc/advanced_associations.rdoc +4 -3
- data/doc/release_notes/3.7.0.txt +2 -2
- data/doc/release_notes/3.8.0.txt +151 -0
- data/lib/sequel/adapters/jdbc.rb +10 -2
- data/lib/sequel/adapters/jdbc/h2.rb +14 -0
- data/lib/sequel/adapters/mysql.rb +36 -26
- data/lib/sequel/adapters/postgres.rb +27 -19
- data/lib/sequel/adapters/shared/mssql.rb +12 -4
- data/lib/sequel/adapters/shared/mysql.rb +16 -0
- data/lib/sequel/connection_pool.rb +178 -57
- data/lib/sequel/database.rb +60 -12
- data/lib/sequel/database/schema_generator.rb +1 -2
- data/lib/sequel/dataset.rb +10 -1
- data/lib/sequel/dataset/actions.rb +4 -8
- data/lib/sequel/dataset/convenience.rb +9 -2
- data/lib/sequel/dataset/query.rb +2 -5
- data/lib/sequel/dataset/sql.rb +0 -1
- data/lib/sequel/exceptions.rb +3 -3
- data/lib/sequel/metaprogramming.rb +4 -18
- data/lib/sequel/model/associations.rb +2 -2
- data/lib/sequel/model/base.rb +15 -18
- data/lib/sequel/model/default_inflections.rb +0 -1
- data/lib/sequel/model/plugins.rb +3 -2
- data/lib/sequel/plugins/boolean_readers.rb +3 -2
- data/lib/sequel/plugins/identity_map.rb +9 -0
- data/lib/sequel/plugins/validation_helpers.rb +8 -1
- data/lib/sequel/sql.rb +21 -11
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +7 -1
- data/spec/adapters/mysql_spec.rb +22 -0
- data/spec/core/connection_pool_spec.rb +211 -3
- data/spec/core/core_sql_spec.rb +7 -0
- data/spec/core/database_spec.rb +159 -7
- data/spec/core/dataset_spec.rb +33 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/extensions/boolean_readers_spec.rb +6 -0
- data/spec/extensions/identity_map_spec.rb +29 -1
- data/spec/extensions/inflector_spec.rb +0 -1
- data/spec/extensions/validation_helpers_spec.rb +23 -0
- data/spec/integration/type_test.rb +1 -1
- metadata +131 -129
data/CHANGELOG
CHANGED
@@ -1,3 +1,53 @@
|
|
1
|
+
=== 3.8.0 (2010-01-04)
|
2
|
+
|
3
|
+
* Catch cases in the postgres adapter where exceptions weren't converted or raised appropriately (jeremyevans)
|
4
|
+
|
5
|
+
* Don't double escape backslashes in string literals in the mssql shared adapter (john_firebaugh)
|
6
|
+
|
7
|
+
* Fix order of ORDER and HAVING clauses in the mssql shared adapter (mluu)
|
8
|
+
|
9
|
+
* Add validates_type to the validation_helpers plugin (mluu)
|
10
|
+
|
11
|
+
* Attempt to detect database disconnects in the JDBC adapter (john_firebaugh)
|
12
|
+
|
13
|
+
* Add Sequel::SQL::Expression#==, so arbtirary expressions can be compared by value (dlee)
|
14
|
+
|
15
|
+
* Respect the :size option for the generic File type on MySQL to create tinyblob, mediumblob, and longblob (ibc)
|
16
|
+
|
17
|
+
* Don't use the OUTPUT clause on SQL Server versions that don't support it (pre-2005) (jeremyevans) (#281)
|
18
|
+
|
19
|
+
* Raise DatabaseConnectionErrors in the single-threaded connection pool if unable to connect (jeremyevans)
|
20
|
+
|
21
|
+
* Fix handling of non-existent server in single-threaded connection pool (jeremyevans)
|
22
|
+
|
23
|
+
* Default to using mysqlplus driver in the native mysql adapter, fall back to mysql driver (ibc, jeremyevans)
|
24
|
+
|
25
|
+
* Handle 64-bit integers in JDBC prepared statements (paulfras)
|
26
|
+
|
27
|
+
* Improve blob support when using the H2 JDBC subadapter (nullstyle, jeremyevans, paulfras)
|
28
|
+
|
29
|
+
* Add Database#each_server, which yields a new Database object for each server in the connection pool which is connected to only that server (jeremyevans)
|
30
|
+
|
31
|
+
* Add Dataset#each_server, which yields a dataset for each server in the connection pool which is will execute on that server (jeremyevans)
|
32
|
+
|
33
|
+
* Remove meta_eval and metaclass private methods from Sequel::Metaprogramming (jeremyevans)
|
34
|
+
|
35
|
+
* Merge Dataset::FROM_SELF_KEEP_OPTS into Dataset::NON_SQL_OPTIONS (jeremyevans)
|
36
|
+
|
37
|
+
* Add Database#remove_servers for removing servers from the pool on the fly (jeremyevans)
|
38
|
+
|
39
|
+
* When disconnecting servers, if there are any connections to the server currently in use, schedule them to be disconnected (jeremyevans)
|
40
|
+
|
41
|
+
* Allow disconnecting specific server(s)/shard(s) in Database#disconnect via a :servers option (jeremyevans)
|
42
|
+
|
43
|
+
* Handle multiple statements in a single query in the native MySQL adapter in all cases, not just when selecting via Dataset#each (jeremyevans)
|
44
|
+
|
45
|
+
* In the boolean_readers plugin, don't raise an error if the model's columns can't be determined (jeremyevans)
|
46
|
+
|
47
|
+
* In the identity_map plugin, remove instances from the cache if they are deleted/destroyed (jeremyevans)
|
48
|
+
|
49
|
+
* Add Database#add_servers, for adding new servers/shards on the fly (chuckremes, jeremyevans)
|
50
|
+
|
1
51
|
=== 3.7.0 (2009-12-01)
|
2
52
|
|
3
53
|
* Add Dataset#sequence to the shared Oracle Adapter, for returning autogenerated primary key values on insert (jeremyevans) (#280)
|
@@ -476,8 +476,8 @@ Let's say you want to store a tree relationship in your database, it's pretty
|
|
476
476
|
simple:
|
477
477
|
|
478
478
|
class Node < Sequel::Model
|
479
|
-
many_to_one :parent
|
480
|
-
one_to_many :children, :key=>:parent_id
|
479
|
+
many_to_one :parent, :class=>self
|
480
|
+
one_to_many :children, :key=>:parent_id, :class=>self
|
481
481
|
end
|
482
482
|
|
483
483
|
You can easily get a node's parent with node.parent, and a node's children with
|
@@ -492,7 +492,8 @@ What if you want to get all ancestors up to the root node, or all descendents,
|
|
492
492
|
without knowing the depth of the tree?
|
493
493
|
|
494
494
|
class Node < Sequel::Model
|
495
|
-
many_to_one :ancestors, :
|
495
|
+
many_to_one :ancestors, :class=>self,
|
496
|
+
:eager_loader=>(proc do |key_hash, nodes, associations|
|
496
497
|
# Handle cases where the root node has the same parent_id as primary_key
|
497
498
|
# and also when it is NULL
|
498
499
|
non_root_nodes = nodes.reject do |n|
|
data/doc/release_notes/3.7.0.txt
CHANGED
@@ -97,8 +97,8 @@ New Features
|
|
97
97
|
database could be changed between retrieving the model object and
|
98
98
|
updating it.
|
99
99
|
|
100
|
-
* The
|
101
|
-
:alias option
|
100
|
+
* The Dataset #union, #intersect, and #except methods now accept an
|
101
|
+
:alias option which is used as the alias for the returned dataset.
|
102
102
|
|
103
103
|
DB[:table].union(DB[:old_table], :alias=>:table)
|
104
104
|
|
@@ -0,0 +1,151 @@
|
|
1
|
+
New Features
|
2
|
+
------------
|
3
|
+
|
4
|
+
* Dataset#each_server was added, allowing you to run the same query
|
5
|
+
(most likely insert/update/delete) on all shards. This is useful
|
6
|
+
if you have a sharded database but have lookup tables that should
|
7
|
+
be identical on all shards. It works by yielding copies of the
|
8
|
+
current dataset that are tied to each server/shard:
|
9
|
+
|
10
|
+
DB[:table].filter(:id=>1).each_server do |ds|
|
11
|
+
ds.update(:name=>'foo')
|
12
|
+
end
|
13
|
+
|
14
|
+
* Database#each_server was added, allowing you to run schema
|
15
|
+
modification methods on all shards. It works by yielding a
|
16
|
+
new Sequel::Database object for each shard, that will connect to
|
17
|
+
only that shard:
|
18
|
+
|
19
|
+
DB.each_server do |db|
|
20
|
+
db.create_table(:t){Integer :num}
|
21
|
+
end
|
22
|
+
|
23
|
+
* You can now add and remove servers/shards from the connection
|
24
|
+
pool while Sequel is running:
|
25
|
+
|
26
|
+
DB.add_servers(:shard1=>{:host=>'s1'}, :shard2=>{:host=>'s2'})
|
27
|
+
DB.remove_servers(:shard1, :shard2)
|
28
|
+
|
29
|
+
* When you attempt to disconnect from a server that has connections
|
30
|
+
currently in use, Sequel will now schedule those connections to
|
31
|
+
be disconnected when they are returned to the pool. Previously,
|
32
|
+
Sequel disconnected available connections, but ignored connections
|
33
|
+
currently in use, so it wasn't possible to guarantee complete
|
34
|
+
disconnection from the server. Even with this new feature, you can
|
35
|
+
only guarantee eventual disconnection, since disconnection of
|
36
|
+
connections in use happens asynchronously.
|
37
|
+
|
38
|
+
* Database#disconnect now accepts a :servers option specifying the
|
39
|
+
server(s) from which to disconnect. This should be a symbol or
|
40
|
+
array of symbols representing servers/shards. Only those specified
|
41
|
+
will be disconnected:
|
42
|
+
|
43
|
+
DB.disconnect(:servers=>[:shard1, :shard2])
|
44
|
+
|
45
|
+
* A validates_type validation was added to the validation_helpers
|
46
|
+
plugin. It allows you to check that a given column contains
|
47
|
+
the correct type. I can be helpful if you are also using the
|
48
|
+
serialization plugin to store serialized ruby objects, by making
|
49
|
+
sure that the objects are of the correct type (e.g. Hash):
|
50
|
+
|
51
|
+
def validate
|
52
|
+
validates_type(Hash, :options)
|
53
|
+
end
|
54
|
+
|
55
|
+
* Sequel::SQL::Expression#== is now supported for all expressions:
|
56
|
+
|
57
|
+
:column.qualify(:table).cast(:type) == \
|
58
|
+
:column.qualify(:table).cast(:type)
|
59
|
+
# => true
|
60
|
+
:column.qualify(:table).cast(:type) == \
|
61
|
+
:other_column.qualify(:table).cast(:type)
|
62
|
+
# => false
|
63
|
+
|
64
|
+
* When using the generic File type to create blob columns on
|
65
|
+
MySQL, you can specify the specific database type by using the
|
66
|
+
:size option (with :tiny, :medium, and :long values recognized):
|
67
|
+
|
68
|
+
DB.create_table(:docs){File :body, :size=>:long} # longblob
|
69
|
+
|
70
|
+
* The mysql adapter will now default to using mysqlplus, falling
|
71
|
+
back to use mysql. mysqlplus is significantly better for threaded
|
72
|
+
code because queries do not block the entire interpreter.
|
73
|
+
|
74
|
+
* The JDBC adapter is now able to detect certain types of disconnect
|
75
|
+
errors.
|
76
|
+
|
77
|
+
* ConnectionPool.servers and Database.servers were added, which
|
78
|
+
return an array of symbols specifying the servers/shards in use.
|
79
|
+
|
80
|
+
Other Improvements
|
81
|
+
------------------
|
82
|
+
|
83
|
+
* The single-threaded connection pool now raises
|
84
|
+
DatabaseConnectionErrors if unable to connect, so it now operates
|
85
|
+
more similarly to the default connection pool.
|
86
|
+
|
87
|
+
* The single-threaded connection pool now operates more similar
|
88
|
+
to the default connection pool when given a nonexistent server.
|
89
|
+
|
90
|
+
* PGErrors are now correctly converted to DatabaseErrors in the
|
91
|
+
postgres adapter when preparing statements or executing prepared
|
92
|
+
statements.
|
93
|
+
|
94
|
+
* DatabaseDisconnectErrors are now raised correctly in the postgres
|
95
|
+
adapter if the connection status is not OK after a query raises an
|
96
|
+
error.
|
97
|
+
|
98
|
+
* In the mysql adapter, multiple statements in a single query should
|
99
|
+
now be handled correctly in the all cases, not just when using
|
100
|
+
Dataset#each. So you can now submit multiple queries in a single
|
101
|
+
string to Database#run.
|
102
|
+
|
103
|
+
* Model object creation on Microsoft SQL Server 2000 once again
|
104
|
+
works correctly. Previously, an optimization was used that was
|
105
|
+
only supported on 2005+.
|
106
|
+
|
107
|
+
* Backslashes are no longer doubled inside string literals when
|
108
|
+
connecting to Microsoft SQL Server.
|
109
|
+
|
110
|
+
* The ORDER clause now correctly comes after the HAVING clause on
|
111
|
+
Microsoft SQL Server.
|
112
|
+
|
113
|
+
* Sequel now checks that there is an active transaction before
|
114
|
+
rolling back transactions on Microsoft SQL Server, since
|
115
|
+
there are cases where Microsoft SQL Server will roll back
|
116
|
+
transactions implicitly.
|
117
|
+
|
118
|
+
* Blobs are now handled correctly when connecting to H2.
|
119
|
+
|
120
|
+
* 64-bit integers are now handled correctly in JDBC prepared
|
121
|
+
statements.
|
122
|
+
|
123
|
+
* In the boolean_readers plugin, correctly handle columns not in
|
124
|
+
the db_schema, and don't raise an error if the model's columns
|
125
|
+
can't be determined.
|
126
|
+
|
127
|
+
* In the identity_map plugin, remove instances from the cache if they
|
128
|
+
are deleted or destroyed.
|
129
|
+
|
130
|
+
Backwards Compatibility
|
131
|
+
-----------------------
|
132
|
+
|
133
|
+
* Dataset::FROM_SELF_KEEP_OPTS was merged into
|
134
|
+
Dataset::NON_SQL_OPTIONS. While used in different places, they
|
135
|
+
were used for the same purpose, and entries missing from one should
|
136
|
+
have been included in the other.
|
137
|
+
|
138
|
+
* The connection pool internals changed substantially. Now,
|
139
|
+
ConnectionPool #allocated and #available_connections will return
|
140
|
+
nil instead of an array or hash if they are called with a
|
141
|
+
nonexistent server. These are generally only used internally,
|
142
|
+
though they are part of the public API. #created_count and #size
|
143
|
+
still return the size of the :default server when called with a
|
144
|
+
nonexistent server, though.
|
145
|
+
|
146
|
+
* The meta_eval and metaclass private methods were removed from
|
147
|
+
Sequel::MetaProgramming (only the meta_def public method remains).
|
148
|
+
If you want these methods, use the metaid gem.
|
149
|
+
|
150
|
+
* The irregular ox->oxen pluralization rule was removed from the
|
151
|
+
default inflections, as it screws up the more common box->boxes.
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -322,7 +322,13 @@ module Sequel
|
|
322
322
|
def metadata(*args, &block)
|
323
323
|
synchronize{|c| metadata_dataset.send(:process_result_set, c.getMetaData.send(*args), &block)}
|
324
324
|
end
|
325
|
-
|
325
|
+
|
326
|
+
# Treat SQLExceptions with a "Connection Error" SQLState as disconnects
|
327
|
+
def raise_error(exception, opts={})
|
328
|
+
cause = exception.respond_to?(:cause) ? exception.cause : exception
|
329
|
+
super(exception, {:disconnect => cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/}.merge(opts))
|
330
|
+
end
|
331
|
+
|
326
332
|
# Close the given statement when removing the transaction
|
327
333
|
def remove_transaction(stmt)
|
328
334
|
stmt.close if stmt && !supports_savepoints?
|
@@ -336,7 +342,7 @@ module Sequel
|
|
336
342
|
def set_ps_arg(cps, arg, i)
|
337
343
|
case arg
|
338
344
|
when Integer
|
339
|
-
cps.
|
345
|
+
cps.setLong(i, arg)
|
340
346
|
when Sequel::SQL::Blob
|
341
347
|
cps.setBytes(i, arg.to_java_bytes)
|
342
348
|
when String
|
@@ -492,6 +498,8 @@ module Sequel
|
|
492
498
|
BigDecimal.new(v.to_string)
|
493
499
|
when Java::byte[]
|
494
500
|
Sequel::SQL::Blob.new(String.from_java_bytes(v))
|
501
|
+
when Java::JavaSQL::Blob
|
502
|
+
convert_type(v.getBytes(0, v.length))
|
495
503
|
else
|
496
504
|
v
|
497
505
|
end
|
@@ -105,6 +105,20 @@ module Sequel
|
|
105
105
|
|
106
106
|
private
|
107
107
|
|
108
|
+
# H2 expects hexadecimal strings for blob values
|
109
|
+
def literal_blob(v)
|
110
|
+
literal_string v.unpack("H*").first
|
111
|
+
end
|
112
|
+
|
113
|
+
def convert_type(v)
|
114
|
+
case v
|
115
|
+
when Java::OrgH2Jdbc::JdbcClob
|
116
|
+
convert_type(v.getSubString(1, v.length))
|
117
|
+
else
|
118
|
+
super(v)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
108
122
|
def select_clause_methods
|
109
123
|
SELECT_CLAUSE_METHODS
|
110
124
|
end
|
@@ -1,5 +1,10 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require "mysqlplus"
|
3
|
+
rescue LoadError
|
4
|
+
require 'mysql'
|
5
|
+
end
|
2
6
|
raise(LoadError, "require 'mysql' did not define Mysql::CLIENT_MULTI_RESULTS!\n You are probably using the pure ruby mysql.rb driver,\n which Sequel does not support. You need to install\n the C based adapter, and make sure that the mysql.so\n file is loaded instead of the mysql.rb file.\n") unless defined?(Mysql::CLIENT_MULTI_RESULTS)
|
7
|
+
|
3
8
|
Sequel.require %w'shared/mysql utils/stored_procedures', 'adapters'
|
4
9
|
|
5
10
|
module Sequel
|
@@ -160,35 +165,40 @@ module Sequel
|
|
160
165
|
r = conn.query(sql)
|
161
166
|
if opts[:type] == :select
|
162
167
|
yield r if r
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
rescue Mysql::Error
|
172
|
-
break
|
173
|
-
end
|
174
|
-
yield r
|
175
|
-
break unless conn.next_result
|
168
|
+
elsif block_given?
|
169
|
+
yield conn
|
170
|
+
end
|
171
|
+
if conn.respond_to?(:more_results?)
|
172
|
+
while conn.more_results? do
|
173
|
+
if r
|
174
|
+
r.free
|
175
|
+
r = nil
|
176
176
|
end
|
177
|
+
begin
|
178
|
+
conn.next_result
|
179
|
+
r = conn.use_result
|
180
|
+
rescue Mysql::Error => e
|
181
|
+
raise_error(e, :disconnect=>true) if MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message)
|
182
|
+
break
|
183
|
+
end
|
184
|
+
yield r if opts[:type] == :select
|
177
185
|
end
|
178
|
-
else
|
179
|
-
yield conn if block_given?
|
180
186
|
end
|
181
187
|
rescue Mysql::Error => e
|
182
188
|
raise_error(e, :disconnect=>MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message))
|
183
189
|
ensure
|
184
|
-
if r
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
190
|
+
r.free if r
|
191
|
+
# Use up all results to avoid a commands out of sync message.
|
192
|
+
if conn.respond_to?(:more_results?)
|
193
|
+
while conn.more_results? do
|
194
|
+
begin
|
195
|
+
conn.next_result
|
189
196
|
r = conn.use_result
|
190
|
-
|
197
|
+
rescue Mysql::Error => e
|
198
|
+
raise_error(e, :disconnect=>true) if MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message)
|
199
|
+
break
|
191
200
|
end
|
201
|
+
r.free if r
|
192
202
|
end
|
193
203
|
end
|
194
204
|
end
|
@@ -314,7 +324,7 @@ module Sequel
|
|
314
324
|
|
315
325
|
# Delete rows matching this dataset
|
316
326
|
def delete
|
317
|
-
execute_dui(delete_sql){|c| c.affected_rows}
|
327
|
+
execute_dui(delete_sql){|c| return c.affected_rows}
|
318
328
|
end
|
319
329
|
|
320
330
|
# Yield all rows matching this dataset. If the dataset is set to
|
@@ -344,7 +354,7 @@ module Sequel
|
|
344
354
|
|
345
355
|
# Insert a new value into this dataset
|
346
356
|
def insert(*values)
|
347
|
-
execute_dui(insert_sql(*values)){|c| c.insert_id}
|
357
|
+
execute_dui(insert_sql(*values)){|c| return c.insert_id}
|
348
358
|
end
|
349
359
|
|
350
360
|
# Store the given type of prepared statement in the associated database
|
@@ -361,7 +371,7 @@ module Sequel
|
|
361
371
|
|
362
372
|
# Replace (update or insert) the matching row.
|
363
373
|
def replace(*args)
|
364
|
-
execute_dui(replace_sql(*args)){|c| c.insert_id}
|
374
|
+
execute_dui(replace_sql(*args)){|c| return c.insert_id}
|
365
375
|
end
|
366
376
|
|
367
377
|
# Makes each yield arrays of rows, with each array containing the rows
|
@@ -382,7 +392,7 @@ module Sequel
|
|
382
392
|
|
383
393
|
# Update the matching rows.
|
384
394
|
def update(values={})
|
385
|
-
execute_dui(update_sql(values)){|c| c.affected_rows}
|
395
|
+
execute_dui(update_sql(values)){|c| return c.affected_rows}
|
386
396
|
end
|
387
397
|
|
388
398
|
private
|
@@ -138,24 +138,29 @@ module Sequel
|
|
138
138
|
end
|
139
139
|
@prepared_statements = {} if SEQUEL_POSTGRES_USES_PG
|
140
140
|
end
|
141
|
-
|
142
|
-
#
|
143
|
-
#
|
144
|
-
def
|
145
|
-
q = nil
|
141
|
+
|
142
|
+
# Raise a Sequel::DatabaseDisconnectError if a PGError is raised and
|
143
|
+
# the connection status cannot be determined or it is not OK.
|
144
|
+
def check_disconnect_errors
|
146
145
|
begin
|
147
|
-
|
148
|
-
rescue PGError =>
|
146
|
+
yield
|
147
|
+
rescue PGError =>e
|
149
148
|
begin
|
150
149
|
s = status
|
151
150
|
rescue PGError
|
152
151
|
raise Sequel.convert_exception_class(e, Sequel::DatabaseDisconnectError)
|
153
152
|
end
|
154
153
|
status_ok = (s == Adapter::CONNECTION_OK)
|
155
|
-
status_ok ? raise : Sequel.convert_exception_class(e, Sequel::DatabaseDisconnectError)
|
154
|
+
status_ok ? raise : raise(Sequel.convert_exception_class(e, Sequel::DatabaseDisconnectError))
|
156
155
|
ensure
|
157
156
|
block if status_ok
|
158
157
|
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Execute the given SQL with this connection. If a block is given,
|
161
|
+
# yield the results, otherwise, return the number of changed rows.
|
162
|
+
def execute(sql, args=nil)
|
163
|
+
q = check_disconnect_errors{args ? async_exec(sql, args) : async_exec(sql)}
|
159
164
|
begin
|
160
165
|
block_given? ? yield(q) : q.cmd_tuples
|
161
166
|
ensure
|
@@ -218,13 +223,10 @@ module Sequel
|
|
218
223
|
|
219
224
|
# Execute the given SQL with the given args on an available connection.
|
220
225
|
def execute(sql, opts={}, &block)
|
221
|
-
|
222
|
-
|
226
|
+
check_database_errors do
|
227
|
+
return execute_prepared_statement(sql, opts, &block) if Symbol === sql
|
223
228
|
log_info(sql, opts[:arguments])
|
224
229
|
synchronize(opts[:server]){|conn| conn.execute(sql, opts[:arguments], &block)}
|
225
|
-
rescue => e
|
226
|
-
log_info(e.message)
|
227
|
-
raise_error(e, :classes=>CONVERTED_EXCEPTIONS)
|
228
230
|
end
|
229
231
|
end
|
230
232
|
|
@@ -232,19 +234,25 @@ module Sequel
|
|
232
234
|
# automatically generated).
|
233
235
|
def execute_insert(sql, opts={})
|
234
236
|
return execute(sql, opts) if Symbol === sql
|
235
|
-
|
237
|
+
check_database_errors do
|
236
238
|
log_info(sql, opts[:arguments])
|
237
239
|
synchronize(opts[:server]) do |conn|
|
238
240
|
conn.execute(sql, opts[:arguments])
|
239
241
|
insert_result(conn, opts[:table], opts[:values])
|
240
242
|
end
|
241
|
-
rescue => e
|
242
|
-
log_info(e.message)
|
243
|
-
raise_error(e, :classes=>CONVERTED_EXCEPTIONS)
|
244
243
|
end
|
245
244
|
end
|
246
245
|
|
247
246
|
private
|
247
|
+
|
248
|
+
# Convert exceptions raised from the block into DatabaseErrors.
|
249
|
+
def check_database_errors
|
250
|
+
begin
|
251
|
+
yield
|
252
|
+
rescue => e
|
253
|
+
raise_error(e, :classes=>CONVERTED_EXCEPTIONS)
|
254
|
+
end
|
255
|
+
end
|
248
256
|
|
249
257
|
# PostgreSQL doesn't need the connection pool to convert exceptions.
|
250
258
|
def connection_pool_default_options
|
@@ -281,10 +289,10 @@ module Sequel
|
|
281
289
|
end
|
282
290
|
conn.prepared_statements[ps_name] = sql
|
283
291
|
log_info("PREPARE #{ps_name} AS #{sql}")
|
284
|
-
conn.prepare(ps_name, sql)
|
292
|
+
conn.check_disconnect_errors{conn.prepare(ps_name, sql)}
|
285
293
|
end
|
286
294
|
log_info("EXECUTE #{ps_name}", args)
|
287
|
-
q = conn.exec_prepared(ps_name, args)
|
295
|
+
q = conn.check_disconnect_errors{conn.exec_prepared(ps_name, args)}
|
288
296
|
if opts[:table] && opts[:values]
|
289
297
|
insert_result(conn, opts[:table], opts[:values])
|
290
298
|
else
|