sequel 4.12.0 → 4.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +64 -0
- data/Rakefile +3 -1
- data/bin/sequel +13 -5
- data/doc/release_notes/4.13.0.txt +169 -0
- data/doc/sql.rdoc +3 -3
- data/lib/sequel/adapters/do.rb +11 -23
- data/lib/sequel/adapters/do/mysql.rb +8 -0
- data/lib/sequel/adapters/do/postgres.rb +8 -0
- data/lib/sequel/adapters/do/{sqlite.rb → sqlite3.rb} +9 -0
- data/lib/sequel/adapters/jdbc.rb +16 -139
- data/lib/sequel/adapters/jdbc/as400.rb +9 -0
- data/lib/sequel/adapters/jdbc/cubrid.rb +9 -0
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +9 -0
- data/lib/sequel/adapters/jdbc/{firebird.rb → firebirdsql.rb} +9 -0
- data/lib/sequel/adapters/jdbc/h2.rb +10 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +9 -0
- data/lib/sequel/adapters/jdbc/{informix.rb → informix-sqli.rb} +9 -0
- data/lib/sequel/adapters/jdbc/{progress.rb → jdbcprogress.rb} +9 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +10 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +14 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +9 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -0
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +23 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +10 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +10 -0
- data/lib/sequel/adapters/odbc.rb +6 -14
- data/lib/sequel/adapters/odbc/db2.rb +9 -0
- data/lib/sequel/adapters/odbc/mssql.rb +8 -0
- data/lib/sequel/adapters/odbc/progress.rb +8 -0
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +1 -1
- data/lib/sequel/adapters/shared/firebird.rb +8 -1
- data/lib/sequel/adapters/shared/mssql.rb +68 -27
- data/lib/sequel/adapters/shared/mysql.rb +3 -5
- data/lib/sequel/adapters/shared/oracle.rb +17 -3
- data/lib/sequel/adapters/shared/postgres.rb +9 -4
- data/lib/sequel/adapters/shared/sqlanywhere.rb +6 -6
- data/lib/sequel/database/connecting.rb +38 -17
- data/lib/sequel/dataset/actions.rb +6 -2
- data/lib/sequel/dataset/graph.rb +18 -20
- data/lib/sequel/dataset/misc.rb +37 -0
- data/lib/sequel/dataset/prepared_statements.rb +1 -2
- data/lib/sequel/dataset/query.rb +1 -0
- data/lib/sequel/dataset/sql.rb +17 -10
- data/lib/sequel/extensions/dataset_source_alias.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +14 -10
- data/lib/sequel/extensions/pg_enum.rb +135 -0
- data/lib/sequel/extensions/pg_hstore.rb +4 -6
- data/lib/sequel/extensions/pg_inet.rb +4 -5
- data/lib/sequel/extensions/pg_interval.rb +3 -3
- data/lib/sequel/extensions/pg_json.rb +16 -12
- data/lib/sequel/extensions/pg_range.rb +5 -3
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/round_timestamps.rb +52 -0
- data/lib/sequel/model.rb +5 -2
- data/lib/sequel/model/associations.rb +29 -3
- data/lib/sequel/model/base.rb +68 -29
- data/lib/sequel/plugins/class_table_inheritance.rb +25 -16
- data/lib/sequel/plugins/column_select.rb +57 -0
- data/lib/sequel/plugins/composition.rb +14 -16
- data/lib/sequel/plugins/dirty.rb +9 -11
- data/lib/sequel/plugins/insert_returning_select.rb +70 -0
- data/lib/sequel/plugins/instance_filters.rb +7 -9
- data/lib/sequel/plugins/lazy_attributes.rb +16 -4
- data/lib/sequel/plugins/list.rb +9 -0
- data/lib/sequel/plugins/modification_detection.rb +90 -0
- data/lib/sequel/plugins/serialization.rb +13 -15
- data/lib/sequel/plugins/serialization_modification_detection.rb +9 -9
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/timestamps.rb +6 -6
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +7 -0
- data/spec/adapters/postgres_spec.rb +41 -0
- data/spec/bin_spec.rb +4 -1
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +100 -90
- data/spec/core/object_graph_spec.rb +5 -0
- data/spec/extensions/class_table_inheritance_spec.rb +18 -13
- data/spec/extensions/column_select_spec.rb +108 -0
- data/spec/extensions/composition_spec.rb +20 -0
- data/spec/extensions/dataset_source_alias_spec.rb +51 -0
- data/spec/extensions/insert_returning_select_spec.rb +46 -0
- data/spec/extensions/lazy_attributes_spec.rb +24 -20
- data/spec/extensions/list_spec.rb +5 -0
- data/spec/extensions/modification_detection_spec.rb +80 -0
- data/spec/extensions/pg_enum_spec.rb +64 -0
- data/spec/extensions/pg_json_spec.rb +7 -13
- data/spec/extensions/prepared_statements_spec.rb +6 -4
- data/spec/extensions/round_timestamps_spec.rb +43 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +10 -1
- data/spec/extensions/serialization_spec.rb +18 -0
- data/spec/extensions/single_table_inheritance_spec.rb +5 -0
- data/spec/extensions/timestamps_spec.rb +6 -0
- data/spec/integration/plugin_test.rb +14 -8
- data/spec/integration/prepared_statement_test.rb +12 -0
- data/spec/model/associations_spec.rb +24 -0
- data/spec/model/model_spec.rb +13 -3
- data/spec/model/record_spec.rb +24 -1
- metadata +22 -6
@@ -106,6 +106,11 @@ describe "List plugin" do
|
|
106
106
|
"SELECT * FROM items WHERE (id = 3) ORDER BY scope_id, position LIMIT 1"]
|
107
107
|
end
|
108
108
|
|
109
|
+
it "should update positions automatically on deletion" do
|
110
|
+
@o.destroy
|
111
|
+
@db.sqls.should == ["DELETE FROM items WHERE (id = 7)", "UPDATE items SET position = (position - 1) WHERE (position > 3)"]
|
112
|
+
end
|
113
|
+
|
109
114
|
it "should have last_position return the last position in the list" do
|
110
115
|
@c.dataset._fetch = {:max=>10}
|
111
116
|
@o.last_position.should == 10
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe "serialization_modification_detection plugin" do
|
5
|
+
before do
|
6
|
+
@ds = Sequel.mock(:fetch=>{:id=>1, :a=>'a', :b=>1, :c=>['a'], :d=>{'b'=>'c'}}, :numrows=>1, :autoid=>1)[:items]
|
7
|
+
@c = Class.new(Sequel::Model(@ds))
|
8
|
+
@c.plugin :modification_detection
|
9
|
+
@c.columns :a, :b, :c, :d
|
10
|
+
@o = @c.first
|
11
|
+
@ds.db.sqls
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should only detect columns that have been changed" do
|
15
|
+
@o.changed_columns.should == []
|
16
|
+
@o.a << 'b'
|
17
|
+
@o.changed_columns.should == [:a]
|
18
|
+
@o.a.replace('a')
|
19
|
+
@o.changed_columns.should == []
|
20
|
+
|
21
|
+
@o.values[:b] = 2
|
22
|
+
@o.changed_columns.should == [:b]
|
23
|
+
@o.values[:b] = 1
|
24
|
+
@o.changed_columns.should == []
|
25
|
+
|
26
|
+
@o.c[0] << 'b'
|
27
|
+
@o.d['b'] << 'b'
|
28
|
+
@o.changed_columns.sort_by{|c| c.to_s}.should == [:c, :d]
|
29
|
+
@o.c[0] = 'a'
|
30
|
+
@o.changed_columns.should == [:d]
|
31
|
+
@o.d['b'] = 'c'
|
32
|
+
@o.changed_columns.should == []
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should not list a column twice" do
|
36
|
+
@o.a = 'b'
|
37
|
+
@o.a << 'a'
|
38
|
+
@o.changed_columns.should == [:a]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should report correct changed_columns after updating" do
|
42
|
+
@o.a << 'a'
|
43
|
+
@o.save_changes
|
44
|
+
@o.changed_columns.should == []
|
45
|
+
|
46
|
+
@o.values[:b] = 2
|
47
|
+
@o.save_changes
|
48
|
+
@o.changed_columns.should == []
|
49
|
+
|
50
|
+
@o.c[0] << 'b'
|
51
|
+
@o.save_changes
|
52
|
+
@o.changed_columns.should == []
|
53
|
+
|
54
|
+
@o.d['b'] << 'a'
|
55
|
+
@o.save_changes
|
56
|
+
@o.changed_columns.should == []
|
57
|
+
|
58
|
+
@ds.db.sqls.should == ["UPDATE items SET a = 'aa' WHERE (id = 1)",
|
59
|
+
"UPDATE items SET b = 2 WHERE (id = 1)",
|
60
|
+
"UPDATE items SET c = ('ab') WHERE (id = 1)",
|
61
|
+
"UPDATE items SET d = ('b' = 'ca') WHERE (id = 1)"]
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should report correct changed_columns after creating new object" do
|
65
|
+
o = @c.create
|
66
|
+
o.changed_columns.should == []
|
67
|
+
o.a << 'a'
|
68
|
+
o.changed_columns.should == [:a]
|
69
|
+
@ds.db.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should report correct changed_columns after refreshing existing object" do
|
73
|
+
@o.a << 'a'
|
74
|
+
@o.changed_columns.should == [:a]
|
75
|
+
@o.refresh
|
76
|
+
@o.changed_columns.should == []
|
77
|
+
@o.a << 'a'
|
78
|
+
@o.changed_columns.should == [:a]
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
describe "pg_inet extension" do
|
4
|
+
before do
|
5
|
+
@db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
|
6
|
+
@db.extend(Module.new do
|
7
|
+
def schema_parse_table(*)
|
8
|
+
[[:a, {:oid=>1}]]
|
9
|
+
end
|
10
|
+
end)
|
11
|
+
@db.send(:metadata_dataset)._fetch = [[{:v=>1, :enumlabel=>'a'}, {:v=>1, :enumlabel=>'b'}, {:v=>1, :enumlabel=>'c'}],
|
12
|
+
[{:typname=>'enum1', :v=>212389}]]
|
13
|
+
@db.extension(:pg_array, :pg_enum)
|
14
|
+
@db.sqls
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should include enum information in the schema entry" do
|
18
|
+
@db.schema(:a).should == [[:a, {:oid=>1, :ruby_default=>nil, :type=>:enum, :enum_values=>%w'a b c'}]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should typecast objects to string" do
|
22
|
+
@db.typecast_value(:enum, :a).should == 'a'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should add array parsers for enum values" do
|
26
|
+
@db.conversion_procs[212389].call('{a,b,c}').should == %w'a b c'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should support #create_enum method for adding a new enum" do
|
30
|
+
@db.create_enum(:foo, [:a, :b, :c])
|
31
|
+
@db.sqls.first.should == "CREATE TYPE foo AS ENUM ('a', 'b', 'c')"
|
32
|
+
@db.create_enum(:sch__foo, %w'a b c')
|
33
|
+
@db.sqls.first.should == "CREATE TYPE sch.foo AS ENUM ('a', 'b', 'c')"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should support #drop_enum method for dropping an enum" do
|
37
|
+
@db.drop_enum(:foo)
|
38
|
+
@db.sqls.first.should == "DROP TYPE foo"
|
39
|
+
@db.drop_enum(:sch__foo, :if_exists=>true)
|
40
|
+
@db.sqls.first.should == "DROP TYPE IF EXISTS sch.foo"
|
41
|
+
@db.drop_enum('foo', :cascade=>true)
|
42
|
+
@db.sqls.first.should == "DROP TYPE foo CASCADE"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should support #add_enum_value method for adding value to an existing enum" do
|
46
|
+
@db.add_enum_value(:foo, :a)
|
47
|
+
@db.sqls.first.should == "ALTER TYPE foo ADD VALUE 'a'"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should support :before option for #add_enum_value method for adding value before an existing enum value" do
|
51
|
+
@db.add_enum_value('foo', :a, :before=>:b)
|
52
|
+
@db.sqls.first.should == "ALTER TYPE foo ADD VALUE 'a' BEFORE 'b'"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should support :after option for #add_enum_value method for adding value after an existing enum value" do
|
56
|
+
@db.add_enum_value(:sch__foo, :a, :after=>:b)
|
57
|
+
@db.sqls.first.should == "ALTER TYPE sch.foo ADD VALUE 'a' AFTER 'b'"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should support :if_not_exists option for #add_enum_value method for not adding the value if it exists" do
|
61
|
+
@db.add_enum_value(:foo, :a, :if_not_exists=>true)
|
62
|
+
@db.sqls.first.should == "ALTER TYPE foo ADD VALUE IF NOT EXISTS 'a'"
|
63
|
+
end
|
64
|
+
end
|
@@ -10,17 +10,6 @@ describe "pg_json extension" do
|
|
10
10
|
@ac = m::JSONArray
|
11
11
|
@bhc = m::JSONBHash
|
12
12
|
@bac = m::JSONBArray
|
13
|
-
|
14
|
-
# Create subclass in correct namespace for easily overriding methods
|
15
|
-
j = m::JSON = JSON.dup
|
16
|
-
j.instance_eval do
|
17
|
-
Parser = JSON::Parser
|
18
|
-
alias old_parse parse
|
19
|
-
def parse(s)
|
20
|
-
return 1 if s == '1'
|
21
|
-
old_parse(s)
|
22
|
-
end
|
23
|
-
end
|
24
13
|
end
|
25
14
|
before do
|
26
15
|
@db = Sequel.connect('mock://postgres', :quote_identifiers=>false)
|
@@ -64,10 +53,15 @@ describe "pg_json extension" do
|
|
64
53
|
Sequel.instance_eval do
|
65
54
|
alias pj parse_json
|
66
55
|
def parse_json(v)
|
67
|
-
v
|
56
|
+
{'1'=>1, "'a'"=>'a', 'true'=>true, 'false'=>false, 'null'=>nil, 'o'=>Object.new}.fetch(v){pj(v)}
|
68
57
|
end
|
69
58
|
end
|
70
|
-
|
59
|
+
@m.parse_json('1').should == 1
|
60
|
+
@m.parse_json("'a'").should == 'a'
|
61
|
+
@m.parse_json('true').should == true
|
62
|
+
@m.parse_json('false').should == false
|
63
|
+
@m.parse_json('null').should == nil
|
64
|
+
proc{@m.parse_json('o')}.should raise_error(Sequel::InvalidValue)
|
71
65
|
ensure
|
72
66
|
Sequel.instance_eval do
|
73
67
|
alias parse_json pj
|
@@ -38,13 +38,15 @@ describe "prepared_statements plugin" do
|
|
38
38
|
def supports_insert_select?
|
39
39
|
true
|
40
40
|
end
|
41
|
+
def supports_returning?(type)
|
42
|
+
true
|
43
|
+
end
|
41
44
|
def insert_select(h)
|
42
45
|
self._fetch = {:id=>1, :name=>'foo', :i => 2}
|
43
|
-
|
44
|
-
ds.server(:default).with_sql(:insert_sql, h).first
|
46
|
+
server(:default).with_sql_first(insert_select_sql(h))
|
45
47
|
end
|
46
|
-
def
|
47
|
-
"#{
|
48
|
+
def insert_select_sql(*v)
|
49
|
+
"#{insert_sql(*v)} RETURNING #{(opts[:returning] && !opts[:returning].empty?) ? opts[:returning].map{|c| literal(c)}.join(', ') : '*'}"
|
48
50
|
end
|
49
51
|
end
|
50
52
|
@c.create(:name=>'foo').should == @c.load(:id=>1, :name=>'foo', :i => 2)
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
2
|
+
|
3
|
+
if RUBY_VERSION >= '1.9.0'
|
4
|
+
describe "Sequel::Dataset::RoundTimestamps" do
|
5
|
+
before do
|
6
|
+
@dataset = Sequel.mock.dataset.extension(:round_timestamps)
|
7
|
+
end
|
8
|
+
|
9
|
+
specify "should round times properly for databases supporting microsecond precision" do
|
10
|
+
@dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499999.5)).should == "'01:02:03.500000'"
|
11
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4999995)).should == "'2010-01-02 03:04:05.500000'"
|
12
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54999995, 10000000))).should == "'2010-01-02 03:04:05.500000'"
|
13
|
+
|
14
|
+
@dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499999.4)).should == "'01:02:03.499999'"
|
15
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4999994)).should == "'2010-01-02 03:04:05.499999'"
|
16
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54999994, 10000000))).should == "'2010-01-02 03:04:05.499999'"
|
17
|
+
end
|
18
|
+
|
19
|
+
specify "should round times properly for databases supporting millisecond precision" do
|
20
|
+
def @dataset.timestamp_precision() 3 end
|
21
|
+
@dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499500)).should == "'01:02:03.500'"
|
22
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4995)).should == "'2010-01-02 03:04:05.500'"
|
23
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54995, 10000))).should == "'2010-01-02 03:04:05.500'"
|
24
|
+
|
25
|
+
@dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499499)).should == "'01:02:03.499'"
|
26
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4994)).should == "'2010-01-02 03:04:05.499'"
|
27
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54994, 10000))).should == "'2010-01-02 03:04:05.499'"
|
28
|
+
end
|
29
|
+
|
30
|
+
specify "should round times properly for databases supporting second precision" do
|
31
|
+
def @dataset.supports_timestamp_usecs?() false end
|
32
|
+
@dataset.literal(Sequel::SQLTime.create(1, 2, 3, 500000)).should == "'01:02:04'"
|
33
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.5)).should == "'2010-01-02 03:04:06'"
|
34
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(55, 10))).should == "'2010-01-02 03:04:06'"
|
35
|
+
|
36
|
+
@dataset.literal(Sequel::SQLTime.create(1, 2, 3, 499999)).should == "'01:02:03'"
|
37
|
+
@dataset.literal(Time.local(2010, 1, 2, 3, 4, 5.4999999)).should == "'2010-01-02 03:04:05'"
|
38
|
+
@dataset.literal(DateTime.new(2010, 1, 2, 3, 4, Rational(54999999, 10000000))).should == "'2010-01-02 03:04:05'"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
skip_warn "round_timestamps extension: only works on ruby 1.9+"
|
43
|
+
end
|
@@ -78,7 +78,7 @@ describe "serialization_modification_detection plugin" do
|
|
78
78
|
@o1.changed_columns.should == [:h]
|
79
79
|
end
|
80
80
|
|
81
|
-
it "should work with
|
81
|
+
it "should work with duplicating objects" do
|
82
82
|
@o2.changed_columns.should == []
|
83
83
|
o = @o2.dup
|
84
84
|
@o2.h.should == {}
|
@@ -86,4 +86,13 @@ describe "serialization_modification_detection plugin" do
|
|
86
86
|
@o2.changed_columns.should == [:h]
|
87
87
|
o.changed_columns.should == []
|
88
88
|
end
|
89
|
+
|
90
|
+
it "should work with duplicating objects after modifying them" do
|
91
|
+
@o2.changed_columns.should == []
|
92
|
+
@o2.h.should == {}
|
93
|
+
@o2.h[1] = 2
|
94
|
+
@o2.changed_columns.should == [:h]
|
95
|
+
o = @o2.dup
|
96
|
+
o.changed_columns.should == [:h]
|
97
|
+
end
|
89
98
|
end
|
@@ -26,6 +26,24 @@ describe "Serialization plugin" do
|
|
26
26
|
DB.sqls.last.should =~ /INSERT INTO items \((ghi)\) VALUES \('\[123\]'\)/
|
27
27
|
end
|
28
28
|
|
29
|
+
it "should handle validations of underlying column" do
|
30
|
+
@c.plugin :serialization, :yaml, :abc
|
31
|
+
o = @c.new
|
32
|
+
def o.validate
|
33
|
+
errors.add(:abc, "not present") unless self[:abc]
|
34
|
+
end
|
35
|
+
o.valid?.should == false
|
36
|
+
o.abc = {}
|
37
|
+
o.valid?.should == true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should set column values even when not validating" do
|
41
|
+
@c.set_primary_key :id
|
42
|
+
@c.plugin :serialization, :yaml, :abc
|
43
|
+
@c.load({:id=>1}).set(:abc=>{}).save(:validate=>false)
|
44
|
+
DB.sqls.last.gsub("\n", '').should == "UPDATE items SET abc = '--- {}' WHERE (id = 1)"
|
45
|
+
end
|
46
|
+
|
29
47
|
it "should allow serializing attributes to yaml" do
|
30
48
|
@c.plugin :serialization, :yaml, :abc
|
31
49
|
@c.create(:abc => 1)
|
@@ -85,6 +85,11 @@ describe Sequel::Model, "single table inheritance plugin" do
|
|
85
85
|
o.valid?.should == true
|
86
86
|
end
|
87
87
|
|
88
|
+
it "should set type column field even if validations are skipped" do
|
89
|
+
StiTestSub1.new.save(:validate=>false)
|
90
|
+
DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE ((sti_tests.kind IN ('StiTestSub1')) AND (id = 10)) LIMIT 1"]
|
91
|
+
end
|
92
|
+
|
88
93
|
it "should override an existing value in the class name field" do
|
89
94
|
StiTest.create(:kind=>'StiTestSub1')
|
90
95
|
DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE (id = 10) LIMIT 1"]
|
@@ -32,6 +32,12 @@ describe "Sequel::Plugins::Timestamps" do
|
|
32
32
|
o.valid?.should == true
|
33
33
|
end
|
34
34
|
|
35
|
+
it "should set timestamp fields when skipping validations" do
|
36
|
+
@c.plugin :timestamps
|
37
|
+
@c.new.save(:validate=>false)
|
38
|
+
@c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
|
39
|
+
end
|
40
|
+
|
35
41
|
it "should set the create timestamp field on creation" do
|
36
42
|
o = @c.create
|
37
43
|
@c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
|
@@ -1,8 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
2
2
|
|
3
|
-
# DB2 does not seem to support USING joins in every version; it seems to be
|
4
|
-
# valid expression in DB2 iSeries UDB though.
|
5
|
-
unless !DB.dataset.supports_join_using? || Sequel.guarded?(:db2)
|
6
3
|
describe "Class Table Inheritance Plugin" do
|
7
4
|
before(:all) do
|
8
5
|
@db = DB
|
@@ -37,7 +34,7 @@ describe "Class Table Inheritance Plugin" do
|
|
37
34
|
class ::Executive < Manager
|
38
35
|
end
|
39
36
|
class ::Staff < Employee
|
40
|
-
many_to_one :manager
|
37
|
+
many_to_one :manager
|
41
38
|
end
|
42
39
|
|
43
40
|
@i1 =@db[:employees].insert(:name=>'E', :kind=>'Employee')
|
@@ -96,10 +93,10 @@ describe "Class Table Inheritance Plugin" do
|
|
96
93
|
end
|
97
94
|
|
98
95
|
specify "should handle associations only defined in subclasses" do
|
99
|
-
Employee.filter(:
|
96
|
+
Employee.filter(:employees__id=>@i2).all.first.manager.id.should == @i4
|
100
97
|
end
|
101
98
|
|
102
|
-
|
99
|
+
specify "should insert rows into all tables" do
|
103
100
|
e = Executive.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
|
104
101
|
i = e.id
|
105
102
|
@db[:employees][:id=>i].should == {:id=>i, :name=>'Ex2', :kind=>'Executive'}
|
@@ -138,13 +135,12 @@ describe "Class Table Inheritance Plugin" do
|
|
138
135
|
Executive.limit(1).eager(:staff_members).first.staff_members.should == [Staff[@i2]]
|
139
136
|
end
|
140
137
|
|
141
|
-
|
138
|
+
specify "should handle eagerly graphing one_to_many relationships" do
|
142
139
|
es = Executive.limit(1).eager_graph(:staff_members).all
|
143
140
|
es.should == [Executive[@i4]]
|
144
141
|
es.map{|x| x.staff_members}.should == [[Staff[@i2]]]
|
145
142
|
end
|
146
143
|
end
|
147
|
-
end
|
148
144
|
|
149
145
|
describe "Many Through Many Plugin" do
|
150
146
|
before(:all) do
|
@@ -1494,6 +1490,11 @@ describe "List plugin without a scope" do
|
|
1494
1490
|
proc { @c[:name => "def"].move_up(10) }.should raise_error(Sequel::Error)
|
1495
1491
|
proc { @c[:name => "def"].move_down(10) }.should raise_error(Sequel::Error)
|
1496
1492
|
end
|
1493
|
+
|
1494
|
+
it "should update positions on destroy" do
|
1495
|
+
@c[:name => "def"].destroy
|
1496
|
+
@c.select_map([:position, :name]).should == [[1, 'abc'], [2, 'hig']]
|
1497
|
+
end
|
1497
1498
|
end
|
1498
1499
|
|
1499
1500
|
describe "List plugin with a scope" do
|
@@ -1572,6 +1573,11 @@ describe "List plugin with a scope" do
|
|
1572
1573
|
proc { @c[:name => "P1"].move_up(10) }.should raise_error(Sequel::Error)
|
1573
1574
|
proc { @c[:name => "P1"].move_down(10) }.should raise_error(Sequel::Error)
|
1574
1575
|
end
|
1576
|
+
|
1577
|
+
it "should update positions on destroy" do
|
1578
|
+
@c[:name => "P2"].destroy
|
1579
|
+
@c.select_order_map([:pos, :name]).should == [[1, "Hm"], [1, "P1"], [1, "Ps"], [2, "Au"], [2, "P3"]]
|
1580
|
+
end
|
1575
1581
|
end
|
1576
1582
|
|
1577
1583
|
describe "Sequel::Plugins::Tree" do
|
@@ -117,6 +117,12 @@ describe "Prepared Statements and Bound Arguments" do
|
|
117
117
|
@ds.filter(:id=>2).first[:numb].should == 20
|
118
118
|
end
|
119
119
|
|
120
|
+
specify "should support bound variables with insert_select" do
|
121
|
+
@ds.call(:insert_select, {:n=>20}, :numb=>:$n).should == {:id=>2, :numb=>20}
|
122
|
+
@ds.count.should == 2
|
123
|
+
@ds.order(:id).map(:numb).should == [10, 20]
|
124
|
+
end if DB.dataset.supports_insert_select?
|
125
|
+
|
120
126
|
specify "should support bound variables with delete" do
|
121
127
|
@ds.filter(:numb=>:$n).call(:delete, :n=>10).should == 1
|
122
128
|
@ds.count.should == 0
|
@@ -228,6 +234,12 @@ describe "Prepared Statements and Bound Arguments" do
|
|
228
234
|
@ds.filter(:id=>2).first[:numb].should == 20
|
229
235
|
end
|
230
236
|
|
237
|
+
specify "should support prepared_statements with insert_select" do
|
238
|
+
@ds.prepare(:insert_select, :insert_select_n, :numb=>:$n).call(:n=>20).should == {:id=>2, :numb=>20}
|
239
|
+
@ds.count.should == 2
|
240
|
+
@ds.order(:id).map(:numb).should == [10, 20]
|
241
|
+
end if DB.dataset.supports_insert_select?
|
242
|
+
|
231
243
|
specify "should support prepared statements with delete" do
|
232
244
|
@ds.filter(:numb=>:$n).prepare(:delete, :delete_n)
|
233
245
|
@db.call(:delete_n, :n=>10).should == 1
|
@@ -1890,6 +1890,30 @@ describe Sequel::Model, "many_to_many" do
|
|
1890
1890
|
end
|
1891
1891
|
end
|
1892
1892
|
|
1893
|
+
it "should not override a selection consisting completely of qualified columns using Sequel::SQL::QualifiedIdentifier" do
|
1894
|
+
@c1.dataset = @c1.dataset.select(Sequel.qualify(:attributes, :id), Sequel.qualify(:attributes, :b))
|
1895
|
+
@c2.many_to_many :attributes, :class => @c1
|
1896
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.id, attributes.b FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
1897
|
+
end
|
1898
|
+
|
1899
|
+
it "should not override a selection consisting completely of qualified columns using symbols" do
|
1900
|
+
@c1.dataset = @c1.dataset.select(:attributes__id, :attributes__b)
|
1901
|
+
@c2.many_to_many :attributes, :class => @c1
|
1902
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.id, attributes.b FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
1903
|
+
end
|
1904
|
+
|
1905
|
+
it "should not override a selection consisting completely of qualified columns using Sequel::SQL::AliasedExpression" do
|
1906
|
+
@c1.dataset = @c1.dataset.select(Sequel.qualify(:attributes, :id).as(:a), Sequel.as(:attributes__b, :c))
|
1907
|
+
@c2.many_to_many :attributes, :class => @c1
|
1908
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.id AS a, attributes.b AS c FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
1909
|
+
end
|
1910
|
+
|
1911
|
+
it "should override a selection consisting of non qualified columns" do
|
1912
|
+
@c1.dataset = @c1.dataset.select{foo(:bar)}
|
1913
|
+
@c2.many_to_many :attributes, :class => @c1
|
1914
|
+
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id = 1234)'
|
1915
|
+
end
|
1916
|
+
|
1893
1917
|
it "should respect :eager_loader_predicate_key when lazily loading" do
|
1894
1918
|
@c2.many_to_many :attributes, :class => @c1, :eager_loading_predicate_key=>Sequel.subscript(:attributes_nodes__node_id, 0)
|
1895
1919
|
@c2.new(:id => 1234).attributes_dataset.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.attribute_id = attributes.id) WHERE (attributes_nodes.node_id[0] = 1234)'
|