sequel 3.47.0 → 3.48.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (243) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +230 -0
  3. data/README.rdoc +31 -40
  4. data/Rakefile +1 -14
  5. data/doc/active_record.rdoc +29 -29
  6. data/doc/association_basics.rdoc +4 -13
  7. data/doc/cheat_sheet.rdoc +8 -6
  8. data/doc/code_order.rdoc +89 -0
  9. data/doc/core_extensions.rdoc +3 -3
  10. data/doc/dataset_basics.rdoc +7 -8
  11. data/doc/dataset_filtering.rdoc +7 -2
  12. data/doc/mass_assignment.rdoc +2 -3
  13. data/doc/migration.rdoc +8 -8
  14. data/doc/model_hooks.rdoc +11 -7
  15. data/doc/object_model.rdoc +2 -2
  16. data/doc/opening_databases.rdoc +5 -14
  17. data/doc/prepared_statements.rdoc +5 -9
  18. data/doc/querying.rdoc +23 -28
  19. data/doc/reflection.rdoc +11 -0
  20. data/doc/release_notes/3.48.0.txt +477 -0
  21. data/doc/schema_modification.rdoc +12 -5
  22. data/doc/security.rdoc +2 -2
  23. data/doc/sharding.rdoc +1 -2
  24. data/doc/sql.rdoc +10 -13
  25. data/doc/testing.rdoc +8 -4
  26. data/doc/transactions.rdoc +2 -2
  27. data/doc/validations.rdoc +40 -17
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado.rb +25 -20
  30. data/lib/sequel/adapters/ado/access.rb +1 -0
  31. data/lib/sequel/adapters/ado/mssql.rb +1 -0
  32. data/lib/sequel/adapters/db2.rb +9 -7
  33. data/lib/sequel/adapters/dbi.rb +16 -16
  34. data/lib/sequel/adapters/do.rb +17 -18
  35. data/lib/sequel/adapters/do/mysql.rb +1 -0
  36. data/lib/sequel/adapters/do/postgres.rb +2 -0
  37. data/lib/sequel/adapters/do/sqlite.rb +1 -0
  38. data/lib/sequel/adapters/firebird.rb +5 -7
  39. data/lib/sequel/adapters/ibmdb.rb +23 -20
  40. data/lib/sequel/adapters/informix.rb +8 -2
  41. data/lib/sequel/adapters/jdbc.rb +39 -35
  42. data/lib/sequel/adapters/jdbc/as400.rb +1 -0
  43. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -0
  44. data/lib/sequel/adapters/jdbc/db2.rb +1 -0
  45. data/lib/sequel/adapters/jdbc/derby.rb +1 -0
  46. data/lib/sequel/adapters/jdbc/firebird.rb +1 -0
  47. data/lib/sequel/adapters/jdbc/h2.rb +1 -0
  48. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -0
  49. data/lib/sequel/adapters/jdbc/informix.rb +1 -0
  50. data/lib/sequel/adapters/jdbc/jtds.rb +1 -0
  51. data/lib/sequel/adapters/jdbc/mssql.rb +1 -0
  52. data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
  53. data/lib/sequel/adapters/jdbc/oracle.rb +1 -0
  54. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -0
  55. data/lib/sequel/adapters/jdbc/progress.rb +1 -0
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -0
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -0
  58. data/lib/sequel/adapters/mock.rb +30 -31
  59. data/lib/sequel/adapters/mysql.rb +6 -7
  60. data/lib/sequel/adapters/mysql2.rb +5 -6
  61. data/lib/sequel/adapters/odbc.rb +22 -20
  62. data/lib/sequel/adapters/odbc/mssql.rb +1 -0
  63. data/lib/sequel/adapters/openbase.rb +4 -1
  64. data/lib/sequel/adapters/oracle.rb +10 -8
  65. data/lib/sequel/adapters/postgres.rb +12 -10
  66. data/lib/sequel/adapters/shared/access.rb +6 -0
  67. data/lib/sequel/adapters/shared/cubrid.rb +2 -0
  68. data/lib/sequel/adapters/shared/db2.rb +2 -0
  69. data/lib/sequel/adapters/shared/firebird.rb +2 -0
  70. data/lib/sequel/adapters/shared/informix.rb +2 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +14 -8
  72. data/lib/sequel/adapters/shared/mysql.rb +6 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +2 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +14 -4
  75. data/lib/sequel/adapters/shared/progress.rb +1 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +4 -3
  77. data/lib/sequel/adapters/sqlite.rb +6 -7
  78. data/lib/sequel/adapters/swift.rb +20 -21
  79. data/lib/sequel/adapters/swift/mysql.rb +1 -0
  80. data/lib/sequel/adapters/swift/postgres.rb +2 -0
  81. data/lib/sequel/adapters/swift/sqlite.rb +1 -0
  82. data/lib/sequel/adapters/tinytds.rb +5 -6
  83. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +68 -0
  84. data/lib/sequel/connection_pool.rb +1 -1
  85. data/lib/sequel/core.rb +57 -50
  86. data/lib/sequel/database/connecting.rb +9 -10
  87. data/lib/sequel/database/dataset.rb +11 -6
  88. data/lib/sequel/database/dataset_defaults.rb +61 -69
  89. data/lib/sequel/database/features.rb +21 -0
  90. data/lib/sequel/database/misc.rb +23 -3
  91. data/lib/sequel/database/query.rb +13 -7
  92. data/lib/sequel/database/schema_methods.rb +6 -6
  93. data/lib/sequel/database/transactions.rb +1 -0
  94. data/lib/sequel/dataset/actions.rb +51 -38
  95. data/lib/sequel/dataset/features.rb +1 -0
  96. data/lib/sequel/dataset/graph.rb +9 -33
  97. data/lib/sequel/dataset/misc.rb +30 -5
  98. data/lib/sequel/dataset/mutation.rb +2 -3
  99. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  100. data/lib/sequel/dataset/query.rb +91 -27
  101. data/lib/sequel/dataset/sql.rb +40 -6
  102. data/lib/sequel/deprecated.rb +74 -0
  103. data/lib/sequel/deprecated_core_extensions.rb +135 -0
  104. data/lib/sequel/extensions/columns_introspection.rb +1 -5
  105. data/lib/sequel/extensions/core_extensions.rb +10 -3
  106. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  107. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +33 -0
  108. data/lib/sequel/extensions/filter_having.rb +58 -0
  109. data/lib/sequel/extensions/graph_each.rb +63 -0
  110. data/lib/sequel/extensions/hash_aliases.rb +44 -0
  111. data/lib/sequel/extensions/looser_typecasting.rb +14 -3
  112. data/lib/sequel/extensions/migration.rb +2 -3
  113. data/lib/sequel/extensions/named_timezones.rb +14 -1
  114. data/lib/sequel/extensions/null_dataset.rb +7 -1
  115. data/lib/sequel/extensions/pagination.rb +15 -5
  116. data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -0
  117. data/lib/sequel/extensions/pg_hstore_ops.rb +48 -14
  118. data/lib/sequel/extensions/pg_json.rb +7 -7
  119. data/lib/sequel/extensions/pg_range_ops.rb +8 -2
  120. data/lib/sequel/extensions/pg_statement_cache.rb +1 -0
  121. data/lib/sequel/extensions/pretty_table.rb +13 -4
  122. data/lib/sequel/extensions/query.rb +21 -4
  123. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +22 -0
  124. data/lib/sequel/extensions/schema_caching.rb +10 -7
  125. data/lib/sequel/extensions/schema_dumper.rb +35 -48
  126. data/lib/sequel/extensions/select_remove.rb +13 -4
  127. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +117 -0
  128. data/lib/sequel/extensions/set_overrides.rb +43 -0
  129. data/lib/sequel/extensions/to_dot.rb +6 -0
  130. data/lib/sequel/model.rb +12 -6
  131. data/lib/sequel/model/associations.rb +80 -38
  132. data/lib/sequel/model/base.rb +137 -52
  133. data/lib/sequel/model/errors.rb +7 -2
  134. data/lib/sequel/plugins/active_model.rb +13 -0
  135. data/lib/sequel/plugins/after_initialize.rb +43 -0
  136. data/lib/sequel/plugins/association_proxies.rb +63 -7
  137. data/lib/sequel/plugins/auto_validations.rb +56 -16
  138. data/lib/sequel/plugins/blacklist_security.rb +63 -0
  139. data/lib/sequel/plugins/class_table_inheritance.rb +9 -0
  140. data/lib/sequel/plugins/constraint_validations.rb +50 -8
  141. data/lib/sequel/plugins/dataset_associations.rb +2 -0
  142. data/lib/sequel/plugins/hook_class_methods.rb +7 -1
  143. data/lib/sequel/plugins/identity_map.rb +4 -0
  144. data/lib/sequel/plugins/json_serializer.rb +32 -13
  145. data/lib/sequel/plugins/optimistic_locking.rb +1 -1
  146. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  147. data/lib/sequel/plugins/scissors.rb +33 -0
  148. data/lib/sequel/plugins/serialization.rb +1 -1
  149. data/lib/sequel/plugins/single_table_inheritance.rb +6 -0
  150. data/lib/sequel/plugins/tree.rb +5 -1
  151. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  152. data/lib/sequel/plugins/validation_helpers.rb +15 -11
  153. data/lib/sequel/plugins/xml_serializer.rb +12 -3
  154. data/lib/sequel/sql.rb +12 -2
  155. data/lib/sequel/timezones.rb +1 -1
  156. data/lib/sequel/version.rb +1 -1
  157. data/lib/sequel_core.rb +1 -0
  158. data/lib/sequel_model.rb +1 -0
  159. data/spec/adapters/mssql_spec.rb +24 -57
  160. data/spec/adapters/postgres_spec.rb +27 -55
  161. data/spec/adapters/spec_helper.rb +1 -1
  162. data/spec/adapters/sqlite_spec.rb +1 -1
  163. data/spec/bin_spec.rb +251 -0
  164. data/spec/core/database_spec.rb +46 -32
  165. data/spec/core/dataset_spec.rb +233 -181
  166. data/spec/core/deprecated_spec.rb +78 -0
  167. data/spec/core/expression_filters_spec.rb +3 -4
  168. data/spec/core/mock_adapter_spec.rb +9 -9
  169. data/spec/core/object_graph_spec.rb +9 -19
  170. data/spec/core/schema_spec.rb +3 -1
  171. data/spec/core/spec_helper.rb +19 -0
  172. data/spec/core_extensions_spec.rb +80 -30
  173. data/spec/extensions/after_initialize_spec.rb +24 -0
  174. data/spec/extensions/association_proxies_spec.rb +37 -1
  175. data/spec/extensions/auto_validations_spec.rb +20 -4
  176. data/spec/extensions/blacklist_security_spec.rb +87 -0
  177. data/spec/extensions/boolean_readers_spec.rb +2 -1
  178. data/spec/extensions/class_table_inheritance_spec.rb +7 -0
  179. data/spec/extensions/columns_introspection_spec.rb +3 -3
  180. data/spec/extensions/constraint_validations_plugin_spec.rb +83 -5
  181. data/spec/extensions/core_refinements_spec.rb +7 -7
  182. data/spec/extensions/dataset_associations_spec.rb +2 -2
  183. data/spec/extensions/date_arithmetic_spec.rb +1 -1
  184. data/spec/extensions/defaults_setter_spec.rb +2 -1
  185. data/spec/extensions/empty_array_ignore_nulls_spec.rb +24 -0
  186. data/spec/extensions/filter_having_spec.rb +40 -0
  187. data/spec/extensions/graph_each_spec.rb +109 -0
  188. data/spec/extensions/hash_aliases_spec.rb +16 -0
  189. data/spec/extensions/hook_class_methods_spec.rb +2 -2
  190. data/spec/extensions/identity_map_spec.rb +3 -3
  191. data/spec/extensions/json_serializer_spec.rb +19 -19
  192. data/spec/extensions/lazy_attributes_spec.rb +1 -0
  193. data/spec/extensions/list_spec.rb +13 -13
  194. data/spec/extensions/looser_typecasting_spec.rb +10 -3
  195. data/spec/extensions/many_through_many_spec.rb +1 -1
  196. data/spec/extensions/migration_spec.rb +7 -7
  197. data/spec/extensions/named_timezones_spec.rb +6 -0
  198. data/spec/extensions/nested_attributes_spec.rb +2 -2
  199. data/spec/extensions/null_dataset_spec.rb +1 -1
  200. data/spec/extensions/pagination_spec.rb +2 -2
  201. data/spec/extensions/pg_hstore_ops_spec.rb +75 -0
  202. data/spec/extensions/pg_range_ops_spec.rb +4 -2
  203. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  204. data/spec/extensions/pretty_table_spec.rb +1 -1
  205. data/spec/extensions/query_literals_spec.rb +1 -1
  206. data/spec/extensions/query_spec.rb +3 -3
  207. data/spec/extensions/schema_caching_spec.rb +3 -3
  208. data/spec/extensions/schema_dumper_spec.rb +27 -2
  209. data/spec/extensions/schema_spec.rb +2 -2
  210. data/spec/extensions/scissors_spec.rb +26 -0
  211. data/spec/extensions/select_remove_spec.rb +1 -1
  212. data/spec/extensions/sequel_3_dataset_methods_spec.rb +102 -0
  213. data/spec/extensions/set_overrides_spec.rb +45 -0
  214. data/spec/extensions/single_table_inheritance_spec.rb +10 -0
  215. data/spec/extensions/spec_helper.rb +24 -1
  216. data/spec/extensions/static_cache_spec.rb +1 -1
  217. data/spec/extensions/string_stripper_spec.rb +2 -1
  218. data/spec/extensions/to_dot_spec.rb +1 -1
  219. data/spec/extensions/typecast_on_load_spec.rb +3 -2
  220. data/spec/extensions/update_primary_key_spec.rb +2 -2
  221. data/spec/extensions/validation_class_methods_spec.rb +19 -19
  222. data/spec/extensions/validation_helpers_spec.rb +30 -21
  223. data/spec/extensions/xml_serializer_spec.rb +5 -5
  224. data/spec/integration/associations_test.rb +10 -30
  225. data/spec/integration/dataset_test.rb +20 -24
  226. data/spec/integration/eager_loader_test.rb +5 -5
  227. data/spec/integration/model_test.rb +3 -3
  228. data/spec/integration/plugin_test.rb +7 -39
  229. data/spec/integration/schema_test.rb +4 -38
  230. data/spec/integration/spec_helper.rb +2 -1
  231. data/spec/model/association_reflection_spec.rb +70 -5
  232. data/spec/model/associations_spec.rb +11 -11
  233. data/spec/model/base_spec.rb +25 -8
  234. data/spec/model/class_dataset_methods_spec.rb +143 -0
  235. data/spec/model/dataset_methods_spec.rb +1 -1
  236. data/spec/model/eager_loading_spec.rb +25 -25
  237. data/spec/model/hooks_spec.rb +1 -1
  238. data/spec/model/model_spec.rb +22 -7
  239. data/spec/model/plugins_spec.rb +1 -6
  240. data/spec/model/record_spec.rb +37 -29
  241. data/spec/model/spec_helper.rb +23 -1
  242. data/spec/model/validations_spec.rb +15 -17
  243. metadata +32 -3
@@ -462,7 +462,7 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
462
462
  @c.allowed_columns.should == [:x, :y]
463
463
  end
464
464
 
465
- it "should set the restricted columns correctly" do
465
+ qspecify "should set the restricted columns correctly" do
466
466
  @c.restricted_columns.should == nil
467
467
  @c.set_restricted_columns :x
468
468
  @c.restricted_columns.should == [:x]
@@ -484,7 +484,7 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
484
484
  MODEL_DB.sqls.should == ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
485
485
  end
486
486
 
487
- it "should not set restricted columns by default" do
487
+ qspecify "should not set restricted columns by default" do
488
488
  @c.set_restricted_columns :z
489
489
  i = @c.new(:x => 1, :y => 2, :z => 3)
490
490
  i.values.should == {:x => 1, :y => 2}
@@ -498,7 +498,7 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
498
498
  MODEL_DB.sqls.should == ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
499
499
  end
500
500
 
501
- it "should have allowed take precedence over restricted" do
501
+ qspecify "should have allowed take precedence over restricted" do
502
502
  @c.set_allowed_columns :x, :y
503
503
  @c.set_restricted_columns :y, :z
504
504
  i = @c.new(:x => 1, :y => 2, :z => 3)
@@ -556,7 +556,7 @@ describe Sequel::Model, ".strict_param_setting" do
556
556
  before do
557
557
  @c = Class.new(Sequel::Model(:blahblah)) do
558
558
  columns :x, :y, :z, :id
559
- set_restricted_columns :z
559
+ set_allowed_columns :x, :y
560
560
  end
561
561
  end
562
562
 
@@ -571,10 +571,14 @@ describe Sequel::Model, ".strict_param_setting" do
571
571
  proc{c.set(:z=>1)}.should raise_error(Sequel::Error)
572
572
  proc{c.set_all(:id=>1)}.should raise_error(Sequel::Error)
573
573
  proc{c.set_only({:x=>1}, :y)}.should raise_error(Sequel::Error)
574
- proc{c.set_except({:x=>1}, :x)}.should raise_error(Sequel::Error)
575
574
  proc{c.update(:z=>1)}.should raise_error(Sequel::Error)
576
575
  proc{c.update_all(:id=>1)}.should raise_error(Sequel::Error)
577
576
  proc{c.update_only({:x=>1}, :y)}.should raise_error(Sequel::Error)
577
+ end
578
+
579
+ qspecify "should raise an error if a missing/restricted column/method is accessed by *_except" do
580
+ c = @c.new
581
+ proc{c.set_except({:x=>1}, :x)}.should raise_error(Sequel::Error)
578
582
  proc{c.update_except({:x=>1}, :x)}.should raise_error(Sequel::Error)
579
583
  end
580
584
 
@@ -631,8 +635,6 @@ describe Sequel::Model, ".[] optimization" do
631
635
  it "should have simple_pk be blank if compound or no primary key" do
632
636
  @c.no_primary_key
633
637
  @c.simple_pk.should == nil
634
- @c.set_primary_key :b, :a
635
- @c.simple_pk.should == nil
636
638
  @c.set_primary_key [:b, :a]
637
639
  @c.simple_pk.should == nil
638
640
  end
@@ -701,6 +703,13 @@ describe "Model datasets #with_pk with #with_pk!" do
701
703
  MODEL_DB.reset
702
704
  end
703
705
 
706
+ it "should be callable on the model class with optimized SQL" do
707
+ @c.with_pk(1).should == @c.load(:id=>1)
708
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE id = 1"]
709
+ @c.with_pk!(1).should == @c.load(:id=>1)
710
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE id = 1"]
711
+ end
712
+
704
713
  it "should return the first record where the primary key matches" do
705
714
  @ds.with_pk(1).should == @c.load(:id=>1)
706
715
  MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
@@ -723,7 +732,7 @@ describe "Model datasets #with_pk with #with_pk!" do
723
732
  end
724
733
 
725
734
  it "should handle an array for composite primary keys" do
726
- @c.set_primary_key :id1, :id2
735
+ @c.set_primary_key [:id1, :id2]
727
736
  @ds.with_pk([1, 2])
728
737
  sqls = MODEL_DB.sqls
729
738
  ["SELECT * FROM a WHERE ((a.id1 = 1) AND (a.id2 = 2)) LIMIT 1",
@@ -745,6 +754,14 @@ describe "Model datasets #with_pk with #with_pk!" do
745
754
  MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
746
755
  end
747
756
 
757
+ it "should have with_pk return nil and with_pk! raise if no rows match when calling the class method" do
758
+ @ds._fetch = []
759
+ @c.with_pk(1).should == nil
760
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE id = 1"]
761
+ proc{@c.with_pk!(1)}.should raise_error(Sequel::NoMatchingRow)
762
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE id = 1"]
763
+ end
764
+
748
765
  it "should have #[] consider an integer as a primary key lookup" do
749
766
  @ds[1].should == @c.load(:id=>1)
750
767
  MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
@@ -0,0 +1,143 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe Sequel::Model, "class dataset methods" do
4
+ before do
5
+ @db = Sequel.mock
6
+ @c = Class.new(Sequel::Model(@db[:items]))
7
+ @d = @c.dataset
8
+ @d._fetch = {:id=>1}
9
+ @d.autoid = 1
10
+ @d.numrows = 0
11
+ @db.sqls
12
+ end
13
+
14
+ it "should call the dataset method of the same name with the same args" do
15
+ @c.<<({}).should == @d
16
+ @db.sqls.should == ["INSERT INTO items DEFAULT VALUES"]
17
+ @c.all.should == [@c.load(:id=>1)]
18
+ @db.sqls.should == ["SELECT * FROM items"]
19
+ @c.avg(:id).should == 1
20
+ @db.sqls.should == ["SELECT avg(id) AS avg FROM items LIMIT 1"]
21
+ @c.count.should == 1
22
+ @db.sqls.should == ["SELECT count(*) AS count FROM items LIMIT 1"]
23
+ @c.cross_join(@c).sql.should == "SELECT * FROM items CROSS JOIN items"
24
+ @c.distinct.sql.should == "SELECT DISTINCT * FROM items"
25
+ @c.each{|r| r.should == @c.load(:id=>1)}.should == @d
26
+ @db.sqls.should == ["SELECT * FROM items"]
27
+ @c.each_server{|r| r.opts[:server].should == :default}
28
+ @c.empty?.should be_false
29
+ @db.sqls.should == ["SELECT 1 AS one FROM items LIMIT 1"]
30
+ @c.except(@d, :from_self=>false).sql.should == "SELECT * FROM items EXCEPT SELECT * FROM items"
31
+ @c.exclude(:a).sql.should == "SELECT * FROM items WHERE NOT a"
32
+ @c.exclude_having(:a).sql.should == "SELECT * FROM items HAVING NOT a"
33
+ @c.exclude_where(:a).sql.should == "SELECT * FROM items WHERE NOT a"
34
+ @c.fetch_rows("S"){|r| r.should == {:id=>1}}
35
+ @db.sqls.should == ["S"]
36
+ @c.filter(:a).sql.should == "SELECT * FROM items WHERE a"
37
+ @c.first.should == @c.load(:id=>1)
38
+ @db.sqls.should == ["SELECT * FROM items LIMIT 1"]
39
+ @c.first!.should == @c.load(:id=>1)
40
+ @db.sqls.should == ["SELECT * FROM items LIMIT 1"]
41
+ @c.for_update.sql.should == "SELECT * FROM items FOR UPDATE"
42
+ @c.from.sql.should == "SELECT *"
43
+ @c.from_self.sql.should == "SELECT * FROM (SELECT * FROM items) AS t1"
44
+ @c.full_join(@c).sql.should == "SELECT * FROM items FULL JOIN items"
45
+ @c.full_outer_join(@c).sql.should == "SELECT * FROM items FULL OUTER JOIN items"
46
+ @c.get(:a).should == 1
47
+ @db.sqls.should == ["SELECT a FROM items LIMIT 1"]
48
+ @c.graph(@c, nil, :table_alias=>:a).sql.should == "SELECT * FROM items LEFT OUTER JOIN items AS a"
49
+ @db.sqls
50
+ @c.grep(:id, 'a%').sql.should == "SELECT * FROM items WHERE ((id LIKE 'a%' ESCAPE '\\'))"
51
+ @c.group(:a).sql.should == "SELECT * FROM items GROUP BY a"
52
+ @c.group_and_count(:a).sql.should == "SELECT a, count(*) AS count FROM items GROUP BY a"
53
+ @c.group_by(:a).sql.should == "SELECT * FROM items GROUP BY a"
54
+ @c.having(:a).sql.should == "SELECT * FROM items HAVING a"
55
+ @c.import([:id], [[1]])
56
+ @db.sqls.should == ["BEGIN", "INSERT INTO items (id) VALUES (1)", "COMMIT"]
57
+ @c.inner_join(@c).sql.should == "SELECT * FROM items INNER JOIN items"
58
+ @c.insert.should == 2
59
+ @db.sqls.should == ["INSERT INTO items DEFAULT VALUES"]
60
+ @c.intersect(@d, :from_self=>false).sql.should == "SELECT * FROM items INTERSECT SELECT * FROM items"
61
+ @c.interval(:id).should == 1
62
+ @db.sqls.should == ["SELECT (max(id) - min(id)) AS interval FROM items LIMIT 1"]
63
+ @c.join(@c).sql.should == "SELECT * FROM items INNER JOIN items"
64
+ @c.join_table(:inner, @c).sql.should == "SELECT * FROM items INNER JOIN items"
65
+ @c.last.should == @c.load(:id=>1)
66
+ @db.sqls.should == ["SELECT * FROM items ORDER BY id DESC LIMIT 1"]
67
+ @c.left_join(@c).sql.should == "SELECT * FROM items LEFT JOIN items"
68
+ @c.left_outer_join(@c).sql.should == "SELECT * FROM items LEFT OUTER JOIN items"
69
+ @c.limit(2).sql.should == "SELECT * FROM items LIMIT 2"
70
+ @c.lock_style(:update).sql.should == "SELECT * FROM items FOR UPDATE"
71
+ @c.map(:id).should == [1]
72
+ @db.sqls.should == ["SELECT * FROM items"]
73
+ @c.max(:id).should == 1
74
+ @db.sqls.should == ["SELECT max(id) AS max FROM items LIMIT 1"]
75
+ @c.min(:id).should == 1
76
+ @db.sqls.should == ["SELECT min(id) AS min FROM items LIMIT 1"]
77
+ @c.multi_insert([{:id=>1}])
78
+ @db.sqls.should == ["BEGIN", "INSERT INTO items (id) VALUES (1)", "COMMIT"]
79
+ @c.naked.row_proc.should == nil
80
+ @c.natural_full_join(@c).sql.should == "SELECT * FROM items NATURAL FULL JOIN items"
81
+ @c.natural_join(@c).sql.should == "SELECT * FROM items NATURAL JOIN items"
82
+ @c.natural_left_join(@c).sql.should == "SELECT * FROM items NATURAL LEFT JOIN items"
83
+ @c.natural_right_join(@c).sql.should == "SELECT * FROM items NATURAL RIGHT JOIN items"
84
+ @c.order(:a).sql.should == "SELECT * FROM items ORDER BY a"
85
+ @c.order_append(:a).sql.should == "SELECT * FROM items ORDER BY a"
86
+ @c.order_by(:a).sql.should == "SELECT * FROM items ORDER BY a"
87
+ @c.order_more(:a).sql.should == "SELECT * FROM items ORDER BY a"
88
+ @c.order_prepend(:a).sql.should == "SELECT * FROM items ORDER BY a"
89
+ @c.paged_each{|r| r.should == @c.load(:id=>1)}
90
+ @db.sqls.should == ["BEGIN", "SELECT * FROM items ORDER BY id LIMIT 1000 OFFSET 0", "COMMIT"]
91
+ @c.qualify.sql.should == 'SELECT items.* FROM items'
92
+ @c.right_join(@c).sql.should == "SELECT * FROM items RIGHT JOIN items"
93
+ @c.right_outer_join(@c).sql.should == "SELECT * FROM items RIGHT OUTER JOIN items"
94
+ @c.select(:a).sql.should == "SELECT a FROM items"
95
+ @c.select_all(:items).sql.should == "SELECT items.* FROM items"
96
+ @c.select_append(:a).sql.should == "SELECT *, a FROM items"
97
+ @c.select_group(:a).sql.should == "SELECT a FROM items GROUP BY a"
98
+ @c.select_hash(:id, :id).should == {1=>1}
99
+ @db.sqls.should == ["SELECT id, id FROM items"]
100
+ @c.select_hash_groups(:id, :id).should == {1=>[1]}
101
+ @db.sqls.should == ["SELECT id, id FROM items"]
102
+ @c.select_map(:id).should == [1]
103
+ @db.sqls.should == ["SELECT id FROM items"]
104
+ @c.select_order_map(:id).should == [1]
105
+ @db.sqls.should == ["SELECT id FROM items ORDER BY id"]
106
+ @c.server(:a).opts[:server].should == :a
107
+ @c.set_graph_aliases(:a=>:b).opts[:graph_aliases].should == {:a=>[:b, :a]}
108
+ @c.single_record.should == @c.load(:id=>1)
109
+ @db.sqls.should == ["SELECT * FROM items LIMIT 1"]
110
+ @c.single_value.should == 1
111
+ @db.sqls.should == ["SELECT * FROM items LIMIT 1"]
112
+ @c.sum(:id).should == 1
113
+ @db.sqls.should == ["SELECT sum(id) AS sum FROM items LIMIT 1"]
114
+ @c.to_hash(:id, :id).should == {1=>1}
115
+ @db.sqls.should == ["SELECT * FROM items"]
116
+ @c.to_hash_groups(:id, :id).should == {1=>[1]}
117
+ @db.sqls.should == ["SELECT * FROM items"]
118
+ @c.truncate
119
+ @db.sqls.should == ["TRUNCATE TABLE items"]
120
+ @c.union(@d, :from_self=>false).sql.should == "SELECT * FROM items UNION SELECT * FROM items"
121
+ @c.where(:a).sql.should == "SELECT * FROM items WHERE a"
122
+ @c.with(:a, @d).sql.should == "WITH a AS (SELECT * FROM items) SELECT * FROM items"
123
+ @c.with_recursive(:a, @d, @d).sql.should == "WITH a AS (SELECT * FROM items UNION ALL SELECT * FROM items) SELECT * FROM items"
124
+ @c.with_sql('S').sql.should == "S"
125
+
126
+ sc = Class.new(@c)
127
+ sc.set_dataset(@d.where(:a).order(:a).select(:a).group(:a).limit(2))
128
+ @db.sqls
129
+ sc.invert.sql.should == 'SELECT a FROM items WHERE NOT a GROUP BY a ORDER BY a LIMIT 2'
130
+ sc.dataset._fetch = {:v1=>1, :v2=>2}
131
+ sc.range(:a).should == (1..2)
132
+ @db.sqls.should == ["SELECT min(a) AS v1, max(a) AS v2 FROM (SELECT a FROM items WHERE a GROUP BY a ORDER BY a LIMIT 2) AS t1 LIMIT 1"]
133
+ sc.reverse.sql.should == 'SELECT a FROM items WHERE a GROUP BY a ORDER BY a DESC LIMIT 2'
134
+ sc.reverse_order.sql.should == 'SELECT a FROM items WHERE a GROUP BY a ORDER BY a DESC LIMIT 2'
135
+ sc.select_more(:a).sql.should == 'SELECT a, a FROM items WHERE a GROUP BY a ORDER BY a LIMIT 2'
136
+ sc.unfiltered.sql.should == 'SELECT a FROM items GROUP BY a ORDER BY a LIMIT 2'
137
+ sc.ungrouped.sql.should == 'SELECT a FROM items WHERE a ORDER BY a LIMIT 2'
138
+ sc.unordered.sql.should == 'SELECT a FROM items WHERE a GROUP BY a LIMIT 2'
139
+ sc.unlimited.sql.should == 'SELECT a FROM items WHERE a GROUP BY a ORDER BY a'
140
+ sc.dataset.graph!(:a)
141
+ sc.dataset.ungraphed.opts[:graph].should == nil
142
+ end
143
+ end
@@ -92,7 +92,7 @@ describe Sequel::Model::DatasetMethods do
92
92
  end
93
93
 
94
94
  specify "#insert_sql should handle a single model instance as an argument" do
95
- @c.insert_sql(@c.load(:id=>1)).should == 'INSERT INTO items (id) VALUES (1)'
95
+ @c.dataset.insert_sql(@c.load(:id=>1)).should == 'INSERT INTO items (id) VALUES (1)'
96
96
  end
97
97
 
98
98
  specify "#first should handle no primary key" do
@@ -7,7 +7,7 @@ describe Sequel::Model, "#eager" do
7
7
  many_to_one :band, :class=>'EagerBand', :key=>:band_id
8
8
  one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id
9
9
  many_to_many :genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag
10
- one_to_many :good_tracks, :class=>'EagerTrack', :key=>:album_id do |ds|
10
+ one_to_many :good_tracks, :class=>'EagerTrack', :reciprocal=>nil, :key=>:album_id do |ds|
11
11
  ds.filter(:name=>'Good')
12
12
  end
13
13
  many_to_one :band_name, :class=>'EagerBand', :key=>:band_id, :select=>[:id, :name]
@@ -21,11 +21,11 @@ describe Sequel::Model, "#eager" do
21
21
 
22
22
  class ::EagerBand < Sequel::Model(:bands)
23
23
  columns :id, :p_k
24
- one_to_many :albums, :class=>'EagerAlbum', :key=>:band_id, :eager=>:tracks
25
- one_to_many :graph_albums, :class=>'EagerAlbum', :key=>:band_id, :eager_graph=>:tracks
24
+ one_to_many :albums, :class=>'EagerAlbum', :key=>:band_id, :eager=>:tracks, :reciprocal=>:band
25
+ one_to_many :graph_albums, :class=>'EagerAlbum', :key=>:band_id, :eager_graph=>:tracks, :reciprocal=>nil
26
26
  many_to_many :members, :class=>'EagerBandMember', :left_key=>:band_id, :right_key=>:member_id, :join_table=>:bm
27
27
  many_to_many :graph_members, :clone=>:members, :eager_graph=>:bands
28
- one_to_many :good_albums, :class=>'EagerAlbum', :key=>:band_id, :eager_block=>proc{|ds| ds.filter(:name=>'good')} do |ds|
28
+ one_to_many :good_albums, :class=>'EagerAlbum', :key=>:band_id, :reciprocal=>nil, :eager_block=>proc{|ds| ds.filter(:name=>'good')} do |ds|
29
29
  ds.filter(:name=>'Good')
30
30
  end
31
31
  one_to_many :self_titled_albums, :class=>'EagerAlbum', :key=>:band_id, :allow_eager=>false do |ds|
@@ -169,7 +169,7 @@ describe Sequel::Model, "#eager" do
169
169
  MODEL_DB.sqls.should == []
170
170
  end
171
171
 
172
- it "should eagerly load a single one_to_one association using the :correlated_subquery strategy" do
172
+ qspecify "should eagerly load a single one_to_one association using the :correlated_subquery strategy" do
173
173
  EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>:name
174
174
  a = EagerAlbum.eager(:track).all
175
175
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
@@ -178,7 +178,7 @@ describe Sequel::Model, "#eager" do
178
178
  MODEL_DB.sqls.should == []
179
179
  end
180
180
 
181
- it "should handle qualified order clauses when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
181
+ qspecify "should handle qualified order clauses when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
182
182
  EagerAlbum.one_to_one :track, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>[:tracks__name, Sequel.desc(:tracks__name), Sequel.qualify(:tracks, :name), Sequel.qualify(:t, :name), 1]
183
183
  a = EagerAlbum.eager(:track).all
184
184
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
@@ -187,7 +187,7 @@ describe Sequel::Model, "#eager" do
187
187
  MODEL_DB.sqls.should == []
188
188
  end
189
189
 
190
- it "should handle qualified composite keys when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
190
+ qspecify "should handle qualified composite keys when eagerly loading a single one_to_one association using the :correlated_subquery strategy" do
191
191
  c1 = Class.new(EagerAlbum)
192
192
  c2 = Class.new(EagerTrack)
193
193
  c1.set_primary_key [:id, :band_id]
@@ -228,7 +228,7 @@ describe Sequel::Model, "#eager" do
228
228
  end
229
229
 
230
230
  it "should support using a custom :primary_key option when eager loading one_to_many associations" do
231
- EagerBand.one_to_many :salbums, :clone=>:albums, :primary_key=>:id3, :eager=>nil
231
+ EagerBand.one_to_many :salbums, :clone=>:albums, :primary_key=>:id3, :eager=>nil, :reciprocal=>nil
232
232
  EagerBand.dataset._fetch = {:id=>6}
233
233
  a = EagerBand.eager(:salbums).all
234
234
  MODEL_DB.sqls.should == ['SELECT * FROM bands', 'SELECT * FROM albums WHERE (albums.band_id IN (2))']
@@ -258,7 +258,7 @@ describe Sequel::Model, "#eager" do
258
258
  end
259
259
 
260
260
  it "should handle a :eager_loading_predicate_key option to change the SQL used in the lookup, for one_to_many associations" do
261
- EagerBand.one_to_many :salbums, :clone=>:albums, :eager_loading_predicate_key=>Sequel.*(:albums__band_id, 3), :key_method=>:band_id3, :eager=>nil
261
+ EagerBand.one_to_many :salbums, :clone=>:albums, :eager_loading_predicate_key=>Sequel.*(:albums__band_id, 3), :key_method=>:band_id3, :eager=>nil, :reciprocal=>nil
262
262
  EagerBand.dataset._fetch = {:id=>6}
263
263
  a = EagerBand.eager(:salbums).all
264
264
  MODEL_DB.sqls.should == ['SELECT * FROM bands', 'SELECT * FROM albums WHERE ((albums.band_id * 3) IN (6))']
@@ -501,7 +501,7 @@ describe Sequel::Model, "#eager" do
501
501
  as.length.should == 1
502
502
  as.first.special_band.should == EagerBand.load(:p_k=>2, :id=>1)
503
503
 
504
- EagerAlbum.one_to_many :special_tracks, :class=>:EagerTrack, :primary_key=>:band_id, :key=>:album_id
504
+ EagerAlbum.one_to_many :special_tracks, :class=>:EagerTrack, :primary_key=>:band_id, :key=>:album_id, :reciprocal=>nil
505
505
  EagerTrack.dataset._fetch = {:album_id=>2, :id=>1}
506
506
  as = EagerAlbum.eager(:special_tracks).all
507
507
  MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT * FROM tracks WHERE (tracks.album_id IN (2))"]
@@ -581,7 +581,7 @@ describe Sequel::Model, "#eager" do
581
581
  MODEL_DB.sqls.should == []
582
582
  end
583
583
 
584
- it "should respect the :limit option on a one_to_many association using the :correlated_subquery strategy" do
584
+ qspecify "should respect the :limit option on a one_to_many association using the :correlated_subquery strategy" do
585
585
  EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>:name, :limit=>2
586
586
  a = EagerAlbum.eager(:tracks).all
587
587
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
@@ -590,7 +590,7 @@ describe Sequel::Model, "#eager" do
590
590
  MODEL_DB.sqls.should == []
591
591
  end
592
592
 
593
- it "should respect the :limit option with an offset on a one_to_many association using the :correlated_subquery strategy" do
593
+ qspecify "should respect the :limit option with an offset on a one_to_many association using the :correlated_subquery strategy" do
594
594
  EagerAlbum.one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id, :eager_limit_strategy=>:correlated_subquery, :order=>:name, :limit=>[2, 1]
595
595
  a = EagerAlbum.eager(:tracks).all
596
596
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
@@ -632,7 +632,7 @@ describe Sequel::Model, "#eager" do
632
632
  as.first.first_two_genres.should == [EagerGenre.load(:id=>5), EagerGenre.load(:id=>6)]
633
633
  end
634
634
 
635
- it "should respect the limit option on a many_to_many association using the :correlated_subquery strategy" do
635
+ qspecify "should respect the limit option on a many_to_many association using the :correlated_subquery strategy" do
636
636
  EagerAlbum.many_to_many :first_two_genres, :class=>:EagerGenre, :left_primary_key=>:band_id, :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :eager_limit_strategy=>:correlated_subquery, :limit=>2, :order=>:name
637
637
  EagerGenre.dataset._fetch = [{:x_foreign_key_x=>2, :id=>5}, {:x_foreign_key_x=>2, :id=>6}]
638
638
  as = EagerAlbum.eager(:first_two_genres).all
@@ -649,17 +649,17 @@ describe Sequel::Model, "#eager" do
649
649
  end
650
650
 
651
651
  it "should use the :eager_loader association option when eager loading" do
652
- EagerAlbum.many_to_one :special_band, :key=>:band_id, :eager_loader=>(proc do |key_hash, records, assocs|
653
- item = EagerBand.filter(:album_id=>records.collect{|r| [r.pk, r.pk*2]}.flatten).order(:name).first
654
- records.each{|r| r.associations[:special_band] = item}
652
+ EagerAlbum.many_to_one :special_band, :key=>:band_id, :eager_loader=>(proc do |eo|
653
+ item = EagerBand.filter(:album_id=>eo[:rows].collect{|r| [r.pk, r.pk*2]}.flatten).order(:name).first
654
+ eo[:rows].each{|r| r.associations[:special_band] = item}
655
655
  end)
656
656
  EagerAlbum.one_to_many :special_tracks, :eager_loader=>(proc do |eo|
657
657
  items = EagerTrack.filter(:album_id=>eo[:rows].collect{|r| [r.pk, r.pk*2]}.flatten).all
658
658
  eo[:rows].each{|r| r.associations[:special_tracks] = items}
659
659
  end)
660
- EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :eager_loader=>(proc do |key_hash, records, assocs|
661
- items = EagerGenre.inner_join(:ag, [:genre_id]).filter(:album_id=>records.collect{|r| r.pk}).all
662
- records.each{|r| r.associations[:special_genres] = items}
660
+ EagerAlbum.many_to_many :special_genres, :class=>:EagerGenre, :eager_loader=>(proc do |eo|
661
+ items = EagerGenre.inner_join(:ag, [:genre_id]).filter(:album_id=>eo[:rows].collect{|r| r.pk}).all
662
+ eo[:rows].each{|r| r.associations[:special_genres] = items}
663
663
  end)
664
664
  a = EagerAlbum.eager(:special_genres, :special_tracks, :special_band).all
665
665
  a.should == [EagerAlbum.load(:id => 1, :band_id => 2)]
@@ -1166,7 +1166,7 @@ describe Sequel::Model, "#eager_graph" do
1166
1166
  as.should == [GraphAlbum.load(:id=>3, :band_id=>2)]
1167
1167
  as.first.inner_band.should == GraphBand.load(:id=>5, :vocalist_id=>2)
1168
1168
 
1169
- GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :primary_key=>:band_id
1169
+ GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :primary_key=>:band_id, :reciprocal=>nil
1170
1170
  ds = GraphAlbum.eager_graph(:right_tracks)
1171
1171
  ds.sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON (right_tracks.album_id = albums.band_id)'
1172
1172
  ds._fetch = [{:id=>3, :band_id=>2, :right_tracks_id=>5, :album_id=>2}, {:id=>3, :band_id=>2, :right_tracks_id=>6, :album_id=>2}]
@@ -1276,7 +1276,7 @@ describe Sequel::Model, "#eager_graph" do
1276
1276
  GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :conditions=>{:active=>true}
1277
1277
  GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands AS active_band ON ((active_band.id = albums.band_id) AND (active_band.active IS TRUE))"
1278
1278
 
1279
- GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :conditions=>{:id=>(0..100)}
1279
+ GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :conditions=>{:id=>(0..100)}, :reciprocal=>nil
1280
1280
  GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums LEFT OUTER JOIN tracks AS right_tracks ON ((right_tracks.album_id = albums.id) AND (right_tracks.id >= 0) AND (right_tracks.id <= 100))'
1281
1281
 
1282
1282
  GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :conditions=>{true=>:active}
@@ -1322,13 +1322,13 @@ describe Sequel::Model, "#eager_graph" do
1322
1322
  end
1323
1323
 
1324
1324
  it "should respect the association's :eager_grapher option" do
1325
- GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :eager_grapher=>proc{|ds, aa, ta| ds.graph(GraphBand, {:active=>true}, :table_alias=>aa, :join_type=>:inner)}
1325
+ GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :eager_grapher=>proc{|eo| eo[:self].graph(GraphBand, {:active=>true}, :table_alias=>eo[:table_alias], :join_type=>:inner)}
1326
1326
  GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums INNER JOIN bands AS active_band ON (active_band.active IS TRUE)"
1327
1327
 
1328
1328
  GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :eager_grapher=>proc{|eo| eo[:self].graph(GraphTrack, nil, :join_type=>:natural, :table_alias=>eo[:table_alias])}
1329
1329
  GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums NATURAL JOIN tracks AS right_tracks'
1330
1330
 
1331
- GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :eager_grapher=>proc{|ds, aa, ta| ds.graph(:ag, {:album_id=>:id}, :table_alias=>:a123, :implicit_qualifier=>ta).graph(GraphGenre, [:album_id], :table_alias=>aa)}
1331
+ GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :eager_grapher=>proc{|eo| eo[:self].graph(:ag, {:album_id=>:id}, :table_alias=>:a123, :implicit_qualifier=>eo[:implicit_qualifier]).graph(GraphGenre, [:album_id], :table_alias=>eo[:table_alias])}
1332
1332
  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 AS a123 ON (a123.album_id = albums.id) LEFT OUTER JOIN genres AS active_genres USING (album_id)"
1333
1333
  end
1334
1334
 
@@ -1380,7 +1380,7 @@ describe Sequel::Model, "#eager_graph" do
1380
1380
  end
1381
1381
 
1382
1382
  it "should add the association's :order for cascading associations" do
1383
- GraphBand.one_to_many :a_albums, :class=>'GraphAlbum', :key=>:band_id, :order=>:name
1383
+ GraphBand.one_to_many :a_albums, :class=>'GraphAlbum', :key=>:band_id, :order=>:name, :reciprocal=>nil
1384
1384
  GraphAlbum.one_to_many :b_tracks, :class=>'GraphTrack', :key=>:album_id, :order=>[:id, :album_id]
1385
1385
  GraphBand.eager_graph(:a_albums=>:b_tracks).sql.should == 'SELECT bands.id, bands.vocalist_id, a_albums.id AS a_albums_id, a_albums.band_id, b_tracks.id AS b_tracks_id, b_tracks.album_id FROM bands LEFT OUTER JOIN albums AS a_albums ON (a_albums.band_id = bands.id) LEFT OUTER JOIN tracks AS b_tracks ON (b_tracks.album_id = a_albums.id) ORDER BY a_albums.name, b_tracks.id, b_tracks.album_id'
1386
1386
  GraphAlbum.one_to_many :albums, :class=>'GraphAlbum', :key=>:band_id, :order=>[:band_id, :id]
@@ -1417,7 +1417,7 @@ describe Sequel::Model, "#eager_graph" do
1417
1417
  GraphAlbum.eager_graph(:band).join(:s__genres, [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1418
1418
  GraphAlbum.eager_graph(:band).join(Sequel.qualify(:s, :genres), [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1419
1419
  GraphAlbum.eager_graph(:band).join(Sequel.expr(:s__b).as('genres'), [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.b AS genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1420
- GraphAlbum.eager_graph(:band).join(:s__b, [:b_id], Sequel.identifier(:genres)).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.b AS genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1420
+ GraphAlbum.eager_graph(:band).join(:s__b, [:b_id], :table_alias=>Sequel.identifier(:genres)).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN s.b AS genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1421
1421
  GraphAlbum.eager_graph(:band).join(Sequel.identifier(:genres), [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1422
1422
  GraphAlbum.eager_graph(:band).join('genres', [:b_id]).eager_graph(:genres).sql.should == 'SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, genres_0.id AS genres_0_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) INNER JOIN genres USING (b_id) LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres AS genres_0 ON (genres_0.id = ag.genre_id)'
1423
1423
  end
@@ -1,7 +1,7 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Model#after_initialize" do
4
- specify "should be called after initialization for both new object and objects retrieved from the database" do
4
+ qspecify "should be called after initialization for both new object and objects retrieved from the database" do
5
5
 
6
6
  a = Class.new(Sequel::Model) do
7
7
  self::Foo = []
@@ -55,7 +55,7 @@ describe "Sequel::Model()" do
55
55
  end
56
56
 
57
57
  it "should return a model subclass associated to the given database if given a database" do
58
- db = Sequel::Database.new
58
+ db = Sequel.mock
59
59
  c = Sequel::Model(db)
60
60
  c.superclass.should == Sequel::Model
61
61
  c.db.should == db
@@ -68,10 +68,10 @@ describe "Sequel::Model()" do
68
68
 
69
69
  describe "reloading" do
70
70
  before do
71
- Sequel::Model.cache_anonymous_models = true
71
+ Sequel.cache_anonymous_models = true
72
72
  end
73
73
  after do
74
- Sequel::Model.cache_anonymous_models = false
74
+ Sequel.cache_anonymous_models = false
75
75
  Object.send(:remove_const, :Album) if defined?(::Album)
76
76
  end
77
77
 
@@ -132,7 +132,7 @@ describe "Sequel::Model()" do
132
132
  end
133
133
 
134
134
  it "should raise an exception if anonymous model caching is disabled" do
135
- Sequel::Model.cache_anonymous_models = false
135
+ Sequel.cache_anonymous_models = false
136
136
  proc do
137
137
  class ::Album < Sequel::Model(@db[Sequel.identifier(:table)]); end
138
138
  class ::Album < Sequel::Model(@db[Sequel.identifier(:table)]); end
@@ -308,7 +308,7 @@ describe Sequel::Model, "constructors" do
308
308
  end
309
309
 
310
310
  it "should have dataset row_proc create an existing object" do
311
- @m.dataset = Sequel::Dataset.new(nil)
311
+ @m.dataset = Sequel.mock.dataset
312
312
  o = @m.dataset.row_proc.call(:a=>1)
313
313
  o.should be_a_kind_of(@m)
314
314
  o.values.should == {:a=>1}
@@ -329,7 +329,7 @@ describe Sequel::Model, "constructors" do
329
329
  o.new?.should be_false
330
330
  end
331
331
 
332
- it "should have .new with a second true argument create an existing object" do
332
+ qspecify "should have .new with a second true argument create an existing object" do
333
333
  o = @m.new({:a=>1}, true)
334
334
  o.should be_a_kind_of(@m)
335
335
  o.values.should == {:a=>1}
@@ -520,6 +520,7 @@ end
520
520
  describe Sequel::Model, "attribute accessors" do
521
521
  before do
522
522
  db = Sequel.mock
523
+ def db.supports_schema_parsing?() true end
523
524
  def db.schema(*)
524
525
  [[:x, {:type=>:integer}], [:z, {:type=>:integer}]]
525
526
  end
@@ -616,7 +617,7 @@ describe Sequel::Model, ".[]" do
616
617
  sqls.first.should =~ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
617
618
  end
618
619
 
619
- it "should work correctly for composite primary key specified as separate arguments" do
620
+ qspecify "should work correctly for composite primary key specified as separate arguments" do
620
621
  @c.set_primary_key :node_id, :kind
621
622
  @c[3921, 201].should be_a_kind_of(@c)
622
623
  sqls = MODEL_DB.sqls
@@ -637,9 +638,23 @@ describe "Model.db_schema" do
637
638
  def self.columns; orig_columns; end
638
639
  end
639
640
  @db = Sequel.mock
641
+ def @db.supports_schema_parsing?() true end
640
642
  @dataset = @db[:items]
641
643
  end
642
644
 
645
+ specify "should not call database's schema if it isn't supported" do
646
+ def @db.supports_schema_parsing?() false end
647
+ def @db.schema(table, opts = {})
648
+ raise Sequel::Error
649
+ end
650
+ @dataset.instance_variable_set(:@columns, [:x, :y])
651
+
652
+ @c.dataset = @dataset
653
+ @c.db_schema.should == {:x=>{}, :y=>{}}
654
+ @c.columns.should == [:x, :y]
655
+ @c.dataset.instance_variable_get(:@columns).should == [:x, :y]
656
+ end
657
+
643
658
  specify "should use the database's schema and set the columns and dataset columns" do
644
659
  def @db.schema(table, opts = {})
645
660
  [[:x, {:type=>:integer}], [:y, {:type=>:string}]]