sequel 4.9.0 → 4.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +79 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/Rakefile +2 -12
- data/bin/sequel +1 -0
- data/doc/advanced_associations.rdoc +82 -25
- data/doc/association_basics.rdoc +21 -22
- data/doc/core_extensions.rdoc +1 -1
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.10.0.txt +226 -0
- data/doc/security.rdoc +1 -0
- data/doc/testing.rdoc +7 -7
- data/doc/transactions.rdoc +8 -0
- data/lib/sequel/adapters/jdbc.rb +160 -168
- data/lib/sequel/adapters/jdbc/db2.rb +17 -18
- data/lib/sequel/adapters/jdbc/derby.rb +5 -28
- data/lib/sequel/adapters/jdbc/h2.rb +11 -22
- data/lib/sequel/adapters/jdbc/hsqldb.rb +31 -18
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -15
- data/lib/sequel/adapters/jdbc/oracle.rb +36 -35
- data/lib/sequel/adapters/jdbc/postgresql.rb +72 -90
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +18 -16
- data/lib/sequel/adapters/jdbc/sqlite.rb +7 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -30
- data/lib/sequel/adapters/jdbc/transactions.rb +5 -6
- data/lib/sequel/adapters/openbase.rb +1 -7
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/access.rb +3 -6
- data/lib/sequel/adapters/shared/cubrid.rb +24 -9
- data/lib/sequel/adapters/shared/db2.rb +13 -5
- data/lib/sequel/adapters/shared/firebird.rb +16 -16
- data/lib/sequel/adapters/shared/informix.rb +2 -5
- data/lib/sequel/adapters/shared/mssql.rb +72 -63
- data/lib/sequel/adapters/shared/mysql.rb +72 -40
- data/lib/sequel/adapters/shared/oracle.rb +27 -15
- data/lib/sequel/adapters/shared/postgres.rb +24 -44
- data/lib/sequel/adapters/shared/progress.rb +1 -5
- data/lib/sequel/adapters/shared/sqlanywhere.rb +26 -18
- data/lib/sequel/adapters/shared/sqlite.rb +21 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +8 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -2
- data/lib/sequel/adapters/utils/split_alter_table.rb +8 -0
- data/lib/sequel/core.rb +14 -9
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +12 -0
- data/lib/sequel/database/query.rb +4 -1
- data/lib/sequel/database/schema_methods.rb +3 -2
- data/lib/sequel/database/transactions.rb +47 -17
- data/lib/sequel/dataset/features.rb +12 -2
- data/lib/sequel/dataset/mutation.rb +2 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +12 -4
- data/lib/sequel/dataset/prepared_statements.rb +6 -0
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/dataset/sql.rb +132 -70
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/null_dataset.rb +8 -4
- data/lib/sequel/extensions/pg_array.rb +4 -4
- data/lib/sequel/extensions/pg_row.rb +1 -0
- data/lib/sequel/model/associations.rb +468 -188
- data/lib/sequel/model/base.rb +88 -13
- data/lib/sequel/plugins/association_pks.rb +23 -64
- data/lib/sequel/plugins/auto_validations.rb +3 -2
- data/lib/sequel/plugins/dataset_associations.rb +1 -3
- data/lib/sequel/plugins/many_through_many.rb +18 -65
- data/lib/sequel/plugins/pg_array_associations.rb +97 -86
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +36 -27
- data/lib/sequel/plugins/rcte_tree.rb +12 -16
- data/lib/sequel/plugins/sharding.rb +21 -3
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -1
- data/lib/sequel/plugins/subclasses.rb +1 -9
- data/lib/sequel/plugins/tactical_eager_loading.rb +9 -0
- data/lib/sequel/plugins/tree.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +57 -15
- data/spec/adapters/mysql_spec.rb +11 -0
- data/spec/bin_spec.rb +2 -2
- data/spec/core/database_spec.rb +38 -4
- data/spec/core/dataset_spec.rb +45 -7
- data/spec/core/placeholder_literalizer_spec.rb +17 -0
- data/spec/core/schema_spec.rb +6 -1
- data/spec/extensions/active_model_spec.rb +18 -9
- data/spec/extensions/association_pks_spec.rb +20 -18
- data/spec/extensions/association_proxies_spec.rb +9 -9
- data/spec/extensions/auto_validations_spec.rb +6 -0
- data/spec/extensions/columns_introspection_spec.rb +1 -0
- data/spec/extensions/constraint_validations_spec.rb +3 -1
- data/spec/extensions/many_through_many_spec.rb +191 -111
- data/spec/extensions/pg_array_associations_spec.rb +133 -103
- data/spec/extensions/prepared_statements_associations_spec.rb +23 -4
- data/spec/extensions/rcte_tree_spec.rb +35 -27
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -1
- data/spec/extensions/sharding_spec.rb +2 -2
- data/spec/extensions/tactical_eager_loading_spec.rb +4 -0
- data/spec/extensions/to_dot_spec.rb +1 -0
- data/spec/extensions/touch_spec.rb +2 -2
- data/spec/integration/associations_test.rb +130 -37
- data/spec/integration/dataset_test.rb +17 -0
- data/spec/integration/model_test.rb +17 -0
- data/spec/integration/schema_test.rb +14 -0
- data/spec/integration/transaction_test.rb +25 -1
- data/spec/model/association_reflection_spec.rb +63 -24
- data/spec/model/associations_spec.rb +104 -57
- data/spec/model/base_spec.rb +14 -1
- data/spec/model/class_dataset_methods_spec.rb +1 -0
- data/spec/model/eager_loading_spec.rb +221 -74
- data/spec/model/model_spec.rb +119 -1
- metadata +4 -2
@@ -22,17 +22,6 @@ module Sequel
|
|
22
22
|
# lambda returns the next integer to use.
|
23
23
|
NEXT = lambda{MUTEX.synchronize{i += 1}}
|
24
24
|
|
25
|
-
module ClassMethods
|
26
|
-
# Disable prepared statement use if a block is given, or the :dataset or :conditions
|
27
|
-
# options are used, or you are cloning an association.
|
28
|
-
def associate(type, name, opts = OPTS, &block)
|
29
|
-
if block || opts[:dataset] || (opts[:clone] && association_reflection(opts[:clone])[:prepared_statement] == false)
|
30
|
-
opts = opts.merge(:prepared_statement=>false)
|
31
|
-
end
|
32
|
-
super(type, name, opts, &block)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
25
|
module InstanceMethods
|
37
26
|
private
|
38
27
|
|
@@ -50,9 +39,9 @@ module Sequel
|
|
50
39
|
association_bound_variable_hash(opts.associated_class.table_name, opts.primary_keys, opts[:keys])
|
51
40
|
when :one_to_many, :one_to_one
|
52
41
|
association_bound_variable_hash(opts.associated_class.table_name, opts[:keys], opts[:primary_keys])
|
53
|
-
when :many_to_many
|
42
|
+
when :many_to_many, :one_through_one
|
54
43
|
association_bound_variable_hash(opts.join_table_alias, opts[:left_keys], opts[:left_primary_keys])
|
55
|
-
when :many_through_many
|
44
|
+
when :many_through_many, :one_through_many
|
56
45
|
association_bound_variable_hash(opts.final_reverse_edge[:alias], Array(opts[:left_key]), opts[:left_primary_keys])
|
57
46
|
end
|
58
47
|
end
|
@@ -62,26 +51,46 @@ module Sequel
|
|
62
51
|
# instance. Return false if such a prepared statement cannot be created.
|
63
52
|
def association_prepared_statement(opts, assoc_bv)
|
64
53
|
opts.send(:cached_fetch, :prepared_statement) do
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
54
|
+
unless opts[:instance_specific]
|
55
|
+
ds, bv = _associated_dataset(opts, {}).unbind
|
56
|
+
if bv.length != assoc_bv.length
|
57
|
+
h = {}
|
58
|
+
bv.each do |k,v|
|
59
|
+
h[k] = v unless assoc_bv.has_key?(k)
|
60
|
+
end
|
61
|
+
ds = ds.bind(h)
|
70
62
|
end
|
71
|
-
|
63
|
+
ps = ds.prepare(opts.returns_array? ? :select : :first, :"smpsap_#{NEXT.call}")
|
64
|
+
ps.log_sql = true
|
65
|
+
ps
|
72
66
|
end
|
73
|
-
ps = ds.prepare(opts.returns_array? ? :select : :first, :"smpsap_#{NEXT.call}")
|
74
|
-
ps.log_sql = true
|
75
|
-
ps
|
76
67
|
end
|
77
68
|
end
|
78
69
|
|
79
|
-
#
|
80
|
-
#
|
81
|
-
def
|
82
|
-
if !
|
70
|
+
# Use a prepared statement if possible to load the associated object,
|
71
|
+
# unless a dynamic callback is given.
|
72
|
+
def _load_associated_object(opts, dynamic_opts)
|
73
|
+
if !dynamic_opts[:callback] && (bv = association_bound_variables(opts)) && (ps ||= association_prepared_statement(opts, bv))
|
74
|
+
ps.call(bv)
|
75
|
+
else
|
83
76
|
super
|
84
|
-
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Use a prepared statement if possible to load the associated object,
|
81
|
+
# unless the associated model uses caching.
|
82
|
+
def _load_associated_object_via_primary_key(opts)
|
83
|
+
if !opts.associated_class.respond_to?(:cache_get_pk) && (bv = association_bound_variables(opts)) && (ps ||= association_prepared_statement(opts, bv))
|
84
|
+
ps.call(bv)
|
85
|
+
else
|
86
|
+
super
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Use a prepared statement if possible to load the associated objects,
|
91
|
+
# unless a dynamic callback is given.
|
92
|
+
def _load_associated_object_array(opts, dynamic_opts)
|
93
|
+
if !dynamic_opts[:callback] && (bv = association_bound_variables(opts)) && (ps ||= association_prepared_statement(opts, bv))
|
85
94
|
ps.call(bv)
|
86
95
|
else
|
87
96
|
super
|
@@ -204,15 +204,12 @@ module Sequel
|
|
204
204
|
end
|
205
205
|
end
|
206
206
|
table_alias = model.dataset.schema_and_table(model.table_name)[1].to_sym
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
eo[:associations], eo)
|
214
|
-
elds = elds.select_append(ka) unless elds.opts[:select] == nil
|
215
|
-
elds.all do |obj|
|
207
|
+
ds = model.from(SQL::AliasedExpression.new(t, table_alias)).
|
208
|
+
with_recursive(t, base_case, recursive_case,
|
209
|
+
:args=>((key_aliases + col_aliases) if col_aliases))
|
210
|
+
ds = r.apply_eager_dataset_changes(ds)
|
211
|
+
ds = ds.select_append(ka) unless ds.opts[:select] == nil
|
212
|
+
model.eager_load_results(r, eo.merge(:loader=>false, :initalize_rows=>false, :dataset=>ds, :id_map=>nil)) do |obj|
|
216
213
|
opk = prkey_conv[obj]
|
217
214
|
if parent_map.has_key?(opk)
|
218
215
|
if idm_obj = parent_map[opk]
|
@@ -308,13 +305,12 @@ module Sequel
|
|
308
305
|
recursive_case = recursive_case.select_more(SQL::AliasedExpression.new(SQL::QualifiedIdentifier.new(t, la) + 1, la)).filter(SQL::QualifiedIdentifier.new(t, la) < level - 1)
|
309
306
|
end
|
310
307
|
table_alias = model.dataset.schema_and_table(model.table_name)[1].to_sym
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
elds.all do |obj|
|
308
|
+
ds = model.from(SQL::AliasedExpression.new(t, table_alias)).
|
309
|
+
with_recursive(t, base_case, recursive_case,
|
310
|
+
:args=>((key_aliases + col_aliases + (level ? [la] : [])) if col_aliases))
|
311
|
+
ds = r.apply_eager_dataset_changes(ds)
|
312
|
+
ds = ds.select_append(ka) unless ds.opts[:select] == nil
|
313
|
+
model.eager_load_results(r, eo.merge(:loader=>false, :initalize_rows=>false, :dataset=>ds, :id_map=>nil, :associations=>{})) do |obj|
|
318
314
|
if level
|
319
315
|
no_cache = no_cache_level == obj.values.delete(la)
|
320
316
|
end
|
@@ -24,9 +24,22 @@ module Sequel
|
|
24
24
|
new_using_server(s, values, &block).save
|
25
25
|
end
|
26
26
|
|
27
|
-
#
|
28
|
-
|
29
|
-
|
27
|
+
# Eager load the association with the given eager loader options.
|
28
|
+
def eager_load_results(opts, eo, &block)
|
29
|
+
if (s = eo[:self]) && (server = s.opts[:server])
|
30
|
+
eb = eo[:eager_block]
|
31
|
+
set_server = proc do |ds|
|
32
|
+
ds = eb.call(ds) if eb
|
33
|
+
ds = ds.server(server) unless ds.opts[:server]
|
34
|
+
ds
|
35
|
+
end
|
36
|
+
eo = eo.merge(:eager_block=>set_server)
|
37
|
+
end
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
# REMOVE410
|
30
43
|
def eager_loading_dataset(opts, ds, select, associations, eager_options=OPTS)
|
31
44
|
ds = super(opts, ds, select, associations, eager_options)
|
32
45
|
if !ds.opts[:server] and s = eager_options[:self] and server = s.opts[:server]
|
@@ -70,6 +83,11 @@ module Sequel
|
|
70
83
|
use_server(super)
|
71
84
|
end
|
72
85
|
|
86
|
+
# Don't use an associated object loader, as it won't respect the shard used.
|
87
|
+
def _associated_object_loader(opts, dynamic_opts)
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
73
91
|
# Ensure that the join table for many_to_many associations uses the correct shard.
|
74
92
|
def _join_table_dataset(opts)
|
75
93
|
use_server(super)
|
@@ -182,7 +182,8 @@ module Sequel
|
|
182
182
|
# keys for all of their descendant classes.
|
183
183
|
def sti_subclass_added(key)
|
184
184
|
if sti_key_array
|
185
|
-
|
185
|
+
key_array = Array(key)
|
186
|
+
Sequel.synchronize{sti_key_array.push(*key_array)}
|
186
187
|
superclass.sti_subclass_added(key)
|
187
188
|
end
|
188
189
|
end
|
@@ -42,7 +42,7 @@ module Sequel
|
|
42
42
|
|
43
43
|
# All descendent classes of this model.
|
44
44
|
def descendents
|
45
|
-
Sequel.synchronize{
|
45
|
+
Sequel.synchronize{subclasses.dup}.map{|x| [x] + x.send(:descendents)}.flatten
|
46
46
|
end
|
47
47
|
|
48
48
|
Plugins.inherited_instance_variables(self, :@subclasses=>lambda{|v| []}, :@on_subclass=>nil)
|
@@ -55,14 +55,6 @@ module Sequel
|
|
55
55
|
Sequel.synchronize{subclasses << subclass}
|
56
56
|
on_subclass.call(subclass) if on_subclass
|
57
57
|
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
# Recursive, non-thread safe version of descendents, since
|
62
|
-
# the mutex Sequel uses isn't reentrant.
|
63
|
-
def _descendents
|
64
|
-
subclasses.map{|x| [x] + x.send(:_descendents)}.flatten
|
65
|
-
end
|
66
58
|
end
|
67
59
|
end
|
68
60
|
end
|
@@ -35,6 +35,15 @@ module Sequel
|
|
35
35
|
# reteived via Dataset#all.
|
36
36
|
attr_accessor :retrieved_with
|
37
37
|
|
38
|
+
# Remove retrieved_by and retrieved_with when marshalling. retrieved_by
|
39
|
+
# contains unmarshallable objects, and retrieved_with can be very large
|
40
|
+
# and is not helpful without retrieved_by.
|
41
|
+
def marshallable!
|
42
|
+
@retrieved_by = nil
|
43
|
+
@retrieved_with = nil
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
38
47
|
private
|
39
48
|
|
40
49
|
# If there the association is not in the associations cache and the object
|
data/lib/sequel/plugins/tree.rb
CHANGED
@@ -88,9 +88,9 @@ module Sequel
|
|
88
88
|
nodes
|
89
89
|
end
|
90
90
|
|
91
|
-
# Returns list of
|
91
|
+
# Returns list of descendants
|
92
92
|
#
|
93
|
-
#
|
93
|
+
# node.descendants # => [child1, child2, subchild1_1, subchild1_2, subchild2_1, subchild2_2]
|
94
94
|
def descendants
|
95
95
|
nodes = children.dup
|
96
96
|
children.each{|child| nodes.concat(child.descendants)}
|
@@ -67,7 +67,7 @@ module Sequel
|
|
67
67
|
# Instructs the model to skip validations defined in superclasses
|
68
68
|
def skip_superclass_validations
|
69
69
|
superclass.validations.each do |att, procs|
|
70
|
-
if
|
70
|
+
if @validations[att]
|
71
71
|
@validations[att] -= procs
|
72
72
|
end
|
73
73
|
end
|
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sequel
|
|
3
3
|
MAJOR = 4
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
5
5
|
# release, generally around once a month.
|
6
|
-
MINOR =
|
6
|
+
MINOR = 10
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
9
|
TINY = 0
|
data/spec/adapters/mssql_spec.rb
CHANGED
@@ -656,25 +656,67 @@ describe "MSSQL Stored Procedure support" do
|
|
656
656
|
@db.execute('DROP PROCEDURE dbo.SequelTest')
|
657
657
|
end
|
658
658
|
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
659
|
+
describe "with unnamed parameters" do
|
660
|
+
it "should return a hash of output variables" do
|
661
|
+
r = @db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})
|
662
|
+
r.should be_a_kind_of(Hash)
|
663
|
+
r.values_at(:var2, :var3).should == [@now, '1']
|
664
|
+
end
|
664
665
|
|
665
|
-
|
666
|
-
|
667
|
-
|
666
|
+
it "should support typed output variables" do
|
667
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, [:output, 'int']]})[:var3].should == 1
|
668
|
+
end
|
668
669
|
|
669
|
-
|
670
|
-
|
671
|
-
|
670
|
+
it "should support named output variables" do
|
671
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, [:output, nil, 'output'], :output]})[:output].should == @now
|
672
|
+
end
|
673
|
+
|
674
|
+
it "should return the number of Affected Rows" do
|
675
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})[:numrows].should == 1
|
676
|
+
end
|
672
677
|
|
673
|
-
|
674
|
-
|
678
|
+
it "should return the Result Code" do
|
679
|
+
@db.call_mssql_sproc(:SequelTest, {:args => [@now, 1, :output, :output]})[:result].should == 1
|
680
|
+
end
|
675
681
|
end
|
676
682
|
|
677
|
-
|
678
|
-
|
683
|
+
describe "with named parameters" do
|
684
|
+
it "should return a hash of output variables" do
|
685
|
+
r = @db.call_mssql_sproc(:SequelTest, :args => {
|
686
|
+
'Input' => @now,
|
687
|
+
'IntegerInput' => 1,
|
688
|
+
'Output' => [:output, nil, 'output'],
|
689
|
+
'IntegerOutput' => [:output, nil, 'integer_output']
|
690
|
+
})
|
691
|
+
r.should be_a_kind_of(Hash)
|
692
|
+
r.values_at(:output, :integer_output).should == [@now, '1']
|
693
|
+
end
|
694
|
+
|
695
|
+
it "should support typed output variables" do
|
696
|
+
@db.call_mssql_sproc(:SequelTest, :args => {
|
697
|
+
'Input' => @now,
|
698
|
+
'IntegerInput' => 1,
|
699
|
+
'Output' => [:output, nil, 'output'],
|
700
|
+
'IntegerOutput' => [:output, 'int', 'integer_output']
|
701
|
+
})[:integer_output].should == 1
|
702
|
+
end
|
703
|
+
|
704
|
+
it "should return the number of Affected Rows" do
|
705
|
+
@db.call_mssql_sproc(:SequelTest, :args => {
|
706
|
+
'Input' => @now,
|
707
|
+
'IntegerInput' => 1,
|
708
|
+
'Output' => [:output, nil, 'output'],
|
709
|
+
'IntegerOutput' => [:output, nil, 'integer_output']
|
710
|
+
})[:numrows].should == 1
|
711
|
+
end
|
712
|
+
|
713
|
+
it "should return the Result Code" do
|
714
|
+
@db.call_mssql_sproc(:SequelTest, :args => {
|
715
|
+
'Input' => @now,
|
716
|
+
'IntegerInput' => 1,
|
717
|
+
'Output' => [:output, nil, 'output'],
|
718
|
+
'IntegerOutput' => [:output, nil, 'integer_output']
|
719
|
+
})[:result].should == 1
|
720
|
+
end
|
679
721
|
end
|
680
722
|
end unless DB.adapter_scheme == :odbc
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -520,6 +520,17 @@ describe "A MySQL database" do
|
|
520
520
|
end
|
521
521
|
end
|
522
522
|
|
523
|
+
specify "should correctly format ALTER TABLE statements with named foreign keys" do
|
524
|
+
@db.create_table(:items){Integer :id}
|
525
|
+
@db.create_table(:users){primary_key :id}
|
526
|
+
@db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade, :foreign_key_constraint_name => :pk_items__users }
|
527
|
+
check_sqls do
|
528
|
+
@db.sqls.should == ["CREATE TABLE `items` (`id` integer)",
|
529
|
+
"CREATE TABLE `users` (`id` integer PRIMARY KEY AUTO_INCREMENT)",
|
530
|
+
"ALTER TABLE `items` ADD COLUMN `p_id` integer NOT NULL, ADD CONSTRAINT `pk_items__users` FOREIGN KEY (`p_id`) REFERENCES `users`(`id`) ON DELETE CASCADE"]
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
523
534
|
specify "should have rename_column support keep existing options" do
|
524
535
|
@db.create_table(:items){String :id, :null=>false, :default=>'blah'}
|
525
536
|
@db.alter_table(:items){rename_column :id, :nid}
|
data/spec/bin_spec.rb
CHANGED
@@ -140,7 +140,7 @@ END
|
|
140
140
|
end
|
141
141
|
|
142
142
|
it "-E should echo SQL statements to stdout" do
|
143
|
-
bin(:args=>'-E -c DB.tables').should =~ %r{
|
143
|
+
bin(:args=>'-E -c DB.tables').should =~ %r{SELECT \* FROM `sqlite_master` WHERE \(type = 'table' AND NOT name = 'sqlite_sequence'\)\n}
|
144
144
|
end
|
145
145
|
|
146
146
|
it "-I should include directory in load path" do
|
@@ -149,7 +149,7 @@ END
|
|
149
149
|
|
150
150
|
it "-l should log SQL statements to file" do
|
151
151
|
bin(:args=>"-l #{TMP_FILE} -c DB.tables").should == ''
|
152
|
-
File.read(TMP_FILE).should =~ %r{
|
152
|
+
File.read(TMP_FILE).should =~ %r{SELECT \* FROM `sqlite_master` WHERE \(type = 'table' AND NOT name = 'sqlite_sequence'\)\n}
|
153
153
|
end
|
154
154
|
|
155
155
|
it "-L should load all *.rb files in given directory" do
|
data/spec/core/database_spec.rb
CHANGED
@@ -927,7 +927,6 @@ describe "Database#transaction with savepoint support" do
|
|
927
927
|
it_should_behave_like "Database#transaction"
|
928
928
|
|
929
929
|
specify "should support after_commit inside savepoints" do
|
930
|
-
meta_def(@db, :supports_savepoints?){true}
|
931
930
|
@db.transaction do
|
932
931
|
@db.after_commit{@db.execute('foo')}
|
933
932
|
@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('bar')}}
|
@@ -937,7 +936,6 @@ describe "Database#transaction with savepoint support" do
|
|
937
936
|
end
|
938
937
|
|
939
938
|
specify "should support after_rollback inside savepoints" do
|
940
|
-
meta_def(@db, :supports_savepoints?){true}
|
941
939
|
@db.transaction do
|
942
940
|
@db.after_rollback{@db.execute('foo')}
|
943
941
|
@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('bar')}}
|
@@ -948,14 +946,12 @@ describe "Database#transaction with savepoint support" do
|
|
948
946
|
end
|
949
947
|
|
950
948
|
specify "should raise an error if you attempt to use after_commit inside a savepoint in a prepared transaction" do
|
951
|
-
meta_def(@db, :supports_savepoints?){true}
|
952
949
|
meta_def(@db, :supports_prepared_transactions?){true}
|
953
950
|
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
954
951
|
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
955
952
|
end
|
956
953
|
|
957
954
|
specify "should raise an error if you attempt to use after_rollback inside a savepoint in a prepared transaction" do
|
958
|
-
meta_def(@db, :supports_savepoints?){true}
|
959
955
|
meta_def(@db, :supports_prepared_transactions?){true}
|
960
956
|
proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{@db.execute('foo')}}}}.should raise_error(Sequel::Error)
|
961
957
|
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1','ROLLBACK TO SAVEPOINT autopoint_1', 'ROLLBACK']
|
@@ -1023,6 +1019,25 @@ describe "Database#transaction with savepoints" do
|
|
1023
1019
|
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
1024
1020
|
end
|
1025
1021
|
|
1022
|
+
specify "should use savepoints if surrounding transaction uses :auto_savepoint option" do
|
1023
|
+
@db.transaction(:auto_savepoint=>true){@db.transaction{@db.execute 'DROP TABLE test;'}}
|
1024
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
1025
|
+
|
1026
|
+
@db.transaction(:auto_savepoint=>true){@db.transaction{@db.transaction{@db.execute 'DROP TABLE test;'}}}
|
1027
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
1028
|
+
|
1029
|
+
@db.transaction(:auto_savepoint=>true){@db.transaction(:auto_savepoint=>true){@db.transaction{@db.execute 'DROP TABLE test;'}}}
|
1030
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'SAVEPOINT autopoint_2', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_2', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
1031
|
+
|
1032
|
+
@db.transaction{@db.transaction(:auto_savepoint=>true, :savepoint=>true){@db.transaction{@db.execute 'DROP TABLE test;'}}}
|
1033
|
+
@db.sqls.should == ['BEGIN', 'SAVEPOINT autopoint_1', 'SAVEPOINT autopoint_2', 'DROP TABLE test;', 'RELEASE SAVEPOINT autopoint_2', 'RELEASE SAVEPOINT autopoint_1', 'COMMIT']
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
specify "should not use savepoints if surrounding transaction uses :auto_savepoint and current transaction uses :savepoint=>false option" do
|
1037
|
+
@db.transaction(:auto_savepoint=>true){@db.transaction(:savepoint=>false){@db.execute 'DROP TABLE test;'}}
|
1038
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
1039
|
+
end
|
1040
|
+
|
1026
1041
|
specify "should not use a savepoint if no transaction is in progress" do
|
1027
1042
|
@db.transaction(:savepoint=>true){@db.execute 'DROP TABLE test;'}
|
1028
1043
|
@db.sqls.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
@@ -2434,3 +2449,22 @@ describe "Database#schema_type_class" do
|
|
2434
2449
|
end
|
2435
2450
|
end
|
2436
2451
|
end
|
2452
|
+
|
2453
|
+
describe "Database#execute_{dui,ddl,insert}" do
|
2454
|
+
before do
|
2455
|
+
@db = Sequel::Database.new
|
2456
|
+
def @db.execute(sql, opts={})
|
2457
|
+
(@sqls ||= []) << sql
|
2458
|
+
end
|
2459
|
+
def @db.sqls
|
2460
|
+
@sqls
|
2461
|
+
end
|
2462
|
+
end
|
2463
|
+
|
2464
|
+
specify "should execute the SQL" do
|
2465
|
+
@db.execute_dui "DELETE FROM table"
|
2466
|
+
@db.execute_ddl "SET foo"
|
2467
|
+
@db.execute_insert "INSERT INTO table DEFAULT VALUES"
|
2468
|
+
@db.sqls.should == ["DELETE FROM table", "SET foo", "INSERT INTO table DEFAULT VALUES"]
|
2469
|
+
end
|
2470
|
+
end
|