sequel 3.21.0 → 3.36.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.
Files changed (311) hide show
  1. data/CHANGELOG +855 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +23 -7
  4. data/Rakefile +42 -24
  5. data/bin/sequel +26 -8
  6. data/doc/active_record.rdoc +1 -0
  7. data/doc/advanced_associations.rdoc +171 -11
  8. data/doc/association_basics.rdoc +293 -43
  9. data/doc/dataset_basics.rdoc +5 -5
  10. data/doc/dataset_filtering.rdoc +8 -0
  11. data/doc/mass_assignment.rdoc +56 -0
  12. data/doc/migration.rdoc +85 -552
  13. data/doc/model_hooks.rdoc +78 -27
  14. data/doc/object_model.rdoc +541 -0
  15. data/doc/opening_databases.rdoc +97 -50
  16. data/doc/prepared_statements.rdoc +40 -14
  17. data/doc/querying.rdoc +28 -4
  18. data/doc/reflection.rdoc +30 -4
  19. data/doc/release_notes/3.22.0.txt +39 -0
  20. data/doc/release_notes/3.23.0.txt +172 -0
  21. data/doc/release_notes/3.24.0.txt +420 -0
  22. data/doc/release_notes/3.25.0.txt +88 -0
  23. data/doc/release_notes/3.26.0.txt +88 -0
  24. data/doc/release_notes/3.27.0.txt +82 -0
  25. data/doc/release_notes/3.28.0.txt +304 -0
  26. data/doc/release_notes/3.29.0.txt +459 -0
  27. data/doc/release_notes/3.30.0.txt +135 -0
  28. data/doc/release_notes/3.31.0.txt +146 -0
  29. data/doc/release_notes/3.32.0.txt +202 -0
  30. data/doc/release_notes/3.33.0.txt +157 -0
  31. data/doc/release_notes/3.34.0.txt +671 -0
  32. data/doc/release_notes/3.35.0.txt +144 -0
  33. data/doc/release_notes/3.36.0.txt +245 -0
  34. data/doc/schema_modification.rdoc +572 -0
  35. data/doc/sharding.rdoc +95 -3
  36. data/doc/testing.rdoc +129 -0
  37. data/doc/thread_safety.rdoc +17 -0
  38. data/doc/transactions.rdoc +137 -0
  39. data/doc/virtual_rows.rdoc +51 -2
  40. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  41. data/lib/sequel/adapters/ado.rb +40 -18
  42. data/lib/sequel/adapters/amalgalite.rb +17 -9
  43. data/lib/sequel/adapters/db2.rb +175 -86
  44. data/lib/sequel/adapters/dbi.rb +15 -15
  45. data/lib/sequel/adapters/do/mysql.rb +17 -11
  46. data/lib/sequel/adapters/do/postgres.rb +1 -57
  47. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  48. data/lib/sequel/adapters/do.rb +18 -36
  49. data/lib/sequel/adapters/firebird.rb +27 -208
  50. data/lib/sequel/adapters/ibmdb.rb +453 -0
  51. data/lib/sequel/adapters/informix.rb +6 -23
  52. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  53. data/lib/sequel/adapters/jdbc/db2.rb +47 -0
  54. data/lib/sequel/adapters/jdbc/derby.rb +287 -0
  55. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  56. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  57. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  58. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  59. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  61. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  62. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
  64. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  65. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  66. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  67. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  68. data/lib/sequel/adapters/jdbc.rb +265 -94
  69. data/lib/sequel/adapters/mock.rb +361 -0
  70. data/lib/sequel/adapters/mysql.rb +118 -222
  71. data/lib/sequel/adapters/mysql2.rb +58 -57
  72. data/lib/sequel/adapters/odbc/mssql.rb +15 -7
  73. data/lib/sequel/adapters/odbc.rb +28 -9
  74. data/lib/sequel/adapters/openbase.rb +3 -5
  75. data/lib/sequel/adapters/oracle.rb +349 -53
  76. data/lib/sequel/adapters/postgres.rb +356 -107
  77. data/lib/sequel/adapters/shared/access.rb +32 -9
  78. data/lib/sequel/adapters/shared/db2.rb +342 -0
  79. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  80. data/lib/sequel/adapters/shared/informix.rb +53 -0
  81. data/lib/sequel/adapters/shared/mssql.rb +335 -118
  82. data/lib/sequel/adapters/shared/mysql.rb +340 -76
  83. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  84. data/lib/sequel/adapters/shared/oracle.rb +243 -45
  85. data/lib/sequel/adapters/shared/postgres.rb +524 -279
  86. data/lib/sequel/adapters/shared/progress.rb +5 -8
  87. data/lib/sequel/adapters/shared/sqlite.rb +265 -89
  88. data/lib/sequel/adapters/sqlite.rb +101 -39
  89. data/lib/sequel/adapters/swift/mysql.rb +9 -12
  90. data/lib/sequel/adapters/swift/postgres.rb +9 -74
  91. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  92. data/lib/sequel/adapters/swift.rb +8 -7
  93. data/lib/sequel/adapters/tinytds.rb +161 -21
  94. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  95. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  96. data/lib/sequel/ast_transformer.rb +194 -0
  97. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  98. data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
  99. data/lib/sequel/connection_pool/single.rb +5 -0
  100. data/lib/sequel/connection_pool/threaded.rb +38 -14
  101. data/lib/sequel/connection_pool.rb +10 -2
  102. data/lib/sequel/core.rb +118 -11
  103. data/lib/sequel/database/connecting.rb +38 -28
  104. data/lib/sequel/database/dataset.rb +4 -4
  105. data/lib/sequel/database/dataset_defaults.rb +63 -2
  106. data/lib/sequel/database/logging.rb +7 -2
  107. data/lib/sequel/database/misc.rb +150 -46
  108. data/lib/sequel/database/query.rb +215 -65
  109. data/lib/sequel/database/schema_generator.rb +64 -20
  110. data/lib/sequel/database/schema_methods.rb +212 -54
  111. data/lib/sequel/dataset/actions.rb +322 -85
  112. data/lib/sequel/dataset/features.rb +96 -8
  113. data/lib/sequel/dataset/graph.rb +38 -11
  114. data/lib/sequel/dataset/misc.rb +50 -23
  115. data/lib/sequel/dataset/mutation.rb +12 -7
  116. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  117. data/lib/sequel/dataset/query.rb +237 -44
  118. data/lib/sequel/dataset/sql.rb +698 -278
  119. data/lib/sequel/dataset.rb +8 -0
  120. data/lib/sequel/exceptions.rb +4 -0
  121. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  122. data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
  123. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  124. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
  125. data/lib/sequel/extensions/migration.rb +97 -11
  126. data/lib/sequel/extensions/named_timezones.rb +5 -0
  127. data/lib/sequel/extensions/null_dataset.rb +90 -0
  128. data/lib/sequel/extensions/pg_array.rb +460 -0
  129. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  130. data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
  131. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  132. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  133. data/lib/sequel/extensions/pg_inet.rb +89 -0
  134. data/lib/sequel/extensions/pg_json.rb +178 -0
  135. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  136. data/lib/sequel/extensions/pretty_table.rb +5 -71
  137. data/lib/sequel/extensions/query.rb +1 -1
  138. data/lib/sequel/extensions/query_literals.rb +79 -0
  139. data/lib/sequel/extensions/schema_caching.rb +76 -0
  140. data/lib/sequel/extensions/schema_dumper.rb +251 -37
  141. data/lib/sequel/extensions/select_remove.rb +35 -0
  142. data/lib/sequel/extensions/server_block.rb +139 -0
  143. data/lib/sequel/extensions/sql_expr.rb +4 -110
  144. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  145. data/lib/sequel/extensions/to_dot.rb +95 -83
  146. data/lib/sequel/model/associations.rb +1187 -393
  147. data/lib/sequel/model/base.rb +578 -170
  148. data/lib/sequel/model/errors.rb +1 -1
  149. data/lib/sequel/model/exceptions.rb +5 -1
  150. data/lib/sequel/model/inflections.rb +1 -1
  151. data/lib/sequel/model.rb +30 -11
  152. data/lib/sequel/no_core_ext.rb +2 -0
  153. data/lib/sequel/plugins/active_model.rb +13 -1
  154. data/lib/sequel/plugins/association_pks.rb +22 -4
  155. data/lib/sequel/plugins/caching.rb +25 -18
  156. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  157. data/lib/sequel/plugins/composition.rb +44 -12
  158. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  159. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  160. data/lib/sequel/plugins/dirty.rb +214 -0
  161. data/lib/sequel/plugins/eager_each.rb +59 -0
  162. data/lib/sequel/plugins/force_encoding.rb +6 -6
  163. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  164. data/lib/sequel/plugins/identity_map.rb +123 -8
  165. data/lib/sequel/plugins/instance_filters.rb +10 -0
  166. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  167. data/lib/sequel/plugins/json_serializer.rb +58 -6
  168. data/lib/sequel/plugins/list.rb +12 -2
  169. data/lib/sequel/plugins/many_through_many.rb +79 -28
  170. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  171. data/lib/sequel/plugins/nested_attributes.rb +139 -63
  172. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  173. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  174. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  175. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  176. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  177. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  178. data/lib/sequel/plugins/schema.rb +7 -2
  179. data/lib/sequel/plugins/serialization.rb +98 -49
  180. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  181. data/lib/sequel/plugins/sharding.rb +21 -54
  182. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  183. data/lib/sequel/plugins/static_cache.rb +99 -0
  184. data/lib/sequel/plugins/subclasses.rb +10 -2
  185. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  186. data/lib/sequel/plugins/timestamps.rb +1 -1
  187. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  188. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  189. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  190. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  191. data/lib/sequel/sql.rb +526 -59
  192. data/lib/sequel/timezones.rb +57 -38
  193. data/lib/sequel/version.rb +1 -1
  194. data/spec/adapters/db2_spec.rb +146 -0
  195. data/spec/adapters/firebird_spec.rb +1 -1
  196. data/spec/adapters/mssql_spec.rb +142 -40
  197. data/spec/adapters/mysql_spec.rb +380 -234
  198. data/spec/adapters/oracle_spec.rb +67 -77
  199. data/spec/adapters/postgres_spec.rb +1050 -212
  200. data/spec/adapters/spec_helper.rb +8 -5
  201. data/spec/adapters/sqlite_spec.rb +139 -27
  202. data/spec/core/connection_pool_spec.rb +196 -93
  203. data/spec/core/database_spec.rb +879 -510
  204. data/spec/core/dataset_spec.rb +1415 -1086
  205. data/spec/core/expression_filters_spec.rb +554 -109
  206. data/spec/core/mock_adapter_spec.rb +449 -0
  207. data/spec/core/object_graph_spec.rb +86 -114
  208. data/spec/core/schema_generator_spec.rb +4 -4
  209. data/spec/core/schema_spec.rb +482 -38
  210. data/spec/core/spec_helper.rb +6 -48
  211. data/spec/extensions/active_model_spec.rb +13 -0
  212. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  213. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  214. data/spec/extensions/association_dependencies_spec.rb +15 -25
  215. data/spec/extensions/association_pks_spec.rb +66 -32
  216. data/spec/extensions/association_proxies_spec.rb +4 -4
  217. data/spec/extensions/caching_spec.rb +47 -51
  218. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  219. data/spec/extensions/columns_introspection_spec.rb +91 -0
  220. data/spec/extensions/composition_spec.rb +18 -13
  221. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
  222. data/spec/extensions/dataset_associations_spec.rb +199 -0
  223. data/spec/extensions/defaults_setter_spec.rb +64 -0
  224. data/spec/extensions/dirty_spec.rb +155 -0
  225. data/spec/extensions/eager_each_spec.rb +34 -0
  226. data/spec/extensions/force_encoding_spec.rb +4 -2
  227. data/spec/extensions/hook_class_methods_spec.rb +69 -92
  228. data/spec/extensions/identity_map_spec.rb +131 -22
  229. data/spec/extensions/inflector_spec.rb +0 -4
  230. data/spec/extensions/instance_filters_spec.rb +11 -21
  231. data/spec/extensions/instance_hooks_spec.rb +72 -0
  232. data/spec/extensions/json_serializer_spec.rb +49 -6
  233. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  234. data/spec/extensions/list_spec.rb +48 -39
  235. data/spec/extensions/many_through_many_spec.rb +283 -250
  236. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  237. data/spec/extensions/migration_spec.rb +140 -35
  238. data/spec/extensions/named_timezones_spec.rb +29 -11
  239. data/spec/extensions/nested_attributes_spec.rb +251 -89
  240. data/spec/extensions/null_dataset_spec.rb +85 -0
  241. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  242. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  243. data/spec/extensions/pg_array_spec.rb +196 -0
  244. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  245. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  246. data/spec/extensions/pg_hstore_spec.rb +195 -0
  247. data/spec/extensions/pg_inet_spec.rb +44 -0
  248. data/spec/extensions/pg_json_spec.rb +101 -0
  249. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  250. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  251. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  252. data/spec/extensions/prepared_statements_spec.rb +87 -0
  253. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  254. data/spec/extensions/pretty_table_spec.rb +7 -6
  255. data/spec/extensions/query_literals_spec.rb +168 -0
  256. data/spec/extensions/query_spec.rb +6 -0
  257. data/spec/extensions/rcte_tree_spec.rb +50 -43
  258. data/spec/extensions/schema_caching_spec.rb +41 -0
  259. data/spec/extensions/schema_dumper_spec.rb +429 -22
  260. data/spec/extensions/schema_spec.rb +25 -21
  261. data/spec/extensions/select_remove_spec.rb +38 -0
  262. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  263. data/spec/extensions/serialization_spec.rb +85 -43
  264. data/spec/extensions/server_block_spec.rb +90 -0
  265. data/spec/extensions/sharding_spec.rb +69 -143
  266. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  267. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  268. data/spec/extensions/spec_helper.rb +22 -61
  269. data/spec/extensions/sql_expr_spec.rb +29 -60
  270. data/spec/extensions/static_cache_spec.rb +145 -0
  271. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  272. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  273. data/spec/extensions/timestamps_spec.rb +6 -6
  274. data/spec/extensions/to_dot_spec.rb +4 -7
  275. data/spec/extensions/touch_spec.rb +13 -14
  276. data/spec/extensions/tree_spec.rb +11 -26
  277. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  278. data/spec/extensions/update_primary_key_spec.rb +30 -24
  279. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  280. data/spec/extensions/validation_helpers_spec.rb +16 -35
  281. data/spec/extensions/xml_serializer_spec.rb +29 -4
  282. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  283. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  284. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  285. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  286. data/spec/integration/associations_test.rb +659 -21
  287. data/spec/integration/database_test.rb +9 -3
  288. data/spec/integration/dataset_test.rb +605 -91
  289. data/spec/integration/eager_loader_test.rb +19 -21
  290. data/spec/integration/migrator_test.rb +2 -3
  291. data/spec/integration/model_test.rb +81 -2
  292. data/spec/integration/plugin_test.rb +454 -143
  293. data/spec/integration/prepared_statement_test.rb +263 -128
  294. data/spec/integration/schema_test.rb +309 -43
  295. data/spec/integration/spec_helper.rb +40 -30
  296. data/spec/integration/timezone_test.rb +38 -12
  297. data/spec/integration/transaction_test.rb +183 -8
  298. data/spec/integration/type_test.rb +18 -4
  299. data/spec/model/association_reflection_spec.rb +201 -7
  300. data/spec/model/associations_spec.rb +1067 -661
  301. data/spec/model/base_spec.rb +329 -95
  302. data/spec/model/dataset_methods_spec.rb +7 -27
  303. data/spec/model/eager_loading_spec.rb +677 -676
  304. data/spec/model/hooks_spec.rb +349 -67
  305. data/spec/model/model_spec.rb +240 -168
  306. data/spec/model/plugins_spec.rb +24 -13
  307. data/spec/model/record_spec.rb +490 -232
  308. data/spec/model/spec_helper.rb +14 -71
  309. data/spec/model/validations_spec.rb +11 -0
  310. data/spec/rcov.opts +2 -0
  311. metadata +178 -80
@@ -1,15 +1,17 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  describe "Sequel timezone support" do
4
- def test_timezone
4
+ def test_timezone(timezone=Sequel.application_timezone)
5
+ tz = timezone
6
+ Sequel.datetime_class = Time
5
7
  # Tests should cover both DST and non-DST times.
6
8
  [Time.now, Time.local(2010,1,1,12), Time.local(2010,6,1,12)].each do |t|
7
9
  @db[:t].insert(t)
8
10
  t2 = @db[:t].single_value
9
- t2 = Sequel.database_to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
11
+ t2 = @db.to_application_timestamp(t2.to_s) unless t2.is_a?(Time)
10
12
  (t2 - t).should be_within(2).of(0)
11
- t2.utc_offset.should == 0 if Sequel.application_timezone == :utc
12
- t2.utc_offset.should == t.getlocal.utc_offset if Sequel.application_timezone == :local
13
+ t2.utc_offset.should == 0 if timezone == :utc
14
+ t2.utc_offset.should == t.getlocal.utc_offset if timezone == :local
13
15
  @db[:t].delete
14
16
  end
15
17
 
@@ -19,10 +21,10 @@ describe "Sequel timezone support" do
19
21
  [DateTime.now, DateTime.civil(2010,1,1,12,0,0,local_std_offset), DateTime.civil(2010,6,1,12,0,0,local_dst_offset)].each do |dt|
20
22
  @db[:t].insert(dt)
21
23
  dt2 = @db[:t].single_value
22
- dt2 = Sequel.database_to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
24
+ dt2 = @db.to_application_timestamp(dt2.to_s) unless dt2.is_a?(DateTime)
23
25
  (dt2 - dt).should be_within(0.00002).of(0)
24
- dt2.offset.should == 0 if Sequel.application_timezone == :utc
25
- dt2.offset.should == dt.offset if Sequel.application_timezone == :local
26
+ dt2.offset.should == 0 if timezone == :utc
27
+ dt2.offset.should == dt.offset if timezone == :local
26
28
  @db[:t].delete
27
29
  end
28
30
  end
@@ -32,30 +34,54 @@ describe "Sequel timezone support" do
32
34
  @db.create_table!(:t){DateTime :t}
33
35
  end
34
36
  after do
35
- @db.drop_table(:t)
37
+ @db.timezone = nil
36
38
  Sequel.default_timezone = nil
37
39
  Sequel.datetime_class = Time
40
+ @db.drop_table(:t)
38
41
  end
39
42
 
40
- cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do, proc{|db| db.database_type != :sqlite}] do
43
+ cspecify "should support using UTC for database storage and local time for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
41
44
  Sequel.database_timezone = :utc
42
45
  Sequel.application_timezone = :local
43
46
  test_timezone
47
+ Sequel.database_timezone = nil
48
+ @db.timezone = :utc
49
+ test_timezone
44
50
  end
45
51
 
46
- cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do, proc{|db| db.database_type != :sqlite}] do
52
+ cspecify "should support using local time for database storage and UTC for the application", [:swift], [:tinytds], [:do, :mysql], [:do, :postgres], [:oracle] do
47
53
  Sequel.database_timezone = :local
48
54
  Sequel.application_timezone = :utc
49
55
  test_timezone
56
+ Sequel.database_timezone = nil
57
+ @db.timezone = :local
58
+ test_timezone
50
59
  end
51
60
 
52
- cspecify "should support using UTC for both database storage and for application", [:swift], [:do, proc{|db| db.database_type != :sqlite}] do
61
+ cspecify "should support using UTC for both database storage and for application", [:swift], [:do, :mysql], [:do, :postgres], [:oracle] do
53
62
  Sequel.default_timezone = :utc
54
63
  test_timezone
64
+ Sequel.database_timezone = :local
65
+ @db.timezone = :utc
66
+ test_timezone
55
67
  end
56
68
 
57
- cspecify "should support using local time for both database storage and for application", [:do, proc{|db| db.database_type != :sqlite}] do
69
+ cspecify "should support using local time for both database storage and for application", [:do, :mysql], [:do, :postgres], [:oracle], [:swift, :postgres], [:swift, :mysql] do
58
70
  Sequel.default_timezone = :local
59
71
  test_timezone
72
+ Sequel.database_timezone = :utc
73
+ @db.timezone = :local
74
+ test_timezone
75
+ end
76
+
77
+ specify "should allow overriding the database_timezone on a per-database basis" do
78
+ Sequel.database_timezone = :utc
79
+ @db.timezone = :local
80
+ t = Time.now
81
+ @db[:t].insert(t)
82
+ s = @db[:t].get(:t.cast(String))
83
+ if o = Date._parse(s)[:offset]
84
+ o.should == t.utc_offset
85
+ end
60
86
  end
61
87
  end
@@ -1,15 +1,16 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  describe "Database transactions" do
4
- before do
4
+ before(:all) do
5
5
  @db = INTEGRATION_DB
6
- @db.drop_table(:items) if @db.table_exists?(:items)
7
- @db.create_table(:items, :engine=>'InnoDB'){String :name; Integer :value}
6
+ @db.create_table!(:items, :engine=>'InnoDB'){String :name; Integer :value}
8
7
  @d = @db[:items]
9
- clear_sqls
10
8
  end
11
- after do
12
- @db.drop_table(:items) if @db.table_exists?(:items)
9
+ before do
10
+ @d.delete
11
+ end
12
+ after(:all) do
13
+ @db.drop_table?(:items)
13
14
  end
14
15
 
15
16
  specify "should support transactions" do
@@ -21,6 +22,13 @@ describe "Database transactions" do
21
22
  @db.transaction{|conn| conn.should_not == nil}
22
23
  end
23
24
 
25
+ specify "should have #in_transaction? work correctly" do
26
+ @db.in_transaction?.should be_false
27
+ c = nil
28
+ @db.transaction{c = @db.in_transaction?}
29
+ c.should be_true
30
+ end
31
+
24
32
  specify "should correctly rollback transactions" do
25
33
  proc do
26
34
  @db.transaction do
@@ -29,12 +37,22 @@ describe "Database transactions" do
29
37
  end
30
38
  end.should raise_error(Interrupt)
31
39
 
40
+ @db.transaction do
41
+ @d << {:name => 'abc', :value => 1}
42
+ raise Sequel::Rollback
43
+ end.should be_nil
44
+
32
45
  proc do
33
- @db.transaction do
46
+ @db.transaction(:rollback=>:reraise) do
34
47
  @d << {:name => 'abc', :value => 1}
35
48
  raise Sequel::Rollback
36
49
  end
37
- end.should_not raise_error
50
+ end.should raise_error(Sequel::Rollback)
51
+
52
+ @db.transaction(:rollback=>:always) do
53
+ @d << {:name => 'abc', :value => 1}
54
+ 2
55
+ end.should be_nil
38
56
 
39
57
  @d.count.should == 0
40
58
  end
@@ -115,6 +133,16 @@ describe "Database transactions" do
115
133
  end
116
134
 
117
135
  if INTEGRATION_DB.supports_prepared_transactions?
136
+ specify "should allow saving and destroying of model objects" do
137
+ c = Class.new(Sequel::Model(@d))
138
+ c.set_primary_key :name
139
+ c.unrestrict_primary_key
140
+ c.use_after_commit_rollback = false
141
+ @db.transaction(:prepare=>'XYZ'){c.create(:name => '1'); c.create(:name => '2').destroy}
142
+ @db.commit_prepared_transaction('XYZ')
143
+ @d.select_order_map(:name).should == ['1']
144
+ end
145
+
118
146
  specify "should commit prepared transactions using commit_prepared_transaction" do
119
147
  @db.transaction(:prepare=>'XYZ'){@d << {:name => '1'}}
120
148
  @db.commit_prepared_transaction('XYZ')
@@ -126,6 +154,14 @@ describe "Database transactions" do
126
154
  @db.rollback_prepared_transaction('XYZ')
127
155
  @d.select_order_map(:name).should == []
128
156
  end
157
+
158
+ if INTEGRATION_DB.supports_savepoints_in_prepared_transactions?
159
+ specify "should support savepoints when using prepared transactions" do
160
+ @db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@d << {:name => '1'}}}
161
+ @db.commit_prepared_transaction('XYZ')
162
+ @d.select_order_map(:name).should == ['1']
163
+ end
164
+ end
129
165
  end
130
166
 
131
167
  specify "should support all transaction isolation levels" do
@@ -134,4 +170,143 @@ describe "Database transactions" do
134
170
  @d.count.should == i + 1
135
171
  end
136
172
  end
173
+
174
+ specify "should support after_commit outside transactions" do
175
+ c = nil
176
+ @db.after_commit{c = 1}
177
+ c.should == 1
178
+ end
179
+
180
+ specify "should support after_rollback outside transactions" do
181
+ c = nil
182
+ @db.after_rollback{c = 1}
183
+ c.should be_nil
184
+ end
185
+
186
+ specify "should support after_commit inside transactions" do
187
+ c = nil
188
+ @db.transaction{@db.after_commit{c = 1}; c.should be_nil}
189
+ c.should == 1
190
+ end
191
+
192
+ specify "should support after_rollback inside transactions" do
193
+ c = nil
194
+ @db.transaction{@db.after_rollback{c = 1}; c.should be_nil}
195
+ c.should be_nil
196
+ end
197
+
198
+ specify "should not call after_commit if the transaction rolls back" do
199
+ c = nil
200
+ @db.transaction{@db.after_commit{c = 1}; c.should be_nil; raise Sequel::Rollback}
201
+ c.should be_nil
202
+ end
203
+
204
+ specify "should call after_rollback if the transaction rolls back" do
205
+ c = nil
206
+ @db.transaction{@db.after_rollback{c = 1}; c.should be_nil; raise Sequel::Rollback}
207
+ c.should == 1
208
+ end
209
+
210
+ specify "should support multiple after_commit blocks inside transactions" do
211
+ c = []
212
+ @db.transaction{@db.after_commit{c << 1}; @db.after_commit{c << 2}; c.should == []}
213
+ c.should == [1, 2]
214
+ end
215
+
216
+ specify "should support multiple after_rollback blocks inside transactions" do
217
+ c = []
218
+ @db.transaction{@db.after_rollback{c << 1}; @db.after_rollback{c << 2}; c.should == []; raise Sequel::Rollback}
219
+ c.should == [1, 2]
220
+ end
221
+
222
+ specify "should support after_commit inside nested transactions" do
223
+ c = nil
224
+ @db.transaction{@db.transaction{@db.after_commit{c = 1}}; c.should be_nil}
225
+ c.should == 1
226
+ end
227
+
228
+ specify "should support after_rollback inside nested transactions" do
229
+ c = nil
230
+ @db.transaction{@db.transaction{@db.after_rollback{c = 1}}; c.should be_nil; raise Sequel::Rollback}
231
+ c.should == 1
232
+ end
233
+
234
+ if INTEGRATION_DB.supports_savepoints?
235
+ specify "should support after_commit inside savepoints" do
236
+ c = nil
237
+ @db.transaction{@db.transaction(:savepoint=>true){@db.after_commit{c = 1}}; c.should be_nil}
238
+ c.should == 1
239
+ end
240
+
241
+ specify "should support after_rollback inside savepoints" do
242
+ c = nil
243
+ @db.transaction{@db.transaction(:savepoint=>true){@db.after_rollback{c = 1}}; c.should be_nil; raise Sequel::Rollback}
244
+ c.should == 1
245
+ end
246
+ end
247
+
248
+ if INTEGRATION_DB.supports_prepared_transactions?
249
+ specify "should raise an error if you attempt to use after_commit or after_rollback inside a prepared transaction" do
250
+ proc{@db.transaction(:prepare=>'XYZ'){@db.after_commit{}}}.should raise_error(Sequel::Error)
251
+ proc{@db.transaction(:prepare=>'XYZ'){@db.after_rollback{}}}.should raise_error(Sequel::Error)
252
+ end
253
+
254
+ if INTEGRATION_DB.supports_savepoints_in_prepared_transactions?
255
+ specify "should raise an error if you attempt to use after_commit or after rollback inside a savepoint in a prepared transaction" do
256
+ proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_commit{}}}}.should raise_error(Sequel::Error)
257
+ proc{@db.transaction(:prepare=>'XYZ'){@db.transaction(:savepoint=>true){@db.after_rollback{}}}}.should raise_error(Sequel::Error)
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ if (! defined?(RUBY_ENGINE) or RUBY_ENGINE == 'ruby' or (RUBY_ENGINE == 'rbx' && !Sequel.guarded?([:do, :sqlite], [:tinytds, :mssql]))) and RUBY_VERSION < '1.9'
264
+ describe "Database transactions and Thread#kill" do
265
+ before do
266
+ @db = INTEGRATION_DB
267
+ @db.create_table!(:items, :engine=>'InnoDB'){String :name; Integer :value}
268
+ @d = @db[:items]
269
+ end
270
+ after do
271
+ @db.drop_table?(:items)
272
+ end
273
+
274
+ specify "should handle transactions inside threads" do
275
+ q = Queue.new
276
+ q1 = Queue.new
277
+ t = Thread.new do
278
+ @db.transaction do
279
+ @d << {:name => 'abc', :value => 1}
280
+ q1.push nil
281
+ q.pop
282
+ @d << {:name => 'def', :value => 2}
283
+ end
284
+ end
285
+ q1.pop
286
+ t.kill
287
+ @d.count.should == 0
288
+ end
289
+
290
+ if INTEGRATION_DB.supports_savepoints?
291
+ specify "should handle transactions with savepoints inside threads" do
292
+ q = Queue.new
293
+ q1 = Queue.new
294
+ t = Thread.new do
295
+ @db.transaction do
296
+ @d << {:name => 'abc', :value => 1}
297
+ @db.transaction(:savepoint=>true) do
298
+ @d << {:name => 'def', :value => 2}
299
+ q1.push nil
300
+ q.pop
301
+ @d << {:name => 'ghi', :value => 3}
302
+ end
303
+ @d << {:name => 'jkl', :value => 4}
304
+ end
305
+ end
306
+ q1.pop
307
+ t.kill
308
+ @d.count.should == 0
309
+ end
310
+ end
311
+ end
137
312
  end
@@ -6,7 +6,7 @@ describe "Supported types" do
6
6
  INTEGRATION_DB[:items]
7
7
  end
8
8
 
9
- cspecify "should support casting correctly", [:sqlite, :sqlite] do
9
+ specify "should support casting correctly" do
10
10
  ds = create_items_table_with_column(:number, Integer)
11
11
  ds.insert(:number => 1)
12
12
  ds.select(:number.cast_string.as(:n)).map(:n).should == %w'1'
@@ -33,7 +33,7 @@ describe "Supported types" do
33
33
  ds.all.should == [{:number=>2}]
34
34
  end
35
35
 
36
- specify "should support generic bignum type" do
36
+ cspecify "should support generic bignum type", [:swift, :sqlite] do
37
37
  ds = create_items_table_with_column(:number, Bignum)
38
38
  ds.insert(:number => 2**34)
39
39
  ds.all.should == [{:number=>2**34}]
@@ -60,7 +60,7 @@ describe "Supported types" do
60
60
  ds.all.should == [{:name=>'Test User'}]
61
61
  end
62
62
 
63
- cspecify "should support generic date type", [:do, :sqlite], [:jdbc, :sqlite], :mssql do
63
+ cspecify "should support generic date type", [:do, :sqlite], [:jdbc, :sqlite], :mssql, :oracle do
64
64
  ds = create_items_table_with_column(:dat, Date)
65
65
  d = Date.today
66
66
  ds.insert(:dat => d)
@@ -68,6 +68,20 @@ describe "Supported types" do
68
68
  ds.first[:dat].to_s.should == d.to_s
69
69
  end
70
70
 
71
+ cspecify "should support generic time type", [:do], [:swift], [:odbc], [:jdbc, :mssql], [:jdbc, :sqlite], [:mysql2], [:tinytds], :oracle do
72
+ ds = create_items_table_with_column(:tim, Time, :only_time=>true)
73
+ t = Sequel::SQLTime.now
74
+ ds.insert(:tim => t)
75
+ v = ds.first[:tim]
76
+ ds.literal(v).should == ds.literal(t)
77
+ v.should be_a_kind_of(Sequel::SQLTime)
78
+ ds.delete
79
+ ds.insert(:tim => v)
80
+ v2 = ds.first[:tim]
81
+ ds.literal(v2).should == ds.literal(t)
82
+ v2.should be_a_kind_of(Sequel::SQLTime)
83
+ end
84
+
71
85
  cspecify "should support generic datetime type", [:do, :sqlite], [:jdbc, :sqlite] do
72
86
  ds = create_items_table_with_column(:tim, DateTime)
73
87
  t = DateTime.now
@@ -86,7 +100,7 @@ describe "Supported types" do
86
100
  ds.first[:name].should be_a_kind_of(::Sequel::SQL::Blob)
87
101
  end
88
102
 
89
- cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:odbc, :mssql] do
103
+ cspecify "should support generic boolean type", [:do, :sqlite], [:jdbc, :sqlite], [:jdbc, :db2], [:odbc, :mssql], :oracle do
90
104
  ds = create_items_table_with_column(:number, TrueClass)
91
105
  ds.insert(:number => true)
92
106
  ds.all.should == [{:number=>true}]
@@ -2,15 +2,19 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe Sequel::Model::Associations::AssociationReflection, "#associated_class" do
4
4
  before do
5
- @c = Class.new(Sequel::Model)
5
+ @c = Class.new(Sequel::Model(:foo))
6
6
  class ::ParParent < Sequel::Model; end
7
7
  end
8
+ after do
9
+ Object.send(:remove_const, :ParParent)
10
+ end
8
11
 
9
12
  it "should use the :class value if present" do
10
13
  @c.many_to_one :c, :class=>ParParent
11
14
  @c.association_reflection(:c).keys.should include(:class)
12
15
  @c.association_reflection(:c).associated_class.should == ParParent
13
16
  end
17
+
14
18
  it "should figure out the class if the :class value is not present" do
15
19
  @c.many_to_one :c, :class=>'ParParent'
16
20
  @c.association_reflection(:c).keys.should_not include(:class)
@@ -20,15 +24,19 @@ end
20
24
 
21
25
  describe Sequel::Model::Associations::AssociationReflection, "#primary_key" do
22
26
  before do
23
- @c = Class.new(Sequel::Model)
27
+ @c = Class.new(Sequel::Model(:foo))
24
28
  class ::ParParent < Sequel::Model; end
25
29
  end
30
+ after do
31
+ Object.send(:remove_const, :ParParent)
32
+ end
26
33
 
27
34
  it "should use the :primary_key value if present" do
28
35
  @c.many_to_one :c, :class=>ParParent, :primary_key=>:blah__blah
29
36
  @c.association_reflection(:c).keys.should include(:primary_key)
30
37
  @c.association_reflection(:c).primary_key.should == :blah__blah
31
38
  end
39
+
32
40
  it "should use the associated table's primary key if :primary_key is not present" do
33
41
  @c.many_to_one :c, :class=>'ParParent'
34
42
  @c.association_reflection(:c).keys.should_not include(:primary_key)
@@ -49,8 +57,8 @@ describe Sequel::Model::Associations::AssociationReflection, "#reciprocal" do
49
57
  end
50
58
 
51
59
  it "should use the :reciprocal value if present" do
52
- @c = Class.new(Sequel::Model)
53
- @d = Class.new(Sequel::Model)
60
+ @c = Class.new(Sequel::Model(:foo))
61
+ @d = Class.new(Sequel::Model(:foo))
54
62
  @c.many_to_one :c, :class=>@d, :reciprocal=>:xx
55
63
  @c.association_reflection(:c).keys.should include(:reciprocal)
56
64
  @c.association_reflection(:c).reciprocal.should == :xx
@@ -111,9 +119,12 @@ end
111
119
 
112
120
  describe Sequel::Model::Associations::AssociationReflection, "#select" do
113
121
  before do
114
- @c = Class.new(Sequel::Model)
122
+ @c = Class.new(Sequel::Model(:foo))
115
123
  class ::ParParent < Sequel::Model; end
116
124
  end
125
+ after do
126
+ Object.send(:remove_const, :ParParent)
127
+ end
117
128
 
118
129
  it "should use the :select value if present" do
119
130
  @c.many_to_one :c, :class=>ParParent, :select=>[:par_parents__id]
@@ -143,9 +154,12 @@ end
143
154
 
144
155
  describe Sequel::Model::Associations::AssociationReflection, "#associated_object_keys" do
145
156
  before do
146
- @c = Class.new(Sequel::Model)
157
+ @c = Class.new(Sequel::Model(:foo))
147
158
  class ::ParParent < Sequel::Model; end
148
159
  end
160
+ after do
161
+ Object.send(:remove_const, :ParParent)
162
+ end
149
163
 
150
164
  it "should use the primary keys for a many_to_one association" do
151
165
  @c.many_to_one :c, :class=>ParParent
@@ -173,9 +187,36 @@ describe Sequel::Model::Associations::AssociationReflection, "#associated_object
173
187
  end
174
188
  end
175
189
 
190
+ describe Sequel::Model::Associations::AssociationReflection do
191
+ before do
192
+ @c = Class.new(Sequel::Model(:foo))
193
+ @c.meta_def(:name){"C"}
194
+ end
195
+
196
+ it "one_to_many #qualified_primary_key should be a qualified version of the primary key" do
197
+ @c.one_to_many :cs, :class=>@c
198
+ @c.dataset.literal(@c.association_reflection(:cs).qualified_primary_key).should == 'foo.id'
199
+ end
200
+
201
+ it "many_to_many #associated_key_column should be the left key" do
202
+ @c.many_to_many :cs, :class=>@c
203
+ @c.association_reflection(:cs).associated_key_column.should == :c_id
204
+ end
205
+
206
+ it "many_to_many #qualified_right_key should be a qualified version of the primary key" do
207
+ @c.many_to_many :cs, :class=>@c, :right_key=>:c2_id
208
+ @c.dataset.literal(@c.association_reflection(:cs).qualified_right_key).should == 'cs_cs.c2_id'
209
+ end
210
+
211
+ it "many_to_many #qualified_right_primary_key should be a qualified version of the primary key" do
212
+ @c.many_to_many :cs, :class=>@c
213
+ @c.dataset.literal(@c.association_reflection(:cs).qualified_right_primary_key).should == 'foo.id'
214
+ end
215
+ end
216
+
176
217
  describe Sequel::Model::Associations::AssociationReflection, "#remove_before_destroy?" do
177
218
  before do
178
- @c = Class.new(Sequel::Model)
219
+ @c = Class.new(Sequel::Model(:foo))
179
220
  end
180
221
 
181
222
  it "should be true for many_to_one and many_to_many associations" do
@@ -184,6 +225,7 @@ describe Sequel::Model::Associations::AssociationReflection, "#remove_before_des
184
225
  @c.many_to_many :cs, :class=>@c
185
226
  @c.association_reflection(:cs).remove_before_destroy?.should be_true
186
227
  end
228
+
187
229
  it "should be false for one_to_one and one_to_many associations" do
188
230
  @c.one_to_one :c, :class=>@c
189
231
  @c.association_reflection(:c).remove_before_destroy?.should be_false
@@ -192,3 +234,155 @@ describe Sequel::Model::Associations::AssociationReflection, "#remove_before_des
192
234
  end
193
235
  end
194
236
 
237
+ describe Sequel::Model::Associations::AssociationReflection, "#eager_limit_strategy" do
238
+ before do
239
+ @c = Class.new(Sequel::Model(:a))
240
+ end
241
+ after do
242
+ Sequel::Model.default_eager_limit_strategy = nil
243
+ end
244
+
245
+ it "should be nil by default for *_one associations" do
246
+ @c.many_to_one :c, :class=>@c
247
+ @c.association_reflection(:c).eager_limit_strategy.should be_nil
248
+ @c.one_to_one :c, :class=>@c
249
+ @c.association_reflection(:c).eager_limit_strategy.should be_nil
250
+ end
251
+
252
+ it "should be :ruby by default for *_many associations" do
253
+ @c.one_to_many :cs, :class=>@c, :limit=>1
254
+ @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
255
+ @c.many_to_many :cs, :class=>@c, :limit=>1
256
+ @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
257
+ end
258
+
259
+ it "should be nil for many_to_one associations" do
260
+ @c.many_to_one :c, :class=>@c, :eager_limit_strategy=>true
261
+ @c.association_reflection(:c).eager_limit_strategy.should be_nil
262
+ @c.many_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
263
+ @c.association_reflection(:c).eager_limit_strategy.should be_nil
264
+ end
265
+
266
+ it "should be a symbol for other associations if given a symbol" do
267
+ @c.one_to_one :c, :class=>@c, :eager_limit_strategy=>:distinct_on
268
+ @c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
269
+ @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>:window_function, :limit=>1
270
+ @c.association_reflection(:cs).eager_limit_strategy.should == :window_function
271
+ end
272
+
273
+ it "should use :distinct_on for one_to_one associations if picking and the association dataset supports ordered distinct on" do
274
+ @c.dataset.meta_def(:supports_ordered_distinct_on?){true}
275
+ @c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
276
+ @c.association_reflection(:c).eager_limit_strategy.should == :distinct_on
277
+ end
278
+
279
+ it "should use :window_function for associations if picking and the association dataset supports window functions" do
280
+ @c.dataset.meta_def(:supports_window_functions?){true}
281
+ @c.one_to_one :c, :class=>@c, :eager_limit_strategy=>true
282
+ @c.association_reflection(:c).eager_limit_strategy.should == :window_function
283
+ @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
284
+ @c.association_reflection(:cs).eager_limit_strategy.should == :window_function
285
+ @c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
286
+ @c.association_reflection(:cs).eager_limit_strategy.should == :window_function
287
+ end
288
+
289
+ it "should use :ruby for *_many associations if picking and the association dataset doesn't window functions" do
290
+ @c.one_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
291
+ @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
292
+ @c.many_to_many :cs, :class=>@c, :eager_limit_strategy=>true, :limit=>1
293
+ @c.association_reflection(:cs).eager_limit_strategy.should == :ruby
294
+ end
295
+
296
+ it "should respect Model.default_eager_limit_strategy to *_many associations" do
297
+ Sequel::Model.default_eager_limit_strategy = :window_function
298
+ Sequel::Model.default_eager_limit_strategy.should == :window_function
299
+ c = Class.new(Sequel::Model)
300
+ c.dataset = :a
301
+ c.default_eager_limit_strategy.should == :window_function
302
+ c.one_to_many :cs, :class=>c, :limit=>1
303
+ c.association_reflection(:cs).eager_limit_strategy.should == :window_function
304
+ c.many_to_many :cs, :class=>c, :limit=>1
305
+ c.association_reflection(:cs).eager_limit_strategy.should == :window_function
306
+
307
+ Sequel::Model.default_eager_limit_strategy = true
308
+ c = Class.new(Sequel::Model)
309
+ c.dataset = :a
310
+ c.one_to_many :cs, :class=>c, :limit=>1
311
+ c.association_reflection(:cs).eager_limit_strategy.should == :ruby
312
+ c.dataset.meta_def(:supports_window_functions?){true}
313
+ c.many_to_many :cs, :class=>c, :limit=>1
314
+ c.association_reflection(:cs).eager_limit_strategy.should == :window_function
315
+
316
+ c.default_eager_limit_strategy = :correlated_subquery
317
+ c.many_to_many :cs, :class=>c, :limit=>1
318
+ c.association_reflection(:cs).eager_limit_strategy.should == :correlated_subquery
319
+ end
320
+
321
+ it "should ignore Model.default_eager_limit_strategy for one_to_one associations" do
322
+ @c.default_eager_limit_strategy = :correlated_subquery
323
+ @c.one_to_one :c, :class=>@c
324
+ @c.association_reflection(:c).eager_limit_strategy.should be_nil
325
+ end
326
+ end
327
+
328
+ describe Sequel::Model, " association reflection methods" do
329
+ before do
330
+ @c1 = Class.new(Sequel::Model(:nodes)) do
331
+ def self.name; 'Node'; end
332
+ def self.to_s; 'Node'; end
333
+ end
334
+ MODEL_DB.reset
335
+ end
336
+
337
+ it "#all_association_reflections should include all association reflection hashes" do
338
+ @c1.all_association_reflections.should == []
339
+
340
+ @c1.associate :many_to_one, :parent, :class => @c1
341
+ @c1.all_association_reflections.collect{|v| v[:name]}.should == [:parent]
342
+ @c1.all_association_reflections.collect{|v| v[:type]}.should == [:many_to_one]
343
+ @c1.all_association_reflections.collect{|v| v[:class]}.should == [@c1]
344
+
345
+ @c1.associate :one_to_many, :children, :class => @c1
346
+ @c1.all_association_reflections.sort_by{|x|x[:name].to_s}
347
+ @c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:name]}.should == [:children, :parent]
348
+ @c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:type]}.should == [:one_to_many, :many_to_one]
349
+ @c1.all_association_reflections.sort_by{|x|x[:name].to_s}.collect{|v| v[:class]}.should == [@c1, @c1]
350
+ end
351
+
352
+ it "#association_reflection should return nil for nonexistent association" do
353
+ @c1.association_reflection(:blah).should == nil
354
+ end
355
+
356
+ it "#association_reflection should return association reflection hash if association exists" do
357
+ @c1.associate :many_to_one, :parent, :class => @c1
358
+ @c1.association_reflection(:parent).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
359
+ @c1.association_reflection(:parent)[:name].should == :parent
360
+ @c1.association_reflection(:parent)[:type].should == :many_to_one
361
+ @c1.association_reflection(:parent)[:class].should == @c1
362
+
363
+ @c1.associate :one_to_many, :children, :class => @c1
364
+ @c1.association_reflection(:children).should be_a_kind_of(Sequel::Model::Associations::AssociationReflection)
365
+ @c1.association_reflection(:children)[:name].should == :children
366
+ @c1.association_reflection(:children)[:type].should == :one_to_many
367
+ @c1.association_reflection(:children)[:class].should == @c1
368
+ end
369
+
370
+ it "#associations should include all association names" do
371
+ @c1.associations.should == []
372
+ @c1.associate :many_to_one, :parent, :class => @c1
373
+ @c1.associations.should == [:parent]
374
+ @c1.associate :one_to_many, :children, :class => @c1
375
+ @c1.associations.sort_by{|x|x.to_s}.should == [:children, :parent]
376
+ end
377
+
378
+ it "association reflections should be copied upon subclasing" do
379
+ @c1.associate :many_to_one, :parent, :class => @c1
380
+ c = Class.new(@c1)
381
+ @c1.associations.should == [:parent]
382
+ c.associations.should == [:parent]
383
+ c.associate :many_to_one, :parent2, :class => @c1
384
+ @c1.associations.should == [:parent]
385
+ c.associations.sort_by{|x| x.to_s}.should == [:parent, :parent2]
386
+ c.instance_methods.map{|x| x.to_s}.should include('parent')
387
+ end
388
+ end