sequel 5.29.0 → 5.30.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 (323) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +8 -1922
  3. data/doc/release_notes/5.30.0.txt +20 -0
  4. data/lib/sequel/adapters/shared/sqlite.rb +7 -1
  5. data/lib/sequel/database/transactions.rb +5 -9
  6. data/lib/sequel/version.rb +1 -1
  7. metadata +4 -368
  8. data/Rakefile +0 -151
  9. data/doc/release_notes/4.0.0.txt +0 -262
  10. data/doc/release_notes/4.1.0.txt +0 -85
  11. data/doc/release_notes/4.10.0.txt +0 -226
  12. data/doc/release_notes/4.11.0.txt +0 -147
  13. data/doc/release_notes/4.12.0.txt +0 -105
  14. data/doc/release_notes/4.13.0.txt +0 -169
  15. data/doc/release_notes/4.14.0.txt +0 -68
  16. data/doc/release_notes/4.15.0.txt +0 -56
  17. data/doc/release_notes/4.16.0.txt +0 -36
  18. data/doc/release_notes/4.17.0.txt +0 -38
  19. data/doc/release_notes/4.18.0.txt +0 -36
  20. data/doc/release_notes/4.19.0.txt +0 -45
  21. data/doc/release_notes/4.2.0.txt +0 -129
  22. data/doc/release_notes/4.20.0.txt +0 -79
  23. data/doc/release_notes/4.21.0.txt +0 -94
  24. data/doc/release_notes/4.22.0.txt +0 -72
  25. data/doc/release_notes/4.23.0.txt +0 -65
  26. data/doc/release_notes/4.24.0.txt +0 -99
  27. data/doc/release_notes/4.25.0.txt +0 -181
  28. data/doc/release_notes/4.26.0.txt +0 -44
  29. data/doc/release_notes/4.27.0.txt +0 -78
  30. data/doc/release_notes/4.28.0.txt +0 -57
  31. data/doc/release_notes/4.29.0.txt +0 -41
  32. data/doc/release_notes/4.3.0.txt +0 -40
  33. data/doc/release_notes/4.30.0.txt +0 -37
  34. data/doc/release_notes/4.31.0.txt +0 -57
  35. data/doc/release_notes/4.32.0.txt +0 -132
  36. data/doc/release_notes/4.33.0.txt +0 -88
  37. data/doc/release_notes/4.34.0.txt +0 -86
  38. data/doc/release_notes/4.35.0.txt +0 -130
  39. data/doc/release_notes/4.36.0.txt +0 -116
  40. data/doc/release_notes/4.37.0.txt +0 -50
  41. data/doc/release_notes/4.38.0.txt +0 -67
  42. data/doc/release_notes/4.39.0.txt +0 -127
  43. data/doc/release_notes/4.4.0.txt +0 -92
  44. data/doc/release_notes/4.40.0.txt +0 -179
  45. data/doc/release_notes/4.41.0.txt +0 -77
  46. data/doc/release_notes/4.42.0.txt +0 -221
  47. data/doc/release_notes/4.43.0.txt +0 -87
  48. data/doc/release_notes/4.44.0.txt +0 -125
  49. data/doc/release_notes/4.45.0.txt +0 -370
  50. data/doc/release_notes/4.46.0.txt +0 -404
  51. data/doc/release_notes/4.47.0.txt +0 -56
  52. data/doc/release_notes/4.48.0.txt +0 -293
  53. data/doc/release_notes/4.49.0.txt +0 -222
  54. data/doc/release_notes/4.5.0.txt +0 -34
  55. data/doc/release_notes/4.6.0.txt +0 -30
  56. data/doc/release_notes/4.7.0.txt +0 -103
  57. data/doc/release_notes/4.8.0.txt +0 -175
  58. data/doc/release_notes/4.9.0.txt +0 -190
  59. data/spec/adapter_spec.rb +0 -4
  60. data/spec/adapters/db2_spec.rb +0 -170
  61. data/spec/adapters/mssql_spec.rb +0 -828
  62. data/spec/adapters/mysql_spec.rb +0 -1060
  63. data/spec/adapters/oracle_spec.rb +0 -371
  64. data/spec/adapters/postgres_spec.rb +0 -4476
  65. data/spec/adapters/spec_helper.rb +0 -44
  66. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  67. data/spec/adapters/sqlite_spec.rb +0 -652
  68. data/spec/bin_spec.rb +0 -278
  69. data/spec/core/connection_pool_spec.rb +0 -1250
  70. data/spec/core/database_spec.rb +0 -2915
  71. data/spec/core/dataset_spec.rb +0 -5544
  72. data/spec/core/deprecated_spec.rb +0 -70
  73. data/spec/core/expression_filters_spec.rb +0 -1498
  74. data/spec/core/mock_adapter_spec.rb +0 -722
  75. data/spec/core/object_graph_spec.rb +0 -336
  76. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  77. data/spec/core/schema_generator_spec.rb +0 -214
  78. data/spec/core/schema_spec.rb +0 -1844
  79. data/spec/core/spec_helper.rb +0 -24
  80. data/spec/core/version_spec.rb +0 -14
  81. data/spec/core_extensions_spec.rb +0 -763
  82. data/spec/core_model_spec.rb +0 -2
  83. data/spec/core_spec.rb +0 -1
  84. data/spec/deprecation_helper.rb +0 -30
  85. data/spec/extensions/accessed_columns_spec.rb +0 -51
  86. data/spec/extensions/active_model_spec.rb +0 -99
  87. data/spec/extensions/after_initialize_spec.rb +0 -28
  88. data/spec/extensions/any_not_empty_spec.rb +0 -23
  89. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  90. data/spec/extensions/association_dependencies_spec.rb +0 -125
  91. data/spec/extensions/association_multi_add_remove_spec.rb +0 -1041
  92. data/spec/extensions/association_pks_spec.rb +0 -423
  93. data/spec/extensions/association_proxies_spec.rb +0 -100
  94. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  95. data/spec/extensions/auto_validations_spec.rb +0 -229
  96. data/spec/extensions/blacklist_security_spec.rb +0 -95
  97. data/spec/extensions/blank_spec.rb +0 -69
  98. data/spec/extensions/boolean_readers_spec.rb +0 -93
  99. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  100. data/spec/extensions/caching_spec.rb +0 -273
  101. data/spec/extensions/caller_logging_spec.rb +0 -52
  102. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  103. data/spec/extensions/column_conflicts_spec.rb +0 -75
  104. data/spec/extensions/column_select_spec.rb +0 -129
  105. data/spec/extensions/columns_introspection_spec.rb +0 -90
  106. data/spec/extensions/columns_updated_spec.rb +0 -35
  107. data/spec/extensions/composition_spec.rb +0 -248
  108. data/spec/extensions/connection_expiration_spec.rb +0 -151
  109. data/spec/extensions/connection_validator_spec.rb +0 -144
  110. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  111. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  112. data/spec/extensions/constraint_validations_spec.rb +0 -439
  113. data/spec/extensions/core_refinements_spec.rb +0 -528
  114. data/spec/extensions/csv_serializer_spec.rb +0 -183
  115. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  116. data/spec/extensions/dataset_associations_spec.rb +0 -365
  117. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  118. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  119. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  120. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  121. data/spec/extensions/defaults_setter_spec.rb +0 -150
  122. data/spec/extensions/delay_add_association_spec.rb +0 -73
  123. data/spec/extensions/dirty_spec.rb +0 -222
  124. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  125. data/spec/extensions/eager_each_spec.rb +0 -62
  126. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  127. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  128. data/spec/extensions/empty_failure_backtraces_spec.rb +0 -60
  129. data/spec/extensions/error_splitter_spec.rb +0 -18
  130. data/spec/extensions/error_sql_spec.rb +0 -20
  131. data/spec/extensions/escaped_like_spec.rb +0 -40
  132. data/spec/extensions/eval_inspect_spec.rb +0 -81
  133. data/spec/extensions/exclude_or_null_spec.rb +0 -15
  134. data/spec/extensions/finder_spec.rb +0 -260
  135. data/spec/extensions/force_encoding_spec.rb +0 -126
  136. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  137. data/spec/extensions/graph_each_spec.rb +0 -113
  138. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  139. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  140. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  141. data/spec/extensions/index_caching_spec.rb +0 -66
  142. data/spec/extensions/inflector_spec.rb +0 -183
  143. data/spec/extensions/input_transformer_spec.rb +0 -69
  144. data/spec/extensions/insert_conflict_spec.rb +0 -103
  145. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  146. data/spec/extensions/instance_filters_spec.rb +0 -79
  147. data/spec/extensions/instance_hooks_spec.rb +0 -246
  148. data/spec/extensions/integer64_spec.rb +0 -22
  149. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  150. data/spec/extensions/json_serializer_spec.rb +0 -346
  151. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  152. data/spec/extensions/list_spec.rb +0 -291
  153. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  154. data/spec/extensions/many_through_many_spec.rb +0 -2177
  155. data/spec/extensions/migration_spec.rb +0 -864
  156. data/spec/extensions/modification_detection_spec.rb +0 -93
  157. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  158. data/spec/extensions/named_timezones_spec.rb +0 -218
  159. data/spec/extensions/nested_attributes_spec.rb +0 -815
  160. data/spec/extensions/null_dataset_spec.rb +0 -85
  161. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  162. data/spec/extensions/pagination_spec.rb +0 -116
  163. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  164. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  165. data/spec/extensions/pg_array_spec.rb +0 -398
  166. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -209
  167. data/spec/extensions/pg_enum_spec.rb +0 -118
  168. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  169. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  170. data/spec/extensions/pg_hstore_spec.rb +0 -219
  171. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  172. data/spec/extensions/pg_inet_spec.rb +0 -72
  173. data/spec/extensions/pg_interval_spec.rb +0 -103
  174. data/spec/extensions/pg_json_ops_spec.rb +0 -356
  175. data/spec/extensions/pg_json_spec.rb +0 -451
  176. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  177. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  178. data/spec/extensions/pg_range_spec.rb +0 -600
  179. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  180. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  181. data/spec/extensions/pg_row_spec.rb +0 -363
  182. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  183. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  184. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  185. data/spec/extensions/prepared_statements_spec.rb +0 -177
  186. data/spec/extensions/pretty_table_spec.rb +0 -123
  187. data/spec/extensions/query_spec.rb +0 -94
  188. data/spec/extensions/rcte_tree_spec.rb +0 -387
  189. data/spec/extensions/round_timestamps_spec.rb +0 -39
  190. data/spec/extensions/s_spec.rb +0 -60
  191. data/spec/extensions/schema_caching_spec.rb +0 -64
  192. data/spec/extensions/schema_dumper_spec.rb +0 -870
  193. data/spec/extensions/select_remove_spec.rb +0 -38
  194. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  195. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  196. data/spec/extensions/serialization_spec.rb +0 -365
  197. data/spec/extensions/server_block_spec.rb +0 -135
  198. data/spec/extensions/server_logging_spec.rb +0 -45
  199. data/spec/extensions/sharding_spec.rb +0 -197
  200. data/spec/extensions/shared_caching_spec.rb +0 -151
  201. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  202. data/spec/extensions/singular_table_names_spec.rb +0 -22
  203. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  204. data/spec/extensions/spec_helper.rb +0 -70
  205. data/spec/extensions/split_array_nil_spec.rb +0 -24
  206. data/spec/extensions/split_values_spec.rb +0 -57
  207. data/spec/extensions/sql_comments_spec.rb +0 -33
  208. data/spec/extensions/sql_expr_spec.rb +0 -59
  209. data/spec/extensions/static_cache_cache_spec.rb +0 -35
  210. data/spec/extensions/static_cache_spec.rb +0 -471
  211. data/spec/extensions/string_agg_spec.rb +0 -90
  212. data/spec/extensions/string_date_time_spec.rb +0 -95
  213. data/spec/extensions/string_stripper_spec.rb +0 -68
  214. data/spec/extensions/subclasses_spec.rb +0 -79
  215. data/spec/extensions/subset_conditions_spec.rb +0 -38
  216. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  217. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  218. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  219. data/spec/extensions/table_select_spec.rb +0 -83
  220. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  221. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  222. data/spec/extensions/throw_failures_spec.rb +0 -74
  223. data/spec/extensions/timestamps_spec.rb +0 -209
  224. data/spec/extensions/to_dot_spec.rb +0 -153
  225. data/spec/extensions/touch_spec.rb +0 -226
  226. data/spec/extensions/tree_spec.rb +0 -334
  227. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  228. data/spec/extensions/unlimited_update_spec.rb +0 -21
  229. data/spec/extensions/update_or_create_spec.rb +0 -83
  230. data/spec/extensions/update_primary_key_spec.rb +0 -105
  231. data/spec/extensions/update_refresh_spec.rb +0 -59
  232. data/spec/extensions/uuid_spec.rb +0 -101
  233. data/spec/extensions/validate_associated_spec.rb +0 -52
  234. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  235. data/spec/extensions/validation_contexts_spec.rb +0 -31
  236. data/spec/extensions/validation_helpers_spec.rb +0 -525
  237. data/spec/extensions/whitelist_security_spec.rb +0 -157
  238. data/spec/extensions/xml_serializer_spec.rb +0 -213
  239. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  240. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  241. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  242. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  243. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  244. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  245. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  246. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  247. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  248. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  249. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  250. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  251. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  252. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  253. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  254. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  255. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  256. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  257. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  258. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  259. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  260. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  261. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  262. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  263. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  264. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  265. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  266. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  267. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  268. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  269. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  270. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  271. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  272. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  273. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  274. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  275. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  276. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  277. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  278. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  279. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  280. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  281. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  282. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  283. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  284. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  285. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  286. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  287. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  288. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  289. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  290. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  291. data/spec/guards_helper.rb +0 -59
  292. data/spec/integration/associations_test.rb +0 -2597
  293. data/spec/integration/database_test.rb +0 -113
  294. data/spec/integration/dataset_test.rb +0 -2037
  295. data/spec/integration/eager_loader_test.rb +0 -687
  296. data/spec/integration/migrator_test.rb +0 -262
  297. data/spec/integration/model_test.rb +0 -203
  298. data/spec/integration/plugin_test.rb +0 -2423
  299. data/spec/integration/prepared_statement_test.rb +0 -405
  300. data/spec/integration/schema_test.rb +0 -903
  301. data/spec/integration/spec_helper.rb +0 -71
  302. data/spec/integration/timezone_test.rb +0 -86
  303. data/spec/integration/transaction_test.rb +0 -603
  304. data/spec/integration/type_test.rb +0 -127
  305. data/spec/model/association_reflection_spec.rb +0 -803
  306. data/spec/model/associations_spec.rb +0 -4738
  307. data/spec/model/base_spec.rb +0 -875
  308. data/spec/model/class_dataset_methods_spec.rb +0 -146
  309. data/spec/model/dataset_methods_spec.rb +0 -198
  310. data/spec/model/eager_loading_spec.rb +0 -2377
  311. data/spec/model/hooks_spec.rb +0 -370
  312. data/spec/model/inflector_spec.rb +0 -26
  313. data/spec/model/model_spec.rb +0 -956
  314. data/spec/model/plugins_spec.rb +0 -429
  315. data/spec/model/record_spec.rb +0 -2118
  316. data/spec/model/spec_helper.rb +0 -46
  317. data/spec/model/validations_spec.rb +0 -220
  318. data/spec/model_no_assoc_spec.rb +0 -1
  319. data/spec/model_spec.rb +0 -1
  320. data/spec/plugin_spec.rb +0 -1
  321. data/spec/sequel_coverage.rb +0 -15
  322. data/spec/sequel_warning.rb +0 -5
  323. data/spec/spec_config.rb +0 -12
@@ -1,1060 +0,0 @@
1
- SEQUEL_ADAPTER_TEST = :mysql
2
-
3
- require_relative 'spec_helper'
4
-
5
- describe "MySQL", '#create_table' do
6
- before do
7
- @db = DB
8
- @db.test_connection
9
- end
10
- after do
11
- @db.drop_table?(:dolls)
12
- end
13
-
14
- it "should create a temporary table" do
15
- @db.create_table(:tmp_dolls, :temp => true, :engine => 'MyISAM', :charset => 'latin2'){text :name}
16
- @db.table_exists?(:tmp_dolls).must_equal true
17
- @db.disconnect
18
- @db.table_exists?(:tmp_dolls).must_equal false
19
- end
20
-
21
- it "should not use a default for a String :text=>true type" do
22
- @db.create_table(:dolls){String :name, :text=>true, :default=>'blah'}
23
- @db[:dolls].insert
24
- @db[:dolls].all.must_equal [{:name=>nil}]
25
- end
26
-
27
- it "should not use a default for a File type" do
28
- @db.create_table(:dolls){File :name, :default=>'blah'}
29
- @db[:dolls].insert
30
- @db[:dolls].all.must_equal [{:name=>nil}]
31
- end
32
-
33
- it "should respect the size option for File type" do
34
- @db.create_table(:dolls) do
35
- File :n1
36
- File :n2, :size=>:tiny
37
- File :n3, :size=>:medium
38
- File :n4, :size=>:long
39
- File :n5, :size=>255
40
- end
41
- @db.schema(:dolls).map{|k, v| v[:db_type]}.must_equal %w"blob tinyblob mediumblob longblob blob"
42
- end
43
-
44
- it "should include an :auto_increment schema attribute if auto incrementing" do
45
- @db.create_table(:dolls) do
46
- primary_key :n4
47
- Integer :n2
48
- String :n3
49
- end
50
- @db.schema(:dolls).map{|k, v| v[:auto_increment]}.must_equal [true, nil, nil]
51
- end
52
-
53
- it "should support collate with various other column options" do
54
- @db.create_table!(:dolls){ String :name, :size=>128, :collate=>:utf8_bin, :default=>'foo', :null=>false, :unique=>true}
55
- @db[:dolls].insert
56
- @db[:dolls].select_map(:name).must_equal ["foo"]
57
- end
58
-
59
- it "should be able to parse the default value for set and enum types" do
60
- @db.create_table!(:dolls){column :t, "set('a', 'b', 'c', 'd')", :default=>'a,b'}
61
- @db.schema(:dolls).first.last[:ruby_default].must_equal 'a,b'
62
- @db.create_table!(:dolls){column :t, "enum('a', 'b', 'c', 'd')", :default=>'b'}
63
- @db.schema(:dolls).first.last[:ruby_default].must_equal 'b'
64
- end
65
-
66
- it "should allow setting auto_increment for existing column" do
67
- @db.create_table(:dolls){Integer :a, :primary_key=>true}
68
- @db.schema(:dolls).first.last[:auto_increment].must_equal false
69
- @db.set_column_type :dolls, :a, Integer, :auto_increment=>true
70
- @db.schema(:dolls).first.last[:auto_increment].must_equal true
71
- end
72
-
73
- it "should create generated column" do
74
- skip("generated columns not supported, skipping test") unless @db.supports_generated_columns?
75
- @db.create_table(:dolls){String :a; String :b, generated_always_as: Sequel.function(:CONCAT, :a, 'plus')}
76
- @db.schema(:dolls)[1][1][:generated].must_equal true
77
- end
78
- end
79
-
80
- if [:mysql, :mysql2].include?(DB.adapter_scheme)
81
- describe "Sequel::MySQL::Database#convert_tinyint_to_bool" do
82
- before do
83
- @db = DB
84
- @db.create_table(:booltest){column :b, 'tinyint(1)'; column :i, 'tinyint(4)'}
85
- @ds = @db[:booltest]
86
- end
87
- after do
88
- @db.convert_tinyint_to_bool = true
89
- @db.drop_table?(:booltest)
90
- end
91
-
92
- it "should consider tinyint(1) datatypes as boolean if set, but not larger tinyints" do
93
- @db.schema(:booltest, :reload=>true).map{|_, s| s[:type]}.must_equal [:boolean, :integer]
94
- @db.convert_tinyint_to_bool = false
95
- @db.schema(:booltest, :reload=>true).map{|_, s| s[:type]}.must_equal [:integer, :integer]
96
- end
97
-
98
- it "should return tinyint(1)s as bools and tinyint(4)s as integers when set" do
99
- @db.convert_tinyint_to_bool = true
100
- @ds.delete
101
- @ds.insert(:b=>true, :i=>10)
102
- @ds.all.must_equal [{:b=>true, :i=>10}]
103
- @ds.delete
104
- @ds.insert(:b=>false, :i=>0)
105
- @ds.all.must_equal [{:b=>false, :i=>0}]
106
- @ds.delete
107
- @ds.insert(:b=>true, :i=>1)
108
- @ds.all.must_equal [{:b=>true, :i=>1}]
109
- end
110
-
111
- it "should return all tinyints as integers when unset" do
112
- @db.convert_tinyint_to_bool = false
113
- @ds.delete
114
- @ds.insert(:b=>true, :i=>10)
115
- @ds.all.must_equal [{:b=>1, :i=>10}]
116
- @ds.delete
117
- @ds.insert(:b=>false, :i=>0)
118
- @ds.all.must_equal [{:b=>0, :i=>0}]
119
-
120
- @ds.delete
121
- @ds.insert(:b=>1, :i=>10)
122
- @ds.all.must_equal [{:b=>1, :i=>10}]
123
- @ds.delete
124
- @ds.insert(:b=>0, :i=>0)
125
- @ds.all.must_equal [{:b=>0, :i=>0}]
126
- end
127
-
128
- it "should allow disabling the conversion on a per-dataset basis" do
129
- @db.convert_tinyint_to_bool = true
130
- ds = @ds.with_extend do
131
- def cast_tinyint_integer?(f) true end #mysql
132
- def convert_tinyint_to_bool?() false end #mysql2
133
- end
134
- ds.delete
135
- ds.insert(:b=>true, :i=>10)
136
- ds.all.must_equal [{:b=>1, :i=>10}]
137
- @ds.all.must_equal [{:b=>true, :i=>10}]
138
- end
139
- end
140
- end
141
-
142
- describe "A MySQL dataset" do
143
- before do
144
- DB.create_table(:items){String :name; Integer :value}
145
- @d = DB[:items]
146
- end
147
- after do
148
- DB.drop_table?(:items)
149
- end
150
-
151
- it "should handle large unsigned smallint/integer values" do
152
- DB.alter_table(:items){set_column_type :value, 'smallint unsigned'}
153
- @d.insert(:value=>(1 << 15) + 1)
154
- @d.get(:value).must_equal((1 << 15) + 1)
155
- DB.alter_table(:items){set_column_type :value, 'integer unsigned'}
156
- @d.update(:value=>(1 << 31) + 1)
157
- @d.get(:value).must_equal((1 << 31) + 1)
158
- DB.alter_table(:items){set_column_type :value, 'bigint unsigned'}
159
- @d.update(:value=>(1 << 63) + 1)
160
- @d.get(:value).must_equal((1 << 63) + 1)
161
- end
162
-
163
- it "should support ORDER clause in UPDATE statements" do
164
- @d.order(:name).update_sql(:value => 1).must_equal 'UPDATE `items` SET `value` = 1 ORDER BY `name`'
165
- end
166
-
167
- it "should support updating a limited dataset" do
168
- @d.import [:value], [[2], [3]]
169
- @d.limit(1).update(:value => 4).must_equal 1
170
- [[2,4], [3,4]].must_include @d.select_order_map(:value)
171
- end
172
-
173
- it "should support updating a ordered, limited dataset" do
174
- @d.import [:value], [[2], [3]]
175
- @d.order(:value).limit(1).update(:value => 4).must_equal 1
176
- @d.select_order_map(:value).must_equal [3,4]
177
- end
178
-
179
- it "should raise error for updating a dataset with an offset" do
180
- proc{@d.offset(1).update(:value => 4)}.must_raise Sequel::InvalidOperation
181
- proc{@d.order(:value).offset(1).update(:value => 4)}.must_raise Sequel::InvalidOperation
182
- end
183
-
184
- it "should support regexps" do
185
- @d.insert(:name => 'abc', :value => 1)
186
- @d.insert(:name => 'bcd', :value => 2)
187
- @d.filter(:name => /bc/).count.must_equal 2
188
- @d.filter(:name => /^bc/).count.must_equal 1
189
- end
190
-
191
- it "should have explain output" do
192
- @d.explain.must_be_kind_of(String)
193
- @d.explain(:extended=>true).must_be_kind_of(String)
194
- end
195
-
196
- it "should correctly literalize strings with comment backslashes in them" do
197
- @d.delete
198
- @d.insert(:name => ':\\')
199
-
200
- @d.first[:name].must_equal ':\\'
201
- end
202
-
203
- it "should handle prepared statements with on_duplicate_key_update" do
204
- @d.db.add_index :items, :value, :unique=>true
205
- ds = @d.on_duplicate_key_update
206
- ps = ds.prepare(:insert, :insert_user_id_feature_name, :value => :$v, :name => :$n)
207
- ps.call(:v => 1, :n => 'a')
208
- ds.all.must_equal [{:value=>1, :name=>'a'}]
209
- ps.call(:v => 1, :n => 'b')
210
- ds.all.must_equal [{:value=>1, :name=>'b'}]
211
- end
212
-
213
- it "should support generated columns" do
214
- skip("generated columns not supported, skipping test") unless DB.supports_generated_columns?
215
- DB.alter_table(:items) {add_column :b, String, :generated_always_as => Sequel.function(:CONCAT, :name, 'plus')}
216
- @d.insert(name: 'hello')
217
- @d.first[:b].must_equal 'helloplus'
218
- end
219
- end
220
-
221
- describe "Dataset#distinct" do
222
- before do
223
- @db = DB
224
- @db.create_table!(:a) do
225
- Integer :a
226
- Integer :b
227
- end
228
- @ds = @db[:a]
229
- end
230
- after do
231
- @db.drop_table?(:a)
232
- end
233
-
234
- it "#distinct with arguments should return results distinct on those arguments" do
235
- skip("ONLY_FULL_GROUP_BY sql_mode set, skipping DISTINCT ON emulation test") if @db.get(Sequel.lit '@@sql_mode').include?('ONLY_FULL_GROUP_BY')
236
-
237
- @ds.insert(20, 10)
238
- @ds.insert(30, 10)
239
- @ds.order(:b, :a).distinct.map(:a).must_equal [20, 30]
240
- @ds.order(:b, Sequel.desc(:a)).distinct.map(:a).must_equal [30, 20]
241
- # MySQL doesn't respect orders when using the nonstandard GROUP BY
242
- [[20], [30]].must_include(@ds.order(:b, :a).distinct(:b).map(:a))
243
- end
244
- end
245
-
246
- describe "MySQL join expressions" do
247
- before(:all) do
248
- @ds = DB[:nodes]
249
- DB.create_table!(:nodes){Integer :id; Integer :y}
250
- DB.create_table!(:n1){Integer :id}
251
- DB.create_table!(:n2){Integer :y}
252
- @ds.insert(:id=>1, :y=>2)
253
- DB[:n1].insert(1)
254
- DB[:n2].insert(2)
255
- end
256
- after(:all) do
257
- DB.drop_table?(:n2, :n1, :nodes)
258
- end
259
-
260
- it "should support straight joins (force left table to be read before right)" do
261
- @ds.join_table(:straight, :n1).all.must_equal [{:id=>1, :y=>2}]
262
- end
263
- it "should support natural joins on multiple tables." do
264
- @ds.join_table(:natural_left_outer, [:n1, :n2]).all.must_equal [{:id=>1, :y=>2}]
265
- end
266
- it "should support straight joins on multiple tables." do
267
- @ds.join_table(:straight, [:n1, :n2]).all.must_equal [{:id=>1, :y=>2}]
268
- end
269
- end
270
-
271
- describe "A MySQL database" do
272
- after do
273
- DB.drop_table?(:test_innodb)
274
- end
275
-
276
- it "should handle the creation and dropping of an InnoDB table with foreign keys" do
277
- DB.create_table!(:test_innodb, :engine=>:InnoDB){primary_key :id; foreign_key :fk, :test_innodb, :key=>:id}
278
- end
279
-
280
- it "should handle qualified tables in #indexes" do
281
- DB.create_table!(:test_innodb){primary_key :id; String :name; index :name, :unique=>true, :name=>:test_innodb_name_idx}
282
- DB.indexes(Sequel.qualify(DB.get{database.function}, :test_innodb)).must_equal(:test_innodb_name_idx=>{:unique=>true, :columns=>[:name]})
283
- end
284
- end
285
-
286
- describe "A MySQL database" do
287
- before(:all) do
288
- @db = DB
289
- @db.create_table! :test2 do
290
- text :name
291
- Integer :value
292
- end
293
- end
294
- after(:all) do
295
- @db.drop_table?(:test2)
296
- end
297
-
298
- it "should provide the server version" do
299
- @db.server_version.must_be :>=, 40000
300
- end
301
-
302
- it "should support for_share" do
303
- @db[:test2].delete
304
- @db.transaction{@db[:test2].for_share.all.must_equal []}
305
- end
306
-
307
- it "should support column operations" do
308
- @db.add_column :test2, :xyz, :text
309
-
310
- @db[:test2].columns.must_equal [:name, :value, :xyz]
311
- @db[:test2].insert(:name => 'mmm', :value => 111, :xyz => '000')
312
- @db[:test2].first[:xyz].must_equal '000'
313
-
314
- @db[:test2].columns.must_equal [:name, :value, :xyz]
315
- @db.drop_column :test2, :xyz
316
-
317
- @db[:test2].columns.must_equal [:name, :value]
318
-
319
- @db[:test2].delete
320
- @db.add_column :test2, :xyz, :text
321
- @db[:test2].insert(:name => 'mmm', :value => 111, :xyz => 'qqqq')
322
-
323
- @db[:test2].columns.must_equal [:name, :value, :xyz]
324
- @db.rename_column :test2, :xyz, :zyx, :type => :text
325
- @db[:test2].columns.must_equal [:name, :value, :zyx]
326
- @db[:test2].first[:zyx].must_equal 'qqqq'
327
-
328
- @db[:test2].delete
329
- @db.add_column :test2, :tre, :text
330
- @db[:test2].insert(:name => 'mmm', :value => 111, :tre => 'qqqq')
331
-
332
- @db[:test2].columns.must_equal [:name, :value, :zyx, :tre]
333
- @db.rename_column :test2, :tre, :ert, :type => :varchar, :size=>255
334
- @db[:test2].columns.must_equal [:name, :value, :zyx, :ert]
335
- @db[:test2].first[:ert].must_equal 'qqqq'
336
-
337
- @db.add_column :test2, :xyz, :float
338
- @db[:test2].delete
339
- @db[:test2].insert(:name => 'mmm', :value => 111, :xyz => 56.78)
340
- @db.set_column_type :test2, :xyz, :integer
341
-
342
- @db[:test2].first[:xyz].must_equal 57
343
-
344
- @db.alter_table :test2 do
345
- add_index :value, :unique=>true
346
- add_foreign_key :value2, :test2, :key=>:value
347
- end
348
- @db[:test2].columns.must_equal [:name, :value, :zyx, :ert, :xyz, :value2]
349
-
350
- @db.alter_table :test2 do
351
- drop_foreign_key :value2
352
- drop_index :value
353
- end
354
- end
355
- end
356
-
357
- describe "A MySQL database with table options" do
358
- before do
359
- @options = {:engine=>'MyISAM', :charset=>'latin1', :collate => 'latin1_swedish_ci'}
360
-
361
- @db = DB
362
- @db.default_engine = 'InnoDB'
363
- @db.default_charset = 'utf8'
364
- @db.default_collate = 'utf8_general_ci'
365
- @db.drop_table?(:items)
366
- end
367
- after do
368
- @db.drop_table?(:items)
369
-
370
- @db.default_engine = nil
371
- @db.default_charset = nil
372
- @db.default_collate = nil
373
- end
374
-
375
- it "should allow to pass custom options (engine, charset, collate) for table creation" do
376
- @db.create_table(:items, @options){Integer :size; text :name}
377
- @db.transaction(:rollback=>:always) do
378
- @db[:items].insert(:size=>1)
379
- end
380
- @db[:items].all.must_equal [{:size=>1, :name=>nil}]
381
- end
382
-
383
- it "should use default options if specified (engine, charset, collate) for table creation" do
384
- @db.create_table(:items){Integer :size; text :name}
385
- @db.transaction(:rollback=>:always) do
386
- @db[:items].insert(:size=>1)
387
- end
388
- @db[:items].all.must_equal []
389
- end
390
-
391
- it "should not use default if option has a nil value" do
392
- @db.default_engine = 'non_existent_engine'
393
- @db.create_table(:items, :engine=>nil, :charset=>nil, :collate=>nil){Integer :size; text :name}
394
- end
395
- end
396
-
397
- describe "A MySQL database" do
398
- before do
399
- @db = DB
400
- @db.drop_table?(:items)
401
- end
402
- after do
403
- @db.drop_table?(:items, :users)
404
- end
405
-
406
- it "should support defaults for boolean columns" do
407
- @db.create_table(:items){TrueClass :active1, :default=>true; FalseClass :active2, :default => false}
408
- @db[:items].insert
409
- @db[:items].get([:active1, :active2]).must_equal [true, false]
410
- @db[:items].get([Sequel.cast(:active1, Integer).as(:v1), Sequel.cast(:active2, Integer).as(:v2)]).must_equal [1, 0]
411
- end
412
-
413
- it "should correctly handle CREATE TABLE statements with foreign keys" do
414
- @db.create_table(:items){primary_key :id; foreign_key :p_id, :items, :key => :id, :null => false, :on_delete => :cascade}
415
- @db[:items].insert(:id=>1, :p_id=>1)
416
- @db[:items].insert(:id=>2, :p_id=>1)
417
- @db[:items].where(:id=>1).delete
418
- @db[:items].count.must_equal 0
419
- end
420
-
421
- it "should correctly handle CREATE TABLE statements with foreign keys, when :key != the default (:id)" do
422
- @db.create_table(:items){primary_key :id; Integer :other_than_id; foreign_key :p_id, :items, :key => :other_than_id, :null => false, :on_delete => :cascade}
423
- @db[:items].insert(:id=>1, :other_than_id=>2, :p_id=>2)
424
- @db[:items].insert(:id=>2, :other_than_id=>3, :p_id=>2)
425
- @db[:items].where(:id=>1).delete
426
- @db[:items].count.must_equal 0
427
- end
428
-
429
- it "should correctly handle ALTER TABLE statements with foreign keys" do
430
- @db.create_table(:items){Integer :id}
431
- @db.create_table(:users){primary_key :id}
432
- @db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade}
433
- @db[:users].insert(:id=>1)
434
- @db[:items].insert(:id=>2, :p_id=>1)
435
- @db[:users].where(:id=>1).delete
436
- @db[:items].count.must_equal 0
437
- end
438
-
439
- it "should correctly format ALTER TABLE statements with named foreign keys" do
440
- @db.create_table(:items){Integer :id}
441
- @db.create_table(:users){primary_key :id}
442
- @db.alter_table(:items){add_foreign_key :p_id, :users, :key => :id, :null => false, :on_delete => :cascade, :foreign_key_constraint_name => :pk_items__users }
443
- @db[:users].insert(:id=>1)
444
- @db[:items].insert(:id=>2, :p_id=>1)
445
- @db[:users].where(:id=>1).delete
446
- @db[:items].count.must_equal 0
447
- end
448
-
449
- it "should correctly handle add_column :after option" do
450
- @db.create_table(:items){Integer :id; Integer :value}
451
- @db.alter_table(:items){add_column :name, String, :after=>:id}
452
- @db[:items].columns.must_equal [:id, :name, :value]
453
- end
454
-
455
- it "should correctly handle add_column :first option" do
456
- @db.create_table(:items){Integer :id; Integer :value}
457
- @db.alter_table(:items){add_column :name, String, :first => true}
458
- @db[:items].columns.must_equal [:name, :id, :value]
459
- end
460
-
461
- it "should correctly handle add_foreign_key :first option" do
462
- @db.create_table(:items){primary_key :id; Integer :value}
463
- @db.alter_table(:items){add_foreign_key :parent_id, :items, :first => true}
464
- @db[:items].columns.must_equal [:parent_id, :id, :value]
465
- end
466
-
467
- it "should have rename_column support keep existing options" do
468
- @db.create_table(:items){String :id, :null=>false, :default=>'blah'}
469
- @db.alter_table(:items){rename_column :id, :nid}
470
- @db[:items].insert
471
- @db[:items].all.must_equal [{:nid=>'blah'}]
472
- proc{@db[:items].insert(:nid=>nil)}.must_raise(Sequel::NotNullConstraintViolation)
473
- end
474
-
475
- it "should have set_column_type support keep existing options" do
476
- @db.create_table(:items){Integer :id, :null=>false, :default=>5}
477
- @db.alter_table(:items){set_column_type :id, :Bignum}
478
- @db[:items].insert
479
- @db[:items].all.must_equal [{:id=>5}]
480
- proc{@db[:items].insert(:id=>nil)}.must_raise(Sequel::NotNullConstraintViolation)
481
- @db[:items].delete
482
- @db[:items].insert(2**40)
483
- @db[:items].all.must_equal [{:id=>2**40}]
484
- end
485
-
486
- it "should have set_column_type pass through options" do
487
- @db.create_table(:items){integer :id; enum :list, :elements=>%w[one]}
488
- @db.alter_table(:items){set_column_type :id, :int, :unsigned=>true, :size=>8; set_column_type :list, :enum, :elements=>%w[two]}
489
- @db.schema(:items)[1][1][:db_type].must_equal "enum('two')"
490
- end
491
-
492
- it "should have set_column_default support keep existing options" do
493
- @db.create_table(:items){Integer :id, :null=>false, :default=>5}
494
- @db.alter_table(:items){set_column_default :id, 6}
495
- @db[:items].insert
496
- @db[:items].all.must_equal [{:id=>6}]
497
- proc{@db[:items].insert(:id=>nil)}.must_raise(Sequel::NotNullConstraintViolation)
498
- end
499
-
500
- it "should have set_column_allow_null support keep existing options" do
501
- @db.create_table(:items){Integer :id, :null=>false, :default=>5}
502
- @db.alter_table(:items){set_column_allow_null :id, true}
503
- @db[:items].insert
504
- @db[:items].all.must_equal [{:id=>5}]
505
- @db[:items].insert(:id=>nil)
506
- end
507
-
508
- it "should accept repeated raw sql statements using Database#<<" do
509
- @db.create_table(:items){String :name; Integer :value}
510
- @db << 'DELETE FROM items'
511
- @db[:items].count.must_equal 0
512
-
513
- @db << "INSERT INTO items (name, value) VALUES ('tutu', 1234)"
514
- @db[:items].first.must_equal(:name => 'tutu', :value => 1234)
515
-
516
- @db << 'DELETE FROM items'
517
- @db[:items].first.must_be_nil
518
- end
519
-
520
- it "should have schema handle generated columns" do
521
- skip("generated columns not supported, skipping test") unless @db.supports_generated_columns?
522
- @db.create_table(:items) {String :a}
523
- @db.alter_table(:items){add_column :b, String, :generated_always_as=>Sequel.function(:CONCAT, :a, 'plus'), :generated_type=>:stored, :unique=>true}
524
- @db.schema(:items)[1][1][:generated].must_equal true
525
- @db.alter_table(:items){add_column :c, String, :generated_always_as=>Sequel.function(:CONCAT, :a, 'minus'), :generated_type=>:virtual}
526
- @db.schema(:items)[2][1][:generated].must_equal true
527
- end
528
- end
529
-
530
- # Socket tests should only be run if the MySQL server is on localhost
531
- if DB.adapter_scheme == :mysql && %w'localhost 127.0.0.1 ::1'.include?(URI.parse(DB.uri).host)
532
- describe "A MySQL database" do
533
- socket_file = defined?(MYSQL_SOCKET_FILE) ? MYSQL_SOCKET_FILE : '/tmp/mysql.sock'
534
-
535
- it "should accept a socket option" do
536
- Sequel.mysql(DB.opts[:database], :host => 'localhost', :user => DB.opts[:user], :password => DB.opts[:password], :socket => socket_file, :keep_reference=>false)
537
- end
538
-
539
- it "should accept a socket option without host option" do
540
- Sequel.mysql(DB.opts[:database], :user => DB.opts[:user], :password => DB.opts[:password], :socket => socket_file, :keep_reference=>false)
541
- end
542
-
543
- it "should fail to connect with invalid socket" do
544
- proc{Sequel.mysql(DB.opts[:database], :user => DB.opts[:user], :password => DB.opts[:password], :socket =>'blah', :keep_reference=>false)}.must_raise Sequel::DatabaseConnectionError
545
- end
546
- end
547
- end
548
-
549
- describe "A MySQL database" do
550
- it "should accept a read_timeout option when connecting" do
551
- db = Sequel.connect(DB.opts.merge(:read_timeout=>22342))
552
- db.test_connection
553
- end
554
- end
555
-
556
- describe "MySQL foreign key support" do
557
- after do
558
- DB.drop_table?(:testfk, :testpk)
559
- end
560
-
561
- it "should create table without :key" do
562
- DB.create_table!(:testpk){primary_key :id}
563
- DB.create_table!(:testfk){foreign_key :fk, :testpk}
564
- end
565
-
566
- it "should create table with composite keys without :key" do
567
- DB.create_table!(:testpk){Integer :id; Integer :id2; primary_key([:id, :id2])}
568
- DB.create_table!(:testfk){Integer :fk; Integer :fk2; foreign_key([:fk, :fk2], :testpk)}
569
- end
570
-
571
- it "should create table with self referential without :key" do
572
- DB.create_table!(:testfk){primary_key :id; foreign_key :fk, :testfk}
573
- end
574
-
575
- it "should create table with self referential with non-autoincrementing key without :key" do
576
- DB.create_table!(:testfk){Integer :id, :primary_key=>true; foreign_key :fk, :testfk}
577
- end
578
-
579
- it "should create table with self referential with composite keys without :key" do
580
- DB.create_table!(:testfk){Integer :id; Integer :id2; Integer :fk; Integer :fk2; primary_key([:id, :id2]); foreign_key([:fk, :fk2], :testfk)}
581
- end
582
-
583
- it "should alter table without :key" do
584
- DB.create_table!(:testpk){primary_key :id}
585
- DB.create_table!(:testfk){Integer :id}
586
- DB.alter_table(:testfk){add_foreign_key :fk, :testpk}
587
- end
588
-
589
- it "should alter table with composite keys without :key" do
590
- DB.create_table!(:testpk){Integer :id; Integer :id2; primary_key([:id, :id2])}
591
- DB.create_table!(:testfk){Integer :fk; Integer :fk2}
592
- DB.alter_table(:testfk){add_foreign_key([:fk, :fk2], :testpk)}
593
- end
594
-
595
- it "should alter table with self referential without :key" do
596
- DB.create_table!(:testfk){primary_key :id}
597
- DB.alter_table(:testfk){add_foreign_key :fk, :testfk}
598
- end
599
-
600
- it "should alter table with self referential with composite keys without :key" do
601
- DB.create_table!(:testfk){Integer :id; Integer :id2; Integer :fk; Integer :fk2; primary_key([:id, :id2])}
602
- DB.alter_table(:testfk){add_foreign_key [:fk, :fk2], :testfk}
603
- end
604
- end
605
-
606
- describe "A grouped MySQL dataset" do
607
- before do
608
- DB.create_table! :test2 do
609
- text :name
610
- integer :value
611
- end
612
- DB[:test2].insert(:name => '11', :value => 10)
613
- DB[:test2].insert(:name => '11', :value => 20)
614
- DB[:test2].insert(:name => '11', :value => 30)
615
- DB[:test2].insert(:name => '12', :value => 10)
616
- DB[:test2].insert(:name => '12', :value => 20)
617
- DB[:test2].insert(:name => '13', :value => 10)
618
- end
619
- after do
620
- DB.drop_table?(:test2)
621
- end
622
-
623
- it "should return the correct count for raw sql query" do
624
- ds = DB["select name FROM test2 WHERE name = '11' GROUP BY name"]
625
- ds.count.must_equal 1
626
- end
627
-
628
- it "should return the correct count for a normal dataset" do
629
- ds = DB[:test2].select(:name).where(:name => '11').group(:name)
630
- ds.count.must_equal 1
631
- end
632
- end
633
-
634
- describe "A MySQL database" do
635
- before do
636
- @db = DB
637
- @db.drop_table?(:posts)
638
- end
639
- after do
640
- @db.drop_table?(:posts)
641
- end
642
-
643
- it "should support fulltext indexes and full_text_search" do
644
- @db.create_table(:posts, :engine=>:MyISAM){text :title; text :body; full_text_index :title; full_text_index [:title, :body]}
645
-
646
- @db[:posts].insert(:title=>'ruby rails', :body=>'y')
647
- @db[:posts].insert(:title=>'sequel', :body=>'ruby')
648
- @db[:posts].insert(:title=>'ruby scooby', :body=>'x')
649
-
650
- @db[:posts].full_text_search(:title, 'rails').all.must_equal [{:title=>'ruby rails', :body=>'y'}]
651
- @db[:posts].full_text_search([:title, :body], ['sequel', 'ruby']).all.must_equal [{:title=>'sequel', :body=>'ruby'}]
652
- @db[:posts].full_text_search(:title, '+ruby -rails', :boolean => true).all.must_equal [{:title=>'ruby scooby', :body=>'x'}]
653
-
654
- @db[:posts].full_text_search(:title, :$n).call(:select, :n=>'rails').must_equal [{:title=>'ruby rails', :body=>'y'}]
655
- @db[:posts].full_text_search(:title, :$n).prepare(:select, :fts_select).call(:n=>'rails').must_equal [{:title=>'ruby rails', :body=>'y'}]
656
- end
657
-
658
- it "should support spatial indexes" do
659
- @db.create_table(:posts, :engine=>:MyISAM){point :geom, :null=>false; spatial_index [:geom]}
660
- end
661
-
662
- it "should support indexes with index type" do
663
- @db.create_table(:posts){Integer :id; index :id, :type => :btree}
664
- @db[:posts].insert(1)
665
- @db[:posts].where(:id=>1).count.must_equal 1
666
- end
667
-
668
- it "should support unique indexes with index type" do
669
- @db.create_table(:posts){Integer :id; index :id, :type => :btree, :unique => true}
670
- @db[:posts].insert(1)
671
- proc{@db[:posts].insert(1)}.must_raise Sequel::UniqueConstraintViolation
672
- end
673
-
674
- it "should not dump partial indexes" do
675
- @db.create_table(:posts){text :id}
676
- @db << "CREATE INDEX posts_id_index ON posts (id(10))"
677
- @db.indexes(:posts).must_equal({})
678
- end
679
-
680
- it "should dump partial indexes if :partial option is set to true" do
681
- @db.create_table(:posts){text :id}
682
- @db << "CREATE INDEX posts_id_index ON posts (id(10))"
683
- @db.indexes(:posts, :partial => true).must_equal(:posts_id_index => {:columns => [:id], :unique => false})
684
- end
685
- end
686
-
687
- describe "MySQL::Dataset#insert and related methods" do
688
- before do
689
- DB.create_table(:items){String :name, :unique=>true; Integer :value}
690
- @d = DB[:items].order(:name)
691
- end
692
- after do
693
- DB.drop_table?(:items)
694
- end
695
-
696
- it "#insert should insert record with default values when no arguments given" do
697
- @d.insert
698
- @d.all.must_equal [{:name => nil, :value => nil}]
699
- end
700
-
701
- it "#insert should insert record with default values when empty hash given" do
702
- @d.insert({})
703
- @d.all.must_equal [{:name => nil, :value => nil}]
704
- end
705
-
706
- it "#insert should insert record with default values when empty array given" do
707
- @d.insert []
708
- @d.all.must_equal [{:name => nil, :value => nil}]
709
- end
710
-
711
- it "#on_duplicate_key_update should work with regular inserts" do
712
- DB.add_index :items, :name, :unique=>true
713
- @d.insert(:name => 'abc', :value => 1)
714
- @d.on_duplicate_key_update(:name, :value => 6).insert(:name => 'abc', :value => 1)
715
- @d.on_duplicate_key_update(:name, :value => 6).insert(:name => 'def', :value => 2)
716
- @d.all.must_equal [{:name => 'abc', :value => 6}, {:name => 'def', :value => 2}]
717
- end
718
-
719
- it "#multi_replace should replace multiple records in a single statement" do
720
- @d.multi_replace([{:name => 'abc'}, {:name => 'def'}])
721
- @d.all.must_equal [ {:name => 'abc', :value => nil}, {:name => 'def', :value => nil} ]
722
- @d.multi_replace([{:name => 'abc', :value=>1}, {:name => 'ghi', :value=>3}])
723
- @d.all.must_equal [ {:name => 'abc', :value => 1}, {:name => 'def', :value => nil}, {:name => 'ghi', :value=>3} ]
724
- end
725
-
726
- it "#multi_replace should support :commit_every option" do
727
- @d.multi_replace([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}], :commit_every => 2)
728
- @d.all.must_equal [ {:name => nil, :value => 1}, {:name => nil, :value => 2}, {:name => nil, :value => 3}, {:name => nil, :value => 4} ]
729
- end
730
-
731
- it "#multi_replace should support :slice option" do
732
- @d.multi_replace([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}], :slice => 2)
733
- @d.all.must_equal [ {:name => nil, :value => 1}, {:name => nil, :value => 2}, {:name => nil, :value => 3}, {:name => nil, :value => 4} ]
734
- end
735
-
736
- it "#multi_insert should insert multiple records in a single statement" do
737
- @d.multi_insert([{:name => 'abc'}, {:name => 'def'}])
738
- @d.all.must_equal [ {:name => 'abc', :value => nil}, {:name => 'def', :value => nil} ]
739
- end
740
-
741
- it "#multi_insert should support :commit_every option" do
742
- @d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}], :commit_every => 2)
743
- @d.all.must_equal [ {:name => nil, :value => 1}, {:name => nil, :value => 2}, {:name => nil, :value => 3}, {:name => nil, :value => 4} ]
744
- end
745
-
746
- it "#multi_insert should support :slice option" do
747
- @d.multi_insert([{:value => 1}, {:value => 2}, {:value => 3}, {:value => 4}], :slice => 2)
748
- @d.all.must_equal [ {:name => nil, :value => 1}, {:name => nil, :value => 2}, {:name => nil, :value => 3}, {:name => nil, :value => 4} ]
749
- end
750
-
751
- it "#import should support inserting using columns and values arrays" do
752
- @d.import([:name, :value], [['abc', 1], ['def', 2]])
753
- @d.all.must_equal [ {:name => 'abc', :value => 1}, {:name => 'def', :value => 2} ]
754
- end
755
-
756
- it "#insert_ignore should ignore existing records when used with multi_insert" do
757
- @d.insert_ignore.multi_insert([{:name => 'abc'}, {:name => 'def'}])
758
- @d.all.must_equal [ {:name => 'abc', :value => nil}, {:name => 'def', :value => nil} ]
759
- @d.insert_ignore.multi_insert([{:name => 'abc', :value=>1}, {:name => 'ghi', :value=>3}])
760
- @d.all.must_equal [ {:name => 'abc', :value => nil}, {:name => 'def', :value => nil}, {:name => 'ghi', :value=>3} ]
761
- end
762
-
763
- it "#insert_ignore should ignore single records when used with insert" do
764
- @d.insert_ignore.insert(:name => 'ghi')
765
- @d.all.must_equal [{:name => 'ghi', :value => nil}]
766
- @d.insert_ignore.insert(:name => 'ghi', :value=>2)
767
- @d.all.must_equal [{:name => 'ghi', :value => nil}]
768
- end
769
-
770
- it "#on_duplicate_key_update should handle inserts with duplicate keys" do
771
- @d.on_duplicate_key_update.import([:name,:value], [['abc', 1], ['def',2]])
772
- @d.all.must_equal [ {:name => 'abc', :value => 1}, {:name => 'def', :value => 2} ]
773
- @d.on_duplicate_key_update.import([:name,:value], [['abc', 2], ['ghi',3]])
774
- @d.all.must_equal [ {:name => 'abc', :value => 2}, {:name => 'def', :value => 2}, {:name => 'ghi', :value=>3} ]
775
- end
776
-
777
- it "#on_duplicate_key_update should add the ON DUPLICATE KEY UPDATE and columns specified when args are given" do
778
- @d.on_duplicate_key_update(:value).import([:name,:value], [['abc', 1], ['def',2]])
779
- @d.all.must_equal [ {:name => 'abc', :value => 1}, {:name => 'def', :value => 2} ]
780
- @d.on_duplicate_key_update(:value).import([:name,:value], [['abc', 2], ['ghi',3]])
781
- @d.all.must_equal [ {:name => 'abc', :value => 2}, {:name => 'def', :value => 2}, {:name => 'ghi', :value=>3} ]
782
- @d.on_duplicate_key_update(:name).import([:name,:value], [['abc', 5], ['ghi',6]])
783
- @d.all.must_equal [ {:name => 'abc', :value => 2}, {:name => 'def', :value => 2}, {:name => 'ghi', :value=>3} ]
784
- end
785
- end
786
-
787
- describe "MySQL::Dataset#update and related methods" do
788
- before do
789
- DB.create_table(:items){String :name; Integer :value; index :name, :unique=>true}
790
- @d = DB[:items]
791
- end
792
- after do
793
- DB.drop_table?(:items)
794
- end
795
-
796
- it "#update_ignore should not raise error where normal update would fail" do
797
- @d.insert(:name => 'cow', :value => 0)
798
- @d.insert(:name => 'cat', :value => 1)
799
- proc{@d.where(:value => 1).update(:name => 'cow')}.must_raise(Sequel::UniqueConstraintViolation)
800
- @d.update_ignore.where(:value => 1).update(:name => 'cow')
801
- @d.order(:name).all.must_equal [{:name => 'cat', :value => 1}, {:name => 'cow', :value => 0}]
802
- end
803
- end
804
-
805
- describe "MySQL::Dataset#replace" do
806
- before do
807
- DB.create_table(:items){Integer :id, :unique=>true; Integer :value}
808
- @d = DB[:items]
809
- end
810
- after do
811
- DB.drop_table?(:items)
812
- end
813
-
814
- it "should use default values if they exist" do
815
- DB.alter_table(:items){set_column_default :id, 1; set_column_default :value, 2}
816
- @d.replace
817
- @d.all.must_equal [{:id=>1, :value=>2}]
818
- @d.replace([])
819
- @d.all.must_equal [{:id=>1, :value=>2}]
820
- @d.replace({})
821
- @d.all.must_equal [{:id=>1, :value=>2}]
822
- end
823
- end
824
-
825
- describe "MySQL::Dataset#complex_expression_sql" do
826
- before do
827
- @d = DB.dataset
828
- end
829
-
830
- it "should handle string concatenation with CONCAT if more than one record" do
831
- @d.literal(Sequel.join([:x, :y])).must_equal "CONCAT(`x`, `y`)"
832
- @d.literal(Sequel.join([:x, :y], ' ')).must_equal "CONCAT(`x`, ' ', `y`)"
833
- @d.literal(Sequel.join([Sequel.function(:x, :y), 1, Sequel.lit('z')], Sequel.subscript(:y, 1))).must_equal "CONCAT(x(`y`), `y`[1], '1', `y`[1], z)"
834
- end
835
-
836
- it "should handle string concatenation as simple string if just one record" do
837
- @d.literal(Sequel.join([:x])).must_equal "`x`"
838
- @d.literal(Sequel.join([:x], ' ')).must_equal "`x`"
839
- end
840
- end
841
-
842
- describe "MySQL::Dataset#calc_found_rows" do
843
- before do
844
- DB.create_table!(:items){Integer :a}
845
- end
846
- after do
847
- DB.drop_table?(:items)
848
- end
849
-
850
- it "should count matching rows disregarding LIMIT clause" do
851
- DB[:items].multi_insert([{:a => 1}, {:a => 1}, {:a => 2}])
852
-
853
- DB.synchronize do
854
- DB[:items].calc_found_rows.filter(:a => 1).limit(1).all.must_equal [{:a => 1}]
855
- DB.dataset.select(Sequel.function(:FOUND_ROWS).as(:rows)).all.must_equal [{:rows => 2 }]
856
- end
857
- end
858
- end
859
-
860
- if DB.adapter_scheme == :mysql or DB.adapter_scheme == :jdbc or DB.adapter_scheme == :mysql2
861
- describe "MySQL Stored Procedures" do
862
- before do
863
- DB.create_table(:items){Integer :id; Integer :value}
864
- @d = DB[:items]
865
- end
866
- after do
867
- DB.drop_table?(:items)
868
- DB.execute('DROP PROCEDURE test_sproc')
869
- end
870
-
871
- it "should be callable on the database object" do
872
- DB.execute_ddl('CREATE PROCEDURE test_sproc() BEGIN DELETE FROM items; END')
873
- DB[:items].delete
874
- DB[:items].insert(:value=>1)
875
- DB[:items].count.must_equal 1
876
- DB.call_sproc(:test_sproc)
877
- DB[:items].count.must_equal 0
878
- end
879
-
880
- # Mysql2 doesn't support stored procedures that return result sets, probably because
881
- # CLIENT_MULTI_RESULTS is not set.
882
- unless DB.adapter_scheme == :mysql2
883
- it "should be callable on the dataset object" do
884
- DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER) BEGIN SELECT *, a AS b FROM items; END')
885
- DB[:items].delete
886
- @d = DB[:items]
887
- @d.call_sproc(:select, :test_sproc, 3).must_equal []
888
- @d.insert(:value=>1)
889
- @d.call_sproc(:select, :test_sproc, 4).must_equal [{:id=>nil, :value=>1, :b=>4}]
890
- @d = @d.with_row_proc(proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r})
891
- @d.call_sproc(:select, :test_sproc, 3).must_equal [{:id=>nil, :value=>2, :b=>6}]
892
- end
893
-
894
- it "should be callable on the dataset object with multiple arguments" do
895
- DB.execute_ddl('CREATE PROCEDURE test_sproc(a INTEGER, c INTEGER) BEGIN SELECT *, a AS b, c AS d FROM items; END')
896
- DB[:items].delete
897
- @d = DB[:items]
898
- @d.call_sproc(:select, :test_sproc, 3, 4).must_equal []
899
- @d.insert(:value=>1)
900
- @d.call_sproc(:select, :test_sproc, 4, 5).must_equal [{:id=>nil, :value=>1, :b=>4, :d=>5}]
901
- @d = @d.with_row_proc(proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r})
902
- @d.call_sproc(:select, :test_sproc, 3, 4).must_equal [{:id=>nil, :value=>2, :b=>6, :d => 8}]
903
- end
904
- end
905
-
906
- it "should deal with nil values" do
907
- DB.execute_ddl('CREATE PROCEDURE test_sproc(i INTEGER, v INTEGER) BEGIN INSERT INTO items VALUES (i, v); END')
908
- DB[:items].delete
909
- DB.call_sproc(:test_sproc, :args=>[1, nil])
910
- DB[:items].all.must_equal [{:id=>1, :value=>nil}]
911
- end
912
- end
913
- end
914
-
915
- if DB.adapter_scheme == :mysql
916
- describe "MySQL bad date/time conversions" do
917
- after do
918
- DB.convert_invalid_date_time = false
919
- end
920
-
921
- it "should raise an exception when a bad date/time is used and convert_invalid_date_time is false" do
922
- DB.convert_invalid_date_time = false
923
- proc{DB["SELECT CAST('0000-00-00' AS date)"].single_value}.must_raise(Sequel::InvalidValue)
924
- proc{DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value}.must_raise(Sequel::InvalidValue)
925
- proc{DB["SELECT CAST('25:00:00' AS time)"].single_value}.must_raise(Sequel::InvalidValue)
926
- end
927
-
928
- it "should not use a nil value bad date/time is used and convert_invalid_date_time is nil or :nil" do
929
- DB.convert_invalid_date_time = nil
930
- DB["SELECT CAST('0000-00-00' AS date)"].single_value.must_be_nil
931
- DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.must_be_nil
932
- DB["SELECT CAST('25:00:00' AS time)"].single_value.must_be_nil
933
- DB.convert_invalid_date_time = :nil
934
- DB["SELECT CAST('0000-00-00' AS date)"].single_value.must_be_nil
935
- DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.must_be_nil
936
- DB["SELECT CAST('25:00:00' AS time)"].single_value.must_be_nil
937
- end
938
-
939
- it "should not use a nil value bad date/time is used and convert_invalid_date_time is :string" do
940
- DB.convert_invalid_date_time = :string
941
- DB["SELECT CAST('0000-00-00' AS date)"].single_value.must_equal '0000-00-00'
942
- DB["SELECT CAST('0000-00-00 00:00:00' AS datetime)"].single_value.must_equal '0000-00-00 00:00:00'
943
- DB["SELECT CAST('25:00:00' AS time)"].single_value.must_equal '25:00:00'
944
- end
945
- end
946
-
947
- describe "MySQL multiple result sets" do
948
- before do
949
- DB.create_table!(:a){Integer :a}
950
- DB.create_table!(:b){Integer :b}
951
- @ds = DB['SELECT * FROM a; SELECT * FROM b']
952
- DB[:a].insert(10)
953
- DB[:a].insert(15)
954
- DB[:b].insert(20)
955
- DB[:b].insert(25)
956
- end
957
- after do
958
- DB.drop_table?(:a, :b)
959
- end
960
-
961
- it "should combine all results by default" do
962
- @ds.all.must_equal [{:a=>10}, {:a=>15}, {:b=>20}, {:b=>25}]
963
- end
964
-
965
- it "should work with Database#run" do
966
- DB.run('SELECT * FROM a; SELECT * FROM b')
967
- DB.run('SELECT * FROM a; SELECT * FROM b')
968
- end
969
-
970
- it "should work with Database#run and other statements" do
971
- DB.run('UPDATE a SET a = 1; SELECT * FROM a; DELETE FROM b')
972
- DB[:a].select_order_map(:a).must_equal [1, 1]
973
- DB[:b].all.must_equal []
974
- end
975
-
976
- it "should split results returned into arrays if split_multiple_result_sets is used" do
977
- @ds.split_multiple_result_sets.all.must_equal [[{:a=>10}, {:a=>15}], [{:b=>20}, {:b=>25}]]
978
- end
979
-
980
- it "should have regular row_procs work when splitting multiple result sets" do
981
- @ds = @ds.with_row_proc(proc{|x| x[x.keys.first] *= 2; x})
982
- @ds.split_multiple_result_sets.all.must_equal [[{:a=>20}, {:a=>30}], [{:b=>40}, {:b=>50}]]
983
- end
984
-
985
- it "should use the columns from the first result set when splitting result sets" do
986
- @ds.split_multiple_result_sets.columns.must_equal [:a]
987
- end
988
-
989
- it "should not allow graphing a dataset that splits multiple statements" do
990
- proc{@ds.split_multiple_result_sets.graph(:b, :b=>:a)}.must_raise(Sequel::Error)
991
- end
992
-
993
- it "should not allow splitting a graphed dataset" do
994
- proc{DB[:a].graph(:b, :b=>:a).split_multiple_result_sets}.must_raise(Sequel::Error)
995
- end
996
- end
997
- end
998
-
999
- if DB.adapter_scheme == :mysql2
1000
- describe "Mysql2 streaming" do
1001
- before(:all) do
1002
- DB.create_table!(:a){Integer :a}
1003
- DB.transaction do
1004
- 1000.times do |i|
1005
- DB[:a].insert(i)
1006
- end
1007
- end
1008
- @ds = DB[:a].stream.order(:a)
1009
- end
1010
- after(:all) do
1011
- DB.drop_table?(:a)
1012
- end
1013
-
1014
- it "should correctly stream results" do
1015
- @ds.map(:a).must_equal((0...1000).to_a)
1016
- end
1017
-
1018
- it "should correctly handle early returning when streaming results" do
1019
- 3.times{@ds.each{|r| break r[:a]}.must_equal 0}
1020
- end
1021
-
1022
- it "#paged_each should bypass streaming when :stream => false passed in" do
1023
- DB[:a].order(:a).paged_each(:stream => false){|x| DB[:a].first; break}
1024
- end
1025
- end
1026
- end
1027
-
1028
- describe "MySQL joined datasets" do
1029
- before do
1030
- @db = DB
1031
- @db.create_table!(:a) do
1032
- Integer :id
1033
- end
1034
- @db.create_table!(:b) do
1035
- Integer :id
1036
- Integer :a_id
1037
- end
1038
- @db[:a].insert(1)
1039
- @db[:a].insert(2)
1040
- @db[:b].insert(3, 1)
1041
- @db[:b].insert(4, 1)
1042
- @db[:b].insert(5, 2)
1043
- @ds = @db[:a].join(:b, :a_id=>:id)
1044
- end
1045
- after do
1046
- @db.drop_table?(:a, :b)
1047
- end
1048
-
1049
- it "should support deletions from a single table" do
1050
- @ds.where(Sequel[:a][:id]=>1).delete
1051
- @db[:a].select_order_map(:id).must_equal [2]
1052
- @db[:b].select_order_map(:id).must_equal [3, 4, 5]
1053
- end
1054
-
1055
- it "should support deletions from multiple tables" do
1056
- @ds.delete_from(:a, :b).where(Sequel[:a][:id]=>1).delete
1057
- @db[:a].select_order_map(:id).must_equal [2]
1058
- @db[:b].select_order_map(:id).must_equal [5]
1059
- end
1060
- end