sequel 5.29.0 → 5.30.0

Sign up to get free protection for your applications and to get access to all the features.
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