sequel 3.4.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG +84 -0
  2. data/Rakefile +1 -1
  3. data/doc/cheat_sheet.rdoc +5 -2
  4. data/doc/opening_databases.rdoc +2 -0
  5. data/doc/release_notes/3.5.0.txt +510 -0
  6. data/lib/sequel/adapters/ado.rb +3 -1
  7. data/lib/sequel/adapters/ado/mssql.rb +2 -2
  8. data/lib/sequel/adapters/do.rb +2 -11
  9. data/lib/sequel/adapters/do/mysql.rb +7 -0
  10. data/lib/sequel/adapters/do/postgres.rb +2 -2
  11. data/lib/sequel/adapters/firebird.rb +3 -3
  12. data/lib/sequel/adapters/informix.rb +3 -3
  13. data/lib/sequel/adapters/jdbc/h2.rb +3 -3
  14. data/lib/sequel/adapters/jdbc/mssql.rb +7 -0
  15. data/lib/sequel/adapters/mysql.rb +60 -21
  16. data/lib/sequel/adapters/odbc.rb +1 -1
  17. data/lib/sequel/adapters/openbase.rb +3 -3
  18. data/lib/sequel/adapters/oracle.rb +1 -5
  19. data/lib/sequel/adapters/postgres.rb +3 -3
  20. data/lib/sequel/adapters/shared/mssql.rb +142 -33
  21. data/lib/sequel/adapters/shared/mysql.rb +54 -31
  22. data/lib/sequel/adapters/shared/oracle.rb +17 -6
  23. data/lib/sequel/adapters/shared/postgres.rb +7 -7
  24. data/lib/sequel/adapters/shared/progress.rb +3 -3
  25. data/lib/sequel/adapters/shared/sqlite.rb +3 -17
  26. data/lib/sequel/connection_pool.rb +4 -6
  27. data/lib/sequel/core.rb +29 -113
  28. data/lib/sequel/database.rb +14 -12
  29. data/lib/sequel/dataset.rb +8 -21
  30. data/lib/sequel/dataset/convenience.rb +1 -1
  31. data/lib/sequel/dataset/graph.rb +9 -2
  32. data/lib/sequel/dataset/sql.rb +170 -104
  33. data/lib/sequel/exceptions.rb +3 -0
  34. data/lib/sequel/extensions/looser_typecasting.rb +21 -0
  35. data/lib/sequel/extensions/named_timezones.rb +61 -0
  36. data/lib/sequel/extensions/schema_dumper.rb +7 -1
  37. data/lib/sequel/extensions/sql_expr.rb +122 -0
  38. data/lib/sequel/extensions/string_date_time.rb +4 -4
  39. data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
  40. data/lib/sequel/model/associations.rb +105 -45
  41. data/lib/sequel/model/base.rb +37 -28
  42. data/lib/sequel/plugins/active_model.rb +35 -0
  43. data/lib/sequel/plugins/association_dependencies.rb +96 -0
  44. data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
  45. data/lib/sequel/plugins/force_encoding.rb +61 -0
  46. data/lib/sequel/plugins/many_through_many.rb +32 -11
  47. data/lib/sequel/plugins/nested_attributes.rb +7 -2
  48. data/lib/sequel/plugins/subclasses.rb +45 -0
  49. data/lib/sequel/plugins/touch.rb +118 -0
  50. data/lib/sequel/plugins/typecast_on_load.rb +61 -0
  51. data/lib/sequel/sql.rb +31 -30
  52. data/lib/sequel/timezones.rb +161 -0
  53. data/lib/sequel/version.rb +1 -1
  54. data/spec/adapters/mssql_spec.rb +262 -0
  55. data/spec/adapters/mysql_spec.rb +46 -8
  56. data/spec/adapters/postgres_spec.rb +6 -3
  57. data/spec/adapters/spec_helper.rb +21 -0
  58. data/spec/adapters/sqlite_spec.rb +1 -1
  59. data/spec/core/connection_pool_spec.rb +1 -1
  60. data/spec/core/database_spec.rb +27 -1
  61. data/spec/core/dataset_spec.rb +63 -1
  62. data/spec/core/object_graph_spec.rb +1 -1
  63. data/spec/core/schema_spec.rb +1 -0
  64. data/spec/extensions/active_model_spec.rb +47 -0
  65. data/spec/extensions/association_dependencies_spec.rb +108 -0
  66. data/spec/extensions/class_table_inheritance_spec.rb +252 -0
  67. data/spec/extensions/force_encoding_spec.rb +75 -0
  68. data/spec/extensions/looser_typecasting_spec.rb +39 -0
  69. data/spec/extensions/many_through_many_spec.rb +60 -2
  70. data/spec/extensions/named_timezones_spec.rb +72 -0
  71. data/spec/extensions/nested_attributes_spec.rb +29 -1
  72. data/spec/extensions/schema_dumper_spec.rb +10 -0
  73. data/spec/extensions/spec_helper.rb +1 -1
  74. data/spec/extensions/sql_expr_spec.rb +89 -0
  75. data/spec/extensions/subclasses_spec.rb +52 -0
  76. data/spec/extensions/thread_local_timezones_spec.rb +45 -0
  77. data/spec/extensions/touch_spec.rb +155 -0
  78. data/spec/extensions/typecast_on_load_spec.rb +60 -0
  79. data/spec/integration/database_test.rb +8 -0
  80. data/spec/integration/dataset_test.rb +9 -9
  81. data/spec/integration/plugin_test.rb +139 -0
  82. data/spec/integration/schema_test.rb +7 -7
  83. data/spec/integration/spec_helper.rb +32 -1
  84. data/spec/integration/timezone_test.rb +3 -3
  85. data/spec/integration/transaction_test.rb +1 -1
  86. data/spec/integration/type_test.rb +6 -6
  87. data/spec/model/association_reflection_spec.rb +18 -0
  88. data/spec/model/associations_spec.rb +169 -9
  89. data/spec/model/base_spec.rb +2 -0
  90. data/spec/model/eager_loading_spec.rb +82 -2
  91. data/spec/model/model_spec.rb +8 -1
  92. data/spec/model/record_spec.rb +52 -9
  93. metadata +33 -23
data/CHANGELOG CHANGED
@@ -1,3 +1,87 @@
1
+ === 3.5.0 (2009-10-01)
2
+
3
+ * Correctly literalize timezones in timestamps when using Oracle (jeremyevans)
4
+
5
+ * Add class_table_inheritance plugin, supporting inheritance in the database using a table-per-model-class approach (jeremyevans)
6
+
7
+ * Allow easier overriding of model code to insert and update individual records (jeremyevans)
8
+
9
+ * Allow graphing to work on previously joined datasets, and eager graphing of models backed by joined datasets (jeremyevans)
10
+
11
+ * Fix MSSQL emulated offset support for datasets with row_procs (e.g. Model datasets) (jeremyevans)
12
+
13
+ * Support composite keys with set_primary_key when called with an array of multiple symbols (jeremyevans)
14
+
15
+ * Fix select_more and order_more to not affect receiver (tamas.denes, jeremyevans)
16
+
17
+ * Support composite keys in model associations, including many_through_many plugin support (jeremyevans)
18
+
19
+ * Add the force_encoding plugin for forcing encoding of strings for models (requires ruby 1.9) (jeremyevans)
20
+
21
+ * Support DataObjects 0.10 (previous DataObjects versions are now unsupported) (jeremyevans)
22
+
23
+ * Allow the user to specify the ADO connection string via the :conn_string option (jeremyevans)
24
+
25
+ * Add thread_local_timezones extension for allow per-thread overrides of the global timezone settings (jeremyevans)
26
+
27
+ * Add named_timezones extension for using named timezones such as "America/Los_Angeles" using TZInfo (jeremyevans)
28
+
29
+ * Pass through unsigned/elements/size and other options when altering columns on MySQL (tmm1)
30
+
31
+ * Replace Dataset#virtual_row_block_call with Sequel.virtual_row (jeremyevans)
32
+
33
+ * Allow Dataset #delete, #update, and #insert to respect existing WITH clauses on MSSQL (dlee, jeremyevans)
34
+
35
+ * Add touch plugin, which adds Model#touch for updating an instance's timestamp, as well as touching associations when an instance is updated or destroyed (jeremyevans)
36
+
37
+ * Add sql_expr extension, which adds the sql_expr to all objects, giving them easy access to Sequel's DSL (jeremyevans)
38
+
39
+ * Add active_model plugin, which gives Sequel::Model an ActiveModel compliant API, passes the ActiveModel::Lint tests (jeremyevans)
40
+
41
+ * Fix MySQL commands out of sync error when using queries with multiple result sets without retrieving all result sets (jeremyevans)
42
+
43
+ * Allow splitting of multiple result sets into separate arrays when using multiple statements in a single query in the native MySQL adapter (jeremyevans)
44
+
45
+ * Don't include primary key indexes when parsing MSSQL indexes on JDBC (jeremyevans)
46
+
47
+ * Make Dataset#insert_select return nil on PostgreSQL if disable_insert_returning is used (jeremyevans)
48
+
49
+ * Speed up execution of prepared statements with bound variables on MySQL (ibc@aliax.net)
50
+
51
+ * Add association_dependencies plugin, for deleting, destroying, or nullifying associated objects when destroying a model object (jeremyevans)
52
+
53
+ * Add :validate association option, set to false to not validate when implicitly saving associated objects (jeremyevans)
54
+
55
+ * Add subclasses plugin, for recording all of a models subclasses and descendent classes (jeremyevans)
56
+
57
+ * Add looser_typecasting extension, for using .to_f and .to_i instead of Kernel.Float and Kernel.Integer when typecasting floats and integers (jeremyevans)
58
+
59
+ * Catch database errors when preparing statements or setting variable values when using the native MySQL adapter (jeremyevans)
60
+
61
+ * Add typecast_on_load plugin, for fixing bad database typecasting when loading model objects (jeremyevans)
62
+
63
+ * Detect more types of MySQL disconnection errors (jeremyevans)
64
+
65
+ * Add Sequel.convert_exception_class for wrapping exceptions (jeremyevans)
66
+
67
+ * Model#modified? now always considers new records as modified (jeremyevans)
68
+
69
+ * Typecast before checking current model attribute value, instead of after (jeremyevans)
70
+
71
+ * Don't attempt to use unparseable defaults as literals when dumping the schema for a MySQL database (jeremyevans)
72
+
73
+ * Handle MySQL enum defaults in the schema dumper (jeremyevans)
74
+
75
+ * Support Database#server_version on MSSQL (dlee, jeremyevans)
76
+
77
+ * Support updating and deleting joined datasets on MSSQL (jfirebaugh)
78
+
79
+ * Support the OUTPUT SQL clause on MSSQL delete, insert, and update statements (jfirebaugh)
80
+
81
+ * Refactor generation of delete, insert, select, and update statements (jfirebaugh, jeremyevans)
82
+
83
+ * Do a better job of parsing defaults on MSSQL (jfirebaugh)
84
+
1
85
  === 3.4.0 (2009-09-02)
2
86
 
3
87
  * Allow datasets without tables to work correctly on Oracle (mikegolod)
data/Rakefile CHANGED
@@ -168,7 +168,7 @@ begin
168
168
  t.spec_opts = spec_opts.call
169
169
  end
170
170
 
171
- %w'postgres sqlite mysql informix oracle firebird'.each do |adapter|
171
+ %w'postgres sqlite mysql informix oracle firebird mssql'.each do |adapter|
172
172
  desc "Run #{adapter} specs without coverage"
173
173
  Spec::Rake::SpecTask.new("spec_#{adapter}") do |t|
174
174
  t.spec_files = ["spec/adapters/#{adapter}_spec.rb"] + Dir["spec/integration/*_test.rb"]
data/doc/cheat_sheet.rdoc CHANGED
@@ -121,9 +121,12 @@ You can use arithmetic operators and specify SQL functions:
121
121
 
122
122
  == Joins
123
123
 
124
- DB[:items].left_outer_join(:categories, :id => :category_id).sql #=>
125
- "SELECT * FROM items LEFT OUTER JOIN categories ON categories.id = items.category_id"
124
+ DB[:items].left_outer_join(:categories, :id => :category_id).sql
125
+ #=> "SELECT * FROM items LEFT OUTER JOIN categories ON categories.id = items.category_id"
126
126
 
127
+ DB[:items].join(:categories, :id => :category_id).join(:groups, :id => :items__group_id)
128
+ #=> "SELECT * FROM items INNER JOIN categories ON categories.id = items.category_id INNER JOIN groups ON groups.id = items.group_id"
129
+
127
130
  == Summarizing
128
131
 
129
132
  dataset.count #=> record count
@@ -97,6 +97,8 @@ The following options are supported:
97
97
  to execute a command before cancelling the attempt and generating
98
98
  an error. Specifically, it sets the ADO CommandTimeout property.
99
99
  If this property is not set, the default of 30 seconds is used.
100
+ * :conn_string - The full ADO connection string. If this is provided,
101
+ the general connection options are ignored.
100
102
  * :provider - Sets the Provider of this ADO connection (for example, "SQLOLEDB")
101
103
 
102
104
  === amalgalite
@@ -0,0 +1,510 @@
1
+ New Plugins
2
+ -----------
3
+
4
+ * A class_table_inheritance plugin has been added, supporting model
5
+ inheritance in the database using a table-per-model-class approach.
6
+ Each table stores only attributes unique to that model or subclass
7
+ hierarchy.
8
+
9
+ For example, with this hierarchy:
10
+
11
+ Employee
12
+ / \
13
+ Staff Manager
14
+ |
15
+ Executive
16
+
17
+ the following database schema may be used (table - columns):
18
+
19
+ * employees - id, name, kind
20
+ * staff - id, manager_id
21
+ * managers - id, num_staff
22
+ * executives - id, num_managers
23
+
24
+ The class_table_inheritance plugin assumes that the main table
25
+ (e.g. employees) has a primary key field (usually
26
+ autoincrementing), and all other tables have a foreign key of the
27
+ same name that points to the same key in their superclass's table.
28
+ For example:
29
+
30
+ * employees.id - primary key, autoincrementing
31
+ * staff.id - foreign key referencing employees(id)
32
+ * managers.id - foreign key referencing employees(id)
33
+ * executives.id - foreign key referencing managers(id)
34
+
35
+ When using the class_table_inheritance plugin, subclasses use joined
36
+ datasets:
37
+
38
+ Employee.dataset.sql # SELECT * FROM employees
39
+ Manager.dataset.sql # SELECT * FROM employees
40
+ # INNER JOIN managers USING (id)
41
+ Executive.dataset.sql # SELECT * FROM employees
42
+ # INNER JOIN managers USING (id)
43
+ # INNER JOIN executives USING (id)
44
+
45
+ This allows Executive.all to return instances with all attributes
46
+ loaded. The plugin overrides deleting, inserting, and updating
47
+ in the model to work with multiple tables, by handling each table
48
+ individually.
49
+
50
+ This plugin allows and encourages the use of a :key option to mark
51
+ a column holding the class name. This allows methods on the
52
+ superclass to return instances of specific subclasses.
53
+
54
+ a = Employee.all # [<#Staff>, <#Manager>, <#Executive>]
55
+
56
+ This plugin requires the lazy_attributes plugin and uses it to
57
+ handle subclass specific attributes that would not be loaded
58
+ when calling superclass methods (since those wouldn't join
59
+ to the subclass tables). For example:
60
+
61
+ a.first.values # {:id=>1, name=>'S', :kind=>'Staff'}
62
+ a.first.manager_id # Loads the manager_id attribute from the
63
+ # database
64
+
65
+ The class_table_inheritance plugin requires JOIN USING and
66
+ therefore is not supported on H2 or Microsoft SQL Server, which do
67
+ not support that SQL-92 feature.
68
+
69
+ * An associations_dependencies plugin was added for deleting,
70
+ destroying, or nullifying associated objects when destroying a
71
+ model object. This just gives an easy way to add the necessary
72
+ before and after destroy hooks. The following association types
73
+ support the following dependency actions:
74
+
75
+ * :many_to_many - :nullify (removes all related entries in join
76
+ table)
77
+ * :many_to_one - :delete, :destroy
78
+ * :one_to_many - :delete, :destroy, :nullify (sets foreign key to
79
+ NULL for all associated objects)
80
+
81
+ This plugin works directly with the association datasets and does
82
+ not use any cached association values. The :delete action will
83
+ delete all associated objects from the database in a single SQL
84
+ call. The :destroy action will load each associated object from the
85
+ database and call the destroy method on it.
86
+
87
+ The plugin call takes a hash of association symbol keys and
88
+ dependency action symbol values. Alternatively, you can specify
89
+ additional dependencies later using add_association_dependencies:
90
+
91
+ Business.plugin :association_dependencies, :address=>:delete
92
+ # or:
93
+ Artist.plugin :association_dependencies
94
+ Artist.add_association_dependencies :albums=>:destroy,
95
+ :reviews=>:delete, :tags=>:nullify
96
+
97
+ * A force_encoding plugin was added that forces the encoding of
98
+ strings used in model instances. When model instances are loaded
99
+ from the database, all values in the hash that are strings are
100
+ forced to the given encoding. Whenever you update a model column
101
+ attribute, the resulting value is forced to a given encoding if the
102
+ value is a string. There are two ways to specify the encoding.
103
+ You can either do so in the plugin call itself, or via the
104
+ forced_encoding class accessor:
105
+
106
+ class Album < Sequel::Model
107
+ plugin :force_encoding, 'UTF-8'
108
+ # or
109
+ plugin :force_encoding
110
+ self.forced_encoding = 'UTF-8'
111
+ end
112
+
113
+ This plugin only works on ruby 1.9, since strings don't have
114
+ encodings in 1.8.
115
+
116
+ * A typecast_on_load plugin was added, for fixing bad database
117
+ typecasting when loading model objects. Most of Sequel's database
118
+ adapters don't have complete control over typecasting, and may
119
+ return columns that aren't typecast correctly (with correct being
120
+ defined as how the model object would typecast the same column
121
+ values).
122
+
123
+ This plugin modifies Model.load to call the setter methods (which
124
+ typecast by default) for all columns given. You can either specify
125
+ the columns to typecast on load in the plugin call itself, or
126
+ afterwards using add_typecast_on_load_columns:
127
+
128
+ Album.plugin :typecast_on_load, :release_date, :record_date
129
+ # or:
130
+ Album.plugin :typecast_on_load
131
+ Album.add_typecast_on_load_columns :release_date, :record_date
132
+
133
+ If the database returns release_date and record_date columns as
134
+ strings instead of dates, this will ensure that if you access those
135
+ columns through the model object, you'll get Date objects instead of
136
+ strings.
137
+
138
+ * A touch plugin was added, which adds Model#touch for updating an
139
+ instance's timestamp, as well as touching associations when an
140
+ instance is updated or destroyed.
141
+
142
+ The Model#touch instance method saves the object with a modified
143
+ timestamp. By default, it uses the :updated_at column, but you can
144
+ set which column to use. It also supports touching of associations,
145
+ so that when the current model object is updated or destroyed, the
146
+ associated rows in the database can have their modified timestamp
147
+ updated to the current timestamp. Example:
148
+
149
+ class Album < Sequel::Model
150
+ plugin :touch, :column=>:modified_on, :associations=>:artist
151
+ end
152
+
153
+ * A subclasses plugin was added, for recording all of a models
154
+ subclasses and descendent classes. Direct subclasses are available
155
+ via the subclasses method, and all descendent classes are available
156
+ via the descendents method:
157
+
158
+ c = Class.new(Sequel::Model)
159
+ c.plugin :subclasses
160
+ sc1 = Class.new(c)
161
+ sc2 = Class.new(c)
162
+ ssc1 = Class.new(sc1)
163
+ c.subclasses # [sc1, sc2]
164
+ sc1.subclasses # [ssc1]
165
+ sc2.subclasses # []
166
+ ssc1.subclasses # []
167
+ c.descendents # [sc1, ssc1, sc2]
168
+
169
+ The main use case for this is if you want to modify all models
170
+ after the model subclasses have been created. Since mutable
171
+ options are copied when subclassing, modifying parent classes
172
+ does not affect current subclasses, only future ones. The
173
+ subclasses plugin allows you get all subclasses so that you can
174
+ easily modify them. The plugin only records subclasses
175
+ created after the plugin call, though.
176
+
177
+ * An active_model plugin was added, giving Sequel::Model an
178
+ ActiveModel complaint API, in so much as it passes the
179
+ ActiveModel::Lint tests.
180
+
181
+ New Extensions
182
+ --------------
183
+
184
+ * A named_timezones extension was added, allowing you to use named
185
+ timezones such as "America/Los_Angeles" (the default Sequel
186
+ timezone support only supports UTC or local time). This extension
187
+ requires TZInfo. It also sets the Sequel.datetime_class to
188
+ DateTime, so database timestamps will be returned as DateTime
189
+ instances instead of Time instances. This is because ruby's
190
+ Time class doesn't support timezones other than UTC and local time.
191
+
192
+ This plugin allows you to pass either strings or TZInfo::Timezone
193
+ instance to Sequel.database_timezone=, application_timezone=, and
194
+ typecast_timezone=. If a string is passed, it is converted to a
195
+ TZInfo::Timezone using TZInfo::Timezone.get.
196
+
197
+ Let's say you have the database server in New York and the
198
+ application server in Los Angeles. For historical reasons, data
199
+ is stored in local New York time, but the application server only
200
+ services clients in Los Angeles, so you want to use New York
201
+ time in the database and Los Angeles time in the application. This
202
+ is easily done via:
203
+
204
+ Sequel.database_timezone = 'America/New_York'
205
+ Sequel.application_timezone = 'America/Los_Angeles'
206
+
207
+ Then, before timestamps are stored in the database, they are
208
+ converted to New York time. When timestamps are retrieved from the
209
+ database, they are converted to Los Angeles time.
210
+
211
+ * A thread_local_timezones extension was added. This allows you to
212
+ set a per-thread timezone that will override the default global
213
+ timezone while the thread is executing. The main use case is for
214
+ web applications that execute each request in its own thread, and
215
+ want to set the timezones based on the request. The most common
216
+ example is having the database always store time in UTC, but have
217
+ the application deal with the timezone of the current user. That
218
+ can be done with:
219
+
220
+ Sequel.database_timezone = :utc
221
+ # In each thread:
222
+ Sequel.thread_application_timezone = current_user.timezone
223
+
224
+ This extension is designed to work with the named_timezones
225
+ extension.
226
+
227
+ * An sql_expr extension was added that adds .sql_expr methods to
228
+ all objects, giving them easy access to Sequel's DSL:
229
+
230
+ 1.sql_expr < :a # 1 < a
231
+ false.sql_expr & :a # FALSE AND a
232
+ true.sql_expr | :a # TRUE OR a
233
+ ~nil.sql_expr # NOT NULL
234
+ "a".sql_expr + "b" # 'a' || 'b'
235
+
236
+ Proc#sql_expr uses a virtual row:
237
+
238
+ proc{[[a, b], [a, c]]}.sql_expr | :x
239
+ # (((a = b) AND (a = c)) OR x)
240
+
241
+ * A looser_typecasting extension was added, for using to_f and to_i
242
+ instead of the more strict Kernel.Float and Kernel.Integer when
243
+ typecasting floats and integers. To use it, you should extend the
244
+ database with the Sequel::LooserTypecasting module after loading
245
+ the extension:
246
+
247
+ Sequel.extension :looser_typecasting
248
+ DB.extend(Sequel::LooserTypecasting)
249
+
250
+ This makes the behavior more like ActiveRecord:
251
+
252
+ a = Artist.new(:num_albums=>'a')
253
+ a.num_albums # => 0
254
+
255
+ Other New Features
256
+ ------------------
257
+
258
+ * Associations now support composite keys. All of the :*key options
259
+ options now accept arrays of symbols instead of plain symbols.
260
+ Example:
261
+
262
+ Artist.primary_key # [:name, :city]
263
+ Album.many_to_one :artist, :key=>[:artist_name, :artist_city]
264
+ Artist.one_to_many :albums, :key=>[:artist_name, :artist_city]
265
+
266
+ All association types are supported, including the built-in
267
+ many_to_many association and the many_through_many plugin. Both
268
+ methods of eager loading work with composite keys for all
269
+ association types. Setter and add/remove/remove_all methods
270
+ also now work with composite keys.
271
+
272
+ * Associations now respect a :validate option, which can be set to
273
+ false to not validate when implicitly saving associated objects.
274
+
275
+ There isn't a lot of implicit saving in Sequel's association
276
+ methods, but this gives the user the control over validation when
277
+ the association methods implicitly save an object.
278
+
279
+ * In addition to the regular association methods, the
280
+ nested_attributes plugin was also updated to respect the
281
+ :validate_association option. It was also modified to not validate
282
+ associated objects twice, once when the parent object was validated
283
+ and again when the associated object was saved. Additionally, if
284
+ you pass :validate=>false to the save method when saving the parent
285
+ object, it will not longer attempt to validate associated objects
286
+ when saving them.
287
+
288
+ * Dataset#insert and #insert_sql were refactored and now support the
289
+ following API:
290
+
291
+ * No arguments - Treat as a single empty hash argument
292
+ * Single argument:
293
+ * Hash - Use keys as columns and values as values
294
+ * Array - Use as values, without specifying columns
295
+ * Dataset - Use a subselect, without specifying columns
296
+ * LiteralString - Use as the values
297
+ * 2 arguments:
298
+ * Array, Array - Use first array as keys, second as values
299
+ * Array, Dataset - Use a subselect, with the array as columns
300
+ * Array, LiteralString - Use LiteralString as the values, with
301
+ the array as the columns
302
+ * Anything else: Treat all given values an an array of values
303
+
304
+ * Graphing now works with previously joined datasets. The main use
305
+ case of this is when eagerly loading (via eager_graph) model
306
+ associations for models backed by joined datasets, such as those
307
+ created by the class_table_inheritance plugin.
308
+
309
+ * Sequel.virtual_row was added allowing you to easily use the
310
+ VirtualRow support outside of select, order, and filter calls:
311
+
312
+ net_benefit = Sequel.virtual_row{revenue > cost}
313
+ good_employee = Sequel.virtual_row{num_commendations > 0}
314
+ fire = ~net_benefit & ~good_employee
315
+ demote = ~net_benefit & good_employee
316
+ promote = net_benefit & good_employee
317
+ DB[:employees].filter(fire).update(:employed=>false)
318
+ DB[:employees].filter(demote).update(:rank=>:rank-1)
319
+ DB[:employees].filter(promote).update(:rank=>:rank+1)
320
+
321
+ * When Sequel wraps exception in its own classes (to provide database
322
+ independence), it now keeps the wrapped exception available in
323
+ a wrapped_exception accessor. This allows you to more easily
324
+ determine the wrapped exception class, without resorting to parsing
325
+ the exception message.
326
+
327
+ begin
328
+ DB.run('...')
329
+ rescue Sequel::DatabaseError => e
330
+ case e.wrapped_exception
331
+ when Mysql::Error
332
+ ...
333
+ when PGError
334
+ ...
335
+ end
336
+ end
337
+
338
+ * The MySQL adapter now supports a Dataset#split_multiple_result_sets
339
+ method that yields arrays of rows (one per result set), instead of
340
+ rows. This allows you to submit multiple statements at the same
341
+ time (or call a stored procedure that returns multiple result
342
+ sets), and know which rows are related to which result sets.
343
+
344
+ This violates a lot of Sequel's internal assumptions and should be
345
+ used with care. Existing row_procs are modified to work correctly,
346
+ but graphing will not work on these datasets.
347
+
348
+ * The ADO adapter now accepts a :conn_string option and uses that
349
+ as the full ADO connection string. This can be used to connect to
350
+ any datasource ADO supports, such as Microsoft Excel.
351
+
352
+ * The Microsoft SQL Server shared adapter now supports a
353
+ Database#server_version method.
354
+
355
+ * The Microsoft SQL Server shared adapter now supports updating and
356
+ deleting from joined datasets.
357
+
358
+ * The Microsoft SQL Server shared adapter now supports a
359
+ Dataset#output method that uses the OUTPUT clause.
360
+
361
+ * Model#_save now calls either Model#_insert or Model#_update for
362
+ inserting/updating the row in the database. This allows for easier
363
+ overriding when you want to allow creating and updating model
364
+ objects backed by a joined dataset.
365
+
366
+ * Dataset#graph now takes a :from_self_alias option specifying the
367
+ alias to use for the subselect created if the receiver is a joined
368
+ but not yet graphed dataset. It defaults to the first source table
369
+ in the receiver.
370
+
371
+ Other Improvements
372
+ ------------------
373
+
374
+ * Typecasting model attributes is now done before checking existing
375
+ values, instead of after. Before, the code for the model attribute
376
+ setters would compare the given value to the existing entry. If it
377
+ didn't match, the value was typecasted and then assigned. That led
378
+ to the following situation:
379
+
380
+ a = Album[1]
381
+ a.num_tracks # => 10
382
+ params # => {'num_tracks'=>'10'}
383
+ a.set(params)
384
+ a.changed_columns # => [:num_tracks]
385
+
386
+ The new behavior typecasts the value first, and only sets it and
387
+ records the column as changed if it doesn't match the typecasted
388
+ value.
389
+
390
+ * Model#modified? is now always true if the record is new. modified?
391
+ indicates the instance's status relative to the database, and since
392
+ a new object is not yet in the database, and saving the object
393
+ would add it, the object is considered modified. A consequence of
394
+ this is that Model#save_changes now always saves if the object is
395
+ new.
396
+
397
+ If you want to check if there were changes to columns since the
398
+ object was first initialized, you should use
399
+ !changed_columns.empty?, which was the historical way to handle
400
+ the situation.
401
+
402
+ * The DataObjects (do) adpater now supports DataObjects 0.10.
403
+
404
+ * Dataset#select_more and Dataset#order_more no longer affect the
405
+ receiver. They are supposed to just return a modified copy of the
406
+ receiver instead of modifying the receiver itself. For a few
407
+ versions they have been broken in that they modified the receiver
408
+ in addition to returning a modified copy.
409
+
410
+ * Performance was increased for execution of prepared statements
411
+ with multiple bound variables on MySQL.
412
+
413
+ * On MySQL, database errors raised when preparing statements or
414
+ setting bound variable values are now caught and raised as
415
+ Sequel::DatabaseErrors.
416
+
417
+ * On MySQL, more types of disconnection errors are detected.
418
+
419
+ * When altering columns in MySQL, options such as :unsigned,
420
+ :elements, and :size that are given in the call are now respected.
421
+
422
+ * MySQL enum defaults are now handled correctly in the schema dumper.
423
+
424
+ * The schema dumper no longer attempts to use unparseable defaults
425
+ as literals on MySQL, since MySQL does not provide defaults as
426
+ valid literals.
427
+
428
+ * The emulated offset support in the shared Microsoft SQL Server
429
+ adapter now works better with model classes (or any datasets with
430
+ row_procs).
431
+
432
+ * Microsoft SQL Server now supports using the WITH clause in delete,
433
+ update, and insert calls.
434
+
435
+ * Parsed indexes when connecting to Microsoft SQL Server via JDBC no
436
+ longer include primary key indexes.
437
+
438
+ * Dataset#insert_select now returns nil if disable_insert_returning
439
+ is used in the shared PostgreSQL adapter. This makes it work as
440
+ expected with model object creation.
441
+
442
+ * Calling Model.set_primary_key with an array of symbols to set
443
+ a composite primary key is now supported. You can also provide
444
+ multiple symbol arguments to do the same thing. Before, specifying
445
+ an array of symbols broke the Model.[] optimization.
446
+
447
+ * Literalization of timezones in timestamps now works correctly on
448
+ Oracle.
449
+
450
+ * __FILE__ and __LINE__ are now used everywhere that eval is called
451
+ with a string, which makes for better backtraces.
452
+
453
+ * The native MySQL adapter now correctly handles returning before
454
+ yielding all result sets. Previously, this caused a commands out
455
+ of sync error.
456
+
457
+ * Table names in common table expressions are now quoted.
458
+
459
+ * The Oracle adapter's Dataset#except now accepts a hash, giving it
460
+ the same API as the default Dataset#except.
461
+
462
+ * When connecting to Microsoft SQL Server via ADO, allow
463
+ Dataset#insert to take multiple arguments.
464
+
465
+ * Fractional timestamps are no longer used on ODBC.
466
+
467
+ * Schema parsing now works on MSSQL when the database is set to not
468
+ quote identifiers.
469
+
470
+ * Timezone offsets are no longer used on Microsoft SQL Server, since
471
+ they only work for the datetimeoffset type.
472
+
473
+ * Only 3 fractional digits in timestamps are used in Microsoft SQL
474
+ Server, since an error is raised if the use the datetime type
475
+ with more than that.
476
+
477
+ * The integration test suite now has guards for expected failures
478
+ when run on known databases. Expected failures are marked as
479
+ pending.
480
+
481
+ Backwards Compatibility
482
+ -----------------------
483
+
484
+ * Graphing to an previously joined (but not graphed) dataset now
485
+ causes the receiver to be wrapped in a subselect, so if you
486
+ graph a dataset to a previously joined dataset, and then filter
487
+ the dataset referring to tables that were in the joined dataset
488
+ (other than the first table), the SQL produced will probably no
489
+ longer be valid. You should either filter the dataset before
490
+ graphing or use the name of the first source of the joined
491
+ dataset (which is what the subselected is aliased to) if filtering
492
+ afterward.
493
+
494
+ In certain cases, this change can cause tables to be aliased
495
+ differently, so if you were graphing previously joined datasets
496
+ and then filtering using the automatically generated aliases, you
497
+ might need to modify your code.
498
+
499
+ * The DataObjects (do) adpater no longer supports DataObjects 0.9.x.
500
+
501
+ * The Dataset#virtual_row_block_call private instance method has
502
+ been removed.
503
+
504
+ * Sequel's timezone support was significantly refactored, so if you
505
+ had any custom modifications to the timezone support, they might
506
+ need to be refactored as well.
507
+
508
+ * The SQL generation code was significantly refactored, so if you
509
+ had any custom modifications in that area, you might need to
510
+ refactor as well.