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,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
2
2
 
3
3
  describe "DB#create_table" do
4
4
  before do
5
- @db = SchemaDummyDatabase.new
5
+ @db = Sequel.mock
6
6
  end
7
7
 
8
8
  specify "should accept the table name" do
@@ -13,14 +13,14 @@ describe "DB#create_table" do
13
13
  specify "should accept the table name in multiple formats" do
14
14
  @db.create_table(:cats__cats) {}
15
15
  @db.create_table("cats__cats1") {}
16
- @db.create_table(:cats__cats2.identifier) {}
17
- @db.create_table(:cats.qualify(:cats3)) {}
16
+ @db.create_table(Sequel.identifier(:cats__cats2)) {}
17
+ @db.create_table(Sequel.qualify(:cats3, :cats)) {}
18
18
  @db.sqls.should == ['CREATE TABLE cats.cats ()', 'CREATE TABLE cats__cats1 ()', 'CREATE TABLE cats__cats2 ()', 'CREATE TABLE cats3.cats ()']
19
19
  end
20
20
 
21
21
  specify "should raise an error if the table name argument is not valid" do
22
22
  proc{@db.create_table(1) {}}.should raise_error(Sequel::Error)
23
- proc{@db.create_table(:cats.as(:c)) {}}.should raise_error(Sequel::Error)
23
+ proc{@db.create_table(Sequel.as(:cats, :c)) {}}.should raise_error(Sequel::Error)
24
24
  end
25
25
 
26
26
  specify "should remove cached schema entry" do
@@ -88,13 +88,11 @@ describe "DB#create_table" do
88
88
  end
89
89
  @db.sqls.should == ['CREATE TABLE cats (id integer PRIMARY KEY AUTOINCREMENT)']
90
90
 
91
- @db.sqls.clear
92
91
  @db.create_table(:cats) do
93
92
  primary_key :id, :serial, :auto_increment => false
94
93
  end
95
94
  @db.sqls.should == ['CREATE TABLE cats (id serial PRIMARY KEY)']
96
95
 
97
- @db.sqls.clear
98
96
  @db.create_table(:cats) do
99
97
  primary_key :id, :type => :serial, :auto_increment => false
100
98
  end
@@ -154,7 +152,6 @@ describe "DB#create_table" do
154
152
  varchar :name
155
153
  end
156
154
  @db.sqls.should == ["CREATE TABLE cats (name varchar(255))"]
157
- @db.sqls.clear
158
155
  @db.create_table(:cats) do
159
156
  varchar :name, :size => 51
160
157
  end
@@ -199,7 +196,6 @@ describe "DB#create_table" do
199
196
  end
200
197
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects(id))"]
201
198
 
202
- @db.sqls.clear
203
199
  @db.create_table(:cats) do
204
200
  foreign_key :project_id, :table => :projects, :key => :zzz
205
201
  end
@@ -212,32 +208,30 @@ describe "DB#create_table" do
212
208
  end
213
209
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE RESTRICT)"]
214
210
 
215
- @db.sqls.clear
216
211
  @db.create_table(:cats) do
217
212
  foreign_key :project_id, :table => :projects, :on_delete => :cascade
218
213
  end
219
214
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE CASCADE)"]
220
215
 
221
- @db.sqls.clear
222
216
  @db.create_table(:cats) do
223
217
  foreign_key :project_id, :table => :projects, :on_delete => :no_action
224
218
  end
225
219
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE NO ACTION)"]
226
- @db.sqls.clear
227
220
 
228
- @db.sqls.clear
229
221
  @db.create_table(:cats) do
230
222
  foreign_key :project_id, :table => :projects, :on_delete => :set_null
231
223
  end
232
224
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE SET NULL)"]
233
- @db.sqls.clear
234
225
 
235
- @db.sqls.clear
236
226
  @db.create_table(:cats) do
237
227
  foreign_key :project_id, :table => :projects, :on_delete => :set_default
238
228
  end
239
229
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE SET DEFAULT)"]
240
- @db.sqls.clear
230
+
231
+ @db.create_table(:cats) do
232
+ foreign_key :project_id, :table => :projects, :on_delete => 'NO ACTION FOO'
233
+ end
234
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE NO ACTION FOO)"]
241
235
  end
242
236
 
243
237
  specify "should accept foreign keys with ON UPDATE clause" do
@@ -246,32 +240,30 @@ describe "DB#create_table" do
246
240
  end
247
241
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON UPDATE RESTRICT)"]
248
242
 
249
- @db.sqls.clear
250
243
  @db.create_table(:cats) do
251
244
  foreign_key :project_id, :table => :projects, :on_update => :cascade
252
245
  end
253
246
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON UPDATE CASCADE)"]
254
247
 
255
- @db.sqls.clear
256
248
  @db.create_table(:cats) do
257
249
  foreign_key :project_id, :table => :projects, :on_update => :no_action
258
250
  end
259
251
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON UPDATE NO ACTION)"]
260
- @db.sqls.clear
261
252
 
262
- @db.sqls.clear
263
253
  @db.create_table(:cats) do
264
254
  foreign_key :project_id, :table => :projects, :on_update => :set_null
265
255
  end
266
256
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON UPDATE SET NULL)"]
267
- @db.sqls.clear
268
257
 
269
- @db.sqls.clear
270
258
  @db.create_table(:cats) do
271
259
  foreign_key :project_id, :table => :projects, :on_update => :set_default
272
260
  end
273
261
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON UPDATE SET DEFAULT)"]
274
- @db.sqls.clear
262
+
263
+ @db.create_table(:cats) do
264
+ foreign_key :project_id, :table => :projects, :on_update => 'SET DEFAULT FOO'
265
+ end
266
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON UPDATE SET DEFAULT FOO)"]
275
267
  end
276
268
 
277
269
  specify "should accept foreign keys with deferrable option" do
@@ -281,6 +273,13 @@ describe "DB#create_table" do
281
273
  @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects DEFERRABLE INITIALLY DEFERRED)"]
282
274
  end
283
275
 
276
+ specify "should accept collation" do
277
+ @db.create_table(:cats) do
278
+ varchar :name, :collate => :utf8_bin
279
+ end
280
+ @db.sqls.should == ["CREATE TABLE cats (name varchar(255) COLLATE utf8_bin)"]
281
+ end
282
+
284
283
  specify "should accept inline index definition" do
285
284
  @db.create_table(:cats) do
286
285
  integer :id, :index => true
@@ -288,6 +287,13 @@ describe "DB#create_table" do
288
287
  @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_id_index ON cats (id)"]
289
288
  end
290
289
 
290
+ specify "should accept inline index definition with a hash of options" do
291
+ @db.create_table(:cats) do
292
+ integer :id, :index => {:unique=>true}
293
+ end
294
+ @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE UNIQUE INDEX cats_id_index ON cats (id)"]
295
+ end
296
+
291
297
  specify "should accept inline index definition for foreign keys" do
292
298
  @db.create_table(:cats) do
293
299
  foreign_key :project_id, :table => :projects, :on_delete => :cascade, :index => true
@@ -296,6 +302,14 @@ describe "DB#create_table" do
296
302
  "CREATE INDEX cats_project_id_index ON cats (project_id)"]
297
303
  end
298
304
 
305
+ specify "should accept inline index definition for foreign keys with a hash of options" do
306
+ @db.create_table(:cats) do
307
+ foreign_key :project_id, :table => :projects, :on_delete => :cascade, :index => {:unique=>true}
308
+ end
309
+ @db.sqls.should == ["CREATE TABLE cats (project_id integer REFERENCES projects ON DELETE CASCADE)",
310
+ "CREATE UNIQUE INDEX cats_project_id_index ON cats (project_id)"]
311
+ end
312
+
299
313
  specify "should accept index definitions" do
300
314
  @db.create_table(:cats) do
301
315
  integer :id
@@ -361,7 +375,6 @@ describe "DB#create_table" do
361
375
  @db.meta_def(:execute_ddl){|*a| raise Sequel::DatabaseError if /blah/.match(a.first); super(*a)}
362
376
  lambda{@db.create_table(:cats){Integer :id; index :blah; index :id}}.should raise_error(Sequel::DatabaseError)
363
377
  @db.sqls.should == ['CREATE TABLE cats (id integer)']
364
- @db.sqls.clear
365
378
  lambda{@db.create_table(:cats, :ignore_index_errors=>true){Integer :id; index :blah; index :id}}.should_not raise_error(Sequel::DatabaseError)
366
379
  @db.sqls.should == ['CREATE TABLE cats (id integer)', 'CREATE INDEX cats_id_index ON cats (id)']
367
380
  end
@@ -378,7 +391,7 @@ describe "DB#create_table" do
378
391
  specify "should accept functional indexes" do
379
392
  @db.create_table(:cats) do
380
393
  integer :id
381
- index :lower.sql_function(:name)
394
+ index Sequel.function(:lower, :name)
382
395
  end
383
396
  @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_lower_name__index ON cats (lower(name))"]
384
397
  end
@@ -386,7 +399,7 @@ describe "DB#create_table" do
386
399
  specify "should accept indexes with identifiers" do
387
400
  @db.create_table(:cats) do
388
401
  integer :id
389
- index :lower__name.identifier
402
+ index Sequel.identifier(:lower__name)
390
403
  end
391
404
  @db.sqls.should == ["CREATE TABLE cats (id integer)", "CREATE INDEX cats_lower__name_index ON cats (lower__name)"]
392
405
  end
@@ -418,7 +431,7 @@ describe "DB#create_table" do
418
431
  specify "should accept unnamed constraint definitions with blocks" do
419
432
  @db.create_table(:cats) do
420
433
  integer :score
421
- check {(:x.sql_number > 0) & (:y.sql_number < 1)}
434
+ check{(x.sql_number > 0) & (y.sql_number < 1)}
422
435
  end
423
436
  @db.sqls.should == ["CREATE TABLE cats (score integer, CHECK ((x > 0) AND (y < 1)))"]
424
437
  end
@@ -447,7 +460,7 @@ describe "DB#create_table" do
447
460
 
448
461
  specify "should accept named constraint definitions with block" do
449
462
  @db.create_table(:cats) do
450
- constraint(:blah_blah) {(:x.sql_number > 0) & (:y.sql_number < 1)}
463
+ constraint(:blah_blah){(x.sql_number > 0) & (y.sql_number < 1)}
451
464
  end
452
465
  @db.sqls.should == ["CREATE TABLE cats (CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1)))"]
453
466
  end
@@ -499,7 +512,6 @@ describe "DB#create_table" do
499
512
  foreign_key [:a, :b], :abc, :key => [:real_a, :real_b]
500
513
  end
501
514
  @db.sqls.should == ["CREATE TABLE cats (a integer, b integer, FOREIGN KEY (a, b) REFERENCES abc(real_a, real_b))"]
502
- @db.sqls.clear
503
515
 
504
516
  @db.create_table(:cats) do
505
517
  integer :a
@@ -517,7 +529,6 @@ describe "DB#create_table" do
517
529
  end
518
530
  @db.sqls.should == ["CREATE TABLE cats (a integer, b integer, FOREIGN KEY (a, b) REFERENCES abc ON DELETE CASCADE)"]
519
531
 
520
- @db.sqls.clear
521
532
  @db.create_table(:cats) do
522
533
  integer :a
523
534
  integer :b
@@ -525,7 +536,6 @@ describe "DB#create_table" do
525
536
  end
526
537
  @db.sqls.should == ["CREATE TABLE cats (a integer, b integer, FOREIGN KEY (a, b) REFERENCES abc ON UPDATE NO ACTION)"]
527
538
 
528
- @db.sqls.clear
529
539
  @db.create_table(:cats) do
530
540
  integer :a
531
541
  integer :b
@@ -533,7 +543,6 @@ describe "DB#create_table" do
533
543
  end
534
544
  @db.sqls.should == ["CREATE TABLE cats (a integer, b integer, FOREIGN KEY (a, b) REFERENCES abc ON DELETE RESTRICT ON UPDATE SET DEFAULT)"]
535
545
 
536
- @db.sqls.clear
537
546
  @db.create_table(:cats) do
538
547
  integer :a
539
548
  integer :b
@@ -541,28 +550,49 @@ describe "DB#create_table" do
541
550
  end
542
551
  @db.sqls.should == ["CREATE TABLE cats (a integer, b integer, FOREIGN KEY (a, b) REFERENCES abc(x, y) ON DELETE SET NULL ON UPDATE SET NULL)"]
543
552
  end
553
+
554
+ specify "should accept an :as option to create a table from the results of a dataset" do
555
+ @db.create_table(:cats, :as=>@db[:a])
556
+ @db.sqls.should == ['CREATE TABLE cats AS SELECT * FROM a']
557
+ end
558
+
559
+ specify "should accept an :as option to create a table from a SELECT string" do
560
+ @db.create_table(:cats, :as=>'SELECT * FROM a')
561
+ @db.sqls.should == ['CREATE TABLE cats AS SELECT * FROM a']
562
+ end
563
+
564
+ specify "should raise an Error if both a block and an :as argument are given" do
565
+ proc{@db.create_table(:cats, :as=>@db[:a]){}}.should raise_error(Sequel::Error)
566
+ end
544
567
  end
545
568
 
546
569
  describe "DB#create_table!" do
547
570
  before do
548
- @db = SchemaDummyDatabase.new
571
+ @db = Sequel.mock
549
572
  end
550
573
 
551
- specify "should drop the table and then create it" do
552
- @db.create_table!(:cats) {}
574
+ specify "should create the table if it does not exist" do
575
+ @db.meta_def(:table_exists?){|a| false}
576
+ @db.create_table!(:cats){|*a|}
577
+ @db.sqls.should == ['CREATE TABLE cats ()']
578
+ end
579
+
580
+ specify "should drop the table before creating it if it already exists" do
581
+ @db.meta_def(:table_exists?){|a| true}
582
+ @db.create_table!(:cats){|*a|}
553
583
  @db.sqls.should == ['DROP TABLE cats', 'CREATE TABLE cats ()']
554
584
  end
555
585
  end
556
586
 
557
587
  describe "DB#create_table?" do
558
588
  before do
559
- @db = SchemaDummyDatabase.new
589
+ @db = Sequel.mock
560
590
  end
561
591
 
562
592
  specify "should not create the table if the table already exists" do
563
593
  @db.meta_def(:table_exists?){|a| true}
564
594
  @db.create_table?(:cats){|*a|}
565
- @db.sqls.should == nil
595
+ @db.sqls.should == []
566
596
  end
567
597
 
568
598
  specify "should create the table if the table doesn't already exist" do
@@ -570,38 +600,191 @@ describe "DB#create_table?" do
570
600
  @db.create_table?(:cats){|*a|}
571
601
  @db.sqls.should == ['CREATE TABLE cats ()']
572
602
  end
603
+
604
+ specify "should use IF NOT EXISTS if the database supports that" do
605
+ @db.meta_def(:supports_create_table_if_not_exists?){true}
606
+ @db.create_table?(:cats){|*a|}
607
+ @db.sqls.should == ['CREATE TABLE IF NOT EXISTS cats ()']
608
+ end
609
+ end
610
+
611
+ describe "DB#create_join_table" do
612
+ before do
613
+ @db = Sequel.mock
614
+ end
615
+
616
+ specify "should take a hash with foreign keys and table name values" do
617
+ @db.create_join_table(:cat_id=>:cats, :dog_id=>:dogs)
618
+ @db.sqls.should == ['CREATE TABLE cats_dogs (cat_id integer NOT NULL REFERENCES cats, dog_id integer NOT NULL REFERENCES dogs, PRIMARY KEY (cat_id, dog_id))', 'CREATE INDEX cats_dogs_dog_id_cat_id_index ON cats_dogs (dog_id, cat_id)']
619
+ end
620
+
621
+ specify "should be able to have values be a hash of options" do
622
+ @db.create_join_table(:cat_id=>{:table=>:cats, :null=>true}, :dog_id=>{:table=>:dogs, :default=>0})
623
+ @db.sqls.should == ['CREATE TABLE cats_dogs (cat_id integer NULL REFERENCES cats, dog_id integer DEFAULT 0 NOT NULL REFERENCES dogs, PRIMARY KEY (cat_id, dog_id))', 'CREATE INDEX cats_dogs_dog_id_cat_id_index ON cats_dogs (dog_id, cat_id)']
624
+ end
625
+
626
+ specify "should be able to pass a second hash of table options" do
627
+ @db.create_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :temp=>true)
628
+ @db.sqls.should == ['CREATE TEMPORARY TABLE cats_dogs (cat_id integer NOT NULL REFERENCES cats, dog_id integer NOT NULL REFERENCES dogs, PRIMARY KEY (cat_id, dog_id))', 'CREATE INDEX cats_dogs_dog_id_cat_id_index ON cats_dogs (dog_id, cat_id)']
629
+ end
630
+
631
+ specify "should recognize :name option in table options" do
632
+ @db.create_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :name=>:f)
633
+ @db.sqls.should == ['CREATE TABLE f (cat_id integer NOT NULL REFERENCES cats, dog_id integer NOT NULL REFERENCES dogs, PRIMARY KEY (cat_id, dog_id))', 'CREATE INDEX f_dog_id_cat_id_index ON f (dog_id, cat_id)']
634
+ end
635
+
636
+ specify "should recognize :index_options option in table options" do
637
+ @db.create_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :index_options=>{:name=>:foo_index})
638
+ @db.sqls.should == ['CREATE TABLE cats_dogs (cat_id integer NOT NULL REFERENCES cats, dog_id integer NOT NULL REFERENCES dogs, PRIMARY KEY (cat_id, dog_id))', 'CREATE INDEX foo_index ON cats_dogs (dog_id, cat_id)']
639
+ end
640
+
641
+ specify "should recognize :no_index option in table options" do
642
+ @db.create_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :no_index=>true)
643
+ @db.sqls.should == ['CREATE TABLE cats_dogs (cat_id integer NOT NULL REFERENCES cats, dog_id integer NOT NULL REFERENCES dogs, PRIMARY KEY (cat_id, dog_id))']
644
+ end
645
+
646
+ specify "should recognize :no_primary_key option in table options" do
647
+ @db.create_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :no_primary_key=>true)
648
+ @db.sqls.should == ['CREATE TABLE cats_dogs (cat_id integer NOT NULL REFERENCES cats, dog_id integer NOT NULL REFERENCES dogs)', 'CREATE INDEX cats_dogs_dog_id_cat_id_index ON cats_dogs (dog_id, cat_id)']
649
+ end
650
+
651
+ specify "should raise an error if the hash doesn't have 2 entries with table names" do
652
+ proc{@db.create_join_table({})}.should raise_error(Sequel::Error)
653
+ proc{@db.create_join_table({:cat_id=>:cats})}.should raise_error(Sequel::Error)
654
+ proc{@db.create_join_table({:cat_id=>:cats, :human_id=>:humans, :dog_id=>:dog})}.should raise_error(Sequel::Error)
655
+ proc{@db.create_join_table({:cat_id=>:cats, :dog_id=>{}})}.should raise_error(Sequel::Error)
656
+ end
657
+ end
658
+
659
+ describe "DB#drop_join_table" do
660
+ before do
661
+ @db = Sequel.mock
662
+ end
663
+
664
+ specify "should take a hash with foreign keys and table name values and drop the table" do
665
+ @db.drop_join_table(:cat_id=>:cats, :dog_id=>:dogs)
666
+ @db.sqls.should == ['DROP TABLE cats_dogs']
667
+ end
668
+
669
+ specify "should be able to have values be a hash of options" do
670
+ @db.drop_join_table(:cat_id=>{:table=>:cats, :null=>true}, :dog_id=>{:table=>:dogs, :default=>0})
671
+ @db.sqls.should == ['DROP TABLE cats_dogs']
672
+ end
673
+
674
+ specify "should respect a second hash of table options" do
675
+ @db.drop_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :cascade=>true)
676
+ @db.sqls.should == ['DROP TABLE cats_dogs CASCADE']
677
+ end
678
+
679
+ specify "should respect :name option for table name" do
680
+ @db.drop_join_table({:cat_id=>:cats, :dog_id=>:dogs}, :name=>:f)
681
+ @db.sqls.should == ['DROP TABLE f']
682
+ end
683
+
684
+ specify "should raise an error if the hash doesn't have 2 entries with table names" do
685
+ proc{@db.drop_join_table({})}.should raise_error(Sequel::Error)
686
+ proc{@db.drop_join_table({:cat_id=>:cats})}.should raise_error(Sequel::Error)
687
+ proc{@db.drop_join_table({:cat_id=>:cats, :human_id=>:humans, :dog_id=>:dog})}.should raise_error(Sequel::Error)
688
+ proc{@db.drop_join_table({:cat_id=>:cats, :dog_id=>{}})}.should raise_error(Sequel::Error)
689
+ end
573
690
  end
574
691
 
575
692
  describe "DB#drop_table" do
576
693
  before do
577
- @db = SchemaDummyDatabase.new
694
+ @db = Sequel.mock
578
695
  end
579
696
 
580
697
  specify "should generate a DROP TABLE statement" do
581
698
  @db.drop_table :cats
582
699
  @db.sqls.should == ['DROP TABLE cats']
583
700
  end
701
+
702
+ specify "should drop multiple tables at once" do
703
+ @db.drop_table :cats, :dogs
704
+ @db.sqls.should == ['DROP TABLE cats', 'DROP TABLE dogs']
705
+ end
706
+
707
+ specify "should take an options hash and support the :cascade option" do
708
+ @db.drop_table :cats, :dogs, :cascade=>true
709
+ @db.sqls.should == ['DROP TABLE cats CASCADE', 'DROP TABLE dogs CASCADE']
710
+ end
711
+ end
712
+
713
+ describe "DB#drop_table?" do
714
+ before do
715
+ @db = Sequel.mock
716
+ end
717
+
718
+ specify "should drop the table if it exists" do
719
+ @db.meta_def(:table_exists?){|a| true}
720
+ @db.drop_table?(:cats)
721
+ @db.sqls.should == ["DROP TABLE cats"]
722
+ end
723
+
724
+ specify "should do nothing if the table does not exist" do
725
+ @db.meta_def(:table_exists?){|a| false}
726
+ @db.drop_table?(:cats)
727
+ @db.sqls.should == []
728
+ end
729
+
730
+ specify "should operate on multiple tables at once" do
731
+ @db.meta_def(:table_exists?){|a| a == :cats}
732
+ @db.drop_table? :cats, :dogs
733
+ @db.sqls.should == ['DROP TABLE cats']
734
+ end
735
+
736
+ specify "should take an options hash and support the :cascade option" do
737
+ @db.meta_def(:table_exists?){|a| true}
738
+ @db.drop_table? :cats, :dogs, :cascade=>true
739
+ @db.sqls.should == ['DROP TABLE cats CASCADE', 'DROP TABLE dogs CASCADE']
740
+ end
741
+
742
+ specify "should use IF NOT EXISTS if the database supports that" do
743
+ @db.meta_def(:supports_drop_table_if_exists?){true}
744
+ @db.drop_table? :cats, :dogs
745
+ @db.sqls.should == ['DROP TABLE IF EXISTS cats', 'DROP TABLE IF EXISTS dogs']
746
+ end
747
+
748
+ specify "should use IF NOT EXISTS with CASCADE if the database supports that" do
749
+ @db.meta_def(:supports_drop_table_if_exists?){true}
750
+ @db.drop_table? :cats, :dogs, :cascade=>true
751
+ @db.sqls.should == ['DROP TABLE IF EXISTS cats CASCADE', 'DROP TABLE IF EXISTS dogs CASCADE']
752
+ end
584
753
  end
585
754
 
586
755
  describe "DB#alter_table" do
587
756
  before do
588
- @db = SchemaDummyDatabase.new
757
+ @db = Sequel.mock
589
758
  end
590
759
 
591
- specify "should allow adding not null constraint" do
760
+ specify "should allow adding not null constraint via set_column_allow_null with false argument" do
592
761
  @db.alter_table(:cats) do
593
762
  set_column_allow_null :score, false
594
763
  end
595
764
  @db.sqls.should == ["ALTER TABLE cats ALTER COLUMN score SET NOT NULL"]
596
765
  end
597
766
 
598
- specify "should allow droping not null constraint" do
767
+ specify "should allow removing not null constraint via set_column_allow_null with true argument" do
599
768
  @db.alter_table(:cats) do
600
769
  set_column_allow_null :score, true
601
770
  end
602
771
  @db.sqls.should == ["ALTER TABLE cats ALTER COLUMN score DROP NOT NULL"]
603
772
  end
604
773
 
774
+ specify "should allow adding not null constraint via set_column_not_null" do
775
+ @db.alter_table(:cats) do
776
+ set_column_not_null :score
777
+ end
778
+ @db.sqls.should == ["ALTER TABLE cats ALTER COLUMN score SET NOT NULL"]
779
+ end
780
+
781
+ specify "should allow removing not null constraint via set_column_allow_null without argument" do
782
+ @db.alter_table(:cats) do
783
+ set_column_allow_null :score
784
+ end
785
+ @db.sqls.should == ["ALTER TABLE cats ALTER COLUMN score DROP NOT NULL"]
786
+ end
787
+
605
788
  specify "should support add_column" do
606
789
  @db.alter_table(:cats) do
607
790
  add_column :score, :integer
@@ -618,7 +801,7 @@ describe "DB#alter_table" do
618
801
 
619
802
  specify "should support add_constraint with block" do
620
803
  @db.alter_table(:cats) do
621
- add_constraint(:blah_blah) {(:x.sql_number > 0) & (:y.sql_number < 1)}
804
+ add_constraint(:blah_blah){(x.sql_number > 0) & (y.sql_number < 1)}
622
805
  end
623
806
  @db.sqls.should == ["ALTER TABLE cats ADD CONSTRAINT blah_blah CHECK ((x > 0) AND (y < 1))"]
624
807
  end
@@ -629,7 +812,6 @@ describe "DB#alter_table" do
629
812
  end
630
813
  @db.sqls.should == ["ALTER TABLE cats ADD UNIQUE (a, b)"]
631
814
 
632
- @db.sqls.clear
633
815
  @db.alter_table(:cats) do
634
816
  add_unique_constraint [:a, :b], :name => :ab_uniq
635
817
  end
@@ -649,19 +831,16 @@ describe "DB#alter_table" do
649
831
  end
650
832
  @db.sqls.should == ["ALTER TABLE cats ADD FOREIGN KEY (node_id, prop_id) REFERENCES nodes_props"]
651
833
 
652
- @db.sqls.clear
653
834
  @db.alter_table(:cats) do
654
835
  add_foreign_key [:node_id, :prop_id], :nodes_props, :name => :cfk
655
836
  end
656
837
  @db.sqls.should == ["ALTER TABLE cats ADD CONSTRAINT cfk FOREIGN KEY (node_id, prop_id) REFERENCES nodes_props"]
657
838
 
658
- @db.sqls.clear
659
839
  @db.alter_table(:cats) do
660
840
  add_foreign_key [:node_id, :prop_id], :nodes_props, :key => [:nid, :pid]
661
841
  end
662
842
  @db.sqls.should == ["ALTER TABLE cats ADD FOREIGN KEY (node_id, prop_id) REFERENCES nodes_props(nid, pid)"]
663
843
 
664
- @db.sqls.clear
665
844
  @db.alter_table(:cats) do
666
845
  add_foreign_key [:node_id, :prop_id], :nodes_props, :on_delete => :restrict, :on_update => :cascade
667
846
  end
@@ -679,7 +858,7 @@ describe "DB#alter_table" do
679
858
  @db.meta_def(:execute_ddl){|*a| raise Sequel::DatabaseError}
680
859
  lambda{@db.add_index(:cats, :id)}.should raise_error(Sequel::DatabaseError)
681
860
  lambda{@db.add_index(:cats, :id, :ignore_errors=>true)}.should_not raise_error(Sequel::DatabaseError)
682
- @db.sqls.should == nil
861
+ @db.sqls.should == []
683
862
  end
684
863
 
685
864
  specify "should support add_primary_key" do
@@ -695,7 +874,6 @@ describe "DB#alter_table" do
695
874
  end
696
875
  @db.sqls.should == ["ALTER TABLE cats ADD PRIMARY KEY (id, type)"]
697
876
 
698
- @db.sqls.clear
699
877
  @db.alter_table(:cats) do
700
878
  add_primary_key [:id, :type], :name => :cpk
701
879
  end
@@ -709,6 +887,13 @@ describe "DB#alter_table" do
709
887
  @db.sqls.should == ["ALTER TABLE cats DROP COLUMN score"]
710
888
  end
711
889
 
890
+ specify "should support drop_column with :cascade=>true option" do
891
+ @db.alter_table(:cats) do
892
+ drop_column :score, :cascade=>true
893
+ end
894
+ @db.sqls.should == ["ALTER TABLE cats DROP COLUMN score CASCADE"]
895
+ end
896
+
712
897
  specify "should support drop_constraint" do
713
898
  @db.alter_table(:cats) do
714
899
  drop_constraint :valid_score
@@ -716,6 +901,13 @@ describe "DB#alter_table" do
716
901
  @db.sqls.should == ["ALTER TABLE cats DROP CONSTRAINT valid_score"]
717
902
  end
718
903
 
904
+ specify "should support drop_constraint with :cascade=>true option" do
905
+ @db.alter_table(:cats) do
906
+ drop_constraint :valid_score, :cascade=>true
907
+ end
908
+ @db.sqls.should == ["ALTER TABLE cats DROP CONSTRAINT valid_score CASCADE"]
909
+ end
910
+
719
911
  specify "should support drop_index" do
720
912
  @db.alter_table(:cats) do
721
913
  drop_index :name
@@ -761,6 +953,270 @@ describe "DB#alter_table" do
761
953
  "ALTER TABLE cats ALTER COLUMN score TYPE varchar(30)",
762
954
  "ALTER TABLE cats ALTER COLUMN score TYPE enum('a', 'b')"]
763
955
  end
956
+
957
+ specify "should combine operations into a single query if the database supports it" do
958
+ @db.meta_def(:supports_combining_alter_table_ops?){true}
959
+ @db.alter_table(:cats) do
960
+ add_column :a, Integer
961
+ drop_column :b
962
+ set_column_not_null :c
963
+ rename_column :d, :e
964
+ set_column_default :f, 'g'
965
+ set_column_type :h, Integer
966
+ add_constraint(:i){a > 1}
967
+ drop_constraint :j
968
+ end
969
+ @db.sqls.should == ["ALTER TABLE cats ADD COLUMN a integer, DROP COLUMN b, ALTER COLUMN c SET NOT NULL, RENAME COLUMN d TO e, ALTER COLUMN f SET DEFAULT 'g', ALTER COLUMN h TYPE integer, ADD CONSTRAINT i CHECK (a > 1), DROP CONSTRAINT j"]
970
+ end
971
+
972
+ specify "should combine operations into consecutive groups of combinable operations if the database supports combining operations" do
973
+ @db.meta_def(:supports_combining_alter_table_ops?){true}
974
+ @db.alter_table(:cats) do
975
+ add_column :a, Integer
976
+ drop_column :b
977
+ set_column_not_null :c
978
+ rename_column :d, :e
979
+ add_index :e
980
+ set_column_default :f, 'g'
981
+ set_column_type :h, Integer
982
+ add_constraint(:i){a > 1}
983
+ drop_constraint :j
984
+ end
985
+ @db.sqls.should == ["ALTER TABLE cats ADD COLUMN a integer, DROP COLUMN b, ALTER COLUMN c SET NOT NULL, RENAME COLUMN d TO e",
986
+ "CREATE INDEX cats_e_index ON cats (e)",
987
+ "ALTER TABLE cats ALTER COLUMN f SET DEFAULT 'g', ALTER COLUMN h TYPE integer, ADD CONSTRAINT i CHECK (a > 1), DROP CONSTRAINT j"]
988
+ end
989
+
990
+ end
991
+
992
+ describe "Database#create_table" do
993
+ before do
994
+ @db = Sequel.mock
995
+ end
996
+
997
+ specify "should construct proper SQL" do
998
+ @db.create_table :test do
999
+ primary_key :id, :integer, :null => false
1000
+ column :name, :text
1001
+ index :name, :unique => true
1002
+ end
1003
+ @db.sqls.should == ['CREATE TABLE test (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
1004
+ 'CREATE UNIQUE INDEX test_name_index ON test (name)']
1005
+ end
1006
+
1007
+ specify "should create a temporary table" do
1008
+ @db.create_table :test_tmp, :temp => true do
1009
+ primary_key :id, :integer, :null => false
1010
+ column :name, :text
1011
+ index :name, :unique => true
1012
+ end
1013
+
1014
+ @db.sqls.should == ['CREATE TEMPORARY TABLE test_tmp (id integer NOT NULL PRIMARY KEY AUTOINCREMENT, name text)',
1015
+ 'CREATE UNIQUE INDEX test_tmp_name_index ON test_tmp (name)']
1016
+ end
1017
+
1018
+ specify "should not use default schema when creating a temporary table" do
1019
+ @db.default_schema = :foo
1020
+ @db.create_table :test_tmp, :temp => true do
1021
+ column :name, :text
1022
+ end
1023
+ @db.sqls.should == ['CREATE TEMPORARY TABLE test_tmp (name text)']
1024
+ end
1025
+ end
1026
+
1027
+ describe "Database#alter_table" do
1028
+ before do
1029
+ @db = Sequel.mock
1030
+ end
1031
+
1032
+ specify "should construct proper SQL" do
1033
+ @db.alter_table :xyz do
1034
+ add_column :aaa, :text, :null => false, :unique => true
1035
+ drop_column :bbb
1036
+ rename_column :ccc, :ddd
1037
+ set_column_type :eee, :integer
1038
+ set_column_default :hhh, 'abcd'
1039
+ add_index :fff, :unique => true
1040
+ drop_index :ggg
1041
+ end
1042
+
1043
+ @db.sqls.should == ['ALTER TABLE xyz ADD COLUMN aaa text NOT NULL UNIQUE',
1044
+ 'ALTER TABLE xyz DROP COLUMN bbb',
1045
+ 'ALTER TABLE xyz RENAME COLUMN ccc TO ddd',
1046
+ 'ALTER TABLE xyz ALTER COLUMN eee TYPE integer',
1047
+ "ALTER TABLE xyz ALTER COLUMN hhh SET DEFAULT 'abcd'",
1048
+ 'CREATE UNIQUE INDEX xyz_fff_index ON xyz (fff)',
1049
+ 'DROP INDEX xyz_ggg_index']
1050
+ end
1051
+ end
1052
+
1053
+ describe "Database#add_column" do
1054
+ specify "should construct proper SQL" do
1055
+ db = Sequel.mock
1056
+ db.add_column :test, :name, :text, :unique => true
1057
+ db.sqls.should == ['ALTER TABLE test ADD COLUMN name text UNIQUE']
1058
+ end
1059
+ end
1060
+
1061
+ describe "Database#drop_column" do
1062
+ before do
1063
+ @db = Sequel.mock
1064
+ end
1065
+
1066
+ specify "should construct proper SQL" do
1067
+ @db.drop_column :test, :name
1068
+ @db.sqls.should == ['ALTER TABLE test DROP COLUMN name']
1069
+ end
1070
+
1071
+ specify "should use CASCADE for :cascade=>true option" do
1072
+ @db.drop_column :test, :name, :cascade=>true
1073
+ @db.sqls.should == ['ALTER TABLE test DROP COLUMN name CASCADE']
1074
+ end
1075
+ end
1076
+
1077
+ describe "Database#rename_column" do
1078
+ before do
1079
+ @db = Sequel.mock
1080
+ end
1081
+
1082
+ specify "should construct proper SQL" do
1083
+ @db.rename_column :test, :abc, :def
1084
+ @db.sqls.should == ['ALTER TABLE test RENAME COLUMN abc TO def']
1085
+ end
1086
+ end
1087
+
1088
+ describe "Database#set_column_type" do
1089
+ before do
1090
+ @db = Sequel.mock
1091
+ end
1092
+
1093
+ specify "should construct proper SQL" do
1094
+ @db.set_column_type :test, :name, :integer
1095
+ @db.sqls.should == ['ALTER TABLE test ALTER COLUMN name TYPE integer']
1096
+ end
1097
+ end
1098
+
1099
+ describe "Database#set_column_default" do
1100
+ before do
1101
+ @db = Sequel.mock
1102
+ end
1103
+
1104
+ specify "should construct proper SQL" do
1105
+ @db.set_column_default :test, :name, 'zyx'
1106
+ @db.sqls.should == ["ALTER TABLE test ALTER COLUMN name SET DEFAULT 'zyx'"]
1107
+ end
1108
+ end
1109
+
1110
+ describe "Database#add_index" do
1111
+ before do
1112
+ @db = Sequel.mock
1113
+ end
1114
+
1115
+ specify "should construct proper SQL" do
1116
+ @db.add_index :test, :name, :unique => true
1117
+ @db.sqls.should == ['CREATE UNIQUE INDEX test_name_index ON test (name)']
1118
+ end
1119
+
1120
+ specify "should accept multiple columns" do
1121
+ @db.add_index :test, [:one, :two]
1122
+ @db.sqls.should == ['CREATE INDEX test_one_two_index ON test (one, two)']
1123
+ end
1124
+ end
1125
+
1126
+ describe "Database#drop_index" do
1127
+ before do
1128
+ @db = Sequel.mock
1129
+ end
1130
+
1131
+ specify "should construct proper SQL" do
1132
+ @db.drop_index :test, :name
1133
+ @db.sqls.should == ['DROP INDEX test_name_index']
1134
+ end
1135
+
1136
+ end
1137
+
1138
+ describe "Database#drop_table" do
1139
+ before do
1140
+ @db = Sequel.mock
1141
+ end
1142
+
1143
+ specify "should construct proper SQL" do
1144
+ @db.drop_table :test
1145
+ @db.sqls.should == ['DROP TABLE test']
1146
+ end
1147
+
1148
+ specify "should accept multiple table names" do
1149
+ @db.drop_table :a, :bb, :ccc
1150
+ @db.sqls.should == ['DROP TABLE a', 'DROP TABLE bb', 'DROP TABLE ccc']
1151
+ end
1152
+ end
1153
+
1154
+ describe "Database#rename_table" do
1155
+ before do
1156
+ @db = Sequel.mock
1157
+ end
1158
+
1159
+ specify "should construct proper SQL" do
1160
+ @db.rename_table :abc, :xyz
1161
+ @db.sqls.should == ['ALTER TABLE abc RENAME TO xyz']
1162
+ end
1163
+ end
1164
+
1165
+ describe "Database#create_view" do
1166
+ before do
1167
+ @db = Sequel.mock
1168
+ end
1169
+
1170
+ specify "should construct proper SQL with raw SQL" do
1171
+ @db.create_view :test, "SELECT * FROM xyz"
1172
+ @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1173
+ @db.create_view Sequel.identifier(:test), "SELECT * FROM xyz"
1174
+ @db.sqls.should == ['CREATE VIEW test AS SELECT * FROM xyz']
1175
+ end
1176
+
1177
+ specify "should construct proper SQL with dataset" do
1178
+ @db.create_view :test, @db[:items].select(:a, :b).order(:c)
1179
+ @db.sqls.should == ['CREATE VIEW test AS SELECT a, b FROM items ORDER BY c']
1180
+ @db.create_or_replace_view :sch__test, "SELECT * FROM xyz"
1181
+ @db.sqls.should == ['CREATE OR REPLACE VIEW sch.test AS SELECT * FROM xyz']
1182
+ end
1183
+
1184
+ specify "should construct proper SQL with dataset" do
1185
+ @db.create_or_replace_view :test, @db[:items].select(:a, :b).order(:c)
1186
+ @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1187
+ @db.create_or_replace_view Sequel.identifier(:test), @db[:items].select(:a, :b).order(:c)
1188
+ @db.sqls.should == ['CREATE OR REPLACE VIEW test AS SELECT a, b FROM items ORDER BY c']
1189
+ end
1190
+ end
1191
+
1192
+ describe "Database#drop_view" do
1193
+ before do
1194
+ @db = Sequel.mock
1195
+ end
1196
+
1197
+ specify "should construct proper SQL" do
1198
+ @db.drop_view :test
1199
+ @db.drop_view Sequel.identifier(:test)
1200
+ @db.drop_view :sch__test
1201
+ @db.drop_view Sequel.qualify(:sch, :test)
1202
+ @db.sqls.should == ['DROP VIEW test', 'DROP VIEW test', 'DROP VIEW sch.test', 'DROP VIEW sch.test']
1203
+ end
1204
+
1205
+ specify "should drop multiple views at once" do
1206
+ @db.drop_view :cats, :dogs
1207
+ @db.sqls.should == ['DROP VIEW cats', 'DROP VIEW dogs']
1208
+ end
1209
+
1210
+ specify "should take an options hash and support the :cascade option" do
1211
+ @db.drop_view :cats, :dogs, :cascade=>true
1212
+ @db.sqls.should == ['DROP VIEW cats CASCADE', 'DROP VIEW dogs CASCADE']
1213
+ end
1214
+ end
1215
+
1216
+ describe "Database#alter_table_sql" do
1217
+ specify "should raise error for an invalid op" do
1218
+ proc {Sequel.mock.send(:alter_table_sql, :mau, :op => :blah)}.should raise_error(Sequel::Error)
1219
+ end
764
1220
  end
765
1221
 
766
1222
  describe "Schema Parser" do
@@ -776,6 +1232,43 @@ describe "Schema Parser" do
776
1232
  proc{@db.schema(:x)}.should raise_error(Sequel::Error)
777
1233
  end
778
1234
 
1235
+ specify "should cache data by default" do
1236
+ @db.meta_def(:schema_parse_table) do |t, opts|
1237
+ [[:a, {}]]
1238
+ end
1239
+ @db.schema(:x).should equal(@db.schema(:x))
1240
+ end
1241
+
1242
+ specify "should not cache data if :reload=>true is given" do
1243
+ @db.meta_def(:schema_parse_table) do |t, opts|
1244
+ [[:a, {}]]
1245
+ end
1246
+ @db.schema(:x).should_not equal(@db.schema(:x, :reload=>true))
1247
+ end
1248
+
1249
+ specify "should not cache schema metadata if cache_schema is false" do
1250
+ @db.cache_schema = false
1251
+ @db.meta_def(:schema_parse_table) do |t, opts|
1252
+ [[:a, {}]]
1253
+ end
1254
+ @db.schema(:x).should_not equal(@db.schema(:x))
1255
+ end
1256
+
1257
+ specify "should provide options if given a table name" do
1258
+ c = nil
1259
+ @db.meta_def(:schema_parse_table) do |t, opts|
1260
+ c = [t, opts]
1261
+ [[:a, {:db_type=>t.to_s}]]
1262
+ end
1263
+ @db.schema(:x)
1264
+ c.should == ["x", {}]
1265
+ @db.schema(:s__x)
1266
+ c.should == ["x", {:schema=>"s"}]
1267
+ ds = @db[:s__y]
1268
+ @db.schema(ds)
1269
+ c.should == ["y", {:schema=>"s", :dataset=>ds}]
1270
+ end
1271
+
779
1272
  specify "should parse the schema correctly for a single table" do
780
1273
  sqls = @sqls
781
1274
  proc{@db.schema(:x)}.should raise_error(Sequel::Error)
@@ -798,19 +1291,21 @@ describe "Schema Parser" do
798
1291
  s1 = @db.schema(:x)
799
1292
  s1.should == [['x', {:db_type=>'x', :ruby_default=>nil}]]
800
1293
  @db.schema(:x).object_id.should == s1.object_id
801
- @db.schema(:x.identifier).object_id.should == s1.object_id
1294
+ @db.schema(Sequel.identifier(:x)).object_id.should == s1.object_id
802
1295
  s2 = @db.schema(:x__y)
803
1296
  s2.should == [['y', {:db_type=>'y', :ruby_default=>nil}]]
804
1297
  @db.schema(:x__y).object_id.should == s2.object_id
805
- @db.schema(:y.qualify(:x)).object_id.should == s2.object_id
1298
+ @db.schema(Sequel.qualify(:x, :y)).object_id.should == s2.object_id
806
1299
  end
807
1300
 
808
1301
  specify "should correctly parse all supported data types" do
809
- @db.meta_def(:schema_parse_table) do |t, opts|
810
- [[:x, {:type=>schema_column_type(t.to_s)}]]
1302
+ sm = Module.new do
1303
+ def schema_parse_table(t, opts)
1304
+ [[:x, {:type=>schema_column_type(t.to_s)}]]
1305
+ end
811
1306
  end
1307
+ @db.extend(sm)
812
1308
  @db.schema(:tinyint).first.last[:type].should == :integer
813
- @db.schema(:interval).first.last[:type].should == :interval
814
1309
  @db.schema(:int).first.last[:type].should == :integer
815
1310
  @db.schema(:integer).first.last[:type].should == :integer
816
1311
  @db.schema(:bigint).first.last[:type].should == :integer
@@ -829,10 +1324,10 @@ describe "Schema Parser" do
829
1324
  @db.schema(:"time with time zone").first.last[:type].should == :time
830
1325
  @db.schema(:"time without time zone").first.last[:type].should == :time
831
1326
  @db.schema(:boolean).first.last[:type].should == :boolean
832
- @db.schema(:bit).first.last[:type].should == :boolean
833
1327
  @db.schema(:real).first.last[:type].should == :float
834
1328
  @db.schema(:float).first.last[:type].should == :float
835
1329
  @db.schema(:double).first.last[:type].should == :float
1330
+ @db.schema(:"double(1,2)").first.last[:type].should == :float
836
1331
  @db.schema(:"double precision").first.last[:type].should == :float
837
1332
  @db.schema(:number).first.last[:type].should == :decimal
838
1333
  @db.schema(:numeric).first.last[:type].should == :decimal
@@ -852,5 +1347,13 @@ describe "Schema Parser" do
852
1347
  @db.schema(:binary).first.last[:type].should == :blob
853
1348
  @db.schema(:varbinary).first.last[:type].should == :blob
854
1349
  @db.schema(:enum).first.last[:type].should == :enum
1350
+
1351
+ @db = Sequel.mock(:host=>'postgres')
1352
+ @db.extend(sm)
1353
+ @db.schema(:interval).first.last[:type].should == :interval
1354
+
1355
+ @db = Sequel.mock(:host=>'mysql')
1356
+ @db.extend(sm)
1357
+ @db.schema(:set).first.last[:type].should == :set
855
1358
  end
856
1359
  end