sequel 3.21.0 → 3.28.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 (158) hide show
  1. data/CHANGELOG +294 -0
  2. data/README.rdoc +20 -6
  3. data/Rakefile +20 -15
  4. data/doc/association_basics.rdoc +210 -43
  5. data/doc/dataset_basics.rdoc +4 -4
  6. data/doc/mass_assignment.rdoc +54 -0
  7. data/doc/migration.rdoc +15 -538
  8. data/doc/model_hooks.rdoc +64 -27
  9. data/doc/opening_databases.rdoc +37 -10
  10. data/doc/prepared_statements.rdoc +16 -10
  11. data/doc/reflection.rdoc +8 -2
  12. data/doc/release_notes/3.22.0.txt +39 -0
  13. data/doc/release_notes/3.23.0.txt +172 -0
  14. data/doc/release_notes/3.24.0.txt +420 -0
  15. data/doc/release_notes/3.25.0.txt +88 -0
  16. data/doc/release_notes/3.26.0.txt +88 -0
  17. data/doc/release_notes/3.27.0.txt +82 -0
  18. data/doc/release_notes/3.28.0.txt +304 -0
  19. data/doc/schema_modification.rdoc +547 -0
  20. data/doc/testing.rdoc +106 -0
  21. data/doc/transactions.rdoc +97 -0
  22. data/doc/virtual_rows.rdoc +2 -2
  23. data/lib/sequel/adapters/ado.rb +12 -1
  24. data/lib/sequel/adapters/amalgalite.rb +4 -0
  25. data/lib/sequel/adapters/db2.rb +95 -58
  26. data/lib/sequel/adapters/do.rb +12 -0
  27. data/lib/sequel/adapters/firebird.rb +25 -203
  28. data/lib/sequel/adapters/ibmdb.rb +440 -0
  29. data/lib/sequel/adapters/informix.rb +4 -19
  30. data/lib/sequel/adapters/jdbc/as400.rb +0 -7
  31. data/lib/sequel/adapters/jdbc/db2.rb +49 -0
  32. data/lib/sequel/adapters/jdbc/firebird.rb +34 -0
  33. data/lib/sequel/adapters/jdbc/h2.rb +16 -5
  34. data/lib/sequel/adapters/jdbc/informix.rb +31 -0
  35. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  36. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  37. data/lib/sequel/adapters/jdbc/mysql.rb +9 -0
  38. data/lib/sequel/adapters/jdbc/oracle.rb +2 -27
  39. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -0
  40. data/lib/sequel/adapters/jdbc/sqlserver.rb +46 -0
  41. data/lib/sequel/adapters/jdbc/transactions.rb +34 -0
  42. data/lib/sequel/adapters/jdbc.rb +62 -29
  43. data/lib/sequel/adapters/mysql.rb +22 -139
  44. data/lib/sequel/adapters/mysql2.rb +9 -14
  45. data/lib/sequel/adapters/odbc/db2.rb +21 -0
  46. data/lib/sequel/adapters/odbc.rb +15 -3
  47. data/lib/sequel/adapters/oracle.rb +17 -1
  48. data/lib/sequel/adapters/postgres.rb +111 -16
  49. data/lib/sequel/adapters/shared/access.rb +21 -0
  50. data/lib/sequel/adapters/shared/db2.rb +290 -0
  51. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  52. data/lib/sequel/adapters/shared/informix.rb +45 -0
  53. data/lib/sequel/adapters/shared/mssql.rb +85 -47
  54. data/lib/sequel/adapters/shared/mysql.rb +50 -7
  55. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
  56. data/lib/sequel/adapters/shared/oracle.rb +0 -4
  57. data/lib/sequel/adapters/shared/postgres.rb +75 -43
  58. data/lib/sequel/adapters/shared/sqlite.rb +56 -8
  59. data/lib/sequel/adapters/sqlite.rb +12 -11
  60. data/lib/sequel/adapters/swift/mysql.rb +9 -0
  61. data/lib/sequel/adapters/tinytds.rb +139 -7
  62. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +55 -0
  63. data/lib/sequel/ast_transformer.rb +190 -0
  64. data/lib/sequel/connection_pool/threaded.rb +3 -2
  65. data/lib/sequel/connection_pool.rb +1 -1
  66. data/lib/sequel/core.rb +6 -5
  67. data/lib/sequel/database/connecting.rb +5 -5
  68. data/lib/sequel/database/dataset.rb +1 -1
  69. data/lib/sequel/database/dataset_defaults.rb +1 -1
  70. data/lib/sequel/database/logging.rb +1 -1
  71. data/lib/sequel/database/misc.rb +38 -17
  72. data/lib/sequel/database/query.rb +50 -19
  73. data/lib/sequel/database/schema_generator.rb +8 -5
  74. data/lib/sequel/database/schema_methods.rb +52 -27
  75. data/lib/sequel/dataset/actions.rb +167 -48
  76. data/lib/sequel/dataset/features.rb +57 -8
  77. data/lib/sequel/dataset/graph.rb +1 -1
  78. data/lib/sequel/dataset/misc.rb +39 -20
  79. data/lib/sequel/dataset/mutation.rb +3 -3
  80. data/lib/sequel/dataset/prepared_statements.rb +29 -14
  81. data/lib/sequel/dataset/query.rb +182 -32
  82. data/lib/sequel/dataset/sql.rb +31 -58
  83. data/lib/sequel/dataset.rb +8 -0
  84. data/lib/sequel/exceptions.rb +4 -0
  85. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  86. data/lib/sequel/extensions/migration.rb +6 -4
  87. data/lib/sequel/extensions/to_dot.rb +95 -83
  88. data/lib/sequel/model/associations.rb +893 -309
  89. data/lib/sequel/model/base.rb +302 -105
  90. data/lib/sequel/model/errors.rb +1 -1
  91. data/lib/sequel/model/exceptions.rb +5 -1
  92. data/lib/sequel/model.rb +13 -7
  93. data/lib/sequel/plugins/association_pks.rb +22 -4
  94. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  95. data/lib/sequel/plugins/identity_map.rb +113 -6
  96. data/lib/sequel/plugins/many_through_many.rb +67 -5
  97. data/lib/sequel/plugins/prepared_statements.rb +140 -0
  98. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  99. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  100. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  101. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  102. data/lib/sequel/plugins/sharding.rb +12 -20
  103. data/lib/sequel/plugins/single_table_inheritance.rb +2 -0
  104. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  105. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  106. data/lib/sequel/sql.rb +107 -51
  107. data/lib/sequel/timezones.rb +12 -3
  108. data/lib/sequel/version.rb +1 -1
  109. data/spec/adapters/db2_spec.rb +146 -0
  110. data/spec/adapters/mssql_spec.rb +36 -0
  111. data/spec/adapters/mysql_spec.rb +36 -19
  112. data/spec/adapters/postgres_spec.rb +115 -28
  113. data/spec/adapters/spec_helper.rb +6 -0
  114. data/spec/adapters/sqlite_spec.rb +11 -0
  115. data/spec/core/connection_pool_spec.rb +62 -77
  116. data/spec/core/database_spec.rb +244 -287
  117. data/spec/core/dataset_spec.rb +383 -34
  118. data/spec/core/expression_filters_spec.rb +159 -41
  119. data/spec/core/schema_spec.rb +326 -3
  120. data/spec/core/spec_helper.rb +45 -0
  121. data/spec/extensions/association_pks_spec.rb +38 -0
  122. data/spec/extensions/columns_introspection_spec.rb +91 -0
  123. data/spec/extensions/defaults_setter_spec.rb +64 -0
  124. data/spec/extensions/identity_map_spec.rb +162 -0
  125. data/spec/extensions/many_through_many_spec.rb +195 -20
  126. data/spec/extensions/migration_spec.rb +17 -17
  127. data/spec/extensions/nested_attributes_spec.rb +1 -0
  128. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  129. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  130. data/spec/extensions/prepared_statements_spec.rb +72 -0
  131. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  132. data/spec/extensions/schema_dumper_spec.rb +2 -2
  133. data/spec/extensions/schema_spec.rb +12 -20
  134. data/spec/extensions/serialization_modification_detection_spec.rb +36 -0
  135. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  136. data/spec/extensions/spec_helper.rb +3 -1
  137. data/spec/extensions/to_dot_spec.rb +3 -5
  138. data/spec/extensions/xml_serializer_spec.rb +16 -4
  139. data/spec/integration/associations_test.rb +405 -15
  140. data/spec/integration/database_test.rb +4 -2
  141. data/spec/integration/dataset_test.rb +240 -20
  142. data/spec/integration/plugin_test.rb +142 -5
  143. data/spec/integration/prepared_statement_test.rb +174 -95
  144. data/spec/integration/schema_test.rb +128 -16
  145. data/spec/integration/spec_helper.rb +15 -0
  146. data/spec/integration/transaction_test.rb +40 -0
  147. data/spec/integration/type_test.rb +16 -2
  148. data/spec/model/association_reflection_spec.rb +91 -0
  149. data/spec/model/associations_spec.rb +476 -5
  150. data/spec/model/base_spec.rb +91 -1
  151. data/spec/model/eager_loading_spec.rb +519 -31
  152. data/spec/model/hooks_spec.rb +161 -0
  153. data/spec/model/model_spec.rb +89 -2
  154. data/spec/model/plugins_spec.rb +17 -0
  155. data/spec/model/record_spec.rb +184 -12
  156. data/spec/model/spec_helper.rb +5 -0
  157. data/spec/model/validations_spec.rb +11 -0
  158. metadata +85 -34
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,51 @@ 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 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. 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+.
61
71
 
62
72
  == Running Hooks
63
73
 
@@ -98,7 +108,7 @@ If you want to insert a row into the model's table without running the creation
98
108
 
99
109
  == Halting Hook Processing
100
110
 
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:
111
+ 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
112
 
103
113
  class Album < Sequel::Model
104
114
  def before_save
@@ -107,9 +117,9 @@ Sequel uses a convention that if any <tt>before_*</tt> hook method returns false
107
117
  end
108
118
  end
109
119
 
110
- While returning false is not really recommended, you should be aware of this behavior so that you do not inadvertently return false.
120
+ 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
121
 
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).
122
+ 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
123
 
114
124
  == Conditional Hooks
115
125
 
@@ -183,6 +193,7 @@ This allows the following general principles to be true:
183
193
 
184
194
  * before hooks are run in reverse order of inclusion
185
195
  * after hooks are run in order of inclusion
196
+ * returning false in any before hook will pass the false value down the hook method chain, halting the hook processing.
186
197
 
187
198
  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
199
 
@@ -193,6 +204,32 @@ So if you define the same before hook in both a model and a plugin that the mode
193
204
 
194
205
  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
206
 
207
+ == Around Hooks
208
+
209
+ 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:
210
+
211
+ class Album < Sequel::Model
212
+ def around_save
213
+ super
214
+ rescue Sequel::DatabaseError => e
215
+ # parse database error, set error on self, and reraise a Sequel::ValidationFailed
216
+ end
217
+ end
218
+
219
+ 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:
220
+
221
+ class Album < Sequel::Model
222
+ def around_save
223
+ super
224
+ ensure
225
+ @file_descriptor.close
226
+ end
227
+ end
228
+
196
229
  == +hook_class_methods+
197
230
 
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.
231
+ 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.
232
+
233
+ == +instance_hooks+
234
+
235
+ 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
@@ -145,10 +152,8 @@ 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
 
@@ -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
 
@@ -262,6 +274,8 @@ The following additional options are supported:
262
274
 
263
275
  === mysql
264
276
 
277
+ Requires: mysqlplus (or mysql if mysqlplus is not available)
278
+
265
279
  The MySQL adapter does not support the pure-ruby MySQL adapter that used to ship with
266
280
  ActiveRecord, it requires the native adapter.
267
281
 
@@ -278,6 +292,12 @@ The following additional options are supported:
278
292
  * :read_timeout - Set the timeout in seconds for reading back results to a query.
279
293
  * :connect_timeout - Set the timeout in seconds before a connection attempt is abandoned.
280
294
 
295
+ === mysql2
296
+
297
+ This is a newer MySQL adapter that does typecasting in C, so it is often faster than the
298
+ mysql adapter. Supports the same additional options as the mysql adapter, except for :compress, and uses
299
+ :timeout instead of :read_timeout and :connect_timeout.
300
+
281
301
  === odbc
282
302
 
283
303
  The ODBC adapter allows you to connect to any database with the appropriate ODBC drivers installed.
@@ -316,6 +336,8 @@ The following additional options are supported:
316
336
 
317
337
  === sqlite
318
338
 
339
+ Requires: sqlite3
340
+
319
341
  As SQLite is a file-based database, the :host and :port options are ignored, and
320
342
  the :database option should be a path to the file.
321
343
 
@@ -353,16 +375,21 @@ Examples:
353
375
 
354
376
  === tinytds
355
377
 
378
+ Requires: tiny_tds
379
+
356
380
  Because the underscore is not a valid character in a URI schema, the adapter
357
381
  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.
382
+ to tiny_tds, except that the tiny_tds :username option is set to
383
+ the Sequel :user option. If you want to use an entry in the freetds.conf file, you
384
+ should specify the :dataserver option with that name as the value. Some other
385
+ options that you may want to set are :login_timeout, :timeout, :tds_version, :azure,
386
+ :appname, and :encoding, see the tiny_tds README for details.
387
+
363
388
  For highest performance, you should disable any identifier output method when
364
389
  using the tinytds adapter, which probably means disabling any identifier input method
365
390
  as well. The default for Microsoft SQL Server is to :downcase identifiers on output
366
391
  and :upcase them on input, so the highest performance will require changing the setting
367
392
  from the default.
368
393
 
394
+ The Sequel tinytds adapter requires tiny_tds >= 0.4.5, and if you are using FreeTDS
395
+ 0.91, you must at least be using 0.91rc2 (0.91rc1 does not work).
@@ -3,15 +3,21 @@
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
+ * postgres (when using the pg driver, may require type specifiers)
13
+ * sqlite
14
+ * tinytds
13
15
 
14
- Support on other databases is emulated via string interpolation.
16
+ Support on other adapters is emulated via string interpolation.
17
+
18
+ You can use the prepared_statements model plugin to automatically use prepared
19
+ statements for some common model actions such as saving or deleting a model
20
+ instance, or looking up a model based on a primary key.
15
21
 
16
22
  == Placeholders
17
23
 
@@ -74,9 +80,9 @@ and update queries, the hash to insert/update is passed to +prepare+:
74
80
 
75
81
  If you are using the ruby-postgres or postgres-pr driver, PostgreSQL uses the
76
82
  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
83
+ but it may require type specifiers. This is easy if you have
78
84
  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
85
+ can be specified another way. This is done by adding a __* suffix to the
80
86
  placeholder symbol (e.g. :$name__text, which will be compiled to "$1::text"
81
87
  in the SQL). Prepared statements are always server side.
82
88
 
@@ -87,7 +93,7 @@ statements are cached per connection.
87
93
 
88
94
  === MySQL
89
95
 
90
- The MySQL ruby driver does not support bound variables, so the the bound
96
+ The MySQL ruby driver does not support bound variables, so the bound
91
97
  variable methods fall back to string interpolation. It uses server side
92
98
  prepared statements.
93
99
 
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.
@@ -0,0 +1,172 @@
1
+ = New Features
2
+
3
+ * Sequel now allows dynamic customization for eager loading.
4
+ Previously, the parameters for eager loading were fixed at
5
+ association creation time. Now, they can be modified at query
6
+ time. To dynamically modify an eager load, you use a hash with
7
+ the proc as the value. For example, if you have this code:
8
+
9
+ Artist.eager(:albums)
10
+
11
+ And you only want to eagerly load albums where the id is greater
12
+ than or equal to some number provided by the user, you do:
13
+
14
+ min = params[:min].to_i
15
+ Artist.eager(:albums=>proc{|ds| ds.where{id > min}})
16
+
17
+ This also works when eager loading via eager_graph:
18
+
19
+ Artist.eager_graph(:albums=>proc{|ds| ds.where{id > min}})
20
+
21
+ For eager_graph, the dataset is the dataset to graph into the
22
+ current dataset, and filtering it will result in an SQL query
23
+ that joins to a subquery.
24
+
25
+ You can also use dynamic customization while cascading to also
26
+ eagerly load dependent associations, by making the hash value
27
+ a single entry hash with a proc key and the value being the
28
+ dependent associations to eagerly load. For example, if you want
29
+ to eagerly load tracks for those albums:
30
+
31
+ Artist.eager(:albums=>{proc{|ds| ds.where{id > min}}=>:tracks})
32
+
33
+ * Sequel also now allows dynamic customization for regular
34
+ association loading. Previously, this was possible by using the
35
+ association's dataset:
36
+
37
+ albums = artist.albums_dataset.filter{id > min}
38
+
39
+ However, then there was no handling of caching, callbacks, or
40
+ reciprocals. For example:
41
+
42
+ albums.each{|album| album.artist}
43
+
44
+ Would issue one query per album to get the artist, because the
45
+ reciprocal association was not set. Now you can provide a
46
+ block to the association method:
47
+
48
+ albums = artist.albums{|ds| ds.filter{id > min}}
49
+
50
+ This block is called with the dataset used to retrieve the
51
+ associated objects, and should return a modified version of that
52
+ dataset.
53
+
54
+ Note that ruby 1.8.6 doesn't allow blocks to take block arguments,
55
+ so you have to pass the block as a separate proc argument to the
56
+ association method if you are still using 1.8.6.
57
+
58
+ * Sequel now supports filtering by associations. This wasn't
59
+ previously supported as filtering is a dataset level feature and
60
+ associations are a model level feature, and datasets do not depend
61
+ on models. Now, model datasets have the ability to filter by
62
+ associations. For example, to get all albums for a given artist,
63
+ you could do:
64
+
65
+ artist = Artist[1]
66
+ Album.filter(:artist=>artist)
67
+
68
+ Since the above can also be accomplished with:
69
+
70
+ artist.albums
71
+
72
+ this may not seem like a big improvement, but it allows you to
73
+ filter on multiple associations simultaneously:
74
+
75
+ Album.filter(:artist=>artist, :publisher=>publisher)
76
+
77
+ For simple many_to_one associations, the above is just a simpler
78
+ way to do:
79
+
80
+ Album.filter(:artist_id=>artist.id, :publisher_id=>publisher.id)
81
+
82
+ Sequel supports this for all association types, including
83
+ many_to_many and many_through_many, where a subquery is used, and
84
+ it also works when composite key associations are used:
85
+
86
+ Album.filter(:artist=>artist, :tags=>tag)
87
+
88
+ This will give you the albums for that artist that are also tagged
89
+ with that tag. To provide multiple values for the same
90
+ association, mostly useful for many_to_many associations, you can
91
+ either use separate filter calls or specify the conditions as an
92
+ array:
93
+
94
+ Album.filter(:tags=>tag1).filter(:tags=>tag2)
95
+ Album.filter([[:tags, tag1], [:tags, tag2]])
96
+
97
+ * A columns_introspection extension has been added that makes
98
+ datasets attempt to guess their columns in some cases instead of
99
+ issuing a database query. This can improve performance in cases
100
+ where the columns are needed implicitly, such as graphing. After
101
+ loading the extension, you can enable the support for specific
102
+ datasets by extending them with Sequel::ColumnIntrospection. To
103
+ enable introspection for all datasets, use:
104
+
105
+ Sequel::Dataset.introspect_all_columns
106
+
107
+ * A serialization_modification_detection plugin has been added.
108
+ Previously, Sequel could not detect modifications made to
109
+ serialized objects. It could detect modification if you assigned
110
+ a new value:
111
+
112
+ model.hash_column = model.hash_column.merge(:foo=>:bar)
113
+
114
+ but not if you just modified the object directly:
115
+
116
+ model.hash_columns[:foo] = :bar
117
+
118
+ With this plugin, such modifications can be detected, at a
119
+ potentially significant performance cost.
120
+
121
+ = Other Improvements
122
+
123
+ * When using a migration directory containing both older integer
124
+ migrations and newer timestamp migrations, where some integer
125
+ migrations have not been applied, make sure to apply the remaining
126
+ integer migrations before the timestamp migrations. Previously,
127
+ they could be applied out of order due to a lexicographic sort
128
+ being used instead of a numeric sort.
129
+
130
+ * If a model does not select all columns from its table, the
131
+ insert_select optimization is no longer used. Previously,
132
+ creating a new model object for such a model could result in the
133
+ object containing columns that the model does not select.
134
+
135
+ * You can now use :select=>[] as an option for many_to_many
136
+ associations to select all columns from both the associated
137
+ table and the join table. Previously, this raised an error and
138
+ required you do :select=>'*'.lit as a workaround. The default
139
+ remains to select all columns in the associated table and none
140
+ from the join table.
141
+
142
+ * The xml_serializer plugin now handles namespaced models by
143
+ using __ instead of / as the namespace separator. Previously, /
144
+ was used and caused problems as it is not valid XML.
145
+
146
+ * The :eager_grapher association option can now accept a proc that
147
+ takes a single hash of options instead of a fixed 3 arguments.
148
+ This is the recommended way going forward of writing custom
149
+ :eager_graphers, and all of the internal ones have been converted.
150
+ The previous way of using 3 arguments is still supported.
151
+
152
+ * A bug in the identity_map plugin for many_to_one associations
153
+ without full association reflection information has been fixed.
154
+
155
+ * Sequel is now using GitHub Issues for issue tracking. Old issues
156
+ have been migrated from Google Code.
157
+
158
+ = Backwards Compatibility
159
+
160
+ * The filter by associations support breaks backward compatibilty for
161
+ users who previously added an sql_literal instance method to
162
+ Sequel::Model. Usually, that was done to for reasons similar to
163
+ but inferior than the filter by association support. The following
164
+ code can be used as a temporary workaround until you can modify
165
+ your program to use the new filter by associations support:
166
+
167
+ Sequel::Model::Associations::DatasetMethods.
168
+ send(:remove_method, :complex_expression_sql)
169
+
170
+ * The private Sequel::Model#_load_associated_objects method now takes
171
+ an additional, optional options hash. Plugins that override that
172
+ method need to be modified.