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,13 +1,35 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Miscellaneous methods
4
+ # :section: 7 - Miscellaneous methods
5
5
  # These methods don't fit neatly into another category.
6
6
  # ---------------------
7
+
8
+ # Hash of extension name symbols to callable objects to load the extension
9
+ # into the Database object (usually by extending it with a module defined
10
+ # in the extension).
11
+ EXTENSIONS = {}
12
+
13
+ # Register an extension callback for Database objects. ext should be the
14
+ # extension name symbol, and mod should either be a Module that the
15
+ # database is extended with, or a callable object called with the database
16
+ # object. If mod is not provided, a block can be provided and is treated
17
+ # as the mod object.
18
+ def self.register_extension(ext, mod=nil, &block)
19
+ if mod
20
+ raise(Error, "cannot provide both mod and block to Database.register_extension") if block
21
+ if mod.is_a?(Module)
22
+ block = proc{|db| db.extend(mod)}
23
+ else
24
+ block = mod
25
+ end
26
+ end
27
+ Sequel.synchronize{EXTENSIONS[ext] = block}
28
+ end
7
29
 
8
30
  # Converts a uri to an options hash. These options are then passed
9
31
  # to a newly created database object.
10
- def self.uri_to_options(uri) # :nodoc:
32
+ def self.uri_to_options(uri)
11
33
  { :user => uri.user,
12
34
  :password => uri.password,
13
35
  :host => uri.host,
@@ -19,12 +41,14 @@ module Sequel
19
41
  # The options hash for this database
20
42
  attr_reader :opts
21
43
 
44
+ # Set the timezone to use for this database, overridding <tt>Sequel.database_timezone</tt>.
45
+ attr_writer :timezone
46
+
22
47
  # Constructs a new instance of a database connection with the specified
23
48
  # options hash.
24
49
  #
25
50
  # Accepts the following options:
26
- # :default_schema :: The default schema to use, should generally be nil
27
- # :disconnection_proc :: A proc used to disconnect the connection
51
+ # :default_schema :: The default schema to use, see #default_schema.
28
52
  # :identifier_input_method :: A string method symbol to call on identifiers going into the database
29
53
  # :identifier_output_method :: A string method symbol to call on identifiers coming from the database
30
54
  # :logger :: A specific logger to use
@@ -34,14 +58,12 @@ module Sequel
34
58
  # :single_threaded :: Whether to use a single-threaded connection pool
35
59
  # :sql_log_level :: Method to use to log SQL to a logger, :info by default.
36
60
  #
37
- # All options given are also passed to the connection pool. If a block
38
- # is given, it is used as the connection_proc for the ConnectionPool.
61
+ # All options given are also passed to the connection pool.
39
62
  def initialize(opts = {}, &block)
40
63
  @opts ||= opts
41
64
  @opts = connection_pool_default_options.merge(@opts)
42
65
  @loggers = Array(@opts[:logger]) + Array(@opts[:loggers])
43
66
  self.log_warn_duration = @opts[:log_warn_duration]
44
- @opts[:disconnection_proc] ||= proc{|conn| disconnect_connection(conn)}
45
67
  block ||= proc{|server| connect(server)}
46
68
  @opts[:servers] = {} if @opts[:servers].is_a?(String)
47
69
  @opts[:adapter_class] = self.class
@@ -50,14 +72,50 @@ module Sequel
50
72
  @schemas = {}
51
73
  @default_schema = @opts.fetch(:default_schema, default_schema_default)
52
74
  @prepared_statements = {}
53
- @transactions = []
75
+ @transactions = {}
54
76
  @identifier_input_method = nil
55
77
  @identifier_output_method = nil
56
78
  @quote_identifiers = nil
79
+ @timezone = nil
80
+ @dataset_class = dataset_class_default
81
+ @cache_schema = typecast_value_boolean(@opts.fetch(:cache_schema, true))
82
+ @dataset_modules = []
57
83
  self.sql_log_level = @opts[:sql_log_level] ? @opts[:sql_log_level].to_sym : :info
58
- @pool = ConnectionPool.get_pool(@opts, &block)
84
+ @pool = ConnectionPool.get_pool(self, @opts)
59
85
 
60
- ::Sequel::DATABASES.push(self)
86
+ Sequel.synchronize{::Sequel::DATABASES.push(self)}
87
+ end
88
+
89
+ # If a transaction is not currently in process, yield to the block immediately.
90
+ # Otherwise, add the block to the list of blocks to call after the currently
91
+ # in progress transaction commits (and only if it commits).
92
+ # Options:
93
+ # :server :: The server/shard to use.
94
+ def after_commit(opts={}, &block)
95
+ raise Error, "must provide block to after_commit" unless block
96
+ synchronize(opts[:server]) do |conn|
97
+ if h = _trans(conn)
98
+ raise Error, "cannot call after_commit in a prepared transaction" if h[:prepare]
99
+ (h[:after_commit] ||= []) << block
100
+ else
101
+ yield
102
+ end
103
+ end
104
+ end
105
+
106
+ # If a transaction is not currently in progress, ignore the block.
107
+ # Otherwise, add the block to the list of the blocks to call after the currently
108
+ # in progress transaction rolls back (and only if it rolls back).
109
+ # Options:
110
+ # :server :: The server/shard to use.
111
+ def after_rollback(opts={}, &block)
112
+ raise Error, "must provide block to after_rollback" unless block
113
+ synchronize(opts[:server]) do |conn|
114
+ if h = _trans(conn)
115
+ raise Error, "cannot call after_rollback in a prepared transaction" if h[:prepare]
116
+ (h[:after_rollback] ||= []) << block
117
+ end
118
+ end
61
119
  end
62
120
 
63
121
  # Cast the given type to a literal type
@@ -68,11 +126,52 @@ module Sequel
68
126
  type_literal(:type=>type)
69
127
  end
70
128
 
129
+ # Load an extension into the receiver. In addition to requiring the extension file, this
130
+ # also modifies the database to work with the extension (usually extending it with a
131
+ # module defined in the extension file). If no related extension file exists or the
132
+ # extension does not have specific support for Database objects, an Error will be raised.
133
+ # Returns self.
134
+ def extension(*exts)
135
+ Sequel.extension(*exts)
136
+ exts.each do |ext|
137
+ if pr = Sequel.synchronize{EXTENSIONS[ext]}
138
+ pr.call(self)
139
+ else
140
+ raise(Error, "Extension #{ext} does not have specific support handling individual databases")
141
+ end
142
+ end
143
+ self
144
+ end
145
+
146
+ # Convert the given timestamp from the application's timezone,
147
+ # to the databases's timezone or the default database timezone if
148
+ # the database does not have a timezone.
149
+ def from_application_timestamp(v)
150
+ Sequel.convert_output_timestamp(v, timezone)
151
+ end
152
+
153
+ # Whether the database uses a global namespace for the index. If
154
+ # false, the indexes are going to be namespaced per table.
155
+ def global_index_namespace?
156
+ true
157
+ end
158
+
159
+ # Return true if already in a transaction given the options,
160
+ # false otherwise. Respects the :server option for selecting
161
+ # a shard.
162
+ def in_transaction?(opts={})
163
+ synchronize(opts[:server]){|conn| !!_trans(conn)}
164
+ end
165
+
71
166
  # Returns a string representation of the database object including the
72
- # class name and the connection URI (or the opts if the URI
73
- # cannot be constructed).
167
+ # class name and connection URI and options used when connecting (if any).
74
168
  def inspect
75
- "#<#{self.class}: #{(uri rescue opts).inspect}>"
169
+ a = []
170
+ a << uri.inspect if uri
171
+ if (oo = opts[:orig_opts]) && !oo.empty?
172
+ a << oo.inspect
173
+ end
174
+ "#<#{self.class}: #{a.join(' ')}>"
76
175
  end
77
176
 
78
177
  # Proxy the literal call to the dataset.
@@ -84,12 +183,34 @@ module Sequel
84
183
  schema_utility_dataset.literal(v)
85
184
  end
86
185
 
186
+ # Synchronize access to the prepared statements cache.
187
+ def prepared_statement(name)
188
+ Sequel.synchronize{prepared_statements[name]}
189
+ end
190
+
87
191
  # Default serial primary key options, used by the table creation
88
192
  # code.
89
193
  def serial_primary_key_options
90
194
  {:primary_key => true, :type => Integer, :auto_increment => true}
91
195
  end
92
196
 
197
+ # Cache the prepared statement object at the given name.
198
+ def set_prepared_statement(name, ps)
199
+ Sequel.synchronize{prepared_statements[name] = ps}
200
+ end
201
+
202
+ # Whether the database supports CREATE TABLE IF NOT EXISTS syntax,
203
+ # false by default.
204
+ def supports_create_table_if_not_exists?
205
+ false
206
+ end
207
+
208
+ # Whether the database supports DROP TABLE IF EXISTS syntax,
209
+ # default is the same as #supports_create_table_if_not_exists?.
210
+ def supports_drop_table_if_exists?
211
+ supports_create_table_if_not_exists?
212
+ end
213
+
93
214
  # Whether the database and adapter support prepared transactions
94
215
  # (two-phase commit), false by default.
95
216
  def supports_prepared_transactions?
@@ -101,11 +222,34 @@ module Sequel
101
222
  false
102
223
  end
103
224
 
225
+ # Whether the database and adapter support savepoints inside prepared transactions
226
+ # (two-phase commit), default is false.
227
+ def supports_savepoints_in_prepared_transactions?
228
+ supports_prepared_transactions? && supports_savepoints?
229
+ end
230
+
104
231
  # Whether the database and adapter support transaction isolation levels, false by default.
105
232
  def supports_transaction_isolation_levels?
106
233
  false
107
234
  end
108
235
 
236
+ # Whether DDL statements work correctly in transactions, false by default.
237
+ def supports_transactional_ddl?
238
+ false
239
+ end
240
+
241
+ # The timezone to use for this database, defaulting to <tt>Sequel.database_timezone</tt>.
242
+ def timezone
243
+ @timezone || Sequel.database_timezone
244
+ end
245
+
246
+ # Convert the given timestamp to the application's timezone,
247
+ # from the databases's timezone or the default database timezone if
248
+ # the database does not have a timezone.
249
+ def to_application_timestamp(v)
250
+ Sequel.convert_timestamp(v, timezone)
251
+ end
252
+
109
253
  # Typecast the value to the given column_type. Calls
110
254
  # typecast_value_#{column_type} if the method exists,
111
255
  # otherwise returns the value.
@@ -121,29 +265,10 @@ module Sequel
121
265
  end
122
266
  end
123
267
 
124
- # Returns the URI identifying the database, which may not be the
125
- # same as the URI used when connecting.
126
- # This method can raise an error if the database used options
127
- # instead of a connection string, and will not include uri
128
- # parameters.
129
- #
130
- # Sequel.connect('postgres://localhost/db?user=billg').url
131
- # # => "postgres://billg@localhost/db"
268
+ # Returns the URI use to connect to the database. If a URI
269
+ # was not used when connecting, returns nil.
132
270
  def uri
133
- uri = URI::Generic.new(
134
- adapter_scheme.to_s,
135
- nil,
136
- @opts[:host],
137
- @opts[:port],
138
- nil,
139
- "/#{@opts[:database]}",
140
- nil,
141
- nil,
142
- nil
143
- )
144
- uri.user = @opts[:user]
145
- uri.password = @opts[:password] if uri.user
146
- uri.to_s
271
+ opts[:uri]
147
272
  end
148
273
 
149
274
  # Explicit alias of uri for easier subclassing.
@@ -175,12 +300,17 @@ module Sequel
175
300
  def database_error_classes
176
301
  []
177
302
  end
303
+
304
+ # Return true if exception represents a disconnect error, false otherwise.
305
+ def disconnect_error?(exception, opts)
306
+ opts[:disconnect]
307
+ end
178
308
 
179
309
  # Convert the given exception to a DatabaseError, keeping message
180
310
  # and traceback.
181
311
  def raise_error(exception, opts={})
182
312
  if !opts[:classes] || Array(opts[:classes]).any?{|c| exception.is_a?(c)}
183
- raise Sequel.convert_exception_class(exception, opts[:disconnect] ? DatabaseDisconnectError : DatabaseError)
313
+ raise Sequel.convert_exception_class(exception, disconnect_error?(exception, opts) ? DatabaseDisconnectError : DatabaseError)
184
314
  else
185
315
  raise exception
186
316
  end
@@ -194,7 +324,7 @@ module Sequel
194
324
  # Typecast the value to true, false, or nil
195
325
  def typecast_value_boolean(value)
196
326
  case value
197
- when false, 0, "0", /\Af(alse)?\z/i
327
+ when false, 0, "0", /\Af(alse)?\z/i, /\Ano?\z/i
198
328
  false
199
329
  else
200
330
  blank_object?(value) ? nil : true
@@ -204,10 +334,10 @@ module Sequel
204
334
  # Typecast the value to a Date
205
335
  def typecast_value_date(value)
206
336
  case value
207
- when Date
208
- value
209
337
  when DateTime, Time
210
338
  Date.new(value.year, value.month, value.day)
339
+ when Date
340
+ value
211
341
  when String
212
342
  Sequel.string_to_date(value)
213
343
  when Hash
@@ -219,12 +349,7 @@ module Sequel
219
349
 
220
350
  # Typecast the value to a DateTime or Time depending on Sequel.datetime_class
221
351
  def typecast_value_datetime(value)
222
- klass = Sequel.datetime_class
223
- if value.is_a?(Hash)
224
- klass.send(klass == Time ? :mktime : :new, *[:year, :month, :day, :hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
225
- else
226
- Sequel.typecast_to_application_timestamp(value)
227
- end
352
+ Sequel.typecast_to_application_timestamp(value)
228
353
  end
229
354
 
230
355
  # Typecast the value to a BigDecimal
@@ -244,9 +369,21 @@ module Sequel
244
369
  Float(value)
245
370
  end
246
371
 
247
- # Typecast the value to an Integer
248
- def typecast_value_integer(value)
249
- Integer(value)
372
+ # Used for checking/removing leading zeroes from strings so they don't get
373
+ # interpreted as octal.
374
+ LEADING_ZERO_RE = /\A0+(\d)/.freeze
375
+ if RUBY_VERSION >= '1.9'
376
+ # Typecast the value to an Integer
377
+ def typecast_value_integer(value)
378
+ (value.is_a?(String) && value =~ LEADING_ZERO_RE) ? Integer(value, 10) : Integer(value)
379
+ end
380
+ else
381
+ # Replacement string when replacing leading zeroes.
382
+ LEADING_ZERO_REP = "\\1".freeze
383
+ # Typecast the value to an Integer
384
+ def typecast_value_integer(value)
385
+ Integer(value.is_a?(String) ? value.sub(LEADING_ZERO_RE, LEADING_ZERO_REP) : value)
386
+ end
250
387
  end
251
388
 
252
389
  # Typecast the value to a String
@@ -258,12 +395,16 @@ module Sequel
258
395
  def typecast_value_time(value)
259
396
  case value
260
397
  when Time
261
- value
398
+ if value.is_a?(SQLTime)
399
+ value
400
+ else
401
+ # specifically check for nsec == 0 value to work around JRuby 1.6 ruby 1.9 mode bug
402
+ SQLTime.create(value.hour, value.min, value.sec, (value.respond_to?(:nsec) && value.nsec != 0) ? value.nsec/1000.0 : value.usec)
403
+ end
262
404
  when String
263
405
  Sequel.string_to_time(value)
264
406
  when Hash
265
- t = Time.now
266
- Time.mktime(t.year, t.month, t.day, *[:hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
407
+ SQLTime.create(*[:hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
267
408
  else
268
409
  raise Sequel::InvalidValue, "invalid value for Time: #{value.inspect}"
269
410
  end