sequel 4.13.0 → 4.14.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.
- checksums.yaml +4 -4
- data/CHANGELOG +24 -0
- data/doc/active_record.rdoc +4 -4
- data/doc/advanced_associations.rdoc +2 -2
- data/doc/association_basics.rdoc +11 -11
- data/doc/cheat_sheet.rdoc +7 -7
- data/doc/core_extensions.rdoc +1 -1
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/extensions.rdoc +1 -1
- data/doc/migration.rdoc +3 -3
- data/doc/model_hooks.rdoc +1 -1
- data/doc/opening_databases.rdoc +4 -0
- data/doc/postgresql.rdoc +2 -2
- data/doc/prepared_statements.rdoc +1 -1
- data/doc/querying.rdoc +31 -31
- data/doc/release_notes/4.13.0.txt +1 -1
- data/doc/release_notes/4.14.0.txt +68 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/sharding.rdoc +2 -2
- data/doc/sql.rdoc +1 -1
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/jdbc/jtds.rb +4 -0
- data/lib/sequel/adapters/mysql.rb +18 -18
- data/lib/sequel/adapters/mysql2.rb +7 -7
- data/lib/sequel/adapters/shared/mysql.rb +15 -5
- data/lib/sequel/adapters/shared/postgres.rb +71 -58
- data/lib/sequel/adapters/shared/sqlite.rb +2 -2
- data/lib/sequel/ast_transformer.rb +1 -1
- data/lib/sequel/connection_pool/sharded_single.rb +8 -8
- data/lib/sequel/connection_pool/sharded_threaded.rb +8 -8
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +12 -0
- data/lib/sequel/database/schema_methods.rb +8 -7
- data/lib/sequel/database/transactions.rb +1 -2
- data/lib/sequel/dataset/actions.rb +4 -4
- data/lib/sequel/dataset/graph.rb +4 -0
- data/lib/sequel/dataset/query.rb +18 -18
- data/lib/sequel/dataset/sql.rb +3 -3
- data/lib/sequel/extensions/_pretty_table.rb +1 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +3 -2
- data/lib/sequel/extensions/columns_introspection.rb +1 -0
- data/lib/sequel/extensions/connection_validator.rb +1 -0
- data/lib/sequel/extensions/constraint_validations.rb +1 -0
- data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -0
- data/lib/sequel/extensions/dataset_source_alias.rb +1 -0
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +1 -0
- data/lib/sequel/extensions/error_sql.rb +1 -0
- data/lib/sequel/extensions/eval_inspect.rb +1 -0
- data/lib/sequel/extensions/filter_having.rb +1 -0
- data/lib/sequel/extensions/from_block.rb +1 -0
- data/lib/sequel/extensions/graph_each.rb +1 -0
- data/lib/sequel/extensions/hash_aliases.rb +1 -0
- data/lib/sequel/extensions/looser_typecasting.rb +1 -0
- data/lib/sequel/extensions/meta_def.rb +1 -0
- data/lib/sequel/extensions/migration.rb +1 -0
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +1 -0
- data/lib/sequel/extensions/named_timezones.rb +1 -0
- data/lib/sequel/extensions/null_dataset.rb +1 -0
- data/lib/sequel/extensions/pagination.rb +1 -0
- data/lib/sequel/extensions/pg_array.rb +2 -2
- data/lib/sequel/extensions/pg_array_ops.rb +1 -0
- data/lib/sequel/extensions/pg_enum.rb +1 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +1 -0
- data/lib/sequel/extensions/pg_json_ops.rb +1 -0
- data/lib/sequel/extensions/pg_loose_count.rb +1 -0
- data/lib/sequel/extensions/pg_range_ops.rb +1 -0
- data/lib/sequel/extensions/pg_row_ops.rb +1 -0
- data/lib/sequel/extensions/pg_static_cache_updater.rb +1 -0
- data/lib/sequel/extensions/pretty_table.rb +1 -0
- data/lib/sequel/extensions/query.rb +1 -0
- data/lib/sequel/extensions/query_literals.rb +1 -0
- data/lib/sequel/extensions/schema_caching.rb +1 -0
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/extensions/select_remove.rb +1 -0
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +1 -0
- data/lib/sequel/extensions/server_block.rb +1 -0
- data/lib/sequel/extensions/set_overrides.rb +1 -0
- data/lib/sequel/extensions/split_array_nil.rb +1 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -0
- data/lib/sequel/extensions/to_dot.rb +1 -0
- data/lib/sequel/model/associations.rb +5 -5
- data/lib/sequel/model/base.rb +3 -3
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/caching.rb +8 -3
- data/lib/sequel/plugins/class_table_inheritance.rb +20 -11
- data/lib/sequel/plugins/composition.rb +18 -18
- data/lib/sequel/plugins/json_serializer.rb +3 -3
- data/lib/sequel/plugins/lazy_attributes.rb +23 -9
- data/lib/sequel/plugins/many_through_many.rb +21 -21
- data/lib/sequel/plugins/nested_attributes.rb +7 -3
- data/lib/sequel/plugins/pg_row.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +13 -13
- data/lib/sequel/plugins/sharding.rb +6 -6
- data/lib/sequel/plugins/timestamps.rb +4 -4
- data/lib/sequel/plugins/touch.rb +7 -7
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +36 -36
- data/lib/sequel/plugins/validation_helpers.rb +3 -4
- data/lib/sequel/plugins/xml_serializer.rb +29 -29
- data/lib/sequel/sql.rb +22 -11
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +10 -0
- data/spec/core/database_spec.rb +3 -4
- data/spec/core/dataset_spec.rb +16 -1
- data/spec/core/expression_filters_spec.rb +12 -0
- data/spec/core/object_graph_spec.rb +5 -0
- data/spec/core/placeholder_literalizer_spec.rb +8 -0
- data/spec/extensions/caching_spec.rb +18 -0
- data/spec/extensions/class_table_inheritance_spec.rb +34 -0
- data/spec/extensions/many_through_many_spec.rb +4 -0
- data/spec/extensions/nested_attributes_spec.rb +59 -4
- data/spec/extensions/pg_array_associations_spec.rb +5 -0
- data/spec/extensions/single_table_inheritance_spec.rb +23 -1
- data/spec/integration/plugin_test.rb +17 -0
- data/spec/model/eager_loading_spec.rb +8 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b817d0bad633a1df7f0a331264d8ce67e0a2c40
|
|
4
|
+
data.tar.gz: e46c816ef87e537d58a982e876011f14ab42c6a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d88876ee4814e172d6ed262b14a87f253e5864d03f8f3167420e10d6d3a873625a1fb797b406bc2438a28d7df846535f9af38f2dc90cc57c6167d6c333723345
|
|
7
|
+
data.tar.gz: c0a61d9260147f6fa4d458242b7ebb6139eacee710e84eb1361d9527a15dea1ecbad377893b3a0dede352af92061308c4e5fd76d4741df60cdc1cf0f3819ddc3
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
=== 4.14.0 (2014-09-01)
|
|
2
|
+
|
|
3
|
+
* Raise original exception if there is an exception raised when rolling back transaction/savepoint (jeremyevans) (#875)
|
|
4
|
+
|
|
5
|
+
* Allow delayed evaluation blocks to take dataset as an argument (jeremyevans)
|
|
6
|
+
|
|
7
|
+
* Allow more types as filter expressions, only specifically disallow Numeric/String expressions (jeremyevans)
|
|
8
|
+
|
|
9
|
+
* Remove objects from cached association array at time of nested_attributes call instead of waiting until save (jeremyevans)
|
|
10
|
+
|
|
11
|
+
* Handle composite primary keys when working around validation issues for one_to_(one|many) associations in nested_attributes plugin (jeremyevans) (#870)
|
|
12
|
+
|
|
13
|
+
* Recognize additional disconnect error in jdbc/jtds adapter (jeremyevans)
|
|
14
|
+
|
|
15
|
+
* Have association_join work with existing model selections (jeremyevans)
|
|
16
|
+
|
|
17
|
+
* Fix regression in class_table_inheritance plugin when lazily loading column in middle table (jeremyevans) (#862)
|
|
18
|
+
|
|
19
|
+
* Add cache_key_prefix method to caching plugin, which can be overridden for custom handling (pete) (#861)
|
|
20
|
+
|
|
21
|
+
* Add :when option to PostgreSQL create_trigger method, for adding a filter to the trigger (aschrab) (#860)
|
|
22
|
+
|
|
23
|
+
* Recognize an additional serialization failure on PostgreSQL (tmtm) (#857)
|
|
24
|
+
|
|
1
25
|
=== 4.13.0 (2014-08-01)
|
|
2
26
|
|
|
3
27
|
* Use copy constructors instead of overriding Model#dup and #clone (ged, jeremyevans) (#852)
|
data/doc/active_record.rdoc
CHANGED
|
@@ -327,8 +327,8 @@ ActiveRecord 2 tries to guess whether to use preloading or JOINs for eager loadi
|
|
|
327
327
|
|
|
328
328
|
With either way of eager loading, you must call +all+ to retrieve all records at once. You cannot use +each+, +map+, or one of the other Enumerable methods. Just like +each+, +all+ takes a block that iterates over the records:
|
|
329
329
|
|
|
330
|
-
Artist.eager(:albums=>[:tags, :tracks]).each{|a|
|
|
331
|
-
Artist.eager(:albums=>[:tags, :tracks]).all{|a|
|
|
330
|
+
Artist.eager(:albums=>[:tags, :tracks]).each{|a| } # No cookie
|
|
331
|
+
Artist.eager(:albums=>[:tags, :tracks]).all{|a| } # Cookie
|
|
332
332
|
|
|
333
333
|
Like ActiveRecord, Sequel supports cascading of eager loading for both methods of eager loading.
|
|
334
334
|
|
|
@@ -495,7 +495,7 @@ Note that +test_connection+ will return true if a connection can be made, but wi
|
|
|
495
495
|
Sequel only uses connections for the minimum amount of time necessary, checking them out to do a query, and returning them as soon as the query finishes. If you do want direct access to the connection object:
|
|
496
496
|
|
|
497
497
|
Sequel::Model.db.synchronize do |connection|
|
|
498
|
-
...
|
|
498
|
+
# ...
|
|
499
499
|
end
|
|
500
500
|
|
|
501
501
|
Note that the connection is yielded to the block, and the block ensures it is returned to the pool. Sequel doesn't have a method that returns a connection, since that would check it out with no ability to ensure it is returned to the pool.
|
|
@@ -532,7 +532,7 @@ If you really want to destroy all rows in the table,call +destroy+ on the Model'
|
|
|
532
532
|
|
|
533
533
|
If you want to use a specific <tt>Sequel::Database</tt> object, you can use <tt>db=</tt>:
|
|
534
534
|
|
|
535
|
-
BACKUP_DB = Sequel.connect(
|
|
535
|
+
BACKUP_DB = Sequel.connect('postgres://...')
|
|
536
536
|
Album.db = BACKUP_DB
|
|
537
537
|
|
|
538
538
|
If you want a specific dataset in that database, you can use +set_dataset+ or <tt>dataset=</tt>:
|
|
@@ -194,7 +194,7 @@ artist or tracks method on the album will not do another database lookup.
|
|
|
194
194
|
|
|
195
195
|
So putting everything together, the artist eager loader looks like:
|
|
196
196
|
|
|
197
|
-
:eager_loader=>(proc do |eo_opts|
|
|
197
|
+
Album.many_to_one :artist, :eager_loader=>(proc do |eo_opts|
|
|
198
198
|
eo_opts[:rows].each{|album| album.associations[:artist] = nil}
|
|
199
199
|
id_map = eo_opts[:id_map]
|
|
200
200
|
Artist.where(:id=>id_map.keys).all do |artist|
|
|
@@ -208,7 +208,7 @@ So putting everything together, the artist eager loader looks like:
|
|
|
208
208
|
|
|
209
209
|
and the tracks eager loader looks like:
|
|
210
210
|
|
|
211
|
-
:eager_loader=>(proc do |eo_opts|
|
|
211
|
+
Album.one_to_many :tracks, :eager_loader=>(proc do |eo_opts|
|
|
212
212
|
eo_opts[:rows].each{|album| album.associations[:tracks] = []}
|
|
213
213
|
id_map = eo_opts[:id_map]
|
|
214
214
|
Track.where(:id=>id_map.keys).all do |tracks|
|
data/doc/association_basics.rdoc
CHANGED
|
@@ -697,7 +697,7 @@ and a new associated object will be created from them:
|
|
|
697
697
|
|
|
698
698
|
@artist.add_album(:name=>'RF') # creates Album object
|
|
699
699
|
|
|
700
|
-
The add_<i>association</i> method returns the
|
|
700
|
+
The add_<i>association</i> method returns the new associated object:
|
|
701
701
|
|
|
702
702
|
@album = @artist.add_album(:name=>'RF')
|
|
703
703
|
|
|
@@ -817,7 +817,7 @@ artist using the artist= method, this approach may perform better.
|
|
|
817
817
|
|
|
818
818
|
=== \_add_<i>association</i> (:adder option)
|
|
819
819
|
|
|
820
|
-
Continuing with the same example, here's how would
|
|
820
|
+
Continuing with the same example, here's how you would handle the same case if
|
|
821
821
|
you also wanted to handle the Artist#add_album method:
|
|
822
822
|
|
|
823
823
|
class Artist < Sequel::Model
|
|
@@ -832,7 +832,7 @@ you also wanted to handle the Artist#add_album method:
|
|
|
832
832
|
|
|
833
833
|
=== \_remove_<i>association</i> (:remover option)
|
|
834
834
|
|
|
835
|
-
Continuing with the same example, here's how would
|
|
835
|
+
Continuing with the same example, here's how you would handle the same case if
|
|
836
836
|
you also wanted to handle the Artist#remove_album method:
|
|
837
837
|
|
|
838
838
|
class Artist < Sequel::Model
|
|
@@ -847,7 +847,7 @@ you also wanted to handle the Artist#remove_album method:
|
|
|
847
847
|
|
|
848
848
|
=== \_remove_all_<i>association</i> (:clearer option)
|
|
849
849
|
|
|
850
|
-
Continuing with the same example, here's how would
|
|
850
|
+
Continuing with the same example, here's how you would handle the same case if
|
|
851
851
|
you also wanted to handle the Artist#remove_all_albums method:
|
|
852
852
|
|
|
853
853
|
class Artist < Sequel::Model
|
|
@@ -909,10 +909,10 @@ or a String:
|
|
|
909
909
|
|
|
910
910
|
==== :key
|
|
911
911
|
|
|
912
|
-
For +many_to_one+ associations, is the foreign_key in current model's
|
|
913
|
-
that references associated model's primary key
|
|
914
|
-
:<i>association</i>_id. Can use an array of symbols for a
|
|
915
|
-
association.
|
|
912
|
+
For +many_to_one+ associations, this is the foreign_key in the current model's
|
|
913
|
+
table that references the associated model's primary key as a symbol.
|
|
914
|
+
Defaults to :<i>association</i>_id. Can use an array of symbols for a
|
|
915
|
+
composite key association.
|
|
916
916
|
|
|
917
917
|
Album.many_to_one :artist # :key=>:artist_id
|
|
918
918
|
|
|
@@ -1583,7 +1583,7 @@ using the association setter method.
|
|
|
1583
1583
|
|
|
1584
1584
|
==== :adder [*_to_many associations]
|
|
1585
1585
|
|
|
1586
|
-
Continuing with the same example, here's how would
|
|
1586
|
+
Continuing with the same example, here's how you would handle the same case if
|
|
1587
1587
|
you also wanted to handle the Artist#add_album method:
|
|
1588
1588
|
|
|
1589
1589
|
class Artist < Sequel::Model
|
|
@@ -1594,7 +1594,7 @@ you also wanted to handle the Artist#add_album method:
|
|
|
1594
1594
|
|
|
1595
1595
|
==== :remover [*_to_many associations]
|
|
1596
1596
|
|
|
1597
|
-
Continuing with the same example, here's how would
|
|
1597
|
+
Continuing with the same example, here's how you would handle the same case if
|
|
1598
1598
|
you also wanted to handle the Artist#remove_album method:
|
|
1599
1599
|
|
|
1600
1600
|
class Artist < Sequel::Model
|
|
@@ -1605,7 +1605,7 @@ you also wanted to handle the Artist#remove_album method:
|
|
|
1605
1605
|
|
|
1606
1606
|
==== :clearer [*_to_many associations]
|
|
1607
1607
|
|
|
1608
|
-
Continuing with the same example, here's how would
|
|
1608
|
+
Continuing with the same example, here's how you would handle the same case if
|
|
1609
1609
|
you also wanted to handle the Artist#remove_all_albums method:
|
|
1610
1610
|
|
|
1611
1611
|
class Artist < Sequel::Model
|
data/doc/cheat_sheet.rdoc
CHANGED
|
@@ -20,7 +20,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
|
20
20
|
require 'logger'
|
|
21
21
|
DB = Sequel.sqlite '', :loggers => [Logger.new($stdout)]
|
|
22
22
|
# or
|
|
23
|
-
DB.loggers << Logger.new(
|
|
23
|
+
DB.loggers << Logger.new($stdout)
|
|
24
24
|
|
|
25
25
|
== Using raw SQL
|
|
26
26
|
|
|
@@ -100,7 +100,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
|
100
100
|
DB[:items].where{(x > 5) & (y > 10)}.sql
|
|
101
101
|
# SELECT * FROM items WHERE ((x > 5) AND (y > 10))
|
|
102
102
|
|
|
103
|
-
DB[:items].where(Sequel.or(:x => 1, :y => 2)
|
|
103
|
+
DB[:items].where(Sequel.or(:x => 1, :y => 2) & Sequel.~(:z => 3)).sql
|
|
104
104
|
# SELECT * FROM items WHERE (((x = 1) OR (y = 2)) AND (z != 3))
|
|
105
105
|
|
|
106
106
|
=== Mathematical operators
|
|
@@ -150,7 +150,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
|
150
150
|
dataset.update(:updated_at => Sequel.function(:NOW))
|
|
151
151
|
dataset.update(:updated_at => Sequel.lit('NOW()'))
|
|
152
152
|
|
|
153
|
-
dataset.update(:updated_at => Sequel.lit("DateValue('1/1/2001')")
|
|
153
|
+
dataset.update(:updated_at => Sequel.lit("DateValue('1/1/2001')"))
|
|
154
154
|
dataset.update(:updated_at => Sequel.function(:DateValue, '1/1/2001'))
|
|
155
155
|
|
|
156
156
|
== Schema Manipulation
|
|
@@ -184,7 +184,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
|
184
184
|
Database#transaction is re-entrant:
|
|
185
185
|
|
|
186
186
|
DB.transaction do # BEGIN issued only here
|
|
187
|
-
DB.transaction
|
|
187
|
+
DB.transaction do
|
|
188
188
|
dataset << {:first_name => 'Inigo', :last_name => 'Montoya'}
|
|
189
189
|
end
|
|
190
190
|
end # COMMIT issued only here
|
|
@@ -205,7 +205,7 @@ Savepoints can be used if the database supports it:
|
|
|
205
205
|
|
|
206
206
|
DB.transaction do
|
|
207
207
|
dataset << {:first_name => 'Farm', :last_name => 'Boy'} # Inserted
|
|
208
|
-
DB.transaction(:savepoint=>true) # This savepoint is rolled back
|
|
208
|
+
DB.transaction(:savepoint=>true) do # This savepoint is rolled back
|
|
209
209
|
dataset << {:first_name => 'Inigo', :last_name => 'Montoya'} # Not inserted
|
|
210
210
|
raise(Sequel::Rollback) if something_bad_happened
|
|
211
211
|
end
|
|
@@ -216,5 +216,5 @@ Savepoints can be used if the database supports it:
|
|
|
216
216
|
|
|
217
217
|
dataset.sql # "SELECT * FROM items"
|
|
218
218
|
dataset.delete_sql # "DELETE FROM items"
|
|
219
|
-
dataset.columns
|
|
220
|
-
DB.schema(:items) => [[:id, {:type=>:integer, ...}], [:name, {:type=>:string, ...}], ...]
|
|
219
|
+
dataset.columns # => array of columns in the result set, does a SELECT
|
|
220
|
+
DB.schema(:items) # => [[:id, {:type=>:integer, ...}], [:name, {:type=>:string, ...}], ...]
|
data/doc/core_extensions.rdoc
CHANGED
data/doc/dataset_filtering.rdoc
CHANGED
|
@@ -110,7 +110,7 @@ This works with other hash values, such as arrays and ranges:
|
|
|
110
110
|
items.where{Sequel.|({:category => ['ruby', 'other']}, (:price - 100 > 200))}.sql
|
|
111
111
|
#=> "SELECT * FROM items WHERE ((category IN ('ruby', 'other')) OR ((price - 100) <= 200))"
|
|
112
112
|
|
|
113
|
-
items.where{Sequel.&({:price => (100..200)}, :active)
|
|
113
|
+
items.where{Sequel.&({:price => (100..200)}, :active)}.sql
|
|
114
114
|
#=> "SELECT * FROM items WHERE ((price >= 100 AND price <= 200) AND active)"
|
|
115
115
|
|
|
116
116
|
=== Negating conditions
|
data/doc/extensions.rdoc
CHANGED
|
@@ -79,6 +79,6 @@ The first argument is the name of the extension as a symbol, and the second is t
|
|
|
79
79
|
|
|
80
80
|
You can also call <tt>Sequel::Dataset.register_extension</tt> with a proc:
|
|
81
81
|
|
|
82
|
-
Sequel::Dataset.register_extension(:extension_name){|ds|
|
|
82
|
+
Sequel::Dataset.register_extension(:extension_name){|ds| }
|
|
83
83
|
|
|
84
84
|
Note that if you use a proc, a corresponding Database extension will not be created automatically (you can still call <tt>Sequel::Database.register_extension</tt> manually in this case).
|
data/doc/migration.rdoc
CHANGED
|
@@ -385,14 +385,14 @@ However, the migrations you write should contain an +up+ block that does somethi
|
|
|
385
385
|
reverses the changes made by the +up+ block:
|
|
386
386
|
|
|
387
387
|
Sequel.migration do
|
|
388
|
-
up{
|
|
389
|
-
down{
|
|
388
|
+
up{}
|
|
389
|
+
down{}
|
|
390
390
|
end
|
|
391
391
|
|
|
392
392
|
or they should use the reversible migrations feature with a +change+ block:
|
|
393
393
|
|
|
394
394
|
Sequel.migration do
|
|
395
|
-
change{
|
|
395
|
+
change{}
|
|
396
396
|
end
|
|
397
397
|
|
|
398
398
|
== What to put in your migration's +down+ block
|
data/doc/model_hooks.rdoc
CHANGED
|
@@ -121,7 +121,7 @@ However, skipping hooks is a bad idea in general and should be avoided. As ment
|
|
|
121
121
|
|
|
122
122
|
The +this+ dataset works just like any other dataset, so you can call +update+ on it to modify it:
|
|
123
123
|
|
|
124
|
-
album.this.update(:copies_sold=>album.copies_sold + 1)
|
|
124
|
+
album.this.update(:copies_sold=>album.copies_sold + 1)
|
|
125
125
|
|
|
126
126
|
If you want to insert a row into the model's table without running the creation hooks, you can use <tt>Model.insert</tt> instead of <tt>Model.create</tt>:
|
|
127
127
|
|
data/doc/opening_databases.rdoc
CHANGED
|
@@ -381,6 +381,10 @@ The following additional options are supported:
|
|
|
381
381
|
to handle notice/warning messages differently. Only respected if using the pg library).
|
|
382
382
|
:sslmode :: Set to 'disable', 'allow', 'prefer', 'require' to choose how to treat SSL (only
|
|
383
383
|
respected if using the pg library)
|
|
384
|
+
:search_path :: Set to the schema search_path. This can either be a single string containing the schemas
|
|
385
|
+
separated by commas (for use via a URL: <tt>postgres:///?search_path=schema1,schema2</tt>), or it
|
|
386
|
+
can be an array of strings (for use via an option:
|
|
387
|
+
<tt>Sequel.postgres(:search_path=>['schema1', 'schema2'])</tt>).
|
|
384
388
|
:use_iso_date_format :: This can be set to false to not force the ISO date format. Sequel forces
|
|
385
389
|
it by default to allow for an optimization.
|
|
386
390
|
|
data/doc/postgresql.rdoc
CHANGED
|
@@ -160,8 +160,8 @@ Sequel has built in support for creating and dropping PostgreSQL schemas, proced
|
|
|
160
160
|
DB.drop_function(:set_updated_at)
|
|
161
161
|
# DROP FUNCTION set_updated_at()
|
|
162
162
|
|
|
163
|
-
DB.create_trigger(:table, :trg_updated_at, :set_updated_at, :events
|
|
164
|
-
# CREATE TRIGGER trg_updated_at BEFORE
|
|
163
|
+
DB.create_trigger(:table, :trg_updated_at, :set_updated_at, :events=>:update, :each_row=>true, :when => {:new__updated_at => :old__updated_at})
|
|
164
|
+
# CREATE TRIGGER trg_updated_at BEFORE UPDATE ON "table" FOR EACH ROW WHEN ("new"."updated_at" = "old"."updated_at") EXECUTE PROCEDURE set_updated_at()
|
|
165
165
|
DB.drop_trigger(:table, :trg_updated_at)
|
|
166
166
|
# DROP TRIGGER trg_updated_at ON "table"
|
|
167
167
|
|
|
@@ -57,7 +57,7 @@ may itself contain placeholders:
|
|
|
57
57
|
# Insert record with 'Jim', note that the previous filter is ignored
|
|
58
58
|
ds.call(:insert, {:n=>'Jim'}, :name=>:$n)
|
|
59
59
|
# Change name to 'Bob' for all records with name of 'Jim'
|
|
60
|
-
ds.call(:update, {:n=>'Jim', :new_n=>'Bob'}, :name
|
|
60
|
+
ds.call(:update, {:n=>'Jim', :new_n=>'Bob'}, :name=>:$new_n)
|
|
61
61
|
|
|
62
62
|
== Prepared Statements
|
|
63
63
|
|
data/doc/querying.rdoc
CHANGED
|
@@ -40,7 +40,7 @@ by its primary key value:
|
|
|
40
40
|
# Find artist with primary key (id) 1
|
|
41
41
|
artist = Artist[1]
|
|
42
42
|
# SELECT * FROM artists WHERE id = 1
|
|
43
|
-
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
|
43
|
+
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
44
44
|
|
|
45
45
|
If there is no record with the given primary key, nil will be returned. If you want
|
|
46
46
|
to raise an exception if no record is found, you can use <tt>Sequel::Model.with_pk!</tt>:
|
|
@@ -54,17 +54,17 @@ If you just want the first record in the dataset,
|
|
|
54
54
|
|
|
55
55
|
artist = Artist.first
|
|
56
56
|
# SELECT * FROM artists LIMIT 1
|
|
57
|
-
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
|
57
|
+
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
58
58
|
|
|
59
59
|
Any options you pass to +first+ will be used as a filter:
|
|
60
60
|
|
|
61
61
|
artist = Artist.first(:name => 'YJM')
|
|
62
62
|
# SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
|
|
63
|
-
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
|
63
|
+
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
64
64
|
|
|
65
65
|
artist = Artist.first(Sequel.like(:name, 'Y%'))
|
|
66
66
|
# SELECT * FROM artists WHERE (name LIKE 'Y%' ESCAPE '\') LIMIT 1
|
|
67
|
-
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
|
67
|
+
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
68
68
|
|
|
69
69
|
If there is no matching row, +first+ will return nil. If you want to
|
|
70
70
|
raise an exception instead, use <tt>first!</tt>.
|
|
@@ -74,7 +74,7 @@ requires an argument:
|
|
|
74
74
|
|
|
75
75
|
DB[:artists][:name => 'YJM']
|
|
76
76
|
# SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
|
|
77
|
-
=> {:name=>"YJM", :id=>1}
|
|
77
|
+
# => {:name=>"YJM", :id=>1}
|
|
78
78
|
|
|
79
79
|
Note that while Model.[] allows you to pass a primary key directly,
|
|
80
80
|
Dataset#[] does not (unless it is a model dataset).
|
|
@@ -89,7 +89,7 @@ reverse order by the primary key field:
|
|
|
89
89
|
|
|
90
90
|
artist = Artist.last
|
|
91
91
|
# SELECT * FROM artists ORDER BY id DESC LIMIT 1
|
|
92
|
-
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
|
92
|
+
# => #<Artist @values={:name=>"YJM", :id=>1}>
|
|
93
93
|
|
|
94
94
|
Note that what +last+ does is reverse the order of the dataset and then
|
|
95
95
|
call +first+. This is why +last+ raises a Sequel::Error if there is no
|
|
@@ -107,7 +107,7 @@ you want:
|
|
|
107
107
|
|
|
108
108
|
artist_name = Artist.get(:name)
|
|
109
109
|
# SELECT name FROM artists LIMIT 1
|
|
110
|
-
=> "YJM"
|
|
110
|
+
# => "YJM"
|
|
111
111
|
|
|
112
112
|
=== Retrieving Multiple Objects
|
|
113
113
|
|
|
@@ -119,8 +119,8 @@ want to use:
|
|
|
119
119
|
|
|
120
120
|
artists = Artist.all
|
|
121
121
|
# SELECT * FROM artists
|
|
122
|
-
=> [#<Artist @values={:name=>"YJM", :id=>1}>,
|
|
123
|
-
|
|
122
|
+
# => [#<Artist @values={:name=>"YJM", :id=>1}>,
|
|
123
|
+
# #<Artist @values={:name=>"AS", :id=>2}>]
|
|
124
124
|
|
|
125
125
|
==== Using an Enumerable Interface
|
|
126
126
|
|
|
@@ -138,7 +138,7 @@ such as +map+:
|
|
|
138
138
|
|
|
139
139
|
artist_names = Artist.map{|x| x.name}
|
|
140
140
|
# SELECT * FROM artists
|
|
141
|
-
=> ["YJM", "AS"]
|
|
141
|
+
# => ["YJM", "AS"]
|
|
142
142
|
|
|
143
143
|
==== As an Array of Column Values
|
|
144
144
|
|
|
@@ -148,7 +148,7 @@ given column. So the previous example can be handled more easily with:
|
|
|
148
148
|
|
|
149
149
|
artist_names = Artist.map(:name)
|
|
150
150
|
# SELECT * FROM artists
|
|
151
|
-
=> ["YJM", "AS"]
|
|
151
|
+
# => ["YJM", "AS"]
|
|
152
152
|
|
|
153
153
|
One difference between these two ways of returning an array of values is
|
|
154
154
|
that providing +map+ with an argument is really doing:
|
|
@@ -162,21 +162,21 @@ single column and return an array of the columns values, you can use
|
|
|
162
162
|
|
|
163
163
|
artist_names = Artist.select_map(:name)
|
|
164
164
|
# SELECT name FROM artists
|
|
165
|
-
=> ["YJM", "AS"]
|
|
165
|
+
# => ["YJM", "AS"]
|
|
166
166
|
|
|
167
167
|
It's also common to want to order such a map, so Sequel provides a
|
|
168
168
|
+select_order_map+ method as well:
|
|
169
169
|
|
|
170
170
|
artist_names = Artist.select_order_map(:name)
|
|
171
171
|
# SELECT name FROM artists ORDER BY name
|
|
172
|
-
=> ["AS", "YJM"]
|
|
172
|
+
# => ["AS", "YJM"]
|
|
173
173
|
|
|
174
174
|
In all of these cases, you can provide an array of column symbols and
|
|
175
175
|
an array of arrays of values will be returned:
|
|
176
176
|
|
|
177
177
|
artist_names = Artist.select_map([:id, :name])
|
|
178
178
|
# SELECT id, name FROM artists
|
|
179
|
-
=> [[1, "YJM"], [2, "AS"]]
|
|
179
|
+
# => [[1, "YJM"], [2, "AS"]]
|
|
180
180
|
|
|
181
181
|
==== As a Hash
|
|
182
182
|
|
|
@@ -185,7 +185,7 @@ using the +to_hash+ method:
|
|
|
185
185
|
|
|
186
186
|
artist_names = Artist.to_hash(:id, :name)
|
|
187
187
|
# SELECT * FROM artists
|
|
188
|
-
=> {1=>"YJM", 2=>"AS"}
|
|
188
|
+
# => {1=>"YJM", 2=>"AS"}
|
|
189
189
|
|
|
190
190
|
As you can see, the +to_hash+ method uses the first symbol as the key
|
|
191
191
|
and the second symbol as the value. So if you swap the two arguments the hash
|
|
@@ -193,7 +193,7 @@ will have its keys and values transposed:
|
|
|
193
193
|
|
|
194
194
|
artist_names = Artist.to_hash(:name, :id)
|
|
195
195
|
# SELECT * FROM artists
|
|
196
|
-
=> {"YJM"=>1, "AS"=>2}
|
|
196
|
+
# => {"YJM"=>1, "AS"=>2}
|
|
197
197
|
|
|
198
198
|
Now what if you have multiple values for the same key? By default, +to_hash+
|
|
199
199
|
will just have the last matching value. If you care about all matching values,
|
|
@@ -202,20 +202,20 @@ values, in the order they were received:
|
|
|
202
202
|
|
|
203
203
|
artist_names = Artist.to_hash_groups(:name, :id)
|
|
204
204
|
# SELECT * FROM artists
|
|
205
|
-
=> {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
|
|
205
|
+
# => {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
|
|
206
206
|
|
|
207
207
|
If you only provide one argument to +to_hash+, it uses the entire hash
|
|
208
208
|
or model object as the value:
|
|
209
209
|
|
|
210
210
|
artist_names = DB[:artists].to_hash(:name)
|
|
211
211
|
# SELECT * FROM artists
|
|
212
|
-
=> {"YJM"=>{:id=>1, :name=>"YJM"}, "AS"=>{:id=>2, :name=>"AS"}}
|
|
212
|
+
# => {"YJM"=>{:id=>1, :name=>"YJM"}, "AS"=>{:id=>2, :name=>"AS"}}
|
|
213
213
|
|
|
214
214
|
and +to_hash_groups+ works similarly:
|
|
215
215
|
|
|
216
216
|
artist_names = DB[:artists].to_hash_groups(:name)
|
|
217
217
|
# SELECT * FROM artists
|
|
218
|
-
=> {"YJM"=>[{:id=>1, :name=>"YJM"}, {:id=>10, :name=>"YJM"}], ...}
|
|
218
|
+
# => {"YJM"=>[{:id=>1, :name=>"YJM"}, {:id=>10, :name=>"YJM"}], ...}
|
|
219
219
|
|
|
220
220
|
Model datasets have a +to_hash+ method that can be called without any
|
|
221
221
|
arguments, in which case it will use the primary key as the key and
|
|
@@ -224,8 +224,8 @@ identity map:
|
|
|
224
224
|
|
|
225
225
|
artist_names = Artist.to_hash
|
|
226
226
|
# SELECT * FROM artists
|
|
227
|
-
=> {1=>#<Artist @values={:id=>1, :name=>"YGM"}>,
|
|
228
|
-
|
|
227
|
+
# => {1=>#<Artist @values={:id=>1, :name=>"YGM"}>,
|
|
228
|
+
# 2=>#<Artist @values={:id=>2, :name=>"AS"}>}
|
|
229
229
|
|
|
230
230
|
There is no equivalent handling to +to_hash_groups+, since there would
|
|
231
231
|
only be one matching record, as the primary key must be unique.
|
|
@@ -237,13 +237,13 @@ columns selected and return a hash:
|
|
|
237
237
|
|
|
238
238
|
artist_names = Artist.select_hash(:name, :id)
|
|
239
239
|
# SELECT name, id FROM artists
|
|
240
|
-
=> {"YJM"=>1, "AS"=>2}
|
|
240
|
+
# => {"YJM"=>1, "AS"=>2}
|
|
241
241
|
|
|
242
242
|
Likewise, +select_hash_groups+ also exists:
|
|
243
243
|
|
|
244
244
|
artist_names = Artist.select_hash_groups(:name, :id)
|
|
245
245
|
# SELECT name, id FROM artists
|
|
246
|
-
=> {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
|
|
246
|
+
# => {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
|
|
247
247
|
|
|
248
248
|
== Modifying datasets
|
|
249
249
|
|
|
@@ -975,15 +975,15 @@ If you just want to know whether the current dataset would return any rows, use
|
|
|
975
975
|
|
|
976
976
|
Album.empty?
|
|
977
977
|
# SELECT 1 FROM albums LIMIT 1
|
|
978
|
-
=> false
|
|
978
|
+
# => false
|
|
979
979
|
|
|
980
980
|
Album.where(:id=>0).empty?
|
|
981
981
|
# SELECT 1 FROM albums WHERE id = 0 LIMIT 1
|
|
982
|
-
=> true
|
|
982
|
+
# => true
|
|
983
983
|
|
|
984
984
|
Album.where(Sequel.like(:name, 'R%')).empty?
|
|
985
985
|
# SELECT 1 FROM albums WHERE name LIKE 'R%' ESCAPE '\' LIMIT 1
|
|
986
|
-
=> false
|
|
986
|
+
# => false
|
|
987
987
|
|
|
988
988
|
== Aggregate Calculations
|
|
989
989
|
|
|
@@ -995,23 +995,23 @@ for each of these aggregate functions.
|
|
|
995
995
|
|
|
996
996
|
Album.count
|
|
997
997
|
# SELECT count(*) AS count FROM albums LIMIT 1
|
|
998
|
-
=> 2
|
|
998
|
+
# => 2
|
|
999
999
|
|
|
1000
1000
|
The other methods take a column argument and call the aggregate function with
|
|
1001
1001
|
the argument:
|
|
1002
1002
|
|
|
1003
1003
|
Album.sum(:id)
|
|
1004
1004
|
# SELECT sum(id) FROM albums LIMIT 1
|
|
1005
|
-
=> 3
|
|
1005
|
+
# => 3
|
|
1006
1006
|
|
|
1007
1007
|
Album.avg(:id)
|
|
1008
1008
|
# SELECT avg(id) FROM albums LIMIT 1
|
|
1009
|
-
=> 1.5
|
|
1009
|
+
# => 1.5
|
|
1010
1010
|
|
|
1011
1011
|
Album.min(:id)
|
|
1012
1012
|
# SELECT min(id) FROM albums LIMIT 1
|
|
1013
|
-
=> 1
|
|
1013
|
+
# => 1
|
|
1014
1014
|
|
|
1015
1015
|
Album.max(:id)
|
|
1016
1016
|
# SELECT max(id) FROM albums LIMIT 1
|
|
1017
|
-
=> 2
|
|
1017
|
+
# => 2
|