sequel 3.21.0 → 3.39.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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,10 +1,13 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Methods that set defaults for created datasets
4
+ # :section: 5 - Methods that set defaults for created datasets
5
5
  # This methods change the default behavior of this database's datasets.
6
6
  # ---------------------
7
7
 
8
+ # The default class to use for datasets
9
+ DatasetClass = Sequel::Dataset
10
+
8
11
  # The identifier input method to use by default
9
12
  @@identifier_input_method = nil
10
13
 
@@ -42,9 +45,62 @@ module Sequel
42
45
  @@quote_identifiers = value
43
46
  end
44
47
 
45
- # The default schema to use, generally should be nil.
48
+ # The class to use for creating datasets. Should respond to
49
+ # new with the Database argument as the first argument, and
50
+ # an optional options hash.
51
+ attr_reader :dataset_class
52
+
53
+ # The default schema to use, generally should be nil. This sets
54
+ # the default schema used for some schema modification and
55
+ # introspection queries, but does not effect most dataset code.
46
56
  attr_accessor :default_schema
47
57
 
58
+ # If the database has any dataset modules associated with it,
59
+ # use a subclass of the given class that includes the modules
60
+ # as the dataset class.
61
+ def dataset_class=(c)
62
+ unless @dataset_modules.empty?
63
+ c = Class.new(c)
64
+ @dataset_modules.each{|m| c.send(:include, m)}
65
+ end
66
+ @dataset_class = c
67
+ end
68
+
69
+ # Equivalent to extending all datasets produced by the database with a
70
+ # module. What it actually does is use a subclass of the current dataset_class
71
+ # as the new dataset_class, and include the module in the subclass.
72
+ # Instead of a module, you can provide a block that is used to create an
73
+ # anonymous module.
74
+ #
75
+ # This allows you to override any of the dataset methods even if they are
76
+ # defined directly on the dataset class that this Database object uses.
77
+ #
78
+ # Examples:
79
+ #
80
+ # # Introspec columns for all of DB's datasets
81
+ # DB.extend_datasets(Sequel::ColumnsIntrospection)
82
+ #
83
+ # # Trace all SELECT queries by printing the SQL and the full backtrace
84
+ # DB.extend_datasets do
85
+ # def fetch_rows(sql)
86
+ # puts sql
87
+ # puts caller
88
+ # super
89
+ # end
90
+ # end
91
+ def extend_datasets(mod=nil, &block)
92
+ raise(Error, "must provide either mod or block, not both") if mod && block
93
+ reset_schema_utility_dataset
94
+ mod = Module.new(&block) if block
95
+ if @dataset_modules.empty?
96
+ @dataset_modules = [mod]
97
+ @dataset_class = Class.new(@dataset_class)
98
+ else
99
+ @dataset_modules << mod
100
+ end
101
+ @dataset_class.send(:include, mod)
102
+ end
103
+
48
104
  # The method to call on identifiers going into the database
49
105
  def identifier_input_method
50
106
  case @identifier_input_method
@@ -109,6 +165,11 @@ module Sequel
109
165
 
110
166
  private
111
167
 
168
+ # The default dataset class to use for the database
169
+ def dataset_class_default
170
+ self.class.const_get(:DatasetClass)
171
+ end
172
+
112
173
  # The default value for default_schema.
113
174
  def default_schema_default
114
175
  nil
@@ -1,7 +1,7 @@
1
1
  module Sequel
2
2
  class Database
3
3
  # ---------------------
4
- # :section: Methods relating to logging
4
+ # :section: 6 - Methods relating to logging
5
5
  # This methods affect relating to the logging of executed SQL.
6
6
  # ---------------------
7
7
 
@@ -17,6 +17,11 @@ module Sequel
17
17
  # is :info, it can be set to :debug to log at DEBUG level.
18
18
  attr_accessor :sql_log_level
19
19
 
20
+ # Log a message at error level, with information about the exception.
21
+ def log_exception(exception, message)
22
+ log_each(:error, "#{exception.class}: #{exception.message.strip}: #{message}")
23
+ end
24
+
20
25
  # Log a message at level info to all loggers.
21
26
  def log_info(message, args=nil)
22
27
  log_each(:info, args ? "#{message}; #{args.inspect}" : message)
@@ -31,7 +36,7 @@ module Sequel
31
36
  begin
32
37
  yield
33
38
  rescue => e
34
- log_each(:error, "#{e.class}: #{e.message.strip}: #{sql}")
39
+ log_exception(e, sql)
35
40
  raise
36
41
  ensure
37
42
  log_duration(Time.now - start, sql) unless e
@@ -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,11 +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
51
+ # :default_schema :: The default schema to use, see #default_schema.
27
52
  # :disconnection_proc :: A proc used to disconnect the connection
28
53
  # :identifier_input_method :: A string method symbol to call on identifiers going into the database
29
54
  # :identifier_output_method :: A string method symbol to call on identifiers coming from the database
@@ -50,14 +75,50 @@ module Sequel
50
75
  @schemas = {}
51
76
  @default_schema = @opts.fetch(:default_schema, default_schema_default)
52
77
  @prepared_statements = {}
53
- @transactions = []
78
+ @transactions = {}
54
79
  @identifier_input_method = nil
55
80
  @identifier_output_method = nil
56
81
  @quote_identifiers = nil
82
+ @timezone = nil
83
+ @dataset_class = dataset_class_default
84
+ @cache_schema = typecast_value_boolean(@opts.fetch(:cache_schema, true))
85
+ @dataset_modules = []
57
86
  self.sql_log_level = @opts[:sql_log_level] ? @opts[:sql_log_level].to_sym : :info
58
87
  @pool = ConnectionPool.get_pool(@opts, &block)
59
88
 
60
- ::Sequel::DATABASES.push(self)
89
+ Sequel.synchronize{::Sequel::DATABASES.push(self)}
90
+ end
91
+
92
+ # If a transaction is not currently in process, yield to the block immediately.
93
+ # Otherwise, add the block to the list of blocks to call after the currently
94
+ # in progress transaction commits (and only if it commits).
95
+ # Options:
96
+ # :server :: The server/shard to use.
97
+ def after_commit(opts={}, &block)
98
+ raise Error, "must provide block to after_commit" unless block
99
+ synchronize(opts[:server]) do |conn|
100
+ if h = _trans(conn)
101
+ raise Error, "cannot call after_commit in a prepared transaction" if h[:prepare]
102
+ (h[:after_commit] ||= []) << block
103
+ else
104
+ yield
105
+ end
106
+ end
107
+ end
108
+
109
+ # If a transaction is not currently in progress, ignore the block.
110
+ # Otherwise, add the block to the list of the blocks to call after the currently
111
+ # in progress transaction rolls back (and only if it rolls back).
112
+ # Options:
113
+ # :server :: The server/shard to use.
114
+ def after_rollback(opts={}, &block)
115
+ raise Error, "must provide block to after_rollback" unless block
116
+ synchronize(opts[:server]) do |conn|
117
+ if h = _trans(conn)
118
+ raise Error, "cannot call after_rollback in a prepared transaction" if h[:prepare]
119
+ (h[:after_rollback] ||= []) << block
120
+ end
121
+ end
61
122
  end
62
123
 
63
124
  # Cast the given type to a literal type
@@ -68,11 +129,52 @@ module Sequel
68
129
  type_literal(:type=>type)
69
130
  end
70
131
 
132
+ # Load an extension into the receiver. In addition to requiring the extension file, this
133
+ # also modifies the database to work with the extension (usually extending it with a
134
+ # module defined in the extension file). If no related extension file exists or the
135
+ # extension does not have specific support for Database objects, an Error will be raised.
136
+ # Returns self.
137
+ def extension(*exts)
138
+ Sequel.extension(*exts)
139
+ exts.each do |ext|
140
+ if pr = Sequel.synchronize{EXTENSIONS[ext]}
141
+ pr.call(self)
142
+ else
143
+ raise(Error, "Extension #{ext} does not have specific support handling individual databases")
144
+ end
145
+ end
146
+ self
147
+ end
148
+
149
+ # Convert the given timestamp from the application's timezone,
150
+ # to the databases's timezone or the default database timezone if
151
+ # the database does not have a timezone.
152
+ def from_application_timestamp(v)
153
+ Sequel.convert_output_timestamp(v, timezone)
154
+ end
155
+
156
+ # Whether the database uses a global namespace for the index. If
157
+ # false, the indexes are going to be namespaced per table.
158
+ def global_index_namespace?
159
+ true
160
+ end
161
+
162
+ # Return true if already in a transaction given the options,
163
+ # false otherwise. Respects the :server option for selecting
164
+ # a shard.
165
+ def in_transaction?(opts={})
166
+ synchronize(opts[:server]){|conn| !!_trans(conn)}
167
+ end
168
+
71
169
  # 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).
170
+ # class name and connection URI and options used when connecting (if any).
74
171
  def inspect
75
- "#<#{self.class}: #{(uri rescue opts).inspect}>"
172
+ a = []
173
+ a << uri.inspect if uri
174
+ if (oo = opts[:orig_opts]) && !oo.empty?
175
+ a << oo.inspect
176
+ end
177
+ "#<#{self.class}: #{a.join(' ')}>"
76
178
  end
77
179
 
78
180
  # Proxy the literal call to the dataset.
@@ -84,12 +186,34 @@ module Sequel
84
186
  schema_utility_dataset.literal(v)
85
187
  end
86
188
 
189
+ # Synchronize access to the prepared statements cache.
190
+ def prepared_statement(name)
191
+ Sequel.synchronize{prepared_statements[name]}
192
+ end
193
+
87
194
  # Default serial primary key options, used by the table creation
88
195
  # code.
89
196
  def serial_primary_key_options
90
197
  {:primary_key => true, :type => Integer, :auto_increment => true}
91
198
  end
92
199
 
200
+ # Cache the prepared statement object at the given name.
201
+ def set_prepared_statement(name, ps)
202
+ Sequel.synchronize{prepared_statements[name] = ps}
203
+ end
204
+
205
+ # Whether the database supports CREATE TABLE IF NOT EXISTS syntax,
206
+ # false by default.
207
+ def supports_create_table_if_not_exists?
208
+ false
209
+ end
210
+
211
+ # Whether the database supports DROP TABLE IF EXISTS syntax,
212
+ # default is the same as #supports_create_table_if_not_exists?.
213
+ def supports_drop_table_if_exists?
214
+ supports_create_table_if_not_exists?
215
+ end
216
+
93
217
  # Whether the database and adapter support prepared transactions
94
218
  # (two-phase commit), false by default.
95
219
  def supports_prepared_transactions?
@@ -101,11 +225,34 @@ module Sequel
101
225
  false
102
226
  end
103
227
 
228
+ # Whether the database and adapter support savepoints inside prepared transactions
229
+ # (two-phase commit), default is false.
230
+ def supports_savepoints_in_prepared_transactions?
231
+ supports_prepared_transactions? && supports_savepoints?
232
+ end
233
+
104
234
  # Whether the database and adapter support transaction isolation levels, false by default.
105
235
  def supports_transaction_isolation_levels?
106
236
  false
107
237
  end
108
238
 
239
+ # Whether DDL statements work correctly in transactions, false by default.
240
+ def supports_transactional_ddl?
241
+ false
242
+ end
243
+
244
+ # The timezone to use for this database, defaulting to <tt>Sequel.database_timezone</tt>.
245
+ def timezone
246
+ @timezone || Sequel.database_timezone
247
+ end
248
+
249
+ # Convert the given timestamp to the application's timezone,
250
+ # from the databases's timezone or the default database timezone if
251
+ # the database does not have a timezone.
252
+ def to_application_timestamp(v)
253
+ Sequel.convert_timestamp(v, timezone)
254
+ end
255
+
109
256
  # Typecast the value to the given column_type. Calls
110
257
  # typecast_value_#{column_type} if the method exists,
111
258
  # otherwise returns the value.
@@ -121,29 +268,10 @@ module Sequel
121
268
  end
122
269
  end
123
270
 
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"
271
+ # Returns the URI use to connect to the database. If a URI
272
+ # was not used when connecting, returns nil.
132
273
  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
274
+ opts[:uri]
147
275
  end
148
276
 
149
277
  # Explicit alias of uri for easier subclassing.
@@ -175,12 +303,17 @@ module Sequel
175
303
  def database_error_classes
176
304
  []
177
305
  end
306
+
307
+ # Return true if exception represents a disconnect error, false otherwise.
308
+ def disconnect_error?(exception, opts)
309
+ opts[:disconnect]
310
+ end
178
311
 
179
312
  # Convert the given exception to a DatabaseError, keeping message
180
313
  # and traceback.
181
314
  def raise_error(exception, opts={})
182
315
  if !opts[:classes] || Array(opts[:classes]).any?{|c| exception.is_a?(c)}
183
- raise Sequel.convert_exception_class(exception, opts[:disconnect] ? DatabaseDisconnectError : DatabaseError)
316
+ raise Sequel.convert_exception_class(exception, disconnect_error?(exception, opts) ? DatabaseDisconnectError : DatabaseError)
184
317
  else
185
318
  raise exception
186
319
  end
@@ -194,7 +327,7 @@ module Sequel
194
327
  # Typecast the value to true, false, or nil
195
328
  def typecast_value_boolean(value)
196
329
  case value
197
- when false, 0, "0", /\Af(alse)?\z/i
330
+ when false, 0, "0", /\Af(alse)?\z/i, /\Ano?\z/i
198
331
  false
199
332
  else
200
333
  blank_object?(value) ? nil : true
@@ -204,10 +337,10 @@ module Sequel
204
337
  # Typecast the value to a Date
205
338
  def typecast_value_date(value)
206
339
  case value
207
- when Date
208
- value
209
340
  when DateTime, Time
210
341
  Date.new(value.year, value.month, value.day)
342
+ when Date
343
+ value
211
344
  when String
212
345
  Sequel.string_to_date(value)
213
346
  when Hash
@@ -219,12 +352,7 @@ module Sequel
219
352
 
220
353
  # Typecast the value to a DateTime or Time depending on Sequel.datetime_class
221
354
  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
355
+ Sequel.typecast_to_application_timestamp(value)
228
356
  end
229
357
 
230
358
  # Typecast the value to a BigDecimal
@@ -244,9 +372,21 @@ module Sequel
244
372
  Float(value)
245
373
  end
246
374
 
247
- # Typecast the value to an Integer
248
- def typecast_value_integer(value)
249
- Integer(value)
375
+ # Used for checking/removing leading zeroes from strings so they don't get
376
+ # interpreted as octal.
377
+ LEADING_ZERO_RE = /\A0+(\d)/.freeze
378
+ if RUBY_VERSION >= '1.9'
379
+ # Typecast the value to an Integer
380
+ def typecast_value_integer(value)
381
+ (value.is_a?(String) && value =~ LEADING_ZERO_RE) ? Integer(value, 10) : Integer(value)
382
+ end
383
+ else
384
+ # Replacement string when replacing leading zeroes.
385
+ LEADING_ZERO_REP = "\\1".freeze
386
+ # Typecast the value to an Integer
387
+ def typecast_value_integer(value)
388
+ Integer(value.is_a?(String) ? value.sub(LEADING_ZERO_RE, LEADING_ZERO_REP) : value)
389
+ end
250
390
  end
251
391
 
252
392
  # Typecast the value to a String
@@ -258,12 +398,16 @@ module Sequel
258
398
  def typecast_value_time(value)
259
399
  case value
260
400
  when Time
261
- value
401
+ if value.is_a?(SQLTime)
402
+ value
403
+ else
404
+ # specifically check for nsec == 0 value to work around JRuby 1.6 ruby 1.9 mode bug
405
+ SQLTime.create(value.hour, value.min, value.sec, (value.respond_to?(:nsec) && value.nsec != 0) ? value.nsec/1000.0 : value.usec)
406
+ end
262
407
  when String
263
408
  Sequel.string_to_time(value)
264
409
  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})
410
+ SQLTime.create(*[:hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
267
411
  else
268
412
  raise Sequel::InvalidValue, "invalid value for Time: #{value.inspect}"
269
413
  end