sequel 3.21.0 → 3.41.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 (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -2,14 +2,20 @@ require 'rubygems'
2
2
  require 'logger'
3
3
  unless Object.const_defined?('Sequel')
4
4
  $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
5
- require 'sequel'
6
- Sequel.quote_identifiers = false
5
+ require 'sequel/no_core_ext'
7
6
  end
8
7
  begin
9
8
  require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'spec_config.rb')
10
9
  rescue LoadError
11
10
  end
12
11
 
12
+ if ENV['SEQUEL_COLUMNS_INTROSPECTION']
13
+ Sequel.extension :columns_introspection
14
+ Sequel::Dataset.introspect_all_columns
15
+ end
16
+
17
+ Sequel::Model.cache_anonymous_models = false
18
+
13
19
  class Sequel::Database
14
20
  def log_duration(duration, message)
15
21
  log_info(message)
@@ -26,11 +32,8 @@ end
26
32
  end
27
33
  end
28
34
 
29
- def self.log_specify(message, &block)
30
- specify(message){log{instance_eval(&block)}}
31
- end
32
-
33
35
  def self.cspecify(message, *checked, &block)
36
+ return specify(message, &block) if ENV['SEQUEL_NO_PENDING']
34
37
  pending = false
35
38
  checked.each do |c|
36
39
  case c
@@ -48,4 +51,11 @@ end
48
51
  specify(message, &block)
49
52
  end
50
53
  end
54
+
55
+ def check_sqls
56
+ yield unless ENV['SEQUEL_NO_CHECK_SQLS']
57
+ end
58
+ def self.check_sqls
59
+ yield unless ENV['SEQUEL_NO_CHECK_SQLS']
60
+ end
51
61
  end
@@ -1,7 +1,13 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
2
 
3
3
  unless defined?(SQLITE_DB)
4
- SQLITE_URL = 'sqlite:/' unless defined? SQLITE_URL
4
+ unless defined? SQLITE_URL
5
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
6
+ SQLITE_URL = 'jdbc:sqlite::memory:'
7
+ else
8
+ SQLITE_URL = 'sqlite:/'
9
+ end
10
+ end
5
11
  SQLITE_DB = Sequel.connect(ENV['SEQUEL_SQLITE_SPEC_DB']||SQLITE_URL)
6
12
  end
7
13
  INTEGRATION_DB = SQLITE_DB unless defined?(INTEGRATION_DB)
@@ -12,7 +18,9 @@ describe "An SQLite database" do
12
18
  @fk = @db.foreign_keys
13
19
  end
14
20
  after do
21
+ @db.drop_table?(:fk)
15
22
  @db.foreign_keys = @fk
23
+ @db.case_sensitive_like = true
16
24
  Sequel.datetime_class = Time
17
25
  end
18
26
 
@@ -38,6 +46,25 @@ describe "An SQLite database" do
38
46
  end
39
47
  end
40
48
 
49
+ specify "should respect case sensitive like false" do
50
+ @db.case_sensitive_like = false
51
+ @db.get(Sequel.like('a', 'A')).to_s.should == '1'
52
+ end
53
+
54
+ specify "should respect case sensitive like true" do
55
+ @db.case_sensitive_like = true
56
+ @db.get(Sequel.like('a', 'A')).to_s.should == '0'
57
+ end
58
+
59
+ specify "should support casting to Date by using the date function" do
60
+ @db.get(Sequel.cast('2012-10-20 11:12:13', Date)).should == '2012-10-20'
61
+ end
62
+
63
+ specify "should support casting to Time or DateTime by using the datetime function" do
64
+ @db.get(Sequel.cast('2012-10-20', Time)).should == '2012-10-20 00:00:00'
65
+ @db.get(Sequel.cast('2012-10-20', DateTime)).should == '2012-10-20 00:00:00'
66
+ end
67
+
41
68
  specify "should provide the SQLite version as an integer" do
42
69
  @db.sqlite_version.should be_a_kind_of(Integer)
43
70
  end
@@ -48,16 +75,14 @@ describe "An SQLite database" do
48
75
  @db.foreign_keys = false
49
76
  end
50
77
 
51
- if SQLITE_DB.sqlite_version >= 30619
52
- specify "should enforce foreign key integrity if foreign_keys pragma is set" do
53
- @db.foreign_keys = true
54
- @db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
55
- @db[:fk].insert(1, nil)
56
- @db[:fk].insert(2, 1)
57
- @db[:fk].insert(3, 3)
58
- proc{@db[:fk].insert(4, 5)}.should raise_error(Sequel::Error)
59
- end
60
- end
78
+ specify "should enforce foreign key integrity if foreign_keys pragma is set" do
79
+ @db.foreign_keys = true
80
+ @db.create_table!(:fk){primary_key :id; foreign_key :parent_id, :fk}
81
+ @db[:fk].insert(1, nil)
82
+ @db[:fk].insert(2, 1)
83
+ @db[:fk].insert(3, 3)
84
+ proc{@db[:fk].insert(4, 5)}.should raise_error(Sequel::Error)
85
+ end if SQLITE_DB.sqlite_version >= 30619
61
86
 
62
87
  specify "should not enforce foreign key integrity if foreign_keys pragma is unset" do
63
88
  @db.foreign_keys = false
@@ -66,14 +91,23 @@ describe "An SQLite database" do
66
91
  @db[:fk].all.should == [{:id=>1, :parent_id=>2}]
67
92
  end
68
93
 
94
+ specify "should support a use_timestamp_timezones setting" do
95
+ @db.create_table!(:fk){Time :time}
96
+ @db[:fk].insert(Time.now)
97
+ @db[:fk].get(Sequel.cast(:time, String)).should =~ /[-+]\d\d\d\d\z/
98
+ @db.use_timestamp_timezones = false
99
+ @db[:fk].delete
100
+ @db[:fk].insert(Time.now)
101
+ @db[:fk].get(Sequel.cast(:time, String)).should_not =~ /[-+]\d\d\d\d\z/
102
+ @db.use_timestamp_timezones = true
103
+ end
104
+
69
105
  specify "should provide a list of existing tables" do
70
- @db.drop_table(:testing) rescue nil
106
+ @db.drop_table?(:fk)
71
107
  @db.tables.should be_a_kind_of(Array)
72
- @db.tables.should_not include(:testing)
73
- @db.create_table! :testing do
74
- text :name
75
- end
76
- @db.tables.should include(:testing)
108
+ @db.tables.should_not include(:fk)
109
+ @db.create_table!(:fk){String :name}
110
+ @db.tables.should include(:fk)
77
111
  end
78
112
 
79
113
  specify "should support getting and setting the synchronous pragma" do
@@ -99,23 +133,23 @@ describe "An SQLite database" do
99
133
  end
100
134
 
101
135
  cspecify "should support timestamps and datetimes and respect datetime_class", :do, :jdbc, :amalgalite, :swift do
102
- @db.create_table!(:time){timestamp :t; datetime :d}
136
+ @db.create_table!(:fk){timestamp :t; datetime :d}
103
137
  t1 = Time.at(1)
104
- @db[:time] << {:t => t1, :d => t1}
105
- @db[:time].map(:t).should == [t1]
106
- @db[:time].map(:d).should == [t1]
138
+ @db[:fk] << {:t => t1, :d => t1}
139
+ @db[:fk].map(:t).should == [t1]
140
+ @db[:fk].map(:d).should == [t1]
107
141
  Sequel.datetime_class = DateTime
108
142
  t2 = Sequel.string_to_datetime(t1.iso8601)
109
- @db[:time].map(:t).should == [t2]
110
- @db[:time].map(:d).should == [t2]
143
+ @db[:fk].map(:t).should == [t2]
144
+ @db[:fk].map(:d).should == [t2]
111
145
  end
112
146
 
113
147
  specify "should support sequential primary keys" do
114
- @db.create_table!(:with_pk) {primary_key :id; text :name}
115
- @db[:with_pk] << {:name => 'abc'}
116
- @db[:with_pk] << {:name => 'def'}
117
- @db[:with_pk] << {:name => 'ghi'}
118
- @db[:with_pk].order(:name).all.should == [
148
+ @db.create_table!(:fk) {primary_key :id; text :name}
149
+ @db[:fk] << {:name => 'abc'}
150
+ @db[:fk] << {:name => 'def'}
151
+ @db[:fk] << {:name => 'ghi'}
152
+ @db[:fk].order(:name).all.should == [
119
153
  {:id => 1, :name => 'abc'},
120
154
  {:id => 2, :name => 'def'},
121
155
  {:id => 3, :name => 'ghi'}
@@ -123,68 +157,147 @@ describe "An SQLite database" do
123
157
  end
124
158
 
125
159
  specify "should correctly parse the schema" do
126
- @db.create_table!(:time2) {timestamp :t}
127
- @db.schema(:time2, :reload=>true).should == [[:t, {:type=>:datetime, :allow_null=>true, :default=>nil, :ruby_default=>nil, :db_type=>"timestamp", :primary_key=>false}]]
160
+ @db.create_table!(:fk) {timestamp :t}
161
+ @db.schema(:fk, :reload=>true).should == [[:t, {:type=>:datetime, :allow_null=>true, :default=>nil, :ruby_default=>nil, :db_type=>"timestamp", :primary_key=>false}]]
162
+ end
163
+
164
+ specify "should handle and return BigDecimal values for numeric columns" do
165
+ SQLITE_DB.create_table!(:fk){numeric :d}
166
+ d = SQLITE_DB[:fk]
167
+ d.insert(:d=>BigDecimal.new('80.0'))
168
+ d.insert(:d=>BigDecimal.new('NaN'))
169
+ d.insert(:d=>BigDecimal.new('Infinity'))
170
+ d.insert(:d=>BigDecimal.new('-Infinity'))
171
+ ds = d.all
172
+ ds.shift.should == {:d=>BigDecimal.new('80.0')}
173
+ ds.map{|x| x[:d].to_s}.should == %w'NaN Infinity -Infinity'
174
+ SQLITE_DB
128
175
  end
129
176
  end
130
177
 
131
- describe "An SQLite dataset" do
178
+ describe "SQLite type conversion" do
132
179
  before do
133
- @d = SQLITE_DB[:items]
180
+ @db = SQLITE_DB
181
+ @integer_booleans = @db.integer_booleans
182
+ @db.integer_booleans = true
183
+ @ds = @db[:items]
184
+ @db.drop_table?(:items)
185
+ end
186
+ after do
187
+ @db.integer_booleans = @integer_booleans
188
+ Sequel.datetime_class = Time
189
+ @db.drop_table?(:items)
134
190
  end
135
191
 
136
- specify "should handle string pattern matches correctly" do
137
- @d.literal(:x.like('a')).should == "(x LIKE 'a')"
138
- @d.literal(~:x.like('a')).should == "NOT (x LIKE 'a')"
139
- @d.literal(:x.ilike('a')).should == "(x LIKE 'a')"
140
- @d.literal(~:x.ilike('a')).should == "NOT (x LIKE 'a')"
192
+ specify "should handle integers in boolean columns" do
193
+ @db.create_table(:items){TrueClass :a}
194
+ @db[:items].insert(false)
195
+ @db[:items].select_map(:a).should == [false]
196
+ @db[:items].select_map(Sequel.expr(:a)+:a).should == [0]
197
+ @db[:items].update(:a=>true)
198
+ @db[:items].select_map(:a).should == [true]
199
+ @db[:items].select_map(Sequel.expr(:a)+:a).should == [2]
200
+ end
201
+
202
+ specify "should handle integers/floats/strings/decimals in numeric/decimal columns" do
203
+ @db.create_table(:items){Numeric :a}
204
+ @db[:items].insert(100)
205
+ @db[:items].select_map(:a).should == [BigDecimal.new('100')]
206
+ @db[:items].get(:a).should be_a_kind_of(BigDecimal)
207
+
208
+ @db[:items].update(:a=>100.1)
209
+ @db[:items].select_map(:a).should == [BigDecimal.new('100.1')]
210
+ @db[:items].get(:a).should be_a_kind_of(BigDecimal)
211
+
212
+ @db[:items].update(:a=>'100.1')
213
+ @db[:items].select_map(:a).should == [BigDecimal.new('100.1')]
214
+ @db[:items].get(:a).should be_a_kind_of(BigDecimal)
215
+
216
+ @db[:items].update(:a=>BigDecimal.new('100.1'))
217
+ @db[:items].select_map(:a).should == [BigDecimal.new('100.1')]
218
+ @db[:items].get(:a).should be_a_kind_of(BigDecimal)
219
+ end
220
+
221
+ specify "should handle integer/float date columns as julian date" do
222
+ @db.create_table(:items){Date :a}
223
+ i = 2455979
224
+ @db[:items].insert(i)
225
+ @db[:items].first.should == {:a=>Date.jd(i)}
226
+ @db[:items].update(:a=>2455979.1)
227
+ @db[:items].first.should == {:a=>Date.jd(i)}
228
+ end
229
+
230
+ specify "should handle integer/float time columns as seconds" do
231
+ @db.create_table(:items){Time :a, :only_time=>true}
232
+ @db[:items].insert(3661)
233
+ @db[:items].first.should == {:a=>Sequel::SQLTime.create(1, 1, 1)}
234
+ @db[:items].update(:a=>3661.000001)
235
+ @db[:items].first.should == {:a=>Sequel::SQLTime.create(1, 1, 1, 1)}
236
+ end
237
+
238
+ specify "should handle integer datetime columns as unix timestamp" do
239
+ @db.create_table(:items){DateTime :a}
240
+ i = 1329860756
241
+ @db[:items].insert(i)
242
+ @db[:items].first.should == {:a=>Time.at(i)}
243
+ Sequel.datetime_class = DateTime
244
+ @db[:items].first.should == {:a=>DateTime.strptime(i.to_s, '%s')}
141
245
  end
142
246
 
143
- specify "should raise errors if given a regexp pattern match" do
144
- proc{@d.literal(:x.like(/a/))}.should raise_error(Sequel::Error)
145
- proc{@d.literal(~:x.like(/a/))}.should raise_error(Sequel::Error)
146
- proc{@d.literal(:x.like(/a/i))}.should raise_error(Sequel::Error)
147
- proc{@d.literal(~:x.like(/a/i))}.should raise_error(Sequel::Error)
247
+ specify "should handle float datetime columns as julian date" do
248
+ @db.create_table(:items){DateTime :a}
249
+ i = 2455979.5
250
+ @db[:items].insert(i)
251
+ @db[:items].first.should == {:a=>Time.at(1329825600)}
252
+ Sequel.datetime_class = DateTime
253
+ @db[:items].first.should == {:a=>DateTime.jd(2455979.5)}
148
254
  end
149
- end
150
255
 
151
- describe "An SQLite numeric column" do
152
- specify "should handle and return BigDecimal values" do
153
- SQLITE_DB.create_table!(:d){numeric :d}
154
- d = SQLITE_DB[:d]
155
- d.insert(:d=>BigDecimal.new('80.0'))
156
- d.insert(:d=>BigDecimal.new('NaN'))
157
- d.insert(:d=>BigDecimal.new('Infinity'))
158
- d.insert(:d=>BigDecimal.new('-Infinity'))
159
- ds = d.all
160
- ds.shift.should == {:d=>BigDecimal.new('80.0')}
161
- ds.map{|x| x[:d].to_s}.should == %w'NaN Infinity -Infinity'
256
+ specify "should handle integer/float blob columns" do
257
+ @db.create_table(:items){File :a}
258
+ @db[:items].insert(1)
259
+ @db[:items].first.should == {:a=>Sequel::SQL::Blob.new('1')}
260
+ @db[:items].update(:a=>'1.1')
261
+ @db[:items].first.should == {:a=>Sequel::SQL::Blob.new(1.1.to_s)}
262
+ end
263
+ end if SQLITE_DB.adapter_scheme == :sqlite
264
+
265
+ describe "An SQLite dataset" do
266
+ before do
267
+ @d = SQLITE_DB[:items]
268
+ end
269
+
270
+ specify "should raise errors if given a regexp pattern match" do
271
+ proc{@d.literal(Sequel.expr(:x).like(/a/))}.should raise_error(Sequel::Error)
272
+ proc{@d.literal(~Sequel.expr(:x).like(/a/))}.should raise_error(Sequel::Error)
273
+ proc{@d.literal(Sequel.expr(:x).like(/a/i))}.should raise_error(Sequel::Error)
274
+ proc{@d.literal(~Sequel.expr(:x).like(/a/i))}.should raise_error(Sequel::Error)
162
275
  end
163
276
  end
164
277
 
165
278
  describe "An SQLite dataset AS clause" do
166
279
  specify "should use a string literal for :col___alias" do
167
- SQLITE_DB.literal(:c___a).should == "c AS 'a'"
280
+ SQLITE_DB.literal(:c___a).should == "`c` AS 'a'"
168
281
  end
169
282
 
170
283
  specify "should use a string literal for :table__col___alias" do
171
- SQLITE_DB.literal(:t__c___a).should == "t.c AS 'a'"
284
+ SQLITE_DB.literal(:t__c___a).should == "`t`.`c` AS 'a'"
172
285
  end
173
286
 
174
287
  specify "should use a string literal for :column.as(:alias)" do
175
- SQLITE_DB.literal(:c.as(:a)).should == "c AS 'a'"
288
+ SQLITE_DB.literal(Sequel.as(:c, :a)).should == "`c` AS 'a'"
176
289
  end
177
290
 
178
291
  specify "should use a string literal in the SELECT clause" do
179
- SQLITE_DB[:t].select(:c___a).sql.should == "SELECT c AS 'a' FROM t"
292
+ SQLITE_DB[:t].select(:c___a).sql.should == "SELECT `c` AS 'a' FROM `t`"
180
293
  end
181
294
 
182
295
  specify "should use a string literal in the FROM clause" do
183
- SQLITE_DB[:t___a].sql.should == "SELECT * FROM t AS 'a'"
296
+ SQLITE_DB[:t___a].sql.should == "SELECT * FROM `t` AS 'a'"
184
297
  end
185
298
 
186
299
  specify "should use a string literal in the JOIN clause" do
187
- SQLITE_DB[:t].join_table(:natural, :j, nil, :a).sql.should == "SELECT * FROM t NATURAL JOIN j AS 'a'"
300
+ SQLITE_DB[:t].join_table(:natural, :j, nil, :a).sql.should == "SELECT * FROM `t` NATURAL JOIN `j` AS 'a'"
188
301
  end
189
302
  end
190
303
 
@@ -204,10 +317,10 @@ describe "SQLite::Dataset#delete" do
204
317
 
205
318
  specify "should return the number of records affected when filtered" do
206
319
  @d.count.should == 3
207
- @d.filter(:value.sql_number < 3).delete.should == 1
320
+ @d.filter{value < 3}.delete.should == 1
208
321
  @d.count.should == 2
209
322
 
210
- @d.filter(:value.sql_number < 3).delete.should == 0
323
+ @d.filter{value < 3}.delete.should == 0
211
324
  @d.count.should == 2
212
325
  end
213
326
 
@@ -261,7 +374,7 @@ describe "SQLite dataset" do
261
374
  @d << {:name => 'ghi', :value => 7.89}
262
375
  end
263
376
  after do
264
- SQLITE_DB.drop_table(:test, :items)
377
+ SQLITE_DB.drop_table?(:test, :items)
265
378
  end
266
379
 
267
380
  specify "should be able to insert from a subquery" do
@@ -272,13 +385,13 @@ describe "SQLite dataset" do
272
385
  end
273
386
 
274
387
  specify "should support #explain" do
275
- SQLITE_DB[:test].explain.should be_a_kind_of(Array)
388
+ SQLITE_DB[:test].explain.should be_a_kind_of(String)
276
389
  end
277
390
 
278
391
  specify "should have #explain work when identifier_output_method is modified" do
279
392
  ds = SQLITE_DB[:test]
280
393
  ds.identifier_output_method = :upcase
281
- ds.explain.should be_a_kind_of(Array)
394
+ ds.explain.should be_a_kind_of(String)
282
395
  end
283
396
  end
284
397
 
@@ -290,6 +403,9 @@ describe "A SQLite database" do
290
403
  integer :value
291
404
  end
292
405
  end
406
+ after do
407
+ @db.drop_table?(:test2)
408
+ end
293
409
 
294
410
  specify "should support add_column operations" do
295
411
  @db.add_column :test2, :xyz, :text
@@ -313,6 +429,15 @@ describe "A SQLite database" do
313
429
  @db[:test2].first.should == {:name => 'mmm'}
314
430
  end
315
431
 
432
+ specify "should keep a composite primary key when dropping columns" do
433
+ @db.create_table!(:test2){Integer :a; Integer :b; Integer :c; primary_key [:a, :b]}
434
+ @db.drop_column :test2, :c
435
+ @db[:test2].columns.should == [:a, :b]
436
+ @db[:test2] << {:a=>1, :b=>2}
437
+ @db[:test2] << {:a=>2, :b=>3}
438
+ proc{@db[:test2] << {:a=>2, :b=>3}}.should raise_error(Sequel::Error)
439
+ end
440
+
316
441
  specify "should keep column attributes when dropping a column" do
317
442
  @db.create_table! :test3 do
318
443
  primary_key :id
@@ -357,7 +482,7 @@ describe "A SQLite database" do
357
482
  @db[:test].filter(:name => 'foo').update(:id=>100)
358
483
  @db[:test3][:name => 'abc'][:test_id].should == 100
359
484
 
360
- @db.drop_table :test, :test3
485
+ @db.drop_table? :test, :test3
361
486
  end
362
487
  end
363
488
 
@@ -395,7 +520,7 @@ describe "A SQLite database" do
395
520
  specify "should handle quoted tables when dropping or renaming columns" do
396
521
  @db.quote_identifiers = true
397
522
  table_name = "T T"
398
- @db.drop_table(table_name) rescue nil
523
+ @db.drop_table?(table_name)
399
524
  @db.create_table! table_name do
400
525
  Integer :"s s"
401
526
  Integer :"i i"
@@ -407,19 +532,21 @@ describe "A SQLite database" do
407
532
  @db.from(table_name).all.should == [{:"s s"=>1}]
408
533
  @db.rename_column table_name, :"s s", :"t t"
409
534
  @db.from(table_name).all.should == [{:"t t"=>1}]
535
+ @db.drop_table?(table_name)
410
536
  end
411
537
 
412
538
  specify "should choose a temporary table name that isn't already used when dropping or renaming columns" do
413
539
  sqls = []
414
540
  @db.loggers << (l=Class.new{%w'info error'.each{|m| define_method(m){|sql| sqls << sql}}}.new)
415
- @db.create_table! :test3 do
541
+ @db.tables.each{|t| @db.drop_table(t) if t.to_s =~ /test3/}
542
+ @db.create_table :test3 do
416
543
  Integer :h
417
544
  Integer :i
418
545
  end
419
- @db.create_table! :test3_backup0 do
546
+ @db.create_table :test3_backup0 do
420
547
  Integer :j
421
548
  end
422
- @db.create_table! :test3_backup1 do
549
+ @db.create_table :test3_backup1 do
423
550
  Integer :k
424
551
  end
425
552
 
@@ -428,25 +555,26 @@ describe "A SQLite database" do
428
555
  @db[:test3_backup1].columns.should == [:k]
429
556
  sqls.clear
430
557
  @db.drop_column(:test3, :i)
431
- sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup2/}.should == true
432
- sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup[01]/}.should == false
558
+ sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup2/}.should == true
559
+ sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup[01]/}.should == false
433
560
  @db[:test3].columns.should == [:h]
434
561
  @db[:test3_backup0].columns.should == [:j]
435
562
  @db[:test3_backup1].columns.should == [:k]
436
563
 
437
- @db.create_table! :test3_backup2 do
564
+ @db.create_table :test3_backup2 do
438
565
  Integer :l
439
566
  end
440
567
 
441
568
  sqls.clear
442
569
  @db.rename_column(:test3, :h, :i)
443
- sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup3/}.should == true
444
- sqls.any?{|x| x =~ /\ACREATE TABLE.*test3_backup[012]/}.should == false
570
+ sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup3/}.should == true
571
+ sqls.any?{|x| x =~ /\AALTER TABLE.*test3.*RENAME TO.*test3_backup[012]/}.should == false
445
572
  @db[:test3].columns.should == [:i]
446
573
  @db[:test3_backup0].columns.should == [:j]
447
574
  @db[:test3_backup1].columns.should == [:k]
448
575
  @db[:test3_backup2].columns.should == [:l]
449
576
  @db.loggers.delete(l)
577
+ @db.drop_table?(:test3, :test3_backup0, :test3_backup1, :test3_backup2)
450
578
  end
451
579
 
452
580
  specify "should support add_index" do
@@ -467,4 +595,37 @@ describe "A SQLite database" do
467
595
  @db.drop_column :a, :b
468
596
  @db.indexes(:a).should == {:a_a_index=>{:unique=>false, :columns=>[:a]}}
469
597
  end
470
- end
598
+
599
+ specify "should have support for various #transaction modes" do
600
+ sqls = []
601
+ @db.loggers << (l=Class.new{%w'info error'.each{|m| define_method(m){|sql| sqls << sql}}}.new)
602
+
603
+ @db.transaction(:mode => :immediate) do
604
+ sqls.last.should == "BEGIN IMMEDIATE TRANSACTION"
605
+ end
606
+ @db.transaction(:mode => :exclusive) do
607
+ sqls.last.should == "BEGIN EXCLUSIVE TRANSACTION"
608
+ end
609
+ @db.transaction(:mode => :deferred) do
610
+ sqls.last.should == "BEGIN DEFERRED TRANSACTION"
611
+ end
612
+ @db.transaction do
613
+ sqls.last.should == Sequel::Database::SQL_BEGIN
614
+ end
615
+
616
+ @db.transaction_mode.should == nil
617
+ @db.transaction_mode = :immediate
618
+ @db.transaction_mode.should == :immediate
619
+ @db.transaction do
620
+ sqls.last.should == "BEGIN IMMEDIATE TRANSACTION"
621
+ end
622
+ @db.transaction(:mode => :exclusive) do
623
+ sqls.last.should == "BEGIN EXCLUSIVE TRANSACTION"
624
+ end
625
+
626
+ proc {@db.transaction_mode = :invalid}.should raise_error(Sequel::Error)
627
+
628
+ @db.transaction_mode.should == :immediate
629
+ proc {@db.transaction(:mode => :invalid) {}}.should raise_error(Sequel::Error)
630
+ end
631
+ end