sequel 5.30.0 → 5.35.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +86 -0
- data/README.rdoc +1 -1
- data/doc/advanced_associations.rdoc +4 -4
- data/doc/association_basics.rdoc +10 -5
- data/doc/code_order.rdoc +12 -2
- data/doc/dataset_filtering.rdoc +2 -2
- data/doc/model_dataset_method_design.rdoc +1 -1
- data/doc/postgresql.rdoc +71 -0
- data/doc/release_notes/5.31.0.txt +148 -0
- data/doc/release_notes/5.32.0.txt +46 -0
- data/doc/release_notes/5.33.0.txt +24 -0
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/testing.rdoc +1 -1
- data/lib/sequel/adapters/oracle.rb +2 -1
- data/lib/sequel/adapters/shared/access.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -5
- data/lib/sequel/adapters/shared/mysql.rb +9 -9
- data/lib/sequel/adapters/shared/oracle.rb +16 -16
- data/lib/sequel/adapters/shared/postgres.rb +169 -14
- data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
- data/lib/sequel/adapters/shared/sqlite.rb +33 -6
- data/lib/sequel/adapters/tinytds.rb +1 -0
- data/lib/sequel/connection_pool/sharded_single.rb +4 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
- data/lib/sequel/connection_pool/single.rb +1 -1
- data/lib/sequel/connection_pool/threaded.rb +2 -2
- data/lib/sequel/core.rb +318 -314
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/misc.rb +16 -10
- data/lib/sequel/database/query.rb +3 -1
- data/lib/sequel/database/schema_generator.rb +0 -1
- data/lib/sequel/database/schema_methods.rb +15 -16
- data/lib/sequel/database/transactions.rb +7 -4
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/query.rb +5 -4
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/connection_expiration.rb +2 -2
- data/lib/sequel/extensions/connection_validator.rb +2 -2
- data/lib/sequel/extensions/core_refinements.rb +2 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -0
- data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
- data/lib/sequel/extensions/index_caching.rb +9 -7
- data/lib/sequel/extensions/integer64.rb +2 -0
- data/lib/sequel/extensions/migration.rb +1 -2
- data/lib/sequel/extensions/pg_array_ops.rb +4 -0
- data/lib/sequel/extensions/pg_enum.rb +7 -2
- data/lib/sequel/extensions/pg_extended_date_support.rb +1 -1
- data/lib/sequel/extensions/pg_hstore.rb +6 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_inet.rb +15 -5
- data/lib/sequel/extensions/pg_interval.rb +2 -0
- data/lib/sequel/extensions/pg_json_ops.rb +2 -0
- data/lib/sequel/extensions/pg_range.rb +5 -7
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +0 -1
- data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
- data/lib/sequel/extensions/s.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +10 -4
- data/lib/sequel/extensions/server_block.rb +3 -3
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model.rb +2 -0
- data/lib/sequel/model/associations.rb +54 -25
- data/lib/sequel/model/base.rb +70 -57
- data/lib/sequel/model/plugins.rb +3 -3
- data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
- data/lib/sequel/plugins/association_multi_add_remove.rb +2 -0
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/association_proxies.rb +2 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/boolean_subsets.rb +4 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +28 -28
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/dirty.rb +13 -13
- data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/json_serializer.rb +3 -7
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/pg_array_associations.rb +2 -3
- data/lib/sequel/plugins/prepared_statements.rb +5 -11
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +10 -16
- data/lib/sequel/plugins/single_table_inheritance.rb +15 -15
- data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +2 -0
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/timezones.rb +6 -4
- data/lib/sequel/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ac0d24707f9029714f4e5258c484148d7dc10a733c0c33865d252141cd4cc2e
|
4
|
+
data.tar.gz: cdabb1bb51fdfe7b7a22df0a6a9102dd15366bbdd98100907b2e3d74db4e5878
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d87a7d026c51d8897c964cca01ad30384b853bdbbda42811ee7245ef669ac23c1093e572a0e414db5daeb84b8f417e63c14c3ac13aa0b12ac9eb8f801ea6e6c2
|
7
|
+
data.tar.gz: 3e788cabe74d01035b930ca699b5ebc763a6a34410c1b8a3a5075d5a276c5155355d9476303b6b606d1b0a74d6a535ca4fdca696cdc0b83e32658be45c8f946e
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,89 @@
|
|
1
|
+
=== 5.35.0 (2020-08-01)
|
2
|
+
|
3
|
+
* Recognize another disconnect error in the oracle adapter (sterlzbd) (#1705)
|
4
|
+
|
5
|
+
* Consider all associations with :dataset options as instance-specific associations (jeremyevans)
|
6
|
+
|
7
|
+
* Make Model.finalize_associations not break with instance-specific associations (jeremyevans)
|
8
|
+
|
9
|
+
* Make association placeholder loader consider block if instance_specific: false association option is used (jeremyevans)
|
10
|
+
|
11
|
+
* Copy composite unique constraints when emulating alter table operations on SQLite (jeremyevans) (#1704)
|
12
|
+
|
13
|
+
* Add instance_specific_default plugin for setting default association :instance_specific value, or warning/raising for cases where it is not specified (jeremyevans)
|
14
|
+
|
15
|
+
* Make Model.plugin issue deprecation warning if loading plugin with arguments and block if plugin does not accept arguments/block (jeremyevans)
|
16
|
+
|
17
|
+
* Make validation_class_methods consider all :if, :allow_missing, :allow_nil, and :allow_blank settings, instead of just the first (jeremyevans)
|
18
|
+
|
19
|
+
* Include hash entries with nil keys in Dataset#to_dot output in to_dot extension (jeremyevans)
|
20
|
+
|
21
|
+
* Remove unneeded conditionals from plugins and extensions (jeremyevans)
|
22
|
+
|
23
|
+
* Fix exception class in run_transaction_hooks extension if calling run_after_{commit,rollback}_hooks outside of a transaction (jeremyevans)
|
24
|
+
|
25
|
+
=== 5.34.0 (2020-07-01)
|
26
|
+
|
27
|
+
* Make eager_graph work correctly if called with no associations (jeremyevans)
|
28
|
+
|
29
|
+
* Make :ruby eager limit strategy handle cases where there is no limit or offset (jeremyevans)
|
30
|
+
|
31
|
+
* Do not keep a reference to a Sequel::Database instance that raises an exception during initialization (jeremyevans)
|
32
|
+
|
33
|
+
* Make Database#pool.all_connections not yield for a single connection pool in disconnected state (jeremyevans)
|
34
|
+
|
35
|
+
* Raise an exception if trying to disconnect a server that doesn't exist in the sharded connection pools (jeremyevans)
|
36
|
+
|
37
|
+
* Support :refresh option when calling *_pks getter method in the association_pks plugin (jeremyevans)
|
38
|
+
|
39
|
+
* Support caching of repeated calls to *_pks getter method in the association_pks plugin using :cache_pks association option (jeremyevans)
|
40
|
+
|
41
|
+
* Add *_pks_dataset methods for one_to_many and many_to_many associations when using the association_pks plugin (jeremyevans)
|
42
|
+
|
43
|
+
=== 5.33.0 (2020-06-01)
|
44
|
+
|
45
|
+
* Support custom join types on a per-association basis when using eager_graph/association_join (jeremyevans)
|
46
|
+
|
47
|
+
* Support primary_key with type: :smallserial on PostgreSQL (j-a-m-l) (#1698)
|
48
|
+
|
49
|
+
* Add Database#current_timestamp_utc accessor on SQLite to keep CURRENT_* in UTC instead of converting to localtime (jeremyevans)
|
50
|
+
|
51
|
+
=== 5.32.0 (2020-05-01)
|
52
|
+
|
53
|
+
* Allow Database#create_table? work with :partition_of option on PostgreSQL (jeremyevans) (#1690)
|
54
|
+
|
55
|
+
* Add fiber_concurrency extension, for using Fiber.current instead of Thread.current for checking out connections (jeremyevans)
|
56
|
+
|
57
|
+
* Move most Sequel singleton methods into a module that extends Sequel for easier overriding (jeremyevans)
|
58
|
+
|
59
|
+
* Fix method visibility issues in model, plugin, extension, and adapter code (jeremyevans)
|
60
|
+
|
61
|
+
* Avoid defining conversion procs for PostgreSQL inet/cidr types in pg_inet extension when using sequel_pg 1.13.0+ (jeremyevans)
|
62
|
+
|
63
|
+
* Add run_transaction_hooks Database extension, allowing for running the transaction hooks before commit/rollback, for use with transactional testing (jeremyevans)
|
64
|
+
|
65
|
+
* Recognize timestamp(N) with time zone type (isc) (#1684)
|
66
|
+
|
67
|
+
=== 5.31.0 (2020-04-01)
|
68
|
+
|
69
|
+
* Fix alter_table drop_constraint :primary_key option on SQLite for non-integer primary keys (jeremyevans)
|
70
|
+
|
71
|
+
* Add skip_saving_columns plugin, which supports columns to skip when saving, and skips generated columns by default (joeosburn, jeremyevans) (#1681, #1682)
|
72
|
+
|
73
|
+
* Add support for creating partitioned tables in PostgreSQL 10+ using :partition_by and :partition_of options (jeremyevans)
|
74
|
+
|
75
|
+
* Dump generated columns as generated columns when using the schema_dumper with :same_db option on PostgreSQL 12+ (jeremyevans) (#1680)
|
76
|
+
|
77
|
+
* Ignore defaults for generated columns by default when using the schema dumper (jeremyevans) (#1680)
|
78
|
+
|
79
|
+
* Include generated columns in schema on SQLite 3.31+ (jeremyevans)
|
80
|
+
|
81
|
+
* Add :generated schema entry on PostgreSQL 12+ and SQLite 3.31+ for whether the columns is generated (jeremyevans)
|
82
|
+
|
83
|
+
* Add association_lazy_eager_option plugin for supporting :eager option for association method (jeremyevans)
|
84
|
+
|
85
|
+
* Add forbid_lazy_load plugin for forbidding lazy loading of associations, to help find N+1 issues (jeremyevans)
|
86
|
+
|
1
87
|
=== 5.30.0 (2020-03-01)
|
2
88
|
|
3
89
|
* Remove specs and old release notes from the gem to reduce gem size by over 40% (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -894,7 +894,7 @@ in the most current release.
|
|
894
894
|
|
895
895
|
Sequel fully supports the currently supported versions of Ruby (MRI) and JRuby. It may
|
896
896
|
support unsupported versions of Ruby or JRuby, but such support may be dropped in any
|
897
|
-
minor version
|
897
|
+
minor version if keeping it becomes a support issue. The minimum Ruby version
|
898
898
|
required to run the current version of Sequel is 1.9.2.
|
899
899
|
|
900
900
|
== Maintainer
|
@@ -731,7 +731,7 @@ associations:
|
|
731
731
|
one_to_one :tracks, key: [:disc_number, :number, :album_id], primary_key: [:disc_number, :number, :album_id]
|
732
732
|
end
|
733
733
|
|
734
|
-
=== Tree - All Ancestors and
|
734
|
+
=== Tree - All Ancestors and Descendants
|
735
735
|
|
736
736
|
Let's say you want to store a tree relationship in your database, it's pretty
|
737
737
|
simple:
|
@@ -749,7 +749,7 @@ node.children. You can even eager load the relationship up to a certain depth:
|
|
749
749
|
# Load parents and grandparents for a group of nodes
|
750
750
|
Node.where{id < 10}.eager(parent: :parent).all
|
751
751
|
|
752
|
-
What if you want to get all ancestors up to the root node, or all
|
752
|
+
What if you want to get all ancestors up to the root node, or all descendants,
|
753
753
|
without knowing the depth of the tree?
|
754
754
|
|
755
755
|
class Node < Sequel::Model
|
@@ -770,7 +770,7 @@ without knowing the depth of the tree?
|
|
770
770
|
id_map = {}
|
771
771
|
# Create an map of parent_ids to nodes that have that parent id
|
772
772
|
non_root_nodes.each{|n| (id_map[n.parent_id] ||= []) << n}
|
773
|
-
# Doesn't cause an
|
773
|
+
# Doesn't cause an infinite loop, because when only the root node
|
774
774
|
# is left, this is not called.
|
775
775
|
Node.where(id: id_map.keys).eager(:ancestors).all do |node|
|
776
776
|
# Populate the parent association for each node
|
@@ -879,4 +879,4 @@ associated tickets.
|
|
879
879
|
end
|
880
880
|
|
881
881
|
Note that it is often better to use a sum cache instead of this approach. You can implement
|
882
|
-
a sum cache using +after_create+, +after_update+, and +after_delete+ hooks, or
|
882
|
+
a sum cache using +after_create+, +after_update+, and +after_delete+ hooks, or preferably using a database trigger.
|
data/doc/association_basics.rdoc
CHANGED
@@ -113,7 +113,7 @@ many rows in the current table, by using a join table to associate the two table
|
|
113
113
|
The one_through_one association can be thought of as a subset of the many_to_many
|
114
114
|
association, but where there can only be 0 or 1 records in the associated table.
|
115
115
|
This is useful if there is a unique constraint on the foreign key in the join table
|
116
|
-
that
|
116
|
+
that references the current table. It's also useful if you want to impose an order
|
117
117
|
on the association and just want the first record returned. The one_through_one
|
118
118
|
association is so named because it sets up a one-to-one association through a
|
119
119
|
single join table.
|
@@ -781,7 +781,7 @@ Sequel is designed to be very flexible. If the default behavior of the
|
|
781
781
|
association modification methods isn't what you desire, you can override
|
782
782
|
the methods in your classes. However, you should be aware that for each
|
783
783
|
of the association modification methods described, there is a private
|
784
|
-
method that is
|
784
|
+
method that is preceded by an underscore that does the actual
|
785
785
|
modification. The public method without the underscore handles caching
|
786
786
|
and callbacks, and shouldn't be overridden by the user.
|
787
787
|
|
@@ -1069,7 +1069,7 @@ option of the first association, it doesn't attempt to merge them.
|
|
1069
1069
|
In addition to the options hash, the :clone option will copy a block argument
|
1070
1070
|
from the existing situation. If you want a cloned association to not have the
|
1071
1071
|
same block as the association you are cloning from, specify the block: nil option
|
1072
|
-
in
|
1072
|
+
in addition to the :clone option.
|
1073
1073
|
|
1074
1074
|
==== :dataset
|
1075
1075
|
|
@@ -1676,11 +1676,16 @@ instances.
|
|
1676
1676
|
==== :instance_specific
|
1677
1677
|
|
1678
1678
|
This allows you to override the setting of whether the dataset contains instance
|
1679
|
-
specific code.
|
1679
|
+
specific code. If you are passing a block to the association,
|
1680
1680
|
Sequel sets this to true by default, which disables some optimizations that
|
1681
1681
|
would be invalid if the association is instance specific. If you know that the
|
1682
1682
|
block does not contain instance specific code, you can set this to false to
|
1683
|
-
reenable the optimizations.
|
1683
|
+
reenable the optimizations. Instance specific code is mostly commonly calling
|
1684
|
+
model instance methods inside an association block, but also
|
1685
|
+
includes cases where the association block can return different values based
|
1686
|
+
on the runtime environment, such as calls to <tt>Time.now</tt> in the block.
|
1687
|
+
Associations that use the :dataset option are always considered instance specific,
|
1688
|
+
even if explicitly specified otherwise.
|
1684
1689
|
|
1685
1690
|
==== :cartesian_product_number
|
1686
1691
|
|
data/doc/code_order.rdoc
CHANGED
@@ -7,7 +7,7 @@ this guide will be specific about which are strictly necessary.
|
|
7
7
|
|
8
8
|
== Require Sequel
|
9
9
|
|
10
|
-
This is sort of a no
|
10
|
+
This is sort of a no-brainer, but you need to require the library
|
11
11
|
first. This is a strict requirement, none of the other code can
|
12
12
|
be executed unless the library has been required first. Example:
|
13
13
|
|
@@ -70,7 +70,7 @@ copied into the subclass when model subclasses are created. Example:
|
|
70
70
|
== Load Model Classes
|
71
71
|
|
72
72
|
After you have established a database connection, and configured your
|
73
|
-
global model
|
73
|
+
global model configuration and global plugins, you can load your model
|
74
74
|
classes. It's recommended to have a separate file for each model class,
|
75
75
|
unless the model classes are very simple. Example:
|
76
76
|
|
@@ -91,6 +91,16 @@ unsafe runtime modification of the configuration:
|
|
91
91
|
model_classes.each(&:freeze)
|
92
92
|
DB.freeze
|
93
93
|
|
94
|
+
The `subclasses` plugin can be used to keep track of all model classes
|
95
|
+
that have been setup in your application. Finalizing their associations
|
96
|
+
and freezing them can easily be achieved through the plugin:
|
97
|
+
|
98
|
+
# Register the plugin before setting up the models
|
99
|
+
Sequel::Model.plugin :subclasses
|
100
|
+
# ... setup models
|
101
|
+
# Now finalize associations & freeze models by calling the plugin:
|
102
|
+
Sequel::Model.freeze_descendents
|
103
|
+
|
94
104
|
== Disconnect If Using Forking Webserver with Code Preloading
|
95
105
|
|
96
106
|
If you are using a forking webserver such as unicorn or passenger, with
|
data/doc/dataset_filtering.rdoc
CHANGED
@@ -36,8 +36,8 @@ Ranges (both inclusive and exclusive) can also be used:
|
|
36
36
|
|
37
37
|
If you need to select multiple items from a dataset, you can supply an array:
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
items.where(id: [1, 38, 47, 99]).sql
|
40
|
+
# "SELECT * FROM items WHERE (id IN (1, 38, 47, 99))"
|
41
41
|
|
42
42
|
== Filtering using expressions
|
43
43
|
|
@@ -4,7 +4,7 @@ How you design your model dataset methods can significantly affect the flexibili
|
|
4
4
|
|
5
5
|
== Flexibility: Use Single Method Per Task
|
6
6
|
|
7
|
-
In general, it is recommended that you have a single method per task for maximum
|
7
|
+
In general, it is recommended that you have a single method per task for maximum flexibility. For example, let's say you need to retrieve all albums released in a given year, ordered by number of units sold descending, and only care about the id, name and number of units sold. One way to do this is in your application code (outside the model), you can
|
8
8
|
call the dataset methods directly:
|
9
9
|
|
10
10
|
Album.
|
data/doc/postgresql.rdoc
CHANGED
@@ -139,6 +139,77 @@ conversion via a USING clause, and Sequel supports this using the <tt>:using</tt
|
|
139
139
|
# ALTER TABLE "table" ALTER COLUMN "unix_time" TYPE timestamp
|
140
140
|
# USING (CAST('epoch' AS timestamp) + (CAST('1 second' AS interval) * "unix_time"))
|
141
141
|
|
142
|
+
=== Creating Partitioned Tables
|
143
|
+
|
144
|
+
PostgreSQL allows marking tables as partitioned tables, and adding partitions to such tables. Sequel
|
145
|
+
offers support for this. You can create a partitioned table using the +:partition_by+ option and
|
146
|
+
+:partition_type+ options (the default partition type is range partitioning):
|
147
|
+
|
148
|
+
DB.create_table(:table1, partition_by: :column, partition_type: :range) do
|
149
|
+
Integer :id
|
150
|
+
Date :column
|
151
|
+
end
|
152
|
+
|
153
|
+
DB.create_table(:table2, partition_by: :column, partition_type: :list) do
|
154
|
+
Integer :id
|
155
|
+
String :column
|
156
|
+
end
|
157
|
+
|
158
|
+
DB.create_table(:table3, partition_by: :column, partition_type: :hash) do
|
159
|
+
Integer :id
|
160
|
+
Integer :column
|
161
|
+
end
|
162
|
+
|
163
|
+
To add partitions of other tables, you use the +:partition_of+ option. This option will use
|
164
|
+
a custom DSL specific to partitioning other tables. For range partitioning, you can use the
|
165
|
+
+from+ and +to+ methods to specify the inclusive beginning and exclusive ending of the
|
166
|
+
range of the partition. You can call the +minvalue+ and +maxvalue+ methods to get the minimum
|
167
|
+
and maximum values for the column(s) in the range, useful as arguments to +from+ and +to+:
|
168
|
+
|
169
|
+
DB.create_table(:table1a, partition_of: :table1) do
|
170
|
+
from minvalue
|
171
|
+
to 0
|
172
|
+
end
|
173
|
+
DB.create_table(:table1b, partition_of: :table1) do
|
174
|
+
from 0
|
175
|
+
to 100
|
176
|
+
end
|
177
|
+
DB.create_table(:table1c, partition_of: :table1) do
|
178
|
+
from 100
|
179
|
+
to maxvalue
|
180
|
+
end
|
181
|
+
|
182
|
+
For list partitioning, you use the +values_in+ method. You can also use the +default+ method
|
183
|
+
to mark a partition as the default partition:
|
184
|
+
|
185
|
+
DB.create_table(:table2a, partition_of: :table2) do
|
186
|
+
values_in 1, 2, 3
|
187
|
+
end
|
188
|
+
DB.create_table(:table2b, partition_of: :table2) do
|
189
|
+
values_in 4, 5, 6
|
190
|
+
end
|
191
|
+
DB.create_table(:table2c, partition_of: :table2) do
|
192
|
+
default
|
193
|
+
end
|
194
|
+
|
195
|
+
For hash partitioning, you use the +modulus+ and +remainder+ methods:
|
196
|
+
|
197
|
+
DB.create_table(:table3a, partition_of: :table3) do
|
198
|
+
modulus 3
|
199
|
+
remainder 0
|
200
|
+
end
|
201
|
+
DB.create_table(:table3b, partition_of: :table3) do
|
202
|
+
modulus 3
|
203
|
+
remainder 1
|
204
|
+
end
|
205
|
+
DB.create_table(:table3c, partition_of: :table3) do
|
206
|
+
modulus 3
|
207
|
+
remainder 2
|
208
|
+
end
|
209
|
+
|
210
|
+
There is currently no support for using custom column or table constraints in partitions of
|
211
|
+
other tables. Support may be added in the future.
|
212
|
+
|
142
213
|
=== Creating Unlogged Tables
|
143
214
|
|
144
215
|
PostgreSQL allows users to create unlogged tables, which are faster but not crash safe. Sequel
|
@@ -0,0 +1,148 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A forbid_lazy_load plugin has been added to forbid the lazy loading
|
4
|
+
of model associations if the current object was retreived with other
|
5
|
+
objects. This plugin helps detect N+1 query issues. This plugin
|
6
|
+
will raise an error if a lazy load is detected in such cases:
|
7
|
+
|
8
|
+
Album.plugin :forbid_lazy_load
|
9
|
+
Album.one_to_many :tracks
|
10
|
+
|
11
|
+
Album.each do |album|
|
12
|
+
album.tracks
|
13
|
+
# Could be N+1, raises Sequel::Plugins::ForbidLazyLoad::Error
|
14
|
+
end
|
15
|
+
|
16
|
+
Album.first.tracks
|
17
|
+
# Could not be N+1, no error raised
|
18
|
+
|
19
|
+
The forbid_lazy_load plugin is designed to be loaded into the base
|
20
|
+
model class (generally Sequel::Model), and can be loaded only in
|
21
|
+
test mode, or only in certain test mode configurations, so that it
|
22
|
+
does not have any production performance impact.
|
23
|
+
|
24
|
+
Note that an alternative approach that Sequel has supported for many
|
25
|
+
years is the tactical_eager_loading plugin, which automatically
|
26
|
+
eager loads when an N+1 query issue is detected.
|
27
|
+
|
28
|
+
* An association_lazy_eager_option plugin has been added which supports
|
29
|
+
the :eager option for the association method. If the association has
|
30
|
+
not been loaded, this eagerly loads the associations specified by the
|
31
|
+
:eager option when loading the association. If the association has
|
32
|
+
already been loaded, this option is ignored, with the assumption that
|
33
|
+
whatever loaded the association already used the correct eager
|
34
|
+
loading. Example:
|
35
|
+
|
36
|
+
Album.plugin :association_lazy_eager_option
|
37
|
+
Album.one_to_many :tracks
|
38
|
+
Track.many_to_one :artist
|
39
|
+
|
40
|
+
album = Album.first
|
41
|
+
album.tracks(:eager=>:artist)
|
42
|
+
# Loads tracks for album, then artist for each track (2 queries)
|
43
|
+
|
44
|
+
album.tracks(:eager=>:artist)
|
45
|
+
# No query issued as association is cached
|
46
|
+
|
47
|
+
You could previously have similar behavior for uncached associations
|
48
|
+
by passing a block to the association method and calling eager on
|
49
|
+
the yielded dataset. However, that would ignore any cached
|
50
|
+
association, causing redundant loading of the association in such
|
51
|
+
cases.
|
52
|
+
|
53
|
+
* On PostgreSQL 10+, creating partitioned tables and partitions of
|
54
|
+
other tables is now supported.
|
55
|
+
|
56
|
+
To create a partitioned table, use the :partition_by option:
|
57
|
+
|
58
|
+
DB.create_table(:table1, partition_by: :date_column,
|
59
|
+
partition_type: :range) do
|
60
|
+
Integer :id
|
61
|
+
Date :date_column
|
62
|
+
end
|
63
|
+
|
64
|
+
DB.create_table(:table2, partition_by: :string_column,
|
65
|
+
partition_type: :list) do
|
66
|
+
Integer :id
|
67
|
+
String :string_column
|
68
|
+
end
|
69
|
+
|
70
|
+
DB.create_table(:table3, partition_by: :int_column,
|
71
|
+
partition_type: :hash) do
|
72
|
+
Integer :id
|
73
|
+
Integer :int_column
|
74
|
+
end
|
75
|
+
|
76
|
+
To add partitions of other tables, use the :partition_of option.
|
77
|
+
This option will use a custom DSL specific to partitions of other
|
78
|
+
tables.
|
79
|
+
|
80
|
+
For range partitioning, you can use the from and to methods to
|
81
|
+
specify the inclusive beginning and exclusive ending of the range
|
82
|
+
of the partition. You can call the minvalue and maxvalue methods
|
83
|
+
to get the minimum and maximum values for the column(s) in the
|
84
|
+
range, useful as arguments to from and to:
|
85
|
+
|
86
|
+
DB.create_table(:table1a, partition_of: :table1) do
|
87
|
+
from minvalue
|
88
|
+
to 0
|
89
|
+
end
|
90
|
+
DB.create_table(:table1b, partition_of: :table1) do
|
91
|
+
from 0
|
92
|
+
to 100
|
93
|
+
end
|
94
|
+
DB.create_table(:table1c, partition_of: :table1) do
|
95
|
+
from 100
|
96
|
+
to maxvalue
|
97
|
+
end
|
98
|
+
|
99
|
+
For list partitioning, you use the values_in method. You can also
|
100
|
+
use the default method to mark a partition as the default partition:
|
101
|
+
|
102
|
+
DB.create_table(:table2a, partition_of: :table2) do
|
103
|
+
values_in 1, 2, 3
|
104
|
+
end
|
105
|
+
DB.create_table(:table2b, partition_of: :table2) do
|
106
|
+
values_in 4, 5, 6
|
107
|
+
end
|
108
|
+
DB.create_table(:table2c, partition_of: :table2) do
|
109
|
+
default
|
110
|
+
end
|
111
|
+
|
112
|
+
For hash partitioning, you use the modulus and remainder methods:
|
113
|
+
|
114
|
+
DB.create_table(:table3a, partition_of: :table3) do
|
115
|
+
modulus 3
|
116
|
+
remainder 0
|
117
|
+
end
|
118
|
+
DB.create_table(:table3b, partition_of: :table3) do
|
119
|
+
modulus 3
|
120
|
+
remainder 1
|
121
|
+
end
|
122
|
+
DB.create_table(:table3c, partition_of: :table3) do
|
123
|
+
modulus 3
|
124
|
+
remainder 2
|
125
|
+
end
|
126
|
+
|
127
|
+
* On PostgreSQL 12+ and SQLite 3.31+, column schema hashes now have
|
128
|
+
a :generated entry for whether the column is a generated column.
|
129
|
+
|
130
|
+
* The schema_dumper extension now dumps generated columns correctly
|
131
|
+
when using the :same_db option on PostgreSQL 12+.
|
132
|
+
|
133
|
+
* A skip_saving_columns plugin has been added. This allows skipping
|
134
|
+
saving of specific columns for the model. By default, it skips
|
135
|
+
saving of generated columns, but you can customize the columns
|
136
|
+
that it skips:
|
137
|
+
|
138
|
+
Album.plugin :skip_saving_columns
|
139
|
+
Album.skip_saving_columns = [:some_column]
|
140
|
+
|
141
|
+
= Other Improvements
|
142
|
+
|
143
|
+
* The alter_table drop_constraint :primary_key option on SQLite now
|
144
|
+
works correctly for non-integer primary keys.
|
145
|
+
|
146
|
+
* When an error is raised due to an irreversible migration, the error
|
147
|
+
message now includes the file containing the migration for easier
|
148
|
+
debugging.
|