colincasey-sequel 2.10.0 → 2.10.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +7 -1
- data/doc/advanced_associations.rdoc +614 -0
- data/doc/cheat_sheet.rdoc +223 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/schema.rdoc +29 -0
- data/doc/sharding.rdoc +113 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel_core/adapters/ado.rb +89 -0
- data/lib/sequel_core/adapters/db2.rb +143 -0
- data/lib/sequel_core/adapters/dbi.rb +112 -0
- data/lib/sequel_core/adapters/do/mysql.rb +38 -0
- data/lib/sequel_core/adapters/do/postgres.rb +92 -0
- data/lib/sequel_core/adapters/do/sqlite.rb +31 -0
- data/lib/sequel_core/adapters/do.rb +205 -0
- data/lib/sequel_core/adapters/firebird.rb +298 -0
- data/lib/sequel_core/adapters/informix.rb +85 -0
- data/lib/sequel_core/adapters/jdbc/h2.rb +69 -0
- data/lib/sequel_core/adapters/jdbc/mysql.rb +66 -0
- data/lib/sequel_core/adapters/jdbc/oracle.rb +23 -0
- data/lib/sequel_core/adapters/jdbc/postgresql.rb +113 -0
- data/lib/sequel_core/adapters/jdbc/sqlite.rb +43 -0
- data/lib/sequel_core/adapters/jdbc.rb +491 -0
- data/lib/sequel_core/adapters/mysql.rb +369 -0
- data/lib/sequel_core/adapters/odbc.rb +174 -0
- data/lib/sequel_core/adapters/openbase.rb +68 -0
- data/lib/sequel_core/adapters/oracle.rb +107 -0
- data/lib/sequel_core/adapters/postgres.rb +456 -0
- data/lib/sequel_core/adapters/shared/ms_access.rb +110 -0
- data/lib/sequel_core/adapters/shared/mssql.rb +102 -0
- data/lib/sequel_core/adapters/shared/mysql.rb +325 -0
- data/lib/sequel_core/adapters/shared/oracle.rb +61 -0
- data/lib/sequel_core/adapters/shared/postgres.rb +715 -0
- data/lib/sequel_core/adapters/shared/progress.rb +31 -0
- data/lib/sequel_core/adapters/shared/sqlite.rb +265 -0
- data/lib/sequel_core/adapters/sqlite.rb +248 -0
- data/lib/sequel_core/connection_pool.rb +258 -0
- data/lib/sequel_core/core_ext.rb +217 -0
- data/lib/sequel_core/core_sql.rb +202 -0
- data/lib/sequel_core/database/schema.rb +164 -0
- data/lib/sequel_core/database.rb +691 -0
- data/lib/sequel_core/dataset/callback.rb +13 -0
- data/lib/sequel_core/dataset/convenience.rb +237 -0
- data/lib/sequel_core/dataset/pagination.rb +96 -0
- data/lib/sequel_core/dataset/prepared_statements.rb +220 -0
- data/lib/sequel_core/dataset/query.rb +41 -0
- data/lib/sequel_core/dataset/schema.rb +15 -0
- data/lib/sequel_core/dataset/sql.rb +1010 -0
- data/lib/sequel_core/dataset/stored_procedures.rb +75 -0
- data/lib/sequel_core/dataset/unsupported.rb +43 -0
- data/lib/sequel_core/dataset.rb +511 -0
- data/lib/sequel_core/deprecated.rb +26 -0
- data/lib/sequel_core/exceptions.rb +44 -0
- data/lib/sequel_core/migration.rb +212 -0
- data/lib/sequel_core/object_graph.rb +230 -0
- data/lib/sequel_core/pretty_table.rb +71 -0
- data/lib/sequel_core/schema/generator.rb +320 -0
- data/lib/sequel_core/schema/sql.rb +325 -0
- data/lib/sequel_core/schema.rb +2 -0
- data/lib/sequel_core/sql.rb +887 -0
- data/lib/sequel_core/version.rb +11 -0
- data/lib/sequel_core.rb +172 -0
- data/lib/sequel_model/association_reflection.rb +267 -0
- data/lib/sequel_model/associations.rb +499 -0
- data/lib/sequel_model/base.rb +523 -0
- data/lib/sequel_model/caching.rb +82 -0
- data/lib/sequel_model/dataset_methods.rb +26 -0
- data/lib/sequel_model/eager_loading.rb +370 -0
- data/lib/sequel_model/exceptions.rb +7 -0
- data/lib/sequel_model/hooks.rb +101 -0
- data/lib/sequel_model/inflector.rb +281 -0
- data/lib/sequel_model/plugins.rb +62 -0
- data/lib/sequel_model/record.rb +568 -0
- data/lib/sequel_model/schema.rb +49 -0
- data/lib/sequel_model/validations.rb +429 -0
- data/lib/sequel_model.rb +91 -0
- data/spec/adapters/ado_spec.rb +46 -0
- data/spec/adapters/firebird_spec.rb +376 -0
- data/spec/adapters/informix_spec.rb +96 -0
- data/spec/adapters/mysql_spec.rb +881 -0
- data/spec/adapters/oracle_spec.rb +244 -0
- data/spec/adapters/postgres_spec.rb +687 -0
- data/spec/adapters/spec_helper.rb +10 -0
- data/spec/adapters/sqlite_spec.rb +555 -0
- data/spec/integration/dataset_test.rb +134 -0
- data/spec/integration/eager_loader_test.rb +696 -0
- data/spec/integration/prepared_statement_test.rb +130 -0
- data/spec/integration/schema_test.rb +180 -0
- data/spec/integration/spec_helper.rb +58 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/rcov.opts +6 -0
- data/spec/sequel_core/connection_pool_spec.rb +526 -0
- data/spec/sequel_core/core_ext_spec.rb +156 -0
- data/spec/sequel_core/core_sql_spec.rb +522 -0
- data/spec/sequel_core/database_spec.rb +1188 -0
- data/spec/sequel_core/dataset_spec.rb +3481 -0
- data/spec/sequel_core/expression_filters_spec.rb +363 -0
- data/spec/sequel_core/migration_spec.rb +261 -0
- data/spec/sequel_core/object_graph_spec.rb +272 -0
- data/spec/sequel_core/pretty_table_spec.rb +58 -0
- data/spec/sequel_core/schema_generator_spec.rb +167 -0
- data/spec/sequel_core/schema_spec.rb +780 -0
- data/spec/sequel_core/spec_helper.rb +55 -0
- data/spec/sequel_core/version_spec.rb +7 -0
- data/spec/sequel_model/association_reflection_spec.rb +93 -0
- data/spec/sequel_model/associations_spec.rb +1767 -0
- data/spec/sequel_model/base_spec.rb +419 -0
- data/spec/sequel_model/caching_spec.rb +215 -0
- data/spec/sequel_model/dataset_methods_spec.rb +78 -0
- data/spec/sequel_model/eager_loading_spec.rb +1165 -0
- data/spec/sequel_model/hooks_spec.rb +485 -0
- data/spec/sequel_model/inflector_spec.rb +119 -0
- data/spec/sequel_model/model_spec.rb +588 -0
- data/spec/sequel_model/plugins_spec.rb +80 -0
- data/spec/sequel_model/record_spec.rb +1184 -0
- data/spec/sequel_model/schema_spec.rb +90 -0
- data/spec/sequel_model/spec_helper.rb +78 -0
- data/spec/sequel_model/validations_spec.rb +1067 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +177 -3
@@ -0,0 +1,253 @@
|
|
1
|
+
The Most Powerful and Flexible Associations of Any Ruby ORM
|
2
|
+
-----------------------------------------------------------
|
3
|
+
|
4
|
+
Sequel can now support any association type supported by
|
5
|
+
ActiveRecord, and many association types ActiveRecord doesn't
|
6
|
+
support.
|
7
|
+
|
8
|
+
Association callbacks (:before_add, :after_add, :before_remove,
|
9
|
+
:after_remove) have been added, and work for all association
|
10
|
+
types. Each of the callback options can be a Symbol specifying an
|
11
|
+
instance method that takes one argument (the associated object), or a
|
12
|
+
Proc that takes two arguments (the current object and the associated
|
13
|
+
object), or an array of Symbols and Procs. Additionally, an
|
14
|
+
:after_load callback is available, which is running after loading the
|
15
|
+
associated record(s) from the database.
|
16
|
+
|
17
|
+
Association extensions are now supported:
|
18
|
+
|
19
|
+
class FindOrCreate
|
20
|
+
def find_or_create(vals)
|
21
|
+
first(vals) || create(vals)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class Author < Sequel::Model
|
25
|
+
one_to_many :authorships, :extend=>FindOrCreate
|
26
|
+
end
|
27
|
+
Author.first.authorships_dataset.find_or_create(:name=>'Bob')
|
28
|
+
|
29
|
+
Sequel has been able to support most has_many :through style
|
30
|
+
associations since 1.3, via many_to_many (since it doesn't break on
|
31
|
+
join tables that are also model tables, unlike ActiveRecord's
|
32
|
+
has_and_belongs_to_many). Now it can also support has_many :through
|
33
|
+
style associations where it goes through a has_many association.
|
34
|
+
|
35
|
+
Sequel can now support polymorphic associations. Polymorphic
|
36
|
+
associations are really a design flaw, so Sequel doesn't support them
|
37
|
+
directly, but the tools that Sequel gives you make them pretty easy
|
38
|
+
to implement.
|
39
|
+
|
40
|
+
Sequel can also support associations that ActiveRecord does not. For
|
41
|
+
example, a belongs_to association where the column referenced in the
|
42
|
+
associated table is not the primary key, an association that depends
|
43
|
+
on multiple columns in each table, or even situations where the
|
44
|
+
association has a column in the primary table that can be referenced
|
45
|
+
by any of multiple columns in a second table that has a has_one style
|
46
|
+
association with the table you want to associate with.
|
47
|
+
|
48
|
+
Some of those associations can be supported for a single object using
|
49
|
+
custom SQL in ActiveRecord, but none are supported when eager
|
50
|
+
loading or allow further filtering.
|
51
|
+
|
52
|
+
Not only can all of these cases be supported with Sequel::Model, all
|
53
|
+
can be supported with eager loading, and can allow for further
|
54
|
+
filtering. See
|
55
|
+
http://sequel.rubyforge.org/files/sequel/doc/advanced_associations_rdoc.html
|
56
|
+
for details and example code for all association types covered above.
|
57
|
+
|
58
|
+
There have also been many additional options added for controlling
|
59
|
+
eager loading via eager_graph. Every part of the SQL JOINs can now
|
60
|
+
be controlled via one of the options, so you can use JOIN USING,
|
61
|
+
NATURAL JOIN, or arbitrary JOIN ON conditions.
|
62
|
+
|
63
|
+
Finally, just to show off the power that Sequel gives you when eager
|
64
|
+
loading, here is example code that will eagerly load all descendants
|
65
|
+
and ancestors in a tree structure, without knowing the depth of the
|
66
|
+
tree:
|
67
|
+
|
68
|
+
class Node < Sequel::Model
|
69
|
+
set_schema do
|
70
|
+
primary_key :id
|
71
|
+
foreign_key :parent_id, :nodes
|
72
|
+
end
|
73
|
+
create_table
|
74
|
+
|
75
|
+
many_to_one :parent
|
76
|
+
one_to_many :children, :key=>:parent_id
|
77
|
+
|
78
|
+
# Only useful when eager loading
|
79
|
+
many_to_one :ancestors, :eager_loader=>(proc do |key_hash, nodes,
|
80
|
+
associations|
|
81
|
+
# Handle cases where the root node has the same parent_id as
|
82
|
+
primary_key
|
83
|
+
# and also when it is NULL
|
84
|
+
non_root_nodes = nodes.reject do |n|
|
85
|
+
if [nil, n.pk].include?(n.parent_id)
|
86
|
+
# Make sure root nodes have their parent association set to
|
87
|
+
nil
|
88
|
+
n.associations[:parent] = nil
|
89
|
+
true
|
90
|
+
else
|
91
|
+
false
|
92
|
+
end
|
93
|
+
end
|
94
|
+
unless non_root_nodes.empty?
|
95
|
+
id_map = {}
|
96
|
+
# Create an map of parent_ids to nodes that have that parent id
|
97
|
+
non_root_nodes.each{|n| (id_map[n.parent_id] ||= []) << n}
|
98
|
+
# Doesn't cause an infinte loop, because when only the root node
|
99
|
+
# is left, this is not called.
|
100
|
+
Node.filter(Node.primary_key=>id_map.keys).eager(:ancestors).all
|
101
|
+
do |node|
|
102
|
+
# Populate the parent association for each node
|
103
|
+
id_map[node.pk].each{|n| n.associations[:parent] = node}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end)
|
107
|
+
many_to_one :descendants, :eager_loader=>(proc do |key_hash, nodes,
|
108
|
+
associations|
|
109
|
+
id_map = {}
|
110
|
+
nodes.each do |n|
|
111
|
+
# Initialize an empty array of child associations for each
|
112
|
+
parent node
|
113
|
+
n.associations[:children] = []
|
114
|
+
# Populate identity map of nodes
|
115
|
+
id_map[n.pk] = n
|
116
|
+
end
|
117
|
+
# Doesn't cause an infinite loop, because the :eager_loader is not
|
118
|
+
called
|
119
|
+
# if no records are returned. Exclude id = parent_id to avoid
|
120
|
+
infinite loop
|
121
|
+
# if the root note is one of the returned records and it has
|
122
|
+
parent_id = id
|
123
|
+
# instead of parent_id = NULL.
|
124
|
+
Node.filter(:parent_id=>id_map.keys).exclude(:id=>:parent_id).eager(:descendants).all
|
125
|
+
do |node|
|
126
|
+
# Get the parent from the identity map
|
127
|
+
parent = id_map[node.parent_id]
|
128
|
+
# Set the child's parent association to the parent
|
129
|
+
node.associations[:parent] = parent
|
130
|
+
# Add the child association to the array of children in the
|
131
|
+
parent
|
132
|
+
parent.associations[:children] << node
|
133
|
+
end
|
134
|
+
end)
|
135
|
+
end
|
136
|
+
|
137
|
+
nodes = Node.filter(:id < 10).eager(:ancestors, :descendants).all
|
138
|
+
|
139
|
+
New Adapter Features
|
140
|
+
--------------------
|
141
|
+
|
142
|
+
* PostgreSQL bytea fields are now fully supported.
|
143
|
+
|
144
|
+
* The PostgreSQL adapter now uses the safer connection-specific
|
145
|
+
string escaping if you are using ruby-pg.
|
146
|
+
|
147
|
+
* The SQLite adapter supports drop_column and add_index.
|
148
|
+
|
149
|
+
* You can now use URL parameters in the connection string, enabling
|
150
|
+
you to connect to PostgreSQL via a socket using
|
151
|
+
postgres://user:password@blah/database?host=/tmp
|
152
|
+
|
153
|
+
Other New Features
|
154
|
+
------------------
|
155
|
+
|
156
|
+
* Dataset#graph now takes a block which it passes to join_table.
|
157
|
+
|
158
|
+
* Symbol#identifier has been added, which can be used if another
|
159
|
+
library defines the same operator(s) on Symbol that Sequel defines.
|
160
|
+
|
161
|
+
* Filter blocks now yield a VirtualRow instance, which can yield
|
162
|
+
Identifiers, QualifiedIdentifiers, or Functions. Like
|
163
|
+
Symbol#identifier, this is useful if another library defines the
|
164
|
+
same operator(s) on Symbol that Sequel defines.
|
165
|
+
|
166
|
+
* You can now call Model.to_hash to get an identity map for all
|
167
|
+
rows (before this required Model.dataset.to_hash).
|
168
|
+
|
169
|
+
* A model that can get it's column information from the schema will
|
170
|
+
set it in the dataset, potentially saving many queries.
|
171
|
+
|
172
|
+
* Model.validates_presence_of now works correctly for boolean
|
173
|
+
columns.
|
174
|
+
|
175
|
+
Notable Bug Fixes
|
176
|
+
-----------------
|
177
|
+
|
178
|
+
* Caching now works with Model subclasses.
|
179
|
+
|
180
|
+
* Model validation methods now work with source reloading.
|
181
|
+
|
182
|
+
* The PostgreSQL adapter no longer raises an Error if you try to
|
183
|
+
insert a record with the primary key already specified.
|
184
|
+
|
185
|
+
* Sequel no longer messes with the native MySQL adapter, so you can
|
186
|
+
use Sequel and ActiveRecord with MySQL in the same process.
|
187
|
+
|
188
|
+
* Dataset#count now works correctly for limited dataset.
|
189
|
+
|
190
|
+
* PostgreSQL Database#transaction method yields a connection, similar
|
191
|
+
to the other adapters.
|
192
|
+
|
193
|
+
* Using a hash argument in #distinct, #order, or #group is treated
|
194
|
+
as an expression instead of a column alias.
|
195
|
+
|
196
|
+
* Cloned datasets no longer ignore the existing columns unless it is
|
197
|
+
necessary.
|
198
|
+
|
199
|
+
* The :quote_identifiers and :single_threaded Database options now
|
200
|
+
work correctly.
|
201
|
+
|
202
|
+
Backwards Incompatible Changes
|
203
|
+
------------------------------
|
204
|
+
|
205
|
+
* ParseTree support, deprecated in 2.1.0, has been removed in 2.2.0.
|
206
|
+
You should use the expression filter syntax instead, perferably
|
207
|
+
without the block (though it can be used inside a block as well).
|
208
|
+
This usually involves the following types of changes:
|
209
|
+
|
210
|
+
filter{:x == :y} => filter(:x => :y)
|
211
|
+
filter{:x << :y} => filter(:x => :y)
|
212
|
+
filter{:x && :y} => filter(:x & :y) # Don't forget about change
|
213
|
+
filter{:x || :y} => filter(:x | :y) # in operator precedence
|
214
|
+
filter{:x.like?('%blah%')} => filter(:x.like('%blah%'))
|
215
|
+
filter do => filter((:x > 1) & (:y < 2))
|
216
|
+
:x > 1
|
217
|
+
:y < 2
|
218
|
+
end
|
219
|
+
|
220
|
+
* Attempts to save an invalid Model instance will raise an error by
|
221
|
+
default. To revert to returning a nil value, use:
|
222
|
+
|
223
|
+
Sequel::Model.raise_on_save_failure = false # Global
|
224
|
+
Album.raise_on_save_failure = false # Class
|
225
|
+
album = Album.new
|
226
|
+
album.raise_on_save_failure = false # Instance
|
227
|
+
|
228
|
+
Note that before, save would return false where now it returns nil
|
229
|
+
if you disable raising on save failure.
|
230
|
+
|
231
|
+
* Dataset#update no longer takes a block, as it's use of the block
|
232
|
+
depended on ParseTree. With the introduction of the expression
|
233
|
+
syntax in 2.0.0, it's no longer necessary. You should use a hash
|
234
|
+
with an expression as the value instead:
|
235
|
+
|
236
|
+
DB[:table].update(:column=>:column + 1)
|
237
|
+
|
238
|
+
* validates_presence of now considers false as present instead of
|
239
|
+
absent. This is so it works with boolean columns.
|
240
|
+
|
241
|
+
* Dataset#graph ignores any previously selected columns when it is
|
242
|
+
called for the first time.
|
243
|
+
|
244
|
+
* Dataset#columns ignores any filtering, ordering, or distinct
|
245
|
+
clauses. This shouldn't cause issues unless you were using
|
246
|
+
SQL functions with side effects and expecting them to be called
|
247
|
+
when columns was called (unlikely at best).
|
248
|
+
|
249
|
+
One significant point of note is that the 2.2.0 release will be the
|
250
|
+
last release with both a sequel_core and sequel gem. Starting
|
251
|
+
with 2.3.0 they will be combined into one sequel gem. You will still
|
252
|
+
be able to get just the sequel_core part by requiring 'sequel_core',
|
253
|
+
but they will be packaged together.
|
@@ -0,0 +1,88 @@
|
|
1
|
+
JRuby and Ruby 1.9 Officially Supported
|
2
|
+
---------------------------------------
|
3
|
+
|
4
|
+
Sequel now officially supports JRuby 1.1.3 and Ruby 1.9 (svn revision
|
5
|
+
18194 at least). Using JRuby with the JDBC adapter, PostgreSQL,
|
6
|
+
MySQL, and SQLite now enjoy almost full support, though not
|
7
|
+
everything works the same as using the native adapter. Depending on
|
8
|
+
what you are doing, it may make sense to use postgres-pr on JRuby
|
9
|
+
instead of PostgreSQL-JDBC.
|
10
|
+
|
11
|
+
To use the new JDBC support, the database connection string you give
|
12
|
+
Sequel is now passed directly to JDBC, here are a few examples:
|
13
|
+
|
14
|
+
Sequel.connect('jdbc:postgresql://host/database?user=*&password=*')
|
15
|
+
Sequel.connect('jdbc:mysql://host/database?user=*&password=*')
|
16
|
+
Sequel.connect('jdbc:sqlite::memory:')
|
17
|
+
Sequel.connect('jdbc:sqlite:relative/path.db')
|
18
|
+
Sequel.connect('jdbc:sqlite:/absolute/path.db')
|
19
|
+
|
20
|
+
Single Gem
|
21
|
+
----------
|
22
|
+
|
23
|
+
Sequel is now distributed as a single gem named sequel, by combining
|
24
|
+
the previous sequel_core and sequel gems. You can still just
|
25
|
+
"require 'sequel_core'" if you don't want the model functionality.
|
26
|
+
|
27
|
+
Database Adapter Improvements
|
28
|
+
-----------------------------
|
29
|
+
|
30
|
+
* Dataset#empty? now works using the MySQL adapter.
|
31
|
+
|
32
|
+
* The Oracle adapter now works with a nonstandard database port.
|
33
|
+
|
34
|
+
* The JDBC adapter should load JDBC drivers automatically for
|
35
|
+
PostgreSQL, MySQL, SQLite, Oracle, and MSSQL. For PostgreSQL,
|
36
|
+
MySQL, and SQLite, the jdbc-* gem can be used, for the others, you
|
37
|
+
must have the correct .jar in your CLASSPATH.
|
38
|
+
|
39
|
+
* The PostgreSQL adapter no longer raises an error when inserting
|
40
|
+
records into a table without a primary key.
|
41
|
+
|
42
|
+
* Database#disconnect now works for the ADO adapter.
|
43
|
+
|
44
|
+
* The ADO adapter no longer raises an error if the dataset contains
|
45
|
+
no records.
|
46
|
+
|
47
|
+
* The ODBC adapter no longer errors when converting ::ODBC::Time
|
48
|
+
values.
|
49
|
+
|
50
|
+
Backwards Incompatible Changes
|
51
|
+
------------------------------
|
52
|
+
|
53
|
+
* Sequel::Worker has been removed. There are no known users, and the
|
54
|
+
specs caused problems on JRuby.
|
55
|
+
|
56
|
+
* Assigning an empty string to a non-string, non-blob model attribute
|
57
|
+
converts it to nil by default. You can use
|
58
|
+
"Model.typecast_empty_string_to_nil = false" to get the old
|
59
|
+
behavior. This should make web development with Sequel
|
60
|
+
significantly easier, hopefully at no expense to other uses.
|
61
|
+
|
62
|
+
* Database.uri_to_options is now a private class method.
|
63
|
+
|
64
|
+
* Model.create_table! now acts the same as Database.create_table!,
|
65
|
+
dropping the table unconditionally and then creating it. This was
|
66
|
+
done for consistency. If you are using Model.create_table! in
|
67
|
+
production code, you should change it to
|
68
|
+
"Model.create_table unless Model.table_exists?", otherwise you risk
|
69
|
+
wiping out your production data. I recommended you use the
|
70
|
+
migration feature instead of Model.set_schema, as that handles
|
71
|
+
altering existing tables.
|
72
|
+
|
73
|
+
Other Notable Changes
|
74
|
+
---------------------
|
75
|
+
|
76
|
+
* Using validates_length_of more than once on the same attribute with
|
77
|
+
different options without a tag no longer causes the first use to
|
78
|
+
be ignored. This was a side effect of the validation tags added
|
79
|
+
in 2.2.0.
|
80
|
+
|
81
|
+
* Other than the adapters, Sequel now has 100% code coverage (line
|
82
|
+
coverage).
|
83
|
+
|
84
|
+
* Model#set* methods now return self.
|
85
|
+
|
86
|
+
* An integration test suite was added, testing Sequel against a live
|
87
|
+
database with nothing mocked, which helped greatly when testing the
|
88
|
+
new support for JDBC adapters.
|
@@ -0,0 +1,106 @@
|
|
1
|
+
Prepared Statements/Bound Variables
|
2
|
+
===================================
|
3
|
+
|
4
|
+
Sequel now supports prepared statements and bound variables. No
|
5
|
+
matter which database you are using, Sequel uses exactly the same API.
|
6
|
+
To specify placeholders, you use the :$placeholder syntax:
|
7
|
+
|
8
|
+
ds = DB[:items].filter(:name=>:$n)
|
9
|
+
|
10
|
+
To use a bound variable:
|
11
|
+
|
12
|
+
ds.call(:select, :n=>'Jim')
|
13
|
+
|
14
|
+
This will do the equivalent of selecting records that have the name
|
15
|
+
'Jim'. In addition to :select, you can use :first or :delete. There
|
16
|
+
is also support for bound variables when inserting or updating
|
17
|
+
records:
|
18
|
+
|
19
|
+
ds.call(:update, {:n=>'Jim', :new_n=>'Bob'}, :name=>:$new_n)
|
20
|
+
|
21
|
+
Which will update all records that have the name 'Jim' to have the
|
22
|
+
name 'Bob'.
|
23
|
+
|
24
|
+
Prepared statement support is very similar to bound variable support,
|
25
|
+
except that the statement is first prepared with a name:
|
26
|
+
|
27
|
+
ps = ds.prepare(:select, :select_by_name)
|
28
|
+
|
29
|
+
It is then called later with the bound arguments to use:
|
30
|
+
|
31
|
+
ps.call(:n=>'Jim')
|
32
|
+
DB.call(:select_by_name, :n=>'Jim') # same as above
|
33
|
+
|
34
|
+
For inserting or updating, the hash to use when inserting or updating
|
35
|
+
is given to prepare:
|
36
|
+
|
37
|
+
ps2 = ds.prepare(:update, :update_name, :name=>:$new_n)
|
38
|
+
ps2.call(:n=>'Jim', :new_n=>'Bob')
|
39
|
+
|
40
|
+
There is some level of native support for these features in the
|
41
|
+
PostgreSQL, MySQL, SQLite, and JDBC adapters. For other adapters,
|
42
|
+
support is emulated, but it shouldn't be too difficult to add native
|
43
|
+
support for them.
|
44
|
+
|
45
|
+
For more details see:
|
46
|
+
http://sequel.rubyforge.org/rdoc/files/doc/prepared_statements_rdoc.html
|
47
|
+
|
48
|
+
Read-Only Slave/Writable Master and Database Sharding
|
49
|
+
=====================================================
|
50
|
+
|
51
|
+
Sequel now has built in support for master/slave database
|
52
|
+
configurations, just by setting an option in Sequel.connect:
|
53
|
+
|
54
|
+
DB=Sequel.connect('postgres://master_server/database', \
|
55
|
+
:servers=>{:read_only=>{:host=>'slave_server'}})
|
56
|
+
|
57
|
+
That will use slave_server for SELECT queries and master_server for
|
58
|
+
other queries. It's fairly easy to use multiple slaves or even
|
59
|
+
multiple masters, examples are included in the link below.
|
60
|
+
|
61
|
+
Sharding support requires some code other than the database
|
62
|
+
configuration, but is still fairly simple. For example, to set up
|
63
|
+
a 16 shard configuration based on a hex character:
|
64
|
+
|
65
|
+
servers = {}
|
66
|
+
(('0'..'9').to_a + ('a'..'f').to_a).each do |hex|
|
67
|
+
servers[hex.to_sym] = {:host=>"hash_host_#{hex}"}
|
68
|
+
end
|
69
|
+
DB=Sequel.connect('postgres://hash_host/hashes', :servers=>servers)
|
70
|
+
|
71
|
+
To set which shard to use for a query, use the Dataset#server method:
|
72
|
+
|
73
|
+
DB[:hashes].server(:a).filter(:hash=>/31337/)
|
74
|
+
|
75
|
+
For more details see:
|
76
|
+
http://sequel.rubyforge.org/rdoc/files/doc/sharding_rdoc.html
|
77
|
+
|
78
|
+
Other Changes
|
79
|
+
=============
|
80
|
+
|
81
|
+
* The sequel.rubyforge.org website has a new design thanks to boof.
|
82
|
+
The online RDoc is now located at http://sequel.rubyforge.org/rdoc.
|
83
|
+
|
84
|
+
* Support was added for anonymous column names in the ADO adapter.
|
85
|
+
|
86
|
+
* Better MSSQL support in the ADO, ODBC, and JDBC adapters. The
|
87
|
+
odbc_mssql adapter has been removed. If you use MSSQL with ODBC,
|
88
|
+
please use the odbc adapter with a :db_type=>'mssql' option.
|
89
|
+
|
90
|
+
* The following Sequel::Error exception subclasses were removed:
|
91
|
+
InvalidExpression, InvalidFilter, InvalidJoinType, and WorkerStop.
|
92
|
+
|
93
|
+
* Documentation was added for the PostgreSQL, MySQL, SQLite, and
|
94
|
+
JDBC adapters.
|
95
|
+
|
96
|
+
* Various internal interfaces were refactored. For example, if you
|
97
|
+
use an adapter not included with Sequel, it probably won't work
|
98
|
+
until you update it to the new internal API.
|
99
|
+
|
100
|
+
* Many low level methods (such as Database#transaction), now take
|
101
|
+
an optional server argument to indicate which server to use.
|
102
|
+
|
103
|
+
* Model plugins that have a DatasetMethods module with non-public
|
104
|
+
methods no longer have Model methods created that call those
|
105
|
+
methods.
|
106
|
+
|
@@ -0,0 +1,137 @@
|
|
1
|
+
New Features
|
2
|
+
------------
|
3
|
+
|
4
|
+
* The values that are used to insert/update records can now be
|
5
|
+
scoped similar to how filter expressions can be scoped.
|
6
|
+
set_defaults is used to set defaults which can be overridden,
|
7
|
+
and set_overrides is used to set defaults which cannot be
|
8
|
+
overridden:
|
9
|
+
|
10
|
+
DB[:t].set_defaults(:x=>1).insert_sql
|
11
|
+
# => INSERT INTO t (x) VALUES (1)
|
12
|
+
DB[:t].set_defaults(:x=>1).insert_sql(:x=>2)
|
13
|
+
# => INSERT INTO t (x) VALUES (2)
|
14
|
+
DB[:t].set_defaults(:x=>1).insert_sql(:y=>2)
|
15
|
+
# => INSERT INTO t (x, y) VALUES (1, 2)
|
16
|
+
DB[:t].set_overrides(:x=>1).insert_sql(:x=>2)
|
17
|
+
# => INSERT INTO t (x) VALUES (1)
|
18
|
+
|
19
|
+
The difference between set_defaults and set_overrides is that
|
20
|
+
with set_defaults, the last value takes precedence, while with
|
21
|
+
set_overrides, the first value takes precedence.
|
22
|
+
|
23
|
+
* The schema generators now support creating and altering tables
|
24
|
+
with composite primary and/or foreign keys:
|
25
|
+
|
26
|
+
DB.create_table(:items) do
|
27
|
+
integer :id
|
28
|
+
text :name
|
29
|
+
primary_key [:id, :name]
|
30
|
+
foreign_key [:id, :name], :other_table, \
|
31
|
+
:key=>[:item_id, :item_name]
|
32
|
+
end
|
33
|
+
|
34
|
+
DB.alter_table(:items) do
|
35
|
+
add_primary_key [:id, :name]
|
36
|
+
add_foreign_key [:id, :name], :other_table, \
|
37
|
+
:key=>[:item_id, :item_name]
|
38
|
+
end
|
39
|
+
|
40
|
+
* The AlterTableGenerator now supports unique constraints:
|
41
|
+
|
42
|
+
DB.alter_table(:items) do
|
43
|
+
add_unique_constraint [:aaa, :bbb, :ccc], :name => :con3
|
44
|
+
end
|
45
|
+
|
46
|
+
* The schema generators now support ON UPDATE (previously, they only
|
47
|
+
supported ON DELETE):
|
48
|
+
|
49
|
+
DB.create_table(:items) do
|
50
|
+
foreign_key :project_id, :projects, :on_update => :cascade
|
51
|
+
end
|
52
|
+
|
53
|
+
* When connecting to a PostgreSQL server version 8.2 and higher,
|
54
|
+
Sequel now uses the INSERT ... RETURNING ... syntax, which should
|
55
|
+
speed up row inserts on PostgreSQL. In addition, Sequel Models
|
56
|
+
use RETURNING * to speed up model object creation.
|
57
|
+
|
58
|
+
* You can now validate multiple attributes at once. This is useful
|
59
|
+
if the combination of two or more attribute values is important,
|
60
|
+
such as checking the uniqueness of multiple columns.
|
61
|
+
validates_uniqueness_of now supports this directly:
|
62
|
+
|
63
|
+
validates_uniqueness_of [:column1, :column2]
|
64
|
+
|
65
|
+
This protects against the database having multiple rows with the
|
66
|
+
same values for both :column1 and :column2. This is different
|
67
|
+
from:
|
68
|
+
|
69
|
+
validates_uniqueness_of :column1, :column2
|
70
|
+
|
71
|
+
Which checks that the value of column1 is unique in the table, and
|
72
|
+
that the value of column2 is unique in the table (which is much
|
73
|
+
more restrictive).
|
74
|
+
|
75
|
+
Other Improvements
|
76
|
+
------------------
|
77
|
+
|
78
|
+
* Dataset methods insert_sql, delete_sql, and update_sql respect the
|
79
|
+
:sql option, allowing you to do things such as:
|
80
|
+
|
81
|
+
ds = DB['INSERT INTO t (time) VALUES (CURRENT_TIMESTAMP)']
|
82
|
+
ds.insert
|
83
|
+
ds.insert
|
84
|
+
|
85
|
+
* The database adapters (at least MySQL, PostgreSQL, SQLite, and
|
86
|
+
JDBC) generally raise Sequel::DatabaseError for database problems,
|
87
|
+
making it easier to tell what is a true database error versus an
|
88
|
+
error raised by Sequel itself.
|
89
|
+
|
90
|
+
* Sequel uses the async features of ruby-pg so that the entire
|
91
|
+
interpreter is not blocked while waiting for the results of
|
92
|
+
queries.
|
93
|
+
|
94
|
+
* Sequel now supports the 2008.08.17 version of ruby-pg.
|
95
|
+
|
96
|
+
* MSSQL support has been improved when using the ODBC and ADO
|
97
|
+
adapters.
|
98
|
+
|
99
|
+
* Index names are quoted and creating or dropping indexes.
|
100
|
+
|
101
|
+
* Automatically generated column accessor methods no longer override
|
102
|
+
instance methods specified by plugins.
|
103
|
+
|
104
|
+
* Inserting a row with an already specified primary key inside a
|
105
|
+
transaction now works correctly when using PostgreSQL.
|
106
|
+
|
107
|
+
* before_save and before_update hooks now work as expected when using
|
108
|
+
save_changes.
|
109
|
+
|
110
|
+
* count and paginate now work correctly on graphed datasets.
|
111
|
+
|
112
|
+
Backwards Compatibility
|
113
|
+
-----------------------
|
114
|
+
|
115
|
+
* The SQLite adapter now raises Sequel::DatabaseError instead of
|
116
|
+
Sequel::Error::InvalidStatement whenever an SQLite3::Exception is
|
117
|
+
raised by the SQLite3 driver.
|
118
|
+
|
119
|
+
* Date and DateTime conversions now convert 2 digit years. To revert
|
120
|
+
to the previous behavior:
|
121
|
+
|
122
|
+
Sequel.convert_two_digit_years = false
|
123
|
+
|
124
|
+
Note that Ruby 1.8 and 1.9 handle Date parsing differently, so
|
125
|
+
there is no backwards compatibility change for Ruby 1.9. However,
|
126
|
+
this also means that the MM/DD/YY date syntax commonly used in the
|
127
|
+
United States is not always parsed correctly on Ruby 1.9, greatly
|
128
|
+
limiting the use of 2 digit year conversion.
|
129
|
+
|
130
|
+
* You can no longer abuse the SQL function syntax for specifying
|
131
|
+
database types. For example, you must change:
|
132
|
+
|
133
|
+
:type=>:varchar[255]
|
134
|
+
|
135
|
+
to:
|
136
|
+
|
137
|
+
:type=>:varchar, :size=>255
|