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
@@ -0,0 +1,46 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A fiber_concurrency extension has been added, for using
|
4
|
+
Fiber.current instead of Thread.current when checking out a
|
5
|
+
connection. This allows separate fibers of the same thread
|
6
|
+
to use separate connections. In addition to allowing direct use
|
7
|
+
of fibers, this also allows concurrent use of multiple enumerators
|
8
|
+
that use database connections in the same thread.
|
9
|
+
|
10
|
+
When using this extension, you must be careful and ensure that you
|
11
|
+
are not using more concurrent fibers than your connection pool size.
|
12
|
+
Otherwise, all fibers will block while one fiber waits until a
|
13
|
+
connection is available. It is possible this issue will be
|
14
|
+
addressed when Ruby implements a fiber scheduler (currently
|
15
|
+
being discussed for inclusion in Ruby 3).
|
16
|
+
|
17
|
+
* A run_transaction_hooks Database extension has been added,
|
18
|
+
allowing for running the transaction hooks before commit/rollback,
|
19
|
+
which can be helpful for testing the hooks when using transactional
|
20
|
+
testing.
|
21
|
+
|
22
|
+
= Other Improvements
|
23
|
+
|
24
|
+
* Database#create_table? now works correctly with the :partition_of
|
25
|
+
option on PostgreSQL.
|
26
|
+
|
27
|
+
* The timestamp(N) with time zone type is now recognized by the
|
28
|
+
schema parser.
|
29
|
+
|
30
|
+
* Singleton methods of the Sequel module have now been moved into a
|
31
|
+
Sequel::SequelMethods module. This allows you to extend Sequel
|
32
|
+
with a module that overrides the methods and call super to get
|
33
|
+
the default behavior.
|
34
|
+
|
35
|
+
* The pg_inet extension no longer defines inet/cidr conversion procs
|
36
|
+
if sequel_pg 1.13.0+ is in use. This is because sequel_pg 1.13.0+
|
37
|
+
will respect the conversion procs and defining them makes things
|
38
|
+
slower. sequel_pg 1.13.0+ handles the same conversion by default
|
39
|
+
without needing a conversion proc.
|
40
|
+
|
41
|
+
* Method visibility issues in the model, plugin, extension, and adapter
|
42
|
+
code have been fixed. Most cases fixed were private methods being
|
43
|
+
accidentally made public when they were overridden.
|
44
|
+
|
45
|
+
During this change, Model#_insert_values was changed from public to
|
46
|
+
private, since it was originally intended to be private.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Custom join types are now supported on a per-association basis when
|
4
|
+
using eager_graph/association_join. This builds on the previous
|
5
|
+
support for custom aliases, using Sequel::SQL::AliasedExpression:
|
6
|
+
|
7
|
+
class Artist < Sequel::Model; end
|
8
|
+
class Album < Sequel::Model; end
|
9
|
+
class Track < Sequel::Model; end
|
10
|
+
Artist.one_to_many :albums
|
11
|
+
Album.one_to_many :tracks
|
12
|
+
Artist.eager_graph(
|
13
|
+
Sequel[:albums].as(:a, join_type: :inner) =>
|
14
|
+
Sequel[:tracks].as(:t, join_type: :left)
|
15
|
+
)
|
16
|
+
|
17
|
+
* A Database#current_timestamp_utc accessor has been added on SQLite.
|
18
|
+
Setting this to true will keep CURRENT_TIMESTAMP, CURRENT_TIME, and
|
19
|
+
CURRENT_DATE in UTC instead of converting them to localtime.
|
20
|
+
|
21
|
+
= Other Improvements
|
22
|
+
|
23
|
+
* The smallserial PostgreSQL type is now recognized and Sequel will
|
24
|
+
not try to mark smallserial columns as identity columns.
|
@@ -0,0 +1,40 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* The association_pks plugin now creates *_pks_dataset methods for
|
4
|
+
each association. These are similar to the existing *_pks getter
|
5
|
+
methods, but they return a dataset of the keys instead of the keys
|
6
|
+
themselves.
|
7
|
+
|
8
|
+
* The association_pks plugin now supports a :cache_pks association
|
9
|
+
option, which will cache calls to the *_pks getter method. The
|
10
|
+
default behavior remains that the *_pks getter method only returns
|
11
|
+
cached values if the *_pks= setter method has been used to set the
|
12
|
+
values.
|
13
|
+
|
14
|
+
* The *_pks getter methods supported by the association_pks plugin
|
15
|
+
now support a :refresh option to ignore any cached values, similar
|
16
|
+
to how the association getter methods work.
|
17
|
+
|
18
|
+
= Other Improvements
|
19
|
+
|
20
|
+
* If trying to disconnect a server that doesn't exist when using a
|
21
|
+
sharded connection pool, a Sequel::Error is now raised. Previously,
|
22
|
+
the sharded threaded pool raised a NoMethodError and the sharded
|
23
|
+
single connection pool did not raise an error.
|
24
|
+
|
25
|
+
* If using the :savepoint option when savepoints are not supported,
|
26
|
+
a Sequel::InvalidOperation exception is now raised, instead of a
|
27
|
+
NoMethodError.
|
28
|
+
|
29
|
+
* Calling Dataset#eager_graph with no arguments now returns the
|
30
|
+
dataset.
|
31
|
+
|
32
|
+
* If not connected to the database, the single connection pool will
|
33
|
+
not yield any connections to Database#pool.all_connections.
|
34
|
+
|
35
|
+
* Forcing a :ruby eager limit strategy for an association without a
|
36
|
+
limit or offset now works correctly.
|
37
|
+
|
38
|
+
* Multiple unnecessary conditionals have been removed.
|
39
|
+
|
40
|
+
* Sequel core and model code now have 100% branch coverage.
|
@@ -0,0 +1,56 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An instance_specific_default plugin has been added for setting the
|
4
|
+
default for the :instance_specific association option, or
|
5
|
+
warning/raises in cases where it is not specified. This allows
|
6
|
+
you to easily find associations that would be considering instance
|
7
|
+
specific by default, and mark them as not instance specific for
|
8
|
+
better performance.
|
9
|
+
|
10
|
+
= Other Improvements
|
11
|
+
|
12
|
+
* Setting the :instance_specific association option to false now
|
13
|
+
works correctly if the association uses a block. Associations
|
14
|
+
that set the :dataset option are now always considered instance
|
15
|
+
specific, even if the :instance_specific option is explicitly
|
16
|
+
passed.
|
17
|
+
|
18
|
+
* The validation_class_methods plugin now considers all :if,
|
19
|
+
:allow_missing, :allow_nil, and :allow_blank options. Previously,
|
20
|
+
it only considered the first of those options that was set.
|
21
|
+
|
22
|
+
* Model.finalize_associations no longer breaks if you have
|
23
|
+
instance-specific associations.
|
24
|
+
|
25
|
+
* Model.plugin now warns if you load the plugin with arguments or a
|
26
|
+
block if the plugin does not accept arguments or block. This is
|
27
|
+
because a future change to Sequel could break the call.
|
28
|
+
|
29
|
+
* When emulating unsupported alter table operations on SQLite, Sequel
|
30
|
+
now copies composite unique constraints unless the alter table
|
31
|
+
operation is the dropping of a unique constraint.
|
32
|
+
|
33
|
+
* Sequel now recognizes an additional disconnect error in the oracle
|
34
|
+
adapter.
|
35
|
+
|
36
|
+
* In the run_transaction_hooks extension, calling
|
37
|
+
run_after_{commit,rollback}_hooks now raises the correct exception
|
38
|
+
class.
|
39
|
+
|
40
|
+
* In the pg_range extension, conversion procs for the tsrange[] and
|
41
|
+
tstzrange[] types are not added unless the Database uses the
|
42
|
+
pg_array extension.
|
43
|
+
|
44
|
+
* Multiple unnecessary conditionals in plugins and extensions have
|
45
|
+
been removed.
|
46
|
+
|
47
|
+
* Sequel plugin and extension code now have 100% branch coverage.
|
48
|
+
|
49
|
+
* Sequel now avoids a statement not reached verbose warning in
|
50
|
+
Dataset#clone.
|
51
|
+
|
52
|
+
= Backwards Compatibility
|
53
|
+
|
54
|
+
* The output of Dataset#to_dot in the to_dot extension has changed
|
55
|
+
slightly, including hash entries with nil keys. These entries
|
56
|
+
were previously ignored.
|
data/doc/testing.rdoc
CHANGED
@@ -162,13 +162,13 @@ SEQUEL_CONNECTION_VALIDATOR :: Use the connection validator extension when runni
|
|
162
162
|
SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
|
163
163
|
SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
|
164
164
|
SEQUEL_INDEX_CACHING :: Use the index_caching extension when running the specs
|
165
|
+
SEQUEL_FIBER_CONCURRENCY :: Use the fiber_concurrency extension when running the adapter and integration specs
|
165
166
|
SEQUEL_FREEZE_DATABASE :: Freeze the database before running the integration specs
|
166
167
|
SEQUEL_IDENTIFIER_MANGLING :: Use the identifier_mangling extension when running the specs
|
167
168
|
SEQUEL_INTEGER64 :: Use the integer64 extension when running the adapter or integration specs
|
168
169
|
SEQUEL_MODEL_PREPARED_STATEMENTS :: Use the prepared_statements plugin when running the specs
|
169
170
|
SEQUEL_MODEL_THROW_FAILURES :: Use the throw_failures plugin when running the specs
|
170
171
|
SEQUEL_NO_CACHE_ASSOCIATIONS :: Don't cache association metadata when running the specs
|
171
|
-
SEQUEL_NO_CHECK_SQLS :: Don't check for specific SQL syntax when running the specs
|
172
172
|
SEQUEL_CHECK_PENDING :: Try running all specs (note, can cause lockups for some adapters), and raise errors for skipped specs that don't fail
|
173
173
|
SEQUEL_NO_PENDING :: Don't skip any specs, try running all specs (note, can cause lockups for some adapters)
|
174
174
|
SEQUEL_PG_TIMESTAMPTZ :: Use the pg_timestamptz extension when running the postgres specs
|
@@ -14,7 +14,8 @@ module Sequel
|
|
14
14
|
# ORA-02396: exceeded maximum idle time, please connect again
|
15
15
|
# ORA-03113: end-of-file on communication channel
|
16
16
|
# ORA-03114: not connected to ORACLE
|
17
|
-
|
17
|
+
# ORA-03135: connection lost contact
|
18
|
+
CONNECTION_ERROR_CODES = [ 28, 1012, 2396, 3113, 3114, 3135 ].freeze
|
18
19
|
|
19
20
|
ORACLE_TYPES = {
|
20
21
|
:blob=>lambda{|b| Sequel::SQL::Blob.new(b.read)},
|
@@ -171,6 +171,12 @@ module Sequel
|
|
171
171
|
clone(:into => table)
|
172
172
|
end
|
173
173
|
|
174
|
+
# Access uses [] for quoting identifiers, and can't handle
|
175
|
+
# ] inside identifiers.
|
176
|
+
def quoted_identifier_append(sql, v)
|
177
|
+
sql << '[' << v.to_s << ']'
|
178
|
+
end
|
179
|
+
|
174
180
|
# Access does not support derived column lists.
|
175
181
|
def supports_derived_column_lists?
|
176
182
|
false
|
@@ -279,12 +285,6 @@ module Sequel
|
|
279
285
|
literal_append(sql, l)
|
280
286
|
end
|
281
287
|
end
|
282
|
-
|
283
|
-
# Access uses [] for quoting identifiers, and can't handle
|
284
|
-
# ] inside identifiers.
|
285
|
-
def quoted_identifier_append(sql, v)
|
286
|
-
sql << '[' << v.to_s << ']'
|
287
|
-
end
|
288
288
|
end
|
289
289
|
end
|
290
290
|
end
|
@@ -775,11 +775,6 @@ module Sequel
|
|
775
775
|
end
|
776
776
|
end
|
777
777
|
|
778
|
-
# MSSQL does not allow ordering in sub-clauses unless TOP (limit) is specified
|
779
|
-
def aggregate_dataset
|
780
|
-
(options_overlap(Sequel::Dataset::COUNT_FROM_SELF_OPTS) && !options_overlap([:limit])) ? unordered.from_self : super
|
781
|
-
end
|
782
|
-
|
783
778
|
# If the dataset using a order without a limit or offset or custom SQL,
|
784
779
|
# remove the order. Compounds on Microsoft SQL Server have undefined
|
785
780
|
# order unless the result is specifically ordered. Applying the current
|
@@ -799,6 +794,11 @@ module Sequel
|
|
799
794
|
|
800
795
|
private
|
801
796
|
|
797
|
+
# MSSQL does not allow ordering in sub-clauses unless TOP (limit) is specified
|
798
|
+
def aggregate_dataset
|
799
|
+
(options_overlap(Sequel::Dataset::COUNT_FROM_SELF_OPTS) && !options_overlap([:limit])) ? unordered.from_self : super
|
800
|
+
end
|
801
|
+
|
802
802
|
# Allow update and delete for unordered, limited datasets only.
|
803
803
|
def check_not_limited!(type)
|
804
804
|
return if @opts[:skip_limit_check] && type != :truncate
|
@@ -717,15 +717,6 @@ module Sequel
|
|
717
717
|
SQL::PlaceholderLiteralString.new((opts[:boolean] ? MATCH_AGAINST_BOOLEAN : MATCH_AGAINST), [Array(cols), terms])
|
718
718
|
end
|
719
719
|
|
720
|
-
# Transforms :straight to STRAIGHT_JOIN.
|
721
|
-
def join_type_sql(join_type)
|
722
|
-
if join_type == :straight
|
723
|
-
'STRAIGHT_JOIN'
|
724
|
-
else
|
725
|
-
super
|
726
|
-
end
|
727
|
-
end
|
728
|
-
|
729
720
|
# Sets up the insert methods to use INSERT IGNORE.
|
730
721
|
# Useful if you have a unique key and want to just skip
|
731
722
|
# inserting rows that violate the unique key restriction.
|
@@ -956,6 +947,15 @@ module Sequel
|
|
956
947
|
end
|
957
948
|
end
|
958
949
|
|
950
|
+
# Transforms :straight to STRAIGHT_JOIN.
|
951
|
+
def join_type_sql(join_type)
|
952
|
+
if join_type == :straight
|
953
|
+
'STRAIGHT_JOIN'
|
954
|
+
else
|
955
|
+
super
|
956
|
+
end
|
957
|
+
end
|
958
|
+
|
959
959
|
# MySQL allows a LIMIT in DELETE and UPDATE statements.
|
960
960
|
def limit_sql(sql)
|
961
961
|
if l = @opts[:limit]
|
@@ -422,22 +422,6 @@ module Sequel
|
|
422
422
|
end
|
423
423
|
end
|
424
424
|
|
425
|
-
def select_limit_sql(sql)
|
426
|
-
return unless supports_fetch_next_rows?
|
427
|
-
|
428
|
-
if offset = @opts[:offset]
|
429
|
-
sql << " OFFSET "
|
430
|
-
literal_append(sql, offset)
|
431
|
-
sql << " ROWS"
|
432
|
-
end
|
433
|
-
|
434
|
-
if limit = @opts[:limit]
|
435
|
-
sql << " FETCH NEXT "
|
436
|
-
literal_append(sql, limit)
|
437
|
-
sql << " ROWS ONLY"
|
438
|
-
end
|
439
|
-
end
|
440
|
-
|
441
425
|
# Oracle requires recursive CTEs to have column aliases.
|
442
426
|
def recursive_cte_requires_column_aliases?
|
443
427
|
true
|
@@ -624,6 +608,22 @@ module Sequel
|
|
624
608
|
:union
|
625
609
|
end
|
626
610
|
|
611
|
+
def select_limit_sql(sql)
|
612
|
+
return unless supports_fetch_next_rows?
|
613
|
+
|
614
|
+
if offset = @opts[:offset]
|
615
|
+
sql << " OFFSET "
|
616
|
+
literal_append(sql, offset)
|
617
|
+
sql << " ROWS"
|
618
|
+
end
|
619
|
+
|
620
|
+
if limit = @opts[:limit]
|
621
|
+
sql << " FETCH NEXT "
|
622
|
+
literal_append(sql, limit)
|
623
|
+
sql << " ROWS ONLY"
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
627
|
# Use SKIP LOCKED if skipping locked rows.
|
628
628
|
def select_lock_sql(sql)
|
629
629
|
super
|
@@ -134,6 +134,96 @@ module Sequel
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
+
# Generator used for creating tables that are partitions of other tables.
|
138
|
+
class CreatePartitionOfTableGenerator
|
139
|
+
MINVALUE = Sequel.lit('MINVALUE').freeze
|
140
|
+
MAXVALUE = Sequel.lit('MAXVALUE').freeze
|
141
|
+
|
142
|
+
def initialize(&block)
|
143
|
+
instance_exec(&block)
|
144
|
+
end
|
145
|
+
|
146
|
+
# The minimum value of the data type used in range partitions, useful
|
147
|
+
# as an argument to #from.
|
148
|
+
def minvalue
|
149
|
+
MINVALUE
|
150
|
+
end
|
151
|
+
|
152
|
+
# The minimum value of the data type used in range partitions, useful
|
153
|
+
# as an argument to #to.
|
154
|
+
def maxvalue
|
155
|
+
MAXVALUE
|
156
|
+
end
|
157
|
+
|
158
|
+
# Assumes range partitioning, sets the inclusive minimum value of the range for
|
159
|
+
# this partition.
|
160
|
+
def from(*v)
|
161
|
+
@from = v
|
162
|
+
end
|
163
|
+
|
164
|
+
# Assumes range partitioning, sets the exclusive maximum value of the range for
|
165
|
+
# this partition.
|
166
|
+
def to(*v)
|
167
|
+
@to = v
|
168
|
+
end
|
169
|
+
|
170
|
+
# Assumes list partitioning, sets the values to be included in this partition.
|
171
|
+
def values_in(*v)
|
172
|
+
@in = v
|
173
|
+
end
|
174
|
+
|
175
|
+
# Assumes hash partitioning, sets the modulus for this parition.
|
176
|
+
def modulus(v)
|
177
|
+
@modulus = v
|
178
|
+
end
|
179
|
+
|
180
|
+
# Assumes hash partitioning, sets the remainder for this parition.
|
181
|
+
def remainder(v)
|
182
|
+
@remainder = v
|
183
|
+
end
|
184
|
+
|
185
|
+
# Sets that this is a default partition, where values not in other partitions
|
186
|
+
# are stored.
|
187
|
+
def default
|
188
|
+
@default = true
|
189
|
+
end
|
190
|
+
|
191
|
+
# The from and to values of this partition for a range partition.
|
192
|
+
def range
|
193
|
+
[@from, @to]
|
194
|
+
end
|
195
|
+
|
196
|
+
# The values to include in this partition for a list partition.
|
197
|
+
def list
|
198
|
+
@in
|
199
|
+
end
|
200
|
+
|
201
|
+
# The modulus and remainder to use for this partition for a hash partition.
|
202
|
+
def hash_values
|
203
|
+
[@modulus, @remainder]
|
204
|
+
end
|
205
|
+
|
206
|
+
# Determine the appropriate partition type for this partition by which methods
|
207
|
+
# were called on it.
|
208
|
+
def partition_type
|
209
|
+
raise Error, "Unable to determine partition type, multiple different partitioning methods called" if [@from || @to, @list, @modulus || @remainder, @default].compact.length > 1
|
210
|
+
|
211
|
+
if @from || @to
|
212
|
+
raise Error, "must call both from and to when creating a partition of a table if calling either" unless @from && @to
|
213
|
+
:range
|
214
|
+
elsif @in
|
215
|
+
:list
|
216
|
+
elsif @modulus || @remainder
|
217
|
+
raise Error, "must call both modulus and remainder when creating a partition of a table if calling either" unless @modulus && @remainder
|
218
|
+
:hash
|
219
|
+
elsif @default
|
220
|
+
:default
|
221
|
+
else
|
222
|
+
raise Error, "unable to determine partition type, no partitioning methods called"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
137
227
|
# Error raised when Sequel determines a PostgreSQL exclusion constraint has been violated.
|
138
228
|
class ExclusionConstraintViolation < Sequel::ConstraintViolation; end
|
139
229
|
|
@@ -359,6 +449,26 @@ module Sequel
|
|
359
449
|
self << create_schema_sql(name, opts)
|
360
450
|
end
|
361
451
|
|
452
|
+
# Support partitions of tables using the :partition_of option.
|
453
|
+
def create_table(name, options=OPTS, &block)
|
454
|
+
if options[:partition_of]
|
455
|
+
create_partition_of_table_from_generator(name, CreatePartitionOfTableGenerator.new(&block), options)
|
456
|
+
return
|
457
|
+
end
|
458
|
+
|
459
|
+
super
|
460
|
+
end
|
461
|
+
|
462
|
+
# Support partitions of tables using the :partition_of option.
|
463
|
+
def create_table?(name, options=OPTS, &block)
|
464
|
+
if options[:partition_of]
|
465
|
+
create_table(name, options.merge!(:if_not_exists=>true), &block)
|
466
|
+
return
|
467
|
+
end
|
468
|
+
|
469
|
+
super
|
470
|
+
end
|
471
|
+
|
362
472
|
# Create a trigger in the database. Arguments:
|
363
473
|
# table :: the table on which this trigger operates
|
364
474
|
# name :: the name of this trigger
|
@@ -840,7 +950,7 @@ module Sequel
|
|
840
950
|
# default value is given.
|
841
951
|
def column_definition_default_sql(sql, column)
|
842
952
|
super
|
843
|
-
if !column[:serial] && !['serial', 'bigserial'].include?(column[:type].to_s) && !column[:default]
|
953
|
+
if !column[:serial] && !['smallserial', 'serial', 'bigserial'].include?(column[:type].to_s) && !column[:default]
|
844
954
|
if (identity = column[:identity])
|
845
955
|
sql << " GENERATED "
|
846
956
|
sql << (identity == :always ? "ALWAYS" : "BY DEFAULT")
|
@@ -1018,6 +1128,36 @@ module Sequel
|
|
1018
1128
|
"CREATE#{' OR REPLACE' if opts[:replace] && server_version >= 90000}#{' TRUSTED' if opts[:trusted]} LANGUAGE #{name}#{" HANDLER #{opts[:handler]}" if opts[:handler]}#{" VALIDATOR #{opts[:validator]}" if opts[:validator]}"
|
1019
1129
|
end
|
1020
1130
|
|
1131
|
+
# Create a partition of another table, used when the create_table with
|
1132
|
+
# the :partition_of option is given.
|
1133
|
+
def create_partition_of_table_from_generator(name, generator, options)
|
1134
|
+
execute_ddl(create_partition_of_table_sql(name, generator, options))
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
# SQL for creating a partition of another table.
|
1138
|
+
def create_partition_of_table_sql(name, generator, options)
|
1139
|
+
sql = create_table_prefix_sql(name, options).dup
|
1140
|
+
|
1141
|
+
sql << " PARTITION OF #{quote_schema_table(options[:partition_of])}"
|
1142
|
+
|
1143
|
+
case generator.partition_type
|
1144
|
+
when :range
|
1145
|
+
from, to = generator.range
|
1146
|
+
sql << " FOR VALUES FROM #{literal(from)} TO #{literal(to)}"
|
1147
|
+
when :list
|
1148
|
+
sql << " FOR VALUES IN #{literal(generator.list)}"
|
1149
|
+
when :hash
|
1150
|
+
mod, remainder = generator.hash_values
|
1151
|
+
sql << " FOR VALUES WITH (MODULUS #{literal(mod)}, REMAINDER #{literal(remainder)})"
|
1152
|
+
when :default
|
1153
|
+
sql << " DEFAULT"
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
sql << create_table_suffix_sql(name, options)
|
1157
|
+
|
1158
|
+
sql
|
1159
|
+
end
|
1160
|
+
|
1021
1161
|
# SQL for creating a schema.
|
1022
1162
|
def create_schema_sql(name, opts=OPTS)
|
1023
1163
|
"CREATE SCHEMA #{'IF NOT EXISTS ' if opts[:if_not_exists]}#{quote_identifier(name)}#{" AUTHORIZATION #{literal(opts[:owner])}" if opts[:owner]}"
|
@@ -1039,25 +1179,36 @@ module Sequel
|
|
1039
1179
|
"CREATE #{prefix_sql}TABLE#{' IF NOT EXISTS' if options[:if_not_exists]} #{options[:temp] ? quote_identifier(name) : quote_schema_table(name)}"
|
1040
1180
|
end
|
1041
1181
|
|
1182
|
+
# SQL for creating a table with PostgreSQL specific options
|
1042
1183
|
def create_table_sql(name, generator, options)
|
1043
|
-
|
1184
|
+
"#{super}#{create_table_suffix_sql(name, options)}"
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
# Handle various PostgreSQl specific table extensions such as inheritance,
|
1188
|
+
# partitioning, tablespaces, and foreign tables.
|
1189
|
+
def create_table_suffix_sql(name, options)
|
1190
|
+
sql = String.new
|
1044
1191
|
|
1045
1192
|
if inherits = options[:inherits]
|
1046
|
-
sql
|
1193
|
+
sql << " INHERITS (#{Array(inherits).map{|t| quote_schema_table(t)}.join(', ')})"
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
if partition_by = options[:partition_by]
|
1197
|
+
sql << " PARTITION BY #{options[:partition_type]||'RANGE'} #{literal(Array(partition_by))}"
|
1047
1198
|
end
|
1048
1199
|
|
1049
1200
|
if on_commit = options[:on_commit]
|
1050
1201
|
raise(Error, "can't provide :on_commit without :temp to create_table") unless options[:temp]
|
1051
1202
|
raise(Error, "unsupported on_commit option: #{on_commit.inspect}") unless ON_COMMIT.has_key?(on_commit)
|
1052
|
-
sql
|
1203
|
+
sql << " ON COMMIT #{ON_COMMIT[on_commit]}"
|
1053
1204
|
end
|
1054
1205
|
|
1055
1206
|
if tablespace = options[:tablespace]
|
1056
|
-
sql
|
1207
|
+
sql << " TABLESPACE #{quote_identifier(tablespace)}"
|
1057
1208
|
end
|
1058
1209
|
|
1059
1210
|
if server = options[:foreign]
|
1060
|
-
sql
|
1211
|
+
sql << " SERVER #{quote_identifier(server)}"
|
1061
1212
|
if foreign_opts = options[:options]
|
1062
1213
|
sql << " OPTIONS (#{foreign_opts.map{|k, v| "#{k} #{literal(v.to_s)}"}.join(', ')})"
|
1063
1214
|
end
|
@@ -1273,6 +1424,10 @@ module Sequel
|
|
1273
1424
|
|
1274
1425
|
if server_version > 100000
|
1275
1426
|
ds = ds.select_append{pg_attribute[:attidentity]}
|
1427
|
+
|
1428
|
+
if server_version > 120000
|
1429
|
+
ds = ds.select_append{Sequel.~(pg_attribute[:attgenerated]=>'').as(:generated)}
|
1430
|
+
end
|
1276
1431
|
end
|
1277
1432
|
|
1278
1433
|
ds.map do |row|
|
@@ -1751,6 +1906,14 @@ module Sequel
|
|
1751
1906
|
end
|
1752
1907
|
end
|
1753
1908
|
|
1909
|
+
def to_prepared_statement(type, *a)
|
1910
|
+
if type == :insert && !@opts.has_key?(:returning)
|
1911
|
+
returning(insert_pk).send(:to_prepared_statement, :insert_pk, *a)
|
1912
|
+
else
|
1913
|
+
super
|
1914
|
+
end
|
1915
|
+
end
|
1916
|
+
|
1754
1917
|
private
|
1755
1918
|
|
1756
1919
|
# Format TRUNCATE statement with PostgreSQL specific options.
|
@@ -1965,14 +2128,6 @@ module Sequel
|
|
1965
2128
|
true
|
1966
2129
|
end
|
1967
2130
|
|
1968
|
-
def to_prepared_statement(type, *a)
|
1969
|
-
if type == :insert && !@opts.has_key?(:returning)
|
1970
|
-
returning(insert_pk).send(:to_prepared_statement, :insert_pk, *a)
|
1971
|
-
else
|
1972
|
-
super
|
1973
|
-
end
|
1974
|
-
end
|
1975
|
-
|
1976
2131
|
# Concatenate the expressions with a space in between
|
1977
2132
|
def full_text_string_join(cols)
|
1978
2133
|
cols = Array(cols).map{|x| SQL::Function.new(:COALESCE, x, '')}
|