sequel 3.21.0 → 3.39.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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,28 +1,34 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  # H2 and MSSQL don't support USING joins
4
- unless [:h2, :mssql].include?(INTEGRATION_DB.database_type)
4
+ # DB2 does not seem to support USING joins in every version; it seems to be
5
+ # valid expression in DB2 iSeries UDB though.
6
+ unless Sequel.guarded?(:h2, :mssql, :db2)
5
7
  describe "Class Table Inheritance Plugin" do
6
- before do
8
+ before(:all) do
7
9
  @db = INTEGRATION_DB
8
10
  @db.instance_variable_set(:@schemas, {})
9
- @db.create_table!(:employees) do
11
+ @db.drop_table?(:staff, :executives, :managers, :employees)
12
+ @db.create_table(:employees) do
10
13
  primary_key :id
11
14
  String :name
12
15
  String :kind
13
16
  end
14
- @db.create_table!(:managers) do
17
+ @db.create_table(:managers) do
15
18
  foreign_key :id, :employees, :primary_key=>true
16
19
  Integer :num_staff
17
20
  end
18
- @db.create_table!(:executives) do
21
+ @db.create_table(:executives) do
19
22
  foreign_key :id, :managers, :primary_key=>true
20
23
  Integer :num_managers
21
24
  end
22
- @db.create_table!(:staff) do
25
+ @db.create_table(:staff) do
23
26
  foreign_key :id, :employees, :primary_key=>true
24
27
  foreign_key :manager_id, :managers
25
28
  end
29
+ end
30
+ before do
31
+ [:staff, :executives, :managers, :employees].each{|t| @db[t].delete}
26
32
  class ::Employee < Sequel::Model(@db)
27
33
  plugin :class_table_inheritance, :key=>:kind, :table_map=>{:Staff=>:staff}
28
34
  end
@@ -32,7 +38,7 @@ describe "Class Table Inheritance Plugin" do
32
38
  class ::Executive < Manager
33
39
  end
34
40
  class ::Staff < Employee
35
- many_to_one :manager
41
+ many_to_one :manager, :qualify=>false
36
42
  end
37
43
 
38
44
  @i1 =@db[:employees].insert(:name=>'E', :kind=>'Employee')
@@ -43,13 +49,13 @@ describe "Class Table Inheritance Plugin" do
43
49
  @db[:managers].insert(:id=>@i4, :num_staff=>5)
44
50
  @db[:executives].insert(:id=>@i4, :num_managers=>6)
45
51
  @db[:staff].insert(:id=>@i2, :manager_id=>@i4)
46
-
47
- clear_sqls
48
52
  end
49
53
  after do
50
- @db.drop_table :staff, :executives, :managers, :employees
51
54
  [:Executive, :Manager, :Staff, :Employee].each{|s| Object.send(:remove_const, s)}
52
55
  end
56
+ after(:all) do
57
+ @db.drop_table? :staff, :executives, :managers, :employees
58
+ end
53
59
 
54
60
  specify "should return rows as subclass instances" do
55
61
  Employee.order(:id).all.should == [
@@ -94,8 +100,7 @@ describe "Class Table Inheritance Plugin" do
94
100
  Employee.filter(:id=>@i2).all.first.manager.id.should == @i4
95
101
  end
96
102
 
97
- # See http://www.sqlite.org/src/tktview/3338b3fa19ac4abee6c475126a2e6d9d61f26ab1
98
- cspecify "should insert rows into all tables", :sqlite do
103
+ cspecify "should insert rows into all tables", [proc{|db| db.sqlite_version < 30709}, :sqlite] do
99
104
  e = Executive.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
100
105
  i = e.id
101
106
  @db[:employees][:id=>i].should == {:id=>i, :name=>'Ex2', :kind=>'Executive'}
@@ -110,17 +115,17 @@ describe "Class Table Inheritance Plugin" do
110
115
  @db[:executives][:id=>@i4].should == {:id=>@i4, :num_managers=>8}
111
116
  end
112
117
 
113
- cspecify "should handle many_to_one relationships", :sqlite do
118
+ specify "should handle many_to_one relationships" do
114
119
  m = Staff.first.manager
115
120
  m.should == Manager[@i4]
116
121
  m.should be_a_kind_of(Executive)
117
122
  end
118
123
 
119
- cspecify "should handle eagerly loading many_to_one relationships", :sqlite do
124
+ specify "should handle eagerly loading many_to_one relationships" do
120
125
  Staff.limit(1).eager(:manager).all.map{|x| x.manager}.should == [Manager[@i4]]
121
126
  end
122
127
 
123
- cspecify "should handle eagerly graphing many_to_one relationships", :sqlite do
128
+ specify "should handle eagerly graphing many_to_one relationships" do
124
129
  ss = Staff.eager_graph(:manager).all
125
130
  ss.should == [Staff[@i2]]
126
131
  ss.map{|x| x.manager}.should == [Manager[@i4]]
@@ -134,7 +139,7 @@ describe "Class Table Inheritance Plugin" do
134
139
  Executive.limit(1).eager(:staff_members).first.staff_members.should == [Staff[@i2]]
135
140
  end
136
141
 
137
- cspecify "should handle eagerly graphing one_to_many relationships", :sqlite do
142
+ cspecify "should handle eagerly graphing one_to_many relationships", [proc{|db| db.sqlite_version < 30709}, :sqlite] do
138
143
  es = Executive.limit(1).eager_graph(:staff_members).all
139
144
  es.should == [Executive[@i4]]
140
145
  es.map{|x| x.staff_members}.should == [[Staff[@i2]]]
@@ -143,21 +148,25 @@ end
143
148
  end
144
149
 
145
150
  describe "Many Through Many Plugin" do
146
- before do
151
+ before(:all) do
147
152
  @db = INTEGRATION_DB
148
153
  @db.instance_variable_set(:@schemas, {})
149
- @db.create_table!(:albums) do
154
+ @db.drop_table?(:albums_artists, :albums, :artists)
155
+ @db.create_table(:albums) do
150
156
  primary_key :id
151
157
  String :name
152
158
  end
153
- @db.create_table!(:artists) do
159
+ @db.create_table(:artists) do
154
160
  primary_key :id
155
161
  String :name
156
162
  end
157
- @db.create_table!(:albums_artists) do
163
+ @db.create_table(:albums_artists) do
158
164
  foreign_key :album_id, :albums
159
165
  foreign_key :artist_id, :artists
160
166
  end
167
+ end
168
+ before do
169
+ [:albums_artists, :albums, :artists].each{|t| @db[t].delete}
161
170
  class ::Album < Sequel::Model(@db)
162
171
  many_to_many :artists
163
172
  end
@@ -181,21 +190,31 @@ describe "Many Through Many Plugin" do
181
190
  @album4 = Album.create(:name=>'D')
182
191
  @album4.add_artist(@artist1)
183
192
  @album4.add_artist(@artist4)
184
-
185
- clear_sqls
186
193
  end
187
194
  after do
188
- @db.drop_table :albums_artists, :albums, :artists
189
195
  [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
190
196
  end
197
+ after(:all) do
198
+ @db.drop_table? :albums_artists, :albums, :artists
199
+ end
191
200
 
201
+ def self_join(c)
202
+ c.join(Sequel.as(c.table_name, :b), Array(c.primary_key).zip(Array(c.primary_key))).select_all(c.table_name)
203
+ end
204
+
192
205
  specify "should handle super simple case with 1 join table" do
193
206
  Artist.many_through_many :albums, [[:albums_artists, :artist_id, :album_id]]
194
- Artist[1].albums.map{|x| x.name}.sort.should == %w'A D'
195
- Artist[2].albums.map{|x| x.name}.sort.should == %w'A C'
196
- Artist[3].albums.map{|x| x.name}.sort.should == %w'B C'
197
- Artist[4].albums.map{|x| x.name}.sort.should == %w'B D'
207
+ Artist[@artist1.id].albums.map{|x| x.name}.sort.should == %w'A D'
208
+ Artist[@artist2.id].albums.map{|x| x.name}.sort.should == %w'A C'
209
+ Artist[@artist3.id].albums.map{|x| x.name}.sort.should == %w'B C'
210
+ Artist[@artist4.id].albums.map{|x| x.name}.sort.should == %w'B D'
198
211
 
212
+ Artist.plugin :prepared_statements_associations
213
+ Artist[@artist1.id].albums.map{|x| x.name}.sort.should == %w'A D'
214
+ Artist[@artist2.id].albums.map{|x| x.name}.sort.should == %w'A C'
215
+ Artist[@artist3.id].albums.map{|x| x.name}.sort.should == %w'B C'
216
+ Artist[@artist4.id].albums.map{|x| x.name}.sort.should == %w'B D'
217
+
199
218
  Artist.filter(:id=>1).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A D'
200
219
  Artist.filter(:id=>2).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A C'
201
220
  Artist.filter(:id=>3).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B C'
@@ -205,24 +224,102 @@ describe "Many Through Many Plugin" do
205
224
  Artist.filter(:artists__id=>2).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'A C'
206
225
  Artist.filter(:artists__id=>3).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B C'
207
226
  Artist.filter(:artists__id=>4).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
227
+
228
+ Artist.filter(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2'
229
+ Artist.filter(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'3 4'
230
+ Artist.filter(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'2 3'
231
+ Artist.filter(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'1 4'
232
+
233
+ Artist.exclude(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'3 4'
234
+ Artist.exclude(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2'
235
+ Artist.exclude(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 4'
236
+ Artist.exclude(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3'
237
+
238
+ Artist.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
239
+ Artist.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'1 3 4'
240
+
241
+ Artist.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
242
+ Artist.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'2'
243
+
244
+ Artist.filter(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
245
+ Artist.exclude(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
246
+
247
+ c = self_join(Artist)
248
+ c.filter(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2'
249
+ c.filter(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'3 4'
250
+ c.filter(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'2 3'
251
+ c.filter(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'1 4'
252
+
253
+ c.exclude(:albums=>@album1).all.map{|a| a.name}.sort.should == %w'3 4'
254
+ c.exclude(:albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2'
255
+ c.exclude(:albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 4'
256
+ c.exclude(:albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3'
257
+
258
+ c.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
259
+ c.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'1 3 4'
260
+
261
+ c.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
262
+ c.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w'2'
263
+
264
+ c.filter(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
265
+ c.exclude(:albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
208
266
  end
209
267
 
210
268
  specify "should handle typical case with 3 join tables" do
211
269
  Artist.many_through_many :related_artists, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id]], :class=>Artist, :distinct=>true
212
- Artist[1].related_artists.map{|x| x.name}.sort.should == %w'1 2 4'
213
- Artist[2].related_artists.map{|x| x.name}.sort.should == %w'1 2 3'
214
- Artist[3].related_artists.map{|x| x.name}.sort.should == %w'2 3 4'
215
- Artist[4].related_artists.map{|x| x.name}.sort.should == %w'1 3 4'
270
+ Artist[@artist1.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 4'
271
+ Artist[@artist2.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 3'
272
+ Artist[@artist3.id].related_artists.map{|x| x.name}.sort.should == %w'2 3 4'
273
+ Artist[@artist4.id].related_artists.map{|x| x.name}.sort.should == %w'1 3 4'
274
+
275
+ Artist.plugin :prepared_statements_associations
276
+ Artist[@artist1.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 4'
277
+ Artist[@artist2.id].related_artists.map{|x| x.name}.sort.should == %w'1 2 3'
278
+ Artist[@artist3.id].related_artists.map{|x| x.name}.sort.should == %w'2 3 4'
279
+ Artist[@artist4.id].related_artists.map{|x| x.name}.sort.should == %w'1 3 4'
216
280
 
217
- Artist.filter(:id=>1).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 4'
218
- Artist.filter(:id=>2).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
219
- Artist.filter(:id=>3).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
220
- Artist.filter(:id=>4).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 3 4'
281
+ Artist.filter(:id=>@artist1.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 4'
282
+ Artist.filter(:id=>@artist2.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
283
+ Artist.filter(:id=>@artist3.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
284
+ Artist.filter(:id=>@artist4.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 3 4'
221
285
 
222
- Artist.filter(:artists__id=>1).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 4'
223
- Artist.filter(:artists__id=>2).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
224
- Artist.filter(:artists__id=>3).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
225
- Artist.filter(:artists__id=>4).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 3 4'
286
+ Artist.filter(:artists__id=>@artist1.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 4'
287
+ Artist.filter(:artists__id=>@artist2.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 2 3'
288
+ Artist.filter(:artists__id=>@artist3.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'2 3 4'
289
+ Artist.filter(:artists__id=>@artist4.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.should == %w'1 3 4'
290
+
291
+ Artist.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'1 2 4'
292
+ Artist.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'1 2 3'
293
+ Artist.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'2 3 4'
294
+ Artist.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'1 3 4'
295
+
296
+ Artist.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'3'
297
+ Artist.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'4'
298
+ Artist.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'1'
299
+ Artist.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'2'
300
+
301
+ Artist.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
302
+ Artist.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w''
303
+
304
+ Artist.filter(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'1 2 4'
305
+ Artist.exclude(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
306
+
307
+ c = self_join(Artist)
308
+ c.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'1 2 4'
309
+ c.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'1 2 3'
310
+ c.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'2 3 4'
311
+ c.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'1 3 4'
312
+
313
+ c.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.should == %w'3'
314
+ c.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.should == %w'4'
315
+ c.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.should == %w'1'
316
+ c.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.should == %w'2'
317
+
318
+ c.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
319
+ c.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.should == %w''
320
+
321
+ c.filter(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'1 2 4'
322
+ c.exclude(:related_artists=>c.filter(:artists__id=>@artist1.id)).all.map{|a| a.name}.sort.should == %w'3'
226
323
  end
227
324
 
228
325
  specify "should handle extreme case with 5 join tables" do
@@ -236,38 +333,84 @@ describe "Many Through Many Plugin" do
236
333
  @album4.add_artist(@artist3)
237
334
  @album4.add_artist(@artist4)
238
335
 
239
- Artist[1].related_albums.map{|x| x.name}.sort.should == %w'A B C'
240
- Artist[2].related_albums.map{|x| x.name}.sort.should == %w'A B C D'
241
- Artist[3].related_albums.map{|x| x.name}.sort.should == %w'A B D'
242
- Artist[4].related_albums.map{|x| x.name}.sort.should == %w'B D'
336
+ Artist[@artist1.id].related_albums.map{|x| x.name}.sort.should == %w'A B C'
337
+ Artist[@artist2.id].related_albums.map{|x| x.name}.sort.should == %w'A B C D'
338
+ Artist[@artist3.id].related_albums.map{|x| x.name}.sort.should == %w'A B D'
339
+ Artist[@artist4.id].related_albums.map{|x| x.name}.sort.should == %w'B D'
243
340
 
244
- Artist.filter(:id=>1).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C'
245
- Artist.filter(:id=>2).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
246
- Artist.filter(:id=>3).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
247
- Artist.filter(:id=>4).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
341
+ Artist.plugin :prepared_statements_associations
342
+ Artist[@artist1.id].related_albums.map{|x| x.name}.sort.should == %w'A B C'
343
+ Artist[@artist2.id].related_albums.map{|x| x.name}.sort.should == %w'A B C D'
344
+ Artist[@artist3.id].related_albums.map{|x| x.name}.sort.should == %w'A B D'
345
+ Artist[@artist4.id].related_albums.map{|x| x.name}.sort.should == %w'B D'
248
346
 
249
- Artist.filter(:artists__id=>1).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C'
250
- Artist.filter(:artists__id=>2).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
251
- Artist.filter(:artists__id=>3).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
252
- Artist.filter(:artists__id=>4).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
347
+ Artist.filter(:id=>@artist1.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C'
348
+ Artist.filter(:id=>@artist2.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
349
+ Artist.filter(:id=>@artist3.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
350
+ Artist.filter(:id=>@artist4.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
351
+
352
+ Artist.filter(:artists__id=>@artist1.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C'
353
+ Artist.filter(:artists__id=>@artist2.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B C D'
354
+ Artist.filter(:artists__id=>@artist3.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'A B D'
355
+ Artist.filter(:artists__id=>@artist4.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.should == %w'B D'
356
+
357
+ Artist.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2 3'
358
+ Artist.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
359
+ Artist.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 2'
360
+ Artist.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3 4'
361
+
362
+ Artist.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'4'
363
+ Artist.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w''
364
+ Artist.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'3 4'
365
+ Artist.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'1'
366
+
367
+ Artist.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
368
+ Artist.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
369
+
370
+ Artist.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
371
+ Artist.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w''
372
+
373
+ Artist.filter(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
374
+ Artist.exclude(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
375
+
376
+ c = self_join(Artist)
377
+ c.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'1 2 3'
378
+ c.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
379
+ c.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'1 2'
380
+ c.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'2 3 4'
381
+
382
+ c.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.should == %w'4'
383
+ c.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.should == %w''
384
+ c.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.should == %w'3 4'
385
+ c.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.should == %w'1'
386
+
387
+ c.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'1 2 3'
388
+ c.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.should == %w'1 2 3 4'
389
+
390
+ c.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.should == %w'4'
391
+ c.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.should == %w''
392
+
393
+ c.filter(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'1 2 3'
394
+ c.exclude(:related_albums=>self_join(Album).filter(:albums__id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.should == %w'4'
253
395
  end
254
396
  end
255
397
 
256
398
  describe "Lazy Attributes plugin" do
257
- before do
399
+ before(:all) do
258
400
  @db = INTEGRATION_DB
259
401
  @db.create_table!(:items) do
260
402
  primary_key :id
261
403
  String :name
262
404
  Integer :num
263
405
  end
406
+ @db[:items].delete
264
407
  class ::Item < Sequel::Model(@db)
265
408
  plugin :lazy_attributes, :num
266
409
  end
267
410
  Item.create(:name=>'J', :num=>1)
268
411
  end
269
- after do
270
- @db.drop_table(:items)
412
+ after(:all) do
413
+ @db.drop_table?(:items)
271
414
  Object.send(:remove_const, :Item)
272
415
  end
273
416
 
@@ -299,7 +442,7 @@ describe "Lazy Attributes plugin" do
299
442
  end
300
443
 
301
444
  describe "Tactical Eager Loading Plugin" do
302
- before do
445
+ before(:all) do
303
446
  @db = INTEGRATION_DB
304
447
  @db.instance_variable_set(:@schemas, {})
305
448
  @db.create_table!(:artists) do
@@ -311,6 +454,10 @@ describe "Tactical Eager Loading Plugin" do
311
454
  String :name
312
455
  foreign_key :artist_id, :artists
313
456
  end
457
+ end
458
+ before do
459
+ @db[:albums].delete
460
+ @db[:artists].delete
314
461
  class ::Album < Sequel::Model(@db)
315
462
  plugin :tactical_eager_loading
316
463
  many_to_one :artist
@@ -328,13 +475,13 @@ describe "Tactical Eager Loading Plugin" do
328
475
  @album2 = Album.create(:name=>'B', :artist=>@artist1)
329
476
  @album3 = Album.create(:name=>'C', :artist=>@artist2)
330
477
  @album4 = Album.create(:name=>'D', :artist=>@artist3)
331
-
332
- clear_sqls
333
478
  end
334
479
  after do
335
- @db.drop_table :albums, :artists
336
480
  [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
337
481
  end
482
+ after(:all) do
483
+ @db.drop_table? :albums, :artists
484
+ end
338
485
 
339
486
  specify "should eagerly load associations for all items when accessing any item" do
340
487
  a = Artist.order(:name).all
@@ -363,7 +510,7 @@ describe "Identity Map plugin" do
363
510
  Item.create(:name=>'J', :num=>3)
364
511
  end
365
512
  after do
366
- @db.drop_table(:items)
513
+ @db.drop_table?(:items)
367
514
  Object.send(:remove_const, :Item)
368
515
  end
369
516
 
@@ -382,7 +529,7 @@ describe "Identity Map plugin" do
382
529
  end
383
530
 
384
531
  describe "Touch plugin" do
385
- before do
532
+ before(:all) do
386
533
  @db = INTEGRATION_DB
387
534
  @db.instance_variable_set(:@schemas, {})
388
535
  @db.create_table!(:artists) do
@@ -396,6 +543,10 @@ describe "Touch plugin" do
396
543
  foreign_key :artist_id, :artists
397
544
  DateTime :updated_at
398
545
  end
546
+ end
547
+ before do
548
+ @db[:albums].delete
549
+ @db[:artists].delete
399
550
  class ::Album < Sequel::Model(@db)
400
551
  many_to_one :artist
401
552
  plugin :touch, :associations=>:artist
@@ -407,9 +558,11 @@ describe "Touch plugin" do
407
558
  @album = Album.create(:name=>'A', :artist=>@artist)
408
559
  end
409
560
  after do
410
- @db.drop_table :albums, :artists
411
561
  [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
412
562
  end
563
+ after(:all) do
564
+ @db.drop_table? :albums, :artists
565
+ end
413
566
 
414
567
  specify "should update the timestamp column when touching the record" do
415
568
  @album.updated_at.should == nil
@@ -417,7 +570,7 @@ describe "Touch plugin" do
417
570
  @album.updated_at.to_i.should be_within(2).of(Time.now.to_i)
418
571
  end
419
572
 
420
- cspecify "should update the timestamp column for associated records when the record is updated or destroyed", [:do, :sqlite], [:jdbc, :sqlite] do
573
+ cspecify "should update the timestamp column for associated records when the record is updated or destroyed", [:do, :sqlite], [:jdbc, :sqlite], [:swift] do
421
574
  @artist.updated_at.should == nil
422
575
  @album.update(:name=>'B')
423
576
  ua = @artist.reload.updated_at
@@ -448,7 +601,7 @@ describe "Serialization plugin" do
448
601
  end
449
602
  end
450
603
  after do
451
- @db.drop_table(:items)
604
+ @db.drop_table?(:items)
452
605
  Object.send(:remove_const, :Item)
453
606
  end
454
607
 
@@ -464,7 +617,7 @@ describe "Serialization plugin" do
464
617
  end
465
618
 
466
619
  describe "OptimisticLocking plugin" do
467
- before do
620
+ before(:all) do
468
621
  @db = INTEGRATION_DB
469
622
  @db.create_table!(:people) do
470
623
  primary_key :id
@@ -473,30 +626,33 @@ describe "OptimisticLocking plugin" do
473
626
  end
474
627
  class ::Person < Sequel::Model(@db)
475
628
  plugin :optimistic_locking
476
- create(:name=>'John')
477
629
  end
478
630
  end
479
- after do
480
- @db.drop_table(:people)
631
+ before do
632
+ @db[:people].delete
633
+ @p = Person.create(:name=>'John')
634
+ end
635
+ after(:all) do
636
+ @db.drop_table?(:people)
481
637
  Object.send(:remove_const, :Person)
482
638
  end
483
639
 
484
640
  specify "should raise an error when updating a stale record" do
485
- p1 = Person[1]
486
- p2 = Person[1]
641
+ p1 = Person[@p.id]
642
+ p2 = Person[@p.id]
487
643
  p1.update(:name=>'Jim')
488
644
  proc{p2.update(:name=>'Bob')}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
489
645
  end
490
646
 
491
647
  specify "should raise an error when destroying a stale record" do
492
- p1 = Person[1]
493
- p2 = Person[1]
648
+ p1 = Person[@p.id]
649
+ p2 = Person[@p.id]
494
650
  p1.update(:name=>'Jim')
495
651
  proc{p2.destroy}.should raise_error(Sequel::Plugins::OptimisticLocking::Error)
496
652
  end
497
653
 
498
654
  specify "should not raise an error when updating the same record twice" do
499
- p1 = Person[1]
655
+ p1 = Person[@p.id]
500
656
  p1.update(:name=>'Jim')
501
657
  proc{p1.update(:name=>'Bob')}.should_not raise_error
502
658
  end
@@ -525,10 +681,10 @@ describe "Composition plugin" do
525
681
  composition :date, :mapping=>[:year, :month, :day]
526
682
  end
527
683
  @e1 = Event.create(:year=>2010, :month=>2, :day=>15)
528
- @e2 = Event.create({})
684
+ @e2 = Event.create(:year=>nil)
529
685
  end
530
686
  after do
531
- @db.drop_table(:events)
687
+ @db.drop_table?(:events)
532
688
  Object.send(:remove_const, :Event)
533
689
  end
534
690
 
@@ -555,9 +711,10 @@ describe "Composition plugin" do
555
711
  end
556
712
  end
557
713
 
558
- if INTEGRATION_DB.dataset.supports_cte?
714
+ # DB2's implemention of CTE is too limited to use this plugin
715
+ if INTEGRATION_DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
559
716
  describe "RcteTree Plugin" do
560
- before do
717
+ before(:all) do
561
718
  @db = INTEGRATION_DB
562
719
  @db.create_table!(:nodes) do
563
720
  primary_key :id
@@ -568,22 +725,26 @@ if INTEGRATION_DB.dataset.supports_cte?
568
725
  plugin :rcte_tree, :order=>:name
569
726
  end
570
727
 
571
- @a = Node.create(:name=>'a')
572
- @b = Node.create(:name=>'b')
573
- @aa = Node.create(:name=>'aa', :parent=>@a)
574
- @ab = Node.create(:name=>'ab', :parent=>@a)
575
- @ba = Node.create(:name=>'ba', :parent=>@b)
576
- @bb = Node.create(:name=>'bb', :parent=>@b)
577
- @aaa = Node.create(:name=>'aaa', :parent=>@aa)
578
- @aab = Node.create(:name=>'aab', :parent=>@aa)
579
- @aba = Node.create(:name=>'aba', :parent=>@ab)
580
- @abb = Node.create(:name=>'abb', :parent=>@ab)
581
- @aaaa = Node.create(:name=>'aaaa', :parent=>@aaa)
582
- @aaab = Node.create(:name=>'aaab', :parent=>@aaa)
583
- @aaaaa = Node.create(:name=>'aaaaa', :parent=>@aaaa)
584
- end
585
- after do
586
- @db.drop_table :nodes
728
+ @nodes = []
729
+ @nodes << @a = Node.create(:name=>'a')
730
+ @nodes << @b = Node.create(:name=>'b')
731
+ @nodes << @aa = Node.create(:name=>'aa', :parent=>@a)
732
+ @nodes << @ab = Node.create(:name=>'ab', :parent=>@a)
733
+ @nodes << @ba = Node.create(:name=>'ba', :parent=>@b)
734
+ @nodes << @bb = Node.create(:name=>'bb', :parent=>@b)
735
+ @nodes << @aaa = Node.create(:name=>'aaa', :parent=>@aa)
736
+ @nodes << @aab = Node.create(:name=>'aab', :parent=>@aa)
737
+ @nodes << @aba = Node.create(:name=>'aba', :parent=>@ab)
738
+ @nodes << @abb = Node.create(:name=>'abb', :parent=>@ab)
739
+ @nodes << @aaaa = Node.create(:name=>'aaaa', :parent=>@aaa)
740
+ @nodes << @aaab = Node.create(:name=>'aaab', :parent=>@aaa)
741
+ @nodes << @aaaaa = Node.create(:name=>'aaaaa', :parent=>@aaaa)
742
+ end
743
+ before do
744
+ @nodes.each{|n| n.associations.clear}
745
+ end
746
+ after(:all) do
747
+ @db.drop_table? :nodes
587
748
  Object.send(:remove_const, :Node)
588
749
  end
589
750
 
@@ -659,13 +820,15 @@ if INTEGRATION_DB.dataset.supports_cte?
659
820
  end
660
821
 
661
822
  specify "should work correctly if not all columns are selected" do
662
- Node.plugin :lazy_attributes, :name
663
- @aaaa.descendants.should == [Node.load(:parent_id=>11, :id=>13)]
664
- @aa.ancestors.should == [Node.load(:parent_id=>nil, :id=>1)]
665
- nodes = Node.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
666
- nodes.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>3, :id=>7}, {:parent_id=>nil, :id=>2}].map{|x| Node.load(x)}
667
- nodes[2].descendants.should == [{:parent_id=>2, :id=>5}, {:parent_id=>2, :id=>6}].map{|x| Node.load(x)}
668
- nodes[1].ancestors.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>1, :id=>3}].map{|x| Node.load(x)}
823
+ c = Class.new(Sequel::Model(@db[:nodes]))
824
+ c.plugin :rcte_tree, :order=>:name
825
+ c.plugin :lazy_attributes, :name
826
+ c[:name=>'aaaa'].descendants.should == [c.load(:parent_id=>11, :id=>13)]
827
+ c[:name=>'aa'].ancestors.should == [c.load(:parent_id=>nil, :id=>1)]
828
+ nodes = c.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
829
+ nodes.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>3, :id=>7}, {:parent_id=>nil, :id=>2}].map{|x| c.load(x)}
830
+ nodes[2].descendants.should == [{:parent_id=>2, :id=>5}, {:parent_id=>2, :id=>6}].map{|x| c.load(x)}
831
+ nodes[1].ancestors.should == [{:parent_id=>nil, :id=>1}, {:parent_id=>1, :id=>3}].map{|x| c.load(x)}
669
832
  end
670
833
 
671
834
  specify "should eagerly load descendants to a given level" do
@@ -751,7 +914,7 @@ if INTEGRATION_DB.dataset.supports_cte?
751
914
  nodes[0].associations.fetch(:parent, 1).should == nil
752
915
  nodes[1].associations[:parent].should == @aa
753
916
  nodes[1].associations[:parent].associations[:parent].should == @a
754
- nodes[1].associations[:parent].associations[:parent].associations.fetch(:parent, 1) == nil
917
+ nodes[1].associations[:parent].associations[:parent].associations.fetch(:parent, 1).should == nil
755
918
  nodes[2].associations[:parent].should == @aaaa
756
919
  nodes[2].associations[:parent].associations[:parent].should == @aaa
757
920
  nodes[2].associations[:parent].associations[:parent].associations[:parent].should == @aa
@@ -783,7 +946,7 @@ if INTEGRATION_DB.dataset.supports_cte?
783
946
  end
784
947
 
785
948
  describe "Instance Filters plugin" do
786
- before do
949
+ before(:all) do
787
950
  @db = INTEGRATION_DB
788
951
  @db.create_table!(:items) do
789
952
  primary_key :id
@@ -794,12 +957,15 @@ describe "Instance Filters plugin" do
794
957
  class ::Item < Sequel::Model(@db)
795
958
  plugin :instance_filters
796
959
  end
960
+ end
961
+ before do
962
+ @db[:items].delete
797
963
  @i = Item.create(:name=>'J', :number=>1, :cost=>2)
798
964
  @i.instance_filter(:number=>1)
799
965
  @i.set(:name=>'K')
800
966
  end
801
- after do
802
- @db.drop_table(:items)
967
+ after(:all) do
968
+ @db.drop_table?(:items)
803
969
  Object.send(:remove_const, :Item)
804
970
  end
805
971
 
@@ -843,21 +1009,24 @@ describe "Instance Filters plugin" do
843
1009
  end
844
1010
 
845
1011
  describe "UpdatePrimaryKey plugin" do
846
- before do
1012
+ before(:all) do
847
1013
  @db = INTEGRATION_DB
848
1014
  @db.create_table!(:t) do
849
1015
  Integer :a, :primary_key=>true
850
1016
  Integer :b
851
1017
  end
852
1018
  @ds = @db[:t]
853
- @ds.insert(:a=>1, :b=>3)
854
1019
  @c = Class.new(Sequel::Model(@ds))
855
1020
  @c.set_primary_key(:a)
856
1021
  @c.unrestrict_primary_key
857
1022
  @c.plugin :update_primary_key
858
1023
  end
859
- after do
860
- @db.drop_table(:t)
1024
+ before do
1025
+ @ds.delete
1026
+ @ds.insert(:a=>1, :b=>3)
1027
+ end
1028
+ after(:all) do
1029
+ @db.drop_table?(:t)
861
1030
  end
862
1031
 
863
1032
  specify "should handle regular updates" do
@@ -898,22 +1067,23 @@ describe "UpdatePrimaryKey plugin" do
898
1067
  end
899
1068
 
900
1069
  describe "AssociationPks plugin" do
901
- before do
1070
+ before(:all) do
902
1071
  @db = INTEGRATION_DB
903
- @db.create_table!(:artists) do
1072
+ @db.drop_table?(:albums_tags, :tags, :albums, :artists)
1073
+ @db.create_table(:artists) do
904
1074
  primary_key :id
905
1075
  String :name
906
1076
  end
907
- @db.create_table!(:albums) do
1077
+ @db.create_table(:albums) do
908
1078
  primary_key :id
909
1079
  String :name
910
1080
  foreign_key :artist_id, :artists
911
1081
  end
912
- @db.create_table!(:tags) do
1082
+ @db.create_table(:tags) do
913
1083
  primary_key :id
914
1084
  String :name
915
1085
  end
916
- @db.create_table!(:albums_tags) do
1086
+ @db.create_table(:albums_tags) do
917
1087
  foreign_key :album_id, :albums
918
1088
  foreign_key :tag_id, :tags
919
1089
  end
@@ -927,7 +1097,9 @@ describe "AssociationPks plugin" do
927
1097
  end
928
1098
  class ::Tag < Sequel::Model
929
1099
  end
930
-
1100
+ end
1101
+ before do
1102
+ [:albums_tags, :tags, :albums, :artists].each{|t| @db[t].delete}
931
1103
  @ar1 =@db[:artists].insert(:name=>'YJM')
932
1104
  @ar2 =@db[:artists].insert(:name=>'AS')
933
1105
  @al1 =@db[:albums].insert(:name=>'RF', :artist_id=>@ar1)
@@ -940,8 +1112,8 @@ describe "AssociationPks plugin" do
940
1112
  tids.each{|tid| @db[:albums_tags].insert([aid, tid])}
941
1113
  end
942
1114
  end
943
- after do
944
- @db.drop_table :albums_tags, :tags, :albums, :artists
1115
+ after(:all) do
1116
+ @db.drop_table? :albums_tags, :tags, :albums, :artists
945
1117
  [:Artist, :Album, :Tag].each{|s| Object.send(:remove_const, s)}
946
1118
  end
947
1119
 
@@ -994,9 +1166,9 @@ end
994
1166
 
995
1167
 
996
1168
  describe "List plugin without a scope" do
997
- before do
1169
+ before(:all) do
998
1170
  @db = INTEGRATION_DB
999
- @db.create_table :sites do
1171
+ @db.create_table!(:sites) do
1000
1172
  primary_key :id
1001
1173
  String :name
1002
1174
  Integer :position
@@ -1004,14 +1176,15 @@ describe "List plugin without a scope" do
1004
1176
 
1005
1177
  @c = Class.new(Sequel::Model(@db[:sites]))
1006
1178
  @c.plugin :list
1179
+ end
1180
+ before do
1007
1181
  @c.delete
1008
- @c.create :name => "hig", :position => 3
1009
- @c.create :name => "def", :position => 2
1010
- @c.create :name => "abc", :position => 1
1182
+ @c.create :name => "abc"
1183
+ @c.create :name => "def"
1184
+ @c.create :name => "hig"
1011
1185
  end
1012
-
1013
- after do
1014
- @db.drop_table(:sites)
1186
+ after(:all) do
1187
+ @db.drop_table?(:sites)
1015
1188
  end
1016
1189
 
1017
1190
  it "should return rows in order of position" do
@@ -1067,9 +1240,9 @@ describe "List plugin without a scope" do
1067
1240
  end
1068
1241
 
1069
1242
  describe "List plugin with a scope" do
1070
- before do
1243
+ before(:all) do
1071
1244
  @db = INTEGRATION_DB
1072
- @db.create_table :pages do
1245
+ @db.create_table!(:pages) do
1073
1246
  primary_key :id
1074
1247
  String :name
1075
1248
  Integer :pos
@@ -1078,19 +1251,21 @@ describe "List plugin with a scope" do
1078
1251
 
1079
1252
  @c = Class.new(Sequel::Model(@db[:pages]))
1080
1253
  @c.plugin :list, :field => :pos, :scope => :parent_id
1081
- p1 = @c.create :name => "Hm", :pos => 1, :parent_id => 0
1082
- p2 = @c.create :name => "Ps", :pos => 1, :parent_id => p1.id
1083
- @c.create :name => "P1", :pos => 1, :parent_id => p2.id
1084
- @c.create :name => "P2", :pos => 2, :parent_id => p2.id
1085
- @c.create :name => "P3", :pos => 3, :parent_id => p2.id
1086
- @c.create :name => "Au", :pos => 2, :parent_id => p1.id
1087
1254
  end
1088
-
1089
- after do
1090
- @db.drop_table(:pages)
1255
+ before do
1256
+ @c.delete
1257
+ p1 = @c.create :name => "Hm", :parent_id => 0
1258
+ p2 = @c.create :name => "Ps", :parent_id => p1.id
1259
+ @c.create :name => "P1", :parent_id => p2.id
1260
+ @c.create :name => "P2", :parent_id => p2.id
1261
+ @c.create :name => "P3", :parent_id => p2.id
1262
+ @c.create :name => "Au", :parent_id => p1.id
1263
+ end
1264
+ after(:all) do
1265
+ @db.drop_table?(:pages)
1091
1266
  end
1092
1267
 
1093
- it "should return rows in order of position" do
1268
+ specify "should return rows in order of position" do
1094
1269
  @c.map(:name).should == %w[ Hm Ps Au P1 P2 P3 ]
1095
1270
  end
1096
1271
 
@@ -1111,7 +1286,7 @@ describe "List plugin with a scope" do
1111
1286
  @c[:name => "P3"].next.should == nil
1112
1287
  end
1113
1288
 
1114
- it "should define move_to" do
1289
+ specify "should define move_to" do
1115
1290
  @c[:name => "P2"].move_to(1)
1116
1291
  @c.map(:name).should == %w[ Hm Ps Au P2 P1 P3 ]
1117
1292
 
@@ -1122,7 +1297,7 @@ describe "List plugin with a scope" do
1122
1297
  proc { @c[:name => "P2"].move_to(10) }.should raise_error(Sequel::Error)
1123
1298
  end
1124
1299
 
1125
- it "should define move_to_top and move_to_bottom" do
1300
+ specify "should define move_to_top and move_to_bottom" do
1126
1301
  @c[:name => "Au"].move_to_top
1127
1302
  @c.map(:name).should == %w[ Hm Au Ps P1 P2 P3 ]
1128
1303
 
@@ -1130,7 +1305,7 @@ describe "List plugin with a scope" do
1130
1305
  @c.map(:name).should == %w[ Hm Ps Au P1 P2 P3 ]
1131
1306
  end
1132
1307
 
1133
- it "should define move_up and move_down" do
1308
+ specify "should define move_up and move_down" do
1134
1309
  @c[:name => "P2"].move_up
1135
1310
  @c.map(:name).should == %w[ Hm Ps Au P2 P1 P3 ]
1136
1311
 
@@ -1143,12 +1318,12 @@ describe "List plugin with a scope" do
1143
1318
  end
1144
1319
 
1145
1320
  describe "Sequel::Plugins::Tree" do
1146
- before do
1321
+ before(:all) do
1147
1322
  @db = INTEGRATION_DB
1148
1323
  end
1149
1324
 
1150
1325
  describe "with natural database order" do
1151
- before do
1326
+ before(:all) do
1152
1327
  @db.create_table!(:nodes) do
1153
1328
  Integer :id, :primary_key=>true
1154
1329
  String :name
@@ -1174,8 +1349,8 @@ describe "Sequel::Plugins::Tree" do
1174
1349
  plugin :tree
1175
1350
  end
1176
1351
  end
1177
- after do
1178
- @db.drop_table(:nodes)
1352
+ after(:all) do
1353
+ @db.drop_table?(:nodes)
1179
1354
  Object.send(:remove_const, :Node)
1180
1355
  end
1181
1356
 
@@ -1249,12 +1424,12 @@ describe "Sequel::Plugins::Tree" do
1249
1424
  end
1250
1425
 
1251
1426
  describe "Nodes in specified order" do
1252
- before do
1427
+ before(:all) do
1253
1428
  class ::OrderedNode < Sequel::Model(:nodes)
1254
1429
  plugin :tree, :order => :position
1255
1430
  end
1256
1431
  end
1257
- after do
1432
+ after(:all) do
1258
1433
  Object.send(:remove_const, :OrderedNode)
1259
1434
  end
1260
1435
 
@@ -1272,7 +1447,7 @@ describe "Sequel::Plugins::Tree" do
1272
1447
  end
1273
1448
 
1274
1449
  describe "Lorems in specified order" do
1275
- before do
1450
+ before(:all) do
1276
1451
  @db.create_table!(:lorems) do
1277
1452
  Integer :id, :primary_key=>true
1278
1453
  String :name
@@ -1290,8 +1465,8 @@ describe "Sequel::Plugins::Tree" do
1290
1465
  plugin :tree, :key => :ipsum_id, :order => :neque
1291
1466
  end
1292
1467
  end
1293
- after do
1294
- @db.drop_table(:lorems)
1468
+ after(:all) do
1469
+ @db.drop_table?(:lorems)
1295
1470
  Object.send(:remove_const, :Lorem)
1296
1471
  end
1297
1472
 
@@ -1306,3 +1481,285 @@ describe "Sequel::Plugins::Tree" do
1306
1481
  end
1307
1482
  end
1308
1483
  end
1484
+
1485
+ describe "Sequel::Plugins::PreparedStatements" do
1486
+ before(:all) do
1487
+ @db = INTEGRATION_DB
1488
+ @db.create_table!(:ps_test) do
1489
+ primary_key :id
1490
+ String :name
1491
+ Integer :i
1492
+ end
1493
+ @c = Class.new(Sequel::Model(@db[:ps_test]))
1494
+ @c.plugin :prepared_statements_with_pk
1495
+ end
1496
+ before do
1497
+ @c.delete
1498
+ @foo = @c.create(:name=>'foo', :i=>10)
1499
+ @bar = @c.create(:name=>'bar', :i=>20)
1500
+ end
1501
+ after(:all) do
1502
+ @db.drop_table?(:ps_test)
1503
+ end
1504
+
1505
+ it "should work with looking up using Model.[]" do
1506
+ @c[@foo.id].should == @foo
1507
+ @c[@bar.id].should == @bar
1508
+ @c[0].should == nil
1509
+ @c[nil].should == nil
1510
+ end
1511
+
1512
+ it "should work with looking up using Dataset#with_pk" do
1513
+ @c.dataset.with_pk(@foo.id).should == @foo
1514
+ @c.dataset.with_pk(@bar.id).should == @bar
1515
+ @c.dataset.with_pk(0).should == nil
1516
+ @c.dataset.with_pk(nil).should == nil
1517
+
1518
+ @c.dataset.filter(:i=>0).with_pk(@foo.id).should == nil
1519
+ @c.dataset.filter(:i=>10).with_pk(@foo.id).should == @foo
1520
+ @c.dataset.filter(:i=>20).with_pk(@bar.id).should == @bar
1521
+ @c.dataset.filter(:i=>10).with_pk(nil).should == nil
1522
+ @c.dataset.filter(:name=>'foo').with_pk(@foo.id).should == @foo
1523
+ @c.dataset.filter(:name=>'bar').with_pk(@bar.id).should == @bar
1524
+ @c.dataset.filter(:name=>'baz').with_pk(@bar.id).should == nil
1525
+ @c.dataset.filter(:name=>'bar').with_pk(nil).should == nil
1526
+ end
1527
+
1528
+ it "should work with Model#destroy" do
1529
+ @foo.destroy
1530
+ @bar.destroy
1531
+ @c[@foo.id].should == nil
1532
+ @c[@bar.id].should == nil
1533
+ end
1534
+
1535
+ it "should work with Model#update" do
1536
+ @foo.update(:name=>'foo2', :i=>30)
1537
+ @c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo2', :i=>30)
1538
+ @foo.update(:name=>'foo3')
1539
+ @c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>30)
1540
+ @foo.update(:i=>40)
1541
+ @c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>40)
1542
+ @foo.update(:i=>nil)
1543
+ @c[@foo.id].should == @c.load(:id=>@foo.id, :name=>'foo3', :i=>nil)
1544
+ end
1545
+
1546
+ it "should work with Model#create" do
1547
+ o = @c.create(:name=>'foo2', :i=>30)
1548
+ @c[o.id].should == @c.load(:id=>o.id, :name=>'foo2', :i=>30)
1549
+ o = @c.create(:name=>'foo2')
1550
+ @c[o.id].should == @c.load(:id=>o.id, :name=>'foo2', :i=>nil)
1551
+ o = @c.create(:i=>30)
1552
+ @c[o.id].should == @c.load(:id=>o.id, :name=>nil, :i=>30)
1553
+ o = @c.create(:name=>nil, :i=>40)
1554
+ @c[o.id].should == @c.load(:id=>o.id, :name=>nil, :i=>40)
1555
+ end
1556
+ end
1557
+
1558
+ describe "Caching plugins" do
1559
+ before(:all) do
1560
+ @db = INTEGRATION_DB
1561
+ @db.drop_table?(:albums, :artists)
1562
+ @db.create_table(:artists) do
1563
+ primary_key :id
1564
+ end
1565
+ @db.create_table(:albums) do
1566
+ primary_key :id
1567
+ foreign_key :artist_id, :artists
1568
+ end
1569
+ @db[:artists].insert
1570
+ @db[:albums].insert(:artist_id=>1)
1571
+ end
1572
+ before do
1573
+ @Album = Class.new(Sequel::Model(@db[:albums]))
1574
+ @Album.plugin :many_to_one_pk_lookup
1575
+ end
1576
+ after(:all) do
1577
+ @db.drop_table?(:albums, :artists)
1578
+ end
1579
+
1580
+ shared_examples_for "a caching plugin" do
1581
+ it "should work with looking up using Model.[]" do
1582
+ @Artist[1].should equal(@Artist[1])
1583
+ @Artist[:id=>1].should == @Artist[1]
1584
+ @Artist[0].should == nil
1585
+ @Artist[nil].should == nil
1586
+ end
1587
+
1588
+ it "should work with lookup up many_to_one associated objects" do
1589
+ a = @Artist[1]
1590
+ @Album.first.artist.should equal(a)
1591
+ end
1592
+ end
1593
+
1594
+ describe "caching plugin" do
1595
+ before do
1596
+ @cache_class = Class.new(Hash) do
1597
+ def set(k, v, ttl) self[k] = v end
1598
+ alias get []
1599
+ end
1600
+ @cache = @cache_class.new
1601
+
1602
+ @Artist = Class.new(Sequel::Model(@db[:artists]))
1603
+ @Artist.plugin :caching, @cache
1604
+ @Album.many_to_one :artist, :class=>@Artist
1605
+ end
1606
+
1607
+ it_should_behave_like "a caching plugin"
1608
+ end
1609
+
1610
+ describe "static_cache plugin" do
1611
+ before do
1612
+ @Artist = Class.new(Sequel::Model(@db[:artists]))
1613
+ @Artist.plugin :static_cache
1614
+ @Album.many_to_one :artist, :class=>@Artist
1615
+ end
1616
+
1617
+ it_should_behave_like "a caching plugin"
1618
+ end
1619
+ end
1620
+
1621
+ describe "Sequel::Plugins::ConstraintValidations" do
1622
+ before(:all) do
1623
+ @db = INTEGRATION_DB
1624
+ @db.extension(:constraint_validations)
1625
+ @db.create_constraint_validations_table
1626
+ @ds = @db[:cv_test]
1627
+ @regexp = regexp = @db.dataset.supports_regexp?
1628
+ @validate_block = proc do
1629
+ presence :pre, :name=>:p
1630
+ exact_length 5, :exactlen, :name=>:el
1631
+ min_length 5, :minlen, :name=>:minl
1632
+ max_length 5, :maxlen, :name=>:maxl
1633
+ length_range 3..5, :lenrange, :name=>:lr
1634
+ if regexp
1635
+ format /^foo\d+/, :form, :name=>:f
1636
+ end
1637
+ like 'foo%', :lik, :name=>:l
1638
+ ilike 'foo%', :ilik, :name=>:il
1639
+ includes %w'abc def', :inc, :name=>:i
1640
+ unique :uniq, :name=>:u
1641
+ max_length 6, :minlen, :name=>:maxl2
1642
+ end
1643
+ @valid_row = {:pre=>'a', :exactlen=>'12345', :minlen=>'12345', :maxlen=>'12345', :lenrange=>'1234', :lik=>'fooabc', :ilik=>'FooABC', :inc=>'abc', :uniq=>'u'}
1644
+ @violations = [
1645
+ [:pre, [nil, '', ' ']],
1646
+ [:exactlen, [nil, '', '1234', '123456']],
1647
+ [:minlen, [nil, '', '1234']],
1648
+ [:maxlen, [nil, '123456']],
1649
+ [:lenrange, [nil, '', '12', '123456']],
1650
+ [:lik, [nil, '', 'fo', 'fotabc', 'FOOABC']],
1651
+ [:ilik, [nil, '', 'fo', 'fotabc']],
1652
+ [:inc, [nil, '', 'ab', 'abcd']],
1653
+ ]
1654
+
1655
+ if @regexp
1656
+ @valid_row[:form] = 'foo1'
1657
+ @violations << [:form, [nil, '', 'foo', 'fooa']]
1658
+ end
1659
+ end
1660
+ after(:all) do
1661
+ @db.drop_constraint_validations_table
1662
+ end
1663
+
1664
+ shared_examples_for "constraint validations" do
1665
+ cspecify "should set up constraints that work even outside the model", :mysql do
1666
+ proc{@ds.insert(@valid_row)}.should_not raise_error
1667
+
1668
+ # Test for unique constraint
1669
+ proc{@ds.insert(@valid_row)}.should raise_error(Sequel::DatabaseError)
1670
+
1671
+ @ds.delete
1672
+ @violations.each do |col, vals|
1673
+ try = @valid_row.dup
1674
+ vals += ['1234567'] if col == :minlen
1675
+ vals.each do |val|
1676
+ try[col] = val
1677
+ proc{@ds.insert(try)}.should raise_error(Sequel::DatabaseError)
1678
+ end
1679
+ end
1680
+
1681
+ # Test for dropping of constraint
1682
+ @db.alter_table(:cv_test){validate{drop :maxl2}}
1683
+ proc{@ds.insert(@valid_row.merge(:minlen=>'1234567'))}.should_not raise_error
1684
+ end
1685
+
1686
+ it "should set up automatic validations inside the model" do
1687
+ c = Class.new(Sequel::Model(@ds))
1688
+ c.plugin :constraint_validations
1689
+ c.delete
1690
+ proc{c.create(@valid_row)}.should_not raise_error
1691
+
1692
+ # Test for unique validation
1693
+ c.new(@valid_row).should_not be_valid
1694
+
1695
+ c.delete
1696
+ @violations.each do |col, vals|
1697
+ try = @valid_row.dup
1698
+ vals.each do |val|
1699
+ try[col] = val
1700
+ c.new(try).should_not be_valid
1701
+ end
1702
+ end
1703
+ end
1704
+ end
1705
+
1706
+ describe "via create_table" do
1707
+ before(:all) do
1708
+ regexp = @regexp
1709
+ validate_block = @validate_block
1710
+ @db.create_table!(:cv_test) do
1711
+ primary_key :id
1712
+ String :pre
1713
+ String :exactlen
1714
+ String :minlen
1715
+ String :maxlen
1716
+ String :lenrange
1717
+ if regexp
1718
+ String :form
1719
+ end
1720
+ String :lik
1721
+ String :ilik
1722
+ String :inc
1723
+ String :uniq, :null=>false
1724
+ validate(&validate_block)
1725
+ end
1726
+ end
1727
+ after(:all) do
1728
+ @db.drop_table?(:cv_test)
1729
+ @db.drop_constraint_validations_for(:table=>:cv_test)
1730
+ end
1731
+
1732
+ it_should_behave_like "constraint validations"
1733
+ end
1734
+
1735
+ describe "via alter_table" do
1736
+ before(:all) do
1737
+ regexp = @regexp
1738
+ validate_block = @validate_block
1739
+ @db.create_table!(:cv_test) do
1740
+ primary_key :id
1741
+ String :lik
1742
+ String :ilik
1743
+ String :inc
1744
+ String :uniq, :null=>false
1745
+ end
1746
+ @db.alter_table(:cv_test) do
1747
+ add_column :pre, String
1748
+ add_column :exactlen, String
1749
+ add_column :minlen, String
1750
+ add_column :maxlen, String
1751
+ add_column :lenrange, String
1752
+ if regexp
1753
+ add_column :form, String
1754
+ end
1755
+ validate(&validate_block)
1756
+ end
1757
+ end
1758
+ after(:all) do
1759
+ @db.drop_table?(:cv_test)
1760
+ @db.drop_constraint_validations_for(:table=>:cv_test)
1761
+ end
1762
+
1763
+ it_should_behave_like "constraint validations"
1764
+ end
1765
+ end