sequel 4.12.0 → 4.13.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 +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)'
|