sequel 3.37.0 → 3.38.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 +56 -0
- data/README.rdoc +82 -58
- data/Rakefile +6 -5
- data/bin/sequel +1 -1
- data/doc/active_record.rdoc +67 -52
- data/doc/advanced_associations.rdoc +33 -48
- data/doc/association_basics.rdoc +41 -51
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +5 -5
- data/doc/dataset_filtering.rdoc +47 -43
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +4 -5
- data/doc/model_hooks.rdoc +3 -3
- data/doc/object_model.rdoc +31 -25
- data/doc/opening_databases.rdoc +19 -5
- data/doc/prepared_statements.rdoc +2 -2
- data/doc/querying.rdoc +109 -52
- data/doc/reflection.rdoc +6 -6
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/schema_modification.rdoc +22 -13
- data/doc/sharding.rdoc +8 -9
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +47 -7
- data/doc/thread_safety.rdoc +1 -1
- data/doc/transactions.rdoc +1 -1
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +29 -43
- data/lib/sequel/adapters/do/postgres.rb +1 -4
- data/lib/sequel/adapters/jdbc.rb +14 -3
- data/lib/sequel/adapters/jdbc/db2.rb +9 -0
- data/lib/sequel/adapters/jdbc/derby.rb +41 -4
- data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
- data/lib/sequel/adapters/mock.rb +10 -4
- data/lib/sequel/adapters/postgres.rb +1 -28
- data/lib/sequel/adapters/shared/mssql.rb +23 -13
- data/lib/sequel/adapters/shared/postgres.rb +46 -0
- data/lib/sequel/adapters/swift.rb +21 -13
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +4 -5
- data/lib/sequel/adapters/swift/sqlite.rb +2 -1
- data/lib/sequel/adapters/tinytds.rb +14 -2
- data/lib/sequel/adapters/utils/pg_types.rb +5 -0
- data/lib/sequel/core.rb +29 -17
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +3 -0
- data/lib/sequel/dataset/actions.rb +5 -6
- data/lib/sequel/dataset/query.rb +7 -7
- data/lib/sequel/dataset/sql.rb +5 -18
- data/lib/sequel/extensions/core_extensions.rb +8 -12
- data/lib/sequel/extensions/pg_array.rb +59 -33
- data/lib/sequel/extensions/pg_array_ops.rb +32 -4
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +32 -17
- data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
- data/lib/sequel/extensions/pg_inet.rb +1 -2
- data/lib/sequel/extensions/pg_interval.rb +0 -1
- data/lib/sequel/extensions/pg_json.rb +41 -23
- data/lib/sequel/extensions/pg_range.rb +36 -11
- data/lib/sequel/extensions/pg_range_ops.rb +32 -4
- data/lib/sequel/extensions/pg_row.rb +572 -0
- data/lib/sequel/extensions/pg_row_ops.rb +164 -0
- data/lib/sequel/extensions/query.rb +3 -3
- data/lib/sequel/extensions/schema_dumper.rb +7 -8
- data/lib/sequel/extensions/select_remove.rb +1 -1
- data/lib/sequel/model/base.rb +1 -0
- data/lib/sequel/no_core_ext.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/validation_helpers.rb +31 -0
- data/lib/sequel/sql.rb +64 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +37 -12
- data/spec/adapters/mysql_spec.rb +39 -75
- data/spec/adapters/oracle_spec.rb +11 -11
- data/spec/adapters/postgres_spec.rb +414 -237
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +14 -14
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +169 -205
- data/spec/core/expression_filters_spec.rb +182 -295
- data/spec/core/object_graph_spec.rb +6 -6
- data/spec/core/schema_spec.rb +14 -14
- data/spec/core/spec_helper.rb +1 -0
- data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
- data/spec/extensions/columns_introspection_spec.rb +5 -5
- data/spec/extensions/hook_class_methods_spec.rb +28 -36
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/pg_array_ops_spec.rb +15 -7
- data/spec/extensions/pg_array_spec.rb +81 -48
- data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
- data/spec/extensions/pg_hstore_spec.rb +66 -65
- data/spec/extensions/pg_inet_spec.rb +2 -4
- data/spec/extensions/pg_interval_spec.rb +2 -3
- data/spec/extensions/pg_json_spec.rb +20 -18
- data/spec/extensions/pg_range_ops_spec.rb +11 -4
- data/spec/extensions/pg_range_spec.rb +30 -7
- data/spec/extensions/pg_row_ops_spec.rb +48 -0
- data/spec/extensions/pg_row_plugin_spec.rb +45 -0
- data/spec/extensions/pg_row_spec.rb +323 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- data/spec/extensions/query_literals_spec.rb +11 -11
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +20 -4
- data/spec/extensions/schema_spec.rb +18 -41
- data/spec/extensions/select_remove_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +4 -8
- data/spec/extensions/to_dot_spec.rb +5 -5
- data/spec/extensions/validation_class_methods_spec.rb +28 -16
- data/spec/integration/associations_test.rb +20 -20
- data/spec/integration/dataset_test.rb +98 -98
- data/spec/integration/eager_loader_test.rb +13 -27
- data/spec/integration/plugin_test.rb +5 -5
- data/spec/integration/prepared_statement_test.rb +22 -13
- data/spec/integration/schema_test.rb +28 -18
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +2 -2
- data/spec/integration/type_test.rb +15 -6
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +4 -4
- data/spec/model/base_spec.rb +5 -5
- data/spec/model/eager_loading_spec.rb +15 -15
- data/spec/model/model_spec.rb +32 -32
- data/spec/model/record_spec.rb +16 -0
- data/spec/model/spec_helper.rb +2 -6
- data/spec/model/validations_spec.rb +1 -1
- metadata +16 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe Sequel::Model, "PgTypecastOnLoad plugin" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel.mock(:host=>'postgres', :fetch=>{:id=>1, :b=>"t", :y=>"0"}, :columns=>[:id, :b, :y], :numrows=>1)
|
|
6
|
+
def @db.schema(*args)
|
|
7
|
+
[[:id, {}], [:b, {:type=>:boolean, :oid=>16}], [:y, {:type=>:integer, :oid=>20}]]
|
|
8
|
+
end
|
|
9
|
+
@c = Class.new(Sequel::Model(@db[:items]))
|
|
10
|
+
@c.plugin :pg_typecast_on_load, :b, :y
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
specify "should call the database conversion proc for all given columns" do
|
|
14
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>0}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
specify "should call the database conversion proc with value when reloading the object, for all given columns" do
|
|
18
|
+
@c.first.refresh.values.should == {:id=>1, :b=>true, :y=>0}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
specify "should call the database conversion proc with value when automatically reloading the object on creation via insert_select" do
|
|
22
|
+
@c.dataset.meta_def(:insert_select){|h| insert(h); first}
|
|
23
|
+
@c.create.values.should == {:id=>1, :b=>true, :y=>0}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
specify "should allowing setting columns separately via add_typecast_on_load_columns" do
|
|
27
|
+
@c = Class.new(Sequel::Model(@db[:items]))
|
|
28
|
+
@c.plugin :pg_typecast_on_load
|
|
29
|
+
@c.first.values.should == {:id=>1, :b=>"t", :y=>"0"}
|
|
30
|
+
@c.add_pg_typecast_on_load_columns :b
|
|
31
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>"0"}
|
|
32
|
+
@c.add_pg_typecast_on_load_columns :y
|
|
33
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>0}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
specify "should work with subclasses" do
|
|
37
|
+
@c = Class.new(Sequel::Model(@db[:items]))
|
|
38
|
+
@c.plugin :pg_typecast_on_load
|
|
39
|
+
@c.first.values.should == {:id=>1, :b=>"t", :y=>"0"}
|
|
40
|
+
|
|
41
|
+
c1 = Class.new(@c)
|
|
42
|
+
@c.add_pg_typecast_on_load_columns :b
|
|
43
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>"0"}
|
|
44
|
+
c1.first.values.should == {:id=>1, :b=>"t", :y=>"0"}
|
|
45
|
+
|
|
46
|
+
c2 = Class.new(@c)
|
|
47
|
+
@c.add_pg_typecast_on_load_columns :y
|
|
48
|
+
@c.first.values.should == {:id=>1, :b=>true, :y=>0}
|
|
49
|
+
c2.first.values.should == {:id=>1, :b=>true, :y=>"0"}
|
|
50
|
+
|
|
51
|
+
c1.add_pg_typecast_on_load_columns :y
|
|
52
|
+
c1.first.values.should == {:id=>1, :b=>"t", :y=>0}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
specify "should not mark the object as modified" do
|
|
56
|
+
@c.first.modified?.should == false
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -18,7 +18,7 @@ describe "query_literals extension" do
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it "should have #select work the standard way if initial string is a literal string already" do
|
|
21
|
-
@ds.select('a, b, ?'
|
|
21
|
+
@ds.select(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT a, b, ?, 1 FROM t'
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
it "should have #select work regularly if not given a string as the first argument" do
|
|
@@ -39,7 +39,7 @@ describe "query_literals extension" do
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
it "should have #select_more work the standard way if initial string is a literal string already" do
|
|
42
|
-
@ds.select_more('a, b, ?'
|
|
42
|
+
@ds.select_more(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT d, a, b, ?, 1 FROM t'
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
it "should have #select_more work regularly if not given a string as the first argument" do
|
|
@@ -56,7 +56,7 @@ describe "query_literals extension" do
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
it "should have #select_append work the standard way if initial string is a literal string already" do
|
|
59
|
-
@ds.select_append('a, b, ?'
|
|
59
|
+
@ds.select_append(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT *, a, b, ?, 1 FROM t'
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
it "should have #select_append work regularly if not given a string as the first argument" do
|
|
@@ -72,7 +72,7 @@ describe "query_literals extension" do
|
|
|
72
72
|
end
|
|
73
73
|
|
|
74
74
|
it "should have #select_group work the standard way if initial string is a literal string already" do
|
|
75
|
-
@ds.select_group('a, b, ?'
|
|
75
|
+
@ds.select_group(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT a, b, ?, 1 FROM t GROUP BY a, b, ?, 1'
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
it "should have #select_group work regularly if not given a string as the first argument" do
|
|
@@ -87,11 +87,11 @@ describe "query_literals extension" do
|
|
|
87
87
|
@ds.group('a, b, ?', 1).sql.should == 'SELECT * FROM t GROUP BY a, b, 1'
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
-
it "should have #
|
|
91
|
-
@ds.group('a, b, ?'
|
|
90
|
+
it "should have #group work the standard way if initial string is a literal string already" do
|
|
91
|
+
@ds.group(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t GROUP BY a, b, ?, 1'
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
it "should have #
|
|
94
|
+
it "should have #group work regularly if not given a string as the first argument" do
|
|
95
95
|
@ds.group(:a, 1).sql.should == 'SELECT * FROM t GROUP BY a, 1'
|
|
96
96
|
end
|
|
97
97
|
|
|
@@ -104,7 +104,7 @@ describe "query_literals extension" do
|
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
it "should have #group_and_count work the standard way if initial string is a literal string already" do
|
|
107
|
-
@ds.group_and_count('a, b, ?'
|
|
107
|
+
@ds.group_and_count(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT a, b, ?, 1, count(*) AS count FROM t GROUP BY a, b, ?, 1'
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
it "should have #group_and_count work regularly if not given a string as the first argument" do
|
|
@@ -120,7 +120,7 @@ describe "query_literals extension" do
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
it "should have #order work the standard way if initial string is a literal string already" do
|
|
123
|
-
@ds.order('a, b, ?'
|
|
123
|
+
@ds.order(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t ORDER BY a, b, ?, 1'
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
it "should have #order work regularly if not given a string as the first argument" do
|
|
@@ -141,7 +141,7 @@ describe "query_literals extension" do
|
|
|
141
141
|
end
|
|
142
142
|
|
|
143
143
|
it "should have #order_more work the standard way if initial string is a literal string already" do
|
|
144
|
-
@ds.order_more('a, b, ?'
|
|
144
|
+
@ds.order_more(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t ORDER BY d, a, b, ?, 1'
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
it "should have #order_more work regularly if not given a string as the first argument" do
|
|
@@ -157,7 +157,7 @@ describe "query_literals extension" do
|
|
|
157
157
|
end
|
|
158
158
|
|
|
159
159
|
it "should have #order_append work the standard way if initial string is a literal string already" do
|
|
160
|
-
@ds.order_prepend('a, b, ?'
|
|
160
|
+
@ds.order_prepend(Sequel.lit('a, b, ?'), 1).sql.should == 'SELECT * FROM t ORDER BY a, b, ?, 1, d'
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
it "should have #order_append work regularly if not given a string as the first argument" do
|
|
@@ -41,13 +41,13 @@ describe "Dataset#query" do
|
|
|
41
41
|
specify "should support #where" do
|
|
42
42
|
q = @d.query do
|
|
43
43
|
from :zzz
|
|
44
|
-
where
|
|
44
|
+
where{x + 2 > Sequel.expr(:y) + 3}
|
|
45
45
|
end
|
|
46
46
|
q.class.should == @d.class
|
|
47
47
|
q.sql.should == "SELECT * FROM zzz WHERE ((x + 2) > (y + 3))"
|
|
48
48
|
|
|
49
49
|
q = @d.from(:zzz).query do
|
|
50
|
-
where(
|
|
50
|
+
where{(x > 1) & (Sequel.expr(:y) > 2)}
|
|
51
51
|
end
|
|
52
52
|
q.class.should == @d.class
|
|
53
53
|
q.sql.should == "SELECT * FROM zzz WHERE ((x > 1) AND (y > 2))"
|
|
@@ -63,7 +63,7 @@ describe "Dataset#query" do
|
|
|
63
63
|
q = @d.query do
|
|
64
64
|
from :abc
|
|
65
65
|
group_by :id
|
|
66
|
-
having
|
|
66
|
+
having{x >= 2}
|
|
67
67
|
end
|
|
68
68
|
q.class.should == @d.class
|
|
69
69
|
q.sql.should == "SELECT * FROM abc GROUP BY id HAVING (x >= 2)"
|
|
@@ -67,7 +67,7 @@ describe "Sequel::Database dump methods" do
|
|
|
67
67
|
@d.meta_def(:tables){|o| [:t1, :t2]}
|
|
68
68
|
@d.meta_def(:schema) do |t, *o|
|
|
69
69
|
case t
|
|
70
|
-
when :t1, 't__t1', :t__t1
|
|
70
|
+
when :t1, 't__t1', Sequel.identifier(:t__t1)
|
|
71
71
|
[[:c1, {:db_type=>'integer', :primary_key=>true, :allow_null=>false}],
|
|
72
72
|
[:c2, {:db_type=>'varchar(20)', :allow_null=>true}]]
|
|
73
73
|
when :t2
|
|
@@ -88,7 +88,7 @@ describe "Sequel::Database dump methods" do
|
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
it "should support dumping table schemas when given an identifier" do
|
|
91
|
-
@d.dump_table_schema(:t__t1
|
|
91
|
+
@d.dump_table_schema(Sequel.identifier(:t__t1)).should == "create_table(\"t__t1\") do\n primary_key :c1\n String :c2, :size=>20\nend"
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
it "should dump non-Integer primary key columns with explicit :type" do
|
|
@@ -593,10 +593,10 @@ END_MIG
|
|
|
593
593
|
s
|
|
594
594
|
end
|
|
595
595
|
@d.dump_table_schema(:t4).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal.new(\"0.1005E3\")\n File :c6, :default=>Sequel::SQL::Blob.new(\"blah\")\n Date :c7, :default=>Date.parse(\"2008-10-29\")\n DateTime :c8, :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n Time :c9, :default=>Sequel::SQLTime.parse(\"10:20:30\"), :only_time=>true\n String :c10\nend"
|
|
596
|
-
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.parse(\"2008-10-29\")\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n column :c9, \"time\", :default=>Sequel::SQLTime.parse(\"10:20:30\")\n column :c10, \"interval\", :default
|
|
596
|
+
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d:\d\d"\)/, '")').should == "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal.new(\"0.1005E3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.parse(\"2008-10-29\")\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30\")\n column :c9, \"time\", :default=>Sequel::SQLTime.parse(\"10:20:30\")\n column :c10, \"interval\", :default=>Sequel::LiteralString.new(\"'6 weeks'\")\nend"
|
|
597
597
|
end
|
|
598
598
|
|
|
599
|
-
it "should not use a
|
|
599
|
+
it "should not use a literal string as a fallback if using MySQL with the :same_db option" do
|
|
600
600
|
@d.meta_def(:database_type){:mysql}
|
|
601
601
|
@d.meta_def(:schema) do |t, *os|
|
|
602
602
|
s = [[:c10, {:db_type=>'interval', :default=>"'6 weeks'", :type=>:interval, :allow_null=>true}]]
|
|
@@ -712,6 +712,22 @@ end
|
|
|
712
712
|
END_MIG
|
|
713
713
|
end
|
|
714
714
|
|
|
715
|
+
it "should convert mysql types to ruby types" do
|
|
716
|
+
types = ['double(15,2)', 'double(7,1) unsigned']
|
|
717
|
+
@d.meta_def(:schema) do |t, *o|
|
|
718
|
+
i = 0
|
|
719
|
+
types.map{|x| [:"c#{i+=1}", {:db_type=>x, :allow_null=>true}]}
|
|
720
|
+
end
|
|
721
|
+
@d.dump_table_schema(:x).should == (<<END_MIG).chomp
|
|
722
|
+
create_table(:x) do
|
|
723
|
+
Float :c1
|
|
724
|
+
Float :c2
|
|
725
|
+
|
|
726
|
+
check Sequel::SQL::BooleanExpression.new(:>=, Sequel::SQL::Identifier.new(:c2), 0)
|
|
727
|
+
end
|
|
728
|
+
END_MIG
|
|
729
|
+
end
|
|
730
|
+
|
|
715
731
|
it "should use separate primary_key call with non autoincrementable types" do
|
|
716
732
|
@d.meta_def(:schema){|*s| [[:c1, {:db_type=>'varchar(8)', :primary_key=>true}]]}
|
|
717
733
|
@d.dump_table_schema(:t3).should == "create_table(:t3) do\n String :c1, :size=>8\n \n primary_key [:c1]\nend"
|
|
@@ -3,6 +3,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
|
3
3
|
describe Sequel::Model, "dataset & schema" do
|
|
4
4
|
before do
|
|
5
5
|
@model = Class.new(Sequel::Model(:items))
|
|
6
|
+
@model.plugin :schema
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
specify "sets schema with implicit table name" do
|
|
@@ -22,27 +23,17 @@ describe Sequel::Model, "dataset & schema" do
|
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
|
|
25
|
-
describe Sequel::Model, "table_exists?" do
|
|
26
|
-
before do
|
|
27
|
-
MODEL_DB.reset
|
|
28
|
-
@model = Class.new(Sequel::Model(:items))
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "should get the table name and question the model's db if table_exists?" do
|
|
32
|
-
@model.db.should_receive(:table_exists?).and_return(false)
|
|
33
|
-
@model.table_exists?.should == false
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
26
|
describe Sequel::Model, "create_table and schema" do
|
|
38
27
|
before do
|
|
39
|
-
|
|
40
|
-
@model
|
|
28
|
+
@model = Class.new(Sequel::Model)
|
|
29
|
+
@model.class_eval do
|
|
30
|
+
plugin :schema
|
|
41
31
|
set_schema(:items) do
|
|
42
32
|
text :name
|
|
43
33
|
float :price, :null => false
|
|
44
34
|
end
|
|
45
35
|
end
|
|
36
|
+
MODEL_DB.reset
|
|
46
37
|
end
|
|
47
38
|
|
|
48
39
|
it "should get the create table SQL list from the db and execute it line by line" do
|
|
@@ -74,61 +65,47 @@ describe Sequel::Model, "create_table and schema" do
|
|
|
74
65
|
|
|
75
66
|
it "should return nil if no schema is present" do
|
|
76
67
|
@model = Class.new(Sequel::Model)
|
|
68
|
+
@model.plugin :schema
|
|
77
69
|
@model.schema.should == nil
|
|
78
70
|
@submodel = Class.new(@model)
|
|
79
71
|
@submodel.schema.should == nil
|
|
80
72
|
end
|
|
81
73
|
end
|
|
82
74
|
|
|
83
|
-
describe Sequel::Model, "
|
|
75
|
+
describe Sequel::Model, "schema methods" do
|
|
84
76
|
before do
|
|
85
77
|
@model = Class.new(Sequel::Model(:items))
|
|
78
|
+
@model.plugin :schema
|
|
86
79
|
MODEL_DB.reset
|
|
87
80
|
end
|
|
88
81
|
|
|
89
|
-
it "should
|
|
90
|
-
@model.
|
|
91
|
-
|
|
82
|
+
it "table_exists? should get the table name and question the model's db if table_exists?" do
|
|
83
|
+
@model.db.should_receive(:table_exists?).and_return(false)
|
|
84
|
+
@model.table_exists?.should == false
|
|
92
85
|
end
|
|
93
|
-
end
|
|
94
86
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
MODEL_DB.reset
|
|
87
|
+
it "drop_table should drop the related table" do
|
|
88
|
+
@model.drop_table
|
|
89
|
+
MODEL_DB.sqls.should == ['DROP TABLE items']
|
|
99
90
|
end
|
|
100
91
|
|
|
101
|
-
it "should drop the table if it exists" do
|
|
92
|
+
it "drop_table? should drop the table if it exists" do
|
|
102
93
|
@model.drop_table?
|
|
103
94
|
MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items']
|
|
104
95
|
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
describe Sequel::Model, "create_table!" do
|
|
108
|
-
before do
|
|
109
|
-
MODEL_DB.reset
|
|
110
|
-
@model = Class.new(Sequel::Model(:items))
|
|
111
|
-
end
|
|
112
96
|
|
|
113
|
-
it "should drop table if it exists and then create the table" do
|
|
97
|
+
it "create_table! should drop table if it exists and then create the table" do
|
|
114
98
|
@model.create_table!
|
|
115
99
|
MODEL_DB.sqls.should == ["SELECT NULL FROM items LIMIT 1", 'DROP TABLE items', 'CREATE TABLE items ()']
|
|
116
100
|
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
describe Sequel::Model, "create_table?" do
|
|
120
|
-
before do
|
|
121
|
-
MODEL_DB.reset
|
|
122
|
-
@model = Class.new(Sequel::Model(:items))
|
|
123
|
-
end
|
|
124
101
|
|
|
125
|
-
it "should not create the table if it already exists" do
|
|
102
|
+
it "create_table? should not create the table if it already exists" do
|
|
126
103
|
@model.should_receive(:table_exists?).and_return(true)
|
|
127
104
|
@model.create_table?
|
|
128
105
|
MODEL_DB.sqls.should == []
|
|
129
106
|
end
|
|
130
107
|
|
|
131
|
-
it "should create the table if it doesn't exist" do
|
|
108
|
+
it "create_table? should create the table if it doesn't exist" do
|
|
132
109
|
@model.should_receive(:table_exists?).and_return(false)
|
|
133
110
|
@model.create_table?
|
|
134
111
|
MODEL_DB.sqls.should == ['CREATE TABLE items ()']
|
|
@@ -24,15 +24,15 @@ describe "Dataset#select_remove" do
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
specify "should handle expressions where Sequel can't determine the alias by itself" do
|
|
27
|
-
d = @d.select(:a, :b
|
|
27
|
+
d = @d.select(:a, Sequel.function(:b), Sequel.as(:c, :b))
|
|
28
28
|
d.columns :a, :"b()", :b
|
|
29
29
|
d.select_remove(:"b()").sql.should == 'SELECT a, c AS b FROM test'
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
specify "should remove expressions if given exact expressions" do
|
|
33
|
-
d = @d.select(:a, :b
|
|
33
|
+
d = @d.select(:a, Sequel.function(:b), Sequel.as(:c, :b))
|
|
34
34
|
d.columns :a, :"b()", :b
|
|
35
|
-
d.select_remove(:b
|
|
36
|
-
d.select_remove(
|
|
35
|
+
d.select_remove(Sequel.function(:b)).sql.should == 'SELECT a, c AS b FROM test'
|
|
36
|
+
d.select_remove(Sequel.as(:c, :b)).sql.should == 'SELECT a, b() FROM test'
|
|
37
37
|
end
|
|
38
38
|
end
|
|
@@ -8,13 +8,9 @@ if defined?(RSpec)
|
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
unless Object.const_defined?('Sequel')
|
|
11
|
+
unless Object.const_defined?('Sequel') && Sequel.const_defined?('Model')
|
|
12
12
|
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
|
13
|
-
require 'sequel/
|
|
14
|
-
end
|
|
15
|
-
unless Sequel.const_defined?('Model')
|
|
16
|
-
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
|
17
|
-
require 'sequel/model'
|
|
13
|
+
require 'sequel/no_core_ext'
|
|
18
14
|
end
|
|
19
15
|
|
|
20
16
|
begin
|
|
@@ -26,8 +22,8 @@ rescue LoadError
|
|
|
26
22
|
nil
|
|
27
23
|
end
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
# Load most extensions by default, so that any conflicts are easily detectable.
|
|
26
|
+
Sequel.extension(*%w'string_date_time inflector pagination query pretty_table blank migration schema_dumper looser_typecasting sql_expr thread_local_timezones to_dot columns_introspection server_block arbitrary_servers pg_auto_parameterize pg_statement_cache pg_array pg_array_ops pg_hstore pg_hstore_ops pg_range pg_range_ops pg_json pg_inet pg_row pg_row_ops schema_caching null_dataset select_remove query_literals eval_inspect')
|
|
31
27
|
|
|
32
28
|
Sequel::Dataset.introspect_all_columns if ENV['SEQUEL_COLUMNS_INTROSPECTION']
|
|
33
29
|
|
|
@@ -100,19 +100,19 @@ END
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
it "should handle SQL::OrderedExpressions" do
|
|
103
|
-
dot(@ds.order(
|
|
103
|
+
dot(@ds.order(Sequel.desc(:a, :nulls=>:last))).should == ["1 -> 2 [label=\"order\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"OrderedExpression: DESC NULLS LAST\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];"]
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
it "should handle SQL::AliasedExpressions" do
|
|
107
|
-
dot(@ds.from(
|
|
107
|
+
dot(@ds.from(Sequel.as(:a, :b))).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"AliasedExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"alias\"];", "5 [label=\":b\"];"]
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
it "should handle SQL::CaseExpressions" do
|
|
111
|
-
dot(@ds.select({:a=>:b}
|
|
111
|
+
dot(@ds.select(Sequel.case({:a=>:b}, :c, :d))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"CaseExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":d\"];", "3 -> 5 [label=\"conditions\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"Array\"];", "6 -> 7 [label=\"0\"];", "7 [label=\":a\"];", "6 -> 8 [label=\"1\"];", "8 [label=\":b\"];", "3 -> 9 [label=\"default\"];", "9 [label=\":c\"];"]
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
it "should handle SQL::Cast" do
|
|
115
|
-
dot(@ds.select(
|
|
115
|
+
dot(@ds.select(Sequel.cast(:a, Integer))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Cast\"];", "3 -> 4 [label=\"expr\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"type\"];", "5 [label=\"Integer\"];"]
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
it "should handle SQL::Function" do
|
|
@@ -120,7 +120,7 @@ END
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
it "should handle SQL::Subscript" do
|
|
123
|
-
dot(@ds.select(:a
|
|
123
|
+
dot(@ds.select(Sequel.subscript(:a, 1))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Subscript\"];", "3 -> 4 [label=\"f\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"sub\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"1\"];"]
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
it "should handle SQL::WindowFunction" do
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
|
+
model_class = proc do |klass, &block|
|
|
4
|
+
c = Class.new(klass)
|
|
5
|
+
c.plugin :validation_class_methods
|
|
6
|
+
c.class_eval(&block) if block
|
|
7
|
+
c
|
|
8
|
+
end
|
|
9
|
+
|
|
3
10
|
describe Sequel::Model do
|
|
4
11
|
before do
|
|
5
|
-
@c =
|
|
12
|
+
@c = model_class.call Sequel::Model do
|
|
6
13
|
def self.validates_coolness_of(attr)
|
|
7
14
|
validates_each(attr) {|o, a, v| o.errors[a] << 'is not cool' if v != :cool}
|
|
8
15
|
end
|
|
@@ -135,8 +142,7 @@ end
|
|
|
135
142
|
|
|
136
143
|
describe Sequel::Model do
|
|
137
144
|
before do
|
|
138
|
-
@c =
|
|
139
|
-
@c.class_eval do
|
|
145
|
+
@c = model_class.call Sequel::Model do
|
|
140
146
|
columns :score
|
|
141
147
|
validates_each :score do |o, a, v|
|
|
142
148
|
o.errors[a] << 'too low' if v < 87
|
|
@@ -165,11 +171,11 @@ describe Sequel::Model do
|
|
|
165
171
|
end
|
|
166
172
|
end
|
|
167
173
|
|
|
168
|
-
describe Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator do
|
|
174
|
+
describe "Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator" do
|
|
169
175
|
before do
|
|
170
176
|
$testit = nil
|
|
171
177
|
|
|
172
|
-
@c =
|
|
178
|
+
@c = model_class.call Sequel::Model do
|
|
173
179
|
def self.validates_blah
|
|
174
180
|
$testit = 1324
|
|
175
181
|
end
|
|
@@ -186,7 +192,7 @@ end
|
|
|
186
192
|
|
|
187
193
|
describe Sequel::Model do
|
|
188
194
|
before do
|
|
189
|
-
@c =
|
|
195
|
+
@c = model_class.call Sequel::Model do
|
|
190
196
|
columns :value
|
|
191
197
|
|
|
192
198
|
def self.filter(*args)
|
|
@@ -579,8 +585,7 @@ end
|
|
|
579
585
|
|
|
580
586
|
describe "Superclass validations" do
|
|
581
587
|
before do
|
|
582
|
-
@c1 =
|
|
583
|
-
@c1.class_eval do
|
|
588
|
+
@c1 = model_class.call Sequel::Model do
|
|
584
589
|
columns :value
|
|
585
590
|
validates_length_of :value, :minimum => 5
|
|
586
591
|
end
|
|
@@ -624,8 +629,7 @@ end
|
|
|
624
629
|
|
|
625
630
|
describe ".validates with block" do
|
|
626
631
|
specify "should support calling .each" do
|
|
627
|
-
@c =
|
|
628
|
-
@c.class_eval do
|
|
632
|
+
@c = model_class.call Sequel::Model do
|
|
629
633
|
columns :vvv
|
|
630
634
|
validates do
|
|
631
635
|
each :vvv do |o, a, v|
|
|
@@ -646,24 +650,36 @@ describe Sequel::Model, "Validations" do
|
|
|
646
650
|
|
|
647
651
|
before(:all) do
|
|
648
652
|
class ::Person < Sequel::Model
|
|
653
|
+
plugin :validation_class_methods
|
|
649
654
|
columns :id,:name,:first_name,:last_name,:middle_name,:initials,:age, :terms
|
|
650
655
|
end
|
|
651
656
|
|
|
652
657
|
class ::Smurf < Person
|
|
653
658
|
end
|
|
659
|
+
|
|
660
|
+
class ::Can < Sequel::Model
|
|
661
|
+
plugin :validation_class_methods
|
|
662
|
+
columns :id, :name
|
|
663
|
+
end
|
|
654
664
|
|
|
655
665
|
class ::Cow < Sequel::Model
|
|
666
|
+
plugin :validation_class_methods
|
|
656
667
|
columns :id, :name, :got_milk
|
|
657
668
|
end
|
|
658
669
|
|
|
659
670
|
class ::User < Sequel::Model
|
|
671
|
+
plugin :validation_class_methods
|
|
660
672
|
columns :id, :username, :password
|
|
661
673
|
end
|
|
662
674
|
|
|
663
675
|
class ::Address < Sequel::Model
|
|
676
|
+
plugin :validation_class_methods
|
|
664
677
|
columns :id, :zip_code
|
|
665
678
|
end
|
|
666
679
|
end
|
|
680
|
+
after(:all) do
|
|
681
|
+
[:Person, :Smurf, :Cow, :User, :Address].each{|c| Object.send(:remove_const, c)}
|
|
682
|
+
end
|
|
667
683
|
|
|
668
684
|
it "should validate the acceptance of a column" do
|
|
669
685
|
class ::Cow < Sequel::Model
|
|
@@ -741,8 +757,7 @@ describe Sequel::Model, "Validations" do
|
|
|
741
757
|
end
|
|
742
758
|
|
|
743
759
|
it "should validate that a column doesn't have a string value" do
|
|
744
|
-
p =
|
|
745
|
-
p.class_eval do
|
|
760
|
+
p = model_class.call Sequel::Model do
|
|
746
761
|
columns :age, :price, :confirmed
|
|
747
762
|
self.raise_on_typecast_failure = false
|
|
748
763
|
validates_not_string :age
|
|
@@ -941,8 +956,6 @@ describe Sequel::Model, "Validations" do
|
|
|
941
956
|
|
|
942
957
|
it "should validate correctly instances initialized with string keys" do
|
|
943
958
|
class ::Can < Sequel::Model
|
|
944
|
-
columns :id, :name
|
|
945
|
-
|
|
946
959
|
validates_length_of :name, :minimum => 4
|
|
947
960
|
end
|
|
948
961
|
|
|
@@ -954,8 +967,7 @@ end
|
|
|
954
967
|
|
|
955
968
|
describe "Model#save" do
|
|
956
969
|
before do
|
|
957
|
-
@c =
|
|
958
|
-
@c.class_eval do
|
|
970
|
+
@c = model_class.call Sequel::Model(:people) do
|
|
959
971
|
columns :id, :x
|
|
960
972
|
|
|
961
973
|
validates_each :x do |o, a, v|
|