sequel 4.38.0 → 4.39.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +28 -0
- data/doc/association_basics.rdoc +1 -1
- data/doc/core_extensions.rdoc +8 -8
- data/doc/object_model.rdoc +7 -8
- data/doc/querying.rdoc +2 -2
- data/doc/release_notes/4.39.0.txt +127 -0
- data/doc/sql.rdoc +31 -31
- data/doc/transactions.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/mock.rb +22 -66
- data/lib/sequel/adapters/shared/access.rb +2 -0
- data/lib/sequel/adapters/shared/cubrid.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +2 -0
- data/lib/sequel/adapters/shared/firebird.rb +2 -0
- data/lib/sequel/adapters/shared/informix.rb +2 -0
- data/lib/sequel/adapters/shared/mssql.rb +10 -2
- data/lib/sequel/adapters/shared/mysql.rb +17 -4
- data/lib/sequel/adapters/shared/oracle.rb +9 -0
- data/lib/sequel/adapters/shared/postgres.rb +34 -1
- data/lib/sequel/adapters/shared/sqlanywhere.rb +1 -0
- data/lib/sequel/adapters/shared/sqlite.rb +8 -0
- data/lib/sequel/core.rb +10 -0
- data/lib/sequel/database.rb +5 -0
- data/lib/sequel/database/connecting.rb +28 -0
- data/lib/sequel/database/misc.rb +0 -51
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +9 -0
- data/lib/sequel/database/transactions.rb +65 -0
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/core_extensions.rb +1 -1
- data/lib/sequel/extensions/core_refinements.rb +1 -1
- data/lib/sequel/extensions/migration.rb +17 -1
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pg_array_ops.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +1 -1
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +28 -15
- data/lib/sequel/extensions/pg_range_ops.rb +1 -1
- data/lib/sequel/extensions/pg_row_ops.rb +1 -1
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/extensions/sql_expr.rb +1 -1
- data/lib/sequel/model/associations.rb +1 -1
- data/lib/sequel/plugins/active_model.rb +19 -8
- data/lib/sequel/plugins/dataset_associations.rb +1 -1
- data/lib/sequel/plugins/hook_class_methods.rb +38 -2
- data/lib/sequel/plugins/list.rb +1 -1
- data/lib/sequel/plugins/pg_array_associations.rb +3 -3
- data/lib/sequel/plugins/timestamps.rb +15 -2
- data/lib/sequel/plugins/touch.rb +6 -0
- data/lib/sequel/sql.rb +15 -11
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +18 -0
- data/spec/adapters/postgres_spec.rb +30 -1
- data/spec/core/database_spec.rb +29 -0
- data/spec/core/mock_adapter_spec.rb +32 -1
- data/spec/extensions/migration_spec.rb +46 -0
- data/spec/extensions/pg_interval_spec.rb +1 -0
- data/spec/extensions/pg_json_ops_spec.rb +13 -0
- data/spec/extensions/timestamps_spec.rb +11 -0
- data/spec/extensions/touch_spec.rb +8 -0
- metadata +4 -2
@@ -88,7 +88,7 @@ module Sequel
|
|
88
88
|
# :schema :: An explicit schema to use. It may also be implicitly provided
|
89
89
|
# via the table name.
|
90
90
|
#
|
91
|
-
# If schema parsing is supported by the database, the column information should
|
91
|
+
# If schema parsing is supported by the database, the column information hash should contain at least the
|
92
92
|
# following entries:
|
93
93
|
#
|
94
94
|
# :allow_null :: Whether NULL is an allowed value for the column.
|
@@ -336,6 +336,15 @@ module Sequel
|
|
336
336
|
# See CreateTableGenerator#column for the available options.
|
337
337
|
#
|
338
338
|
# add_column(:name, String) # ADD COLUMN name varchar(255)
|
339
|
+
#
|
340
|
+
# PostgreSQL specific options:
|
341
|
+
#
|
342
|
+
# :if_not_exists :: Set to true to not add the column if it already exists (PostgreSQL 9.6+)
|
343
|
+
#
|
344
|
+
# MySQL specific options:
|
345
|
+
#
|
346
|
+
# :after :: The name of an existing column that the new column should be positioned after
|
347
|
+
# :first :: Create this new column before all other existing columns
|
339
348
|
def add_column(name, type, opts = OPTS)
|
340
349
|
@operations << {:op => :add_column, :name => name, :type => type}.merge!(opts)
|
341
350
|
end
|
@@ -32,6 +32,58 @@ module Sequel
|
|
32
32
|
# on the same connection.
|
33
33
|
attr_accessor :transaction_isolation_level
|
34
34
|
|
35
|
+
# If a transaction is not currently in process, yield to the block immediately.
|
36
|
+
# Otherwise, add the block to the list of blocks to call after the currently
|
37
|
+
# in progress transaction commits (and only if it commits).
|
38
|
+
# Options:
|
39
|
+
# :server :: The server/shard to use.
|
40
|
+
def after_commit(opts=OPTS, &block)
|
41
|
+
raise Error, "must provide block to after_commit" unless block
|
42
|
+
synchronize(opts[:server]) do |conn|
|
43
|
+
if h = _trans(conn)
|
44
|
+
raise Error, "cannot call after_commit in a prepared transaction" if h[:prepare]
|
45
|
+
add_transaction_hook(conn, :after_commit, block)
|
46
|
+
else
|
47
|
+
yield
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# If a transaction is not currently in progress, ignore the block.
|
53
|
+
# Otherwise, add the block to the list of the blocks to call after the currently
|
54
|
+
# in progress transaction rolls back (and only if it rolls back).
|
55
|
+
# Options:
|
56
|
+
# :server :: The server/shard to use.
|
57
|
+
def after_rollback(opts=OPTS, &block)
|
58
|
+
raise Error, "must provide block to after_rollback" unless block
|
59
|
+
synchronize(opts[:server]) do |conn|
|
60
|
+
if h = _trans(conn)
|
61
|
+
raise Error, "cannot call after_rollback in a prepared transaction" if h[:prepare]
|
62
|
+
add_transaction_hook(conn, :after_rollback, block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return true if already in a transaction given the options,
|
68
|
+
# false otherwise. Respects the :server option for selecting
|
69
|
+
# a shard.
|
70
|
+
def in_transaction?(opts=OPTS)
|
71
|
+
synchronize(opts[:server]){|conn| !!_trans(conn)}
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a proc that you can call to check if the transaction
|
75
|
+
# has been rolled back. The proc will return nil if the
|
76
|
+
# transaction is still in progress, true if the transaction was
|
77
|
+
# rolled back, and false if it was committed. Raises an
|
78
|
+
# Error if called outside a transaction. Respects the :server
|
79
|
+
# option for selecting a shard.
|
80
|
+
def rollback_checker(opts=OPTS)
|
81
|
+
synchronize(opts[:server]) do |conn|
|
82
|
+
raise Error, "not in a transaction" unless t = _trans(conn)
|
83
|
+
t[:rollback_checker] ||= proc{t[:rolled_back]}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
35
87
|
# Starts a database transaction. When a database transaction is used,
|
36
88
|
# either all statements are successful or none of the statements are
|
37
89
|
# successful. Note that MySQL MyISAM tables do not support transactions.
|
@@ -215,6 +267,13 @@ module Sequel
|
|
215
267
|
Sequel.synchronize{@transactions[conn] = hash}
|
216
268
|
end
|
217
269
|
|
270
|
+
# Set the given callable as a hook to be called. Type should be either
|
271
|
+
# :after_commit or :after_rollback.
|
272
|
+
def add_transaction_hook(conn, type, block)
|
273
|
+
hooks = _trans(conn)[type] ||= []
|
274
|
+
hooks << block
|
275
|
+
end
|
276
|
+
|
218
277
|
# Whether the current thread/connection is already inside a transaction
|
219
278
|
def already_in_transaction?(conn, opts)
|
220
279
|
_trans(conn) && (!supports_savepoints? || !opts[:savepoint])
|
@@ -305,6 +364,11 @@ module Sequel
|
|
305
364
|
:execute
|
306
365
|
end
|
307
366
|
|
367
|
+
# Which transaction errors to translate, blank by default.
|
368
|
+
def database_error_classes
|
369
|
+
[]
|
370
|
+
end
|
371
|
+
|
308
372
|
# Retrieve the transaction hooks that should be run for the given
|
309
373
|
# connection and commit status.
|
310
374
|
def transaction_hooks(conn, committed)
|
@@ -318,6 +382,7 @@ module Sequel
|
|
318
382
|
callbacks = transaction_hooks(conn, committed)
|
319
383
|
|
320
384
|
if transaction_finished?(conn)
|
385
|
+
@transactions[conn][:rolled_back] = !committed
|
321
386
|
Sequel.synchronize{@transactions.delete(conn)}
|
322
387
|
end
|
323
388
|
|
@@ -817,7 +817,7 @@ module Sequel
|
|
817
817
|
# DB[:table].update(:x=>nil) # UPDATE table SET x = NULL
|
818
818
|
# # => 10
|
819
819
|
#
|
820
|
-
# DB[:table].update(:x=>Sequel
|
820
|
+
# DB[:table].update(:x=>Sequel[:x]+1, :y=>0) # UPDATE table SET x = (x + 1), y = 0
|
821
821
|
# # => 10
|
822
822
|
def update(values=OPTS, &block)
|
823
823
|
sql = update_sql(values)
|
@@ -444,7 +444,7 @@ module Sequel
|
|
444
444
|
# for all columns unless the :allow_nil option is given.
|
445
445
|
def generator_add_constraint_from_validation(generator, val, cons)
|
446
446
|
if val[:allow_nil]
|
447
|
-
nil_cons = Sequel
|
447
|
+
nil_cons = Sequel[val[:columns].map{|c| [c, nil]}]
|
448
448
|
cons = Sequel.|(nil_cons, cons) if cons
|
449
449
|
else
|
450
450
|
nil_cons = Sequel.negate(val[:columns].map{|c| [c, nil]})
|
@@ -58,7 +58,7 @@ class Array
|
|
58
58
|
# [[:a, true]].sql_expr # SQL: a IS TRUE
|
59
59
|
# [[:a, 1], [:b, [2, 3]]].sql_expr # SQL: a = 1 AND b IN (2, 3)
|
60
60
|
def sql_expr
|
61
|
-
Sequel
|
61
|
+
Sequel[self]
|
62
62
|
end
|
63
63
|
|
64
64
|
# Return a <tt>Sequel::SQL::BooleanExpression</tt> created from this array, matching none
|
@@ -55,7 +55,7 @@ module Sequel::CoreRefinements
|
|
55
55
|
# [[:a, true]].sql_expr # SQL: a IS TRUE
|
56
56
|
# [[:a, 1], [:b, [2, 3]]].sql_expr # SQL: a = 1 AND b IN (2, 3)
|
57
57
|
def sql_expr
|
58
|
-
Sequel
|
58
|
+
Sequel[self]
|
59
59
|
end
|
60
60
|
|
61
61
|
# Return a <tt>Sequel::SQL::BooleanExpression</tt> created from this array, matching none
|
@@ -387,6 +387,8 @@ module Sequel
|
|
387
387
|
# :column :: The column in the :table argument storing the migration version (default: :version).
|
388
388
|
# :current :: The current version of the database. If not given, it is retrieved from the database
|
389
389
|
# using the :table and :column options.
|
390
|
+
# :relative :: Run the given number of migrations, with a positive number being migrations to migrate
|
391
|
+
# up, and a negative number being migrations to migrate down (IntegerMigrator only).
|
390
392
|
# :table :: The table containing the schema version (default: :schema_info).
|
391
393
|
# :target :: The target version to which to migrate. If not given, migrates to the maximum version.
|
392
394
|
#
|
@@ -520,8 +522,22 @@ module Sequel
|
|
520
522
|
# Set up all state for the migrator instance
|
521
523
|
def initialize(db, directory, opts=OPTS)
|
522
524
|
super
|
523
|
-
@target = opts[:target] || latest_migration_version
|
524
525
|
@current = opts[:current] || current_migration_version
|
526
|
+
latest_version = latest_migration_version
|
527
|
+
|
528
|
+
@target = if opts[:target]
|
529
|
+
opts[:target]
|
530
|
+
elsif opts[:relative]
|
531
|
+
@current + opts[:relative]
|
532
|
+
else
|
533
|
+
latest_version
|
534
|
+
end
|
535
|
+
|
536
|
+
if @target > latest_version
|
537
|
+
@target = latest_version
|
538
|
+
elsif @target < 0
|
539
|
+
@target = 0
|
540
|
+
end
|
525
541
|
|
526
542
|
raise(Error, "No current version available") unless current
|
527
543
|
raise(Error, "No target version available, probably because no migration files found or filenames don't follow the migration filename convention") unless target
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# Also, on most Sequel expression objects, you can call the pg_array
|
20
20
|
# method:
|
21
21
|
#
|
22
|
-
# ia = Sequel
|
22
|
+
# ia = Sequel[:int_array_column].pg_array
|
23
23
|
#
|
24
24
|
# If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
25
25
|
# or you have loaded the core_refinements extension
|
@@ -20,7 +20,7 @@
|
|
20
20
|
# Also, on most Sequel expression objects, you can call the hstore
|
21
21
|
# method:
|
22
22
|
#
|
23
|
-
# h = Sequel
|
23
|
+
# h = Sequel[:hstore_column].hstore
|
24
24
|
#
|
25
25
|
# If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
26
26
|
# or you have loaded the core_refinements extension
|
@@ -14,7 +14,7 @@
|
|
14
14
|
# Also, on most Sequel expression objects, you can call the pg_inet
|
15
15
|
# method:
|
16
16
|
#
|
17
|
-
# r = Sequel
|
17
|
+
# r = Sequel[:ip].pg_inet
|
18
18
|
#
|
19
19
|
# If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
20
20
|
# or you have loaded the core_refinements extension
|
@@ -42,7 +42,7 @@ module Sequel
|
|
42
42
|
module Postgres
|
43
43
|
module IntervalDatabaseMethods
|
44
44
|
EMPTY_INTERVAL = '0'.freeze
|
45
|
-
DURATION_UNITS = [:years, :months, :days, :minutes, :seconds].freeze
|
45
|
+
DURATION_UNITS = [:years, :months, :weeks, :days, :hours, :minutes, :seconds].freeze
|
46
46
|
|
47
47
|
# Return an unquoted string version of the duration object suitable for
|
48
48
|
# use as a bound variable.
|
@@ -24,8 +24,8 @@
|
|
24
24
|
# Also, on most Sequel expression objects, you can call the pg_json
|
25
25
|
# or pg_jsonb # method:
|
26
26
|
#
|
27
|
-
# j = Sequel
|
28
|
-
# jb = Sequel
|
27
|
+
# j = Sequel[:json_column].pg_json
|
28
|
+
# jb = Sequel[:jsonb_column].pg_jsonb
|
29
29
|
#
|
30
30
|
# If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
31
31
|
# or you have loaded the core_refinements extension
|
@@ -61,16 +61,17 @@
|
|
61
61
|
#
|
62
62
|
# There are additional methods are are only supported on JSONBOp instances:
|
63
63
|
#
|
64
|
-
# j - 1
|
65
|
-
# j.concat(:h)
|
66
|
-
# j.contain_all(:a)
|
67
|
-
# j.contain_any(:a)
|
68
|
-
# j.contains(:h)
|
69
|
-
# j.contained_by(:h)
|
70
|
-
# j.delete_path(%w'0 a')
|
71
|
-
# j.has_key?('a')
|
72
|
-
# j.
|
73
|
-
# j.
|
64
|
+
# j - 1 # (jsonb_column - 1)
|
65
|
+
# j.concat(:h) # (jsonb_column || h)
|
66
|
+
# j.contain_all(:a) # (jsonb_column ?& a)
|
67
|
+
# j.contain_any(:a) # (jsonb_column ?| a)
|
68
|
+
# j.contains(:h) # (jsonb_column @> h)
|
69
|
+
# j.contained_by(:h) # (jsonb_column <@ h)
|
70
|
+
# j.delete_path(%w'0 a') # (jsonb_column #- ARRAY['0','a'])
|
71
|
+
# j.has_key?('a') # (jsonb_column ? 'a')
|
72
|
+
# j.insert(%w'0 a', 'a'=>1) # jsonb_insert(jsonb_column, ARRAY[0, 'a'], '{"a":1}'::jsonb, false)
|
73
|
+
# j.pretty # jsonb_pretty(jsonb_column)
|
74
|
+
# j.set(%w'0 a', :h) # jsonb_set(jsonb_column, ARRAY['0','a'], h, true)
|
74
75
|
#
|
75
76
|
# If you are also using the pg_json extension, you should load it before
|
76
77
|
# loading this extension. Doing so will allow you to use the #op method on
|
@@ -336,7 +337,7 @@ module Sequel
|
|
336
337
|
bool_op(CONTAINED_BY, wrap_input_jsonb(other))
|
337
338
|
end
|
338
339
|
|
339
|
-
#
|
340
|
+
# Removes the given path from the receiver.
|
340
341
|
#
|
341
342
|
# jsonb_op.delete_path(:h) # (jsonb #- h)
|
342
343
|
def delete_path(other)
|
@@ -351,19 +352,31 @@ module Sequel
|
|
351
352
|
end
|
352
353
|
alias include? has_key?
|
353
354
|
|
355
|
+
# Inserts the given jsonb value at the given path in the receiver.
|
356
|
+
# The default is to insert the value before the given path, but
|
357
|
+
# insert_after can be set to true to insert it after the given path.
|
358
|
+
#
|
359
|
+
# jsonb_op.insert(['a', 'b'], h) # jsonb_insert(jsonb, ARRAY['a', 'b'], h, false)
|
360
|
+
# jsonb_op.insert(['a', 'b'], h, true) # jsonb_insert(jsonb, ARRAY['a', 'b'], h, true)
|
361
|
+
def insert(path, other, insert_after=false)
|
362
|
+
self.class.new(function(:insert, wrap_input_array(path), wrap_input_jsonb(other), insert_after))
|
363
|
+
end
|
364
|
+
|
354
365
|
# Return the receiver, since it is already a JSONBOp.
|
355
366
|
def pg_jsonb
|
356
367
|
self
|
357
368
|
end
|
358
369
|
|
359
|
-
#
|
370
|
+
# Return a pretty printed version of the receiver as a string expression.
|
360
371
|
#
|
361
372
|
# jsonb_op.pretty # jsonb_pretty(jsonb)
|
362
373
|
def pretty
|
363
374
|
Sequel::SQL::StringExpression.new(:NOOP, function(:pretty))
|
364
375
|
end
|
365
376
|
|
366
|
-
#
|
377
|
+
# Set the given jsonb value at the given path in the receiver.
|
378
|
+
# By default, this will create the value if it does not exist, but
|
379
|
+
# create_missing can be set to false to not create a new value.
|
367
380
|
#
|
368
381
|
# jsonb_op.set(['a', 'b'], h) # jsonb_set(jsonb, ARRAY['a', 'b'], h, true)
|
369
382
|
# jsonb_op.set(['a', 'b'], h, false) # jsonb_set(jsonb, ARRAY['a', 'b'], h, false)
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# Also, on most Sequel expression objects, you can call the pg_range
|
20
20
|
# method:
|
21
21
|
#
|
22
|
-
# r = Sequel
|
22
|
+
# r = Sequel[:range].pg_range
|
23
23
|
#
|
24
24
|
# If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
25
25
|
# or you have loaded the core_refinements extension
|
@@ -19,7 +19,7 @@
|
|
19
19
|
# Also, on most Sequel expression objects, you can call the pg_row
|
20
20
|
# method:
|
21
21
|
#
|
22
|
-
# r = Sequel
|
22
|
+
# r = Sequel[:row_column].pg_row
|
23
23
|
#
|
24
24
|
# If you have loaded the {core_extensions extension}[rdoc-ref:doc/core_extensions.rdoc],
|
25
25
|
# or you have loaded the core_refinements extension
|
@@ -35,7 +35,7 @@ module Sequel
|
|
35
35
|
# In this case, the code will currently use unqualified column names for all columns
|
36
36
|
# the dataset returns, except for the columns given.
|
37
37
|
# * This dataset has an existing explicit selection containing an item that returns
|
38
|
-
# multiple database columns (e.g. Sequel
|
38
|
+
# multiple database columns (e.g. Sequel[:table].*, Sequel.lit('column1, column2')). In this case,
|
39
39
|
# the behavior is undefined and this method should not be used.
|
40
40
|
#
|
41
41
|
# There may be other cases where this method does not work correctly, use it with caution.
|
@@ -2792,7 +2792,7 @@ END
|
|
2792
2792
|
# included by the association's conditions.
|
2793
2793
|
def add_association_filter_conditions(ref, obj, expr)
|
2794
2794
|
if expr != SQL::Constants::FALSE && ref.filter_by_associations_add_conditions?
|
2795
|
-
Sequel
|
2795
|
+
Sequel[ref.filter_by_associations_conditions_expression(obj)]
|
2796
2796
|
else
|
2797
2797
|
expr
|
2798
2798
|
end
|
@@ -46,13 +46,6 @@ module Sequel
|
|
46
46
|
@destroyed = true
|
47
47
|
end
|
48
48
|
|
49
|
-
# Mark current instance as destroyed if the transaction in which this
|
50
|
-
# instance is created is rolled back.
|
51
|
-
def before_create
|
52
|
-
db.after_rollback{@destroyed = true}
|
53
|
-
super
|
54
|
-
end
|
55
|
-
|
56
49
|
# Return ::ActiveModel::Name instance for the class.
|
57
50
|
def model_name
|
58
51
|
model.model_name
|
@@ -60,7 +53,16 @@ module Sequel
|
|
60
53
|
|
61
54
|
# False if the object is new? or has been destroyed, true otherwise.
|
62
55
|
def persisted?
|
63
|
-
|
56
|
+
return false if new?
|
57
|
+
return false if defined?(@destroyed)
|
58
|
+
|
59
|
+
if defined?(@rollback_checker)
|
60
|
+
if @rollback_checker.call
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
true
|
64
66
|
end
|
65
67
|
|
66
68
|
# An array of primary key values, or nil if the object is not persisted.
|
@@ -93,6 +95,15 @@ module Sequel
|
|
93
95
|
|
94
96
|
private
|
95
97
|
|
98
|
+
# For new objects, add a rollback checker to check if the transaction
|
99
|
+
# in which this instance is created is rolled back.
|
100
|
+
def _save(opts)
|
101
|
+
if new? && db.in_transaction?(opts)
|
102
|
+
@rollback_checker = db.rollback_checker(opts)
|
103
|
+
end
|
104
|
+
super
|
105
|
+
end
|
106
|
+
|
96
107
|
# Use ActiveModel compliant errors class.
|
97
108
|
def errors_class
|
98
109
|
Errors
|
@@ -103,7 +103,7 @@ module Sequel
|
|
103
103
|
edges.each{|e| mds = mds.join(e[:table], Array(e[:right]).zip(Array(e[:left])))}
|
104
104
|
ds.filter(r.qualified_right_primary_key=>r.send(:apply_filter_by_associations_limit_strategy, mds))
|
105
105
|
when :pg_array_to_many
|
106
|
-
ds.filter(Sequel
|
106
|
+
ds.filter(Sequel[r.primary_key=>sds.select{Sequel.pg_array_op(r.qualify(r[:model].table_name, r[:key])).unnest}])
|
107
107
|
when :many_to_pg_array
|
108
108
|
ds.filter(Sequel.function(:coalesce, Sequel.pg_array_op(r[:key]).overlaps(sds.select{array_agg(r.qualify(r[:model].table_name, r.primary_key))}), false))
|
109
109
|
else
|
@@ -119,8 +119,44 @@ module Sequel
|
|
119
119
|
end
|
120
120
|
|
121
121
|
module InstanceMethods
|
122
|
-
Model::BEFORE_HOOKS.each{|h| class_eval("def #{h}; model.hook_blocks(:#{h}){|b| return false if instance_eval(&b) == false}; super; end", __FILE__, __LINE__)}
|
123
|
-
Model::AFTER_HOOKS.each{|h| class_eval("def #{h}; super; model.hook_blocks(:#{h}){|b| instance_eval(&b)}; end", __FILE__, __LINE__)}
|
122
|
+
(Model::BEFORE_HOOKS - [:before_save, :before_destroy]).each{|h| class_eval("def #{h}; model.hook_blocks(:#{h}){|b| return false if instance_eval(&b) == false}; super; end", __FILE__, __LINE__)}
|
123
|
+
(Model::AFTER_HOOKS - [:after_save, :after_destroy, :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback]).each{|h| class_eval("def #{h}; super; model.hook_blocks(:#{h}){|b| instance_eval(&b)}; end", __FILE__, __LINE__)}
|
124
|
+
|
125
|
+
def after_destroy
|
126
|
+
super
|
127
|
+
model.hook_blocks(:after_destroy){|b| instance_eval(&b)}
|
128
|
+
if model.has_hooks?(:after_destroy_commit)
|
129
|
+
db.after_rollback{model.hook_blocks(:after_destroy_commit){|b| instance_eval(&b)}}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def after_save
|
134
|
+
super
|
135
|
+
model.hook_blocks(:after_save){|b| instance_eval(&b)}
|
136
|
+
if model.has_hooks?(:after_commit)
|
137
|
+
db.after_rollback{model.hook_blocks(:after_commit){|b| instance_eval(&b)}}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def before_destroy
|
142
|
+
model.hook_blocks(:before_destroy) do |b|
|
143
|
+
return false if instance_eval(&b) == false
|
144
|
+
end
|
145
|
+
super
|
146
|
+
if model.has_hooks?(:after_destroy_rollback)
|
147
|
+
db.after_rollback{model.hook_blocks(:after_destroy_rollback){|b| instance_eval(&b)}}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def before_save
|
152
|
+
model.hook_blocks(:before_save) do |b|
|
153
|
+
return false if instance_eval(&b) == false
|
154
|
+
end
|
155
|
+
super
|
156
|
+
if model.has_hooks?(:after_rollback)
|
157
|
+
db.after_rollback{model.hook_blocks(:after_rollback){|b| instance_eval(&b)}}
|
158
|
+
end
|
159
|
+
end
|
124
160
|
end
|
125
161
|
end
|
126
162
|
end
|