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
data/lib/sequel/plugins/list.rb
CHANGED
@@ -491,14 +491,14 @@ module Sequel
|
|
491
491
|
expr = case obj
|
492
492
|
when Sequel::Model
|
493
493
|
if (assoc_pks = obj.get_column_value(key)) && !assoc_pks.empty?
|
494
|
-
Sequel
|
494
|
+
Sequel[pk=>assoc_pks.to_a]
|
495
495
|
end
|
496
496
|
when Array
|
497
497
|
if (assoc_pks = obj.map{|o| o.get_column_value(key)}.flatten.compact.uniq) && !assoc_pks.empty?
|
498
|
-
Sequel
|
498
|
+
Sequel[pk=>assoc_pks]
|
499
499
|
end
|
500
500
|
when Sequel::Dataset
|
501
|
-
Sequel
|
501
|
+
Sequel[pk=>obj.select{Sequel.pg_array_op(ref.qualify(obj.model.table_name, ref[:key_column])).unnest}]
|
502
502
|
end
|
503
503
|
expr = Sequel::SQL::Constants::FALSE unless expr
|
504
504
|
expr = add_association_filter_conditions(ref, obj, expr)
|
@@ -24,12 +24,14 @@ module Sequel
|
|
24
24
|
# Configure the plugin by setting the available options. Note that
|
25
25
|
# if this method is run more than once, previous settings are ignored,
|
26
26
|
# and it will just use the settings given or the default settings. Options:
|
27
|
+
# :allow_manual_update :: Whether to skip setting the update timestamp if it has been modified manually (default: false)
|
27
28
|
# :create :: The field to hold the create timestamp (default: :created_at)
|
28
29
|
# :force :: Whether to overwrite an existing create timestamp (default: false)
|
29
30
|
# :update :: The field to hold the update timestamp (default: :updated_at)
|
30
31
|
# :update_on_create :: Whether to set the update timestamp to the create timestamp when creating (default: false)
|
31
32
|
def self.configure(model, opts=OPTS)
|
32
33
|
model.instance_eval do
|
34
|
+
@allow_manual_timestamp_update = opts[:allow_manual_update]||false
|
33
35
|
@create_timestamp_field = opts[:create]||:created_at
|
34
36
|
@update_timestamp_field = opts[:update]||:updated_at
|
35
37
|
@create_timestamp_overwrite = opts[:force]||false
|
@@ -49,9 +51,19 @@ module Sequel
|
|
49
51
|
@create_timestamp_overwrite
|
50
52
|
end
|
51
53
|
|
52
|
-
Plugins.inherited_instance_variables(self,
|
53
|
-
:@
|
54
|
+
Plugins.inherited_instance_variables(self,
|
55
|
+
:@allow_manual_timestamp_update=>nil,
|
56
|
+
:@create_timestamp_field=>nil,
|
57
|
+
:@create_timestamp_overwrite=>nil,
|
58
|
+
:@set_update_timestamp_on_create=>nil,
|
59
|
+
:@update_timestamp_field=>nil)
|
54
60
|
|
61
|
+
|
62
|
+
# Whether to allow manual setting of the update timestamp when creating
|
63
|
+
def allow_manual_timestamp_update?
|
64
|
+
@allow_manual_timestamp_update
|
65
|
+
end
|
66
|
+
|
55
67
|
# Whether to set the update timestamp to the create timestamp when creating
|
56
68
|
def set_update_timestamp_on_create?
|
57
69
|
@set_update_timestamp_on_create
|
@@ -88,6 +100,7 @@ module Sequel
|
|
88
100
|
# Set the update timestamp to the time given or the current time if the
|
89
101
|
# object has a setter method for the update timestamp field.
|
90
102
|
def set_update_timestamp(time=nil)
|
103
|
+
return if model.allow_manual_timestamp_update? && modified?(model.update_timestamp_field)
|
91
104
|
meth = :"#{model.update_timestamp_field}="
|
92
105
|
set_column_value(meth, time||model.dataset.current_datetime) if respond_to?(meth)
|
93
106
|
end
|
data/lib/sequel/plugins/touch.rb
CHANGED
@@ -78,6 +78,12 @@ module Sequel
|
|
78
78
|
end
|
79
79
|
|
80
80
|
module InstanceMethods
|
81
|
+
# Touch all of the model's touched_associations when creating the object.
|
82
|
+
def after_create
|
83
|
+
super
|
84
|
+
touch_associations
|
85
|
+
end
|
86
|
+
|
81
87
|
# Touch all of the model's touched_associations when destroying the object.
|
82
88
|
def after_destroy
|
83
89
|
super
|
data/lib/sequel/sql.rb
CHANGED
@@ -465,6 +465,10 @@ module Sequel
|
|
465
465
|
# to construct via other methods. For example:
|
466
466
|
#
|
467
467
|
# Sequel.expr(1) - :a # SQL: (1 - a)
|
468
|
+
#
|
469
|
+
# On the Sequel module, this is aliased as #[], for easier use:
|
470
|
+
#
|
471
|
+
# Sequel[1] - :a # SQL: (1 - a)
|
468
472
|
def expr(arg=(no_arg=true), &block)
|
469
473
|
if block_given?
|
470
474
|
if no_arg
|
@@ -793,7 +797,7 @@ module Sequel
|
|
793
797
|
# If the argument given is Numeric, treat it as a NumericExpression,
|
794
798
|
# allowing code such as:
|
795
799
|
#
|
796
|
-
# 1 + Sequel
|
800
|
+
# 1 + Sequel[:x] # SQL: (1 + x)
|
797
801
|
# Sequel.expr{1 - x(y)} # SQL: (1 - x(y))
|
798
802
|
def coerce(other)
|
799
803
|
if other.is_a?(Numeric)
|
@@ -822,17 +826,17 @@ module Sequel
|
|
822
826
|
# return when using a hash with a single entry, where the receiver was the key
|
823
827
|
# and the argument was the value. Example:
|
824
828
|
#
|
825
|
-
# Sequel
|
826
|
-
# Sequel
|
827
|
-
# Sequel
|
829
|
+
# Sequel[:a] =~ 1 # (a = 1)
|
830
|
+
# Sequel[:a] =~ [1, 2] # (a IN [1, 2])
|
831
|
+
# Sequel[:a] =~ nil # (a IS NULL)
|
828
832
|
#
|
829
833
|
# On Ruby 1.9+, this also adds the !~ method, for easily setting up not equals,
|
830
834
|
# exclusion, and inverse pattern matching. This is the same as as inverting the
|
831
835
|
# result of the =~ method
|
832
836
|
#
|
833
|
-
# Sequel
|
834
|
-
# Sequel
|
835
|
-
# Sequel
|
837
|
+
# Sequel[:a] !~ 1 # (a != 1)
|
838
|
+
# Sequel[:a] !~ [1, 2] # (a NOT IN [1, 2])
|
839
|
+
# Sequel[:a] !~ nil # (a IS NOT NULL)
|
836
840
|
module PatternMatchMethods
|
837
841
|
# Set up an equality, inclusion, or pattern match operation, based on the type
|
838
842
|
# of the argument.
|
@@ -929,7 +933,7 @@ module Sequel
|
|
929
933
|
module QualifyingMethods
|
930
934
|
# If no arguments are given, return an SQL::ColumnAll:
|
931
935
|
#
|
932
|
-
# Sequel
|
936
|
+
# Sequel[:a__b].* # a.b.*
|
933
937
|
def *(ce=(arg=false;nil))
|
934
938
|
if arg == false
|
935
939
|
Sequel::SQL::ColumnAll.new(self)
|
@@ -940,8 +944,8 @@ module Sequel
|
|
940
944
|
|
941
945
|
# Qualify the receiver with the given +qualifier+ (table for column/schema for table).
|
942
946
|
#
|
943
|
-
# Sequel
|
944
|
-
# Sequel
|
947
|
+
# Sequel[:column].qualify(:table) # "table"."column"
|
948
|
+
# Sequel[:table].qualify(:schema) # "schema"."table"
|
945
949
|
# Sequel.qualify(:table, :column).qualify(:schema) # "schema"."table"."column"
|
946
950
|
def qualify(qualifier)
|
947
951
|
QualifiedIdentifier.new(qualifier, self)
|
@@ -1392,7 +1396,7 @@ module Sequel
|
|
1392
1396
|
# Return a new function where the function name will not be quoted even
|
1393
1397
|
# if the database supports quoted functions:
|
1394
1398
|
#
|
1395
|
-
# Sequel
|
1399
|
+
# Sequel[:foo].function.unquoted # foo()
|
1396
1400
|
def unquoted
|
1397
1401
|
with_opts(:quoted=>false)
|
1398
1402
|
end
|
data/lib/sequel/version.rb
CHANGED
@@ -5,7 +5,7 @@ module Sequel
|
|
5
5
|
MAJOR = 4
|
6
6
|
# The minor version of Sequel. Bumped for every non-patch level
|
7
7
|
# release, generally around once a month.
|
8
|
-
MINOR =
|
8
|
+
MINOR = 39
|
9
9
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
10
10
|
# releases that fix regressions from previous versions.
|
11
11
|
TINY = 0
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -515,6 +515,24 @@ describe "A MySQL database" do
|
|
515
515
|
end
|
516
516
|
end
|
517
517
|
|
518
|
+
it "should correctly handle add_column :after option" do
|
519
|
+
@db.create_table(:items){Integer :id; Integer :value}
|
520
|
+
@db.alter_table(:items){add_column :name, String, :after=>:id}
|
521
|
+
@db[:items].columns.must_equal [:id, :name, :value]
|
522
|
+
end
|
523
|
+
|
524
|
+
it "should correctly handle add_column :first option" do
|
525
|
+
@db.create_table(:items){Integer :id; Integer :value}
|
526
|
+
@db.alter_table(:items){add_column :name, String, :first => true}
|
527
|
+
@db[:items].columns.must_equal [:name, :id, :value]
|
528
|
+
end
|
529
|
+
|
530
|
+
it "should correctly handle add_foreign_key :first option" do
|
531
|
+
@db.create_table(:items){primary_key :id; Integer :value}
|
532
|
+
@db.alter_table(:items){add_foreign_key :parent_id, :items, :first => true}
|
533
|
+
@db[:items].columns.must_equal [:parent_id, :id, :value]
|
534
|
+
end
|
535
|
+
|
518
536
|
it "should have rename_column support keep existing options" do
|
519
537
|
@db.create_table(:items){String :id, :null=>false, :default=>'blah'}
|
520
538
|
@db.alter_table(:items){rename_column :id, :nid}
|
@@ -204,6 +204,17 @@ describe "PostgreSQL", 'INSERT ON CONFLICT' do
|
|
204
204
|
@ds.all.must_equal [{:a=>1, :b=>2, :c=>3}]
|
205
205
|
end
|
206
206
|
|
207
|
+
it "Dataset#insert_ignore and insert_conflict should work with multi_insert/import" do
|
208
|
+
@ds.insert(1, 2, 3)
|
209
|
+
@ds.insert_ignore.multi_insert([{:a=>1, :b=>3, :c=>4}])
|
210
|
+
@ds.insert_ignore.import([:a, :b, :c], [[1, 3, 4]])
|
211
|
+
@ds.all.must_equal [{:a=>1, :b=>2, :c=>3}]
|
212
|
+
@ds.insert_conflict(:target=>:a, :update=>{:b=>3}).import([:a, :b, :c], [[1, 3, 4]])
|
213
|
+
@ds.all.must_equal [{:a=>1, :b=>3, :c=>3}]
|
214
|
+
@ds.insert_conflict(:target=>:a, :update=>{:b=>4}).multi_insert([{:a=>1, :b=>5, :c=>6}])
|
215
|
+
@ds.all.must_equal [{:a=>1, :b=>4, :c=>3}]
|
216
|
+
end
|
217
|
+
|
207
218
|
it "Dataset#insert_conflict should handle upserts" do
|
208
219
|
@ds.insert(1, 2, 3)
|
209
220
|
@ds.insert_conflict(:target=>:a, :update=>{:b=>3}).insert(1, 3, 4).must_equal nil
|
@@ -991,6 +1002,11 @@ describe "A PostgreSQL database" do
|
|
991
1002
|
@db[:posts].full_text_search(:title, 'rubinius ruby', :plain=>true).select_order_map(:title).must_equal ['jruby rubinius ruby maglev mri iron', 'ruby jruby maglev mri rubinius iron']
|
992
1003
|
@db[:posts].full_text_search(:title, 'jruby maglev', :plain=>true).select_order_map(:title).must_equal ['jruby rubinius ruby maglev mri iron', 'ruby jruby maglev mri rubinius iron']
|
993
1004
|
|
1005
|
+
if DB.server_version >= 90600
|
1006
|
+
@db[:posts].full_text_search(:title, 'rubinius ruby', :to_tsquery=>:phrase).select_order_map(:title).must_equal ['jruby rubinius ruby maglev mri iron']
|
1007
|
+
@db[:posts].full_text_search(:title, 'jruby maglev', :to_tsquery=>:phrase).select_order_map(:title).must_equal ['ruby jruby maglev mri rubinius iron']
|
1008
|
+
end
|
1009
|
+
|
994
1010
|
@db[:posts].full_text_search(Sequel.function(:to_tsvector, 'simple', :title), 'rails', :tsvector=>true).all.must_equal [{:title=>'ruby rails', :body=>'yowsa'}]
|
995
1011
|
@db[:posts].full_text_search(:title, Sequel.function(:to_tsquery, 'simple', 'rails'), :tsquery=>true).all.must_equal [{:title=>'ruby rails', :body=>'yowsa'}]
|
996
1012
|
proc{@db[:posts].full_text_search(Sequel.function(:to_tsvector, 'simple', :title), 'rubinius ruby', :tsvector=>true, :phrase=>true)}.must_raise(Sequel::Error)
|
@@ -1058,6 +1074,13 @@ describe "A PostgreSQL database" do
|
|
1058
1074
|
@db.create_table!(:posts1){primary_key :a}
|
1059
1075
|
@db.rename_table(:posts1, :posts)
|
1060
1076
|
end
|
1077
|
+
|
1078
|
+
it "should adding a primary key only if it does not already exists" do
|
1079
|
+
@db.create_table(:posts){Integer :a}
|
1080
|
+
@db.alter_table(:posts){add_column :b, Integer}
|
1081
|
+
@db.alter_table(:posts){add_column :b, Integer, :if_not_exists=>true}
|
1082
|
+
proc{@db.alter_table(:posts){add_column :b, Integer}}.must_raise Sequel::DatabaseError
|
1083
|
+
end if DB.server_version >= 90600
|
1061
1084
|
end
|
1062
1085
|
|
1063
1086
|
describe "Postgres::Dataset#import" do
|
@@ -1071,7 +1094,6 @@ describe "Postgres::Dataset#import" do
|
|
1071
1094
|
@db.drop_table?(:test)
|
1072
1095
|
end
|
1073
1096
|
|
1074
|
-
|
1075
1097
|
it "#import should a single insert statement" do
|
1076
1098
|
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
1077
1099
|
check_sqls do
|
@@ -2916,6 +2938,13 @@ describe 'PostgreSQL json type' do
|
|
2916
2938
|
@db.get(jo.set(%w'a', 'f'=>'g')['a']['f']).must_equal 'g'
|
2917
2939
|
end
|
2918
2940
|
|
2941
|
+
if DB.server_version >= 90600 && json_type == :jsonb
|
2942
|
+
@db.get(pg_json.call([3]).op.insert(['0'], {'a'=>2})[0]['a']).must_equal 2
|
2943
|
+
@db.get(pg_json.call([3]).op.insert(['0'], {'a'=>2}, false)[0]['a']).must_equal 2
|
2944
|
+
@db.get(pg_json.call([3]).op.insert(['0'], {'a'=>2}, true)[0]).must_equal 3
|
2945
|
+
@db.get(pg_json.call([3]).op.insert(['0'], {'a'=>2}, true)[1]['a']).must_equal 2
|
2946
|
+
end
|
2947
|
+
|
2919
2948
|
@db.from(jo.keys.as(:k)).select_order_map(:k).must_equal %w'a b'
|
2920
2949
|
@db.from(jo.each).select_order_map(:key).must_equal %w'a b'
|
2921
2950
|
@db.from(jo.each).order(:key).select_map(:value).must_equal [1, {'c'=>2, 'd'=>{'e'=>3}}]
|
data/spec/core/database_spec.rb
CHANGED
@@ -834,6 +834,35 @@ DatabaseTransactionSpecs = shared_description do
|
|
834
834
|
@db.in_transaction?.must_equal false
|
835
835
|
end
|
836
836
|
|
837
|
+
it "should have rollback_checker return a proc which returns whether the transaction was rolled back" do
|
838
|
+
proc{@db.rollback_checker}.must_raise Sequel::Error
|
839
|
+
proc{@db.transaction(:server=>:test){@db.rollback_checker}}.must_raise Sequel::Error
|
840
|
+
|
841
|
+
rbc = nil
|
842
|
+
@db.transaction do
|
843
|
+
rbc = @db.rollback_checker
|
844
|
+
rbc.call.must_equal nil
|
845
|
+
end
|
846
|
+
rbc.call.must_equal false
|
847
|
+
|
848
|
+
@db.transaction(:rollback=>:always) do
|
849
|
+
rbc = @db.rollback_checker
|
850
|
+
rbc.call.must_equal nil
|
851
|
+
end
|
852
|
+
rbc.call.must_equal true
|
853
|
+
|
854
|
+
proc do
|
855
|
+
@db.transaction do
|
856
|
+
rbc = @db.rollback_checker
|
857
|
+
raise
|
858
|
+
end
|
859
|
+
end.must_raise RuntimeError
|
860
|
+
rbc.call.must_equal true
|
861
|
+
|
862
|
+
@db.transaction(:server=>:test){rbc = @db.rollback_checker(:server=>:test)}
|
863
|
+
rbc.call.must_equal false
|
864
|
+
end
|
865
|
+
|
837
866
|
it "should return nil if Sequel::Rollback is called in the transaction" do
|
838
867
|
@db.transaction{raise Sequel::Rollback}.must_equal nil
|
839
868
|
end
|
@@ -7,6 +7,37 @@ describe "Sequel Mock Adapter" do
|
|
7
7
|
db.adapter_scheme.must_equal :mock
|
8
8
|
end
|
9
9
|
|
10
|
+
it "should support registering mock adapter type" do
|
11
|
+
begin
|
12
|
+
mod = Module.new do
|
13
|
+
Sequel::Database.set_shared_adapter_scheme(:foo, self)
|
14
|
+
|
15
|
+
def self.mock_adapter_setup(db)
|
16
|
+
db.instance_variable_set(:@foo, :foo)
|
17
|
+
end
|
18
|
+
|
19
|
+
module self::DatabaseMethods
|
20
|
+
def foo
|
21
|
+
@foo
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module self::DatasetMethods
|
26
|
+
def foo
|
27
|
+
db.foo
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Sequel.connect('mock://foo') do |db|
|
33
|
+
db.foo.must_equal :foo
|
34
|
+
db.dataset.foo.must_equal :foo
|
35
|
+
end
|
36
|
+
ensure
|
37
|
+
Sequel.synchronize{Sequel::SHARED_ADAPTER_MAP.delete(:foo)}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
10
41
|
it "should have constructor accept no arguments" do
|
11
42
|
Sequel::Mock::Database.new.must_be_kind_of(Sequel::Mock::Database)
|
12
43
|
end
|
@@ -443,7 +474,7 @@ describe "Sequel Mock Adapter" do
|
|
443
474
|
end
|
444
475
|
end
|
445
476
|
|
446
|
-
it "should automatically set version for adapters
|
477
|
+
it "should automatically set version for adapters needing versions" do
|
447
478
|
Sequel.mock(:host=>'postgres').server_version.must_be :>=, 90400
|
448
479
|
Sequel.mock(:host=>'mssql').server_version.must_be :>=, 11000000
|
449
480
|
Sequel.mock(:host=>'mysql').server_version.must_be :>=, 50617
|
@@ -319,6 +319,52 @@ describe "Sequel::IntegerMigrator" do
|
|
319
319
|
@db.dataset.columns.must_equal [:sic]
|
320
320
|
end
|
321
321
|
|
322
|
+
it "should support :relative option for running relative migrations" do
|
323
|
+
Sequel::Migrator.run(@db, @dirname, :relative=>2).must_equal 2
|
324
|
+
@db.creates.must_equal [1111, 2222]
|
325
|
+
@db.version.must_equal 2
|
326
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [1, 2]
|
327
|
+
|
328
|
+
Sequel::Migrator.run(@db, @dirname, :relative=>-1).must_equal 1
|
329
|
+
@db.drops.must_equal [2222]
|
330
|
+
@db.version.must_equal 1
|
331
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [1]
|
332
|
+
|
333
|
+
Sequel::Migrator.run(@db, @dirname, :relative=>2).must_equal 3
|
334
|
+
@db.creates.must_equal [1111, 2222, 2222, 3333]
|
335
|
+
@db.version.must_equal 3
|
336
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [2, 3]
|
337
|
+
|
338
|
+
Sequel::Migrator.run(@db, @dirname, :relative=>-3).must_equal 0
|
339
|
+
@db.drops.must_equal [2222, 3333, 2222, 1111]
|
340
|
+
@db.version.must_equal 0
|
341
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [2, 1, 0]
|
342
|
+
end
|
343
|
+
|
344
|
+
it "should handle :relative option beyond the upper and lower limit" do
|
345
|
+
Sequel::Migrator.run(@db, @dirname, :relative=>100).must_equal 3
|
346
|
+
@db.creates.must_equal [1111, 2222, 3333]
|
347
|
+
@db.version.must_equal 3
|
348
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [1, 2, 3]
|
349
|
+
|
350
|
+
Sequel::Migrator.run(@db, @dirname, :relative=>-200).must_equal 0
|
351
|
+
@db.drops.must_equal [3333, 2222, 1111]
|
352
|
+
@db.version.must_equal 0
|
353
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [2, 1, 0]
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should correctly handle migration target versions beyond the upper and lower limits" do
|
357
|
+
Sequel::Migrator.run(@db, @dirname, :target=>100).must_equal 3
|
358
|
+
@db.creates.must_equal [1111, 2222, 3333]
|
359
|
+
@db.version.must_equal 3
|
360
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [1, 2, 3]
|
361
|
+
|
362
|
+
Sequel::Migrator.run(@db, @dirname, :target=>-100).must_equal 0
|
363
|
+
@db.drops.must_equal [3333, 2222, 1111]
|
364
|
+
@db.version.must_equal 0
|
365
|
+
@db.sqls.map{|x| x =~ /\AUPDATE.*(\d+)/ ? $1.to_i : nil}.compact.must_equal [2, 1, 0]
|
366
|
+
end
|
367
|
+
|
322
368
|
it "should apply migrations correctly in the up direction if no target is given" do
|
323
369
|
Sequel::Migrator.apply(@db, @dirname)
|
324
370
|
@db.creates.must_equal [1111, 2222, 3333]
|
@@ -15,6 +15,7 @@ describe "pg_interval extension" do
|
|
15
15
|
@db.literal(ActiveSupport::Duration.new(0, [])).must_equal "'0'::interval"
|
16
16
|
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 0]])).must_equal "'0'::interval"
|
17
17
|
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 10], [:minutes, 20], [:days, 3], [:months, 4], [:years, 6]])).must_equal "'6 years 4 months 3 days 20 minutes 10 seconds '::interval"
|
18
|
+
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 10], [:minutes, 20], [:hours, 8], [:days, 3], [:weeks, 2], [:months, 4], [:years, 6]])).must_equal "'6 years 4 months 2 weeks 3 days 8 hours 20 minutes 10 seconds '::interval"
|
18
19
|
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, -10.000001], [:minutes, -20], [:days, -3], [:months, -4], [:years, -6]])).must_equal "'-6 years -4 months -3 days -20 minutes -10.000001 seconds '::interval"
|
19
20
|
end
|
20
21
|
|
@@ -190,6 +190,19 @@ describe "Sequel::Postgres::JSONOp" do
|
|
190
190
|
@l[@jb.concat([1, 2])].must_equal "(j || '[1,2]'::jsonb)"
|
191
191
|
end
|
192
192
|
|
193
|
+
it "#insert should use the jsonb_insert function" do
|
194
|
+
@l[@jb.insert(:a, :h)].must_equal "jsonb_insert(j, a, h, false)"
|
195
|
+
@l[@jb.insert(:a, :h, true)].must_equal "jsonb_insert(j, a, h, true)"
|
196
|
+
end
|
197
|
+
|
198
|
+
it "#insert should handle hashes" do
|
199
|
+
@l[@jb.insert(:a, 'a'=>'b')].must_equal "jsonb_insert(j, a, '{\"a\":\"b\"}'::jsonb, false)"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "#insert should handle arrays" do
|
203
|
+
@l[@jb.insert(%w'a b', [1, 2])].must_equal "jsonb_insert(j, ARRAY['a','b'], '[1,2]'::jsonb, false)"
|
204
|
+
end
|
205
|
+
|
193
206
|
it "#set should use the jsonb_set function" do
|
194
207
|
@l[@jb.set(:a, :h)].must_equal "jsonb_set(j, a, h, true)"
|
195
208
|
@l[@jb.set(:a, :h, false)].must_equal "jsonb_set(j, a, h, false)"
|
@@ -50,6 +50,17 @@ describe "Sequel::Plugins::Timestamps" do
|
|
50
50
|
o.updated_at.must_equal '2009-08-01'
|
51
51
|
end
|
52
52
|
|
53
|
+
it "should leave manually set update timestamp, if :allow_manual_update was given" do
|
54
|
+
o = @c.load(:id=>1).update(:updated_at=>Date.new(2016))
|
55
|
+
@c.db.sqls.must_equal ["UPDATE t SET updated_at = '2009-08-01' WHERE (id = 1)"]
|
56
|
+
o.updated_at.must_equal '2009-08-01'
|
57
|
+
|
58
|
+
@c.plugin :timestamps, :allow_manual_update=>true
|
59
|
+
o = @c.load(:id=>1).update(:updated_at=>Date.new(2016))
|
60
|
+
@c.db.sqls.must_equal ["UPDATE t SET updated_at = '2016-01-01' WHERE (id = 1)"]
|
61
|
+
o.updated_at.must_equal Date.new(2016)
|
62
|
+
end
|
63
|
+
|
53
64
|
it "should work with current_datetime_timestamp extension" do
|
54
65
|
Sequel.datetime_class = Time
|
55
66
|
@c.dataset = @c.dataset.extension(:current_datetime_timestamp)
|
@@ -127,6 +127,14 @@ describe "Touch plugin" do
|
|
127
127
|
end
|
128
128
|
|
129
129
|
it "should be able to touch many_to_one associations" do
|
130
|
+
@Album.plugin :touch, :associations=>:artist
|
131
|
+
@Album.plugin :skip_create_refresh
|
132
|
+
@Album.create(:artist_id=>4)
|
133
|
+
DB.sqls.must_equal ["INSERT INTO albums (artist_id) VALUES (4)",
|
134
|
+
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 4)"]
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should be able to touch one_to_one associations" do
|
130
138
|
@Artist.one_to_one :album, :class=>@Album, :key=>:artist_id
|
131
139
|
@Artist.plugin :touch, :associations=>:album
|
132
140
|
@a.touch
|