sequel 3.21.0 → 3.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,6 +1,5 @@
1
- require 'mysql2' unless defined? Mysql2
2
-
3
- Sequel.require %w'shared/mysql', 'adapters'
1
+ require 'mysql2'
2
+ Sequel.require %w'shared/mysql_prepared_statements', 'adapters'
4
3
 
5
4
  module Sequel
6
5
  # Module for holding all Mysql2-related classes and modules for Sequel.
@@ -8,11 +7,18 @@ module Sequel
8
7
  # Database class for MySQL databases used with Sequel.
9
8
  class Database < Sequel::Database
10
9
  include Sequel::MySQL::DatabaseMethods
11
-
12
- # Mysql::Error messages that indicate the current connection should be disconnected
13
- MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away)/
10
+ include Sequel::MySQL::PreparedStatements::DatabaseMethods
14
11
 
15
12
  set_adapter_scheme :mysql2
13
+
14
+ # Whether to convert tinyint columns to bool for this database
15
+ attr_accessor :convert_tinyint_to_bool
16
+
17
+ # Set the convert_tinyint_to_bool setting based on the default value.
18
+ def initialize(opts={})
19
+ super
20
+ self.convert_tinyint_to_bool = Sequel::MySQL.convert_tinyint_to_bool
21
+ end
16
22
 
17
23
  # Connect to the database. In addition to the usual database options,
18
24
  # the following options have effect:
@@ -21,7 +27,6 @@ module Sequel
21
27
  # a filter for an autoincrement column equals NULL to return the last
22
28
  # inserted row.
23
29
  # * :charset - Same as :encoding (:encoding takes precendence)
24
- # * :compress - Set to false to not compress results from the server
25
30
  # * :config_default_group - The default group to read from the in
26
31
  # the MySQL config file.
27
32
  # * :config_local_infile - If provided, sets the Mysql::OPT_LOCAL_INFILE
@@ -37,42 +42,34 @@ module Sequel
37
42
  opts = server_opts(server)
38
43
  opts[:host] ||= 'localhost'
39
44
  opts[:username] ||= opts[:user]
45
+ opts[:flags] = ::Mysql2::Client::FOUND_ROWS if ::Mysql2::Client.const_defined?(:FOUND_ROWS)
40
46
  conn = ::Mysql2::Client.new(opts)
47
+ conn.query_options.merge!(:symbolize_keys=>true, :cache_rows=>false)
48
+
49
+ sqls = mysql_connection_setting_sqls
41
50
 
42
- sqls = []
43
51
  # Set encoding a slightly different way after connecting,
44
52
  # in case the READ_DEFAULT_GROUP overrode the provided encoding.
45
53
  # Doesn't work across implicit reconnects, but Sequel doesn't turn on
46
54
  # that feature.
47
55
  if encoding = opts[:encoding] || opts[:charset]
48
- sqls << "SET NAMES #{conn.escape(encoding.to_s)}"
56
+ sqls.unshift("SET NAMES #{conn.escape(encoding.to_s)}")
49
57
  end
50
58
 
51
- # Increase timeout so mysql server doesn't disconnect us.
52
- # Value used by default is maximum allowed value on Windows.
53
- sqls << "SET @@wait_timeout = #{opts[:timeout] || 2147483}"
54
-
55
- # By default, MySQL 'where id is null' selects the last inserted id
56
- sqls << "SET SQL_AUTO_IS_NULL=0" unless opts[:auto_is_null]
57
-
58
59
  sqls.each{|sql| log_yield(sql){conn.query(sql)}}
59
60
 
61
+ add_prepared_statements_cache(conn)
60
62
  conn
61
63
  end
62
64
 
63
- # Returns instance of Sequel::MySQL::Dataset with the given options.
64
- def dataset(opts = nil)
65
- Mysql2::Dataset.new(self, opts)
65
+ # Return the number of matched rows when executing a delete/update statement.
66
+ def execute_dui(sql, opts={})
67
+ execute(sql, opts){|c| return c.affected_rows}
66
68
  end
67
69
 
68
- # Executes the given SQL using an available connection, yielding the
69
- # connection if the block is given.
70
- def execute(sql, opts={}, &block)
71
- if opts[:sproc]
72
- call_sproc(sql, opts, &block)
73
- else
74
- synchronize(opts[:server]){|conn| _execute(conn, sql, opts, &block)}
75
- end
70
+ # Return the last inserted id when executing an insert statement.
71
+ def execute_insert(sql, opts={})
72
+ execute(sql, opts){|c| return c.last_id}
76
73
  end
77
74
 
78
75
  # Return the version of the MySQL server two which we are connecting.
@@ -87,14 +84,14 @@ module Sequel
87
84
  # yield the connection if a block is given.
88
85
  def _execute(conn, sql, opts)
89
86
  begin
90
- r = log_yield(sql){conn.query(sql, :symbolize_keys => true, :database_timezone => Sequel.database_timezone, :application_timezone => Sequel.application_timezone)}
87
+ r = log_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql){conn.query(sql, :database_timezone => timezone, :application_timezone => Sequel.application_timezone)}
91
88
  if opts[:type] == :select
92
89
  yield r if r
93
90
  elsif block_given?
94
91
  yield conn
95
92
  end
96
93
  rescue ::Mysql2::Error => e
97
- raise_error(e, :disconnect=>MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message))
94
+ raise_error(e)
98
95
  end
99
96
  end
100
97
 
@@ -108,71 +105,75 @@ module Sequel
108
105
  [::Mysql2::Error]
109
106
  end
110
107
 
108
+ # If a connection object is available, try pinging it. Otherwise, if the
109
+ # error is a Mysql2::Error, check the SQL state and exception message for
110
+ # disconnects.
111
+ def disconnect_error?(e, opts)
112
+ super ||
113
+ ((conn = opts[:conn]) && !conn.ping) ||
114
+ (e.is_a?(::Mysql2::Error) &&
115
+ (e.sql_state =~ /\A08/ ||
116
+ MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message)))
117
+ end
118
+
111
119
  # The database name when using the native adapter is always stored in
112
120
  # the :database option.
113
121
  def database_name
114
122
  @opts[:database]
115
123
  end
116
124
 
117
- # Closes given database connection.
118
- def disconnect_connection(c)
119
- c.close
120
- end
121
-
122
125
  # Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
123
126
  def schema_column_type(db_type)
124
- Sequel::MySQL.convert_tinyint_to_bool && db_type == 'tinyint(1)' ? :boolean : super
127
+ convert_tinyint_to_bool && db_type == 'tinyint(1)' ? :boolean : super
125
128
  end
126
129
  end
127
130
 
128
131
  # Dataset class for MySQL datasets accessed via the native driver.
129
132
  class Dataset < Sequel::Dataset
130
133
  include Sequel::MySQL::DatasetMethods
134
+ include Sequel::MySQL::PreparedStatements::DatasetMethods
131
135
 
132
- # Delete rows matching this dataset
133
- def delete
134
- execute_dui(delete_sql){|c| return c.affected_rows}
135
- end
136
+ Database::DatasetClass = self
136
137
 
137
138
  # Yield all rows matching this dataset.
138
- def fetch_rows(sql, &block)
139
+ def fetch_rows(sql)
139
140
  execute(sql) do |r|
140
- @columns = r.fields
141
- r.each(:cast_booleans => Sequel::MySQL.convert_tinyint_to_bool, &block)
141
+ if identifier_output_method
142
+ cols = r.fields
143
+ @columns = cols2 = cols.map{|c| output_identifier(c.to_s)}
144
+ cs = cols.zip(cols2)
145
+ r.each(:cast_booleans=>convert_tinyint_to_bool?) do |row|
146
+ h = {}
147
+ cs.each do |a, b|
148
+ h[b] = row[a]
149
+ end
150
+ yield h
151
+ end
152
+ else
153
+ @columns = r.fields
154
+ r.each(:cast_booleans=>convert_tinyint_to_bool?){|h| yield h}
155
+ end
142
156
  end
143
157
  self
144
158
  end
145
159
 
146
- # Insert a new value into this dataset
147
- def insert(*values)
148
- execute_dui(insert_sql(*values)){|c| return c.last_id}
149
- end
150
-
151
- # Replace (update or insert) the matching row.
152
- def replace(*args)
153
- execute_dui(replace_sql(*args)){|c| return c.last_id}
154
- end
160
+ private
155
161
 
156
- # Update the matching rows.
157
- def update(values={})
158
- execute_dui(update_sql(values)){|c| return c.affected_rows}
162
+ # Whether to cast tinyint(1) columns to integer instead of boolean.
163
+ # By default, uses the opposite of the database's convert_tinyint_to_bool
164
+ # setting. Exists for compatibility with the mysql adapter.
165
+ def convert_tinyint_to_bool?
166
+ @db.convert_tinyint_to_bool
159
167
  end
160
168
 
161
- private
162
-
163
169
  # Set the :type option to :select if it hasn't been set.
164
170
  def execute(sql, opts={}, &block)
165
171
  super(sql, {:type=>:select}.merge(opts), &block)
166
172
  end
167
173
 
168
- # Set the :type option to :dui if it hasn't been set.
169
- def execute_dui(sql, opts={}, &block)
170
- super(sql, {:type=>:dui}.merge(opts), &block)
171
- end
172
-
173
174
  # Handle correct quoting of strings using ::Mysql2::Client#escape.
174
- def literal_string(v)
175
- db.synchronize{|c| "'#{c.escape(v)}'"}
175
+ def literal_string_append(sql, v)
176
+ sql << "'" << db.synchronize{|c| c.escape(v)} << "'"
176
177
  end
177
178
  end
178
179
  end
@@ -7,12 +7,7 @@ module Sequel
7
7
  module MSSQL
8
8
  module DatabaseMethods
9
9
  include Sequel::MSSQL::DatabaseMethods
10
- LAST_INSERT_ID_SQL='SELECT SCOPE_IDENTITY()'
11
-
12
- # Return an instance of Sequel::ODBC::MSSQL::Dataset with the given opts.
13
- def dataset(opts=nil)
14
- Sequel::ODBC::MSSQL::Dataset.new(self, opts)
15
- end
10
+ LAST_INSERT_ID_SQL='SELECT SCOPE_IDENTITY()'.freeze
16
11
 
17
12
  # Return the last inserted identity value.
18
13
  def execute_insert(sql, opts={})
@@ -21,8 +16,8 @@ module Sequel
21
16
  log_yield(sql){conn.do(sql)}
22
17
  begin
23
18
  s = log_yield(LAST_INSERT_ID_SQL){conn.run(LAST_INSERT_ID_SQL)}
24
- if (rows = s.fetch_all) and (row = rows.first)
25
- Integer(row.first)
19
+ if (rows = s.fetch_all) and (row = rows.first) and (v = row.first)
20
+ Integer(v)
26
21
  end
27
22
  ensure
28
23
  s.drop if s
@@ -33,9 +28,22 @@ module Sequel
33
28
  end
34
29
  end
35
30
  end
36
-
37
31
  class Dataset < ODBC::Dataset
38
32
  include Sequel::MSSQL::DatasetMethods
33
+
34
+ private
35
+
36
+ # Use ODBC format, not Microsoft format, as the ODBC layer does
37
+ # some translation.
38
+ def default_timestamp_format
39
+ TIMESTAMP_FORMAT
40
+ end
41
+
42
+ # Use ODBC format, not Microsoft format, as the ODBC layer does
43
+ # some translation.
44
+ def literal_date(v)
45
+ v.strftime(ODBC_DATE_FORMAT)
46
+ end
39
47
  end
40
48
  end
41
49
  end
@@ -15,9 +15,16 @@ module Sequel
15
15
  when 'mssql'
16
16
  Sequel.ts_require 'adapters/odbc/mssql'
17
17
  extend Sequel::ODBC::MSSQL::DatabaseMethods
18
+ @dataset_class = Sequel::ODBC::MSSQL::Dataset
19
+ set_mssql_unicode_strings
18
20
  when 'progress'
19
21
  Sequel.ts_require 'adapters/shared/progress'
20
22
  extend Sequel::Progress::DatabaseMethods
23
+ extend_datasets(Sequel::Progress::DatasetMethods)
24
+ when 'db2'
25
+ Sequel.ts_require 'adapters/shared/db2'
26
+ extend ::Sequel::DB2::DatabaseMethods
27
+ extend_datasets ::Sequel::DB2::DatasetMethods
21
28
  end
22
29
  end
23
30
 
@@ -41,17 +48,17 @@ module Sequel
41
48
  conn
42
49
  end
43
50
 
44
- def dataset(opts = nil)
45
- ODBC::Dataset.new(self, opts)
51
+ def disconnect_connection(c)
52
+ c.disconnect
46
53
  end
47
-
54
+
48
55
  def execute(sql, opts={})
49
56
  synchronize(opts[:server]) do |conn|
50
57
  begin
51
58
  r = log_yield(sql){conn.run(sql)}
52
59
  yield(r) if block_given?
53
60
  rescue ::ODBC::Error, ArgumentError => e
54
- raise_error(e, :disconnect=>DISCONNECT_ERRORS.match(e.message))
61
+ raise_error(e)
55
62
  ensure
56
63
  r.drop if r
57
64
  end
@@ -64,7 +71,7 @@ module Sequel
64
71
  begin
65
72
  log_yield(sql){conn.do(sql)}
66
73
  rescue ::ODBC::Error, ArgumentError => e
67
- raise_error(e, :disconnect=>DISCONNECT_ERRORS.match(e.message))
74
+ raise_error(e)
68
75
  end
69
76
  end
70
77
  end
@@ -76,8 +83,12 @@ module Sequel
76
83
  :do
77
84
  end
78
85
 
79
- def disconnect_connection(c)
80
- c.disconnect
86
+ def database_error_classes
87
+ [::ODBC::Error]
88
+ end
89
+
90
+ def disconnect_error?(e, opts)
91
+ super || (e.is_a?(::ODBC::Error) && DISCONNECT_ERRORS.match(e.message))
81
92
  end
82
93
  end
83
94
 
@@ -87,15 +98,23 @@ module Sequel
87
98
  ODBC_DATE_FORMAT = "{d '%Y-%m-%d'}".freeze
88
99
  TIMESTAMP_FORMAT="{ts '%Y-%m-%d %H:%M:%S'}".freeze
89
100
 
101
+ Database::DatasetClass = self
102
+
90
103
  def fetch_rows(sql)
91
104
  execute(sql) do |s|
92
105
  i = -1
93
106
  cols = s.columns(true).map{|c| [output_identifier(c.name), i+=1]}
94
- @columns = cols.map{|c| c.at(0)}
107
+ columns = cols.map{|c| c.at(0)}
108
+ if opts[:offset] && offset_returns_row_number_column?
109
+ rn = row_number_column
110
+ columns.delete(rn)
111
+ end
112
+ @columns = columns
95
113
  if rows = s.fetch_all
96
114
  rows.each do |row|
97
115
  hash = {}
98
116
  cols.each{|n,i| hash[n] = convert_odbc_value(row[i])}
117
+ hash.delete(rn) if rn
99
118
  yield hash
100
119
  end
101
120
  end
@@ -114,9 +133,9 @@ module Sequel
114
133
  # ODBCColumn#mapSqlTypeToGenericType and Column#klass.
115
134
  case v
116
135
  when ::ODBC::TimeStamp
117
- Sequel.database_to_application_timestamp([v.year, v.month, v.day, v.hour, v.minute, v.second])
136
+ db.to_application_timestamp([v.year, v.month, v.day, v.hour, v.minute, v.second])
118
137
  when ::ODBC::Time
119
- Sequel.database_to_application_timestamp([now.year, now.month, now.day, v.hour, v.minute, v.second])
138
+ Sequel::SQLTime.create(v.hour, v.minute, v.second)
120
139
  when ::ODBC::Date
121
140
  Date.new(v.year, v.month, v.day)
122
141
  else
@@ -14,11 +14,11 @@ module Sequel
14
14
  opts[:password]
15
15
  )
16
16
  end
17
-
18
- def dataset(opts = nil)
19
- OpenBase::Dataset.new(self, opts)
17
+
18
+ def disconnect_connection(c)
19
+ c.disconnect
20
20
  end
21
-
21
+
22
22
  def execute(sql, opts={})
23
23
  synchronize(opts[:server]) do |conn|
24
24
  r = log_yield(sql){conn.execute(sql)}
@@ -27,16 +27,12 @@ module Sequel
27
27
  end
28
28
  end
29
29
  alias_method :do, :execute
30
-
31
- private
32
-
33
- def disconnect_connection(c)
34
- c.disconnect
35
- end
36
30
  end
37
31
 
38
32
  class Dataset < Sequel::Dataset
39
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit')
33
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit')
34
+
35
+ Database::DatasetClass = self
40
36
 
41
37
  def fetch_rows(sql)
42
38
  execute(sql) do |result|