sequel 4.9.0 → 4.10.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.
- 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
|