sequel 3.21.0 → 3.32.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 (234) hide show
  1. data/CHANGELOG +539 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +20 -6
  4. data/Rakefile +37 -19
  5. data/bin/sequel +1 -5
  6. data/doc/advanced_associations.rdoc +17 -0
  7. data/doc/association_basics.rdoc +293 -43
  8. data/doc/dataset_basics.rdoc +4 -4
  9. data/doc/dataset_filtering.rdoc +8 -0
  10. data/doc/mass_assignment.rdoc +54 -0
  11. data/doc/migration.rdoc +15 -538
  12. data/doc/model_hooks.rdoc +72 -27
  13. data/doc/opening_databases.rdoc +89 -50
  14. data/doc/prepared_statements.rdoc +40 -13
  15. data/doc/reflection.rdoc +8 -2
  16. data/doc/release_notes/3.22.0.txt +39 -0
  17. data/doc/release_notes/3.23.0.txt +172 -0
  18. data/doc/release_notes/3.24.0.txt +420 -0
  19. data/doc/release_notes/3.25.0.txt +88 -0
  20. data/doc/release_notes/3.26.0.txt +88 -0
  21. data/doc/release_notes/3.27.0.txt +82 -0
  22. data/doc/release_notes/3.28.0.txt +304 -0
  23. data/doc/release_notes/3.29.0.txt +459 -0
  24. data/doc/release_notes/3.30.0.txt +135 -0
  25. data/doc/release_notes/3.31.0.txt +146 -0
  26. data/doc/release_notes/3.32.0.txt +202 -0
  27. data/doc/schema_modification.rdoc +547 -0
  28. data/doc/sharding.rdoc +7 -1
  29. data/doc/testing.rdoc +129 -0
  30. data/doc/transactions.rdoc +137 -0
  31. data/doc/virtual_rows.rdoc +2 -2
  32. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  33. data/lib/sequel/adapters/ado.rb +40 -18
  34. data/lib/sequel/adapters/amalgalite.rb +17 -9
  35. data/lib/sequel/adapters/db2.rb +175 -86
  36. data/lib/sequel/adapters/dbi.rb +15 -15
  37. data/lib/sequel/adapters/do/mysql.rb +5 -7
  38. data/lib/sequel/adapters/do/postgres.rb +0 -5
  39. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  40. data/lib/sequel/adapters/do.rb +17 -36
  41. data/lib/sequel/adapters/firebird.rb +27 -208
  42. data/lib/sequel/adapters/ibmdb.rb +448 -0
  43. data/lib/sequel/adapters/informix.rb +6 -23
  44. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  45. data/lib/sequel/adapters/jdbc/db2.rb +52 -0
  46. data/lib/sequel/adapters/jdbc/derby.rb +260 -0
  47. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  48. data/lib/sequel/adapters/jdbc/h2.rb +66 -30
  49. data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
  50. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  51. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  52. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  53. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  54. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  55. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  58. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  59. data/lib/sequel/adapters/jdbc.rb +231 -78
  60. data/lib/sequel/adapters/mock.rb +339 -0
  61. data/lib/sequel/adapters/mysql.rb +85 -184
  62. data/lib/sequel/adapters/mysql2.rb +26 -25
  63. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  64. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  65. data/lib/sequel/adapters/odbc.rb +28 -9
  66. data/lib/sequel/adapters/openbase.rb +3 -5
  67. data/lib/sequel/adapters/oracle.rb +355 -53
  68. data/lib/sequel/adapters/postgres.rb +194 -33
  69. data/lib/sequel/adapters/shared/access.rb +32 -9
  70. data/lib/sequel/adapters/shared/db2.rb +328 -0
  71. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  72. data/lib/sequel/adapters/shared/informix.rb +53 -0
  73. data/lib/sequel/adapters/shared/mssql.rb +278 -107
  74. data/lib/sequel/adapters/shared/mysql.rb +203 -65
  75. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  76. data/lib/sequel/adapters/shared/oracle.rb +237 -46
  77. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  78. data/lib/sequel/adapters/shared/progress.rb +5 -8
  79. data/lib/sequel/adapters/shared/sqlite.rb +200 -50
  80. data/lib/sequel/adapters/sqlite.rb +29 -21
  81. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  82. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  83. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  84. data/lib/sequel/adapters/swift.rb +5 -5
  85. data/lib/sequel/adapters/tinytds.rb +160 -19
  86. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  87. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  88. data/lib/sequel/ast_transformer.rb +190 -0
  89. data/lib/sequel/connection_pool/threaded.rb +3 -2
  90. data/lib/sequel/connection_pool.rb +1 -1
  91. data/lib/sequel/core.rb +68 -5
  92. data/lib/sequel/database/connecting.rb +5 -6
  93. data/lib/sequel/database/dataset.rb +4 -4
  94. data/lib/sequel/database/dataset_defaults.rb +59 -1
  95. data/lib/sequel/database/logging.rb +1 -1
  96. data/lib/sequel/database/misc.rb +104 -19
  97. data/lib/sequel/database/query.rb +163 -59
  98. data/lib/sequel/database/schema_generator.rb +17 -7
  99. data/lib/sequel/database/schema_methods.rb +59 -29
  100. data/lib/sequel/dataset/actions.rb +240 -76
  101. data/lib/sequel/dataset/features.rb +91 -8
  102. data/lib/sequel/dataset/graph.rb +38 -11
  103. data/lib/sequel/dataset/misc.rb +50 -23
  104. data/lib/sequel/dataset/mutation.rb +12 -7
  105. data/lib/sequel/dataset/prepared_statements.rb +59 -27
  106. data/lib/sequel/dataset/query.rb +236 -43
  107. data/lib/sequel/dataset/sql.rb +676 -267
  108. data/lib/sequel/dataset.rb +8 -0
  109. data/lib/sequel/exceptions.rb +4 -0
  110. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  111. data/lib/sequel/extensions/migration.rb +6 -4
  112. data/lib/sequel/extensions/named_timezones.rb +5 -0
  113. data/lib/sequel/extensions/query.rb +1 -1
  114. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  115. data/lib/sequel/extensions/to_dot.rb +95 -83
  116. data/lib/sequel/model/associations.rb +1081 -344
  117. data/lib/sequel/model/base.rb +420 -133
  118. data/lib/sequel/model/errors.rb +1 -1
  119. data/lib/sequel/model/exceptions.rb +5 -1
  120. data/lib/sequel/model.rb +20 -10
  121. data/lib/sequel/plugins/active_model.rb +13 -1
  122. data/lib/sequel/plugins/association_pks.rb +22 -4
  123. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  124. data/lib/sequel/plugins/composition.rb +43 -10
  125. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  126. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  127. data/lib/sequel/plugins/force_encoding.rb +6 -6
  128. data/lib/sequel/plugins/identity_map.rb +114 -7
  129. data/lib/sequel/plugins/many_through_many.rb +68 -7
  130. data/lib/sequel/plugins/nested_attributes.rb +65 -10
  131. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  132. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  133. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  134. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  135. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  136. data/lib/sequel/plugins/serialization.rb +98 -49
  137. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  138. data/lib/sequel/plugins/sharding.rb +21 -54
  139. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  140. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  141. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  142. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  143. data/lib/sequel/sql.rb +109 -52
  144. data/lib/sequel/timezones.rb +57 -38
  145. data/lib/sequel/version.rb +1 -1
  146. data/spec/adapters/db2_spec.rb +146 -0
  147. data/spec/adapters/mssql_spec.rb +135 -30
  148. data/spec/adapters/mysql_spec.rb +244 -212
  149. data/spec/adapters/oracle_spec.rb +67 -77
  150. data/spec/adapters/postgres_spec.rb +267 -78
  151. data/spec/adapters/spec_helper.rb +6 -5
  152. data/spec/adapters/sqlite_spec.rb +35 -21
  153. data/spec/core/connection_pool_spec.rb +71 -92
  154. data/spec/core/core_sql_spec.rb +21 -30
  155. data/spec/core/database_spec.rb +789 -512
  156. data/spec/core/dataset_spec.rb +1176 -1061
  157. data/spec/core/expression_filters_spec.rb +159 -42
  158. data/spec/core/mock_adapter_spec.rb +419 -0
  159. data/spec/core/object_graph_spec.rb +86 -114
  160. data/spec/core/schema_generator_spec.rb +3 -3
  161. data/spec/core/schema_spec.rb +298 -38
  162. data/spec/core/spec_helper.rb +6 -48
  163. data/spec/extensions/active_model_spec.rb +13 -0
  164. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  165. data/spec/extensions/association_dependencies_spec.rb +2 -12
  166. data/spec/extensions/association_pks_spec.rb +66 -32
  167. data/spec/extensions/caching_spec.rb +23 -50
  168. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  169. data/spec/extensions/columns_introspection_spec.rb +91 -0
  170. data/spec/extensions/composition_spec.rb +18 -13
  171. data/spec/extensions/dataset_associations_spec.rb +199 -0
  172. data/spec/extensions/defaults_setter_spec.rb +64 -0
  173. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  174. data/spec/extensions/identity_map_spec.rb +114 -22
  175. data/spec/extensions/instance_filters_spec.rb +11 -21
  176. data/spec/extensions/instance_hooks_spec.rb +53 -0
  177. data/spec/extensions/json_serializer_spec.rb +4 -5
  178. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  179. data/spec/extensions/list_spec.rb +17 -39
  180. data/spec/extensions/many_through_many_spec.rb +283 -250
  181. data/spec/extensions/migration_spec.rb +35 -32
  182. data/spec/extensions/named_timezones_spec.rb +23 -3
  183. data/spec/extensions/nested_attributes_spec.rb +97 -88
  184. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  185. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  186. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  187. data/spec/extensions/prepared_statements_spec.rb +53 -0
  188. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  189. data/spec/extensions/pretty_table_spec.rb +1 -6
  190. data/spec/extensions/query_spec.rb +6 -0
  191. data/spec/extensions/rcte_tree_spec.rb +41 -43
  192. data/spec/extensions/schema_dumper_spec.rb +5 -8
  193. data/spec/extensions/schema_spec.rb +13 -21
  194. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  195. data/spec/extensions/serialization_spec.rb +81 -43
  196. data/spec/extensions/sharding_spec.rb +66 -140
  197. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  198. data/spec/extensions/spec_helper.rb +13 -61
  199. data/spec/extensions/sql_expr_spec.rb +20 -60
  200. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  201. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  202. data/spec/extensions/timestamps_spec.rb +6 -6
  203. data/spec/extensions/to_dot_spec.rb +4 -7
  204. data/spec/extensions/touch_spec.rb +13 -14
  205. data/spec/extensions/tree_spec.rb +11 -26
  206. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  207. data/spec/extensions/update_primary_key_spec.rb +30 -24
  208. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  209. data/spec/extensions/validation_helpers_spec.rb +16 -35
  210. data/spec/extensions/xml_serializer_spec.rb +16 -4
  211. data/spec/integration/associations_test.rb +661 -21
  212. data/spec/integration/database_test.rb +4 -2
  213. data/spec/integration/dataset_test.rb +500 -67
  214. data/spec/integration/eager_loader_test.rb +19 -21
  215. data/spec/integration/model_test.rb +80 -1
  216. data/spec/integration/plugin_test.rb +367 -119
  217. data/spec/integration/prepared_statement_test.rb +222 -125
  218. data/spec/integration/schema_test.rb +217 -39
  219. data/spec/integration/spec_helper.rb +39 -30
  220. data/spec/integration/timezone_test.rb +38 -12
  221. data/spec/integration/transaction_test.rb +182 -5
  222. data/spec/integration/type_test.rb +17 -3
  223. data/spec/model/association_reflection_spec.rb +201 -7
  224. data/spec/model/associations_spec.rb +955 -662
  225. data/spec/model/base_spec.rb +275 -95
  226. data/spec/model/dataset_methods_spec.rb +7 -27
  227. data/spec/model/eager_loading_spec.rb +677 -676
  228. data/spec/model/hooks_spec.rb +349 -67
  229. data/spec/model/model_spec.rb +222 -168
  230. data/spec/model/plugins_spec.rb +24 -13
  231. data/spec/model/record_spec.rb +381 -218
  232. data/spec/model/spec_helper.rb +13 -71
  233. data/spec/model/validations_spec.rb +11 -0
  234. metadata +117 -73
data/doc/model_hooks.rdoc CHANGED
@@ -4,7 +4,7 @@ This guide is based on http://guides.rubyonrails.org/activerecord_validations_ca
4
4
 
5
5
  == Overview
6
6
 
7
- Model hooks, also known as model callbacks, are used to specify actions that occur at a given point in a model instance's lifecycle, such as before or after the model object is saved, created, updated, destroyed, or validated.
7
+ Model hooks, also known as model callbacks, are used to specify actions that occur at a given point in a model instance's lifecycle, such as before or after the model object is saved, created, updated, destroyed, or validated. There are also around hooks for all types, which wrap the before hooks, the behavior, and the after hooks.
8
8
 
9
9
  == Basic Usage
10
10
 
@@ -23,41 +23,59 @@ The one important thing to note here is the call to +super+ inside the hook. Wh
23
23
 
24
24
  Sequel calls hooks in the following order when saving/creating a new object (one that does not already exist in the database):
25
25
 
26
- * +before_validation+
27
- * +after_validation+
28
- * +before_save+
29
- * +before_create+
30
- * INSERT QUERY
31
- * +after_create+
32
- * +after_save+
26
+ * +around_validation+
27
+ * +before_validation+
28
+ * +validate+ method called
29
+ * +after_validation+
30
+ * +around_save+
31
+ * +before_save+
32
+ * +around_create+
33
+ * +before_create+
34
+ * INSERT QUERY
35
+ * +after_create+
36
+ * +after_save+
33
37
 
34
38
  Sequel calls hooks in the following order when saving an existing object:
35
39
 
36
- * +before_validation+
37
- * +after_validation+
38
- * +before_save+
39
- * +before_update+
40
- * UPDATE QUERY
41
- * +after_update+
42
- * +after_save+
40
+ * +around_validation+
41
+ * +before_validation+
42
+ * +validate+ method called
43
+ * +after_validation+
44
+ * +around_save+
45
+ * +before_save+
46
+ * +around_update+
47
+ * +before_update+
48
+ * INSERT QUERY
49
+ * +after_update+
50
+ * +after_save+
43
51
 
44
- Note that all of the hook calls are the same, except that +before_create+ and +after_create+ are used for a new object, and +before_update+ and +after_update+ are used for an existing object. Note that +before_save+ is called in both cases, before either +before_create+ or +before_update+, and that +after_save+ is also called in both cases, after either +after_create+ or +after_update+.
52
+ Note that all of the hook calls are the same, except that +around_create+, +before_create+ and +after_create+ are used for a new object, and +around_update+, +before_update+ and +after_update+ are used for an existing object. Note that +around_save+, +before_save+, and +after_save+ are called in both cases.
45
53
 
46
54
  Also note that the validation hooks are not called if the <tt>:validate => false</tt> option is passed to save. However, the validation hooks are called if you call <tt>Model#valid?</tt> manually:
47
55
 
48
- * +before_validation+
49
- * VALIDATION HAPPENS
50
- * +after_validation+
56
+ * +around_validation+
57
+ * +before_validation+
58
+ * +validate+ method called
59
+ * +after_validation+
51
60
 
52
61
  Sequel calls hooks in the following order when destroying an existing object:
53
62
 
54
- * +before_destroy+
55
- * DELETE QUERY
56
- * +after_destroy+
63
+ * +around_destroy+
64
+ * +before_destroy+
65
+ * DELETE QUERY
66
+ * +after_destroy+
57
67
 
58
68
  Note that these hooks are only called when using <tt>Model#destroy</tt>, they are not called if you use <tt>Model#delete</tt>.
59
69
 
60
- <tt>Sequel::Model</tt> does support one additional hook, +after_intialize+, which is called after the model object has been initalized. It can be used to set default attribute values for new objects, since by default new <tt>Sequel::Model</tt> objects have no attributes, and the attributes are not filled in until the model object is saved. You should be careful when you are using +after_initialize+, since it is called for every created record. So if you run a query that returns 1000 model objects, it will be called 1000 times.
70
+ <tt>Sequel::Model</tt> does support a few additional hooks. One is +after_intialize+, which is called after the model object has been initalized. It can be used to set default attribute values for new objects, since by default new <tt>Sequel::Model</tt> objects have no attributes, and the attributes are not filled in until the model object is saved. You should be careful when you are using +after_initialize+, since it is called for every created record. So if you run a query that returns 1000 model objects, it will be called 1000 times. If you only want to change the behavior for new records, you can override the +initialize_set+ private method, which is called with the hash passed to +initialize+.
71
+
72
+ == Transaction-related Hooks
73
+
74
+ There are four other model hooks that <tt>Sequel::Model</tt> supports, all related to transactions. These are +after_commit+, +after_rollback+, +after_destroy_commit+, and +after_destroy_rollback+. +after_commit+ is called after the transaction in which you saved the object commits, only if it commits. +after_rollback+ is called after the transaction in which you saved the object rolls back, if it rolls back. +after_destroy_commit+ is called after the transaction in which you destroyed the object commits, if it commits. +after_destroy_rollback+ is called after the transaction in which you destroyed the object rolls back, if it rolls back.
75
+
76
+ If you aren't using transactions when saving or destroying model objects, and there isn't a currently open transaction, +after_commit+ and +after_destroy_commit+ will be called after +after_save+ and +after_destroy+, respectively, and +after_rollback+ and +after_destroy_rollback+ won't be called at all.
77
+
78
+ The purpose of these hooks is dealing with external systems that are interacting with the same database. For example, let's say you have a model that stores a picture, and you have a background job library that makes thumbnails of all of the pictures. So when a model object is created, you want to add a background job that will create the thumbnail for the picture. If you used after_save for this and transactions are being used, you are subject to a race condition where the background job library will check the database table for the record before the transaction that saved the record commits, and it won't be able to see the record's data. Using after_commit, you are guaranteed that the background job library will not get notified of the record until after the transaction commits and the data is viewable.
61
79
 
62
80
  == Running Hooks
63
81
 
@@ -98,7 +116,7 @@ If you want to insert a row into the model's table without running the creation
98
116
 
99
117
  == Halting Hook Processing
100
118
 
101
- Sequel uses a convention that if any <tt>before_*</tt> hook method returns false (but not nil), that the action will be canceled. You can use this to implement validation-like behavior, that will run even if validations are skipped. For example:
119
+ Sequel uses a convention that if any <tt>before_*</tt> hook method returns false (but not nil), that the action will be canceled and a <tt>Sequel::HookFailed</tt> raised (or +nil+ to be returned by +save+ if +raise_on_save_failure+ is +false+). You can use this to implement validation-like behavior, that will run even if validations are skipped. For example:
102
120
 
103
121
  class Album < Sequel::Model
104
122
  def before_save
@@ -107,9 +125,9 @@ Sequel uses a convention that if any <tt>before_*</tt> hook method returns false
107
125
  end
108
126
  end
109
127
 
110
- While returning false is not really recommended, you should be aware of this behavior so that you do not inadvertently return false.
128
+ While returning false is not really recommended, you should be aware of this behavior so that you do not inadvertently return false. For around hooks, neglecting to call +super+ halts hook processing in the same way as returning +false+ in a before hook. You can't halt hook processing in after hooks, since by then the main processing has already taken place.
111
129
 
112
- By default, Sequel runs hooks other than validation hooks inside a transaction, so if you abort the hook by returning false in a before hook or by raising an exception in the hook, Sequel will rollback the transaction. However, note that the implicit use of transactions when saving and destroying model objects is conditional (it depends on the model instance's +use_transactions+ setting).
130
+ By default, Sequel runs hooks other than validation hooks inside a transaction, so if you abort the hook by returning false in a before hook or by raising an exception in any hook, Sequel will rollback the transaction. However, note that the implicit use of transactions when saving and destroying model objects is conditional (it depends on the model instance's +use_transactions+ setting and the <tt>:transaction</tt> option passed to save).
113
131
 
114
132
  == Conditional Hooks
115
133
 
@@ -183,6 +201,7 @@ This allows the following general principles to be true:
183
201
 
184
202
  * before hooks are run in reverse order of inclusion
185
203
  * after hooks are run in order of inclusion
204
+ * returning false in any before hook will pass the false value down the hook method chain, halting the hook processing.
186
205
 
187
206
  So if you define the same before hook in both a model and a plugin that the model uses, the hooks will be called in this order:
188
207
 
@@ -193,6 +212,32 @@ So if you define the same before hook in both a model and a plugin that the mode
193
212
 
194
213
  Again, Sequel does not enforce that, and you are free to call +super+ in an order other than the recommended one (just make sure that you call it).
195
214
 
215
+ == Around Hooks
216
+
217
+ Around hooks should only be used if you cannot accomplish the same results with before and after hooks. For example, if you want to catch database errors caused by the +INSERT+ or +UPDATE+ query when saving a model object and raise them as validation errors, you cannot use a before or after hook. You have use an +around_save+ hook:
218
+
219
+ class Album < Sequel::Model
220
+ def around_save
221
+ super
222
+ rescue Sequel::DatabaseError => e
223
+ # parse database error, set error on self, and reraise a Sequel::ValidationFailed
224
+ end
225
+ end
226
+
227
+ Likewise, let's say that upon retrieval, you associate an object with a file descriptor, and you want to ensure that the file descriptor is closed after the object is saved to the database. Let's assume you are always saving the object and you are not using validations. You could not use an +after_save+ hook safely, since if the database raises an error, the +after_save+ method will not be called. In this case, an +around_save+ hook is also the correct choice:
228
+
229
+ class Album < Sequel::Model
230
+ def around_save
231
+ super
232
+ ensure
233
+ @file_descriptor.close
234
+ end
235
+ end
236
+
196
237
  == +hook_class_methods+
197
238
 
198
- While it's recommended to write your hooks as instance methods, Sequel ships with a +hook_class_methods+ plugin that allows you to define hooks via class methods. It exists mostly for legacy compatibility, but is still supported.
239
+ While it's recommended to write your hooks as instance methods, Sequel ships with a +hook_class_methods+ plugin that allows you to define hooks via class methods. It exists mostly for legacy compatibility, but is still supported. However, it does not implement around hooks.
240
+
241
+ == +instance_hooks+
242
+
243
+ Sequel also ships with an +instance_hooks+ plugin that allows you to define before and after hooks on a per instance basis. It's very useful as it allows you to delay action on an instance until before or after saving. This can be important if you want to modify a group of related objects together (which is how the +nested_attributes+ plugin uses +instance_hooks+).
@@ -46,6 +46,13 @@ unless the first argument is a hash. So the following statements are equivalent
46
46
  DB = Sequel.postgres('blog', :host=>'localhost', :user=>'user', :password=>'password')
47
47
  DB = Sequel.postgres(:host=>'localhost', :user=>'user', :password=>'password', :database=>'blog')
48
48
 
49
+ Note that using an adapter method forces the use of the specified adapter, not a database type, even
50
+ though some adapters have the same name as the database type. So if you
51
+ want to connect to SQLite, for example, you can do so using the sqlite, do, dbi, jdbc, odbc, and swift adapters.
52
+ If you want to connect to SQLite on JRuby using the jdbc adapter, you should not use <tt>Sequel.sqlite</tt>
53
+ for example, as that uses the C-based sqlite3 gem. Instead, the <tt>Sequel.jdbc</tt> would be appropriate (though
54
+ as mentioned below, using <tt>Sequel.connect</tt> is recommended instead of <tt>Sequel.jdbc</tt>).
55
+
49
56
  == Passing a block to either method
50
57
 
51
58
  Both the Sequel.connect method and the specialized adapter methods take a block. If you
@@ -59,24 +66,24 @@ For example:
59
66
 
60
67
  These options are shared by all adapters unless otherwise noted.
61
68
 
62
- * :adapter - The adapter to use
63
- * :database - The name of the database to which to connect
64
- * :default_schema - The database schema to use by default.
65
- * :host - The hostname of the database server to which to connect
66
- * :logger - An array of SQL loggers to log to
67
- * :loggers - An array of SQL loggers to log to
68
- * :password - The password for the user account
69
- * :servers - A hash with symbol keys and hash or proc values, used with master/slave/partitioned database configurations
70
- * :single_threaded - Whether to use a single-threaded (non-thread safe) connection pool
71
- * :test - Whether to test that a valid database connection can be made (false by default)
72
- * :user - The user account name to use logging in
69
+ :adapter :: The adapter to use
70
+ :database :: The name of the database to which to connect
71
+ :default_schema :: The database schema to use by default.
72
+ :host :: The hostname of the database server to which to connect
73
+ :logger :: An array of SQL loggers to log to
74
+ :loggers :: An array of SQL loggers to log to
75
+ :password :: The password for the user account
76
+ :servers :: A hash with symbol keys and hash or proc values, used with master/slave/partitioned database configurations
77
+ :single_threaded :: Whether to use a single-threaded (non-thread safe) connection pool
78
+ :test :: Whether to test that a valid database connection can be made (false by default)
79
+ :user :: The user account name to use logging in
73
80
 
74
81
  The following options can be specified and are passed to the the database's internal connection pool.
75
82
 
76
- * :after_connect - A proc called after a new connection is made, with the connection object (default: nil)
77
- * :max_connections - The maximum size of the connection pool (default: 4 connections on most databases)
78
- * :pool_sleep_time - The number of seconds to sleep before trying to acquire a connection again (default: 0.001 seconds)
79
- * :pool_timeout - The number of seconds to wait if a connection cannot be acquired before raising an error (default: 5 seconds)
83
+ :after_connect :: A proc called after a new connection is made, with the connection object (default: nil)
84
+ :max_connections :: The maximum size of the connection pool (default: 4 connections on most databases)
85
+ :pool_sleep_time :: The number of seconds to sleep before trying to acquire a connection again (default: 0.001 seconds)
86
+ :pool_timeout :: The number of seconds to wait if a connection cannot be acquired before raising an error (default: 5 seconds)
80
87
 
81
88
  == Adapter specific connection options
82
89
 
@@ -131,8 +138,8 @@ Amalgalite is an ruby extension that provides self contained access to SQLite,
131
138
  so you don't need to install SQLite separately. As amalgalite is a file backed
132
139
  database, the :host, :user, and :password options are not used.
133
140
 
134
- * :database - The name of the database file
135
- * :timeout - The busy timeout period given in milliseconds
141
+ :database :: The name of the database file
142
+ :timeout :: The busy timeout period given in milliseconds
136
143
 
137
144
  Without a database argument, assumes a memory database, so you can do:
138
145
 
@@ -145,17 +152,15 @@ the sqlite section below for details.
145
152
 
146
153
  Requires: db2/db2cli
147
154
 
148
- I'm not even sure exactly how this works, or if it works at all (I've never heard from
149
- anyone who attempted to use it). It uses the SQL_HANDLE_DBC constant to
150
- get a handle, and respects the :database, :user, and :password options. It doesn't
151
- appear to respect the :host or :port options.
155
+ This is the older DB2 adapter. It's recommended you try the ibmdb adapter
156
+ instead for new DB2 work, as it is better supported.
152
157
 
153
158
  === dbi
154
159
 
155
160
  Allows access to a multitude of databases via ruby-dbi. Additional options:
156
161
 
157
- * :db_type - Specifying 'mssql' allows Microsoft SQL Server specific syntax to
158
- be used. Otherwise has no effect.
162
+ :db_type :: Specifying 'mssql' allows Microsoft SQL Server specific syntax to
163
+ be used. Otherwise has no effect.
159
164
 
160
165
  DBI connection strings are a preprocessed a bit, and are specified with a dbi-
161
166
  in front of the protocol. Examples:
@@ -201,6 +206,13 @@ Requires: fb (using code at http://github.com/wishdev/fb)
201
206
 
202
207
  Does not support the :port option.
203
208
 
209
+ === ibmdb
210
+
211
+ requires 'ibm_db'
212
+
213
+ This connects to DB2 using IBM_DB. This is the recommended adapter if you are
214
+ using a C-based ruby to connect to DB2.
215
+
204
216
  === informix
205
217
 
206
218
  Does not support the :host or :port options. Depending on the configuration of your server
@@ -221,7 +233,7 @@ Requires: java
221
233
  Houses Sequel's JDBC support when running on JRuby.
222
234
  Support for individual database types is done using sub adapters.
223
235
  There are currently subadapters for PostgreSQL, MySQL, SQLite, H2,
224
- Oracle, MSSQL, JTDS, and AS400. All except Oracle, MSSQL, and AS400 can load the
236
+ Oracle, MSSQL, JTDS, AS400, and DB2. All except Oracle, MSSQL, AS400, and DB2 can load the
225
237
  jdbc-* gem, for those you need to have the .jar in your CLASSPATH
226
238
  or load the Java class manually before calling Sequel.connect.
227
239
 
@@ -246,37 +258,51 @@ Example connection strings:
246
258
  jdbc:postgresql://localhost/database?user=username
247
259
  jdbc:mysql://localhost/test?user=root&password=root
248
260
  jdbc:h2:mem:
261
+ jdbc:hsqldb:mem:mymemdb
262
+ jdbc:derby:memory:myDb;create=true
249
263
  jdbc:sqlserver://localhost;database=sequel_test;integratedSecurity=true
250
264
  jdbc:jtds:sqlserver://localhost/sequel_test;user=sequel_test;password=sequel_test
251
-
265
+ jdbc:oracle:thin:user/password@localhost:1521:database
266
+ jdbc:db2://localhost:3700/database:user=user;password=password;
267
+ jdbc:firebirdsql:localhost/3050:/path/to/database.fdb
268
+
252
269
  You can also use JNDI connection strings:
253
270
 
254
271
  jdbc:jndi:java:comp/env/jndi_resource_name
255
272
 
256
273
  The following additional options are supported:
257
274
 
258
- * :convert_types - If set to false, does not attempt to convert some Java types to ruby types.
259
- Setting to false roughly doubles performance when selecting large numbers of rows.
260
- Note that you can't provide this option inside the connection string (as that is passed
261
- directly to JDBC), you have to pass it as a separate option.
275
+ :convert_types :: If set to false, does not attempt to convert some Java types to ruby types.
276
+ Setting to false roughly doubles performance when selecting large numbers of rows.
277
+ Note that you can't provide this option inside the connection string (as that is passed
278
+ directly to JDBC), you have to pass it as a separate option.
279
+ :login_timeout :: Set the login timeout on the JDBC connection (in seconds).
262
280
 
263
281
  === mysql
264
282
 
283
+ Requires: mysqlplus (or mysql if mysqlplus is not available)
284
+
265
285
  The MySQL adapter does not support the pure-ruby MySQL adapter that used to ship with
266
286
  ActiveRecord, it requires the native adapter.
267
287
 
268
288
  The following additional options are supported:
269
289
 
270
- * :auto_is_null - If set to true, makes "WHERE primary_key IS NULL" select the last inserted id.
271
- * :charset - Same as :encoding, :encoding takes precedence.
272
- * :compress - Whether to compress data sent/received via the socket connection.
273
- * :config_default_group - The default group to read from the in the MySQL config file.
274
- * :config_local_infile - If provided, sets the Mysql::OPT_LOCAL_INFILE option on the connection with the given value.
275
- * :encoding - Specify the encoding/character set to use for the connection.
276
- * :socket - Can be used to specify a Unix socket file to connect to instead of a TCP host and port.
277
- * :timeout - Sets the wait_timeout for the connection, defaults to 1 month.
278
- * :read_timeout - Set the timeout in seconds for reading back results to a query.
279
- * :connect_timeout - Set the timeout in seconds before a connection attempt is abandoned.
290
+ :auto_is_null :: If set to true, makes "WHERE primary_key IS NULL" select the last inserted id.
291
+ :charset :: Same as :encoding, :encoding takes precedence.
292
+ :compress :: Whether to compress data sent/received via the socket connection.
293
+ :config_default_group :: The default group to read from the in the MySQL config file.
294
+ :config_local_infile :: If provided, sets the Mysql::OPT_LOCAL_INFILE option on the connection with the given value.
295
+ :encoding :: Specify the encoding/character set to use for the connection.
296
+ :socket :: Can be used to specify a Unix socket file to connect to instead of a TCP host and port.
297
+ :timeout :: Sets the wait_timeout for the connection, defaults to 1 month.
298
+ :read_timeout :: Set the timeout in seconds for reading back results to a query.
299
+ :connect_timeout :: Set the timeout in seconds before a connection attempt is abandoned.
300
+
301
+ === mysql2
302
+
303
+ This is a newer MySQL adapter that does typecasting in C, so it is often faster than the
304
+ mysql adapter. Supports the same additional options as the mysql adapter, except for :compress, and uses
305
+ :timeout instead of :read_timeout and :connect_timeout.
280
306
 
281
307
  === odbc
282
308
 
@@ -287,8 +313,8 @@ The :database option given ODBC database should be the DSN (Descriptive Service
287
313
 
288
314
  The :host and :port options are not respected. The following additional options are supported:
289
315
 
290
- * :db_type - Can be specified as 'mssql' or 'progress' to use SQL syntax specific to those databases.
291
- * :driver - The name of the ODBC driver to utilize.
316
+ :db_type :: Can be specified as 'mssql' or 'progress' to use SQL syntax specific to those databases.
317
+ :driver :: The name of the ODBC driver to utilize.
292
318
 
293
319
  === openbase
294
320
 
@@ -300,7 +326,11 @@ Requires: oci8
300
326
 
301
327
  The following additional options are supported:
302
328
 
303
- * :privilege - The Oracle privilege level.
329
+ :autosequence :: Set to true to use Sequel's conventions to guess the sequence to use for datasets. False
330
+ by default.
331
+ :prefetch_rows :: The number of rows to prefetch. Defaults to 1, a larger number can be specified
332
+ and will improve performance when retrieving a large number of rows.
333
+ :privilege :: The Oracle privilege level.
304
334
 
305
335
  === postgres
306
336
 
@@ -311,11 +341,15 @@ The pg library is the best supported, as it supports real bound variables and pr
311
341
 
312
342
  The following additional options are supported:
313
343
 
314
- * :charset - Same as :encoding, :encoding takes precedence
315
- * :encoding - Set the client_encoding to the given string
344
+ :charset :: Same as :encoding, :encoding takes precedence
345
+ :encoding :: Set the client_encoding to the given string
346
+ :connect_timeout :: Set the number of seconds to wait for a connection (default 20, only respected
347
+ if using the pg library).
316
348
 
317
349
  === sqlite
318
350
 
351
+ Requires: sqlite3
352
+
319
353
  As SQLite is a file-based database, the :host and :port options are ignored, and
320
354
  the :database option should be a path to the file.
321
355
 
@@ -337,7 +371,7 @@ Examples:
337
371
 
338
372
  The following additional options are supported:
339
373
 
340
- * :timeout - the busy timeout to use in milliseconds (default: 5000).
374
+ :timeout :: the busy timeout to use in milliseconds (default: 5000).
341
375
 
342
376
  === swift
343
377
 
@@ -353,16 +387,21 @@ Examples:
353
387
 
354
388
  === tinytds
355
389
 
390
+ Requires: tiny_tds
391
+
356
392
  Because the underscore is not a valid character in a URI schema, the adapter
357
393
  is named tinytds instead of tiny_tds. The connection options are passed directly
358
- to tiny_tds, except that the tiny_tds :dataserver and :username options are set to
359
- the Sequel :host and :user options. The :host option should be an entry in the
360
- freetds.conf file, it's not currently possible to a host not present in the
361
- freetds.conf file. Some options that you may want to set are
362
- :login_timeout, :timeout, :appname, and :encoding, see the tiny_tds README for details.
394
+ to tiny_tds, except that the tiny_tds :username option is set to
395
+ the Sequel :user option. If you want to use an entry in the freetds.conf file, you
396
+ should specify the :dataserver option with that name as the value. Some other
397
+ options that you may want to set are :login_timeout, :timeout, :tds_version, :azure,
398
+ :appname, and :encoding, see the tiny_tds README for details.
399
+
363
400
  For highest performance, you should disable any identifier output method when
364
401
  using the tinytds adapter, which probably means disabling any identifier input method
365
402
  as well. The default for Microsoft SQL Server is to :downcase identifiers on output
366
403
  and :upcase them on input, so the highest performance will require changing the setting
367
404
  from the default.
368
405
 
406
+ The Sequel tinytds adapter requires tiny_tds >= 0.4.5, and if you are using FreeTDS
407
+ 0.91, you must at least be using 0.91rc2 (0.91rc1 does not work).
@@ -3,15 +3,22 @@
3
3
  Sequel has support for prepared statements and bound variables. No matter which
4
4
  database you are using, the Sequel prepared statement/bound variable API remains
5
5
  the same. There is native support for prepared statements/bound variables on
6
- the following databases:
6
+ the following adapters:
7
7
 
8
- * PostgreSQL (using the pg driver, requires type specifiers)
9
- * MySQL (prepared statements only, as the ruby mysql driver doesn't support
10
- bound variables)
11
- * SQLite
12
- * JDBC
8
+ * ibmdb (prepared statements only)
9
+ * jdbc
10
+ * mysql (prepared statements only)
11
+ * mysql2 (prepared statements only)
12
+ * oracle (requires type specifiers for nil/NULL values)
13
+ * postgres (when using the pg driver, may require type specifiers)
14
+ * sqlite
15
+ * tinytds
13
16
 
14
- Support on other databases is emulated via string interpolation.
17
+ Support on other adapters is emulated via string interpolation.
18
+
19
+ You can use the prepared_statements model plugin to automatically use prepared
20
+ statements for some common model actions such as saving or deleting a model
21
+ instance, or looking up a model based on a primary key.
15
22
 
16
23
  == Placeholders
17
24
 
@@ -74,20 +81,20 @@ and update queries, the hash to insert/update is passed to +prepare+:
74
81
 
75
82
  If you are using the ruby-postgres or postgres-pr driver, PostgreSQL uses the
76
83
  default emulated support. If you are using ruby-pg, there is native support,
77
- but it requires type specifiers most of the time. This is easy if you have
84
+ but it may require type specifiers on some old versions (generally not anymore).
78
85
  direct control over the SQL string, but since Sequel abstracts that, the types
79
- have to be specified another way. This is done by adding a __* suffix to the
80
- placeholder symbol (e.g. :$name__text, which will be compiled to "$1::text"
81
- in the SQL). Prepared statements are always server side.
86
+ You can add a __* suffix to the placeholder symbol to specify a type, which
87
+ casts to that type in the SQL (e.g. :$name__text, which will be compiled to
88
+ "$1::text" in the SQL). Prepared statements are always server side.
82
89
 
83
90
  === SQLite
84
91
 
85
92
  SQLite supports both prepared statements and bound variables. Prepared
86
93
  statements are cached per connection.
87
94
 
88
- === MySQL
95
+ === MySQL/Mysql2
89
96
 
90
- The MySQL ruby driver does not support bound variables, so the the bound
97
+ The MySQL/Mysql2 ruby drivers do not support bound variables, so the bound
91
98
  variable methods fall back to string interpolation. It uses server side
92
99
  prepared statements.
93
100
 
@@ -99,6 +106,26 @@ over JDBC, you can add the prepareThreshold=N parameter to the connection
99
106
  string, which will use a server side prepared statement after N calls to
100
107
  the prepared statement.
101
108
 
109
+ === TinyTDS
110
+
111
+ Uses the sp_executesql stored procedure with bound variables, since
112
+ Microsoft SQL Server doesn't support true prepared statements.
113
+
114
+ === IBM_DB
115
+
116
+ DB2 supports both prepared statements and bound variables. Prepared
117
+ statement objects are cached per connection.
118
+
119
+ === Oracle
120
+
121
+ Oracle supports both prepared statements and bound variables. Prepared
122
+ statements (OCI8::Cursor objects) are cached per connection. If you
123
+ ever plan to use a nil/NULL value as a bound variable/prepared statement
124
+ value, you must specify the type in the placeholder using a __* suffix.
125
+ You can use any of the schema types that Sequel supports, such as
126
+ :$name__string or :$num__integer. Using blobs as bound variables is
127
+ not currently supported.
128
+
102
129
  === All Others
103
130
 
104
131
  Support is emulated using interpolation.
data/doc/reflection.rdoc CHANGED
@@ -16,13 +16,19 @@ In some cases, the adapter scheme will be the same as the database to which you
16
16
 
17
17
  == Tables in the Database
18
18
 
19
- On many database types/adapters, Database#tables exists and gives an array of table name symbols:
19
+ Database#tables gives an array of table name symbols:
20
+
21
+ DB.tables # [:table1, :table2, :table3, ...]
22
+
23
+ == Views in the Database
24
+
25
+ Database#views and gives an array of view name symbols:
20
26
 
21
27
  DB.tables # [:table1, :table2, :table3, ...]
22
28
 
23
29
  == Indexes on a table
24
30
 
25
- On a few database types/adapters, Database#indexes takes a table name gives a hash of index information. Keys are index names, values are subhashes with the keys :columns and :unique :
31
+ Database#indexes takes a table name gives a hash of index information. Keys are index names, values are subhashes with the keys :columns and :unique :
26
32
 
27
33
  DB.indexes(:table1) # {:index1=>{:columns=>[:column1], :unique=>false}, :index2=>{:columns=>[:column2, :column3], :unique=>true}}
28
34
 
@@ -0,0 +1,39 @@
1
+ = New Features
2
+
3
+ * Support COLLATE in column definitions. At least MySQL and Microsoft
4
+ SQL Server support them, and PostgreSQL 9.1 should as well.
5
+
6
+ * When connecting to Microsoft SQL Server, you can use the
7
+ mssql_unicode_strings accessor to turn of the default usage
8
+ of unicode strings (N'') and use regular strings (''). This
9
+ can improve performance, but changes the behavior. It's
10
+ set to true by default for backwards compatibility. You can
11
+ change it at both the dataset and database level:
12
+
13
+ DB.mssql_unicode_strings = false # default for datasets
14
+ dataset.mssql_unicode_strings = false # just this dataset
15
+
16
+ * In the oracle adapter, if Sequel.application_timezone is :utc, set
17
+ the timezone for the connection to use the 00:00 timezone.
18
+
19
+ = Other Improvements
20
+
21
+ * In the single_table_inheritance plugin, correctly handle a
22
+ multi-level class hierarchy so that loading instances from a
23
+ middle level of the hierarchy can return instances of subclasses.
24
+
25
+ * Don't use a schema when creating a temporary table, even if
26
+ default_schema is set.
27
+
28
+ * Fix the migrator when a default_schema is used.
29
+
30
+ * In the ado adapter, assume a connection to SQL Server if the
31
+ :conn_string is given and doesn't indicate Access/Jet.
32
+
33
+ * Fix fetching rows in the tinytds adapter when the
34
+ identifier_output_method is nil.
35
+
36
+ * The tinytds adapter now checks for disconnect errors, but it might
37
+ not be reliable until the next release of tiny_tds.
38
+
39
+ * The odbc adapter now handles ODBC::Time instances correctly.