sequel 3.21.0 → 3.32.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 +539 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +89 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +52 -0
- data/lib/sequel/adapters/jdbc/derby.rb +260 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +66 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +339 -0
- data/lib/sequel/adapters/mysql.rb +85 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +355 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +328 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +278 -107
- data/lib/sequel/adapters/shared/mysql.rb +203 -65
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +237 -46
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +200 -50
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +68 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +104 -19
- data/lib/sequel/database/query.rb +163 -59
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +240 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +59 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +676 -267
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1081 -344
- data/lib/sequel/model/base.rb +420 -133
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +20 -10
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +43 -10
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +68 -7
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +135 -30
- data/spec/adapters/mysql_spec.rb +244 -212
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +21 -30
- data/spec/core/database_spec.rb +789 -512
- data/spec/core/dataset_spec.rb +1176 -1061
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +81 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +661 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +500 -67
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +367 -119
- data/spec/integration/prepared_statement_test.rb +222 -125
- data/spec/integration/schema_test.rb +217 -39
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +182 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +955 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +117 -73
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Sequel
|
|
2
2
|
class Database
|
|
3
3
|
# ---------------------
|
|
4
|
-
# :section: Methods that execute queries and/or return results
|
|
4
|
+
# :section: 1 - Methods that execute queries and/or return results
|
|
5
5
|
# This methods generally execute SQL code on the database server.
|
|
6
6
|
# ---------------------
|
|
7
7
|
|
|
@@ -37,9 +37,12 @@ module Sequel
|
|
|
37
37
|
attr_accessor :transaction_isolation_level
|
|
38
38
|
|
|
39
39
|
# Runs the supplied SQL statement string on the database server.
|
|
40
|
-
#
|
|
40
|
+
# Returns self so it can be safely chained:
|
|
41
|
+
#
|
|
42
|
+
# DB << "UPADTE albums SET artist_id = NULL" << "DROP TABLE artists"
|
|
41
43
|
def <<(sql)
|
|
42
44
|
run(sql)
|
|
45
|
+
self
|
|
43
46
|
end
|
|
44
47
|
|
|
45
48
|
# Call the prepared statement with the given name with the given hash
|
|
@@ -82,12 +85,12 @@ module Sequel
|
|
|
82
85
|
#
|
|
83
86
|
# DB.get(1) # SELECT 1
|
|
84
87
|
# # => 1
|
|
85
|
-
# DB.get{
|
|
88
|
+
# DB.get{server_version{}} # SELECT server_version()
|
|
86
89
|
def get(*args, &block)
|
|
87
90
|
dataset.get(*args, &block)
|
|
88
91
|
end
|
|
89
92
|
|
|
90
|
-
# Return a hash containing index information. Hash keys are index name symbols.
|
|
93
|
+
# Return a hash containing index information for the table. Hash keys are index name symbols.
|
|
91
94
|
# Values are subhashes with two keys, :columns and :unique. The value of :columns
|
|
92
95
|
# is an array of symbols of column names. The value of :unique is true or false
|
|
93
96
|
# depending on if the index is unique.
|
|
@@ -110,17 +113,17 @@ module Sequel
|
|
|
110
113
|
nil
|
|
111
114
|
end
|
|
112
115
|
|
|
113
|
-
# Parse the schema from the database.
|
|
114
116
|
# Returns the schema for the given table as an array with all members being arrays of length 2,
|
|
115
117
|
# the first member being the column name, and the second member being a hash of column information.
|
|
118
|
+
# The table argument can also be a dataset, as long as it only has one table.
|
|
116
119
|
# Available options are:
|
|
117
120
|
#
|
|
118
121
|
# :reload :: Ignore any cached results, and get fresh information from the database.
|
|
119
122
|
# :schema :: An explicit schema to use. It may also be implicitly provided
|
|
120
123
|
# via the table name.
|
|
121
124
|
#
|
|
122
|
-
# If schema parsing is supported by the database, the column information should at least contain the
|
|
123
|
-
# following
|
|
125
|
+
# If schema parsing is supported by the database, the column information should hash at least contain the
|
|
126
|
+
# following entries:
|
|
124
127
|
#
|
|
125
128
|
# :allow_null :: Whether NULL is an allowed value for the column.
|
|
126
129
|
# :db_type :: The database type for the column, as a database specific string.
|
|
@@ -129,7 +132,8 @@ module Sequel
|
|
|
129
132
|
# it means that primary key information is unavailable, not that the column
|
|
130
133
|
# is not a primary key.
|
|
131
134
|
# :ruby_default :: The database default for the column, as a ruby object. In many cases, complex
|
|
132
|
-
# database defaults cannot be parsed into ruby objects
|
|
135
|
+
# database defaults cannot be parsed into ruby objects, in which case nil will be
|
|
136
|
+
# used as the value.
|
|
133
137
|
# :type :: A symbol specifying the type, such as :integer or :string.
|
|
134
138
|
#
|
|
135
139
|
# Example:
|
|
@@ -152,9 +156,20 @@ module Sequel
|
|
|
152
156
|
def schema(table, opts={})
|
|
153
157
|
raise(Error, 'schema parsing is not implemented on this database') unless respond_to?(:schema_parse_table, true)
|
|
154
158
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
opts = opts.dup
|
|
160
|
+
if table.is_a?(Dataset)
|
|
161
|
+
o = table.opts
|
|
162
|
+
from = o[:from]
|
|
163
|
+
raise(Error, "can only parse the schema for a dataset with a single from table") unless from && from.length == 1 && !o.include?(:join) && !o.include?(:sql)
|
|
164
|
+
tab = table.first_source_table
|
|
165
|
+
sch, table_name = schema_and_table(tab)
|
|
166
|
+
quoted_name = table.literal(tab)
|
|
167
|
+
opts[:dataset] = table
|
|
168
|
+
else
|
|
169
|
+
sch, table_name = schema_and_table(table)
|
|
170
|
+
quoted_name = quote_schema_table(table)
|
|
171
|
+
end
|
|
172
|
+
opts[:schema] = sch if sch && !opts.include?(:schema)
|
|
158
173
|
|
|
159
174
|
@schemas.delete(quoted_name) if opts[:reload]
|
|
160
175
|
return @schemas[quoted_name] if @schemas[quoted_name]
|
|
@@ -169,15 +184,19 @@ module Sequel
|
|
|
169
184
|
# to the database.
|
|
170
185
|
#
|
|
171
186
|
# DB.table_exists?(:foo) # => false
|
|
187
|
+
# # SELECT NULL FROM foo LIMIT 1
|
|
188
|
+
#
|
|
189
|
+
# Note that since this does a SELECT from the table, it can give false negatives
|
|
190
|
+
# if you don't have permission to SELECT from the table.
|
|
172
191
|
def table_exists?(name)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
192
|
+
sch, table_name = schema_and_table(name)
|
|
193
|
+
name = SQL::QualifiedIdentifier.new(sch, table_name) if sch
|
|
194
|
+
_table_exists?(from(name))
|
|
195
|
+
true
|
|
196
|
+
rescue DatabaseError
|
|
197
|
+
false
|
|
179
198
|
end
|
|
180
|
-
|
|
199
|
+
|
|
181
200
|
# Return all tables in the database as an array of symbols.
|
|
182
201
|
#
|
|
183
202
|
# DB.tables # => [:albums, :artists]
|
|
@@ -198,6 +217,9 @@ module Sequel
|
|
|
198
217
|
# :prepare :: A string to use as the transaction identifier for a
|
|
199
218
|
# prepared transaction (two-phase commit), if the database/adapter
|
|
200
219
|
# supports prepared transactions.
|
|
220
|
+
# :rollback :: Can the set to :reraise to reraise any Sequel::Rollback exceptions
|
|
221
|
+
# raised, or :always to always rollback even if no exceptions occur
|
|
222
|
+
# (useful for testing).
|
|
201
223
|
# :server :: The server to use for the transaction.
|
|
202
224
|
# :savepoint :: Whether to create a new savepoint for this transaction,
|
|
203
225
|
# only respected if the database/adapter supports savepoints. By
|
|
@@ -210,47 +232,85 @@ module Sequel
|
|
|
210
232
|
end
|
|
211
233
|
end
|
|
212
234
|
|
|
235
|
+
# Return all views in the database as an array of symbols.
|
|
236
|
+
#
|
|
237
|
+
# DB.views # => [:gold_albums, :artists_with_many_albums]
|
|
238
|
+
def views(opts={})
|
|
239
|
+
raise NotImplemented, "#views should be overridden by adapters"
|
|
240
|
+
end
|
|
241
|
+
|
|
213
242
|
private
|
|
214
243
|
|
|
244
|
+
# Should raise an error if the table doesn't not exist,
|
|
245
|
+
# and not raise an error if the table does exist.
|
|
246
|
+
def _table_exists?(ds)
|
|
247
|
+
ds.get(Sequel::NULL)
|
|
248
|
+
end
|
|
249
|
+
|
|
215
250
|
# Internal generic transaction method. Any exception raised by the given
|
|
216
251
|
# block will cause the transaction to be rolled back. If the exception is
|
|
217
252
|
# not a Sequel::Rollback, the error will be reraised. If no exception occurs
|
|
218
253
|
# inside the block, the transaction is commited.
|
|
219
254
|
def _transaction(conn, opts={})
|
|
255
|
+
rollback = opts[:rollback]
|
|
220
256
|
begin
|
|
221
|
-
add_transaction
|
|
222
|
-
|
|
223
|
-
|
|
257
|
+
add_transaction(conn, opts)
|
|
258
|
+
begin_transaction(conn, opts)
|
|
259
|
+
if rollback == :always
|
|
260
|
+
begin
|
|
261
|
+
yield(conn)
|
|
262
|
+
rescue Exception => e1
|
|
263
|
+
raise e1
|
|
264
|
+
ensure
|
|
265
|
+
raise ::Sequel::Rollback unless e1
|
|
266
|
+
end
|
|
267
|
+
else
|
|
268
|
+
yield(conn)
|
|
269
|
+
end
|
|
224
270
|
rescue Exception => e
|
|
225
|
-
rollback_transaction(
|
|
226
|
-
transaction_error(e)
|
|
271
|
+
rollback_transaction(conn, opts)
|
|
272
|
+
transaction_error(e, :conn=>conn, :rollback=>rollback)
|
|
227
273
|
ensure
|
|
228
274
|
begin
|
|
229
|
-
|
|
230
|
-
rescue Exception =>
|
|
231
|
-
raise_error(
|
|
275
|
+
committed = commit_or_rollback_transaction(e, conn, opts)
|
|
276
|
+
rescue Exception => e2
|
|
277
|
+
raise_error(e2, :classes=>database_error_classes, :conn=>conn)
|
|
232
278
|
ensure
|
|
233
|
-
remove_transaction(
|
|
279
|
+
remove_transaction(conn, committed)
|
|
234
280
|
end
|
|
235
281
|
end
|
|
236
282
|
end
|
|
237
|
-
|
|
283
|
+
|
|
238
284
|
# Add the current thread to the list of active transactions
|
|
239
|
-
def add_transaction
|
|
240
|
-
th = Thread.current
|
|
285
|
+
def add_transaction(conn, opts)
|
|
241
286
|
if supports_savepoints?
|
|
242
|
-
unless @transactions
|
|
243
|
-
|
|
244
|
-
@transactions
|
|
287
|
+
unless @transactions[conn]
|
|
288
|
+
@transactions[conn] = {:savepoint_level=>0}
|
|
289
|
+
@transactions[conn][:prepare] = opts[:prepare] if supports_prepared_transactions?
|
|
245
290
|
end
|
|
246
291
|
else
|
|
247
|
-
@transactions
|
|
292
|
+
@transactions[conn] = {}
|
|
293
|
+
@transactions[conn][:prepare] = opts[:prepare] if supports_prepared_transactions?
|
|
248
294
|
end
|
|
249
295
|
end
|
|
250
296
|
|
|
297
|
+
# Call all stored after_commit blocks for the given transaction
|
|
298
|
+
def after_transaction_commit(conn)
|
|
299
|
+
if ary = @transactions[conn][:after_commit]
|
|
300
|
+
ary.each{|b| b.call}
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Call all stored after_rollback blocks for the given transaction
|
|
305
|
+
def after_transaction_rollback(conn)
|
|
306
|
+
if ary = @transactions[conn][:after_rollback]
|
|
307
|
+
ary.each{|b| b.call}
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
251
311
|
# Whether the current thread/connection is already inside a transaction
|
|
252
312
|
def already_in_transaction?(conn, opts)
|
|
253
|
-
@transactions.
|
|
313
|
+
@transactions.has_key?(conn) && (!supports_savepoints? || !opts[:savepoint])
|
|
254
314
|
end
|
|
255
315
|
|
|
256
316
|
# SQL to start a new savepoint
|
|
@@ -267,17 +327,16 @@ module Sequel
|
|
|
267
327
|
# Start a new database transaction or a new savepoint on the given connection.
|
|
268
328
|
def begin_transaction(conn, opts={})
|
|
269
329
|
if supports_savepoints?
|
|
270
|
-
th =
|
|
271
|
-
if (depth = th[:
|
|
330
|
+
th = @transactions[conn]
|
|
331
|
+
if (depth = th[:savepoint_level]) > 0
|
|
272
332
|
log_connection_execute(conn, begin_savepoint_sql(depth))
|
|
273
333
|
else
|
|
274
334
|
begin_new_transaction(conn, opts)
|
|
275
335
|
end
|
|
276
|
-
th[:
|
|
336
|
+
th[:savepoint_level] += 1
|
|
277
337
|
else
|
|
278
338
|
begin_new_transaction(conn, opts)
|
|
279
339
|
end
|
|
280
|
-
conn
|
|
281
340
|
end
|
|
282
341
|
|
|
283
342
|
# SQL to BEGIN a transaction.
|
|
@@ -335,6 +394,38 @@ module Sequel
|
|
|
335
394
|
end
|
|
336
395
|
end
|
|
337
396
|
|
|
397
|
+
if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or RUBY_ENGINE == 'rbx') and RUBY_VERSION < '1.9'
|
|
398
|
+
# Whether to commit the current transaction. On ruby 1.8 and rubinius,
|
|
399
|
+
# Thread.current.status is checked because Thread#kill skips rescue
|
|
400
|
+
# blocks (so exception would be nil), but the transaction should
|
|
401
|
+
# still be rolled back.
|
|
402
|
+
def commit_or_rollback_transaction(exception, conn, opts)
|
|
403
|
+
if exception
|
|
404
|
+
false
|
|
405
|
+
else
|
|
406
|
+
if Thread.current.status == 'aborting'
|
|
407
|
+
rollback_transaction(conn, opts)
|
|
408
|
+
false
|
|
409
|
+
else
|
|
410
|
+
commit_transaction(conn, opts)
|
|
411
|
+
true
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
else
|
|
416
|
+
# Whether to commit the current transaction. On ruby 1.9 and JRuby,
|
|
417
|
+
# transactions will be committed if Thread#kill is used on an thread
|
|
418
|
+
# that has a transaction open, and there isn't a work around.
|
|
419
|
+
def commit_or_rollback_transaction(exception, conn, opts)
|
|
420
|
+
if exception
|
|
421
|
+
false
|
|
422
|
+
else
|
|
423
|
+
commit_transaction(conn, opts)
|
|
424
|
+
true
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
338
429
|
# SQL to commit a savepoint
|
|
339
430
|
def commit_savepoint_sql(depth)
|
|
340
431
|
SQL_RELEASE_SAVEPOINT % depth
|
|
@@ -343,7 +434,7 @@ module Sequel
|
|
|
343
434
|
# Commit the active transaction on the connection
|
|
344
435
|
def commit_transaction(conn, opts={})
|
|
345
436
|
if supports_savepoints?
|
|
346
|
-
depth =
|
|
437
|
+
depth = @transactions[conn][:savepoint_level]
|
|
347
438
|
log_connection_execute(conn, depth > 1 ? commit_savepoint_sql(depth-1) : commit_transaction_sql)
|
|
348
439
|
else
|
|
349
440
|
log_connection_execute(conn, commit_transaction_sql)
|
|
@@ -364,8 +455,8 @@ module Sequel
|
|
|
364
455
|
# Return a Method object for the dataset's output_identifier_method.
|
|
365
456
|
# Used in metadata parsing to make sure the returned information is in the
|
|
366
457
|
# correct format.
|
|
367
|
-
def input_identifier_meth
|
|
368
|
-
dataset.method(:input_identifier)
|
|
458
|
+
def input_identifier_meth(ds=nil)
|
|
459
|
+
(ds || dataset).method(:input_identifier)
|
|
369
460
|
end
|
|
370
461
|
|
|
371
462
|
# Return a dataset that uses the default identifier input and output methods
|
|
@@ -382,24 +473,28 @@ module Sequel
|
|
|
382
473
|
# Return a Method object for the dataset's output_identifier_method.
|
|
383
474
|
# Used in metadata parsing to make sure the returned information is in the
|
|
384
475
|
# correct format.
|
|
385
|
-
def output_identifier_meth
|
|
386
|
-
dataset.method(:output_identifier)
|
|
476
|
+
def output_identifier_meth(ds=nil)
|
|
477
|
+
(ds || dataset).method(:output_identifier)
|
|
387
478
|
end
|
|
388
479
|
|
|
389
|
-
# SQL to ROLLBACK a transaction.
|
|
390
|
-
def rollback_transaction_sql
|
|
391
|
-
SQL_ROLLBACK
|
|
392
|
-
end
|
|
393
|
-
|
|
394
480
|
# Remove the cached schema for the given schema name
|
|
395
481
|
def remove_cached_schema(table)
|
|
396
482
|
@schemas.delete(quote_schema_table(table)) if @schemas
|
|
397
483
|
end
|
|
398
484
|
|
|
399
485
|
# Remove the current thread from the list of active transactions
|
|
400
|
-
def remove_transaction(conn)
|
|
401
|
-
|
|
402
|
-
|
|
486
|
+
def remove_transaction(conn, committed)
|
|
487
|
+
if !supports_savepoints? || ((@transactions[conn][:savepoint_level] -= 1) <= 0)
|
|
488
|
+
begin
|
|
489
|
+
if committed
|
|
490
|
+
after_transaction_commit(conn)
|
|
491
|
+
else
|
|
492
|
+
after_transaction_rollback(conn)
|
|
493
|
+
end
|
|
494
|
+
ensure
|
|
495
|
+
@transactions.delete(conn)
|
|
496
|
+
end
|
|
497
|
+
end
|
|
403
498
|
end
|
|
404
499
|
|
|
405
500
|
# SQL to rollback to a savepoint
|
|
@@ -410,13 +505,18 @@ module Sequel
|
|
|
410
505
|
# Rollback the active transaction on the connection
|
|
411
506
|
def rollback_transaction(conn, opts={})
|
|
412
507
|
if supports_savepoints?
|
|
413
|
-
depth =
|
|
508
|
+
depth = @transactions[conn][:savepoint_level]
|
|
414
509
|
log_connection_execute(conn, depth > 1 ? rollback_savepoint_sql(depth-1) : rollback_transaction_sql)
|
|
415
510
|
else
|
|
416
511
|
log_connection_execute(conn, rollback_transaction_sql)
|
|
417
512
|
end
|
|
418
513
|
end
|
|
419
514
|
|
|
515
|
+
# SQL to ROLLBACK a transaction.
|
|
516
|
+
def rollback_transaction_sql
|
|
517
|
+
SQL_ROLLBACK
|
|
518
|
+
end
|
|
519
|
+
|
|
420
520
|
# Match the database's column type to a ruby type via a
|
|
421
521
|
# regular expression, and return the ruby type as a symbol
|
|
422
522
|
# such as :integer or :string.
|
|
@@ -434,13 +534,13 @@ module Sequel
|
|
|
434
534
|
:datetime
|
|
435
535
|
when /\Atime( with(out)? time zone)?\z/io
|
|
436
536
|
:time
|
|
437
|
-
when /\A(
|
|
537
|
+
when /\A(bool(ean)?)\z/io
|
|
438
538
|
:boolean
|
|
439
539
|
when /\A(real|float|double( precision)?)\z/io
|
|
440
540
|
:float
|
|
441
|
-
when /\A(?:(?:(?:num(?:ber|eric)?|decimal)(?:\(\d+,\s*(\d
|
|
442
|
-
$1 &&
|
|
443
|
-
when /bytea|
|
|
541
|
+
when /\A(?:(?:(?:num(?:ber|eric)?|decimal)(?:\(\d+,\s*(\d+|false|true)\))?)|(?:small)?money)\z/io
|
|
542
|
+
$1 && ['0', 'false'].include?($1) ? :integer : :decimal
|
|
543
|
+
when /bytea|[bc]lob|image|(var)?binary/io
|
|
444
544
|
:blob
|
|
445
545
|
when /\Aenum/io
|
|
446
546
|
:enum
|
|
@@ -460,8 +560,12 @@ module Sequel
|
|
|
460
560
|
end
|
|
461
561
|
|
|
462
562
|
# Raise a database error unless the exception is an Rollback.
|
|
463
|
-
def transaction_error(e)
|
|
464
|
-
|
|
563
|
+
def transaction_error(e, opts={})
|
|
564
|
+
if e.is_a?(Rollback)
|
|
565
|
+
raise e if opts[:rollback] == :reraise
|
|
566
|
+
else
|
|
567
|
+
raise_error(e, opts.merge(:classes=>database_error_classes))
|
|
568
|
+
end
|
|
465
569
|
end
|
|
466
570
|
end
|
|
467
571
|
end
|
|
@@ -86,7 +86,8 @@ module Sequel
|
|
|
86
86
|
# :index :: Create an index on this column.
|
|
87
87
|
# :key :: For foreign key columns, the column in the associated table
|
|
88
88
|
# that this column references. Unnecessary if this column
|
|
89
|
-
# references the primary key of the associated table
|
|
89
|
+
# references the primary key of the associated table, except if you are
|
|
90
|
+
# using MySQL.
|
|
90
91
|
# :null :: Mark the column as allowing NULL values (if true),
|
|
91
92
|
# or not allowing NULL values (if false). If unspecified, will default
|
|
92
93
|
# to whatever the database default is.
|
|
@@ -124,6 +125,13 @@ module Sequel
|
|
|
124
125
|
# foreign_key(:artist_id) # artist_id INTEGER
|
|
125
126
|
# foreign_key(:artist_id, :artists) # artist_id INTEGER REFERENCES artists
|
|
126
127
|
# foreign_key(:artist_id, :artists, :key=>:id) # artist_id INTEGER REFERENCES artists(id)
|
|
128
|
+
#
|
|
129
|
+
# If you want a foreign key constraint without adding a column (usually because it is a
|
|
130
|
+
# composite foreign key), you can provide an array of columns as the first argument, and
|
|
131
|
+
# you can provide the :name option to name the constraint:
|
|
132
|
+
#
|
|
133
|
+
# foreign_key([:artist_name, :artist_location], :artists, :name=>:artist_fk)
|
|
134
|
+
# # ADD CONSTRAINT artist_fk FOREIGN KEY (artist_name, artist_location) REFERENCES artists
|
|
127
135
|
def foreign_key(name, table=nil, opts = {})
|
|
128
136
|
opts = case table
|
|
129
137
|
when Hash
|
|
@@ -281,8 +289,8 @@ module Sequel
|
|
|
281
289
|
# to the DDL for the table. See Generator#column for the available options.
|
|
282
290
|
#
|
|
283
291
|
# You can also pass an array of column names for creating composite foreign
|
|
284
|
-
# keys. In this case, it will assume the columns
|
|
285
|
-
# the constraint.
|
|
292
|
+
# keys. In this case, it will assume the columns exist and will only add
|
|
293
|
+
# the constraint. You can provide a :name option to name the constraint.
|
|
286
294
|
#
|
|
287
295
|
# NOTE: If you need to add a foreign key constraint to a single existing column
|
|
288
296
|
# use the composite key syntax even if it is only one column.
|
|
@@ -329,15 +337,17 @@ module Sequel
|
|
|
329
337
|
# Remove a column from the DDL for the table.
|
|
330
338
|
#
|
|
331
339
|
# drop_column(:artist_id) # DROP COLUMN artist_id
|
|
332
|
-
|
|
333
|
-
|
|
340
|
+
# drop_column(:artist_id, :cascade=>true) # DROP COLUMN artist_id CASCADE
|
|
341
|
+
def drop_column(name, opts={})
|
|
342
|
+
@operations << {:op => :drop_column, :name => name}.merge(opts)
|
|
334
343
|
end
|
|
335
344
|
|
|
336
345
|
# Remove a constraint from the DDL for the table.
|
|
337
346
|
#
|
|
338
347
|
# drop_constraint(:unique_name) # DROP CONSTRAINT unique_name
|
|
339
|
-
|
|
340
|
-
|
|
348
|
+
# drop_constraint(:unique_name, :cascade=>true) # DROP CONSTRAINT unique_name CASCADE
|
|
349
|
+
def drop_constraint(name, opts={})
|
|
350
|
+
@operations << {:op => :drop_constraint, :name => name}.merge(opts)
|
|
341
351
|
end
|
|
342
352
|
|
|
343
353
|
# Remove an index from the DDL for the table.
|