sequel 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1551 -4
- data/README +306 -19
- data/Rakefile +84 -56
- data/bin/sequel +106 -0
- data/doc/cheat_sheet.rdoc +225 -0
- data/doc/dataset_filtering.rdoc +182 -0
- data/lib/sequel_core.rb +136 -0
- data/lib/sequel_core/adapters/adapter_skeleton.rb +54 -0
- data/lib/sequel_core/adapters/ado.rb +80 -0
- data/lib/sequel_core/adapters/db2.rb +148 -0
- data/lib/sequel_core/adapters/dbi.rb +117 -0
- data/lib/sequel_core/adapters/informix.rb +78 -0
- data/lib/sequel_core/adapters/jdbc.rb +186 -0
- data/lib/sequel_core/adapters/jdbc/mysql.rb +55 -0
- data/lib/sequel_core/adapters/jdbc/postgresql.rb +66 -0
- data/lib/sequel_core/adapters/jdbc/sqlite.rb +47 -0
- data/lib/sequel_core/adapters/mysql.rb +231 -0
- data/lib/sequel_core/adapters/odbc.rb +155 -0
- data/lib/sequel_core/adapters/odbc_mssql.rb +106 -0
- data/lib/sequel_core/adapters/openbase.rb +64 -0
- data/lib/sequel_core/adapters/oracle.rb +170 -0
- data/lib/sequel_core/adapters/postgres.rb +199 -0
- data/lib/sequel_core/adapters/shared/mysql.rb +275 -0
- data/lib/sequel_core/adapters/shared/postgres.rb +351 -0
- data/lib/sequel_core/adapters/shared/sqlite.rb +146 -0
- data/lib/sequel_core/adapters/sqlite.rb +138 -0
- data/lib/sequel_core/connection_pool.rb +194 -0
- data/lib/sequel_core/core_ext.rb +203 -0
- data/lib/sequel_core/core_sql.rb +184 -0
- data/lib/sequel_core/database.rb +471 -0
- data/lib/sequel_core/database/schema.rb +156 -0
- data/lib/sequel_core/dataset.rb +457 -0
- data/lib/sequel_core/dataset/callback.rb +13 -0
- data/lib/sequel_core/dataset/convenience.rb +245 -0
- data/lib/sequel_core/dataset/pagination.rb +96 -0
- data/lib/sequel_core/dataset/query.rb +41 -0
- data/lib/sequel_core/dataset/schema.rb +15 -0
- data/lib/sequel_core/dataset/sql.rb +889 -0
- data/lib/sequel_core/deprecated.rb +26 -0
- data/lib/sequel_core/exceptions.rb +42 -0
- data/lib/sequel_core/migration.rb +187 -0
- data/lib/sequel_core/object_graph.rb +216 -0
- data/lib/sequel_core/pretty_table.rb +71 -0
- data/lib/sequel_core/schema.rb +2 -0
- data/lib/sequel_core/schema/generator.rb +239 -0
- data/lib/sequel_core/schema/sql.rb +325 -0
- data/lib/sequel_core/sql.rb +812 -0
- data/lib/sequel_model.rb +5 -1
- data/lib/sequel_model/association_reflection.rb +3 -8
- data/lib/sequel_model/base.rb +15 -10
- data/lib/sequel_model/inflector.rb +3 -5
- data/lib/sequel_model/plugins.rb +1 -1
- data/lib/sequel_model/record.rb +11 -3
- data/lib/sequel_model/schema.rb +4 -4
- data/lib/sequel_model/validations.rb +6 -1
- data/spec/adapters/ado_spec.rb +17 -0
- data/spec/adapters/informix_spec.rb +96 -0
- data/spec/adapters/mysql_spec.rb +764 -0
- data/spec/adapters/oracle_spec.rb +222 -0
- data/spec/adapters/postgres_spec.rb +441 -0
- data/spec/adapters/spec_helper.rb +7 -0
- data/spec/adapters/sqlite_spec.rb +400 -0
- data/spec/integration/dataset_test.rb +51 -0
- data/spec/integration/eager_loader_test.rb +702 -0
- data/spec/integration/schema_test.rb +102 -0
- data/spec/integration/spec_helper.rb +44 -0
- data/spec/integration/type_test.rb +43 -0
- data/spec/rcov.opts +2 -0
- data/spec/sequel_core/connection_pool_spec.rb +363 -0
- data/spec/sequel_core/core_ext_spec.rb +156 -0
- data/spec/sequel_core/core_sql_spec.rb +427 -0
- data/spec/sequel_core/database_spec.rb +964 -0
- data/spec/sequel_core/dataset_spec.rb +2977 -0
- data/spec/sequel_core/expression_filters_spec.rb +346 -0
- data/spec/sequel_core/migration_spec.rb +261 -0
- data/spec/sequel_core/object_graph_spec.rb +234 -0
- data/spec/sequel_core/pretty_table_spec.rb +58 -0
- data/spec/sequel_core/schema_generator_spec.rb +122 -0
- data/spec/sequel_core/schema_spec.rb +497 -0
- data/spec/sequel_core/spec_helper.rb +51 -0
- data/spec/{association_reflection_spec.rb → sequel_model/association_reflection_spec.rb} +6 -6
- data/spec/{associations_spec.rb → sequel_model/associations_spec.rb} +47 -18
- data/spec/{base_spec.rb → sequel_model/base_spec.rb} +2 -1
- data/spec/{caching_spec.rb → sequel_model/caching_spec.rb} +0 -0
- data/spec/{dataset_methods_spec.rb → sequel_model/dataset_methods_spec.rb} +13 -1
- data/spec/{eager_loading_spec.rb → sequel_model/eager_loading_spec.rb} +75 -14
- data/spec/{hooks_spec.rb → sequel_model/hooks_spec.rb} +4 -4
- data/spec/sequel_model/inflector_spec.rb +119 -0
- data/spec/{model_spec.rb → sequel_model/model_spec.rb} +30 -11
- data/spec/{plugins_spec.rb → sequel_model/plugins_spec.rb} +0 -0
- data/spec/{record_spec.rb → sequel_model/record_spec.rb} +47 -6
- data/spec/{schema_spec.rb → sequel_model/schema_spec.rb} +18 -4
- data/spec/{spec_helper.rb → sequel_model/spec_helper.rb} +3 -2
- data/spec/{validations_spec.rb → sequel_model/validations_spec.rb} +37 -17
- data/spec/spec_config.rb +9 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +110 -37
- data/spec/inflector_spec.rb +0 -34
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
unless Object.const_defined?('Sequel')
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
4
|
+
require 'sequel_core'
|
5
|
+
end
|
6
|
+
|
7
|
+
class MockDataset < Sequel::Dataset
|
8
|
+
def insert(*args)
|
9
|
+
@db.execute insert_sql(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def update(*args)
|
13
|
+
@db.execute update_sql(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def fetch_rows(sql)
|
17
|
+
@db.execute(sql)
|
18
|
+
yield({:id => 1, :x => 1})
|
19
|
+
end
|
20
|
+
|
21
|
+
def quoted_identifier(c)
|
22
|
+
"\"#{c}\""
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class MockDatabase < Sequel::Database
|
27
|
+
@@quote_identifiers = false
|
28
|
+
attr_reader :sqls
|
29
|
+
|
30
|
+
def execute(sql)
|
31
|
+
@sqls ||= []
|
32
|
+
@sqls << sql
|
33
|
+
end
|
34
|
+
|
35
|
+
def reset
|
36
|
+
@sqls = []
|
37
|
+
end
|
38
|
+
|
39
|
+
def transaction; yield; end
|
40
|
+
|
41
|
+
def dataset; MockDataset.new(self); end
|
42
|
+
end
|
43
|
+
|
44
|
+
class SchemaDummyDatabase < Sequel::Database
|
45
|
+
attr_reader :sqls
|
46
|
+
|
47
|
+
def execute(sql)
|
48
|
+
@sqls ||= []
|
49
|
+
@sqls << sql
|
50
|
+
end
|
51
|
+
end
|
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), "spec_helper")
|
|
3
3
|
describe Sequel::Model::Associations::AssociationReflection, "#associated_class" do
|
4
4
|
before do
|
5
5
|
@c = Class.new(Sequel::Model)
|
6
|
-
class ParParent < Sequel::Model; end
|
6
|
+
class ::ParParent < Sequel::Model; end
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should use the :class value if present" do
|
@@ -21,7 +21,7 @@ end
|
|
21
21
|
describe Sequel::Model::Associations::AssociationReflection, "#associated_primary_key" do
|
22
22
|
before do
|
23
23
|
@c = Class.new(Sequel::Model)
|
24
|
-
class ParParent < Sequel::Model; end
|
24
|
+
class ::ParParent < Sequel::Model; end
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should use the :right_primary_key value if present" do
|
@@ -46,9 +46,9 @@ describe Sequel::Model::Associations::AssociationReflection, "#reciprocal" do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should figure out the reciprocal if the :reciprocal value is not present" do
|
49
|
-
class ParParent < Sequel::Model; end
|
50
|
-
class ParParentTwo < Sequel::Model; end
|
51
|
-
class ParParentThree < Sequel::Model; end
|
49
|
+
class ::ParParent < Sequel::Model; end
|
50
|
+
class ::ParParentTwo < Sequel::Model; end
|
51
|
+
class ::ParParentThree < Sequel::Model; end
|
52
52
|
ParParent.many_to_one :par_parent_two
|
53
53
|
ParParentTwo.one_to_many :par_parents
|
54
54
|
ParParent.many_to_many :par_parent_threes
|
@@ -68,7 +68,7 @@ end
|
|
68
68
|
describe Sequel::Model::Associations::AssociationReflection, "#select" do
|
69
69
|
before do
|
70
70
|
@c = Class.new(Sequel::Model)
|
71
|
-
class ParParent < Sequel::Model; end
|
71
|
+
class ::ParParent < Sequel::Model; end
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should use the :select value if present" do
|
@@ -4,7 +4,7 @@ describe Sequel::Model, "associate" do
|
|
4
4
|
it "should use explicit class if given a class, symbol, or string" do
|
5
5
|
MODEL_DB.reset
|
6
6
|
klass = Class.new(Sequel::Model(:nodes))
|
7
|
-
class ParParent < Sequel::Model
|
7
|
+
class ::ParParent < Sequel::Model
|
8
8
|
end
|
9
9
|
|
10
10
|
klass.associate :many_to_one, :par_parent0, :class=>ParParent
|
@@ -48,6 +48,7 @@ describe Sequel::Model, "many_to_one" do
|
|
48
48
|
MODEL_DB.reset
|
49
49
|
|
50
50
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
51
|
+
unrestrict_primary_key
|
51
52
|
columns :id, :parent_id, :par_parent_id, :blah
|
52
53
|
end
|
53
54
|
|
@@ -66,7 +67,7 @@ describe Sequel::Model, "many_to_one" do
|
|
66
67
|
end
|
67
68
|
|
68
69
|
it "should use implicit class if omitted" do
|
69
|
-
class ParParent < Sequel::Model
|
70
|
+
class ::ParParent < Sequel::Model
|
70
71
|
end
|
71
72
|
|
72
73
|
@c2.many_to_one :par_parent
|
@@ -79,7 +80,7 @@ describe Sequel::Model, "many_to_one" do
|
|
79
80
|
end
|
80
81
|
|
81
82
|
it "should use class inside module if given as a string" do
|
82
|
-
module Par
|
83
|
+
module ::Par
|
83
84
|
class Parent < Sequel::Model
|
84
85
|
end
|
85
86
|
end
|
@@ -263,10 +264,29 @@ describe Sequel::Model, "many_to_one" do
|
|
263
264
|
MODEL_DB.sqls.should == []
|
264
265
|
end
|
265
266
|
|
267
|
+
it "should get all matching records and only return the first if :key option is set to nil" do
|
268
|
+
c2 = @c2
|
269
|
+
@c2.one_to_many :children, :class => @c2, :key=>:parent_id
|
270
|
+
@c2.many_to_one :first_grand_parent, :class => @c2, :key=>nil, :eager_graph=>:children, :dataset=>proc{c2.filter(:children_id=>parent_id)}
|
271
|
+
ds = @c2.dataset
|
272
|
+
def ds.columns
|
273
|
+
[:id, :parent_id, :par_parent_id, :blah]
|
274
|
+
end
|
275
|
+
def ds.fetch_rows(sql, &block)
|
276
|
+
MODEL_DB.sqls << sql
|
277
|
+
yield({:id=>1, :parent_id=>0, :par_parent_id=>3, :blah=>4, :children_id=>2, :children_parent_id=>1, :children_par_parent_id=>5, :children_blah=>6})
|
278
|
+
end
|
279
|
+
p = @c2.new(:parent_id=>2)
|
280
|
+
fgp = p.first_grand_parent
|
281
|
+
MODEL_DB.sqls.should == ["SELECT nodes.id, nodes.parent_id, nodes.par_parent_id, nodes.blah, children.id AS children_id, children.parent_id AS children_parent_id, children.par_parent_id AS children_par_parent_id, children.blah AS children_blah FROM nodes LEFT OUTER JOIN nodes AS children ON (children.parent_id = nodes.id) WHERE (children_id = 2)"]
|
282
|
+
fgp.values.should == {:id=>1, :parent_id=>0, :par_parent_id=>3, :blah=>4}
|
283
|
+
fgp.children.first.values.should == {:id=>2, :parent_id=>1, :par_parent_id=>5, :blah=>6}
|
284
|
+
end
|
285
|
+
|
266
286
|
it "should not create the setter method if :read_only option is used" do
|
267
287
|
@c2.many_to_one :parent, :class => @c2, :read_only=>true
|
268
|
-
@c2.instance_methods.should(include('parent'))
|
269
|
-
@c2.instance_methods.should_not(include('parent='))
|
288
|
+
@c2.instance_methods.collect{|x| x.to_s}.should(include('parent'))
|
289
|
+
@c2.instance_methods.collect{|x| x.to_s}.should_not(include('parent='))
|
270
290
|
end
|
271
291
|
|
272
292
|
it "should raise an error if trying to set a model object that doesn't have a valid primary key" do
|
@@ -292,7 +312,7 @@ describe Sequel::Model, "many_to_one" do
|
|
292
312
|
|
293
313
|
it "should make the change to the foreign_key value inside a _association= method" do
|
294
314
|
@c2.many_to_one :parent, :class => @c2
|
295
|
-
@c2.private_instance_methods.sort.should(include("_parent="))
|
315
|
+
@c2.private_instance_methods.collect{|x| x.to_s}.sort.should(include("_parent="))
|
296
316
|
p = @c2.new
|
297
317
|
c = @c2.load(:id=>123)
|
298
318
|
def p._parent=(x)
|
@@ -362,6 +382,11 @@ describe Sequel::Model, "many_to_one" do
|
|
362
382
|
proc{p.parent = nil}.should raise_error(Sequel::Error)
|
363
383
|
end
|
364
384
|
|
385
|
+
it "should raise an error if a callback is not a proc or symbol" do
|
386
|
+
@c2.many_to_one :parent, :class => @c2, :before_add=>Object.new
|
387
|
+
proc{@c2.new.parent = @c2.load(:id=>1)}.should raise_error(Sequel::Error)
|
388
|
+
end
|
389
|
+
|
365
390
|
it "should call the remove callbacks for the previous object and the add callbacks for the new object" do
|
366
391
|
c = @c2.load(:id=>123)
|
367
392
|
d = @c2.load(:id=>321)
|
@@ -398,10 +423,12 @@ describe Sequel::Model, "one_to_many" do
|
|
398
423
|
MODEL_DB.reset
|
399
424
|
|
400
425
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
426
|
+
unrestrict_primary_key
|
401
427
|
columns :id, :node_id
|
402
428
|
end
|
403
429
|
|
404
430
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
431
|
+
unrestrict_primary_key
|
405
432
|
attr_accessor :xxx
|
406
433
|
|
407
434
|
def self.name; 'Node'; end
|
@@ -435,7 +462,7 @@ describe Sequel::Model, "one_to_many" do
|
|
435
462
|
end
|
436
463
|
|
437
464
|
it "should use implicit class if omitted" do
|
438
|
-
class HistoricalValue < Sequel::Model
|
465
|
+
class ::HistoricalValue < Sequel::Model
|
439
466
|
end
|
440
467
|
|
441
468
|
@c2.one_to_many :historical_values
|
@@ -448,7 +475,7 @@ describe Sequel::Model, "one_to_many" do
|
|
448
475
|
end
|
449
476
|
|
450
477
|
it "should use class inside a module if given as a string" do
|
451
|
-
module Historical
|
478
|
+
module ::Historical
|
452
479
|
class Value < Sequel::Model
|
453
480
|
end
|
454
481
|
end
|
@@ -692,7 +719,7 @@ describe Sequel::Model, "one_to_many" do
|
|
692
719
|
|
693
720
|
it "should not create the add_, remove_, or remove_all_ methods if :read_only option is used" do
|
694
721
|
@c2.one_to_many :attributes, :class => @c1, :read_only=>true
|
695
|
-
im = @c2.instance_methods
|
722
|
+
im = @c2.instance_methods.collect{|x| x.to_s}
|
696
723
|
im.should(include('attributes'))
|
697
724
|
im.should(include('attributes_dataset'))
|
698
725
|
im.should_not(include('add_attribute'))
|
@@ -803,7 +830,7 @@ describe Sequel::Model, "one_to_many" do
|
|
803
830
|
|
804
831
|
it "should not add a getter method if the :one_to_one option is true and :read_only option is true" do
|
805
832
|
@c2.one_to_many :attributes, :class => @c1, :one_to_one=>true, :read_only=>true
|
806
|
-
im = @c2.instance_methods
|
833
|
+
im = @c2.instance_methods.collect{|x| x.to_s}
|
807
834
|
im.should(include('attribute'))
|
808
835
|
im.should_not(include('attribute='))
|
809
836
|
end
|
@@ -846,7 +873,7 @@ describe Sequel::Model, "one_to_many" do
|
|
846
873
|
|
847
874
|
it "should make non getter and setter methods private if :one_to_one option is used" do
|
848
875
|
@c2.one_to_many :attributes, :class => @c1, :one_to_one=>true do |ds| end
|
849
|
-
meths = @c2.private_instance_methods(false)
|
876
|
+
meths = @c2.private_instance_methods(false).collect{|x| x.to_s}
|
850
877
|
meths.should(include("attributes"))
|
851
878
|
meths.should(include("add_attribute"))
|
852
879
|
meths.should(include("attributes_dataset"))
|
@@ -854,7 +881,7 @@ describe Sequel::Model, "one_to_many" do
|
|
854
881
|
|
855
882
|
it "should call an _add_ method internally to add attributes" do
|
856
883
|
@c2.one_to_many :attributes, :class => @c1
|
857
|
-
@c2.private_instance_methods.sort.should(include("_add_attribute"))
|
884
|
+
@c2.private_instance_methods.collect{|x| x.to_s}.sort.should(include("_add_attribute"))
|
858
885
|
p = @c2.load(:id=>10)
|
859
886
|
c = @c1.load(:id=>123)
|
860
887
|
def p._add_attribute(x)
|
@@ -867,7 +894,7 @@ describe Sequel::Model, "one_to_many" do
|
|
867
894
|
|
868
895
|
it "should call a _remove_ method internally to remove attributes" do
|
869
896
|
@c2.one_to_many :attributes, :class => @c1
|
870
|
-
@c2.private_instance_methods.sort.should(include("_remove_attribute"))
|
897
|
+
@c2.private_instance_methods.collect{|x| x.to_s}.sort.should(include("_remove_attribute"))
|
871
898
|
p = @c2.load(:id=>10)
|
872
899
|
c = @c1.load(:id=>123)
|
873
900
|
def p._remove_attribute(x)
|
@@ -966,12 +993,14 @@ describe Sequel::Model, "many_to_many" do
|
|
966
993
|
MODEL_DB.reset
|
967
994
|
|
968
995
|
@c1 = Class.new(Sequel::Model(:attributes)) do
|
996
|
+
unrestrict_primary_key
|
969
997
|
def self.name; 'Attribute'; end
|
970
998
|
def self.to_s; 'Attribute'; end
|
971
999
|
columns :id
|
972
1000
|
end
|
973
1001
|
|
974
1002
|
@c2 = Class.new(Sequel::Model(:nodes)) do
|
1003
|
+
unrestrict_primary_key
|
975
1004
|
attr_accessor :xxx
|
976
1005
|
|
977
1006
|
def self.name; 'Node'; end
|
@@ -1000,7 +1029,7 @@ describe Sequel::Model, "many_to_many" do
|
|
1000
1029
|
end
|
1001
1030
|
|
1002
1031
|
it "should use implicit class if omitted" do
|
1003
|
-
class Tag < Sequel::Model
|
1032
|
+
class ::Tag < Sequel::Model
|
1004
1033
|
end
|
1005
1034
|
|
1006
1035
|
@c2.many_to_many :tags
|
@@ -1012,7 +1041,7 @@ describe Sequel::Model, "many_to_many" do
|
|
1012
1041
|
end
|
1013
1042
|
|
1014
1043
|
it "should use class inside module if given as a string" do
|
1015
|
-
module Historical
|
1044
|
+
module ::Historical
|
1016
1045
|
class Tag < Sequel::Model
|
1017
1046
|
end
|
1018
1047
|
end
|
@@ -1263,7 +1292,7 @@ describe Sequel::Model, "many_to_many" do
|
|
1263
1292
|
|
1264
1293
|
it "should not create the add_, remove_, or remove_all_ methods if :read_only option is used" do
|
1265
1294
|
@c2.many_to_many :attributes, :class => @c1, :read_only=>true
|
1266
|
-
im = @c2.instance_methods
|
1295
|
+
im = @c2.instance_methods.collect{|x| x.to_s}
|
1267
1296
|
im.should(include('attributes'))
|
1268
1297
|
im.should(include('attributes_dataset'))
|
1269
1298
|
im.should_not(include('add_attribute'))
|
@@ -1329,7 +1358,7 @@ describe Sequel::Model, "many_to_many" do
|
|
1329
1358
|
|
1330
1359
|
it "should call an _add_ method internally to add attributes" do
|
1331
1360
|
@c2.many_to_many :attributes, :class => @c1
|
1332
|
-
@c2.private_instance_methods.sort.should(include("_add_attribute"))
|
1361
|
+
@c2.private_instance_methods.collect{|x| x.to_s}.sort.should(include("_add_attribute"))
|
1333
1362
|
p = @c2.load(:id=>10)
|
1334
1363
|
c = @c1.load(:id=>123)
|
1335
1364
|
def p._add_attribute(x)
|
@@ -1342,7 +1371,7 @@ describe Sequel::Model, "many_to_many" do
|
|
1342
1371
|
|
1343
1372
|
it "should call a _remove_ method internally to remove attributes" do
|
1344
1373
|
@c2.many_to_many :attributes, :class => @c1
|
1345
|
-
@c2.private_instance_methods.sort.should(include("_remove_attribute"))
|
1374
|
+
@c2.private_instance_methods.collect{|x| x.to_s}.sort.should(include("_remove_attribute"))
|
1346
1375
|
p = @c2.load(:id=>10)
|
1347
1376
|
c = @c1.load(:id=>123)
|
1348
1377
|
def p._remove_attribute(x)
|
@@ -79,10 +79,11 @@ describe "Model#serialize" do
|
|
79
79
|
|
80
80
|
@c.create(:abc => 1)
|
81
81
|
@c.create(:abc => "hello")
|
82
|
+
x = [Marshal.dump("hello")].pack('m')
|
82
83
|
|
83
84
|
MODEL_DB.sqls.should == [ \
|
84
85
|
"INSERT INTO items (abc) VALUES ('BAhpBg==\n')", \
|
85
|
-
"INSERT INTO items (abc) VALUES ('
|
86
|
+
"INSERT INTO items (abc) VALUES ('#{x}')", \
|
86
87
|
]
|
87
88
|
end
|
88
89
|
|
File without changes
|
@@ -56,7 +56,19 @@ describe Sequel::Model::DatasetMethods, "#to_hash" do
|
|
56
56
|
h.should be_a_kind_of(Hash)
|
57
57
|
a = h.to_a
|
58
58
|
a.collect{|x| x[1].class}.should == [@c, @c]
|
59
|
-
[[[
|
59
|
+
a.sort_by{|x| x[0]}.collect{|x| [x[0], x[1].values]}.should == [[1, {:name=>1}], [2, {:name=>2}]]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should result in a hash with given value keys and model object values" do
|
63
|
+
def @d.fetch_rows(sql)
|
64
|
+
yield({:name=>1, :number=>3})
|
65
|
+
yield({:name=>2, :number=>4})
|
66
|
+
end
|
67
|
+
h = @d.to_hash(:number)
|
68
|
+
h.should be_a_kind_of(Hash)
|
69
|
+
a = h.to_a
|
70
|
+
a.collect{|x| x[1].class}.should == [@c, @c]
|
71
|
+
a.sort_by{|x| x[0]}.collect{|x| [x[0], x[1].values]}.should == [[3, {:name=>1, :number=>3}], [4, {:name=>2, :number=>4}]]
|
60
72
|
end
|
61
73
|
|
62
74
|
it "should raise an error if the class doesn't have a primary key" do
|
@@ -4,7 +4,7 @@ describe Sequel::Model, "#eager" do
|
|
4
4
|
before(:each) do
|
5
5
|
MODEL_DB.reset
|
6
6
|
|
7
|
-
class EagerAlbum < Sequel::Model(:albums)
|
7
|
+
class ::EagerAlbum < Sequel::Model(:albums)
|
8
8
|
columns :id, :band_id
|
9
9
|
many_to_one :band, :class=>'EagerBand', :key=>:band_id
|
10
10
|
one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id
|
@@ -17,7 +17,7 @@ describe Sequel::Model, "#eager" do
|
|
17
17
|
many_to_many :genre_names, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :select=>[:id]
|
18
18
|
end
|
19
19
|
|
20
|
-
class EagerBand < Sequel::Model(:bands)
|
20
|
+
class ::EagerBand < Sequel::Model(:bands)
|
21
21
|
columns :id
|
22
22
|
one_to_many :albums, :class=>'EagerAlbum', :key=>:band_id, :eager=>:tracks
|
23
23
|
one_to_many :graph_albums, :class=>'EagerAlbum', :key=>:band_id, :eager_graph=>:tracks
|
@@ -32,17 +32,17 @@ describe Sequel::Model, "#eager" do
|
|
32
32
|
one_to_many :top_10_albums, :class=>'EagerAlbum', :key=>:band_id, :limit=>10
|
33
33
|
end
|
34
34
|
|
35
|
-
class EagerTrack < Sequel::Model(:tracks)
|
35
|
+
class ::EagerTrack < Sequel::Model(:tracks)
|
36
36
|
columns :id, :album_id
|
37
37
|
many_to_one :album, :class=>'EagerAlbum', :key=>:album_id
|
38
38
|
end
|
39
39
|
|
40
|
-
class EagerGenre < Sequel::Model(:genres)
|
40
|
+
class ::EagerGenre < Sequel::Model(:genres)
|
41
41
|
columns :id
|
42
42
|
many_to_many :albums, :class=>'EagerAlbum', :left_key=>:genre_id, :right_key=>:album_id, :join_table=>:ag
|
43
43
|
end
|
44
44
|
|
45
|
-
class EagerBandMember < Sequel::Model(:members)
|
45
|
+
class ::EagerBandMember < Sequel::Model(:members)
|
46
46
|
columns :id
|
47
47
|
many_to_many :bands, :class=>'EagerBand', :left_key=>:member_id, :right_key=>:band_id, :join_table=>:bm, :order =>:id
|
48
48
|
end
|
@@ -106,6 +106,10 @@ describe Sequel::Model, "#eager" do
|
|
106
106
|
})
|
107
107
|
end
|
108
108
|
|
109
|
+
it "should raise an error if called without a symbol or hash" do
|
110
|
+
proc{EagerAlbum.eager(Object.new)}.should raise_error(Sequel::Error)
|
111
|
+
end
|
112
|
+
|
109
113
|
it "should eagerly load a single many_to_one association" do
|
110
114
|
a = EagerAlbum.eager(:band).all
|
111
115
|
a.should be_a_kind_of(Array)
|
@@ -149,7 +153,7 @@ describe Sequel::Model, "#eager" do
|
|
149
153
|
MODEL_DB.sqls.length.should == 2
|
150
154
|
end
|
151
155
|
|
152
|
-
it "should eagerly load multiple associations" do
|
156
|
+
it "should eagerly load multiple associations in a single call" do
|
153
157
|
a = EagerAlbum.eager(:genres, :tracks, :band).all
|
154
158
|
a.should be_a_kind_of(Array)
|
155
159
|
a.size.should == 1
|
@@ -174,6 +178,31 @@ describe Sequel::Model, "#eager" do
|
|
174
178
|
MODEL_DB.sqls.length.should == 4
|
175
179
|
end
|
176
180
|
|
181
|
+
it "should eagerly load multiple associations in separate calls" do
|
182
|
+
a = EagerAlbum.eager(:genres).eager(:tracks).eager(:band).all
|
183
|
+
a.should be_a_kind_of(Array)
|
184
|
+
a.size.should == 1
|
185
|
+
a.first.should be_a_kind_of(EagerAlbum)
|
186
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
187
|
+
MODEL_DB.sqls.length.should == 4
|
188
|
+
MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
|
189
|
+
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM bands WHERE (bands.id IN (2))'))
|
190
|
+
MODEL_DB.sqls[1..-1].should(include('SELECT * FROM tracks WHERE (tracks.album_id IN (1))'))
|
191
|
+
MODEL_DB.sqls[1..-1].should(include('SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))'))
|
192
|
+
a = a.first
|
193
|
+
a.band.should be_a_kind_of(EagerBand)
|
194
|
+
a.band.values.should == {:id => 2}
|
195
|
+
a.tracks.should be_a_kind_of(Array)
|
196
|
+
a.tracks.size.should == 1
|
197
|
+
a.tracks.first.should be_a_kind_of(EagerTrack)
|
198
|
+
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
199
|
+
a.genres.should be_a_kind_of(Array)
|
200
|
+
a.genres.size.should == 1
|
201
|
+
a.genres.first.should be_a_kind_of(EagerGenre)
|
202
|
+
a.genres.first.values.should == {:id => 4}
|
203
|
+
MODEL_DB.sqls.length.should == 4
|
204
|
+
end
|
205
|
+
|
177
206
|
it "should allow cascading of eager loading for associations of associated models" do
|
178
207
|
a = EagerTrack.eager(:album=>{:band=>:members}).all
|
179
208
|
a.should be_a_kind_of(Array)
|
@@ -430,13 +459,13 @@ end
|
|
430
459
|
|
431
460
|
describe Sequel::Model, "#eager_graph" do
|
432
461
|
after(:all) do
|
433
|
-
class MockDataset
|
462
|
+
class ::MockDataset
|
434
463
|
alias clone orig_clone
|
435
464
|
end
|
436
465
|
end
|
437
466
|
|
438
467
|
before(:all) do
|
439
|
-
class MockDataset
|
468
|
+
class ::MockDataset
|
440
469
|
alias orig_clone clone
|
441
470
|
def clone(opts = {})
|
442
471
|
c = super()
|
@@ -446,15 +475,16 @@ describe Sequel::Model, "#eager_graph" do
|
|
446
475
|
end
|
447
476
|
end
|
448
477
|
|
449
|
-
class GraphAlbum < Sequel::Model(:albums)
|
478
|
+
class ::GraphAlbum < Sequel::Model(:albums)
|
450
479
|
dataset.opts[:from] = [:albums]
|
451
480
|
columns :id, :band_id
|
452
481
|
many_to_one :band, :class=>'GraphBand', :key=>:band_id
|
453
482
|
one_to_many :tracks, :class=>'GraphTrack', :key=>:album_id
|
454
483
|
many_to_many :genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag
|
484
|
+
many_to_one :previous_album, :class=>'GraphAlbum'
|
455
485
|
end
|
456
486
|
|
457
|
-
class GraphBand < Sequel::Model(:bands)
|
487
|
+
class ::GraphBand < Sequel::Model(:bands)
|
458
488
|
dataset.opts[:from] = [:bands]
|
459
489
|
columns :id, :vocalist_id
|
460
490
|
many_to_one :vocalist, :class=>'GraphBandMember', :key=>:vocalist_id
|
@@ -463,25 +493,29 @@ describe Sequel::Model, "#eager_graph" do
|
|
463
493
|
many_to_many :genres, :class=>'GraphGenre', :left_key=>:band_id, :right_key=>:genre_id, :join_table=>:bg
|
464
494
|
end
|
465
495
|
|
466
|
-
class GraphTrack < Sequel::Model(:tracks)
|
496
|
+
class ::GraphTrack < Sequel::Model(:tracks)
|
467
497
|
dataset.opts[:from] = [:tracks]
|
468
498
|
columns :id, :album_id
|
469
499
|
many_to_one :album, :class=>'GraphAlbum', :key=>:album_id
|
470
500
|
end
|
471
501
|
|
472
|
-
class GraphGenre < Sequel::Model(:genres)
|
502
|
+
class ::GraphGenre < Sequel::Model(:genres)
|
473
503
|
dataset.opts[:from] = [:genres]
|
474
504
|
columns :id
|
475
505
|
many_to_many :albums, :class=>'GraphAlbum', :left_key=>:genre_id, :right_key=>:album_id, :join_table=>:ag
|
476
506
|
end
|
477
507
|
|
478
|
-
class GraphBandMember < Sequel::Model(:members)
|
508
|
+
class ::GraphBandMember < Sequel::Model(:members)
|
479
509
|
dataset.opts[:from] = [:members]
|
480
510
|
columns :id
|
481
511
|
many_to_many :bands, :class=>'GraphBand', :left_key=>:member_id, :right_key=>:band_id, :join_table=>:bm
|
482
512
|
end
|
483
513
|
end
|
484
514
|
|
515
|
+
it "should raise an error if called without a symbol or hash" do
|
516
|
+
proc{GraphAlbum.eager_graph(Object.new)}.should raise_error(Sequel::Error)
|
517
|
+
end
|
518
|
+
|
485
519
|
it "should eagerly load a single many_to_one association" do
|
486
520
|
ds = GraphAlbum.eager_graph(:band)
|
487
521
|
ds.sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
@@ -534,7 +568,7 @@ describe Sequel::Model, "#eager_graph" do
|
|
534
568
|
a.genres.first.values.should == {:id => 4}
|
535
569
|
end
|
536
570
|
|
537
|
-
it "should eagerly load multiple associations" do
|
571
|
+
it "should eagerly load multiple associations in a single call" do
|
538
572
|
ds = GraphAlbum.eager_graph(:genres, :tracks, :band)
|
539
573
|
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
540
574
|
def ds.fetch_rows(sql, &block)
|
@@ -558,6 +592,30 @@ describe Sequel::Model, "#eager_graph" do
|
|
558
592
|
a.genres.first.values.should == {:id => 4}
|
559
593
|
end
|
560
594
|
|
595
|
+
it "should eagerly load multiple associations in separate calls" do
|
596
|
+
ds = GraphAlbum.eager_graph(:genres).eager_graph(:tracks).eager_graph(:band)
|
597
|
+
ds.sql.should == 'SELECT albums.id, albums.band_id, genres.id AS genres_id, tracks.id AS tracks_id, tracks.album_id, band.id AS band_id_0, band.vocalist_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres ON (genres.id = ag.genre_id) LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id) LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id)'
|
598
|
+
def ds.fetch_rows(sql, &block)
|
599
|
+
yield({:id=>1, :band_id=>2, :genres_id=>4, :tracks_id=>3, :album_id=>1, :band_id_0=>2, :vocalist_id=>6})
|
600
|
+
end
|
601
|
+
a = ds.all
|
602
|
+
a.should be_a_kind_of(Array)
|
603
|
+
a.size.should == 1
|
604
|
+
a.first.should be_a_kind_of(GraphAlbum)
|
605
|
+
a.first.values.should == {:id => 1, :band_id => 2}
|
606
|
+
a = a.first
|
607
|
+
a.band.should be_a_kind_of(GraphBand)
|
608
|
+
a.band.values.should == {:id => 2, :vocalist_id=>6}
|
609
|
+
a.tracks.should be_a_kind_of(Array)
|
610
|
+
a.tracks.size.should == 1
|
611
|
+
a.tracks.first.should be_a_kind_of(GraphTrack)
|
612
|
+
a.tracks.first.values.should == {:id => 3, :album_id=>1}
|
613
|
+
a.genres.should be_a_kind_of(Array)
|
614
|
+
a.genres.size.should == 1
|
615
|
+
a.genres.first.should be_a_kind_of(GraphGenre)
|
616
|
+
a.genres.first.values.should == {:id => 4}
|
617
|
+
end
|
618
|
+
|
561
619
|
it "should allow cascading of eager loading for associations of associated models" do
|
562
620
|
ds = GraphTrack.eager_graph(:album=>{:band=>:members})
|
563
621
|
ds.sql.should == 'SELECT tracks.id, tracks.album_id, album.id AS album_id_0, album.band_id, band.id AS band_id_0, band.vocalist_id, members.id AS members_id FROM tracks LEFT OUTER JOIN albums AS album ON (album.id = tracks.album_id) LEFT OUTER JOIN bands AS band ON (band.id = album.band_id) LEFT OUTER JOIN bm ON (bm.band_id = band.id) LEFT OUTER JOIN members ON (members.id = bm.member_id)'
|
@@ -900,4 +958,7 @@ describe Sequel::Model, "#eager_graph" do
|
|
900
958
|
GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON (active) LEFT OUTER JOIN genres AS active_genres ON ((price + 2) > 100)"
|
901
959
|
end
|
902
960
|
|
961
|
+
it "should create unique table aliases for all associations" do
|
962
|
+
GraphAlbum.eager_graph(:previous_album=>{:previous_album=>:previous_album}).sql.should == "SELECT albums.id, albums.band_id, previous_album.id AS previous_album_id, previous_album.band_id AS previous_album_band_id, previous_album_0.id AS previous_album_0_id, previous_album_0.band_id AS previous_album_0_band_id, previous_album_1.id AS previous_album_1_id, previous_album_1.band_id AS previous_album_1_band_id FROM albums LEFT OUTER JOIN albums AS previous_album ON (previous_album.id = albums.previous_album_id) LEFT OUTER JOIN albums AS previous_album_0 ON (previous_album_0.id = previous_album.previous_album_id) LEFT OUTER JOIN albums AS previous_album_1 ON (previous_album_1.id = previous_album_0.previous_album_id)"
|
963
|
+
end
|
903
964
|
end
|