sequel 3.21.0 → 3.36.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 (311) hide show
  1. data/CHANGELOG +855 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +23 -7
  4. data/Rakefile +42 -24
  5. data/bin/sequel +26 -8
  6. data/doc/active_record.rdoc +1 -0
  7. data/doc/advanced_associations.rdoc +171 -11
  8. data/doc/association_basics.rdoc +293 -43
  9. data/doc/dataset_basics.rdoc +5 -5
  10. data/doc/dataset_filtering.rdoc +8 -0
  11. data/doc/mass_assignment.rdoc +56 -0
  12. data/doc/migration.rdoc +85 -552
  13. data/doc/model_hooks.rdoc +78 -27
  14. data/doc/object_model.rdoc +541 -0
  15. data/doc/opening_databases.rdoc +97 -50
  16. data/doc/prepared_statements.rdoc +40 -14
  17. data/doc/querying.rdoc +28 -4
  18. data/doc/reflection.rdoc +30 -4
  19. data/doc/release_notes/3.22.0.txt +39 -0
  20. data/doc/release_notes/3.23.0.txt +172 -0
  21. data/doc/release_notes/3.24.0.txt +420 -0
  22. data/doc/release_notes/3.25.0.txt +88 -0
  23. data/doc/release_notes/3.26.0.txt +88 -0
  24. data/doc/release_notes/3.27.0.txt +82 -0
  25. data/doc/release_notes/3.28.0.txt +304 -0
  26. data/doc/release_notes/3.29.0.txt +459 -0
  27. data/doc/release_notes/3.30.0.txt +135 -0
  28. data/doc/release_notes/3.31.0.txt +146 -0
  29. data/doc/release_notes/3.32.0.txt +202 -0
  30. data/doc/release_notes/3.33.0.txt +157 -0
  31. data/doc/release_notes/3.34.0.txt +671 -0
  32. data/doc/release_notes/3.35.0.txt +144 -0
  33. data/doc/release_notes/3.36.0.txt +245 -0
  34. data/doc/schema_modification.rdoc +572 -0
  35. data/doc/sharding.rdoc +95 -3
  36. data/doc/testing.rdoc +129 -0
  37. data/doc/thread_safety.rdoc +17 -0
  38. data/doc/transactions.rdoc +137 -0
  39. data/doc/virtual_rows.rdoc +51 -2
  40. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  41. data/lib/sequel/adapters/ado.rb +40 -18
  42. data/lib/sequel/adapters/amalgalite.rb +17 -9
  43. data/lib/sequel/adapters/db2.rb +175 -86
  44. data/lib/sequel/adapters/dbi.rb +15 -15
  45. data/lib/sequel/adapters/do/mysql.rb +17 -11
  46. data/lib/sequel/adapters/do/postgres.rb +1 -57
  47. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  48. data/lib/sequel/adapters/do.rb +18 -36
  49. data/lib/sequel/adapters/firebird.rb +27 -208
  50. data/lib/sequel/adapters/ibmdb.rb +453 -0
  51. data/lib/sequel/adapters/informix.rb +6 -23
  52. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  53. data/lib/sequel/adapters/jdbc/db2.rb +47 -0
  54. data/lib/sequel/adapters/jdbc/derby.rb +287 -0
  55. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  56. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  57. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  58. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  59. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  61. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  62. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +58 -48
  64. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  65. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  66. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  67. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  68. data/lib/sequel/adapters/jdbc.rb +265 -94
  69. data/lib/sequel/adapters/mock.rb +361 -0
  70. data/lib/sequel/adapters/mysql.rb +118 -222
  71. data/lib/sequel/adapters/mysql2.rb +58 -57
  72. data/lib/sequel/adapters/odbc/mssql.rb +15 -7
  73. data/lib/sequel/adapters/odbc.rb +28 -9
  74. data/lib/sequel/adapters/openbase.rb +3 -5
  75. data/lib/sequel/adapters/oracle.rb +349 -53
  76. data/lib/sequel/adapters/postgres.rb +356 -107
  77. data/lib/sequel/adapters/shared/access.rb +32 -9
  78. data/lib/sequel/adapters/shared/db2.rb +342 -0
  79. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  80. data/lib/sequel/adapters/shared/informix.rb +53 -0
  81. data/lib/sequel/adapters/shared/mssql.rb +335 -118
  82. data/lib/sequel/adapters/shared/mysql.rb +340 -76
  83. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  84. data/lib/sequel/adapters/shared/oracle.rb +243 -45
  85. data/lib/sequel/adapters/shared/postgres.rb +524 -279
  86. data/lib/sequel/adapters/shared/progress.rb +5 -8
  87. data/lib/sequel/adapters/shared/sqlite.rb +265 -89
  88. data/lib/sequel/adapters/sqlite.rb +101 -39
  89. data/lib/sequel/adapters/swift/mysql.rb +9 -12
  90. data/lib/sequel/adapters/swift/postgres.rb +9 -74
  91. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  92. data/lib/sequel/adapters/swift.rb +8 -7
  93. data/lib/sequel/adapters/tinytds.rb +161 -21
  94. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  95. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  96. data/lib/sequel/ast_transformer.rb +194 -0
  97. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  98. data/lib/sequel/connection_pool/sharded_threaded.rb +28 -2
  99. data/lib/sequel/connection_pool/single.rb +5 -0
  100. data/lib/sequel/connection_pool/threaded.rb +38 -14
  101. data/lib/sequel/connection_pool.rb +10 -2
  102. data/lib/sequel/core.rb +118 -11
  103. data/lib/sequel/database/connecting.rb +38 -28
  104. data/lib/sequel/database/dataset.rb +4 -4
  105. data/lib/sequel/database/dataset_defaults.rb +63 -2
  106. data/lib/sequel/database/logging.rb +7 -2
  107. data/lib/sequel/database/misc.rb +150 -46
  108. data/lib/sequel/database/query.rb +215 -65
  109. data/lib/sequel/database/schema_generator.rb +64 -20
  110. data/lib/sequel/database/schema_methods.rb +212 -54
  111. data/lib/sequel/dataset/actions.rb +322 -85
  112. data/lib/sequel/dataset/features.rb +96 -8
  113. data/lib/sequel/dataset/graph.rb +38 -11
  114. data/lib/sequel/dataset/misc.rb +50 -23
  115. data/lib/sequel/dataset/mutation.rb +12 -7
  116. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  117. data/lib/sequel/dataset/query.rb +237 -44
  118. data/lib/sequel/dataset/sql.rb +698 -278
  119. data/lib/sequel/dataset.rb +8 -0
  120. data/lib/sequel/exceptions.rb +4 -0
  121. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  122. data/lib/sequel/extensions/arbitrary_servers.rb +108 -0
  123. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  124. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +16 -34
  125. data/lib/sequel/extensions/migration.rb +97 -11
  126. data/lib/sequel/extensions/named_timezones.rb +5 -0
  127. data/lib/sequel/extensions/null_dataset.rb +90 -0
  128. data/lib/sequel/extensions/pg_array.rb +460 -0
  129. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  130. data/lib/sequel/extensions/pg_auto_parameterize.rb +169 -0
  131. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  132. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  133. data/lib/sequel/extensions/pg_inet.rb +89 -0
  134. data/lib/sequel/extensions/pg_json.rb +178 -0
  135. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  136. data/lib/sequel/extensions/pretty_table.rb +5 -71
  137. data/lib/sequel/extensions/query.rb +1 -1
  138. data/lib/sequel/extensions/query_literals.rb +79 -0
  139. data/lib/sequel/extensions/schema_caching.rb +76 -0
  140. data/lib/sequel/extensions/schema_dumper.rb +251 -37
  141. data/lib/sequel/extensions/select_remove.rb +35 -0
  142. data/lib/sequel/extensions/server_block.rb +139 -0
  143. data/lib/sequel/extensions/sql_expr.rb +4 -110
  144. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  145. data/lib/sequel/extensions/to_dot.rb +95 -83
  146. data/lib/sequel/model/associations.rb +1187 -393
  147. data/lib/sequel/model/base.rb +578 -170
  148. data/lib/sequel/model/errors.rb +1 -1
  149. data/lib/sequel/model/exceptions.rb +5 -1
  150. data/lib/sequel/model/inflections.rb +1 -1
  151. data/lib/sequel/model.rb +30 -11
  152. data/lib/sequel/no_core_ext.rb +2 -0
  153. data/lib/sequel/plugins/active_model.rb +13 -1
  154. data/lib/sequel/plugins/association_pks.rb +22 -4
  155. data/lib/sequel/plugins/caching.rb +25 -18
  156. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  157. data/lib/sequel/plugins/composition.rb +44 -12
  158. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  159. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  160. data/lib/sequel/plugins/dirty.rb +214 -0
  161. data/lib/sequel/plugins/eager_each.rb +59 -0
  162. data/lib/sequel/plugins/force_encoding.rb +6 -6
  163. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  164. data/lib/sequel/plugins/identity_map.rb +123 -8
  165. data/lib/sequel/plugins/instance_filters.rb +10 -0
  166. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  167. data/lib/sequel/plugins/json_serializer.rb +58 -6
  168. data/lib/sequel/plugins/list.rb +12 -2
  169. data/lib/sequel/plugins/many_through_many.rb +79 -28
  170. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  171. data/lib/sequel/plugins/nested_attributes.rb +139 -63
  172. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  173. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  174. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  175. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  176. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  177. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  178. data/lib/sequel/plugins/schema.rb +7 -2
  179. data/lib/sequel/plugins/serialization.rb +98 -49
  180. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  181. data/lib/sequel/plugins/sharding.rb +21 -54
  182. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  183. data/lib/sequel/plugins/static_cache.rb +99 -0
  184. data/lib/sequel/plugins/subclasses.rb +10 -2
  185. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  186. data/lib/sequel/plugins/timestamps.rb +1 -1
  187. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  188. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  189. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  190. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  191. data/lib/sequel/sql.rb +526 -59
  192. data/lib/sequel/timezones.rb +57 -38
  193. data/lib/sequel/version.rb +1 -1
  194. data/spec/adapters/db2_spec.rb +146 -0
  195. data/spec/adapters/firebird_spec.rb +1 -1
  196. data/spec/adapters/mssql_spec.rb +142 -40
  197. data/spec/adapters/mysql_spec.rb +380 -234
  198. data/spec/adapters/oracle_spec.rb +67 -77
  199. data/spec/adapters/postgres_spec.rb +1050 -212
  200. data/spec/adapters/spec_helper.rb +8 -5
  201. data/spec/adapters/sqlite_spec.rb +139 -27
  202. data/spec/core/connection_pool_spec.rb +196 -93
  203. data/spec/core/database_spec.rb +879 -510
  204. data/spec/core/dataset_spec.rb +1415 -1086
  205. data/spec/core/expression_filters_spec.rb +554 -109
  206. data/spec/core/mock_adapter_spec.rb +449 -0
  207. data/spec/core/object_graph_spec.rb +86 -114
  208. data/spec/core/schema_generator_spec.rb +4 -4
  209. data/spec/core/schema_spec.rb +482 -38
  210. data/spec/core/spec_helper.rb +6 -48
  211. data/spec/extensions/active_model_spec.rb +13 -0
  212. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  213. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  214. data/spec/extensions/association_dependencies_spec.rb +15 -25
  215. data/spec/extensions/association_pks_spec.rb +66 -32
  216. data/spec/extensions/association_proxies_spec.rb +4 -4
  217. data/spec/extensions/caching_spec.rb +47 -51
  218. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  219. data/spec/extensions/columns_introspection_spec.rb +91 -0
  220. data/spec/extensions/composition_spec.rb +18 -13
  221. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +119 -139
  222. data/spec/extensions/dataset_associations_spec.rb +199 -0
  223. data/spec/extensions/defaults_setter_spec.rb +64 -0
  224. data/spec/extensions/dirty_spec.rb +155 -0
  225. data/spec/extensions/eager_each_spec.rb +34 -0
  226. data/spec/extensions/force_encoding_spec.rb +4 -2
  227. data/spec/extensions/hook_class_methods_spec.rb +69 -92
  228. data/spec/extensions/identity_map_spec.rb +131 -22
  229. data/spec/extensions/inflector_spec.rb +0 -4
  230. data/spec/extensions/instance_filters_spec.rb +11 -21
  231. data/spec/extensions/instance_hooks_spec.rb +72 -0
  232. data/spec/extensions/json_serializer_spec.rb +49 -6
  233. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  234. data/spec/extensions/list_spec.rb +48 -39
  235. data/spec/extensions/many_through_many_spec.rb +283 -250
  236. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  237. data/spec/extensions/migration_spec.rb +140 -35
  238. data/spec/extensions/named_timezones_spec.rb +29 -11
  239. data/spec/extensions/nested_attributes_spec.rb +251 -89
  240. data/spec/extensions/null_dataset_spec.rb +85 -0
  241. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  242. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  243. data/spec/extensions/pg_array_spec.rb +196 -0
  244. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  245. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  246. data/spec/extensions/pg_hstore_spec.rb +195 -0
  247. data/spec/extensions/pg_inet_spec.rb +44 -0
  248. data/spec/extensions/pg_json_spec.rb +101 -0
  249. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  250. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  251. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  252. data/spec/extensions/prepared_statements_spec.rb +87 -0
  253. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  254. data/spec/extensions/pretty_table_spec.rb +7 -6
  255. data/spec/extensions/query_literals_spec.rb +168 -0
  256. data/spec/extensions/query_spec.rb +6 -0
  257. data/spec/extensions/rcte_tree_spec.rb +50 -43
  258. data/spec/extensions/schema_caching_spec.rb +41 -0
  259. data/spec/extensions/schema_dumper_spec.rb +429 -22
  260. data/spec/extensions/schema_spec.rb +25 -21
  261. data/spec/extensions/select_remove_spec.rb +38 -0
  262. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  263. data/spec/extensions/serialization_spec.rb +85 -43
  264. data/spec/extensions/server_block_spec.rb +90 -0
  265. data/spec/extensions/sharding_spec.rb +69 -143
  266. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  267. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  268. data/spec/extensions/spec_helper.rb +22 -61
  269. data/spec/extensions/sql_expr_spec.rb +29 -60
  270. data/spec/extensions/static_cache_spec.rb +145 -0
  271. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  272. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  273. data/spec/extensions/timestamps_spec.rb +6 -6
  274. data/spec/extensions/to_dot_spec.rb +4 -7
  275. data/spec/extensions/touch_spec.rb +13 -14
  276. data/spec/extensions/tree_spec.rb +11 -26
  277. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  278. data/spec/extensions/update_primary_key_spec.rb +30 -24
  279. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  280. data/spec/extensions/validation_helpers_spec.rb +16 -35
  281. data/spec/extensions/xml_serializer_spec.rb +29 -4
  282. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  283. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  284. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  285. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  286. data/spec/integration/associations_test.rb +659 -21
  287. data/spec/integration/database_test.rb +9 -3
  288. data/spec/integration/dataset_test.rb +605 -91
  289. data/spec/integration/eager_loader_test.rb +19 -21
  290. data/spec/integration/migrator_test.rb +2 -3
  291. data/spec/integration/model_test.rb +81 -2
  292. data/spec/integration/plugin_test.rb +454 -143
  293. data/spec/integration/prepared_statement_test.rb +263 -128
  294. data/spec/integration/schema_test.rb +309 -43
  295. data/spec/integration/spec_helper.rb +40 -30
  296. data/spec/integration/timezone_test.rb +38 -12
  297. data/spec/integration/transaction_test.rb +183 -8
  298. data/spec/integration/type_test.rb +18 -4
  299. data/spec/model/association_reflection_spec.rb +201 -7
  300. data/spec/model/associations_spec.rb +1067 -661
  301. data/spec/model/base_spec.rb +329 -95
  302. data/spec/model/dataset_methods_spec.rb +7 -27
  303. data/spec/model/eager_loading_spec.rb +677 -676
  304. data/spec/model/hooks_spec.rb +349 -67
  305. data/spec/model/model_spec.rb +240 -168
  306. data/spec/model/plugins_spec.rb +24 -13
  307. data/spec/model/record_spec.rb +490 -232
  308. data/spec/model/spec_helper.rb +14 -71
  309. data/spec/model/validations_spec.rb +11 -0
  310. data/spec/rcov.opts +2 -0
  311. metadata +178 -80
@@ -1,13 +1,13 @@
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
7
 
8
8
  # Converts a uri to an options hash. These options are then passed
9
9
  # to a newly created database object.
10
- def self.uri_to_options(uri) # :nodoc:
10
+ def self.uri_to_options(uri)
11
11
  { :user => uri.user,
12
12
  :password => uri.password,
13
13
  :host => uri.host,
@@ -19,11 +19,14 @@ module Sequel
19
19
  # The options hash for this database
20
20
  attr_reader :opts
21
21
 
22
+ # Set the timezone to use for this database, overridding <tt>Sequel.database_timezone</tt>.
23
+ attr_writer :timezone
24
+
22
25
  # Constructs a new instance of a database connection with the specified
23
26
  # options hash.
24
27
  #
25
28
  # Accepts the following options:
26
- # :default_schema :: The default schema to use, should generally be nil
29
+ # :default_schema :: The default schema to use, see #default_schema.
27
30
  # :disconnection_proc :: A proc used to disconnect the connection
28
31
  # :identifier_input_method :: A string method symbol to call on identifiers going into the database
29
32
  # :identifier_output_method :: A string method symbol to call on identifiers coming from the database
@@ -50,14 +53,50 @@ module Sequel
50
53
  @schemas = {}
51
54
  @default_schema = @opts.fetch(:default_schema, default_schema_default)
52
55
  @prepared_statements = {}
53
- @transactions = []
56
+ @transactions = {}
54
57
  @identifier_input_method = nil
55
58
  @identifier_output_method = nil
56
59
  @quote_identifiers = nil
60
+ @timezone = nil
61
+ @dataset_class = dataset_class_default
62
+ @cache_schema = typecast_value_boolean(@opts.fetch(:cache_schema, true))
63
+ @dataset_modules = []
57
64
  self.sql_log_level = @opts[:sql_log_level] ? @opts[:sql_log_level].to_sym : :info
58
65
  @pool = ConnectionPool.get_pool(@opts, &block)
59
66
 
60
- ::Sequel::DATABASES.push(self)
67
+ Sequel.synchronize{::Sequel::DATABASES.push(self)}
68
+ end
69
+
70
+ # If a transaction is not currently in process, yield to the block immediately.
71
+ # Otherwise, add the block to the list of blocks to call after the currently
72
+ # in progress transaction commits (and only if it commits).
73
+ # Options:
74
+ # :server :: The server/shard to use.
75
+ def after_commit(opts={}, &block)
76
+ raise Error, "must provide block to after_commit" unless block
77
+ synchronize(opts[:server]) do |conn|
78
+ if h = _trans(conn)
79
+ raise Error, "cannot call after_commit in a prepared transaction" if h[:prepare]
80
+ (h[:after_commit] ||= []) << block
81
+ else
82
+ yield
83
+ end
84
+ end
85
+ end
86
+
87
+ # If a transaction is not currently in progress, ignore the block.
88
+ # Otherwise, add the block to the list of the blocks to call after the currently
89
+ # in progress transaction rolls back (and only if it rolls back).
90
+ # Options:
91
+ # :server :: The server/shard to use.
92
+ def after_rollback(opts={}, &block)
93
+ raise Error, "must provide block to after_rollback" unless block
94
+ synchronize(opts[:server]) do |conn|
95
+ if h = _trans(conn)
96
+ raise Error, "cannot call after_rollback in a prepared transaction" if h[:prepare]
97
+ (h[:after_rollback] ||= []) << block
98
+ end
99
+ end
61
100
  end
62
101
 
63
102
  # Cast the given type to a literal type
@@ -68,11 +107,35 @@ module Sequel
68
107
  type_literal(:type=>type)
69
108
  end
70
109
 
110
+ # Convert the given timestamp from the application's timezone,
111
+ # to the databases's timezone or the default database timezone if
112
+ # the database does not have a timezone.
113
+ def from_application_timestamp(v)
114
+ Sequel.convert_output_timestamp(v, timezone)
115
+ end
116
+
117
+ # Whether the database uses a global namespace for the index. If
118
+ # false, the indexes are going to be namespaced per table.
119
+ def global_index_namespace?
120
+ true
121
+ end
122
+
123
+ # Return true if already in a transaction given the options,
124
+ # false otherwise. Respects the :server option for selecting
125
+ # a shard.
126
+ def in_transaction?(opts={})
127
+ synchronize(opts[:server]){|conn| !!_trans(conn)}
128
+ end
129
+
71
130
  # 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).
131
+ # class name and connection URI and options used when connecting (if any).
74
132
  def inspect
75
- "#<#{self.class}: #{(uri rescue opts).inspect}>"
133
+ a = []
134
+ a << uri.inspect if uri
135
+ if (oo = opts[:orig_opts]) && !oo.empty?
136
+ a << oo.inspect
137
+ end
138
+ "#<#{self.class}: #{a.join(' ')}>"
76
139
  end
77
140
 
78
141
  # Proxy the literal call to the dataset.
@@ -84,12 +147,34 @@ module Sequel
84
147
  schema_utility_dataset.literal(v)
85
148
  end
86
149
 
150
+ # Synchronize access to the prepared statements cache.
151
+ def prepared_statement(name)
152
+ Sequel.synchronize{prepared_statements[name]}
153
+ end
154
+
87
155
  # Default serial primary key options, used by the table creation
88
156
  # code.
89
157
  def serial_primary_key_options
90
158
  {:primary_key => true, :type => Integer, :auto_increment => true}
91
159
  end
92
160
 
161
+ # Cache the prepared statement object at the given name.
162
+ def set_prepared_statement(name, ps)
163
+ Sequel.synchronize{prepared_statements[name] = ps}
164
+ end
165
+
166
+ # Whether the database supports CREATE TABLE IF NOT EXISTS syntax,
167
+ # false by default.
168
+ def supports_create_table_if_not_exists?
169
+ false
170
+ end
171
+
172
+ # Whether the database supports DROP TABLE IF EXISTS syntax,
173
+ # default is the same as #supports_create_table_if_not_exists?.
174
+ def supports_drop_table_if_exists?
175
+ supports_create_table_if_not_exists?
176
+ end
177
+
93
178
  # Whether the database and adapter support prepared transactions
94
179
  # (two-phase commit), false by default.
95
180
  def supports_prepared_transactions?
@@ -101,11 +186,34 @@ module Sequel
101
186
  false
102
187
  end
103
188
 
189
+ # Whether the database and adapter support savepoints inside prepared transactions
190
+ # (two-phase commit), default is false.
191
+ def supports_savepoints_in_prepared_transactions?
192
+ supports_prepared_transactions? && supports_savepoints?
193
+ end
194
+
104
195
  # Whether the database and adapter support transaction isolation levels, false by default.
105
196
  def supports_transaction_isolation_levels?
106
197
  false
107
198
  end
108
199
 
200
+ # Whether DDL statements work correctly in transactions, false by default.
201
+ def supports_transactional_ddl?
202
+ false
203
+ end
204
+
205
+ # The timezone to use for this database, defaulting to <tt>Sequel.database_timezone</tt>.
206
+ def timezone
207
+ @timezone || Sequel.database_timezone
208
+ end
209
+
210
+ # Convert the given timestamp to the application's timezone,
211
+ # from the databases's timezone or the default database timezone if
212
+ # the database does not have a timezone.
213
+ def to_application_timestamp(v)
214
+ Sequel.convert_timestamp(v, timezone)
215
+ end
216
+
109
217
  # Typecast the value to the given column_type. Calls
110
218
  # typecast_value_#{column_type} if the method exists,
111
219
  # otherwise returns the value.
@@ -121,29 +229,10 @@ module Sequel
121
229
  end
122
230
  end
123
231
 
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"
232
+ # Returns the URI use to connect to the database. If a URI
233
+ # was not used when connecting, returns nil.
132
234
  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
235
+ opts[:uri]
147
236
  end
148
237
 
149
238
  # Explicit alias of uri for easier subclassing.
@@ -175,12 +264,17 @@ module Sequel
175
264
  def database_error_classes
176
265
  []
177
266
  end
267
+
268
+ # Return true if exception represents a disconnect error, false otherwise.
269
+ def disconnect_error?(exception, opts)
270
+ opts[:disconnect]
271
+ end
178
272
 
179
273
  # Convert the given exception to a DatabaseError, keeping message
180
274
  # and traceback.
181
275
  def raise_error(exception, opts={})
182
276
  if !opts[:classes] || Array(opts[:classes]).any?{|c| exception.is_a?(c)}
183
- raise Sequel.convert_exception_class(exception, opts[:disconnect] ? DatabaseDisconnectError : DatabaseError)
277
+ raise Sequel.convert_exception_class(exception, disconnect_error?(exception, opts) ? DatabaseDisconnectError : DatabaseError)
184
278
  else
185
279
  raise exception
186
280
  end
@@ -194,7 +288,7 @@ module Sequel
194
288
  # Typecast the value to true, false, or nil
195
289
  def typecast_value_boolean(value)
196
290
  case value
197
- when false, 0, "0", /\Af(alse)?\z/i
291
+ when false, 0, "0", /\Af(alse)?\z/i, /\Ano?\z/i
198
292
  false
199
293
  else
200
294
  blank_object?(value) ? nil : true
@@ -204,10 +298,10 @@ module Sequel
204
298
  # Typecast the value to a Date
205
299
  def typecast_value_date(value)
206
300
  case value
207
- when Date
208
- value
209
301
  when DateTime, Time
210
302
  Date.new(value.year, value.month, value.day)
303
+ when Date
304
+ value
211
305
  when String
212
306
  Sequel.string_to_date(value)
213
307
  when Hash
@@ -219,12 +313,7 @@ module Sequel
219
313
 
220
314
  # Typecast the value to a DateTime or Time depending on Sequel.datetime_class
221
315
  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
316
+ Sequel.typecast_to_application_timestamp(value)
228
317
  end
229
318
 
230
319
  # Typecast the value to a BigDecimal
@@ -244,9 +333,21 @@ module Sequel
244
333
  Float(value)
245
334
  end
246
335
 
247
- # Typecast the value to an Integer
248
- def typecast_value_integer(value)
249
- Integer(value)
336
+ # Used for checking/removing leading zeroes from strings so they don't get
337
+ # interpreted as octal.
338
+ LEADING_ZERO_RE = /\A0+(\d)/.freeze
339
+ if RUBY_VERSION >= '1.9'
340
+ # Typecast the value to an Integer
341
+ def typecast_value_integer(value)
342
+ (value.is_a?(String) && value =~ LEADING_ZERO_RE) ? Integer(value, 10) : Integer(value)
343
+ end
344
+ else
345
+ # Replacement string when replacing leading zeroes.
346
+ LEADING_ZERO_REP = "\\1".freeze
347
+ # Typecast the value to an Integer
348
+ def typecast_value_integer(value)
349
+ Integer(value.is_a?(String) ? value.sub(LEADING_ZERO_RE, LEADING_ZERO_REP) : value)
350
+ end
250
351
  end
251
352
 
252
353
  # Typecast the value to a String
@@ -258,12 +359,15 @@ module Sequel
258
359
  def typecast_value_time(value)
259
360
  case value
260
361
  when Time
261
- value
362
+ if value.is_a?(SQLTime)
363
+ value
364
+ else
365
+ SQLTime.create(value.hour, value.min, value.sec, value.respond_to?(:nsec) ? value.nsec/1000.0 : value.usec)
366
+ end
262
367
  when String
263
368
  Sequel.string_to_time(value)
264
369
  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})
370
+ SQLTime.create(*[:hour, :minute, :second].map{|x| (value[x] || value[x.to_s]).to_i})
267
371
  else
268
372
  raise Sequel::InvalidValue, "invalid value for Time: #{value.inspect}"
269
373
  end