sequel 3.21.0 → 3.32.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 +539 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +89 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +52 -0
- data/lib/sequel/adapters/jdbc/derby.rb +260 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +66 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +339 -0
- data/lib/sequel/adapters/mysql.rb +85 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +355 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +328 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +278 -107
- data/lib/sequel/adapters/shared/mysql.rb +203 -65
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +237 -46
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +200 -50
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +68 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +104 -19
- data/lib/sequel/database/query.rb +163 -59
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +240 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +59 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +676 -267
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1081 -344
- data/lib/sequel/model/base.rb +420 -133
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +20 -10
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +43 -10
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +68 -7
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +135 -30
- data/spec/adapters/mysql_spec.rb +244 -212
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +21 -30
- data/spec/core/database_spec.rb +789 -512
- data/spec/core/dataset_spec.rb +1176 -1061
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -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 +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- 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 +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +81 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- 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/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +661 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +500 -67
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +367 -119
- data/spec/integration/prepared_statement_test.rb +222 -125
- data/spec/integration/schema_test.rb +217 -39
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +182 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +955 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +117 -73
data/spec/model/model_spec.rb
CHANGED
|
@@ -12,13 +12,48 @@ describe "Sequel::Model()" do
|
|
|
12
12
|
c.dataset.should == ds
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
it "should return a model subclass with a dataset with the default database and given table name if given a
|
|
15
|
+
it "should return a model subclass with a dataset with the default database and given table name if given a Symbol" do
|
|
16
16
|
c = Sequel::Model(:blah)
|
|
17
17
|
c.superclass.should == Sequel::Model
|
|
18
18
|
c.db.should == @db
|
|
19
19
|
c.table_name.should == :blah
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
it "should return a model subclass with a dataset with the default database and given table name if given a LiteralString" do
|
|
23
|
+
c = Sequel::Model('blah'.lit)
|
|
24
|
+
c.superclass.should == Sequel::Model
|
|
25
|
+
c.db.should == @db
|
|
26
|
+
c.table_name.should == 'blah'.lit
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should return a model subclass with a dataset with the default database and given table name if given an SQL::Identifier" do
|
|
30
|
+
c = Sequel::Model(:blah.identifier)
|
|
31
|
+
c.superclass.should == Sequel::Model
|
|
32
|
+
c.db.should == @db
|
|
33
|
+
c.table_name.should == :blah.identifier
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should return a model subclass with a dataset with the default database and given table name if given an SQL::QualifiedIdentifier" do
|
|
37
|
+
c = Sequel::Model(:blah.qualify(:boo))
|
|
38
|
+
c.superclass.should == Sequel::Model
|
|
39
|
+
c.db.should == @db
|
|
40
|
+
c.table_name.should == :blah.qualify(:boo)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should return a model subclass with a dataset with the default database and given table name if given an SQL::AliasedExpression" do
|
|
44
|
+
c = Sequel::Model(:blah.as(:boo))
|
|
45
|
+
c.superclass.should == Sequel::Model
|
|
46
|
+
c.db.should == @db
|
|
47
|
+
c.table_name.should == :boo
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should return a model subclass with the given dataset if given a dataset using an SQL::Identifier" do
|
|
51
|
+
ds = @db[:blah.identifier]
|
|
52
|
+
c = Sequel::Model(ds)
|
|
53
|
+
c.superclass.should == Sequel::Model
|
|
54
|
+
c.dataset.should == ds
|
|
55
|
+
end
|
|
56
|
+
|
|
22
57
|
it "should return a model subclass associated to the given database if given a database" do
|
|
23
58
|
db = Sequel::Database.new
|
|
24
59
|
c = Sequel::Model(db)
|
|
@@ -43,6 +78,34 @@ describe "Sequel::Model()" do
|
|
|
43
78
|
end.should_not raise_error
|
|
44
79
|
end
|
|
45
80
|
|
|
81
|
+
it "should work without raising an exception with an SQL::Identifier " do
|
|
82
|
+
proc do
|
|
83
|
+
class ::Album < Sequel::Model(:table.identifier); end
|
|
84
|
+
class ::Album < Sequel::Model(:table.identifier); end
|
|
85
|
+
end.should_not raise_error
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should work without raising an exception with an SQL::QualifiedIdentifier " do
|
|
89
|
+
proc do
|
|
90
|
+
class ::Album < Sequel::Model(:table.qualify(:schema)); end
|
|
91
|
+
class ::Album < Sequel::Model(:table.qualify(:schema)); end
|
|
92
|
+
end.should_not raise_error
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "should work without raising an exception with an SQL::AliasedExpression" do
|
|
96
|
+
proc do
|
|
97
|
+
class ::Album < Sequel::Model(:table.as(:alias)); end
|
|
98
|
+
class ::Album < Sequel::Model(:table.as(:alias)); end
|
|
99
|
+
end.should_not raise_error
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "should work without raising an exception with an LiteralString" do
|
|
103
|
+
proc do
|
|
104
|
+
class ::Album < Sequel::Model('table'.lit); end
|
|
105
|
+
class ::Album < Sequel::Model('table'.lit); end
|
|
106
|
+
end.should_not raise_error
|
|
107
|
+
end
|
|
108
|
+
|
|
46
109
|
it "should work without raising an exception with a database" do
|
|
47
110
|
proc do
|
|
48
111
|
class ::Album < Sequel::Model(@db); end
|
|
@@ -56,6 +119,13 @@ describe "Sequel::Model()" do
|
|
|
56
119
|
class ::Album < Sequel::Model(@db[:table]); end
|
|
57
120
|
end.should_not raise_error
|
|
58
121
|
end
|
|
122
|
+
|
|
123
|
+
it "should work without raising an exception with a dataset with an SQL::Identifier" do
|
|
124
|
+
proc do
|
|
125
|
+
class ::Album < Sequel::Model(@db[:table.identifier]); end
|
|
126
|
+
class ::Album < Sequel::Model(@db[:table.identifier]); end
|
|
127
|
+
end.should_not raise_error
|
|
128
|
+
end
|
|
59
129
|
end
|
|
60
130
|
end
|
|
61
131
|
|
|
@@ -70,17 +140,16 @@ describe Sequel::Model do
|
|
|
70
140
|
it "should be associated with a dataset" do
|
|
71
141
|
model_a = Class.new(Sequel::Model) { set_dataset MODEL_DB[:as] }
|
|
72
142
|
|
|
73
|
-
model_a.dataset.should be_a_kind_of(
|
|
143
|
+
model_a.dataset.should be_a_kind_of(Sequel::Mock::Dataset)
|
|
74
144
|
model_a.dataset.opts[:from].should == [:as]
|
|
75
145
|
|
|
76
146
|
model_b = Class.new(Sequel::Model) { set_dataset MODEL_DB[:bs] }
|
|
77
147
|
|
|
78
|
-
model_b.dataset.should be_a_kind_of(
|
|
148
|
+
model_b.dataset.should be_a_kind_of(Sequel::Mock::Dataset)
|
|
79
149
|
model_b.dataset.opts[:from].should == [:bs]
|
|
80
150
|
|
|
81
151
|
model_a.dataset.opts[:from].should == [:as]
|
|
82
152
|
end
|
|
83
|
-
|
|
84
153
|
end
|
|
85
154
|
|
|
86
155
|
describe Sequel::Model, "dataset & schema" do
|
|
@@ -106,12 +175,36 @@ describe Sequel::Model, "dataset & schema" do
|
|
|
106
175
|
@model.table_name.should == :foo
|
|
107
176
|
end
|
|
108
177
|
|
|
109
|
-
it "set_dataset should take a
|
|
178
|
+
it "set_dataset should take a Symbol" do
|
|
110
179
|
@model.db = MODEL_DB
|
|
111
180
|
@model.set_dataset(:foo)
|
|
112
181
|
@model.table_name.should == :foo
|
|
113
182
|
end
|
|
114
183
|
|
|
184
|
+
it "set_dataset should take a LiteralString" do
|
|
185
|
+
@model.db = MODEL_DB
|
|
186
|
+
@model.set_dataset('foo'.lit)
|
|
187
|
+
@model.table_name.should == 'foo'.lit
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "set_dataset should take an SQL::Identifier" do
|
|
191
|
+
@model.db = MODEL_DB
|
|
192
|
+
@model.set_dataset(:foo.identifier)
|
|
193
|
+
@model.table_name.should == :foo.identifier
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "set_dataset should take an SQL::QualifiedIdentifier" do
|
|
197
|
+
@model.db = MODEL_DB
|
|
198
|
+
@model.set_dataset(:foo.qualify(:bar))
|
|
199
|
+
@model.table_name.should == :foo.qualify(:bar)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it "set_dataset should take an SQL::AliasedExpression" do
|
|
203
|
+
@model.db = MODEL_DB
|
|
204
|
+
@model.set_dataset(:foo.as(:bar))
|
|
205
|
+
@model.table_name.should == :bar
|
|
206
|
+
end
|
|
207
|
+
|
|
115
208
|
it "table_name should respect table aliases" do
|
|
116
209
|
@model.set_dataset(:foo___x)
|
|
117
210
|
@model.table_name.should == :x
|
|
@@ -121,16 +214,30 @@ describe Sequel::Model, "dataset & schema" do
|
|
|
121
214
|
proc{@model.set_dataset(Object.new)}.should raise_error(Sequel::Error)
|
|
122
215
|
end
|
|
123
216
|
|
|
124
|
-
it "set_dataset should add the destroy method to the dataset" do
|
|
217
|
+
it "set_dataset should add the destroy method to the dataset that destroys each object" do
|
|
125
218
|
ds = MODEL_DB[:foo]
|
|
126
219
|
ds.should_not respond_to(:destroy)
|
|
127
220
|
@model.set_dataset(ds)
|
|
128
221
|
ds.should respond_to(:destroy)
|
|
222
|
+
MODEL_DB.sqls
|
|
223
|
+
ds._fetch = [{:id=>1}, {:id=>2}]
|
|
224
|
+
ds.destroy.should == 2
|
|
225
|
+
MODEL_DB.sqls.should == ["SELECT * FROM foo", "DELETE FROM foo WHERE (id = 1)", "DELETE FROM foo WHERE (id = 2)"]
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
it "set_dataset should add the destroy method that respects sharding with transactions" do
|
|
229
|
+
db = Sequel.mock(:servers=>{:s1=>{}})
|
|
230
|
+
ds = db[:foo].server(:s1)
|
|
231
|
+
@model.use_transactions = true
|
|
232
|
+
@model.set_dataset(ds)
|
|
233
|
+
db.sqls
|
|
234
|
+
ds.destroy.should == 0
|
|
235
|
+
db.sqls.should == ["BEGIN -- s1", "SELECT * FROM foo -- s1", "COMMIT -- s1"]
|
|
129
236
|
end
|
|
130
237
|
|
|
131
238
|
it "should raise an error on set_dataset if there is an error connecting to the database" do
|
|
132
239
|
@model.meta_def(:columns){raise Sequel::DatabaseConnectionError}
|
|
133
|
-
proc{@model.set_dataset(
|
|
240
|
+
proc{@model.set_dataset(Sequel::Database.new[:foo].join(:blah))}.should raise_error
|
|
134
241
|
end
|
|
135
242
|
|
|
136
243
|
it "should not raise an error if there is a problem getting the columns for a dataset" do
|
|
@@ -149,9 +256,8 @@ describe Sequel::Model, "dataset & schema" do
|
|
|
149
256
|
end
|
|
150
257
|
end
|
|
151
258
|
|
|
152
|
-
describe Sequel::Model, "
|
|
153
|
-
|
|
154
|
-
before(:each) do
|
|
259
|
+
describe Sequel::Model, "constructors" do
|
|
260
|
+
before do
|
|
155
261
|
@m = Class.new(Sequel::Model)
|
|
156
262
|
@m.columns :a, :b
|
|
157
263
|
end
|
|
@@ -170,11 +276,38 @@ describe Sequel::Model, "constructor" do
|
|
|
170
276
|
m.values[:a].should == 1
|
|
171
277
|
end
|
|
172
278
|
|
|
279
|
+
it "should have dataset row_proc create an existing object" do
|
|
280
|
+
@m.dataset = Sequel::Dataset.new(nil)
|
|
281
|
+
o = @m.dataset.row_proc.call(:a=>1)
|
|
282
|
+
o.should be_a_kind_of(@m)
|
|
283
|
+
o.values.should == {:a=>1}
|
|
284
|
+
o.new?.should be_false
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it "should have .call create an existing object" do
|
|
288
|
+
o = @m.call(:a=>1)
|
|
289
|
+
o.should be_a_kind_of(@m)
|
|
290
|
+
o.values.should == {:a=>1}
|
|
291
|
+
o.new?.should be_false
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
it "should have .load create an existing object" do
|
|
295
|
+
o = @m.load(:a=>1)
|
|
296
|
+
o.should be_a_kind_of(@m)
|
|
297
|
+
o.values.should == {:a=>1}
|
|
298
|
+
o.new?.should be_false
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
it "should have .new with a second true argument create an existing object" do
|
|
302
|
+
o = @m.new({:a=>1}, true)
|
|
303
|
+
o.should be_a_kind_of(@m)
|
|
304
|
+
o.values.should == {:a=>1}
|
|
305
|
+
o.new?.should be_false
|
|
306
|
+
end
|
|
173
307
|
end
|
|
174
308
|
|
|
175
309
|
describe Sequel::Model, "new" do
|
|
176
|
-
|
|
177
|
-
before(:each) do
|
|
310
|
+
before do
|
|
178
311
|
@m = Class.new(Sequel::Model) do
|
|
179
312
|
set_dataset MODEL_DB[:items]
|
|
180
313
|
columns :x, :id
|
|
@@ -194,15 +327,8 @@ describe Sequel::Model, "new" do
|
|
|
194
327
|
end
|
|
195
328
|
|
|
196
329
|
it "should use the last inserted id as primary key if not in values" do
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
super
|
|
200
|
-
1234
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
def d.first
|
|
204
|
-
{:x => 1, :id => 1234}
|
|
205
|
-
end
|
|
330
|
+
@m.dataset._fetch = {:x => 1, :id => 1234}
|
|
331
|
+
@m.dataset.autoid = 1234
|
|
206
332
|
|
|
207
333
|
o = @m.new(:x => 1)
|
|
208
334
|
o.save
|
|
@@ -212,14 +338,12 @@ describe Sequel::Model, "new" do
|
|
|
212
338
|
o.save
|
|
213
339
|
o.id.should == 333
|
|
214
340
|
end
|
|
215
|
-
|
|
216
341
|
end
|
|
217
342
|
|
|
218
343
|
describe Sequel::Model, ".subset" do
|
|
219
344
|
before do
|
|
220
|
-
MODEL_DB.reset
|
|
221
|
-
|
|
222
345
|
@c = Class.new(Sequel::Model(:items))
|
|
346
|
+
MODEL_DB.reset
|
|
223
347
|
end
|
|
224
348
|
|
|
225
349
|
specify "should create a filter on the underlying dataset" do
|
|
@@ -247,44 +371,31 @@ describe Sequel::Model, ".subset" do
|
|
|
247
371
|
end
|
|
248
372
|
|
|
249
373
|
describe Sequel::Model, ".find" do
|
|
250
|
-
|
|
251
|
-
before(:each) do
|
|
252
|
-
MODEL_DB.reset
|
|
253
|
-
|
|
374
|
+
before do
|
|
254
375
|
@c = Class.new(Sequel::Model(:items))
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
@dataset = @c.dataset
|
|
258
|
-
$sqls = []
|
|
259
|
-
@dataset.extend(Module.new {
|
|
260
|
-
def fetch_rows(sql)
|
|
261
|
-
$sqls << sql
|
|
262
|
-
yield $cache_dataset_row
|
|
263
|
-
end
|
|
264
|
-
})
|
|
376
|
+
@c.dataset._fetch = {:name => 'sharon', :id => 1}
|
|
377
|
+
MODEL_DB.reset
|
|
265
378
|
end
|
|
266
379
|
|
|
267
380
|
it "should return the first record matching the given filter" do
|
|
268
381
|
@c.find(:name => 'sharon').should be_a_kind_of(@c)
|
|
269
|
-
|
|
382
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"]
|
|
270
383
|
|
|
271
384
|
@c.find(:name.like('abc%')).should be_a_kind_of(@c)
|
|
272
|
-
|
|
385
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (name LIKE 'abc%') LIMIT 1"]
|
|
273
386
|
end
|
|
274
387
|
|
|
275
388
|
specify "should accept filter blocks" do
|
|
276
389
|
@c.find{:id.sql_number > 1}.should be_a_kind_of(@c)
|
|
277
|
-
|
|
390
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id > 1) LIMIT 1"]
|
|
278
391
|
|
|
279
392
|
@c.find {(:x.sql_number > 1) & (:y.sql_number < 2)}.should be_a_kind_of(@c)
|
|
280
|
-
|
|
393
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE ((x > 1) AND (y < 2)) LIMIT 1"]
|
|
281
394
|
end
|
|
282
|
-
|
|
283
395
|
end
|
|
284
396
|
|
|
285
397
|
describe Sequel::Model, ".fetch" do
|
|
286
|
-
|
|
287
|
-
before(:each) do
|
|
398
|
+
before do
|
|
288
399
|
MODEL_DB.reset
|
|
289
400
|
@c = Class.new(Sequel::Model(:items))
|
|
290
401
|
end
|
|
@@ -301,80 +412,53 @@ describe Sequel::Model, ".fetch" do
|
|
|
301
412
|
end
|
|
302
413
|
|
|
303
414
|
describe Sequel::Model, ".find_or_create" do
|
|
304
|
-
|
|
305
|
-
before(:each) do
|
|
306
|
-
MODEL_DB.reset
|
|
415
|
+
before do
|
|
307
416
|
@c = Class.new(Sequel::Model(:items)) do
|
|
308
|
-
|
|
417
|
+
set_primary_key :id
|
|
309
418
|
columns :x
|
|
310
419
|
end
|
|
420
|
+
MODEL_DB.reset
|
|
311
421
|
end
|
|
312
422
|
|
|
313
423
|
it "should find the record" do
|
|
314
|
-
@c.find_or_create(:x => 1)
|
|
424
|
+
@c.find_or_create(:x => 1).should == @c.load(:x=>1, :id=>1)
|
|
315
425
|
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (x = 1) LIMIT 1"]
|
|
316
|
-
|
|
317
|
-
MODEL_DB.reset
|
|
318
426
|
end
|
|
319
427
|
|
|
320
428
|
it "should create the record if not found" do
|
|
321
|
-
@c.
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
MODEL_DB.sqls.should == [
|
|
328
|
-
"SELECT * FROM items WHERE (x = 1) LIMIT 1",
|
|
329
|
-
"INSERT INTO items (x) VALUES (1)"
|
|
330
|
-
]
|
|
429
|
+
@c.dataset._fetch = [[], {:x=>1, :id=>1}]
|
|
430
|
+
@c.dataset.autoid = 1
|
|
431
|
+
@c.find_or_create(:x => 1).should == @c.load(:x=>1, :id=>1)
|
|
432
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (x = 1) LIMIT 1",
|
|
433
|
+
"INSERT INTO items (x) VALUES (1)",
|
|
434
|
+
"SELECT * FROM items WHERE (id = 1) LIMIT 1"]
|
|
331
435
|
end
|
|
332
436
|
|
|
333
437
|
it "should pass the new record to be created to the block if no record is found" do
|
|
334
|
-
@c.
|
|
335
|
-
@c.
|
|
336
|
-
|
|
438
|
+
@c.dataset._fetch = [[], {:x=>1, :id=>1}]
|
|
439
|
+
@c.dataset.autoid = 1
|
|
440
|
+
@c.find_or_create(:x => 1){|x| x[:y] = 2}.should == @c.load(:x=>1, :id=>1)
|
|
441
|
+
sqls = MODEL_DB.sqls
|
|
442
|
+
sqls.first.should == "SELECT * FROM items WHERE (x = 1) LIMIT 1"
|
|
443
|
+
["INSERT INTO items (x, y) VALUES (1, 2)", "INSERT INTO items (y, x) VALUES (2, 1)"].should include(sqls[1])
|
|
444
|
+
sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
|
|
337
445
|
end
|
|
338
446
|
end
|
|
339
447
|
|
|
340
448
|
describe Sequel::Model, ".all" do
|
|
341
|
-
|
|
342
|
-
before(:each) do
|
|
343
|
-
MODEL_DB.reset
|
|
344
|
-
@c = Class.new(Sequel::Model(:items)) do
|
|
345
|
-
no_primary_key
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
@c.dataset.meta_def(:all) {1234}
|
|
349
|
-
end
|
|
350
|
-
|
|
351
449
|
it "should return all records in the dataset" do
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
class DummyModelBased < Sequel::Model(:blog)
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
describe Sequel::Model, "(:tablename)" do
|
|
361
|
-
|
|
362
|
-
it "should allow reopening of descendant classes" do
|
|
363
|
-
proc do
|
|
364
|
-
eval "class DummyModelBased < Sequel::Model(:blog); end"
|
|
365
|
-
end.should_not raise_error
|
|
450
|
+
c = Class.new(Sequel::Model(:items))
|
|
451
|
+
c.all.should == [c.load(:x=>1, :id=>1)]
|
|
366
452
|
end
|
|
367
|
-
|
|
368
453
|
end
|
|
369
454
|
|
|
370
455
|
describe Sequel::Model, "A model class without a primary key" do
|
|
371
|
-
|
|
372
|
-
before(:each) do
|
|
373
|
-
MODEL_DB.reset
|
|
456
|
+
before do
|
|
374
457
|
@c = Class.new(Sequel::Model(:items)) do
|
|
375
458
|
columns :x
|
|
376
459
|
no_primary_key
|
|
377
460
|
end
|
|
461
|
+
MODEL_DB.reset
|
|
378
462
|
end
|
|
379
463
|
|
|
380
464
|
it "should be able to insert records without selecting them back" do
|
|
@@ -387,8 +471,11 @@ describe Sequel::Model, "A model class without a primary key" do
|
|
|
387
471
|
end
|
|
388
472
|
|
|
389
473
|
it "should raise when deleting" do
|
|
390
|
-
|
|
391
|
-
|
|
474
|
+
proc{@c.load(:x=>1).delete}.should raise_error
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
it "should raise when updating" do
|
|
478
|
+
proc{@c.load(:x=>1).update(:x=>2)}.should raise_error
|
|
392
479
|
end
|
|
393
480
|
|
|
394
481
|
it "should insert a record when saving" do
|
|
@@ -397,24 +484,17 @@ describe Sequel::Model, "A model class without a primary key" do
|
|
|
397
484
|
o.save
|
|
398
485
|
MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (2)']
|
|
399
486
|
end
|
|
400
|
-
|
|
401
487
|
end
|
|
402
488
|
|
|
403
489
|
describe Sequel::Model, "attribute accessors" do
|
|
404
490
|
before do
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
@c = Class.new(Sequel::Model) do
|
|
409
|
-
def self.db_schema
|
|
410
|
-
set_columns(Array(@columns))
|
|
411
|
-
@db_schema = {:x=>{:type=>:integer}, :y=>{:type=>:integer}}
|
|
412
|
-
end
|
|
413
|
-
def self.set_dataset(ds, opts={})
|
|
414
|
-
@columns = ds.columns
|
|
415
|
-
db_schema
|
|
416
|
-
end
|
|
491
|
+
db = Sequel.mock
|
|
492
|
+
def db.schema(*)
|
|
493
|
+
[[:x, {:type=>:integer}], [:y, {:type=>:integer}]]
|
|
417
494
|
end
|
|
495
|
+
@dataset = db[:items].columns(:x, :y)
|
|
496
|
+
@c = Class.new(Sequel::Model)
|
|
497
|
+
MODEL_DB.reset
|
|
418
498
|
end
|
|
419
499
|
|
|
420
500
|
it "should be created on set_dataset" do
|
|
@@ -446,7 +526,7 @@ describe Sequel::Model, "attribute accessors" do
|
|
|
446
526
|
end
|
|
447
527
|
|
|
448
528
|
it "should have a working typecasting setter even if the column is not selected" do
|
|
449
|
-
@c.set_dataset(@dataset.select(:y))
|
|
529
|
+
@c.set_dataset(@dataset.select(:y).columns(:y))
|
|
450
530
|
o = @c.new
|
|
451
531
|
|
|
452
532
|
o.x = '34'
|
|
@@ -454,7 +534,7 @@ describe Sequel::Model, "attribute accessors" do
|
|
|
454
534
|
end
|
|
455
535
|
|
|
456
536
|
it "should typecast if the new value is the same as the existing but has a different class" do
|
|
457
|
-
@c.set_dataset(@dataset.select(:y))
|
|
537
|
+
@c.set_dataset(@dataset.select(:y).columns(:y))
|
|
458
538
|
o = @c.new
|
|
459
539
|
|
|
460
540
|
o.x = 34
|
|
@@ -466,58 +546,51 @@ describe Sequel::Model, "attribute accessors" do
|
|
|
466
546
|
end
|
|
467
547
|
|
|
468
548
|
describe Sequel::Model, ".[]" do
|
|
469
|
-
|
|
470
|
-
before(:each) do
|
|
471
|
-
MODEL_DB.reset
|
|
472
|
-
|
|
549
|
+
before do
|
|
473
550
|
@c = Class.new(Sequel::Model(:items))
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
@dataset = @c.dataset
|
|
477
|
-
$sqls = []
|
|
478
|
-
@dataset.extend(Module.new {
|
|
479
|
-
def fetch_rows(sql)
|
|
480
|
-
$sqls << sql
|
|
481
|
-
yield $cache_dataset_row
|
|
482
|
-
end
|
|
483
|
-
})
|
|
551
|
+
@c.dataset._fetch = {:name => 'sharon', :id => 1}
|
|
552
|
+
MODEL_DB.reset
|
|
484
553
|
end
|
|
485
554
|
|
|
486
555
|
it "should return the first record for the given pk" do
|
|
487
|
-
@c[1].should
|
|
488
|
-
|
|
489
|
-
@c[9999].should
|
|
490
|
-
|
|
556
|
+
@c[1].should == @c.load(:name => 'sharon', :id => 1)
|
|
557
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE id = 1"]
|
|
558
|
+
@c[9999].should == @c.load(:name => 'sharon', :id => 1)
|
|
559
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE id = 9999"]
|
|
491
560
|
end
|
|
492
561
|
|
|
493
562
|
it "should work correctly for custom primary key" do
|
|
494
563
|
@c.set_primary_key :name
|
|
495
|
-
@c['sharon'].should
|
|
496
|
-
|
|
564
|
+
@c['sharon'].should == @c.load(:name => 'sharon', :id => 1)
|
|
565
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE name = 'sharon'"]
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
it "should return the first record for the given pk for a filtered dataset" do
|
|
569
|
+
@c.dataset = @c.dataset.filter(:active=>true)
|
|
570
|
+
@c[1].should == @c.load(:name => 'sharon', :id => 1)
|
|
571
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE ((active IS TRUE) AND (id = 1)) LIMIT 1"]
|
|
497
572
|
end
|
|
498
573
|
|
|
499
574
|
it "should work correctly for composite primary key specified as array" do
|
|
500
575
|
@c.set_primary_key [:node_id, :kind]
|
|
501
576
|
@c[3921, 201].should be_a_kind_of(@c)
|
|
502
|
-
|
|
503
|
-
|
|
577
|
+
sqls = MODEL_DB.sqls
|
|
578
|
+
sqls.length.should == 1
|
|
579
|
+
sqls.first.should =~ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
|
|
504
580
|
end
|
|
505
581
|
|
|
506
582
|
it "should work correctly for composite primary key specified as separate arguments" do
|
|
507
583
|
@c.set_primary_key :node_id, :kind
|
|
508
584
|
@c[3921, 201].should be_a_kind_of(@c)
|
|
509
|
-
|
|
510
|
-
|
|
585
|
+
sqls = MODEL_DB.sqls
|
|
586
|
+
sqls.length.should == 1
|
|
587
|
+
sqls.first.should =~ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
|
|
511
588
|
end
|
|
512
589
|
end
|
|
513
590
|
|
|
514
591
|
describe "Model#inspect" do
|
|
515
|
-
before do
|
|
516
|
-
@o = Sequel::Model.load(:x => 333)
|
|
517
|
-
end
|
|
518
|
-
|
|
519
592
|
specify "should include the class name and the values" do
|
|
520
|
-
|
|
593
|
+
Sequel::Model.load(:x => 333).inspect.should == '#<Sequel::Model @values={:x=>333}>'
|
|
521
594
|
end
|
|
522
595
|
end
|
|
523
596
|
|
|
@@ -526,16 +599,13 @@ describe "Model.db_schema" do
|
|
|
526
599
|
@c = Class.new(Sequel::Model(:items)) do
|
|
527
600
|
def self.columns; orig_columns; end
|
|
528
601
|
end
|
|
529
|
-
@
|
|
530
|
-
@dataset
|
|
531
|
-
def @dataset.naked; self; end
|
|
532
|
-
def @dataset.columns; []; end
|
|
533
|
-
def @dataset.def_mutation_method(*names); end
|
|
602
|
+
@db = Sequel.mock
|
|
603
|
+
@dataset = @db[:items]
|
|
534
604
|
end
|
|
535
605
|
|
|
536
606
|
specify "should use the database's schema_for_table and set the columns and dataset columns" do
|
|
537
607
|
d = @dataset.db
|
|
538
|
-
def
|
|
608
|
+
def @db.schema(table, opts = {})
|
|
539
609
|
[[:x, {:type=>:integer}], [:y, {:type=>:string}]]
|
|
540
610
|
end
|
|
541
611
|
@c.dataset = @dataset
|
|
@@ -545,36 +615,20 @@ describe "Model.db_schema" do
|
|
|
545
615
|
end
|
|
546
616
|
|
|
547
617
|
specify "should not restrict the schema for datasets with a :select option" do
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
def d.schema(table, opts = {})
|
|
618
|
+
def @c.columns; [:x, :z]; end
|
|
619
|
+
def @db.schema(table, opts = {})
|
|
551
620
|
[[:x, {:type=>:integer}], [:y, {:type=>:string}]]
|
|
552
621
|
end
|
|
553
|
-
|
|
554
|
-
@c.dataset = ds
|
|
622
|
+
@c.dataset = @dataset.select(:x, :y___z)
|
|
555
623
|
@c.db_schema.should == {:x=>{:type=>:integer}, :z=>{}, :y=>{:type=>:string}}
|
|
556
624
|
end
|
|
557
625
|
|
|
558
|
-
specify "should not use schema if the dataset uses multiple tables or custom sql" do
|
|
559
|
-
ds = @dataset.join(:x, :id)
|
|
560
|
-
d = ds.db
|
|
561
|
-
e = false
|
|
562
|
-
d.meta_def(:schema){|table, *opts| e = true}
|
|
563
|
-
def @c.columns; [:x]; end
|
|
564
|
-
@c.dataset = ds
|
|
565
|
-
@c.db_schema.should == {:x=>{}}
|
|
566
|
-
e.should == false
|
|
567
|
-
end
|
|
568
|
-
|
|
569
626
|
specify "should fallback to fetching records if schema raises an error" do
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
def d.schema(table, opts={})
|
|
573
|
-
raise StandardError
|
|
627
|
+
def @db.schema(table, opts={})
|
|
628
|
+
raise Sequel::Error
|
|
574
629
|
end
|
|
575
|
-
|
|
576
|
-
@c.
|
|
577
|
-
@c.db_schema.should == {:x=>{}}
|
|
630
|
+
@c.dataset = @dataset.join(:x, :id).columns(:id, :x)
|
|
631
|
+
@c.db_schema.should == {:x=>{}, :id=>{}}
|
|
578
632
|
end
|
|
579
633
|
|
|
580
634
|
specify "should automatically set a singular primary key based on the schema" do
|