sequel 3.29.0 → 3.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +35 -3
- data/Rakefile +2 -1
- data/doc/association_basics.rdoc +11 -0
- data/doc/opening_databases.rdoc +2 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/testing.rdoc +17 -3
- data/lib/sequel/adapters/amalgalite.rb +2 -2
- data/lib/sequel/adapters/do/mysql.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc.rb +126 -43
- data/lib/sequel/adapters/jdbc/as400.rb +11 -3
- data/lib/sequel/adapters/jdbc/db2.rb +2 -1
- data/lib/sequel/adapters/jdbc/derby.rb +44 -19
- data/lib/sequel/adapters/jdbc/h2.rb +32 -19
- data/lib/sequel/adapters/jdbc/hsqldb.rb +21 -17
- data/lib/sequel/adapters/jdbc/jtds.rb +9 -4
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -1
- data/lib/sequel/adapters/jdbc/mysql.rb +2 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +21 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +48 -18
- data/lib/sequel/adapters/mock.rb +2 -1
- data/lib/sequel/adapters/mysql.rb +4 -2
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +6 -6
- data/lib/sequel/adapters/postgres.rb +25 -12
- data/lib/sequel/adapters/shared/access.rb +14 -6
- data/lib/sequel/adapters/shared/db2.rb +36 -13
- data/lib/sequel/adapters/shared/firebird.rb +12 -5
- data/lib/sequel/adapters/shared/informix.rb +11 -3
- data/lib/sequel/adapters/shared/mssql.rb +94 -47
- data/lib/sequel/adapters/shared/mysql.rb +107 -49
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +2 -2
- data/lib/sequel/adapters/shared/oracle.rb +54 -27
- data/lib/sequel/adapters/shared/postgres.rb +65 -26
- data/lib/sequel/adapters/shared/progress.rb +4 -1
- data/lib/sequel/adapters/shared/sqlite.rb +36 -20
- data/lib/sequel/adapters/sqlite.rb +2 -3
- data/lib/sequel/adapters/swift/mysql.rb +3 -2
- data/lib/sequel/adapters/swift/sqlite.rb +2 -2
- data/lib/sequel/adapters/tinytds.rb +14 -8
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -4
- data/lib/sequel/database/misc.rb +6 -2
- data/lib/sequel/dataset/graph.rb +33 -7
- data/lib/sequel/dataset/prepared_statements.rb +19 -5
- data/lib/sequel/dataset/sql.rb +611 -201
- data/lib/sequel/model/associations.rb +12 -5
- data/lib/sequel/model/base.rb +20 -5
- data/lib/sequel/plugins/sharding.rb +9 -29
- data/lib/sequel/sql.rb +2 -1
- data/lib/sequel/timezones.rb +14 -4
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +10 -0
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/core/core_sql_spec.rb +3 -1
- data/spec/core/database_spec.rb +42 -0
- data/spec/core/dataset_spec.rb +10 -3
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/object_graph_spec.rb +38 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +35 -39
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +30 -82
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +33 -103
- data/spec/extensions/instance_filters_spec.rb +10 -21
- data/spec/extensions/instance_hooks_spec.rb +6 -24
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +135 -277
- data/spec/extensions/migration_spec.rb +18 -15
- data/spec/extensions/named_timezones_spec.rb +1 -1
- data/spec/extensions/nested_attributes_spec.rb +97 -92
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +22 -37
- data/spec/extensions/prepared_statements_safe_spec.rb +9 -27
- data/spec/extensions/prepared_statements_spec.rb +11 -30
- data/spec/extensions/prepared_statements_with_pk_spec.rb +6 -13
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +3 -6
- data/spec/extensions/serialization_spec.rb +20 -32
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +14 -36
- data/spec/extensions/spec_helper.rb +10 -64
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +1 -2
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/integration/dataset_test.rb +16 -4
- data/spec/integration/prepared_statement_test.rb +4 -2
- data/spec/model/eager_loading_spec.rb +16 -0
- data/spec/model/model_spec.rb +15 -1
- data/spec/model/record_spec.rb +60 -0
- metadata +23 -40
|
@@ -3,9 +3,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
3
3
|
describe Sequel::Model, "#sti_key" do
|
|
4
4
|
before do
|
|
5
5
|
class ::StiTest < Sequel::Model
|
|
6
|
-
|
|
7
|
-
def kind=(x); self[:kind] = x; end
|
|
8
|
-
def _refresh(x); end
|
|
6
|
+
columns :id, :kind, :blah
|
|
9
7
|
plugin :single_table_inheritance, :kind
|
|
10
8
|
end
|
|
11
9
|
class ::StiTestSub1 < StiTest
|
|
@@ -22,7 +20,7 @@ describe Sequel::Model, "#sti_key" do
|
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
specify "should have simple_table = nil" do
|
|
25
|
-
StiTest.simple_table.should ==
|
|
23
|
+
StiTest.simple_table.should == "sti_tests"
|
|
26
24
|
StiTestSub1.simple_table.should == nil
|
|
27
25
|
end
|
|
28
26
|
|
|
@@ -30,15 +28,9 @@ describe Sequel::Model, "#sti_key" do
|
|
|
30
28
|
StiTest.plugin :single_table_inheritance, :blah
|
|
31
29
|
Object.send(:remove_const, :StiTestSub1)
|
|
32
30
|
Object.send(:remove_const, :StiTestSub2)
|
|
33
|
-
class ::StiTestSub1 < StiTest
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
def @ds.fetch_rows(sql)
|
|
38
|
-
yield({:blah=>'StiTest'})
|
|
39
|
-
yield({:blah=>'StiTestSub1'})
|
|
40
|
-
yield({:blah=>'StiTestSub2'})
|
|
41
|
-
end
|
|
31
|
+
class ::StiTestSub1 < StiTest; end
|
|
32
|
+
class ::StiTestSub2 < StiTest; end
|
|
33
|
+
@ds._fetch = [{:blah=>'StiTest'}, {:blah=>'StiTestSub1'}, {:blah=>'StiTestSub2'}]
|
|
42
34
|
StiTest.all.collect{|x| x.class}.should == [StiTest, StiTestSub1, StiTestSub2]
|
|
43
35
|
StiTest.dataset.sql.should == "SELECT * FROM sti_tests"
|
|
44
36
|
StiTestSub1.dataset.sql.should == "SELECT * FROM sti_tests WHERE (sti_tests.blah IN ('StiTestSub1'))"
|
|
@@ -46,29 +38,18 @@ describe Sequel::Model, "#sti_key" do
|
|
|
46
38
|
end
|
|
47
39
|
|
|
48
40
|
it "should return rows with the correct class based on the polymorphic_key value" do
|
|
49
|
-
|
|
50
|
-
yield({:kind=>'StiTest'})
|
|
51
|
-
yield({:kind=>'StiTestSub1'})
|
|
52
|
-
yield({:kind=>'StiTestSub2'})
|
|
53
|
-
end
|
|
41
|
+
@ds._fetch = [{:kind=>'StiTest'}, {:kind=>'StiTestSub1'}, {:kind=>'StiTestSub2'}]
|
|
54
42
|
StiTest.all.collect{|x| x.class}.should == [StiTest, StiTestSub1, StiTestSub2]
|
|
55
43
|
end
|
|
56
44
|
|
|
57
45
|
it "should return rows with the correct class for subclasses based on the polymorphic_key value" do
|
|
58
|
-
class ::StiTestSub1Sub < StiTestSub1
|
|
59
|
-
|
|
60
|
-
ds = StiTestSub1.dataset
|
|
61
|
-
def ds.fetch_rows(sql)
|
|
62
|
-
yield({:kind=>'StiTestSub1'})
|
|
63
|
-
yield({:kind=>'StiTestSub1Sub'})
|
|
64
|
-
end
|
|
46
|
+
class ::StiTestSub1Sub < StiTestSub1; end
|
|
47
|
+
StiTestSub1.dataset._fetch = [{:kind=>'StiTestSub1'}, {:kind=>'StiTestSub1Sub'}]
|
|
65
48
|
StiTestSub1.all.collect{|x| x.class}.should == [StiTestSub1, StiTestSub1Sub]
|
|
66
49
|
end
|
|
67
50
|
|
|
68
51
|
it "should fallback to the main class if the given class does not exist" do
|
|
69
|
-
|
|
70
|
-
yield({:kind=>'StiTestSub3'})
|
|
71
|
-
end
|
|
52
|
+
@ds._fetch = {:kind=>'StiTestSub3'}
|
|
72
53
|
StiTest.all.collect{|x| x.class}.should == [StiTest]
|
|
73
54
|
end
|
|
74
55
|
|
|
@@ -79,10 +60,7 @@ describe Sequel::Model, "#sti_key" do
|
|
|
79
60
|
Object
|
|
80
61
|
end
|
|
81
62
|
StiTest.plugin :single_table_inheritance, :kind
|
|
82
|
-
|
|
83
|
-
yield({:kind=>''})
|
|
84
|
-
yield({:kind=>nil})
|
|
85
|
-
end
|
|
63
|
+
@ds._fetch = [{:kind=>''}, {:kind=>nil}]
|
|
86
64
|
StiTest.all.collect{|x| x.class}.should == [StiTest, StiTest]
|
|
87
65
|
called.should == false
|
|
88
66
|
end
|
|
@@ -91,19 +69,19 @@ describe Sequel::Model, "#sti_key" do
|
|
|
91
69
|
StiTest.new.save
|
|
92
70
|
StiTestSub1.new.save
|
|
93
71
|
StiTestSub2.new.save
|
|
94
|
-
MODEL_DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTest')", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub2')"]
|
|
72
|
+
MODEL_DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTest')", "SELECT * FROM sti_tests WHERE (id = 10) LIMIT 1", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE ((sti_tests.kind IN ('StiTestSub1')) AND (id = 10)) LIMIT 1", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub2')", "SELECT * FROM sti_tests WHERE ((sti_tests.kind IN ('StiTestSub2')) AND (id = 10)) LIMIT 1"]
|
|
95
73
|
end
|
|
96
74
|
|
|
97
75
|
it "should have the before_create hook not override an existing value" do
|
|
98
76
|
StiTest.create(:kind=>'StiTestSub1')
|
|
99
|
-
MODEL_DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')"]
|
|
77
|
+
MODEL_DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE (id = 10) LIMIT 1"]
|
|
100
78
|
end
|
|
101
79
|
|
|
102
80
|
it "should have the before_create hook handle columns with the same name as existing method names" do
|
|
103
81
|
StiTest.plugin :single_table_inheritance, :type
|
|
104
82
|
StiTest.columns :id, :type
|
|
105
83
|
StiTest.create
|
|
106
|
-
MODEL_DB.sqls.should == ["INSERT INTO sti_tests (type) VALUES ('StiTest')"]
|
|
84
|
+
MODEL_DB.sqls.should == ["INSERT INTO sti_tests (type) VALUES ('StiTest')", "SELECT * FROM sti_tests WHERE (id = 10) LIMIT 1"]
|
|
107
85
|
end
|
|
108
86
|
|
|
109
87
|
it "should add a filter to model datasets inside subclasses hook to only retreive objects with the matching key" do
|
|
@@ -129,7 +107,7 @@ describe Sequel::Model, "#sti_key" do
|
|
|
129
107
|
before do
|
|
130
108
|
class ::StiTest2 < Sequel::Model
|
|
131
109
|
columns :id, :kind
|
|
132
|
-
def
|
|
110
|
+
def _save_refresh; end
|
|
133
111
|
end
|
|
134
112
|
end
|
|
135
113
|
after do
|
|
@@ -17,70 +17,15 @@ def skip_warn(s)
|
|
|
17
17
|
warn "Skipping test of #{s}" if ENV["SKIPPED_TEST_WARN"]
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def update(*args)
|
|
26
|
-
@db.execute update_sql(*args)
|
|
27
|
-
1
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def delete(*args)
|
|
31
|
-
@db.execute delete_sql(*args)
|
|
32
|
-
1
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def fetch_rows(sql)
|
|
36
|
-
return if sql =~ /information_schema/
|
|
37
|
-
@db.execute(sql)
|
|
38
|
-
yield({:id => 1, :x => 1})
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def quoted_identifier(c)
|
|
42
|
-
"\"#{c}\""
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
class MockDatabase < Sequel::Database
|
|
47
|
-
@@quote_identifiers = false
|
|
48
|
-
self.identifier_input_method = nil
|
|
49
|
-
self.identifier_output_method = nil
|
|
50
|
-
attr_reader :sqls
|
|
51
|
-
|
|
52
|
-
def connect(opts)
|
|
53
|
-
Object.new
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def execute(sql, opts={})
|
|
57
|
-
@sqls ||= []
|
|
58
|
-
@sqls << sql
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def new_sqls
|
|
62
|
-
s = sqls
|
|
63
|
-
reset
|
|
64
|
-
s
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def reset
|
|
68
|
-
@sqls = []
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def schema(table_name, opts)
|
|
72
|
-
[[:id, {:primary_key=>true}]]
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def transaction(opts={}); yield; end
|
|
76
|
-
|
|
77
|
-
def dataset(opts=nil); MockDataset.new(self, opts); end
|
|
78
|
-
end
|
|
20
|
+
Sequel.quote_identifiers = false
|
|
21
|
+
Sequel.identifier_input_method = nil
|
|
22
|
+
Sequel.identifier_output_method = nil
|
|
79
23
|
|
|
80
24
|
class << Sequel::Model
|
|
25
|
+
attr_writer :db_schema
|
|
81
26
|
alias orig_columns columns
|
|
82
27
|
def columns(*cols)
|
|
83
|
-
return
|
|
28
|
+
return super if cols.empty?
|
|
84
29
|
define_method(:columns){cols}
|
|
85
30
|
@dataset.instance_variable_set(:@columns, cols) if @dataset
|
|
86
31
|
def_column_accessor(*cols)
|
|
@@ -88,10 +33,11 @@ class << Sequel::Model
|
|
|
88
33
|
@db_schema = {}
|
|
89
34
|
cols.each{|c| @db_schema[c] = {}}
|
|
90
35
|
end
|
|
91
|
-
def simple_table
|
|
92
|
-
nil
|
|
93
|
-
end
|
|
94
36
|
end
|
|
95
37
|
|
|
96
|
-
Sequel::Model.db = MODEL_DB = MockDatabase.new
|
|
97
38
|
Sequel::Model.use_transactions = false
|
|
39
|
+
|
|
40
|
+
db = Sequel.mock(:fetch=>{:id => 1, :x => 1}, :numrows=>1, :autoid=>proc{|sql| 10})
|
|
41
|
+
def db.schema(*) [[:id, {:primary_key=>true}]] end
|
|
42
|
+
def db.reset() sqls end
|
|
43
|
+
Sequel::Model.db = MODEL_DB = db
|
|
@@ -4,86 +4,46 @@ describe "Sequel sql_expr extension" do
|
|
|
4
4
|
specify "Object#sql_expr should wrap the object in a GenericComplexExpression" do
|
|
5
5
|
o = Object.new
|
|
6
6
|
s = o.sql_expr
|
|
7
|
-
s.should
|
|
8
|
-
s.
|
|
9
|
-
s.
|
|
10
|
-
(s
|
|
11
|
-
(
|
|
12
|
-
(
|
|
13
|
-
s.
|
|
14
|
-
s.
|
|
15
|
-
s.
|
|
16
|
-
s.
|
|
17
|
-
s.desc.should be_a_kind_of(Sequel::SQL::OrderedExpression)
|
|
18
|
-
s.sql_string.should be_a_kind_of(Sequel::SQL::StringExpression)
|
|
7
|
+
s.should == Sequel::SQL::GenericComplexExpression.new(:NOOP, o)
|
|
8
|
+
(s+1).should == Sequel::SQL::NumericExpression.new(:+, s, 1)
|
|
9
|
+
(s & true).should == Sequel::SQL::BooleanExpression.new(:AND, s, true)
|
|
10
|
+
(s < 1).should == Sequel::SQL::BooleanExpression.new(:<, s, 1)
|
|
11
|
+
s.sql_subscript(1).should == Sequel::SQL::Subscript.new(s, [1])
|
|
12
|
+
s.like('a').should == Sequel::SQL::BooleanExpression.new(:LIKE, s, 'a')
|
|
13
|
+
s.as(:a).should == Sequel::SQL::AliasedExpression.new(s, :a)
|
|
14
|
+
s.cast(Integer).should == Sequel::SQL::Cast.new(s, Integer)
|
|
15
|
+
s.desc.should == Sequel::SQL::OrderedExpression.new(s, true)
|
|
16
|
+
s.sql_string.should == Sequel::SQL::StringExpression.new(:NOOP, s)
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
specify "Numeric#sql_expr should wrap the object in a NumericExpression" do
|
|
22
|
-
[1, 2.0, 2^
|
|
23
|
-
|
|
24
|
-
s.should be_a_kind_of(Sequel::SQL::NumericExpression)
|
|
25
|
-
s.op.should == :NOOP
|
|
26
|
-
s.args.should == [o]
|
|
20
|
+
[1, 2.0, 2^70, BigDecimal.new('1.0')].each do |o|
|
|
21
|
+
o.sql_expr.should == Sequel::SQL::NumericExpression.new(:NOOP, o)
|
|
27
22
|
end
|
|
28
23
|
end
|
|
29
24
|
|
|
30
25
|
specify "String#sql_expr should wrap the object in a StringExpression" do
|
|
31
|
-
|
|
32
|
-
s = o.sql_expr
|
|
33
|
-
s.should be_a_kind_of(Sequel::SQL::StringExpression)
|
|
34
|
-
s.op.should == :NOOP
|
|
35
|
-
s.args.should == [o]
|
|
26
|
+
"".sql_expr.should == Sequel::SQL::StringExpression.new(:NOOP, "")
|
|
36
27
|
end
|
|
37
28
|
|
|
38
29
|
specify "NilClass, TrueClass, and FalseClass#sql_expr should wrap the object in a BooleanExpression" do
|
|
39
30
|
[nil, true, false].each do |o|
|
|
40
|
-
|
|
41
|
-
s.should be_a_kind_of(Sequel::SQL::BooleanExpression)
|
|
42
|
-
s.op.should == :NOOP
|
|
43
|
-
s.args.should == [o]
|
|
31
|
+
o.sql_expr.should == Sequel::SQL::BooleanExpression.new(:NOOP, o)
|
|
44
32
|
end
|
|
45
33
|
end
|
|
46
34
|
|
|
47
35
|
specify "Proc#sql_expr should should treat the object as a virtual row block" do
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
s = proc{a__b}.sql_expr
|
|
53
|
-
s.should be_a_kind_of(Sequel::SQL::QualifiedIdentifier)
|
|
54
|
-
s.table.should == "a"
|
|
55
|
-
s.column.should == "b"
|
|
56
|
-
|
|
57
|
-
s = proc{a(b)}.sql_expr
|
|
58
|
-
s.should be_a_kind_of(Sequel::SQL::Function)
|
|
59
|
-
s.f.should == :a
|
|
60
|
-
s.args.length.should == 1
|
|
61
|
-
s.args.first.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
62
|
-
s.args.first.value.should == :b
|
|
36
|
+
proc{a}.sql_expr.should == Sequel::SQL::Identifier.new(:a)
|
|
37
|
+
proc{a__b}.sql_expr.should == Sequel::SQL::QualifiedIdentifier.new('a', 'b')
|
|
38
|
+
proc{a(b)}.sql_expr.should == Sequel::SQL::Function.new(:a, Sequel::SQL::Identifier.new(:b))
|
|
63
39
|
end
|
|
64
40
|
|
|
65
41
|
specify "Proc#sql_expr should should wrap the object in a GenericComplexExpression if the object is not already an expression" do
|
|
66
|
-
|
|
67
|
-
s.should be_a_kind_of(Sequel::SQL::GenericComplexExpression)
|
|
68
|
-
s.op.should == :NOOP
|
|
69
|
-
s.args.should == [1]
|
|
42
|
+
proc{1}.sql_expr.should == Sequel::SQL::GenericComplexExpression.new(:NOOP, 1)
|
|
70
43
|
end
|
|
71
44
|
|
|
72
45
|
specify "Proc#sql_expr should should convert a hash or array of two element arrays to a BooleanExpression" do
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
s.op.should == :"="
|
|
76
|
-
s.args.first.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
77
|
-
s.args.first.value.should == :a
|
|
78
|
-
s.args.last.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
79
|
-
s.args.last.value.should == :b
|
|
80
|
-
|
|
81
|
-
s = proc{[[a,b]]}.sql_expr
|
|
82
|
-
s.should be_a_kind_of(Sequel::SQL::BooleanExpression)
|
|
83
|
-
s.op.should == :"="
|
|
84
|
-
s.args.first.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
85
|
-
s.args.first.value.should == :a
|
|
86
|
-
s.args.last.should be_a_kind_of(Sequel::SQL::Identifier)
|
|
87
|
-
s.args.last.value.should == :b
|
|
46
|
+
proc{{a=>b}}.sql_expr.should == Sequel::SQL::BooleanExpression.new(:'=', Sequel::SQL::Identifier.new(:a), Sequel::SQL::Identifier.new(:b))
|
|
47
|
+
proc{[[a,b]]}.sql_expr.should == Sequel::SQL::BooleanExpression.new(:'=', Sequel::SQL::Identifier.new(:a), Sequel::SQL::Identifier.new(:b))
|
|
88
48
|
end
|
|
89
49
|
end
|
|
@@ -7,23 +7,13 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
|
7
7
|
columns :id, :parent_id
|
|
8
8
|
many_to_one :parent, :class=>self
|
|
9
9
|
one_to_many :children, :class=>self, :key=>:parent_id
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
yield(:id=>101, :parent_id=>nil)
|
|
18
|
-
yield(:id=>102, :parent_id=>nil)
|
|
19
|
-
elsif where.args.first.column == :id
|
|
20
|
-
Array(where.args.last).each do |x|
|
|
21
|
-
yield(:id=>x, :parent_id=>nil)
|
|
22
|
-
end
|
|
23
|
-
elsif where.args.first.column == :parent_id
|
|
24
|
-
Array(where.args.last).each do |x|
|
|
25
|
-
yield(:id=>x-100, :parent_id=>x) if x > 100
|
|
26
|
-
end
|
|
10
|
+
dataset._fetch = proc do |sql|
|
|
11
|
+
if sql !~ /WHERE/
|
|
12
|
+
[{:id=>1, :parent_id=>101}, {:id=>2, :parent_id=>102}, {:id=>101, :parent_id=>nil}, {:id=>102, :parent_id=>nil}]
|
|
13
|
+
elsif sql =~ /WHERE.*\bid IN \(([\d, ]*)\)/
|
|
14
|
+
$1.split(', ').map{|x| {:id=>x.to_i, :parent_id=>nil}}
|
|
15
|
+
elsif sql =~ /WHERE.*\bparent_id IN \(([\d, ]*)\)/
|
|
16
|
+
$1.split(', ').map{|x| {:id=>x.to_i - 100, :parent_id=>x.to_i} if x.to_i > 100}.compact
|
|
27
17
|
end
|
|
28
18
|
end
|
|
29
19
|
end
|
|
@@ -49,9 +39,9 @@ describe "Sequel::Plugins::TacticalEagerLoading" do
|
|
|
49
39
|
ts = @c.all
|
|
50
40
|
MODEL_DB.sqls.length.should == 1
|
|
51
41
|
ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
|
|
52
|
-
MODEL_DB.sqls.length.should ==
|
|
42
|
+
MODEL_DB.sqls.length.should == 1
|
|
53
43
|
ts.map{|x| x.children}.should == [[], [], [ts[0]], [ts[1]]]
|
|
54
|
-
MODEL_DB.sqls.length.should ==
|
|
44
|
+
MODEL_DB.sqls.length.should == 1
|
|
55
45
|
end
|
|
56
46
|
|
|
57
47
|
it "association getter methods should not eagerly load the association if the association is cached" do
|
|
@@ -13,9 +13,10 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
13
13
|
@c.class_eval do
|
|
14
14
|
columns :id, :created_at, :updated_at
|
|
15
15
|
plugin :timestamps
|
|
16
|
+
def _save_refresh(*) end
|
|
16
17
|
db.reset
|
|
17
|
-
def _refresh(ds); self end
|
|
18
18
|
end
|
|
19
|
+
@c.dataset.autoid = nil
|
|
19
20
|
end
|
|
20
21
|
after do
|
|
21
22
|
Sequel.datetime_class = Time
|
|
@@ -40,8 +41,9 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
40
41
|
it "should use the same value for the creation and update timestamps when creating if the :update_on_create option is given" do
|
|
41
42
|
@c.plugin :timestamps, :update_on_create=>true
|
|
42
43
|
o = @c.create
|
|
43
|
-
@c.db.sqls
|
|
44
|
-
|
|
44
|
+
sqls = @c.db.sqls
|
|
45
|
+
sqls.shift.should =~ /INSERT INTO t \((creat|updat)ed_at, (creat|updat)ed_at\) VALUES \('2009-08-01', '2009-08-01'\)/
|
|
46
|
+
sqls.should == []
|
|
45
47
|
o.created_at.should === o.updated_at
|
|
46
48
|
end
|
|
47
49
|
|
|
@@ -50,8 +52,7 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
50
52
|
c.class_eval do
|
|
51
53
|
columns :id, :c
|
|
52
54
|
plugin :timestamps, :create=>:c
|
|
53
|
-
|
|
54
|
-
def _refresh(ds); self end
|
|
55
|
+
def _save_refresh(*) end
|
|
55
56
|
end
|
|
56
57
|
o = c.create
|
|
57
58
|
c.db.sqls.should == ["INSERT INTO t (c) VALUES ('2009-08-01')"]
|
|
@@ -64,7 +65,6 @@ describe "Sequel::Plugins::Timestamps" do
|
|
|
64
65
|
columns :id, :u
|
|
65
66
|
plugin :timestamps, :update=>:u
|
|
66
67
|
db.reset
|
|
67
|
-
def _refresh(ds); self end
|
|
68
68
|
end
|
|
69
69
|
o = c.load(:id=>1).save
|
|
70
70
|
c.db.sqls.should == ["UPDATE t SET u = '2009-08-01' WHERE (id = 1)"]
|
|
@@ -11,14 +11,13 @@ describe Sequel::Model, "to_dot extension" do
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
it "should output a string suitable for input to the graphviz dot program" do
|
|
14
|
-
@ds.to_dot.should == (<<END
|
|
14
|
+
@ds.to_dot.should == (<<END).strip
|
|
15
15
|
digraph G {
|
|
16
16
|
0 [label="self"];
|
|
17
17
|
0 -> 1 [label=""];
|
|
18
18
|
1 [label="Dataset"];
|
|
19
19
|
}
|
|
20
20
|
END
|
|
21
|
-
).strip
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
it "should handle an empty dataset" do
|
|
@@ -2,9 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
2
2
|
|
|
3
3
|
describe "Touch plugin" do
|
|
4
4
|
before do
|
|
5
|
-
@c = Class.new(Sequel::Model)
|
|
6
|
-
def _refresh(*); end
|
|
7
|
-
end
|
|
5
|
+
@c = Class.new(Sequel::Model)
|
|
8
6
|
p = proc{def touch_instance_value; touch_association_value; end}
|
|
9
7
|
@Artist = Class.new(@c, &p).set_dataset(:artists)
|
|
10
8
|
@Album = Class.new(@c, &p).set_dataset(:albums)
|
|
@@ -63,8 +61,9 @@ describe "Touch plugin" do
|
|
|
63
61
|
specify "should be able to give an array to the :associations option specifying multiple associations" do
|
|
64
62
|
@Album.plugin :touch, :associations=>[:artist, :followup_albums]
|
|
65
63
|
@Album.load(:id=>4, :artist_id=>1).touch
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
sqls = MODEL_DB.sqls
|
|
65
|
+
sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
|
|
66
|
+
sqls.sort.should == ["UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
68
67
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
69
68
|
end
|
|
70
69
|
|
|
@@ -85,8 +84,9 @@ describe "Touch plugin" do
|
|
|
85
84
|
specify "should allow the mixed use of symbols and hashes inside an array for the :associations option" do
|
|
86
85
|
@Album.plugin :touch, :associations=>[:artist, {:followup_albums=>:modified_on}]
|
|
87
86
|
@Album.load(:id=>4, :artist_id=>1).touch
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
sqls = MODEL_DB.sqls
|
|
88
|
+
sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
|
|
89
|
+
sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
90
90
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
91
91
|
end
|
|
92
92
|
|
|
@@ -94,8 +94,9 @@ describe "Touch plugin" do
|
|
|
94
94
|
@Album.plugin :touch
|
|
95
95
|
@Album.touch_associations(:artist, {:followup_albums=>:modified_on})
|
|
96
96
|
@Album.load(:id=>4, :artist_id=>1).touch
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
sqls = MODEL_DB.sqls
|
|
98
|
+
sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
|
|
99
|
+
sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
99
100
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
100
101
|
end
|
|
101
102
|
|
|
@@ -103,8 +104,9 @@ describe "Touch plugin" do
|
|
|
103
104
|
@Album.plugin :touch
|
|
104
105
|
@Album.touch_associations(:artist, {:followup_albums=>:modified_on})
|
|
105
106
|
@Album.load(:id=>4, :artist_id=>1).destroy
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
sqls = MODEL_DB.sqls
|
|
108
|
+
sqls.shift.should == "DELETE FROM albums WHERE (id = 4)"
|
|
109
|
+
sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
|
|
108
110
|
"UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
|
|
109
111
|
end
|
|
110
112
|
|
|
@@ -133,18 +135,15 @@ describe "Touch plugin" do
|
|
|
133
135
|
c1 = Class.new(@Artist)
|
|
134
136
|
c1.load(:id=>4).touch
|
|
135
137
|
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"]
|
|
136
|
-
MODEL_DB.reset
|
|
137
138
|
|
|
138
139
|
c1.touch_column = :modified_on
|
|
139
140
|
c1.touch_associations :albums
|
|
140
141
|
c1.load(:id=>1).touch
|
|
141
142
|
MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)",
|
|
142
143
|
"UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
|
|
143
|
-
MODEL_DB.reset
|
|
144
144
|
|
|
145
145
|
@a.touch
|
|
146
146
|
MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
|
147
|
-
MODEL_DB.reset
|
|
148
147
|
|
|
149
148
|
@Artist.plugin :touch, :column=>:modified_on, :associations=>:albums
|
|
150
149
|
c2 = Class.new(@Artist)
|