sequel 3.44.0 → 3.45.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +44 -0
- data/Rakefile +12 -4
- data/doc/reflection.rdoc +3 -3
- data/doc/release_notes/3.45.0.txt +179 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/transactions.rdoc +23 -0
- data/lib/sequel/adapters/db2.rb +1 -0
- data/lib/sequel/adapters/ibmdb.rb +19 -3
- data/lib/sequel/adapters/jdbc.rb +15 -0
- data/lib/sequel/adapters/jdbc/derby.rb +1 -5
- data/lib/sequel/adapters/jdbc/h2.rb +1 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -1
- data/lib/sequel/adapters/jdbc/jtds.rb +5 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +5 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +7 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
- data/lib/sequel/adapters/jdbc/transactions.rb +28 -1
- data/lib/sequel/adapters/mysql.rb +4 -0
- data/lib/sequel/adapters/mysql2.rb +5 -1
- data/lib/sequel/adapters/oracle.rb +18 -0
- data/lib/sequel/adapters/postgres.rb +11 -1
- data/lib/sequel/adapters/shared/access.rb +14 -2
- data/lib/sequel/adapters/shared/cubrid.rb +1 -11
- data/lib/sequel/adapters/shared/db2.rb +11 -6
- data/lib/sequel/adapters/shared/mssql.rb +10 -10
- data/lib/sequel/adapters/shared/mysql.rb +11 -1
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +17 -1
- data/lib/sequel/adapters/shared/oracle.rb +16 -15
- data/lib/sequel/adapters/shared/postgres.rb +91 -59
- data/lib/sequel/adapters/shared/sqlite.rb +1 -4
- data/lib/sequel/adapters/tinytds.rb +15 -0
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +10 -0
- data/lib/sequel/database/connecting.rb +2 -0
- data/lib/sequel/database/misc.rb +46 -4
- data/lib/sequel/database/query.rb +33 -14
- data/lib/sequel/database/schema_methods.rb +0 -5
- data/lib/sequel/dataset/misc.rb +9 -0
- data/lib/sequel/dataset/mutation.rb +9 -7
- data/lib/sequel/dataset/sql.rb +13 -0
- data/lib/sequel/exceptions.rb +3 -0
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +0 -8
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/named_timezones.rb +18 -2
- data/lib/sequel/extensions/pg_array.rb +5 -1
- data/lib/sequel/extensions/pg_array_ops.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_json.rb +3 -1
- data/lib/sequel/extensions/pg_range.rb +2 -0
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +2 -0
- data/lib/sequel/extensions/pg_row_ops.rb +2 -0
- data/lib/sequel/extensions/query.rb +18 -22
- data/lib/sequel/model/associations.rb +3 -4
- data/lib/sequel/model/base.rb +2 -0
- data/lib/sequel/plugins/force_encoding.rb +2 -0
- data/lib/sequel/plugins/json_serializer.rb +155 -39
- data/lib/sequel/plugins/serialization.rb +14 -2
- data/lib/sequel/plugins/unlimited_update.rb +31 -0
- data/lib/sequel/plugins/validation_class_methods.rb +6 -4
- data/lib/sequel/plugins/xml_serializer.rb +133 -30
- data/lib/sequel/sql.rb +2 -0
- data/lib/sequel/timezones.rb +4 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +0 -11
- data/spec/adapters/postgres_spec.rb +86 -54
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/core/connection_pool_spec.rb +16 -0
- data/spec/core/database_spec.rb +77 -1
- data/spec/core/dataset_spec.rb +30 -15
- data/spec/core/expression_filters_spec.rb +55 -13
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/schema_spec.rb +0 -2
- data/spec/core/spec_helper.rb +5 -0
- data/spec/core_extensions_spec.rb +33 -28
- data/spec/extensions/constraint_validations_spec.rb +2 -2
- data/spec/extensions/core_refinements_spec.rb +12 -12
- data/spec/extensions/json_serializer_spec.rb +137 -31
- data/spec/extensions/named_timezones_spec.rb +10 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +5 -0
- data/spec/extensions/pg_json_spec.rb +14 -0
- data/spec/extensions/pg_row_spec.rb +11 -0
- data/spec/extensions/pretty_table_spec.rb +2 -2
- data/spec/extensions/query_spec.rb +11 -8
- data/spec/extensions/serialization_spec.rb +20 -0
- data/spec/extensions/spec_helper.rb +8 -2
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/unlimited_update_spec.rb +20 -0
- data/spec/extensions/xml_serializer_spec.rb +68 -16
- data/spec/integration/dataset_test.rb +28 -0
- data/spec/integration/spec_helper.rb +6 -0
- data/spec/integration/transaction_test.rb +39 -0
- data/spec/model/model_spec.rb +1 -1
- data/spec/sequel_coverage.rb +15 -0
- metadata +8 -3
data/CHANGELOG
CHANGED
@@ -1,3 +1,47 @@
|
|
1
|
+
=== 3.45.0 (2013-03-01)
|
2
|
+
|
3
|
+
* Remove bad model typecasting of money type on PostgreSQL (jeremyevans) (#624)
|
4
|
+
|
5
|
+
* Use simplecov instead of rcov for coverage testing on 1.9+ (jeremyevans)
|
6
|
+
|
7
|
+
* Make the Database#quote_identifier method public (jeremyevans)
|
8
|
+
|
9
|
+
* Make PostgreSQL metadata parsing handle tables with the same name in multiple schemas (jeremyevans)
|
10
|
+
|
11
|
+
* Switch query extension to use a proxy instead of Object#extend (chanks, jeremyevans)
|
12
|
+
|
13
|
+
* Remove Dataset#def_mutiation_method instance method (jeremyevans)
|
14
|
+
|
15
|
+
* Make foreign key parsing on MySQL not pick up foreign keys in other databases (jeremyevans)
|
16
|
+
|
17
|
+
* Allow per-instance overrides of Postgres.force_standard_strings and .client_min_messages (jeremyevans) (#618)
|
18
|
+
|
19
|
+
* Add Sequel.tzinfo_disambiguator= to the named_timezones plugin for automatically handling TZInfo::AmbiguousTime exceptions (jeremyevans) (#616)
|
20
|
+
|
21
|
+
* Add Dataset#escape_like, for escaping LIKE metacharacters (jeremyevans) (#614)
|
22
|
+
|
23
|
+
* The LIKE operators now use an explicit ESCAPE '\' clause for similar behavior across databases (jeremyevans)
|
24
|
+
|
25
|
+
* Make Database#tables and #views accept a :qualify option on PostgreSQL to return qualified identifiers (jeremyevans)
|
26
|
+
|
27
|
+
* Make json_serializer and xml_serializer plugins secure by default (jeremyevans)
|
28
|
+
|
29
|
+
* Address JSON.parse vulnerabilities (jeremyevans)
|
30
|
+
|
31
|
+
* Fix Dataset#from_self! to no longer create a self-referential dataset (jeremyevans)
|
32
|
+
|
33
|
+
* Use SQLSTATE or database error codes if available instead of regexp parsing for more specific DatabaseErrors (jeremyevans)
|
34
|
+
|
35
|
+
* Add unlimited_update plugin to work around MySQL warning in replicated environments (jeremyevans)
|
36
|
+
|
37
|
+
* Add the :retry_on and :num_retries transaction options for automatically retrying transactions (jeremyevans)
|
38
|
+
|
39
|
+
* Raise serialization failures/deadlocks as Sequel::SerializationFailure exceptions (jeremyevans)
|
40
|
+
|
41
|
+
* Support transaction isolation levels on Oracle and DB2 (jeremyevans)
|
42
|
+
|
43
|
+
* Support transaction isolation levels when using the JDBC transaction support (jeremyevans)
|
44
|
+
|
1
45
|
=== 3.44.0 (2013-02-04)
|
2
46
|
|
3
47
|
* Speedup mysql2 adapter with identifier output method fetch speed by up to 50% (jeremyevans)
|
data/Rakefile
CHANGED
@@ -125,10 +125,18 @@ begin
|
|
125
125
|
|
126
126
|
spec_with_cov = lambda do |name, files, d, &b|
|
127
127
|
spec.call(name, files, d)
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
128
|
+
if RUBY_VERSION < '1.9'
|
129
|
+
t = spec.call("#{name}_cov", files, "#{d} with coverage")
|
130
|
+
t.rcov = true
|
131
|
+
t.rcov_opts = File.read("spec/rcov.opts").split("\n")
|
132
|
+
b.call(t) if b
|
133
|
+
else
|
134
|
+
desc "#{d} with coverage"
|
135
|
+
task "#{name}_cov" do
|
136
|
+
ENV['COVERAGE'] = '1'
|
137
|
+
Rake::Task[name].invoke
|
138
|
+
end
|
139
|
+
end
|
132
140
|
t
|
133
141
|
end
|
134
142
|
|
data/doc/reflection.rdoc
CHANGED
@@ -99,12 +99,12 @@ You can get an array of association symbols with Model.associations:
|
|
99
99
|
|
100
100
|
You can get the association reflection for a single association via the Model.association_reflection. Association reflections are subclasses of hash, for ease of use and introspection (and backwards compatibility):
|
101
101
|
|
102
|
-
Model.association_reflection(:association1) # {:name=>:association1, :type=>:many_to_one, :model=>Model,
|
102
|
+
Model.association_reflection(:association1) # {:name=>:association1, :type=>:many_to_one, :model=>Model, ...}
|
103
103
|
|
104
104
|
You can get an array of all association reflections via Model.all_association_reflections:
|
105
105
|
|
106
|
-
Model.all_association_reflections # [{:name=>:association1, :type=>:many_to_one, :model=>Model,
|
106
|
+
Model.all_association_reflections # [{:name=>:association1, :type=>:many_to_one, :model=>Model, ...}, ...]
|
107
107
|
|
108
108
|
Finally, you can get a hash of association reflections via Model.association_reflections:
|
109
109
|
|
110
|
-
Model.association_reflections # {:association1=>{:name=>:association1, :type=>:many_to_one, :model=>Model,
|
110
|
+
Model.association_reflections # {:association1=>{:name=>:association1, :type=>:many_to_one, :model=>Model, ...}, ...}
|
@@ -0,0 +1,179 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Database#transaction now recognizes a :retry_on option, which
|
4
|
+
should contain an exception class or array of exception classes.
|
5
|
+
If the transaction raises one of the given exceptions, Sequel
|
6
|
+
will automatically retry the transaction block. It's a bad idea to
|
7
|
+
use this option if the transaction block is not idempotent.
|
8
|
+
|
9
|
+
By default, Sequel only retries the block 5 times by default,
|
10
|
+
to protect against infinite looping. You can change the number
|
11
|
+
of retries with the :num_retries option.
|
12
|
+
|
13
|
+
Users of the :disconnect=>:retry option are encouraged to switch
|
14
|
+
to :retry_on=>Sequel::DatabaseDisconnectError.
|
15
|
+
|
16
|
+
* Dataset#escape_like has been added for escaping LIKE
|
17
|
+
metacharacters. This is designed for the case where part of
|
18
|
+
the LIKE pattern is based on user input that should not treat the
|
19
|
+
metacharacters specially.
|
20
|
+
|
21
|
+
* Serialization failures/deadlocks are now raised as
|
22
|
+
Sequel::SerializationFailure exception instances. This exception
|
23
|
+
class is a good candidate for the transaction :retry_on option.
|
24
|
+
|
25
|
+
* On PostgreSQL, you can now provide the :force_standard_strings
|
26
|
+
and :client_min_messages Database options to override the defaults
|
27
|
+
on a per-instance basis.
|
28
|
+
|
29
|
+
* On PostgreSQL, Database#tables and #views now recognizes a
|
30
|
+
:qualify option, which if true will return qualified identifiers
|
31
|
+
instead of plain symbols.
|
32
|
+
|
33
|
+
* Transaction isolation levels are now supported on Oracle, DB2,
|
34
|
+
and all jdbc subadapters using the JDBC transaction support.
|
35
|
+
|
36
|
+
* Dataset.def_mutation_method now accepts a :module option for
|
37
|
+
the module in which to define the methods (defaulting to self).
|
38
|
+
|
39
|
+
* An unlimited_update plugin has been added. It's sole purpose is to
|
40
|
+
eliminate a MySQL warning in replicated environments, since by
|
41
|
+
default Sequel::Model uses a LIMIT clause when updating on MySQL.
|
42
|
+
|
43
|
+
* The named_timezones extension now adds a
|
44
|
+
Sequel.tzinfo_disambiguator accessor to automatically handle
|
45
|
+
TZInfo::AmbiguousTime exceptions. This should be a callable object
|
46
|
+
that accepts two arguments, a DateTime instance and an array of
|
47
|
+
timezone periods, and returns the timezone period to use.
|
48
|
+
|
49
|
+
= Other Improvements
|
50
|
+
|
51
|
+
* Sequel now handles JSON securely, specifying the
|
52
|
+
:create_additions=>false option when using JSON.parse. If you
|
53
|
+
really want to get the old vulnerable behavior back, override
|
54
|
+
Sequel.parse_json.
|
55
|
+
|
56
|
+
* The json_serializer and xml_serializer plugins are now secure
|
57
|
+
by default. Before, the default behavior of these plugins
|
58
|
+
allowed for round tripping, such that:
|
59
|
+
|
60
|
+
Album.from_xml(album.to_xml) == album
|
61
|
+
|
62
|
+
Unfortunately, that requires that the deserialization allow
|
63
|
+
the setting of any column. Since the plugins also handle
|
64
|
+
associations, you could also set any column in any associated
|
65
|
+
object, even cascading to associated objects of those objects.
|
66
|
+
|
67
|
+
The new default behavior only allows deserialization to set
|
68
|
+
the same columns that mass-assignment would set, and not to
|
69
|
+
handle associated objects at all by default. The following
|
70
|
+
additional options are supported:
|
71
|
+
|
72
|
+
:fields :: The specific fields to set (this was already supported
|
73
|
+
by the json_serializer plugin).
|
74
|
+
:associations :: The specific associations to handle.
|
75
|
+
:all_columns :: The previous behavior of setting all columns.
|
76
|
+
:all_associations :: The previous behavior of setting all
|
77
|
+
associations.
|
78
|
+
|
79
|
+
Since JSON parsing no longer deserializes into arbitrary ruby
|
80
|
+
instances, from_json and array_from_json class methods have been
|
81
|
+
added to the json_serializer plugin, for deserializing into model
|
82
|
+
instances. These mirror the from_xml and array_from_xml class
|
83
|
+
methods in the xml_serializer plugin.
|
84
|
+
|
85
|
+
Note that the :all_columns and :all_associations methods were
|
86
|
+
only added to make backwards compatibility easier. It is
|
87
|
+
likely they will be removed in Sequel 4, along with the
|
88
|
+
json_create class method.
|
89
|
+
|
90
|
+
* Sequel now attempts to use database specific error codes or
|
91
|
+
SQLState codes instead of regexp parsing to determine if a more
|
92
|
+
specific DatabaseError subclass should be used. This should make
|
93
|
+
error handling faster and more robust.
|
94
|
+
|
95
|
+
* Sequel now uses ESCAPE '\' when using LIKE, for similar behavior
|
96
|
+
across databases. Previously, no ESCAPE clause was used, so
|
97
|
+
behavior differed across databases, with most not using escaping,
|
98
|
+
and PostgreSQL, MySQL, and H2 defaulting to backslash as the escape
|
99
|
+
character.
|
100
|
+
|
101
|
+
* The query extension has been reimplemented and now uses a proxy
|
102
|
+
object instead of Object#extend.
|
103
|
+
|
104
|
+
* The :pool_timeout Database option now supports fractional seconds.
|
105
|
+
|
106
|
+
* Database#quote_identifier is now a public method.
|
107
|
+
|
108
|
+
* Metadata parsing (schema, indexes, foreign_key_list) on PostgreSQL
|
109
|
+
now correctly handles the case where an unqualified table name is
|
110
|
+
used and tables with that name exist in multiple schemas. It now
|
111
|
+
picks the first matching table in the schema_search_path, instead of
|
112
|
+
failing or returning results from all tables.
|
113
|
+
|
114
|
+
* Sequel::Model instances no longer attempt to typecast the money
|
115
|
+
type on PostgreSQL, since the previous typecast didn't work
|
116
|
+
correctly, and correct typecasting is locale-dependent.
|
117
|
+
|
118
|
+
* Sequel no longer picks up foreign keys for tables in other
|
119
|
+
databases when using Database#foreign_key_list on MySQL.
|
120
|
+
|
121
|
+
* A warning when using the mysql2 3.12 beta has been eliminated.
|
122
|
+
|
123
|
+
* A warning has been eliminated when using the jdbc/oracle adapter
|
124
|
+
on JRuby 1.7.
|
125
|
+
|
126
|
+
* Sequel's ilike emulation should now work by default on databases
|
127
|
+
without specific syntax support.
|
128
|
+
|
129
|
+
* Dataset#from_self! no longer creates a self referential dataset.
|
130
|
+
|
131
|
+
* Coverage testing now uses simplecov instead of rcov on ruby 1.9+.
|
132
|
+
|
133
|
+
= Backwards Compatibility
|
134
|
+
|
135
|
+
* The switch to using JSON.parse :create_additions=>false means
|
136
|
+
that if your app expected JSON to deserialize into arbitrary
|
137
|
+
ruby objects, it is probably broken. You should update your
|
138
|
+
application code to manually convert the deserialized hashes
|
139
|
+
into the ruby objects you want.
|
140
|
+
|
141
|
+
Note that it's not just this new version of Sequel that will
|
142
|
+
cause that, older versions of Sequel will break in the same
|
143
|
+
way if you update your JSON library to a version that is not
|
144
|
+
vulnerable by default.
|
145
|
+
|
146
|
+
This potentially affects the pg_json extension and serialization
|
147
|
+
plugin if you were expecting the JSON stored in the database
|
148
|
+
to be deserialized into arbitrary ruby objects.
|
149
|
+
|
150
|
+
See the json_serializer/xml_serializer changes mentioned in
|
151
|
+
the Other Improvements section.
|
152
|
+
|
153
|
+
* The reimplemented query extension is not completely backwards
|
154
|
+
compatible. For example, inside a query block, self refers to the
|
155
|
+
proxy object instead of a dataset, and calling methods that return
|
156
|
+
rows no longer raises an exception.
|
157
|
+
|
158
|
+
* The metadata parsing methods on PostgreSQL no longer work with
|
159
|
+
unqualified tables where the table is not in the schema search
|
160
|
+
path. This makes metadata parsing consistent with how datasets
|
161
|
+
operate. For tables outside the schema search path, you must
|
162
|
+
qualify it before use now.
|
163
|
+
|
164
|
+
Additionally, using a nonexistent table name will raise an
|
165
|
+
exception instead of returning empty results in some cases.
|
166
|
+
|
167
|
+
* The Dataset#def_mutation_method instance method has been removed.
|
168
|
+
This method added mutation methods directly on the dataset instance,
|
169
|
+
which is generally not desired. Using the def_mutation_method class
|
170
|
+
method with the :module option is now the recommended approach.
|
171
|
+
|
172
|
+
* The switch to using ESCAPE for LIKE characters is backwards
|
173
|
+
incompatible on databases that don't use escaping by default,
|
174
|
+
when backslash is used in a LIKE pattern as a regular character.
|
175
|
+
Now you have to double the backslash in the pattern.
|
176
|
+
|
177
|
+
* Database#database_error_regexps private method now can return any
|
178
|
+
enumerable yielding regexp/exception class pairs, it is no longer
|
179
|
+
specified to return a hash.
|
@@ -532,7 +532,7 @@ keys before the tables containing the primary keys they reference.
|
|
532
532
|
=== <tt>drop_table?</tt>
|
533
533
|
|
534
534
|
<tt>drop_table?</tt> is similar to drop_table, except that it only drops
|
535
|
-
the table if the table
|
535
|
+
the table if the table already exists. On some databases, it uses
|
536
536
|
<tt>IF NOT EXISTS</tt>, on others it does a separate query to check for
|
537
537
|
existence.
|
538
538
|
|
data/doc/transactions.rdoc
CHANGED
@@ -135,3 +135,26 @@ The SQL standard supports 4 isolation levels: READ UNCOMMITTED, READ COMMITTED,
|
|
135
135
|
# SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
|
136
136
|
DB[:foo].insert(1) # INSERT
|
137
137
|
end # COMMIT
|
138
|
+
|
139
|
+
== Automatically Restarting Transactions
|
140
|
+
|
141
|
+
Sequel offers the ability to automatically restart transactions if specific types of errors are detected. For example, if you want to automatically restart a transaction if a serialization failure is detected:
|
142
|
+
|
143
|
+
DB.transaction(:isolation => :serializable, :retry_on=>[Sequel::SerializationFailure]) do
|
144
|
+
ModelClass.find_or_create(:name=>'Foo')
|
145
|
+
end
|
146
|
+
|
147
|
+
At the serializable transaction isolation level, find_or_create may raises a Sequel::SerializationFailure exception if multiple threads simultaneously run that code. With the :retry_on option set, the transaction will be automatically retried until it succeeds.
|
148
|
+
|
149
|
+
Note that automatic retrying should not be used unless the entire transaction
|
150
|
+
block is idempotent, as otherwise it can cause non-idempotent
|
151
|
+
behavior to execute multiple times. For example, with the following code:
|
152
|
+
|
153
|
+
DB.transaction(:isolation => :serializable, :retry_on=>[Sequel::SerializationFailure]) do
|
154
|
+
logger.info 'Ensuring existence of ModelClass with name Foo'
|
155
|
+
ModelClass.find_or_create(:name=>'Foo')
|
156
|
+
end
|
157
|
+
|
158
|
+
The logger.info method will be called multiple times if there is a serialization failure.
|
159
|
+
|
160
|
+
The :num_retries option can be used to set the maxmimum number of times to retry. It is set to 5 times by default.
|
data/lib/sequel/adapters/db2.rb
CHANGED
@@ -122,6 +122,7 @@ module Sequel
|
|
122
122
|
|
123
123
|
def begin_transaction(conn, opts={})
|
124
124
|
log_yield(TRANSACTION_BEGIN){DB2CLI.SQLSetConnectAttr(conn, DB2CLI::SQL_ATTR_AUTOCOMMIT, DB2CLI::SQL_AUTOCOMMIT_OFF)}
|
125
|
+
set_transaction_isolation(conn, opts)
|
125
126
|
end
|
126
127
|
|
127
128
|
def remove_transaction(conn, committed)
|
@@ -35,6 +35,12 @@ module Sequel
|
|
35
35
|
|
36
36
|
# Error class for exceptions raised by the connection.
|
37
37
|
class Error < StandardError
|
38
|
+
attr_reader :sqlstate
|
39
|
+
|
40
|
+
def initialize(message, sqlstate)
|
41
|
+
@sqlstate = sqlstate
|
42
|
+
super(message)
|
43
|
+
end
|
38
44
|
end
|
39
45
|
|
40
46
|
# Create the underlying IBM_DB connection.
|
@@ -69,11 +75,16 @@ module Sequel
|
|
69
75
|
IBM_DB.getErrormsg(@conn, IBM_DB::DB_CONN)
|
70
76
|
end
|
71
77
|
|
78
|
+
# Return the related error message for the connection.
|
79
|
+
def error_sqlstate
|
80
|
+
IBM_DB.getErrorstate(@conn, IBM_DB::DB_CONN)
|
81
|
+
end
|
82
|
+
|
72
83
|
# Execute the given SQL on the database, and return a Statement instance
|
73
84
|
# holding the results.
|
74
85
|
def execute(sql)
|
75
86
|
stmt = IBM_DB.exec(@conn, sql)
|
76
|
-
raise Error,
|
87
|
+
raise Error.new(error_msg, error_sqlstate) unless stmt
|
77
88
|
Statement.new(stmt)
|
78
89
|
end
|
79
90
|
|
@@ -83,7 +94,7 @@ module Sequel
|
|
83
94
|
stmt = @prepared_statements[ps_name].last
|
84
95
|
res = stmt.execute(*values)
|
85
96
|
unless res
|
86
|
-
raise Error
|
97
|
+
raise Error.new("Error executing statement #{ps_name}: #{error_msg}", error_sqlstate)
|
87
98
|
end
|
88
99
|
stmt
|
89
100
|
end
|
@@ -98,7 +109,7 @@ module Sequel
|
|
98
109
|
else
|
99
110
|
err = error_msg
|
100
111
|
err = "Error preparing #{ps_name} with SQL: #{sql}" if error_msg.nil? || error_msg.empty?
|
101
|
-
raise Error,
|
112
|
+
raise Error.new(err, error_sqlstate)
|
102
113
|
end
|
103
114
|
end
|
104
115
|
|
@@ -301,6 +312,7 @@ module Sequel
|
|
301
312
|
# So starting a transaction just turns autocommit off.
|
302
313
|
def begin_transaction(conn, opts={})
|
303
314
|
log_yield(TRANSACTION_BEGIN){conn.autocommit = false}
|
315
|
+
set_transaction_isolation(conn, opts)
|
304
316
|
end
|
305
317
|
|
306
318
|
# This commits transaction in progress on the
|
@@ -313,6 +325,10 @@ module Sequel
|
|
313
325
|
[Connection::Error]
|
314
326
|
end
|
315
327
|
|
328
|
+
def database_exception_sqlstate(exception, opts)
|
329
|
+
exception.sqlstate
|
330
|
+
end
|
331
|
+
|
316
332
|
# Don't convert smallint to boolean for the metadata
|
317
333
|
# dataset, since the DB2 metadata does not use
|
318
334
|
# boolean columns, and some smallint columns are
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -345,6 +345,21 @@ module Sequel
|
|
345
345
|
[NativeException]
|
346
346
|
end
|
347
347
|
|
348
|
+
def database_exception_sqlstate(exception, opts)
|
349
|
+
if database_exception_use_sqlstates?
|
350
|
+
while exception.respond_to?(:cause)
|
351
|
+
exception = exception.cause
|
352
|
+
return exception.getSQLState if exception.respond_to?(:getSQLState)
|
353
|
+
end
|
354
|
+
end
|
355
|
+
nil
|
356
|
+
end
|
357
|
+
|
358
|
+
# Whether the JDBC subadapter should use SQL states for exception handling, true by default.
|
359
|
+
def database_exception_use_sqlstates?
|
360
|
+
true
|
361
|
+
end
|
362
|
+
|
348
363
|
# Raise a disconnect error if the SQL state of the cause of the exception indicates so.
|
349
364
|
def disconnect_error?(exception, opts)
|
350
365
|
cause = exception.respond_to?(:cause) ? exception.cause : exception
|
@@ -109,6 +109,7 @@ module Sequel
|
|
109
109
|
/violation of foreign key constraint/ => ForeignKeyConstraintViolation,
|
110
110
|
/The check constraint .+ was violated/ => CheckConstraintViolation,
|
111
111
|
/cannot accept a NULL value/ => NotNullConstraintViolation,
|
112
|
+
/A lock could not be obtained due to a deadlock/ => SerializationFailure,
|
112
113
|
}.freeze
|
113
114
|
def database_error_regexps
|
114
115
|
DATABASE_ERROR_REGEXPS
|
@@ -208,13 +209,8 @@ module Sequel
|
|
208
209
|
end
|
209
210
|
end
|
210
211
|
|
211
|
-
# Handle Derby specific LIKE, extract, and some bitwise compliment support.
|
212
212
|
def complex_expression_sql_append(sql, op, args)
|
213
213
|
case op
|
214
|
-
when :ILIKE
|
215
|
-
super(sql, :LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
|
216
|
-
when :"NOT ILIKE"
|
217
|
-
super(sql, :"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
|
218
214
|
when :%
|
219
215
|
sql << complex_expression_arg_pairs(args){|a, b| "MOD(#{literal(a)}, #{literal(b)})"}
|
220
216
|
when :&, :|, :^, :<<, :>>
|
@@ -101,6 +101,7 @@ module Sequel
|
|
101
101
|
/Referential integrity constraint violation/ => ForeignKeyConstraintViolation,
|
102
102
|
/Check constraint violation/ => CheckConstraintViolation,
|
103
103
|
/NULL not allowed for column/ => NotNullConstraintViolation,
|
104
|
+
/Deadlock detected\. The current transaction was rolled back\./ => SerializationFailure,
|
104
105
|
}.freeze
|
105
106
|
def database_error_regexps
|
106
107
|
DATABASE_ERROR_REGEXPS
|
@@ -57,6 +57,7 @@ module Sequel
|
|
57
57
|
/integrity constraint violation: foreign key/ => ForeignKeyConstraintViolation,
|
58
58
|
/integrity constraint violation: check constraint/ => CheckConstraintViolation,
|
59
59
|
/integrity constraint violation: NOT NULL check constraint/ => NotNullConstraintViolation,
|
60
|
+
/serialization failure/ => SerializationFailure,
|
60
61
|
}.freeze
|
61
62
|
def database_error_regexps
|
62
63
|
DATABASE_ERROR_REGEXPS
|
@@ -124,7 +125,7 @@ module Sequel
|
|
124
125
|
def complex_expression_sql_append(sql, op, args)
|
125
126
|
case op
|
126
127
|
when :ILIKE, :"NOT ILIKE"
|
127
|
-
super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"),
|
128
|
+
super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|v| SQL::Function.new(:ucase, v)})
|
128
129
|
when :&, :|, :^
|
129
130
|
op = BITWISE_METHOD_MAP[op]
|
130
131
|
sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
|