sequel 3.44.0 → 3.45.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 +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))}
|