sequel 2.10.0 → 2.11.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 (78) hide show
  1. data/CHANGELOG +51 -1
  2. data/README.rdoc +2 -2
  3. data/Rakefile +2 -2
  4. data/doc/advanced_associations.rdoc +6 -18
  5. data/doc/release_notes/1.0.txt +38 -0
  6. data/doc/release_notes/1.1.txt +143 -0
  7. data/doc/release_notes/1.3.txt +101 -0
  8. data/doc/release_notes/1.4.0.txt +53 -0
  9. data/doc/release_notes/1.5.0.txt +155 -0
  10. data/doc/release_notes/2.0.0.txt +298 -0
  11. data/doc/release_notes/2.1.0.txt +271 -0
  12. data/doc/release_notes/2.10.0.txt +328 -0
  13. data/doc/release_notes/2.11.0.txt +215 -0
  14. data/doc/release_notes/2.2.0.txt +253 -0
  15. data/doc/release_notes/2.3.0.txt +88 -0
  16. data/doc/release_notes/2.4.0.txt +106 -0
  17. data/doc/release_notes/2.5.0.txt +137 -0
  18. data/doc/release_notes/2.6.0.txt +157 -0
  19. data/doc/release_notes/2.7.0.txt +166 -0
  20. data/doc/release_notes/2.8.0.txt +171 -0
  21. data/doc/release_notes/2.9.0.txt +97 -0
  22. data/lib/sequel_core/adapters/ado.rb +3 -0
  23. data/lib/sequel_core/adapters/db2.rb +0 -11
  24. data/lib/sequel_core/adapters/dbi.rb +0 -11
  25. data/lib/sequel_core/adapters/do.rb +0 -12
  26. data/lib/sequel_core/adapters/firebird.rb +21 -16
  27. data/lib/sequel_core/adapters/informix.rb +1 -11
  28. data/lib/sequel_core/adapters/jdbc.rb +1 -13
  29. data/lib/sequel_core/adapters/jdbc/h2.rb +3 -11
  30. data/lib/sequel_core/adapters/jdbc/mysql.rb +0 -17
  31. data/lib/sequel_core/adapters/jdbc/postgresql.rb +3 -15
  32. data/lib/sequel_core/adapters/mysql.rb +31 -27
  33. data/lib/sequel_core/adapters/odbc.rb +34 -28
  34. data/lib/sequel_core/adapters/openbase.rb +0 -11
  35. data/lib/sequel_core/adapters/oracle.rb +11 -9
  36. data/lib/sequel_core/adapters/postgres.rb +14 -17
  37. data/lib/sequel_core/adapters/shared/mssql.rb +6 -15
  38. data/lib/sequel_core/adapters/shared/mysql.rb +29 -14
  39. data/lib/sequel_core/adapters/shared/oracle.rb +4 -0
  40. data/lib/sequel_core/adapters/shared/postgres.rb +30 -35
  41. data/lib/sequel_core/adapters/shared/progress.rb +4 -0
  42. data/lib/sequel_core/adapters/shared/sqlite.rb +73 -13
  43. data/lib/sequel_core/adapters/sqlite.rb +8 -18
  44. data/lib/sequel_core/adapters/utils/date_format.rb +21 -0
  45. data/lib/sequel_core/{dataset → adapters/utils}/stored_procedures.rb +0 -0
  46. data/lib/sequel_core/{dataset → adapters/utils}/unsupported.rb +0 -0
  47. data/lib/sequel_core/core_ext.rb +1 -1
  48. data/lib/sequel_core/core_sql.rb +9 -4
  49. data/lib/sequel_core/database.rb +63 -62
  50. data/lib/sequel_core/dataset.rb +9 -4
  51. data/lib/sequel_core/dataset/convenience.rb +10 -9
  52. data/lib/sequel_core/dataset/prepared_statements.rb +1 -1
  53. data/lib/sequel_core/dataset/sql.rb +130 -36
  54. data/lib/sequel_core/schema/sql.rb +2 -2
  55. data/lib/sequel_core/sql.rb +44 -51
  56. data/lib/sequel_core/version.rb +1 -1
  57. data/lib/sequel_model/associations.rb +25 -17
  58. data/lib/sequel_model/base.rb +35 -7
  59. data/lib/sequel_model/caching.rb +1 -6
  60. data/lib/sequel_model/record.rb +23 -5
  61. data/lib/sequel_model/validations.rb +20 -5
  62. data/spec/adapters/firebird_spec.rb +6 -1
  63. data/spec/adapters/mysql_spec.rb +12 -0
  64. data/spec/adapters/postgres_spec.rb +2 -2
  65. data/spec/adapters/sqlite_spec.rb +81 -2
  66. data/spec/integration/dataset_test.rb +2 -2
  67. data/spec/integration/type_test.rb +12 -2
  68. data/spec/sequel_core/core_sql_spec.rb +46 -12
  69. data/spec/sequel_core/database_spec.rb +24 -12
  70. data/spec/sequel_core/dataset_spec.rb +82 -32
  71. data/spec/sequel_core/schema_spec.rb +16 -0
  72. data/spec/sequel_model/associations_spec.rb +89 -0
  73. data/spec/sequel_model/base_spec.rb +66 -0
  74. data/spec/sequel_model/eager_loading_spec.rb +32 -0
  75. data/spec/sequel_model/record_spec.rb +9 -9
  76. data/spec/sequel_model/spec_helper.rb +3 -0
  77. data/spec/sequel_model/validations_spec.rb +63 -3
  78. metadata +41 -4
@@ -0,0 +1,155 @@
1
+ You can now graph a dataset and have the result split into component
2
+ tables:
3
+
4
+ DB[:artists].graph(:albums, :artist_id=>:id).first
5
+ # => {:artists=>{:id=>artists.id, :name=>artists.name}, \
6
+ # :albums=>{:id=>albums.id, :name=>albums.name,
7
+ :artist_id=>albums.artist_id}}
8
+
9
+ This aliases columns if necessary so they don't stomp on each other,
10
+ which
11
+ is what usually happens if you just join the tables:
12
+
13
+ DB[:artists].left_outer_join(:albums, :artist_id=>:id).first
14
+ # => {:id=>(albums.id||artists.id),
15
+ :name=>(albums.name||artist.names), \
16
+ :artist_id=>albums.artist_id}
17
+
18
+ Models can use graph as well, in which case the values will be model
19
+ objects:
20
+
21
+ Artist.graph(Album, :artist_id=>:id)
22
+ # => {:artists=>#<Artist...>, :albums=>#<Album...>}
23
+
24
+ Models can now eager load via .eager_graph, which will load all the
25
+ results
26
+ and all associations in a single query. This is necessary if you want
27
+ to
28
+ filter on columns in associated tables. It works exactly the same way
29
+ as
30
+ .eager, and supports cascading of associations as well:
31
+
32
+ # Artist.one_to_many :albums
33
+ # Album.one_to_many :tracks
34
+ # Track.many_to_one :genre
35
+ Artist.eager_graph(:albums=>{:tracks=>:genre}).filter( \
36
+ :tracks_name=>"Firewire").all
37
+
38
+ This will give you all artists have have an album with a track named
39
+ "Firewire", and calling .albums on one of those artists will only return
40
+ albums that have a track named "Firewire", and calling .tracks on one of
41
+ those albums will return only the track(s) named "Firewire".
42
+
43
+ You can use set_graph_aliases to select specific columns:
44
+
45
+ DB[:artists].graph(:albums, :artist_id=>:id).set_graph_aliases( \
46
+ :artist_name=>[:artists, :name], :album_name=>[:albums,
47
+ :name]).first
48
+ # => {:artists=>{:name=>artists.name}, :albums=>{:name=>albums.name}}
49
+
50
+ You can use eager_graph with set_graph_aliases to have eager loading
51
+ with
52
+ control over the SELECT clause.
53
+
54
+ All associations now update their reciprocal associations whenever the
55
+ association methods are used, so you don't need to refresh the
56
+ association or model to have the reciprocal association updated:
57
+
58
+ Album.many_to_one :band
59
+ Band.one_to_many :albums
60
+
61
+ # Note that all of these associations are cached,
62
+ # so after the first access there are no additional
63
+ # database queries to fetch associated records.
64
+
65
+ # many_to_one setter adds to reciprocal association
66
+ band1.albums # => []
67
+ album1.band = band1
68
+ band1.albums # => [album1]
69
+ band2.albums # => []
70
+ album1.band = band2
71
+ band1.albums # => []
72
+ band2.albums # => [album1]
73
+ album1.band = band2
74
+ band2.albums # => [album1]
75
+ album1.band = nil
76
+ band2.albums # => []
77
+
78
+ # one_to_many add_* method sets reciprocal association
79
+ # one_to_many remove_* method removes reciprocal association
80
+ album1.band # => nil
81
+ band1.add_album(album1)
82
+ album1.band # => band1
83
+ band2.add_album(album1)
84
+ album1.band # => band2
85
+ band2.remove_album(album1)
86
+ album1.band # => nil
87
+
88
+ Post.many_to_many :tags
89
+ Tag.many_to_many :posts
90
+
91
+ # many_to_many add_* method adds to reciprocal association
92
+ # many_to_many remove_* method removes from reciprocal association
93
+ post1.tags # => []
94
+ tag1.posts # => []
95
+ tag1.add_post(post1)
96
+ post1.tags # => [tag1]
97
+ tag1.posts # => [post1]
98
+ tag1.remove_post(post1)
99
+ post1.tags # => []
100
+ tag1.posts # => []
101
+ post1.add_tag(tag1)
102
+ post1.tags # => [tag1]
103
+ tag1.posts # => [post1]
104
+ post1.remove_tag(tag1)
105
+ post1.tags # => []
106
+ tag1.posts # => []
107
+
108
+ The MySQL and PostgreSQL adapters now support index types:
109
+
110
+ index :some_column, :type => :hash # or :spatial, :full_text, :rtree,
111
+ etc.
112
+
113
+ Starting in Sequel 1.5.0, some methods are deprecated. These methods
114
+ will be
115
+ removed in Sequel 2.0.0. The deprecation framework is fairly flexible.
116
+ You
117
+ can choose where the messages get sent:
118
+
119
+ Sequel::Deprecation.deprecation_message_stream = STDERR # the default
120
+ Sequel::Deprecation.deprecation_message_stream = \
121
+ File.new('deprecation.txt', 'wb') # A file
122
+ Sequel::Deprecation.deprecation_message_stream = nil # ignore the
123
+ messages
124
+
125
+ You can even have all deprecation messages accompanied by a traceback,
126
+ so you
127
+ can see exactly where in your code you are using a deprecated method:
128
+
129
+ Sequel::Deprecation.print_tracebacks = true
130
+
131
+ All deprecation methods come with an message telling you what
132
+ alternative code
133
+ will work.
134
+
135
+ In addition to deprecating some methods, we removed the ability to have
136
+ arrays returned instead of hashes. The array code still had debugging
137
+ messages
138
+ left it in, and we are not aware of anyone using it. Hashes have been
139
+ returned
140
+ by default since Sequel 0.3.
141
+
142
+ We have also removed the Numeric date/time extensions (e.g. 3.days.ago).
143
+ The
144
+ existing extensions were incomplete, better ones are provided elsewhere,
145
+ and the extensions were not really related to Sequel's purpose.
146
+
147
+ Sequel no longer depends on ParseTree, RubyInline, or ruby2ruby. They
148
+ are
149
+ still required to use the block filters. Sequel's only gem dependency
150
+ is on
151
+ the tiny metaid.
152
+
153
+ Sequel 1.5.0 has fixes for 12 tracker issues, including fixes to the
154
+ Informix,
155
+ MySQL, ODBC, ADO, JDBC, Postgres, and SQLite adapters.
@@ -0,0 +1,298 @@
1
+ Blockless Filter Expressions
2
+ ----------------------------
3
+
4
+ Before 2.0.0, in order to specify complex SQL expressions, you
5
+ either had to resort to writing the SQL yourself in a string or
6
+ using an expression inside a block that was parsed by ParseTree.
7
+ Because ParseTree was required, only ruby 1.8.* was supported, and
8
+ supporting other ruby versions (ruby 1.9, JRuby, Rubinius) would
9
+ never be possible.
10
+
11
+ With 2.0.0, you no longer need to use a block to write complex SQL
12
+ expressions. The basics of the blockless filters are the usual
13
+ arithmetic, inequality, and binary operators:
14
+
15
+ + = addition
16
+ - = subtraction
17
+ * = multiplication
18
+ / = division
19
+ > = greater than
20
+ < = less than
21
+ >= = greater than or equal to
22
+ <= = less than or equal to
23
+ ~ = negation
24
+ & = AND
25
+ | = OR
26
+
27
+ You can use these operators on Symbols, LiteralStrings, and other
28
+ Sequel::SQL::Expressions. Note that there is no equal operator or
29
+ not equal operator, to specify those, you use a Hash.
30
+
31
+ Here are some examples:
32
+
33
+ # Ruby code => SQL WHERE clause
34
+ :active => active
35
+ ~:active => NOT active
36
+ ~~:active => active
37
+ ~~~:active => NOT active
38
+ :is_true[] => is_true()
39
+ ~:is_true[] => NOT is_true()
40
+ :x > 100 => (x > 100)
41
+ :x < 100.01 => (x < 100.01)
42
+ :x <= 0 => (x <= 0)
43
+ :x >= 1 => (x >= 1)
44
+ ~(:x > 100) => (x <= 100)
45
+ {:x => 100} => (x = 100)
46
+ {:x => 'a'} => (x = 'a')
47
+ {:x => nil} => (x IS NULL)
48
+ ~{:x => 100} => (x != 100)
49
+ ~{:x => 'a'} => (x != 'a')
50
+ ~{:x => nil} => (x IS NOT NULL)
51
+ {:x => /a/} => (x ~ 'blah') # Default, MySQL different
52
+ ~{:x => /a/} => (x !~ 'blah') # Default, MySQL different
53
+ :x.like('a') => (x LIKE 'a')
54
+ ~:x.like('a') => (x NOT LIKE 'a')
55
+ :x.like(/a/) => (x ~ 'a') # Default, MySQL different
56
+ ~:x.like('a', /b/) => ((x NOT LIKE 'a') AND (x !~ 'b')) # Default
57
+ ~{:x => 1..5} => ((x < 1) OR (x > 5))
58
+ ~{:x => DB[:items].select(:i)} => (x NOT IN (SELECT i FROM items))
59
+ ~{:x => [1,2,3]} => (x NOT IN (1, 2, 3))
60
+ :x + 1 > 100 => ((x + 1) > 100)
61
+ (:x * :y) < 100.01 => ((x * y) < 100.01)
62
+ (:x - :y/2) >= 100 => ((x - (y / 2)) >= 100)
63
+ (((:x - :y)/(:x + :y))*:z) <= 100 => ((((x - y) / (x + y)) * z) <=
64
+ 100)
65
+ ~((((:x - :y)/(:x + :y))*:z) <= 100) => ((((x - y) / (x + y)) * z) >
66
+ 100)
67
+ :x & :y => (x AND y)
68
+ :x & :y & :z => ((x AND y) AND z)
69
+ :x & {:y => :z} => (x AND (y = z))
70
+ {:y => :z} & :x => ((y = z) AND x)
71
+ {:x => :a} & {:y => :z} => ((x = a) AND (y = z))
72
+ (:x > 200) & (:y < 200) => ((x > 200) AND (y < 200))
73
+ :x | :y => (x OR y)
74
+ :x | :y | :z => ((x OR y) OR z)
75
+ :x | {:y => :z} => (x OR (y = z))
76
+ {:y => :z} | :x => ((y = z) OR x)
77
+ {:x => :a} | {:y => :z} => ((x = a) OR (y = z))
78
+ (:x > 200) | (:y < 200) => ((x > 200) OR (y < 200))
79
+ (:x | :y) & :z => ((x OR y) AND z)
80
+ :x | (:y & :z) => (x OR (y AND z))
81
+ (:x & :w) | (:y & :z) => ((x AND w) OR (y AND z))
82
+ ~((:x | :y) & :z) => ((NOT x AND NOT y) OR NOT z)
83
+ ~((:x & :w) | (:y & :z)) => ((NOT x OR NOT w) AND (NOT y OR NOT z))
84
+ ~((:x > 200) | (:y & :z)) => ((x <= 200) AND (NOT y OR NOT z))
85
+ ~('x'.lit + 1 > 100) => ((x + 1) <= 100)
86
+ 'x'.lit.like(/a/) => (x ~ 'a') # (x ~ \'a\')
87
+
88
+ None of these require blocks, you can use any directly in a call to
89
+ filter:
90
+
91
+ DB[:items].filter((:price * :tax) - :discount > 100)
92
+ # => SELECT * FROM items WHERE (((price * tax) - discount) > 100)
93
+ DB[:items].filter(:active & ~:archived)
94
+ # => SELECT * FROM items WHERE (active AND NOT archived)
95
+
96
+ SQL String Concatenation
97
+ ------------------------
98
+
99
+ Sequel now has support for expressing SQL string concatenation in an
100
+ easy way:
101
+
102
+ [:name, :title].sql_string_join(" - ")
103
+ # SQL: name || ' - ' || title
104
+
105
+ You can use this in selecting columns, creating filters, ordering
106
+ datasets, and possibly elsewhere.
107
+
108
+ Schema Reflection Support/Typecasting on Assignment
109
+ ---------------------------------------------------
110
+
111
+ When used with PostgreSQL, MySQL, or SQLite, Sequel now has the
112
+ ability to get information from the database's schema in regards
113
+ to column types:
114
+
115
+ DB.schema(:artist)
116
+ => [[:id, {:type=>:integer, :db_type=>"integer", :max_chars=>0
117
+ :numeric_precision=>32, :allow_null=>false,
118
+ :default=>"nextval('artist_id_seq'::regclass)"}], [:name,
119
+ {:type=>:string, :default=>nil, :db_type=>"text",
120
+ :numeric_precision=>0, :allow_null=>true, :max_chars=>0}]]
121
+
122
+ Models now use this information to typecast values on attribute
123
+ assignment. For example, if you have an integer column named number
124
+ and a text (e.g. varchar) column named title:
125
+
126
+ 1.5.1:
127
+ model.number = '1'
128
+ model.number # => '1'
129
+ model.title = 1
130
+ model.title # => 1
131
+ 2.0.0:
132
+ model.number = '1'
133
+ model.number # => 1
134
+ model.title = 1
135
+ model.title # => '1'
136
+
137
+ Typecasting can be turned off on a global, per class, and per object
138
+ basis:
139
+
140
+ Sequel::Model.typecast_on_assignment = false # Global
141
+ Album.typecast_on_assignment = false # Per Class
142
+ Album.new.typecast_on_assignment = false # Per Object
143
+
144
+ Typecasting is somewhat strict, it does not allow obviously bogus
145
+ data to be used:
146
+
147
+ model.number = 'a' # Raises error
148
+
149
+ This is in contrast to how some other ORMs handle the situation:
150
+
151
+ model.number = 'a'
152
+ model.number # => 0
153
+
154
+ If Sequel is being used with a web framework and you want to display
155
+ friendly error messages to the user, you should probably turn
156
+ typecasting off and set up the necessary validations in your models.
157
+
158
+ Model Association Improvements
159
+ ------------------------------
160
+
161
+ Associations can now be eagerly loaded even if they have a block,
162
+ though the block should not rely on being evaluated in the context
163
+ of an instance. This allows you filter on associations when eagerly
164
+ loading:
165
+
166
+ Artist.one_to_many :albums_with_10_tracks, :class=>:Album do |ds|
167
+ ds.filter(:num_tracks => 10)
168
+ end
169
+ Artist.filter(:name.like('A%)).eager(:albums_with_10_tracks).all
170
+ # SELECT * FROM artists WHERE (name LIKE 'A%')
171
+ # SELECT albums.* FROM albums WHERE ((artist_id IN (...)) AND
172
+ # (num_tracks = 10))
173
+
174
+ Associations now have a remove_all_ method for removing all
175
+ associated objects in a single query:
176
+
177
+ Artist.many_to_many :albums
178
+ Artist[1].remove_all_albums
179
+ # DELETE FROM albums_artists WHERE artist_id = 1
180
+
181
+ Artist.one_to_many :albums
182
+ Artist[1].remove_all_albums
183
+ # UPDATE albums SET artist_id = NULL WHERE artist_id = 1
184
+
185
+ All associations can specify a :select option to change which columns
186
+ are selected. Previously only many to many associations suppported
187
+ this.
188
+
189
+ The SQL used when eagerly loading through eager_graph can be
190
+ modified via the :graph_join_type, :graph_conditions, and
191
+ :graph_join_conditions options.
192
+
193
+ :graph_join_type changes the join type from the default of
194
+ :left_outer. This can be useful if you do not want any
195
+ albums that don't have an artist in the result set:
196
+
197
+ Album.many_to_one :artist, :graph_join_type=>:inner
198
+ Album.eager_graph(:artist).sql
199
+ # SELECT ... FROM albums INNER JOIN artists ...
200
+
201
+ :graph_conditions adds conditions on the join to the table you are
202
+ joining, the eager_graph equivalent of an association block argument
203
+ in eager. It takes either a hash or an array where all elements
204
+ are arrays of length two, similar to join_table, where key symbols
205
+ specify columns in the joined table and value symbols specify
206
+ columns in the last joined or primary table:
207
+
208
+ Album.many_to_one :artist, :graph_conditions=>{:active=>true}
209
+ Album.eager_graph(:artist).sql
210
+ # SELECT ... FROM albums LEFT OUTER JOIN artists ON ((artists.id =
211
+ # albums.artist_id) AND (artists.active = 't'))
212
+
213
+ :graph_join_table_conditions exists for many to many associations only,
214
+ and operates the same as :graph_conditions, except it specifies a
215
+ condition on the many to many join table instead of the associated
216
+ model's table. This is necessary if the join table is also model
217
+ table with other columns on which you may want to filter:
218
+
219
+ Album.many_to_many :genres, :join_table=>:ag, \
220
+ :graph_join_table_conditions=>{:active=>true}
221
+ Album.eager_graph(:genres).sql
222
+ # SELECT ... FROM albums LEFT OUTER JOIN ag ON ((ag.album_id =
223
+ albums.id) AND (ag.active = 't')) LEFT OUTER JOIN genres ON
224
+ (genres.id = ag.genre_id)
225
+
226
+ Other Small Improvements
227
+ ------------------------
228
+
229
+ * Dataset#invert returns a dataset that matches all records not
230
+ matching the current filter.
231
+ * Dataset#unfiltered returns a dataset that has any filters removed.
232
+ * Dataset#last_page? and Dataset#first_page? for paginated datasets.
233
+ * The sequel command line tool now support an -E or --echo argument
234
+ that logs all SQL to the standard output. It also can take a path
235
+ to a yaml file with database connection options, in addition to a
236
+ database URL.
237
+ * Databases can now have multiple SQL loggers, so you can log to the
238
+ standard output as well as a file.
239
+ * SQL identifiers (columns and tables) are now quoted by default (you
240
+ can turn this off via Sequel.quote_identifiers = false if need be).
241
+ * Sequel.connect now takes an optional block that will disconnect the
242
+ database when the block finishes.
243
+ * AlterTableGenerator now has add_primary_key and add_foreign_key
244
+ methods.
245
+ * Running the specs without ParseTree installed skips the specs that
246
+ require ParseTree.
247
+ * You can use an array of arrays instead of a hash when specifying
248
+ conditions, which may be necessary in certain situations where
249
+ you would be using the same hash key more than once.
250
+ * Almost all documentation for Sequel was updated for 2.0.0, so if you
251
+ found Sequel documentation lacking before, check out the new RDoc
252
+ pages.
253
+ * There have been many minor refactoring improvements, the code
254
+ should now be easier to read and follow.
255
+ * Sequel now has no external dependencies.
256
+ * Sequel::Models now have before_validation and after_validation
257
+ hooks.
258
+ * Sequel::Model hooks that return false cause the methods that call
259
+ them (such as save) to return false.
260
+ * Sequel::Models can now load their schema on first instantiation,
261
+ instead of when they are created, via
262
+ Sequel::Model.lazy_load_schema=. This is helpful for certain
263
+ web frameworks that reload all models on every request.
264
+ * Hook methods that use blocks can now include an optional tag,
265
+ which allows them to work well with web frameworks that load source
266
+ files every time they are modified.
267
+
268
+ The PostgreSQL adapter has been rewritten and now supports ruby-pg.
269
+ There have also been improvements in the following adapters: DBI,
270
+ MySQL, SQLite, Oracle, and MSSQL.
271
+
272
+ All of the methods that have been deprecated in 1.5.0 have now been
273
+ removed. If you are want to upgrade to Sequel 2.0.0 from version 1.4.0
274
+ or previous, upgrade to 1.5.1 first, fix all of the deprecation
275
+ warnings that show up, and then upgrade to 2.0.0.
276
+
277
+ There were some backwards incompatible changes made in 2.0.0 beyond the
278
+ removal of deprecated methods. These are:
279
+
280
+ * Inflector is no longer used, the inflection methods were moved
281
+ directly into String (where they belong because inflections only
282
+ make sense for strings). So to override singularization
283
+ or pluralization rules, use String.inflections instead of
284
+ Inflector.inflections.
285
+ * MySQL tinyints are now returned as boolean values instead of
286
+ integers. MySQL doesn't have a boolean type, and usually it
287
+ is recommended to use tinyint for a boolean column.
288
+ * You can no longer pass an array to Dataset#order or Dataset#select,
289
+ you need to pass each argument separately (the * operator is your
290
+ friend).
291
+ * You must use '?' instead of '(?)' when interpolating an array
292
+ argument into a string (e.g. filter('x IN ?', [1,2,3]))
293
+ * You must pass an explicit table alias argument to join_table and
294
+ related methods, you can no longer include the table alias
295
+ inside the table argument.
296
+ * sqlite:// URLs now operate the same as file:// URLs (2 slashes
297
+ for a relative path, 3 for an absolute path).
298
+