sequel 3.26.0 → 3.27.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +26 -0
- data/Rakefile +2 -3
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +9 -533
- data/doc/prepared_statements.rdoc +8 -7
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/testing.rdoc +64 -0
- data/lib/sequel/adapters/amalgalite.rb +4 -0
- data/lib/sequel/adapters/jdbc.rb +3 -1
- data/lib/sequel/adapters/jdbc/h2.rb +11 -5
- data/lib/sequel/adapters/mysql.rb +4 -122
- data/lib/sequel/adapters/mysql2.rb +4 -13
- data/lib/sequel/adapters/odbc.rb +4 -1
- data/lib/sequel/adapters/odbc/db2.rb +21 -0
- data/lib/sequel/adapters/shared/mysql.rb +12 -0
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +143 -0
- data/lib/sequel/adapters/tinytds.rb +122 -3
- data/lib/sequel/core.rb +4 -3
- data/lib/sequel/database/misc.rb +7 -10
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/sql.rb +7 -0
- data/lib/sequel/model/associations.rb +2 -2
- data/lib/sequel/model/base.rb +60 -10
- data/lib/sequel/plugins/prepared_statements_safe.rb +17 -7
- data/lib/sequel/sql.rb +5 -0
- data/lib/sequel/timezones.rb +12 -3
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +25 -21
- data/spec/core/database_spec.rb +200 -0
- data/spec/core/dataset_spec.rb +6 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +10 -0
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/integration/schema_test.rb +30 -1
- data/spec/integration/type_test.rb +10 -3
- data/spec/model/base_spec.rb +44 -0
- data/spec/model/model_spec.rb +14 -0
- data/spec/model/record_spec.rb +131 -12
- metadata +14 -4
@@ -3,15 +3,16 @@
|
|
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
|
6
|
+
the following adapters:
|
7
7
|
|
8
|
-
*
|
9
|
-
*
|
10
|
-
|
11
|
-
*
|
12
|
-
*
|
8
|
+
* jdbc
|
9
|
+
* mysql (prepared statements only)
|
10
|
+
* mysql2 (prepared statements only)
|
11
|
+
* postgres (when using the pg driver, may require type specifiers)
|
12
|
+
* sqlite
|
13
|
+
* tinytds
|
13
14
|
|
14
|
-
Support on other
|
15
|
+
Support on other adapters is emulated via string interpolation.
|
15
16
|
|
16
17
|
You can use the prepared_statements model plugin to automatically use prepared
|
17
18
|
statements for some common model actions such as saving or deleting a model
|
@@ -0,0 +1,82 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Model.dataset_module has been added for easily adding methods to
|
4
|
+
a model's dataset:
|
5
|
+
|
6
|
+
Album.dataset_module do
|
7
|
+
def with_name_like(x)
|
8
|
+
filter(:name.like(x))
|
9
|
+
end
|
10
|
+
def selling_at_least(x)
|
11
|
+
filter{copies_sold > x}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
Album.with_name_like('Foo%').selling_at_least(100000).all
|
15
|
+
|
16
|
+
Previously, you could use def_dataset_method to accomplish the
|
17
|
+
same thing. dataset_module is generally cleaner, plus you are
|
18
|
+
using actual methods instead of blocks, so calling the methods
|
19
|
+
is faster on some ruby implementations.
|
20
|
+
|
21
|
+
* Sequel now uses a Sequel::SQLTime class (a subclass of Time) when
|
22
|
+
dealing with values for SQL time columns (which don't have a date
|
23
|
+
component). These values are handled correctly when used in
|
24
|
+
filters or insert/update statements (using only the time
|
25
|
+
component), so Sequel can now successfully round trip values for
|
26
|
+
time columns. Not all adapters support returning time column
|
27
|
+
values as SQLTime instances, but the most common ones do.
|
28
|
+
|
29
|
+
* You can now drop foreign key, primary key, and unique constraints
|
30
|
+
on MySQL by passing the :type=>(:foreign_key|:primary_key|:unique)
|
31
|
+
option to Database#drop_constraint.
|
32
|
+
|
33
|
+
* The ODBC adapter now has initial support for the DB2 database, use
|
34
|
+
the :db_type=>'db2' option to load the support.
|
35
|
+
|
36
|
+
= Other Improvements
|
37
|
+
|
38
|
+
* The mysql2 adapter now uses native prepared statements.
|
39
|
+
|
40
|
+
* The tinytds adapter now uses uses sp_executesql for prepared
|
41
|
+
statements.
|
42
|
+
|
43
|
+
* DateTime and Time objects are now converted to Date objects when
|
44
|
+
they are assigned to a date column in a Model instance.
|
45
|
+
|
46
|
+
* When converting a Date object to a DateTime object, the resulting
|
47
|
+
DateTime object now has no fractional day components. Previously,
|
48
|
+
depending on your timezone settings, it could have had fractional
|
49
|
+
day components.
|
50
|
+
|
51
|
+
* The mysql2 adapter now supports stored procedures, as long as they
|
52
|
+
don't return results.
|
53
|
+
|
54
|
+
* Mass assignment protection now handles including modules in model
|
55
|
+
classes and extending model instances with modules. Previously, if
|
56
|
+
you defined a setter method in a module, access to it may have been
|
57
|
+
restricted.
|
58
|
+
|
59
|
+
* The prepared_statements_safe plugin now works on classes without
|
60
|
+
datasets, so you can now do the following to load it for all models:
|
61
|
+
|
62
|
+
Sequel::Model.plugin :prepared_statements_safe
|
63
|
+
|
64
|
+
* Dataset#hash now works correctly when handling SQL::Expression
|
65
|
+
instances.
|
66
|
+
|
67
|
+
* Model#hash now correctly handles classes with no primary key or with
|
68
|
+
a composite primary key.
|
69
|
+
|
70
|
+
* Model#exists? now always returns false for new model objects.
|
71
|
+
|
72
|
+
= Backwards Compatibility
|
73
|
+
|
74
|
+
* If you were previously setting primary key values manually for new
|
75
|
+
model objects and then calling exists? to see if the instance is
|
76
|
+
already in the database, you need to change your code from:
|
77
|
+
|
78
|
+
model.exists?
|
79
|
+
|
80
|
+
to:
|
81
|
+
|
82
|
+
model.this.get(1).nil?
|
@@ -0,0 +1,547 @@
|
|
1
|
+
= Schema modification methods
|
2
|
+
|
3
|
+
Here's a brief description of the most common schema modification methods:
|
4
|
+
|
5
|
+
== +create_table+
|
6
|
+
|
7
|
+
+create_table+ is the most common schema modification method, and it's used for adding new tables
|
8
|
+
to the schema. You provide it with the name of the table as a symbol, as well a block:
|
9
|
+
|
10
|
+
create_table(:artists) do
|
11
|
+
primary_key :id
|
12
|
+
String :name
|
13
|
+
end
|
14
|
+
|
15
|
+
Not that if you want a primary key for the table, you need to specify it, Sequel does not create one
|
16
|
+
by default.
|
17
|
+
|
18
|
+
=== Column types
|
19
|
+
|
20
|
+
Most method calls inside the create_table block will create columns, since +method_missing+ calls +column+.
|
21
|
+
Columns are generally created by specifying the column type as the method
|
22
|
+
name, followed by the column name symbol to use, and after that any options that should be used.
|
23
|
+
If the method is a ruby class name that Sequel recognizes, Sequel will transform it into the appropriate
|
24
|
+
type for the given database. So while you specified +String+, Sequel will actually use +varchar+ or
|
25
|
+
+text+ depending on the underlying database. Here's a list of all of ruby classes that Sequel will
|
26
|
+
convert to database types:
|
27
|
+
|
28
|
+
create_table(:columns_types) do # common database type used
|
29
|
+
Integer :a0 # integer
|
30
|
+
String :a1 # varchar(255)
|
31
|
+
String :a2, :size=>50 # varchar(50)
|
32
|
+
String :a3, :fixed=>true # char(255)
|
33
|
+
String :a4, :fixed=>true, :size=>50 # char(50)
|
34
|
+
String :a5, :text=>true # text
|
35
|
+
File :b, # blob
|
36
|
+
Fixnum :c # integer
|
37
|
+
Bignum :d # bigint
|
38
|
+
Float :e # double precision
|
39
|
+
BigDecimal :f # numeric
|
40
|
+
BigDecimal :f2, :size=>10 # numeric(10)
|
41
|
+
BigDecimal :f3, :size=>[10, 2] # numeric(10, 2)
|
42
|
+
Date :g # date
|
43
|
+
DateTime :h # timestamp
|
44
|
+
Time :i # timestamp
|
45
|
+
Time :i2, :only_time=>true # time
|
46
|
+
Numeric :j # numeric
|
47
|
+
TrueClass :k # boolean
|
48
|
+
FalseClass :l # boolean
|
49
|
+
end
|
50
|
+
|
51
|
+
Note that in addition to the ruby class name, Sequel also pays attention to the column options when
|
52
|
+
determining which database type to use. Also note that for boolean columns, you can use either
|
53
|
+
TrueClass or FalseClass, they are treated the same way (ruby doesn't have a Boolean class).
|
54
|
+
|
55
|
+
Also note that this conversion is only done if you use a supported ruby class name. In all other
|
56
|
+
cases, Sequel uses the type specified verbatim:
|
57
|
+
|
58
|
+
create_table(:columns_types) do # database type used
|
59
|
+
string :a1 # string
|
60
|
+
datetime :a2 # datetime
|
61
|
+
blob :a3 # blob
|
62
|
+
inet :a4 # inet
|
63
|
+
end
|
64
|
+
|
65
|
+
In addition to specifying the types as methods, you can use the +column+ method and specify the types
|
66
|
+
as the second argument, either as ruby classes, symbols, or strings:
|
67
|
+
|
68
|
+
create_table(:columns_types) do # database type used
|
69
|
+
column :a1, :string # string
|
70
|
+
column :a2, String # varchar(255)
|
71
|
+
column :a3, 'string' # string
|
72
|
+
column :a4, :datetime # datetime
|
73
|
+
column :a5, DateTime # timestamp
|
74
|
+
column :a6, 'timestamp(6)' # timestamp(6)
|
75
|
+
end
|
76
|
+
|
77
|
+
=== Column options
|
78
|
+
|
79
|
+
When using the type name as method, the third argument is an options hash, and when using the +column+
|
80
|
+
method, the fourth argument is the options hash. The following options are supported:
|
81
|
+
|
82
|
+
:default :: The default value for the column.
|
83
|
+
:index :: Create an index on this column.
|
84
|
+
:null :: Mark the column as allowing NULL values (if true),
|
85
|
+
or not allowing NULL values (if false). If unspecified, will default
|
86
|
+
to whatever the database default is.
|
87
|
+
:size :: The size of the column, generally used with string
|
88
|
+
columns to specify the maximum number of characters the column will hold.
|
89
|
+
An array of two integers can be provided to set the size and the
|
90
|
+
precision, respectively, of decimal columns.
|
91
|
+
:unique :: Mark the column as unique, generally has the same effect as
|
92
|
+
creating a unique index on the column.
|
93
|
+
:unsigned :: Make the column type unsigned, only useful for integer
|
94
|
+
columns.
|
95
|
+
|
96
|
+
=== Other methods
|
97
|
+
|
98
|
+
In addition to the +column+ method and other methods that create columns, there are a other methods that can be used:
|
99
|
+
|
100
|
+
==== +primary_key+
|
101
|
+
|
102
|
+
You've seen this one used already. It's used to create an autoincrementing integer primary key column.
|
103
|
+
|
104
|
+
create_table(:a0){primary_key :id}
|
105
|
+
|
106
|
+
If you want to create a primary key column that doesn't use an autoincrementing integer, you should
|
107
|
+
not use this method. Instead, you should use the :primary_key option to the +column+ method or type
|
108
|
+
method:
|
109
|
+
|
110
|
+
create_table(:a1){Integer :id, :primary_key=>true} # Non autoincrementing integer primary key
|
111
|
+
create_table(:a2){String :name, :primary_key=>true} # varchar(255) primary key
|
112
|
+
|
113
|
+
If you want to create a composite primary key, you should call the +primary_key+ method with an
|
114
|
+
array of column symbols:
|
115
|
+
|
116
|
+
create_table(:items) do
|
117
|
+
Integer :group_id
|
118
|
+
Integer :position
|
119
|
+
primary_key [:group_id, :position]
|
120
|
+
end
|
121
|
+
|
122
|
+
If provided with an array, +primary_key+ does not create a column, it just sets up the primary key constraint.
|
123
|
+
|
124
|
+
==== +foreign_key+
|
125
|
+
|
126
|
+
+foreign_key+ is used to create a foreign key column that references a column in another table (or the same table).
|
127
|
+
It takes the column name as the first argument, the table it references as the second argument, and an options hash
|
128
|
+
as it's third argument. A simple example is:
|
129
|
+
|
130
|
+
create_table(:albums) do
|
131
|
+
primary_key :id
|
132
|
+
foreign_key :artist_id, :artists
|
133
|
+
String :name
|
134
|
+
end
|
135
|
+
|
136
|
+
+foreign_key+ accepts some specific options:
|
137
|
+
|
138
|
+
:deferrable :: Makes the foreign key constraint checks deferrable, so they aren't checked
|
139
|
+
until the end of the transaction.
|
140
|
+
:key :: For foreign key columns, the column in the associated table
|
141
|
+
that this column references. Unnecessary if this column
|
142
|
+
references the primary key of the associated table, at least
|
143
|
+
on most databases.
|
144
|
+
:on_delete :: Specify the behavior of this foreign key column when the row with the primary key
|
145
|
+
it references is deleted , can be :restrict, :cascade, :set_null, or :set_default.
|
146
|
+
:on_update :: Specify the behavior of this foreign key column when the row with the primary key
|
147
|
+
it references modifies the value of the primary key, can be
|
148
|
+
:restrict, :cascade, :set_null, or :set_default.
|
149
|
+
|
150
|
+
Like +primary_key+, if you provide +foreign_key+ with an array of symbols, it will not create a
|
151
|
+
column, but create a foreign key constraint:
|
152
|
+
|
153
|
+
create_table(:artists) do
|
154
|
+
String :name
|
155
|
+
String :location
|
156
|
+
primary_key [:name, :location]
|
157
|
+
end
|
158
|
+
create_table(:albums) do
|
159
|
+
String :artist_name
|
160
|
+
String :artist_location
|
161
|
+
String :name
|
162
|
+
foreign_key [:artist_name, :artist_location], :artists
|
163
|
+
end
|
164
|
+
|
165
|
+
==== +index+
|
166
|
+
|
167
|
+
+index+ creates indexes on the table. For single columns, calling index is the same as using the
|
168
|
+
<tt>:index</tt> option when creating the column:
|
169
|
+
|
170
|
+
create_table(:a){Integer :id, :index=>true}
|
171
|
+
# Same as:
|
172
|
+
create_table(:a) do
|
173
|
+
Integer :id
|
174
|
+
index :id
|
175
|
+
end
|
176
|
+
|
177
|
+
Similar to the +primary_key+ and +foreign_key+ methods, calling +index+ with an array of symbols
|
178
|
+
will create a multiple column index:
|
179
|
+
|
180
|
+
create_table(:albums) do
|
181
|
+
primary_key :id
|
182
|
+
foreign_key :artist_id, :artists
|
183
|
+
Integer :position
|
184
|
+
index [:artist_id, :position]
|
185
|
+
end
|
186
|
+
|
187
|
+
The +index+ method also accepts some options:
|
188
|
+
|
189
|
+
:name :: The name of the index (generated based on the table and column names if not provided).
|
190
|
+
:type :: The type of index to use (only supported by some databases)
|
191
|
+
:unique :: Make the index unique, so duplicate values are not allowed.
|
192
|
+
:where :: Create a partial index (only supported by some databases)
|
193
|
+
|
194
|
+
==== +unique+
|
195
|
+
|
196
|
+
The +unique+ method creates a unique constraint on the table. A unique constraint generally
|
197
|
+
operates identically to a unique index, so the following three +create_table+ blocks are
|
198
|
+
pretty much identical:
|
199
|
+
|
200
|
+
create_table(:a){Integer :a, :unique=>true}
|
201
|
+
|
202
|
+
create_table(:a) do
|
203
|
+
Integer :a
|
204
|
+
index :a, :unique=>true
|
205
|
+
end
|
206
|
+
|
207
|
+
create_table(:a) do
|
208
|
+
Integer :a
|
209
|
+
unique :a
|
210
|
+
end
|
211
|
+
|
212
|
+
Just like +index+, +unique+ can set up a multiple column unique constraint, where the
|
213
|
+
combination of the columns must be unique:
|
214
|
+
|
215
|
+
create_table(:a) do
|
216
|
+
Integer :a
|
217
|
+
Integer :b
|
218
|
+
unique [:a, :b]
|
219
|
+
end
|
220
|
+
|
221
|
+
==== +full_text_index+ and +spatial_index+
|
222
|
+
|
223
|
+
Both of these create specialized index types supported by some databases. They
|
224
|
+
both take the same options as +index+.
|
225
|
+
|
226
|
+
==== +constraint+
|
227
|
+
|
228
|
+
+constraint+ creates a named table constraint:
|
229
|
+
|
230
|
+
create_table(:artists) do
|
231
|
+
primary_key :id
|
232
|
+
String :name
|
233
|
+
constraint(:name_min_length){char_length(name) > 2}
|
234
|
+
end
|
235
|
+
|
236
|
+
Instead of using a block, you can use arguments that will be handled similarly
|
237
|
+
to <tt>Dataset#filter</tt>:
|
238
|
+
|
239
|
+
create_table(:artists) do
|
240
|
+
primary_key :id
|
241
|
+
String :name
|
242
|
+
constraint(:name_length_range, :char_length.sql_function(:name)=>3..50)
|
243
|
+
end
|
244
|
+
|
245
|
+
==== +check+
|
246
|
+
|
247
|
+
+check+ operates just like +constraint+, except that it doesn't take a name
|
248
|
+
and it creates an unnamed constraint
|
249
|
+
|
250
|
+
create_table(:artists) do
|
251
|
+
primary_key :id
|
252
|
+
String :name
|
253
|
+
check{char_length(name) > 2}
|
254
|
+
end
|
255
|
+
|
256
|
+
== +alter_table+
|
257
|
+
|
258
|
+
+alter_table+ is used to alter existing tables, changing their columns, indexes,
|
259
|
+
or constraints. It it used just like +create_table+, accepting a block which
|
260
|
+
is instance_evaled, and providing its own methods:
|
261
|
+
|
262
|
+
=== +add_column+
|
263
|
+
|
264
|
+
One of the most common methods, +add_column+ is used to add a column to the table.
|
265
|
+
Its API is similar to that of +create_table+'s +column+ method, where the first
|
266
|
+
argument is the column name, the second is the type, and the third is an options
|
267
|
+
hash:
|
268
|
+
|
269
|
+
alter_table(:albums) do
|
270
|
+
add_column :copies_sold, Integer, :default=>0
|
271
|
+
end
|
272
|
+
|
273
|
+
When adding a column, it's a good idea to provide a default value, unless you
|
274
|
+
want the value for all rows to be set to NULL.
|
275
|
+
|
276
|
+
=== +drop_column+
|
277
|
+
|
278
|
+
As you may expect, +drop_column+ takes a column name and drops the column. It's
|
279
|
+
often used in the +down+ block of a migration to drop a column added in an +up+ block:
|
280
|
+
|
281
|
+
alter_table(:albums) do
|
282
|
+
drop_column :copies_sold
|
283
|
+
end
|
284
|
+
|
285
|
+
=== +rename_column+
|
286
|
+
|
287
|
+
+rename_column+ is used to rename a column. It takes the old column name as the first
|
288
|
+
argument, and the new column name as the second argument:
|
289
|
+
|
290
|
+
alter_table(:albums) do
|
291
|
+
rename_column :copies_sold, :total_sales
|
292
|
+
end
|
293
|
+
|
294
|
+
=== +add_primary_key+
|
295
|
+
|
296
|
+
If you forgot to include a primary key on the table, and want to add one later, you
|
297
|
+
can use +add_primary_key+. A common use of this is to make many_to_many association
|
298
|
+
join tables into real models:
|
299
|
+
|
300
|
+
alter_table(:albums_artists) do
|
301
|
+
add_primary_key :id
|
302
|
+
end
|
303
|
+
|
304
|
+
Just like +create_table+'s +primary_key+ method, if you provide an array of symbols,
|
305
|
+
Sequel will not add a column, but will add a composite primary key constraint:
|
306
|
+
|
307
|
+
alter_table(:albums_artists) do
|
308
|
+
add_primary_key [:album_id, :artist_id]
|
309
|
+
end
|
310
|
+
|
311
|
+
If you just want to take an existing single column and make it a primary key, call
|
312
|
+
+add_primary_key+ with an array with a single symbol:
|
313
|
+
|
314
|
+
alter_table(:artists) do
|
315
|
+
add_primary_key [:id]
|
316
|
+
end
|
317
|
+
|
318
|
+
=== +add_foreign_key+
|
319
|
+
|
320
|
+
+add_foreign_key+ can be used to add a new foreign key column or constraint to a table.
|
321
|
+
Like +add_primary_key+, if you provide it with a symbol as the first argument, it
|
322
|
+
creates a new column:
|
323
|
+
|
324
|
+
alter_table(:albums) do
|
325
|
+
add_foreign_key :artist_id, :artists
|
326
|
+
end
|
327
|
+
|
328
|
+
If you want to add a new foreign key constraint to an existing column, you provide an
|
329
|
+
array with a single element:
|
330
|
+
|
331
|
+
alter_table(:albums) do
|
332
|
+
add_foreign_key [:artist_id], :artists
|
333
|
+
end
|
334
|
+
|
335
|
+
To set up a multiple column foreign key constraint, use an array with multiple column
|
336
|
+
symbols:
|
337
|
+
|
338
|
+
alter_table(:albums) do
|
339
|
+
add_foreign_key [:artist_name, :artist_location], :artists
|
340
|
+
end
|
341
|
+
|
342
|
+
=== +add_index+
|
343
|
+
|
344
|
+
+add_index+ works just like +create_table+'s +index+ method, creating a new index on
|
345
|
+
the table:
|
346
|
+
|
347
|
+
alter_table(:albums) do
|
348
|
+
add_index :artist_id
|
349
|
+
end
|
350
|
+
|
351
|
+
It accepts the same options as +create_table+'s +index+ method, and you can set up
|
352
|
+
a multiple column index using an array:
|
353
|
+
|
354
|
+
alter_table(:albums_artists) do
|
355
|
+
add_index [:album_id, :artist_id], :unique=>true
|
356
|
+
end
|
357
|
+
|
358
|
+
=== +drop_index+
|
359
|
+
|
360
|
+
As you may expect, +drop_index+ drops an existing index:
|
361
|
+
|
362
|
+
alter_table(:albums) do
|
363
|
+
drop_index :artist_id
|
364
|
+
end
|
365
|
+
|
366
|
+
Just like +drop_column+, it is often used in the +down+ block of a migration.
|
367
|
+
|
368
|
+
To drop an index with a specific name, use the <tt>:name</tt> option:
|
369
|
+
|
370
|
+
alter_table(:albums) do
|
371
|
+
drop_index :artist_id, :name=>:artists_id_index
|
372
|
+
end
|
373
|
+
|
374
|
+
=== +add_full_text_index+, +add_spatial_index+
|
375
|
+
|
376
|
+
Corresponding to +create_table+'s +full_text_index+ and +spatial_index+ methods,
|
377
|
+
these two methods create new indexes on the table.
|
378
|
+
|
379
|
+
=== +add_constraint+
|
380
|
+
|
381
|
+
This adds a named constraint to the table, similar to +create_table+'s +constraint+
|
382
|
+
method:
|
383
|
+
|
384
|
+
alter_table(:albums) do
|
385
|
+
add_constraint(:name_min_length){char_length(name) > 2}
|
386
|
+
end
|
387
|
+
|
388
|
+
There is no method to add an unnamed constraint, but you can pass nil as the first
|
389
|
+
argument of +add_constraint+ to do so. However, it's not recommend to do that
|
390
|
+
as it is difficult to drop such a constraint.
|
391
|
+
|
392
|
+
=== +add_unique_constraint+
|
393
|
+
|
394
|
+
This adds a unique constraint to the table, similar to +create_table+'s +unique+
|
395
|
+
method. This usually has the same effect as adding a unique index.
|
396
|
+
|
397
|
+
alter_table(:albums) do
|
398
|
+
add_unique_constraint [:artist_id, :name]
|
399
|
+
end
|
400
|
+
|
401
|
+
=== +drop_constraint+
|
402
|
+
|
403
|
+
This method drops an existing named constraint:
|
404
|
+
|
405
|
+
alter_table(:albums) do
|
406
|
+
drop_constraint(:name_min_length)
|
407
|
+
end
|
408
|
+
|
409
|
+
There is no database independent method to drop an unnamed constraint. Generally, the
|
410
|
+
database will give it a name automatically, and you will have to figure out what it is.
|
411
|
+
For that reason, you should not add unnamed constraints that you ever might need to remove.
|
412
|
+
|
413
|
+
On MySQL, you must specify the type of constraint via a <tt>:type</tt> option:
|
414
|
+
|
415
|
+
alter_table(:albums) do
|
416
|
+
drop_constraint(:albums_pk, :type=>:primary_key)
|
417
|
+
drop_constraint(:albums_fk, :type=>:foreign_key)
|
418
|
+
drop_constraint(:albums_uk, :type=>:unique)
|
419
|
+
end
|
420
|
+
|
421
|
+
=== +set_column_default+
|
422
|
+
|
423
|
+
This modifies the default value of a column:
|
424
|
+
|
425
|
+
alter_table(:albums) do
|
426
|
+
set_column_default :copies_sold, 0
|
427
|
+
end
|
428
|
+
|
429
|
+
=== +set_column_type+
|
430
|
+
|
431
|
+
This modifies a column's type. Most databases will attempt to convert existing values in
|
432
|
+
the columns to the new type:
|
433
|
+
|
434
|
+
alter_table(:albums) do
|
435
|
+
set_column_type :copies_sold, Bignum
|
436
|
+
end
|
437
|
+
|
438
|
+
You can specify the type as a string or symbol, in which case it is used verbatim, or as a supported
|
439
|
+
ruby class, in which case it gets converted to an appropriate database type.
|
440
|
+
|
441
|
+
=== +set_column_allow_null+
|
442
|
+
|
443
|
+
This changes the NULL or NOT NULL setting of a column:
|
444
|
+
|
445
|
+
alter_table(:albums) do
|
446
|
+
set_column_allow_null :artist_id, true # NULL
|
447
|
+
set_column_allow_null :copies_sold, false # NOT NULL
|
448
|
+
end
|
449
|
+
|
450
|
+
== Other +Database+ schema modification methods
|
451
|
+
|
452
|
+
<tt>Sequel::Database</tt> has many schema modification instance methods,
|
453
|
+
most of which are shortcuts to the same methods in +alter_table+. The
|
454
|
+
following +Database+ instance methods just call +alter_table+ with a
|
455
|
+
block that calls the method with the same name inside the +alter_table+
|
456
|
+
block with all arguments after the first argument (which is used as
|
457
|
+
the table name):
|
458
|
+
|
459
|
+
* +add_column+
|
460
|
+
* +drop_column+
|
461
|
+
* +rename_column+
|
462
|
+
* +add_index+
|
463
|
+
* +drop_index+
|
464
|
+
* +set_column_default+
|
465
|
+
* +set_column_type+
|
466
|
+
|
467
|
+
For example, the following two method calls do the same thing:
|
468
|
+
|
469
|
+
alter_table(:artists){add_column :copies_sold, Integer}
|
470
|
+
add_column :artists, :copies_sold, Integer
|
471
|
+
|
472
|
+
There are some other schema modification methods that have no +alter_table+
|
473
|
+
counterpart:
|
474
|
+
|
475
|
+
=== +drop_table+
|
476
|
+
|
477
|
+
+drop_table+ takes multiple arguments and treats all arguments as a
|
478
|
+
table name to drop:
|
479
|
+
|
480
|
+
drop_table(:albums_artists, :albums, :artists)
|
481
|
+
|
482
|
+
Note that when dropping tables, you may need to drop them in a specific order
|
483
|
+
if you are using foreign keys and the database is enforcing referential
|
484
|
+
integrity. In general, you need to drop the tables containing the foreign
|
485
|
+
keys before the tables containing the primary keys they reference.
|
486
|
+
|
487
|
+
=== +rename_table+
|
488
|
+
|
489
|
+
You can rename an existing table using +rename_table+. Like +rename_column+,
|
490
|
+
the first argument is the current name, and the second is the new name:
|
491
|
+
|
492
|
+
rename_table(:artist, :artists)
|
493
|
+
|
494
|
+
=== <tt>create_table!</tt>
|
495
|
+
|
496
|
+
<tt>create_table!</tt> with the bang drops the table if it exists
|
497
|
+
before attempting to create it, so:
|
498
|
+
|
499
|
+
create_table!(:artists)
|
500
|
+
primary_key :id
|
501
|
+
end
|
502
|
+
|
503
|
+
is the same as:
|
504
|
+
|
505
|
+
drop_table(:artists) if table_exists?(:artists)
|
506
|
+
create_table(:artists)
|
507
|
+
primary_key :id
|
508
|
+
end
|
509
|
+
|
510
|
+
It should not be used inside migrations, as if the table does not exist, it may
|
511
|
+
mess up the migration.
|
512
|
+
|
513
|
+
=== <tt>create_table?</tt>
|
514
|
+
|
515
|
+
<tt>create_table?</tt> with a question mark only creates the table if it does
|
516
|
+
not already exist, so:
|
517
|
+
|
518
|
+
create_table!(:artists)
|
519
|
+
primary_key :id
|
520
|
+
end
|
521
|
+
|
522
|
+
is the same as:
|
523
|
+
|
524
|
+
create_table(:artists)
|
525
|
+
primary_key :id
|
526
|
+
end unless table_exists?(:artists)
|
527
|
+
|
528
|
+
Like <tt>create_table!</tt>, it should not be used inside migrations.
|
529
|
+
|
530
|
+
=== +create_view+ and +create_or_replace_view+
|
531
|
+
|
532
|
+
These can be used to create views. The difference between them is that
|
533
|
+
+create_or_replace_view+ will unconditionally replace an existing view of
|
534
|
+
the same name, while +create_view+ will probably raise an error. Both methods
|
535
|
+
take the name as the first argument, and either an string or a dataset as the
|
536
|
+
second argument:
|
537
|
+
|
538
|
+
create_view(:gold_albums, DB[:albums].filter{copies_sold > 500000})
|
539
|
+
create_or_replace_view(:gold_albums, "SELECT * FROM albums WHERE copies_sold > 500000")
|
540
|
+
|
541
|
+
=== +drop_view+
|
542
|
+
|
543
|
+
+drop_view+ drops existing views. Just like +drop_table+, it can accept multiple
|
544
|
+
arguments:
|
545
|
+
|
546
|
+
drop_view(:gold_albums, :platinum_albums)
|
547
|
+
|