sequel 5.30.0 → 5.35.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 +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, '')}
|