sequel 5.61.0 → 5.62.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +32 -0
- data/README.rdoc +20 -19
- data/doc/advanced_associations.rdoc +13 -13
- data/doc/association_basics.rdoc +21 -15
- data/doc/cheat_sheet.rdoc +3 -3
- data/doc/model_hooks.rdoc +1 -1
- data/doc/object_model.rdoc +8 -8
- data/doc/opening_databases.rdoc +4 -4
- data/doc/postgresql.rdoc +8 -8
- data/doc/querying.rdoc +1 -1
- data/doc/release_notes/5.62.0.txt +132 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +9 -9
- data/doc/sql.rdoc +13 -13
- data/doc/testing.rdoc +13 -11
- data/doc/transactions.rdoc +6 -6
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/postgres.rb +4 -0
- data/lib/sequel/adapters/shared/access.rb +9 -1
- data/lib/sequel/adapters/shared/mssql.rb +9 -5
- data/lib/sequel/adapters/shared/mysql.rb +7 -0
- data/lib/sequel/adapters/shared/oracle.rb +7 -0
- data/lib/sequel/adapters/shared/postgres.rb +275 -152
- data/lib/sequel/adapters/shared/sqlanywhere.rb +7 -0
- data/lib/sequel/adapters/shared/sqlite.rb +5 -0
- data/lib/sequel/connection_pool.rb +42 -28
- data/lib/sequel/database/connecting.rb +24 -0
- data/lib/sequel/database/misc.rb +8 -2
- data/lib/sequel/database/query.rb +37 -0
- data/lib/sequel/dataset/actions.rb +31 -11
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/query.rb +9 -9
- data/lib/sequel/dataset/sql.rb +5 -1
- data/lib/sequel/extensions/_model_pg_row.rb +0 -12
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +11 -11
- data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +1 -1
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/extensions/named_timezones.rb +17 -5
- data/lib/sequel/extensions/pg_array.rb +22 -3
- data/lib/sequel/extensions/pg_auto_parameterize.rb +478 -0
- data/lib/sequel/extensions/pg_extended_date_support.rb +12 -0
- data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
- data/lib/sequel/extensions/pg_hstore.rb +5 -0
- data/lib/sequel/extensions/pg_inet.rb +9 -10
- data/lib/sequel/extensions/pg_interval.rb +9 -10
- data/lib/sequel/extensions/pg_json.rb +10 -10
- data/lib/sequel/extensions/pg_multirange.rb +5 -10
- data/lib/sequel/extensions/pg_range.rb +5 -10
- data/lib/sequel/extensions/pg_row.rb +18 -13
- data/lib/sequel/model/associations.rb +7 -2
- data/lib/sequel/model/base.rb +6 -5
- data/lib/sequel/plugins/auto_validations.rb +53 -15
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/composition.rb +2 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +4 -4
- data/lib/sequel/plugins/dirty.rb +1 -1
- data/lib/sequel/plugins/finder.rb +3 -1
- data/lib/sequel/plugins/nested_attributes.rb +4 -4
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +1 -1
- data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
- data/lib/sequel/plugins/sql_comments.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +20 -0
- data/lib/sequel/version.rb +1 -1
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df5fea5cf2d6dae7a5721c549c89a190df5a1cf79f2e7d48921dcdaeae398839
|
4
|
+
data.tar.gz: e1155c60bb4c2845a96cddf0a7d5498358f1cba826fdc9d7f00754a017b4310f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e52498bbcc1c2d472592b213be8e6e508f5881de5c1ae0579b426211aa448960e06bdb297f43eb26ee3024923f78e54bb17f9a886710c3ffe60f0c134746029
|
7
|
+
data.tar.gz: 0d5ae732cde0ad90a4c331f40628628e346386c483267173eb50eaad067d7de14ba6ff3c83f598d7440a6fcc752e4439cf1856706489cc3d3b7cffaf5b6d8de8
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
=== 5.62.0 (2022-11-01)
|
2
|
+
|
3
|
+
* Add back the pg_auto_parameterize extension for automatically using bound variables when using postgres adapter with pg driver (jeremyevans)
|
4
|
+
|
5
|
+
* Add pg_extended_integer_support extension for customizing behavior when literalizing a Ruby integer outside PostgreSQL bigint range (jeremyevans)
|
6
|
+
|
7
|
+
* Raise Postgres::IntegerOutsideBigintRange if attempting to literalize a Ruby integer outside PostgreSQL bigint range (jeremyevans)
|
8
|
+
|
9
|
+
* Add primary_key_lookup_check_values plugin for typecasting and checking primary key values during lookup (jeremyevans)
|
10
|
+
|
11
|
+
* Setup validation of minimum and maximum values for integer columns in auto_validations (jeremyevans)
|
12
|
+
|
13
|
+
* Add validates_max_value and validates_min_value to validation_helpers (jeremyevans)
|
14
|
+
|
15
|
+
* Include :min_value and :max_value schema entries for integer columns on most databases (jeremyevans)
|
16
|
+
|
17
|
+
* Don't wrap multi-inserts in a transaction when it's not required (shannoncole, jeremyevans) (#1945)
|
18
|
+
|
19
|
+
* Update mock PostgreSQL adapter to default to PostgreSQL 15 instead of PostgreSQL 14 (jeremyevans)
|
20
|
+
|
21
|
+
* Support fractional seconds in the named_timezones extension (jeremyevans) (#1943)
|
22
|
+
|
23
|
+
* Cache reflection datasets in the postgres adapter to improve performance (jeremyevans)
|
24
|
+
|
25
|
+
* Handle BC dates and timestamps in bound variables when using the pg_extended_date_support extension (jeremyevans)
|
26
|
+
|
27
|
+
* Correctly format hstore[] types in bound variables on PostgreSQL (jeremyevans)
|
28
|
+
|
29
|
+
* Fix corner case in eager loading where window function eager limit strategy is used, but row number entry is not removed (jeremyevans)
|
30
|
+
|
31
|
+
* Support server/shard specific :after_connect and :connect_sqls Database options (jeremyevans) (#1935)
|
32
|
+
|
1
33
|
=== 5.61.0 (2022-10-01)
|
2
34
|
|
3
35
|
* Make Database#foreign_key_list on PostgreSQL return results for partitioned tables (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -24,8 +24,9 @@ Bug tracking (GitHub Issues) :: https://github.com/jeremyevans/sequel/issues
|
|
24
24
|
Discussion Forum (GitHub Discussions) :: https://github.com/jeremyevans/sequel/discussions
|
25
25
|
Alternate Discussion Forum (sequel-talk Google Group) :: http://groups.google.com/group/sequel-talk
|
26
26
|
|
27
|
-
If you have questions about how to use Sequel, please ask on
|
28
|
-
sequel-talk Google Group.
|
27
|
+
If you have questions about how to use Sequel, please ask on
|
28
|
+
GitHub Discussions or the sequel-talk Google Group.
|
29
|
+
Only use the the bug tracker to report
|
29
30
|
bugs in Sequel, not to ask for help on using Sequel.
|
30
31
|
|
31
32
|
To check out the source code:
|
@@ -55,9 +56,9 @@ If you have any comments or suggestions please post to the Google group.
|
|
55
56
|
items = DB[:items] # Create a dataset
|
56
57
|
|
57
58
|
# Populate the table
|
58
|
-
items.insert(:
|
59
|
-
items.insert(:
|
60
|
-
items.insert(:
|
59
|
+
items.insert(name: 'abc', price: rand * 100)
|
60
|
+
items.insert(name: 'def', price: rand * 100)
|
61
|
+
items.insert(name: 'ghi', price: rand * 100)
|
61
62
|
|
62
63
|
# Print out the number of records
|
63
64
|
puts "Item count: #{items.count}"
|
@@ -83,7 +84,7 @@ Sequel uses the concept of datasets to retrieve data. A Dataset object encapsula
|
|
83
84
|
|
84
85
|
For example, the following one-liner returns the average GDP for countries in the middle east region:
|
85
86
|
|
86
|
-
DB[:countries].where(:
|
87
|
+
DB[:countries].where(region: 'Middle East').avg(:GDP)
|
87
88
|
|
88
89
|
Which is equivalent to:
|
89
90
|
|
@@ -91,7 +92,7 @@ Which is equivalent to:
|
|
91
92
|
|
92
93
|
Since datasets retrieve records only when needed, they can be stored and later reused. Records are fetched as hashes, and are accessed using an +Enumerable+ interface:
|
93
94
|
|
94
|
-
middle_east = DB[:countries].where(:
|
95
|
+
middle_east = DB[:countries].where(region: 'Middle East')
|
95
96
|
middle_east.order(:name).each{|r| puts r[:name]}
|
96
97
|
|
97
98
|
Sequel also offers convenience methods for extracting data from Datasets, such as an extended +map+ method:
|
@@ -209,12 +210,12 @@ If the dataset is ordered, you can also ask for the last record:
|
|
209
210
|
|
210
211
|
You can also provide a filter when asking for a single record:
|
211
212
|
|
212
|
-
posts.first(:
|
213
|
+
posts.first(id: 1)
|
213
214
|
# SELECT * FROM posts WHERE id = 1 LIMIT 1
|
214
215
|
|
215
216
|
Or retrieve a single value for a specific record:
|
216
217
|
|
217
|
-
posts.where(:
|
218
|
+
posts.where(id: 1).get(:name)
|
218
219
|
# SELECT name FROM posts WHERE id = 1 LIMIT 1
|
219
220
|
|
220
221
|
=== Filtering Records
|
@@ -410,9 +411,9 @@ As with +delete+, +update+ affects all rows in the dataset, so +where+ first,
|
|
410
411
|
+update+ second:
|
411
412
|
|
412
413
|
# DO THIS:
|
413
|
-
posts.where(Sequel[:stamp] < Date.today - 7).update(:
|
414
|
+
posts.where(Sequel[:stamp] < Date.today - 7).update(state: 'archived')
|
414
415
|
# NOT THIS:
|
415
|
-
posts.update(:
|
416
|
+
posts.update(state: 'archived').where(Sequel[:stamp] < Date.today - 7)
|
416
417
|
|
417
418
|
=== Merging records
|
418
419
|
|
@@ -447,7 +448,7 @@ You can wrap a block of code in a database transaction using the <tt>Database#tr
|
|
447
448
|
# BEGIN
|
448
449
|
posts.insert(category: 'ruby', author: 'david')
|
449
450
|
# INSERT
|
450
|
-
posts.where(Sequel[:stamp] < Date.today - 7).update(:
|
451
|
+
posts.where(Sequel[:stamp] < Date.today - 7).update(state: 'archived')
|
451
452
|
# UPDATE
|
452
453
|
end
|
453
454
|
# COMMIT
|
@@ -460,9 +461,9 @@ and not raise an exception outside the block, you can raise the
|
|
460
461
|
|
461
462
|
DB.transaction do
|
462
463
|
# BEGIN
|
463
|
-
posts.insert(:
|
464
|
+
posts.insert(category: 'ruby', author: 'david')
|
464
465
|
# INSERT
|
465
|
-
if posts.where('stamp < ?', Date.today - 7).update(:
|
466
|
+
if posts.where('stamp < ?', Date.today - 7).update(state: 'archived') == 0
|
466
467
|
# UPDATE
|
467
468
|
raise Sequel::Rollback
|
468
469
|
end
|
@@ -705,8 +706,8 @@ You can delete individual records by calling +delete+ or +destroy+. The only dif
|
|
705
706
|
|
706
707
|
Records can also be deleted en-masse by calling <tt>delete</tt> and <tt>destroy</tt> on the model's dataset. As stated above, you can specify filters for the deleted records:
|
707
708
|
|
708
|
-
Post.where(:
|
709
|
-
Post.where(:
|
709
|
+
Post.where(category: 32).delete # => bypasses hooks
|
710
|
+
Post.where(category: 32).destroy # => runs hooks
|
710
711
|
|
711
712
|
Please note that if <tt>destroy</tt> is called, each record is deleted
|
712
713
|
separately, but <tt>delete</tt> deletes all matching records with a single
|
@@ -719,9 +720,9 @@ Associations are used in order to specify relationships between model classes th
|
|
719
720
|
class Post < Sequel::Model
|
720
721
|
many_to_one :author
|
721
722
|
one_to_many :comments
|
722
|
-
one_to_one :first_comment, :
|
723
|
+
one_to_one :first_comment, class: :Comment, order: :id
|
723
724
|
many_to_many :tags
|
724
|
-
one_through_one :first_tag, :
|
725
|
+
one_through_one :first_tag, class: :Tag, order: :name, right_key: :tag_id
|
725
726
|
end
|
726
727
|
|
727
728
|
+many_to_one+ and +one_to_one+ create a getter and setter for each model object:
|
@@ -760,7 +761,7 @@ All associations add a dataset method that can be used to further filter or reor
|
|
760
761
|
Associations can be eagerly loaded via +eager+ and the <tt>:eager</tt> association option. Eager loading is used when loading a group of objects. It loads all associated objects for all of the current objects in one query, instead of using a separate query to get the associated objects for each current object. Eager loading requires that you retrieve all model objects at once via +all+ (instead of individually by +each+). Eager loading can be cascaded, loading association's associated objects.
|
761
762
|
|
762
763
|
class Person < Sequel::Model
|
763
|
-
one_to_many :posts, :
|
764
|
+
one_to_many :posts, eager: [:tags]
|
764
765
|
end
|
765
766
|
|
766
767
|
class Post < Sequel::Model
|
@@ -115,7 +115,7 @@ These two approaches can also be nested, with +eager+ -> +eager_graph+ -> +eager
|
|
115
115
|
|
116
116
|
Or with 2 separate +eager_graph+ queries:
|
117
117
|
|
118
|
-
Artist.eager_graph(:albums).eager_graph_eager([:albums], :
|
118
|
+
Artist.eager_graph(:albums).eager_graph_eager([:albums], tracks: proc{|ds| ds.eager_graph(:lyric)})
|
119
119
|
# 2 Queries:
|
120
120
|
# SELECT artists.id, artists.name, ...
|
121
121
|
# albums.id AS albums_id, albums.name AS albums_name, ...
|
@@ -238,9 +238,9 @@ have the following associations
|
|
238
238
|
|
239
239
|
and the following three albums in the database:
|
240
240
|
|
241
|
-
album1 = Album.create(:
|
242
|
-
album2 = Album.create(:
|
243
|
-
album3 = Album.create(:
|
241
|
+
album1 = Album.create(artist_id: 3) # id: 1
|
242
|
+
album2 = Album.create(artist_id: 3) # id: 2
|
243
|
+
album3 = Album.create(artist_id: 2) # id: 3
|
244
244
|
|
245
245
|
If you try to eager load this dataset:
|
246
246
|
|
@@ -256,7 +256,7 @@ the are both in the array related to that key. album3 has a different
|
|
256
256
|
artist_id, so it is in a different array. Eager loading of artists is
|
257
257
|
done by looking for any artist having one of the keys in the hash:
|
258
258
|
|
259
|
-
artists = Artist.where(:
|
259
|
+
artists = Artist.where(id: id_map.keys).all
|
260
260
|
|
261
261
|
When the artists are retrieved, you can iterate over them, find entries
|
262
262
|
with matching keys, and manually associate them to the albums:
|
@@ -281,7 +281,7 @@ case each array only has a single object, because id is the primary key). So wh
|
|
281
281
|
looking for tracks to eagerly load, you only need to look for ones that have an
|
282
282
|
album_id with one of the keys in the hash:
|
283
283
|
|
284
|
-
tracks = Track.where(:
|
284
|
+
tracks = Track.where(album_id: id_map.keys).all
|
285
285
|
|
286
286
|
When the tracks are retrieved, you can iterate over them, find entries with matching
|
287
287
|
keys, and manually associate them to the albums:
|
@@ -314,10 +314,10 @@ artist or tracks method on the album will not do another database lookup.
|
|
314
314
|
|
315
315
|
So putting everything together, the artist eager loader looks like:
|
316
316
|
|
317
|
-
Album.many_to_one :artist, :
|
317
|
+
Album.many_to_one :artist, eager_loader: (proc do |eo_opts|
|
318
318
|
eo_opts[:rows].each{|album| album.associations[:artist] = nil}
|
319
319
|
id_map = eo_opts[:id_map]
|
320
|
-
Artist.where(:
|
320
|
+
Artist.where(id: id_map.keys).all do |artist|
|
321
321
|
if albums = id_map[artist.id]
|
322
322
|
albums.each do |album|
|
323
323
|
album.associations[:artist] = artist
|
@@ -328,10 +328,10 @@ So putting everything together, the artist eager loader looks like:
|
|
328
328
|
|
329
329
|
and the tracks eager loader looks like:
|
330
330
|
|
331
|
-
Album.one_to_many :tracks, :
|
331
|
+
Album.one_to_many :tracks, eager_loader: (proc do |eo_opts|
|
332
332
|
eo_opts[:rows].each{|album| album.associations[:tracks] = []}
|
333
333
|
id_map = eo_opts[:id_map]
|
334
|
-
Track.where(:
|
334
|
+
Track.where(album_id: id_map.keys).all do |track|
|
335
335
|
if albums = id_map[track.album_id]
|
336
336
|
albums.each do |album|
|
337
337
|
album.associations[:tracks] << track
|
@@ -405,7 +405,7 @@ the window function strategy:
|
|
405
405
|
|
406
406
|
Artist.one_to_many :first_10_albums, class: :Album, order: :release_date, limit: 10,
|
407
407
|
eager_limit_strategy: :window_function
|
408
|
-
Artist.where(:
|
408
|
+
Artist.where(id: [1,2]).eager(:first_10_albums).all
|
409
409
|
# SELECT * FROM (
|
410
410
|
# SELECT *, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
|
411
411
|
# FROM albums
|
@@ -483,7 +483,7 @@ function:
|
|
483
483
|
The :correlated_subquery approach JOINs to a nested subquery using a correlated
|
484
484
|
subquery:
|
485
485
|
|
486
|
-
Artist.eager_graph_with_options(:first_10_albums, :
|
486
|
+
Artist.eager_graph_with_options(:first_10_albums, limit_strategy: :correlated_subquery).all
|
487
487
|
# SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
|
488
488
|
# first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
|
489
489
|
# first_10_albums.release_date
|
@@ -853,7 +853,7 @@ associated tickets.
|
|
853
853
|
class Project < Sequel::Model
|
854
854
|
one_to_many :tickets
|
855
855
|
many_to_one :ticket_hours, read_only: true, key: :id,
|
856
|
-
dataset: proc{Ticket.where(:
|
856
|
+
dataset: proc{Ticket.where(project_id: id).select{sum(hours).as(hours)}},
|
857
857
|
eager_loader: (lambda do |eo|
|
858
858
|
eo[:rows].each{|p| p.associations[:ticket_hours] = nil}
|
859
859
|
Ticket.where(project_id: eo[:id_map].keys).
|
data/doc/association_basics.rdoc
CHANGED
@@ -320,11 +320,11 @@ Associations are cached after being retrieved:
|
|
320
320
|
@album.artists # Cached - No Database Query
|
321
321
|
|
322
322
|
You can choose to ignore the cached versions and do a database query to
|
323
|
-
retrieve results by passing a :
|
323
|
+
retrieve results by passing a <tt>reload: true</tt> option to the association method:
|
324
324
|
|
325
325
|
@album.artists # Not cached - Database Query
|
326
326
|
@album.artists # Cached - No Database Query
|
327
|
-
@album.artists(:
|
327
|
+
@album.artists(reload: true) # Ignore cache - Database Query
|
328
328
|
|
329
329
|
If you reload/refresh the object, it will automatically clear the
|
330
330
|
associations cache for the object:
|
@@ -342,6 +342,12 @@ instance method:
|
|
342
342
|
@album.artists # [<Artist ...>, ...]
|
343
343
|
@album.associations[:artists] # [<Artist ...>, ...]
|
344
344
|
|
345
|
+
=== Code Reloading
|
346
|
+
|
347
|
+
When declaring associations, Sequel caches association metadata in the association reflection. If you're doing any code reloading that doesn't involve restarting the related process, you should disable caching of the association reflection, to avoid stale model classes still being referenced after reloading:
|
348
|
+
|
349
|
+
Sequel::Model.cache_associations = false
|
350
|
+
|
345
351
|
== Dataset Method
|
346
352
|
|
347
353
|
In addition to the above methods, associations also add an instance method
|
@@ -532,14 +538,14 @@ Which could be created using the following Sequel code:
|
|
532
538
|
DB.create_table(:artists) do
|
533
539
|
# Primary key must be set explicitly
|
534
540
|
primary_key :id
|
535
|
-
String :name, :
|
541
|
+
String :name, null: false, unique: true
|
536
542
|
end
|
537
543
|
DB.create_table(:albums) do
|
538
544
|
primary_key :id
|
539
545
|
# Table that foreign key references needs to be set explicitly
|
540
546
|
# for a database foreign key reference to be created.
|
541
|
-
foreign_key :artist_id, :artists, :
|
542
|
-
String :name, :
|
547
|
+
foreign_key :artist_id, :artists, null: false
|
548
|
+
String :name, null: false, unique: true
|
543
549
|
end
|
544
550
|
|
545
551
|
If you already had a schema such as:
|
@@ -552,7 +558,7 @@ If you already had a schema such as:
|
|
552
558
|
Then you just need to add the column:
|
553
559
|
|
554
560
|
DB.alter_table(:albums) do
|
555
|
-
add_foreign_key :artist_id, :artists, :
|
561
|
+
add_foreign_key :artist_id, :artists, null: false
|
556
562
|
end
|
557
563
|
|
558
564
|
=== many_to_many
|
@@ -588,11 +594,11 @@ wanted to add an albums_artists join table to create the following schema:
|
|
588
594
|
|
589
595
|
You could use the following Sequel code:
|
590
596
|
|
591
|
-
DB.create_join_table(:
|
597
|
+
DB.create_join_table(album_id: :albums, artist_id: :artists)
|
592
598
|
# or
|
593
599
|
DB.create_table(:albums_artists) do
|
594
|
-
foreign_key :album_id, :albums, :
|
595
|
-
foreign_key :artist_id, :artists, :
|
600
|
+
foreign_key :album_id, :albums, null: false
|
601
|
+
foreign_key :artist_id, :artists, null: false
|
596
602
|
primary_key [:album_id, :artist_id]
|
597
603
|
index [:artist_id, :album_id]
|
598
604
|
end
|
@@ -713,7 +719,7 @@ saving the passed in (or newly created) object. However, to avoid
|
|
713
719
|
silent failures of these methods, they explicitly raise exceptions
|
714
720
|
even when raise_on_save_failure is false for the associated model.
|
715
721
|
You can disable this behavior (i.e. return nil instead of raising
|
716
|
-
exceptions on a save failure) by setting the <tt
|
722
|
+
exceptions on a save failure) by setting the <tt>raise_on_save_failure: false</tt>
|
717
723
|
option for the association.
|
718
724
|
|
719
725
|
=== remove_<i>association</i>(object_to_disassociate) (e.g. remove_album) [+one_to_many+ and +many_to_many+]
|
@@ -981,7 +987,7 @@ If you do not use a hash or array of two element arrays, you should use the
|
|
981
987
|
:graph_conditions, :graph_only_conditions, or :graph_block option or you will not
|
982
988
|
be able to use eager_graph or association_join with the association.
|
983
989
|
|
984
|
-
Artist.one_to_many :good_albums, class: :Album, conditions: {:
|
990
|
+
Artist.one_to_many :good_albums, class: :Album, conditions: {good: true}
|
985
991
|
@artist.good_albums
|
986
992
|
# SELECT * FROM albums WHERE ((artist_id = 1) AND (good IS TRUE))
|
987
993
|
|
@@ -1162,7 +1168,7 @@ join of the join table and the associated table, whereas this option just
|
|
1162
1168
|
applies to the join table. It can be used to make sure that filters are used
|
1163
1169
|
when deleting.
|
1164
1170
|
|
1165
|
-
Artist.many_to_many :lead_guitar_albums, class: :Album, :
|
1171
|
+
Artist.many_to_many :lead_guitar_albums, class: :Album, join_table_block: (lambda do |ds|
|
1166
1172
|
ds.where(instrument_id: 5)
|
1167
1173
|
end)
|
1168
1174
|
|
@@ -1177,7 +1183,7 @@ access to the join table.
|
|
1177
1183
|
For example, if the Album class uses a different Sequel::Database than the Artist
|
1178
1184
|
class, and the join table is in the database that the Artist class uses:
|
1179
1185
|
|
1180
|
-
Artist.many_to_many :lead_guitar_albums, class: :Album, :
|
1186
|
+
Artist.many_to_many :lead_guitar_albums, class: :Album, join_table_db: Artist.db
|
1181
1187
|
|
1182
1188
|
This option also affects the add/remove/remove_all methods, by changing
|
1183
1189
|
which database is used for inserts/deletes from the join table (add/remove/remove_all
|
@@ -1470,7 +1476,7 @@ at least the following keys:
|
|
1470
1476
|
Example:
|
1471
1477
|
|
1472
1478
|
Artist.one_to_many :self_title_albums, class: :Album,
|
1473
|
-
:
|
1479
|
+
eager_grapher: (lambda do |eo|
|
1474
1480
|
eo[:self].graph(:albums, {artist_id: :id, name: :name},
|
1475
1481
|
table_alias: eo[:table_alias], implicit_qualifier: eo[:implicit_qualifier])
|
1476
1482
|
end)
|
@@ -1727,7 +1733,7 @@ support joins.
|
|
1727
1733
|
If set to false, you cannot use the association when filtering.
|
1728
1734
|
|
1729
1735
|
Artist.one_to_many :albums, allow_filtering_by: false
|
1730
|
-
Artist.where(:
|
1736
|
+
Artist.where(albums: Album.where(name: 'A')).all # Raises Sequel::Error
|
1731
1737
|
|
1732
1738
|
This is useful if such filtering cannot work, such as when a subquery cannot
|
1733
1739
|
be used because the necessary tables are not in the same database.
|
data/doc/cheat_sheet.rdoc
CHANGED
@@ -54,8 +54,8 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
54
54
|
== Update/Delete rows
|
55
55
|
|
56
56
|
dataset.exclude(:active).delete
|
57
|
-
dataset.where{price < 100}.update(:
|
58
|
-
dataset.where(:active).update(:
|
57
|
+
dataset.where{price < 100}.update(active: true)
|
58
|
+
dataset.where(:active).update(price: Sequel[:price] * 0.90)
|
59
59
|
|
60
60
|
= Merge rows
|
61
61
|
|
@@ -174,7 +174,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
174
174
|
String :name, unique: true, null: false
|
175
175
|
TrueClass :active, default: true
|
176
176
|
foreign_key :category_id, :categories
|
177
|
-
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP, :
|
177
|
+
DateTime :created_at, default: Sequel::CURRENT_TIMESTAMP, index: true
|
178
178
|
|
179
179
|
index [:category_id, :active]
|
180
180
|
end
|
data/doc/model_hooks.rdoc
CHANGED
data/doc/object_model.rdoc
CHANGED
@@ -36,7 +36,7 @@ schema modification,
|
|
36
36
|
and transactions:
|
37
37
|
|
38
38
|
DB.transaction do
|
39
|
-
DB[:table].insert(:
|
39
|
+
DB[:table].insert(column: value)
|
40
40
|
end
|
41
41
|
|
42
42
|
Sequel::Database#literal can be used to take any object that Sequel handles
|
@@ -468,7 +468,7 @@ objects:
|
|
468
468
|
Sequel.lit(['', ' = '], :a, 1)
|
469
469
|
|
470
470
|
'? = ?'.lit(:a, 1) # core_extensions extension
|
471
|
-
':b = :v'.lit(:
|
471
|
+
':b = :v'.lit(b: :a, v: 1) # core_extensions extension
|
472
472
|
|
473
473
|
=== Sequel::SQL::OrderedExpression
|
474
474
|
|
@@ -482,20 +482,20 @@ it ascending or descending:
|
|
482
482
|
Additionally, they take an options hash, which can be used to specify how nulls
|
483
483
|
can be sorted:
|
484
484
|
|
485
|
-
Sequel::SQL::OrderedExpression.new(:a, true, :
|
486
|
-
Sequel::SQL::OrderedExpression.new(:a, false, :
|
485
|
+
Sequel::SQL::OrderedExpression.new(:a, true, nulls: :first) # "a" DESC NULLS FIRST
|
486
|
+
Sequel::SQL::OrderedExpression.new(:a, false, nulls: :last) # "a" ASC NULLS LAST
|
487
487
|
|
488
488
|
The following shortcuts exist for creating Sequel::SQL::OrderedExpression objects:
|
489
489
|
|
490
490
|
Sequel.asc(:a)
|
491
491
|
Sequel.desc(:a)
|
492
|
-
Sequel.asc(:a, :
|
493
|
-
Sequel.desc(:a, :
|
492
|
+
Sequel.asc(:a, nulls: :first)
|
493
|
+
Sequel.desc(:a, nulls: :last)
|
494
494
|
|
495
495
|
:a.asc # core_extensions extension
|
496
496
|
:a.desc # core_extensions extension
|
497
|
-
:a.asc(:
|
498
|
-
:a.desc(:
|
497
|
+
:a.asc(nulls: :first) # core_extensions extension
|
498
|
+
:a.desc(nulls: :last) # core_extensions extension
|
499
499
|
|
500
500
|
=== Sequel::SQL::Subscript
|
501
501
|
|
data/doc/opening_databases.rdoc
CHANGED
@@ -268,7 +268,7 @@ The following additional options are supported:
|
|
268
268
|
to MySQL.
|
269
269
|
:socket :: Can be used to specify a Unix socket file to connect to instead of a TCP host and port.
|
270
270
|
:sql_mode :: Set the sql_mode(s) for a given connection. Can be single symbol or string,
|
271
|
-
or an array of symbols or strings (e.g. <tt
|
271
|
+
or an array of symbols or strings (e.g. <tt>sql_mode: [:no_zero_date, :pipes_as_concat]</tt>).
|
272
272
|
:timeout :: Sets the wait_timeout for the connection, defaults to 1 month.
|
273
273
|
:read_timeout :: Set the timeout in seconds for reading back results to a query.
|
274
274
|
:connect_timeout :: Set the timeout in seconds before a connection attempt is abandoned
|
@@ -290,13 +290,13 @@ mysql, such as the jdbc/mysql adapter).
|
|
290
290
|
The ODBC adapter allows you to connect to any database with the appropriate ODBC drivers installed.
|
291
291
|
The :database option given ODBC database should be the DSN (Descriptive Service Name) from the ODBC configuration.
|
292
292
|
|
293
|
-
Sequel.odbc('mydb', :
|
293
|
+
Sequel.odbc('mydb', user: "user", password: "password")
|
294
294
|
|
295
295
|
The :host and :port options are not respected. The following additional options are supported:
|
296
296
|
|
297
297
|
:db_type :: Can be specified as 'mssql', 'progress', or 'db2' to use SQL syntax specific to those databases.
|
298
298
|
:drvconnect :: Can be given an ODBC connection string, and will use ODBC::Database#drvconnect to
|
299
|
-
do the connection. Typical usage would be: <tt>Sequel.odbc(:
|
299
|
+
do the connection. Typical usage would be: <tt>Sequel.odbc(drvconnect: 'driver={...};...')</tt>
|
300
300
|
|
301
301
|
=== oracle
|
302
302
|
|
@@ -345,7 +345,7 @@ The following additional options are supported:
|
|
345
345
|
:search_path :: Set to the schema search_path. This can either be a single string containing the schemas
|
346
346
|
separated by commas (for use via a URL: <tt>postgres:///?search_path=schema1,schema2</tt>), or it
|
347
347
|
can be an array of strings (for use via an option:
|
348
|
-
<tt>Sequel.postgres(:
|
348
|
+
<tt>Sequel.postgres(search_path: ['schema1', 'schema2'])</tt>).
|
349
349
|
:use_iso_date_format :: This can be set to false to not force the ISO date format. Sequel forces
|
350
350
|
it by default to allow for an optimization.
|
351
351
|
|
data/doc/postgresql.rdoc
CHANGED
@@ -295,16 +295,16 @@ option to +foreign_key_list+:
|
|
295
295
|
primary_key :id
|
296
296
|
Integer :i
|
297
297
|
Integer :j
|
298
|
-
foreign_key :a_id, :a, :
|
298
|
+
foreign_key :a_id, :a, foreign_key_constraint_name: :a_a
|
299
299
|
unique [:i, :j]
|
300
300
|
end
|
301
301
|
DB.create_table!(:b) do
|
302
|
-
foreign_key :a_id, :a, :
|
302
|
+
foreign_key :a_id, :a, foreign_key_constraint_name: :a_a
|
303
303
|
Integer :c
|
304
304
|
Integer :d
|
305
|
-
foreign_key [:c, :d], :a, :
|
305
|
+
foreign_key [:c, :d], :a, key: [:j, :i], name: :a_c_d
|
306
306
|
end
|
307
|
-
DB.foreign_key_list(:a, :
|
307
|
+
DB.foreign_key_list(:a, reverse: true)
|
308
308
|
# => [
|
309
309
|
# {:name=>:a_a, :columns=>[:a_id], :key=>[:id], :on_update=>:no_action, :on_delete=>:no_action, :deferrable=>false, :table=>:a, :schema=>:public},
|
310
310
|
# {:name=>:a_a, :columns=>[:a_id], :key=>[:id], :on_update=>:no_action, :on_delete=>:no_action, :deferrable=>false, :table=>:b, :schema=>:public},
|
@@ -413,12 +413,12 @@ syntax:
|
|
413
413
|
|
414
414
|
DB.create_table(:table){primary_key :id}
|
415
415
|
# Ignore the given value for id, using the identity's sequence value.
|
416
|
-
DB[:table].overriding_user_value.insert(:
|
416
|
+
DB[:table].overriding_user_value.insert(id: 1)
|
417
417
|
|
418
|
-
DB.create_table(:table){primary_key :id, :
|
418
|
+
DB.create_table(:table){primary_key :id, identity: :always}
|
419
419
|
# Force the use of the given value for id, because otherwise the insert will
|
420
420
|
# raise an error, since GENERATED ALWAYS was used when creating the column.
|
421
|
-
DB[:table].overriding_system_value.insert(:
|
421
|
+
DB[:table].overriding_system_value.insert(id: 1)
|
422
422
|
|
423
423
|
=== Distinct On Specific Columns
|
424
424
|
|
@@ -561,7 +561,7 @@ such as the related table and column or constraint.
|
|
561
561
|
|
562
562
|
DB.create_table(:test1){primary_key :id}
|
563
563
|
DB.create_table(:test2){primary_key :id; foreign_key :test1_id, :test1}
|
564
|
-
DB[:test2].insert(:
|
564
|
+
DB[:test2].insert(test1_id: 1) rescue DB.error_info($!)
|
565
565
|
# => {
|
566
566
|
# :schema=>"public",
|
567
567
|
# :table=>"test2",
|
data/doc/querying.rdoc
CHANGED
@@ -715,7 +715,7 @@ aggregation:
|
|
715
715
|
|
716
716
|
Album.select_group(:artist_id).select_append{sum(num_tracks).as(tracks)}
|
717
717
|
# SELECT artist_id, sum(num_tracks) AS tracks FROM albums GROUP BY artist_id
|
718
|
-
|
718
|
+
|
719
719
|
== Having
|
720
720
|
|
721
721
|
The SQL HAVING clause is similar to the WHERE clause, except that
|