sequel 5.66.0 → 5.68.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 +26 -0
- data/doc/advanced_associations.rdoc +3 -1
- data/doc/release_notes/5.67.0.txt +32 -0
- data/doc/release_notes/5.68.0.txt +61 -0
- data/lib/sequel/adapters/shared/mssql.rb +7 -2
- data/lib/sequel/adapters/shared/postgres.rb +67 -3
- data/lib/sequel/database/dataset.rb +16 -6
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/deprecated_singleton_class_methods.rb +42 -0
- data/lib/sequel/dataset/query.rb +53 -28
- data/lib/sequel/dataset.rb +4 -0
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -1
- data/lib/sequel/extensions/pg_enum.rb +1 -2
- data/lib/sequel/extensions/pg_extended_date_support.rb +10 -2
- data/lib/sequel/extensions/pg_multirange.rb +1 -1
- data/lib/sequel/extensions/pg_range.rb +1 -1
- data/lib/sequel/extensions/pg_row.rb +2 -6
- data/lib/sequel/extensions/schema_dumper.rb +32 -9
- data/lib/sequel/extensions/set_literalizer.rb +58 -0
- data/lib/sequel/plugins/constraint_validations.rb +8 -5
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +3 -1
- data/lib/sequel/plugins/prepared_statements.rb +2 -1
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +8 -1
- data/lib/sequel/plugins/validation_helpers_generic_type_messages.rb +73 -0
- data/lib/sequel/version.rb +1 -1
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e682467c455e044847fffb313b6d8a669e0dc89ca8ea330468841de642b84227
|
4
|
+
data.tar.gz: cd0687fd059a6b6d38cb31279d5cdacccd4a0a309f1155171f12551d43eacb0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c16f027251aa67e04cab0973a57da21682e083c7362f37bdbf84937266ca6878e200fb7c44a0583b8ac6fab62d1fd4b55744929760fc63a9d1f850452db5df6
|
7
|
+
data.tar.gz: 60eee01297c47ee9c18ae76b6974b6eb3e492e58c7f408ee9c32476f1ae0ae5848ffc47cb80889f7070b02088e7e66509b64e460a1ef61c90ffb5a59da6a3c09
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
=== 5.68.0 (2023-05-01)
|
2
|
+
|
3
|
+
* Add validation_helpers_generic_type_messages plugin for more useful type validation failure messages (jeremyevans) (#2028)
|
4
|
+
|
5
|
+
* Make constraint_validations plugin not validate missing columns that have a default value (jeremyevans) (#2023)
|
6
|
+
|
7
|
+
* Skip normal type name parsing for enum/array/composite/range/multirange types on PostgreSQL (jeremyevans) (#2019)
|
8
|
+
|
9
|
+
* Fix corner case where pg_extended_date_support did not work correctly when using the jdbc/postgresql adapter (jeremyevans)
|
10
|
+
|
11
|
+
* Include :min_value and :max_value schema entries for date/timestamp/timestamptz columns on PostgreSQL 9.6+ (jeremyevans)
|
12
|
+
|
13
|
+
=== 5.67.0 (2023-04-01)
|
14
|
+
|
15
|
+
* Fix dumping of string column sizes in the schema dumper on MSSQL (jeremyevans) (#2013)
|
16
|
+
|
17
|
+
* Improve dumping of tables in non-default schemas in the schema_dumper extension (jeremyevans) (#2006)
|
18
|
+
|
19
|
+
* Make Database#{tables,views} support :qualify option on Microsoft SQL Server (jeremyevans)
|
20
|
+
|
21
|
+
* Avoid use of singleton classes for datasets instances on Ruby 2.4+ (jeremyevans) (#2007)
|
22
|
+
|
23
|
+
* Deprecate registering datasets extensions using an object other than a module (jeremyevans)
|
24
|
+
|
25
|
+
* Add set_literalizer extension, for treating set usage in datasets similar to array usage (jeremyevans) (#1997)
|
26
|
+
|
1
27
|
=== 5.66.0 (2023-03-01)
|
2
28
|
|
3
29
|
* Recognize SQLite error related to strict tables as a constraint violation when using the amalgalite adapter (jeremyevans)
|
@@ -670,8 +670,10 @@ polymorphic associations in Sequel about as easy as it is in ActiveRecord. Howe
|
|
670
670
|
here's how they can be done using Sequel's custom associations (the sequel_polymorphic
|
671
671
|
external plugin is just a generic version of this code):
|
672
672
|
|
673
|
+
Sequel.extension :inflector # for attachable_type.constantize
|
674
|
+
|
673
675
|
class Asset < Sequel::Model
|
674
|
-
many_to_one :attachable, reciprocal: :assets,
|
676
|
+
many_to_one :attachable, reciprocal: :assets, reciprocal_type: :one_to_many,
|
675
677
|
setter: (lambda do |attachable|
|
676
678
|
self[:attachable_id] = (attachable.pk if attachable)
|
677
679
|
self[:attachable_type] = (attachable.class.name if attachable)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A set_literalizer extension has been added, for treating Set
|
4
|
+
instances in datasets similar to Array instances:
|
5
|
+
|
6
|
+
DB.extension :set_literalizer
|
7
|
+
DB[:table].where(column: Set.new([1, 2, 3]))
|
8
|
+
# SELECT FROM table WHERE (column IN (1, 2, 3))
|
9
|
+
|
10
|
+
= Improvements
|
11
|
+
|
12
|
+
* Sequel now avoids the use of singleton classes for datasets on Ruby
|
13
|
+
2.4+, instead creating a regular subclass whenever a dataset would
|
14
|
+
be extended via #extension or #with_extend. This significantly
|
15
|
+
improves performance, up to 20-40% for common dataset usage,
|
16
|
+
because it avoids creating new singleton classes for every dataset
|
17
|
+
clone, and it allows for cached method lookup.
|
18
|
+
|
19
|
+
* Database#tables and #views now support a :qualify option on Microsoft
|
20
|
+
SQL Server to returned qualified identifiers.
|
21
|
+
|
22
|
+
* The schema_dumper extension can now dump tables in non-default schemas
|
23
|
+
when using Microsoft SQL Server.
|
24
|
+
|
25
|
+
* The schema_dumper extension now correctly dumps string column sizes
|
26
|
+
when using Microsoft SQL Server.
|
27
|
+
|
28
|
+
= Backwards Compatibility
|
29
|
+
|
30
|
+
* Calling Sequel::Dataset.register_extension where the second argument
|
31
|
+
is not a module now issues a deprecation warning. Support for this
|
32
|
+
will be removed in Sequel 6.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* On PostgreSQL 9.6+, date, timestamp, and timestamptz columns now
|
4
|
+
have min_value and max_value column schema entries, allowing the
|
5
|
+
auto_validations plugin to automatically enforce minimum and
|
6
|
+
maximum values for these column types, raising a validation error
|
7
|
+
before saving, instead of database error when the query is sent
|
8
|
+
to the database.
|
9
|
+
|
10
|
+
* A validation_helpers_generic_type_messages plugin has been added,
|
11
|
+
which improves the default type validation error messages in
|
12
|
+
validation_helpers. This change was not made directly to
|
13
|
+
validation_helpers for backwards compatibility reasons, but will
|
14
|
+
probably become the default behavior in Sequel 6. Some examples
|
15
|
+
of the improvements:
|
16
|
+
|
17
|
+
# :blob type
|
18
|
+
# validation_helpers default: "value is not a valid sequel::sql::blob"
|
19
|
+
# with this plugin: "value is not a blob"
|
20
|
+
|
21
|
+
# :boolean type
|
22
|
+
# validation_helpers default: "value is not a valid trueclass or falseclass"
|
23
|
+
# with this plugin: "value is not true or false"
|
24
|
+
|
25
|
+
# :datetime type
|
26
|
+
# validation_helpers default: "value is not a valid time or datetime"
|
27
|
+
# with this plugin: "value is not a valid timestamp"
|
28
|
+
|
29
|
+
# custom/database-specific types
|
30
|
+
# validation_helpers default: "value is not a valid sequel::class_name"
|
31
|
+
# with this plugin: "value is not the expected type"
|
32
|
+
|
33
|
+
= Improvements
|
34
|
+
|
35
|
+
* The constraint_validations plugin no longer raises validation
|
36
|
+
errors for missing columns that have a default value. If a column
|
37
|
+
is missing but has a default value, we can assume the default
|
38
|
+
value is valid. Additionally, the constraint validations are now
|
39
|
+
based on the underlying column value and not any deserialized
|
40
|
+
value, so that the validation matches the constraint.
|
41
|
+
|
42
|
+
* On PostgreSQL, normal type name parsing is skipped for enum,
|
43
|
+
array, composite, range, and multirange types, ensuring that
|
44
|
+
such types will not be treated incorrectly based on their
|
45
|
+
type name.
|
46
|
+
|
47
|
+
* The pg_extended_date_support extension now works correctly with
|
48
|
+
the jdbc/postgresql adapter if there is already an entry in the
|
49
|
+
oid_convertor_map for the timestamp and timestamptz types.
|
50
|
+
|
51
|
+
= Backwards Compatibility
|
52
|
+
|
53
|
+
* Database#schema_column_type is no longer called for all columns
|
54
|
+
on PostgreSQL when parsing schema. Enum, array, composite, range,
|
55
|
+
and multirange types each have their own separate type parsing
|
56
|
+
method. So if you were overriding Database#schema_column_type to
|
57
|
+
implement custom column schema parsing, you may need to adjust
|
58
|
+
your code.
|
59
|
+
|
60
|
+
* The Sequel::Postgres::ExtendedDateSupport::DATE_YEAR_1 constant
|
61
|
+
has been removed.
|
@@ -404,10 +404,15 @@ module Sequel
|
|
404
404
|
# Backbone of the tables and views support.
|
405
405
|
def information_schema_tables(type, opts)
|
406
406
|
m = output_identifier_meth
|
407
|
-
|
407
|
+
schema = opts[:schema]||'dbo'
|
408
|
+
tables = metadata_dataset.from(Sequel[:information_schema][:tables].as(:t)).
|
408
409
|
select(:table_name).
|
409
|
-
where(:table_type=>type, :table_schema=>
|
410
|
+
where(:table_type=>type, :table_schema=>schema.to_s).
|
410
411
|
map{|x| m.call(x[:table_name])}
|
412
|
+
|
413
|
+
tables.map!{|t| Sequel.qualify(m.call(schema).to_s, m.call(t).to_s)} if opts[:qualify]
|
414
|
+
|
415
|
+
tables
|
411
416
|
end
|
412
417
|
|
413
418
|
# Always quote identifiers in the metadata_dataset, so schema parsing works.
|
@@ -1007,11 +1007,15 @@ module Sequel
|
|
1007
1007
|
SQL::Function.new(:format_type, pg_type[:oid], pg_attribute[:atttypmod]).as(:db_type),
|
1008
1008
|
SQL::Function.new(:pg_get_expr, pg_attrdef[:adbin], pg_class[:oid]).as(:default),
|
1009
1009
|
SQL::BooleanExpression.new(:NOT, pg_attribute[:attnotnull]).as(:allow_null),
|
1010
|
-
SQL::Function.new(:COALESCE, SQL::BooleanExpression.from_value_pairs(pg_attribute[:attnum] => SQL::Function.new(:ANY, pg_index[:indkey])), false).as(:primary_key)
|
1010
|
+
SQL::Function.new(:COALESCE, SQL::BooleanExpression.from_value_pairs(pg_attribute[:attnum] => SQL::Function.new(:ANY, pg_index[:indkey])), false).as(:primary_key),
|
1011
|
+
Sequel[:pg_type][:typtype],
|
1012
|
+
(~Sequel[Sequel[:elementtype][:oid]=>nil]).as(:is_array),
|
1013
|
+
]}.
|
1011
1014
|
from(:pg_class).
|
1012
1015
|
join(:pg_attribute, :attrelid=>:oid).
|
1013
1016
|
join(:pg_type, :oid=>:atttypid).
|
1014
1017
|
left_outer_join(Sequel[:pg_type].as(:basetype), :oid=>:typbasetype).
|
1018
|
+
left_outer_join(Sequel[:pg_type].as(:elementtype), :typarray=>Sequel[:pg_type][:oid]).
|
1015
1019
|
left_outer_join(:pg_attrdef, :adrelid=>Sequel[:pg_class][:oid], :adnum=>Sequel[:pg_attribute][:attnum]).
|
1016
1020
|
left_outer_join(:pg_index, :indrelid=>Sequel[:pg_class][:oid], :indisprimary=>true).
|
1017
1021
|
where{{pg_attribute[:attisdropped]=>false}}.
|
@@ -1538,11 +1542,12 @@ module Sequel
|
|
1538
1542
|
end
|
1539
1543
|
|
1540
1544
|
# SQL DDL statement for renaming a table. PostgreSQL doesn't allow you to change a table's schema in
|
1541
|
-
# a rename table operation, so
|
1545
|
+
# a rename table operation, so specifying a new schema in new_name will not have an effect.
|
1542
1546
|
def rename_table_sql(name, new_name)
|
1543
1547
|
"ALTER TABLE #{quote_schema_table(name)} RENAME TO #{quote_identifier(schema_and_table(new_name).last)}"
|
1544
1548
|
end
|
1545
1549
|
|
1550
|
+
# Handle interval and citext types.
|
1546
1551
|
def schema_column_type(db_type)
|
1547
1552
|
case db_type
|
1548
1553
|
when /\Ainterval\z/io
|
@@ -1554,6 +1559,43 @@ module Sequel
|
|
1554
1559
|
end
|
1555
1560
|
end
|
1556
1561
|
|
1562
|
+
# The schema :type entry to use for array types.
|
1563
|
+
def schema_array_type(db_type)
|
1564
|
+
:array
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
# The schema :type entry to use for row/composite types.
|
1568
|
+
def schema_composite_type(db_type)
|
1569
|
+
:composite
|
1570
|
+
end
|
1571
|
+
|
1572
|
+
# The schema :type entry to use for enum types.
|
1573
|
+
def schema_enum_type(db_type)
|
1574
|
+
:enum
|
1575
|
+
end
|
1576
|
+
|
1577
|
+
# The schema :type entry to use for range types.
|
1578
|
+
def schema_range_type(db_type)
|
1579
|
+
:range
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
# The schema :type entry to use for multirange types.
|
1583
|
+
def schema_multirange_type(db_type)
|
1584
|
+
:multirange
|
1585
|
+
end
|
1586
|
+
|
1587
|
+
MIN_DATE = Date.new(-4713, 11, 24)
|
1588
|
+
MAX_DATE = Date.new(5874897, 12, 31)
|
1589
|
+
MIN_TIMESTAMP = Time.utc(-4713, 11, 24).freeze
|
1590
|
+
MAX_TIMESTAMP = (Time.utc(294277) - Rational(1, 1000000)).freeze
|
1591
|
+
TYPTYPE_METHOD_MAP = {
|
1592
|
+
'c' => :schema_composite_type,
|
1593
|
+
'e' => :schema_enum_type,
|
1594
|
+
'r' => :schema_range_type,
|
1595
|
+
'm' => :schema_multirange_type,
|
1596
|
+
}
|
1597
|
+
TYPTYPE_METHOD_MAP.default = :schema_column_type
|
1598
|
+
TYPTYPE_METHOD_MAP.freeze
|
1557
1599
|
# The dataset used for parsing table schemas, using the pg_* system catalogs.
|
1558
1600
|
def schema_parse_table(table_name, opts)
|
1559
1601
|
m = output_identifier_meth(opts[:dataset])
|
@@ -1569,11 +1611,33 @@ module Sequel
|
|
1569
1611
|
row.delete(:base_oid)
|
1570
1612
|
row.delete(:db_base_type)
|
1571
1613
|
end
|
1572
|
-
|
1614
|
+
|
1615
|
+
db_type = row[:db_type]
|
1616
|
+
row[:type] = if row.delete(:is_array)
|
1617
|
+
schema_array_type(db_type)
|
1618
|
+
else
|
1619
|
+
send(TYPTYPE_METHOD_MAP[row.delete(:typtype)], db_type)
|
1620
|
+
end
|
1573
1621
|
identity = row.delete(:attidentity)
|
1574
1622
|
if row[:primary_key]
|
1575
1623
|
row[:auto_increment] = !!(row[:default] =~ /\A(?:nextval)/i) || identity == 'a' || identity == 'd'
|
1576
1624
|
end
|
1625
|
+
|
1626
|
+
# :nocov:
|
1627
|
+
if server_version >= 90600
|
1628
|
+
# :nocov:
|
1629
|
+
case row[:oid]
|
1630
|
+
when 1082
|
1631
|
+
row[:min_value] = MIN_DATE
|
1632
|
+
row[:max_value] = MAX_DATE
|
1633
|
+
when 1184, 1114
|
1634
|
+
if Sequel.datetime_class == Time
|
1635
|
+
row[:min_value] = MIN_TIMESTAMP
|
1636
|
+
row[:max_value] = MAX_TIMESTAMP
|
1637
|
+
end
|
1638
|
+
end
|
1639
|
+
end
|
1640
|
+
|
1577
1641
|
[m.call(row.delete(:name)), row]
|
1578
1642
|
end
|
1579
1643
|
end
|
@@ -30,19 +30,29 @@ module Sequel
|
|
30
30
|
@dataset_class.new(self)
|
31
31
|
end
|
32
32
|
|
33
|
-
#
|
34
|
-
# it is used to iterate over the records:
|
33
|
+
# Returns a dataset instance for the given SQL string:
|
35
34
|
#
|
36
|
-
# DB.fetch('SELECT * FROM items')
|
35
|
+
# ds = DB.fetch('SELECT * FROM items')
|
36
|
+
#
|
37
|
+
# You can then call methods on the dataset to retrieve results:
|
37
38
|
#
|
38
|
-
#
|
39
|
+
# ds.all
|
40
|
+
# # SELECT * FROM items
|
41
|
+
# # => [{:column=>value, ...}, ...]
|
39
42
|
#
|
40
|
-
#
|
43
|
+
# If a block is given, it is passed to #each on the resulting dataset to
|
44
|
+
# iterate over the records returned by the query:
|
45
|
+
#
|
46
|
+
# DB.fetch('SELECT * FROM items'){|r| p r}
|
47
|
+
# # {:column=>value, ...}
|
48
|
+
# # ...
|
41
49
|
#
|
42
50
|
# +fetch+ can also perform parameterized queries for protection against SQL
|
43
51
|
# injection:
|
44
52
|
#
|
45
|
-
# DB.fetch('SELECT * FROM items WHERE name = ?',
|
53
|
+
# ds = DB.fetch('SELECT * FROM items WHERE name = ?', "my name")
|
54
|
+
# ds.all
|
55
|
+
# # SELECT * FROM items WHERE name = 'my name'
|
46
56
|
#
|
47
57
|
# See caveats listed in Dataset#with_sql regarding datasets using custom
|
48
58
|
# SQL and the methods that can be called on them.
|
@@ -307,7 +307,7 @@ module Sequel
|
|
307
307
|
# Examples:
|
308
308
|
# primary_key(:id)
|
309
309
|
# primary_key(:id, type: :Bignum, keep_order: true)
|
310
|
-
# primary_key([:street_number, :house_number], name: :
|
310
|
+
# primary_key([:street_number, :house_number], name: :some_constraint_name)
|
311
311
|
def primary_key(name, *args)
|
312
312
|
return composite_primary_key(name, *args) if name.is_a?(Array)
|
313
313
|
column = @db.serial_primary_key_options.merge({:name => name})
|
@@ -900,7 +900,7 @@ module Sequel
|
|
900
900
|
#
|
901
901
|
# Any other object given is just converted to a string, with "_" converted to " " and upcased.
|
902
902
|
def on_delete_clause(action)
|
903
|
-
action.to_s.
|
903
|
+
action.to_s.tr("_", " ").upcase
|
904
904
|
end
|
905
905
|
|
906
906
|
# Alias of #on_delete_clause, since the two usually behave the same.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
class Dataset
|
5
|
+
# This module implements methods to support deprecated use of extensions registered
|
6
|
+
# not using a module. In such cases, for backwards compatibility, Sequel has to use
|
7
|
+
# a singleton class for the dataset.
|
8
|
+
module DeprecatedSingletonClassMethods
|
9
|
+
# Load the extension into a clone of the receiver.
|
10
|
+
def extension(*a)
|
11
|
+
c = _clone(:freeze=>false)
|
12
|
+
c.send(:_extension!, a)
|
13
|
+
c.freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
# Extend the cloned of the receiver with the given modules, instead of the default
|
17
|
+
# approach of creating a subclass of the receiver's class and including the modules
|
18
|
+
# into that.
|
19
|
+
def with_extend(*mods, &block)
|
20
|
+
c = _clone(:freeze=>false)
|
21
|
+
c.extend(*mods) unless mods.empty?
|
22
|
+
c.extend(DatasetModule.new(&block)) if block
|
23
|
+
c.freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Load the extensions into the receiver.
|
29
|
+
def _extension!(exts)
|
30
|
+
Sequel.extension(*exts)
|
31
|
+
exts.each do |ext|
|
32
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
33
|
+
pr.call(self)
|
34
|
+
else
|
35
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual datasets (try: Sequel.extension #{ext.inspect})")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -12,6 +12,10 @@ module Sequel
|
|
12
12
|
# in the extension).
|
13
13
|
EXTENSIONS = {}
|
14
14
|
|
15
|
+
# Hash of extension name symbols to modules to load to implement the extension.
|
16
|
+
EXTENSION_MODULES = {}
|
17
|
+
private_constant :EXTENSION_MODULES
|
18
|
+
|
15
19
|
EMPTY_ARRAY = [].freeze
|
16
20
|
|
17
21
|
# The dataset options that require the removal of cached columns if changed.
|
@@ -45,12 +49,8 @@ module Sequel
|
|
45
49
|
METHS
|
46
50
|
|
47
51
|
# Register an extension callback for Dataset objects. ext should be the
|
48
|
-
# extension name symbol, and mod should
|
49
|
-
# dataset
|
50
|
-
# object. If mod is not provided, a block can be provided and is treated
|
51
|
-
# as the mod object.
|
52
|
-
#
|
53
|
-
# If mod is a module, this also registers a Database extension that will
|
52
|
+
# extension name symbol, and mod should be a Module that will be
|
53
|
+
# included in the dataset's class. This also registers a Database extension that will
|
54
54
|
# extend all of the database's datasets.
|
55
55
|
def self.register_extension(ext, mod=nil, &block)
|
56
56
|
if mod
|
@@ -58,10 +58,16 @@ module Sequel
|
|
58
58
|
if mod.is_a?(Module)
|
59
59
|
block = proc{|ds| ds.extend(mod)}
|
60
60
|
Sequel::Database.register_extension(ext){|db| db.extend_datasets(mod)}
|
61
|
+
Sequel.synchronize{EXTENSION_MODULES[ext] = mod}
|
61
62
|
else
|
62
63
|
block = mod
|
63
64
|
end
|
64
65
|
end
|
66
|
+
|
67
|
+
unless mod.is_a?(Module)
|
68
|
+
Sequel::Deprecation.deprecate("Providing a block or non-module to Sequel::Dataset.register_extension is deprecated and support for it will be removed in Sequel 6.")
|
69
|
+
end
|
70
|
+
|
65
71
|
Sequel.synchronize{EXTENSIONS[ext] = block}
|
66
72
|
end
|
67
73
|
|
@@ -195,11 +201,15 @@ module Sequel
|
|
195
201
|
if TRUE_FREEZE
|
196
202
|
# Return a clone of the dataset loaded with the given dataset extensions.
|
197
203
|
# If no related extension file exists or the extension does not have
|
198
|
-
# specific support for Dataset objects, an
|
199
|
-
def extension(*
|
200
|
-
|
201
|
-
|
202
|
-
|
204
|
+
# specific support for Dataset objects, an error will be raised.
|
205
|
+
def extension(*exts)
|
206
|
+
Sequel.extension(*exts)
|
207
|
+
mods = exts.map{|ext| Sequel.synchronize{EXTENSION_MODULES[ext]}}
|
208
|
+
if mods.all?
|
209
|
+
with_extend(*mods)
|
210
|
+
else
|
211
|
+
with_extend(DeprecatedSingletonClassMethods).extension(*exts)
|
212
|
+
end
|
203
213
|
end
|
204
214
|
else
|
205
215
|
# :nocov:
|
@@ -1199,16 +1209,27 @@ module Sequel
|
|
1199
1209
|
end
|
1200
1210
|
|
1201
1211
|
if TRUE_FREEZE
|
1202
|
-
#
|
1212
|
+
# Create a subclass of the receiver's class, and include the given modules
|
1213
|
+
# into it. If a block is provided, a DatasetModule is created using the block and
|
1214
|
+
# is included into the subclass. Create an instance of the subclass using the
|
1215
|
+
# same db and opts, so that the returned dataset operates similarly to a clone
|
1216
|
+
# extended with the given modules. This approach is used to avoid singleton
|
1217
|
+
# classes, which significantly improves performance.
|
1218
|
+
#
|
1203
1219
|
# Note that like Object#extend, when multiple modules are provided
|
1204
|
-
# as arguments the
|
1205
|
-
# order. If a block is provided, a DatasetModule is created using the block and
|
1206
|
-
# the clone is extended with that module after any modules given as arguments.
|
1220
|
+
# as arguments the subclass includes the modules in reverse order.
|
1207
1221
|
def with_extend(*mods, &block)
|
1208
|
-
c =
|
1209
|
-
c.
|
1210
|
-
c.
|
1211
|
-
c.freeze
|
1222
|
+
c = Class.new(self.class)
|
1223
|
+
c.include(*mods) unless mods.empty?
|
1224
|
+
c.include(DatasetModule.new(&block)) if block
|
1225
|
+
o = c.freeze.allocate
|
1226
|
+
o.instance_variable_set(:@db, @db)
|
1227
|
+
o.instance_variable_set(:@opts, @opts)
|
1228
|
+
o.instance_variable_set(:@cache, {})
|
1229
|
+
if cols = cache_get(:_columns)
|
1230
|
+
o.send(:columns=, cols)
|
1231
|
+
end
|
1232
|
+
o.freeze
|
1212
1233
|
end
|
1213
1234
|
else
|
1214
1235
|
# :nocov:
|
@@ -1315,18 +1336,22 @@ module Sequel
|
|
1315
1336
|
|
1316
1337
|
private
|
1317
1338
|
|
1318
|
-
#
|
1319
|
-
|
1320
|
-
|
1321
|
-
exts
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1339
|
+
# :nocov:
|
1340
|
+
unless TRUE_FREEZE
|
1341
|
+
# Load the extensions into the receiver, without checking if the receiver is frozen.
|
1342
|
+
def _extension!(exts)
|
1343
|
+
Sequel.extension(*exts)
|
1344
|
+
exts.each do |ext|
|
1345
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
1346
|
+
pr.call(self)
|
1347
|
+
else
|
1348
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual datasets (try: Sequel.extension #{ext.inspect})")
|
1349
|
+
end
|
1326
1350
|
end
|
1351
|
+
self
|
1327
1352
|
end
|
1328
|
-
self
|
1329
1353
|
end
|
1354
|
+
# :nocov:
|
1330
1355
|
|
1331
1356
|
# If invert is true, invert the condition.
|
1332
1357
|
def _invert_filter(cond, invert)
|
data/lib/sequel/dataset.rb
CHANGED
@@ -53,4 +53,8 @@ module Sequel
|
|
53
53
|
require_relative "dataset/sql"
|
54
54
|
require_relative "dataset/placeholder_literalizer"
|
55
55
|
require_relative "dataset/dataset_module"
|
56
|
+
|
57
|
+
# :nocov:
|
58
|
+
require_relative "dataset/deprecated_singleton_class_methods" if Dataset::TRUE_FREEZE
|
59
|
+
# :nocov:
|
56
60
|
end
|
@@ -28,7 +28,7 @@
|
|
28
28
|
# connections on every checkout without setting up coarse
|
29
29
|
# connection checkouts will hurt performance, in some cases
|
30
30
|
# significantly. Note that setting up coarse connection
|
31
|
-
# checkouts reduces the concurrency level
|
31
|
+
# checkouts reduces the concurrency level achievable. For
|
32
32
|
# example, in a web application, using Database#synchronize
|
33
33
|
# in a rack middleware will limit the number of concurrent
|
34
34
|
# web requests to the number to connections in the database
|
@@ -257,7 +257,7 @@ module Sequel
|
|
257
257
|
end
|
258
258
|
|
259
259
|
# Make the column type detection handle registered array types.
|
260
|
-
def
|
260
|
+
def schema_array_type(db_type)
|
261
261
|
if (db_type =~ /\A([^(]+)(?:\([^(]+\))?\[\]\z/io) && (type = pg_array_schema_type($1))
|
262
262
|
type
|
263
263
|
else
|
@@ -166,8 +166,7 @@ module Sequel
|
|
166
166
|
def schema_post_process(_)
|
167
167
|
super.each do |_, s|
|
168
168
|
oid = s[:oid]
|
169
|
-
if values = Sequel.synchronize{@enum_labels[oid]}
|
170
|
-
s[:type] = :enum
|
169
|
+
if s[:type] == :enum && (values = Sequel.synchronize{@enum_labels[oid]})
|
171
170
|
s[:enum_values] = values
|
172
171
|
end
|
173
172
|
end
|
@@ -22,7 +22,6 @@
|
|
22
22
|
module Sequel
|
23
23
|
module Postgres
|
24
24
|
module ExtendedDateSupport
|
25
|
-
DATE_YEAR_1 = Date.new(1)
|
26
25
|
DATETIME_YEAR_1 = DateTime.new(1)
|
27
26
|
TIME_YEAR_1 = Time.at(-62135596800).utc
|
28
27
|
INFINITE_TIMESTAMP_STRINGS = ['infinity'.freeze, '-infinity'.freeze].freeze
|
@@ -38,6 +37,15 @@ module Sequel
|
|
38
37
|
procs = db.conversion_procs
|
39
38
|
procs[1082] = ::Sequel.method(:string_to_date)
|
40
39
|
procs[1184] = procs[1114] = db.method(:to_application_timestamp)
|
40
|
+
if ocps = db.instance_variable_get(:@oid_convertor_map)
|
41
|
+
# Clear the oid convertor map entries for timestamps if they
|
42
|
+
# exist, so it will regenerate new ones that use this extension.
|
43
|
+
# This is only taken when using the jdbc adapter.
|
44
|
+
Sequel.synchronize do
|
45
|
+
ocps.delete(1184)
|
46
|
+
ocps.delete(1114)
|
47
|
+
end
|
48
|
+
end
|
41
49
|
end
|
42
50
|
|
43
51
|
# Handle BC dates and times in bound variables. This is necessary for Date values
|
@@ -181,7 +189,7 @@ module Sequel
|
|
181
189
|
|
182
190
|
# Handle BC Date objects.
|
183
191
|
def literal_date(date)
|
184
|
-
if date <
|
192
|
+
if date.year < 1
|
185
193
|
date <<= ((date.year) * 24 - 12)
|
186
194
|
date.strftime("'%Y-%m-%d BC'")
|
187
195
|
else
|
@@ -538,12 +538,8 @@ module Sequel
|
|
538
538
|
private
|
539
539
|
|
540
540
|
# Make the column type detection handle registered row types.
|
541
|
-
def
|
542
|
-
|
543
|
-
type
|
544
|
-
else
|
545
|
-
super
|
546
|
-
end
|
541
|
+
def schema_composite_type(db_type)
|
542
|
+
@row_schema_types[db_type] || super
|
547
543
|
end
|
548
544
|
end
|
549
545
|
end
|
@@ -88,11 +88,11 @@ module Sequel
|
|
88
88
|
# Note that the migration this produces does not have a down
|
89
89
|
# block, so you cannot reverse it.
|
90
90
|
def dump_foreign_key_migration(options=OPTS)
|
91
|
-
ts =
|
91
|
+
ts = _dump_tables(options)
|
92
92
|
<<END_MIG
|
93
93
|
Sequel.migration do
|
94
94
|
change do
|
95
|
-
#{ts.
|
95
|
+
#{ts.map{|t| dump_table_foreign_keys(t)}.reject{|x| x == ''}.join("\n\n").gsub(/^/, ' ')}
|
96
96
|
end
|
97
97
|
end
|
98
98
|
END_MIG
|
@@ -106,11 +106,11 @@ END_MIG
|
|
106
106
|
# set to :namespace, prepend the table name to the index name if the
|
107
107
|
# database does not use a global index namespace.
|
108
108
|
def dump_indexes_migration(options=OPTS)
|
109
|
-
ts =
|
109
|
+
ts = _dump_tables(options)
|
110
110
|
<<END_MIG
|
111
111
|
Sequel.migration do
|
112
112
|
change do
|
113
|
-
#{ts.
|
113
|
+
#{ts.map{|t| dump_table_indexes(t, :add_index, options)}.reject{|x| x == ''}.join("\n\n").gsub(/^/, ' ')}
|
114
114
|
end
|
115
115
|
end
|
116
116
|
END_MIG
|
@@ -138,7 +138,7 @@ END_MIG
|
|
138
138
|
options[:foreign_keys] = false
|
139
139
|
end
|
140
140
|
|
141
|
-
ts = sort_dumped_tables(
|
141
|
+
ts = sort_dumped_tables(_dump_tables(options), options)
|
142
142
|
skipped_fks = if sfk = options[:skipped_foreign_keys]
|
143
143
|
# Handle skipped foreign keys by adding them at the end via
|
144
144
|
# alter_table/add_foreign_key. Note that skipped foreign keys
|
@@ -166,6 +166,21 @@ END_MIG
|
|
166
166
|
|
167
167
|
private
|
168
168
|
|
169
|
+
# Handle schema option to dump tables in a different schema. Such
|
170
|
+
# tables must be schema qualified for this to work correctly.
|
171
|
+
def _dump_tables(opts)
|
172
|
+
if opts[:schema]
|
173
|
+
_literal_table_sort(tables(opts.merge(:qualify=>true)))
|
174
|
+
else
|
175
|
+
tables(opts).sort
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Sort the given table by the literalized value.
|
180
|
+
def _literal_table_sort(tables)
|
181
|
+
tables.sort_by{|s| literal(s)}
|
182
|
+
end
|
183
|
+
|
169
184
|
# If a database default exists and can't be converted, and we are dumping with :same_db,
|
170
185
|
# return a string with the inspect method modified a literal string is created if the code is evaled.
|
171
186
|
def column_schema_to_ruby_default_fallback(default, options)
|
@@ -204,12 +219,20 @@ END_MIG
|
|
204
219
|
if database_type == :mysql && h[:type] =~ /\Atimestamp/
|
205
220
|
h[:null] = true
|
206
221
|
end
|
222
|
+
if database_type == :mssql && schema[:max_length]
|
223
|
+
h[:size] = schema[:max_length]
|
224
|
+
end
|
207
225
|
h
|
208
226
|
else
|
209
227
|
column_schema_to_ruby_type(schema)
|
210
228
|
end
|
211
229
|
type = col_opts.delete(:type)
|
212
|
-
col_opts.
|
230
|
+
if col_opts.key?(:size) && col_opts[:size].nil?
|
231
|
+
col_opts.delete(:size)
|
232
|
+
if max_length = schema[:max_length]
|
233
|
+
col_opts[:size] = max_length
|
234
|
+
end
|
235
|
+
end
|
213
236
|
if schema[:generated]
|
214
237
|
if options[:same_db] && database_type == :postgres
|
215
238
|
col_opts[:generated_always_as] = column_schema_to_ruby_default_fallback(schema[:default], options)
|
@@ -352,7 +375,7 @@ END_MIG
|
|
352
375
|
options[:skipped_foreign_keys] = skipped_foreign_keys
|
353
376
|
tables
|
354
377
|
else
|
355
|
-
tables
|
378
|
+
tables
|
356
379
|
end
|
357
380
|
end
|
358
381
|
|
@@ -377,14 +400,14 @@ END_MIG
|
|
377
400
|
# outstanding foreign keys and skipping those foreign keys.
|
378
401
|
# The skipped foreign keys will be added at the end of the
|
379
402
|
# migration.
|
380
|
-
skip_table, skip_fks = table_fks.sort_by{|table, fks| [fks.length, table]}.first
|
403
|
+
skip_table, skip_fks = table_fks.sort_by{|table, fks| [fks.length, literal(table)]}.first
|
381
404
|
skip_fks_hash = skipped_foreign_keys[skip_table] = {}
|
382
405
|
skip_fks.each{|fk| skip_fks_hash[fk[:columns]] = fk}
|
383
406
|
this_loop << skip_table
|
384
407
|
end
|
385
408
|
|
386
409
|
# Add sorted tables from this loop to the final list
|
387
|
-
sorted_tables.concat(this_loop
|
410
|
+
sorted_tables.concat(_literal_table_sort(this_loop))
|
388
411
|
|
389
412
|
# Remove tables that were handled this loop
|
390
413
|
this_loop.each{|t| table_fks.delete(t)}
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# The set_literalizer extension allows for using Set instances in many of the
|
4
|
+
# same places that you would use Array instances:
|
5
|
+
#
|
6
|
+
# DB[:table].where(column: Set.new([1, 2, 3]))
|
7
|
+
# # SELECT FROM table WHERE (column IN (1, 2, 3))
|
8
|
+
#
|
9
|
+
# To load the extension into all datasets created from a given Database:
|
10
|
+
#
|
11
|
+
# DB.extension :set_literalizer
|
12
|
+
#
|
13
|
+
# Related module: Sequel::Dataset::SetLiteralizer
|
14
|
+
|
15
|
+
require 'set'
|
16
|
+
|
17
|
+
module Sequel
|
18
|
+
class Dataset
|
19
|
+
module SetLiteralizer
|
20
|
+
# Try to generate the same SQL for Set instances used in datasets
|
21
|
+
# that would be used for equivalent Array instances.
|
22
|
+
def complex_expression_sql_append(sql, op, args)
|
23
|
+
# Array instances are treated specially by
|
24
|
+
# Sequel::SQL::BooleanExpression.from_value_pairs. That cannot
|
25
|
+
# be modified by a dataset extension, so this tries to convert
|
26
|
+
# the complex expression values generated by default to what would
|
27
|
+
# be the complex expression values used for the equivalent array.
|
28
|
+
case op
|
29
|
+
when :'=', :'!='
|
30
|
+
if (set = args[1]).is_a?(Set)
|
31
|
+
op = op == :'=' ? :IN : :'NOT IN'
|
32
|
+
col = args[0]
|
33
|
+
array = set.to_a
|
34
|
+
if Sequel.condition_specifier?(array) && col.is_a?(Array)
|
35
|
+
array = Sequel.value_list(array)
|
36
|
+
end
|
37
|
+
args = [col, array]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
super
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Literalize Set instances by converting the set to array.
|
47
|
+
def literal_other_append(sql, v)
|
48
|
+
if Set === v
|
49
|
+
literal_append(sql, v.to_a)
|
50
|
+
else
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
register_extension(:set_literalizer, SetLiteralizer)
|
57
|
+
end
|
58
|
+
end
|
@@ -125,14 +125,15 @@ module Sequel
|
|
125
125
|
ds = @dataset.with_quote_identifiers(false)
|
126
126
|
table_name = ds.literal(ds.first_source_table)
|
127
127
|
reflections = {}
|
128
|
-
|
128
|
+
allow_missing_columns = db_schema.select{|col, sch| sch[:allow_null] == false && nil != sch[:default]}.map(&:first)
|
129
|
+
@constraint_validations = (Sequel.synchronize{hash[table_name]} || []).map{|r| constraint_validation_array(r, reflections, allow_missing_columns)}
|
129
130
|
@constraint_validation_reflections = reflections
|
130
131
|
end
|
131
132
|
end
|
132
133
|
|
133
134
|
# Given a specific database constraint validation metadata row hash, transform
|
134
135
|
# it in an validation method call array suitable for splatting to send.
|
135
|
-
def constraint_validation_array(r, reflections)
|
136
|
+
def constraint_validation_array(r, reflections, allow_missing_columns=EMPTY_ARRAY)
|
136
137
|
opts = {}
|
137
138
|
opts[:message] = r[:message] if r[:message]
|
138
139
|
opts[:allow_nil] = true if db.typecast_value(:boolean, r[:allow_nil])
|
@@ -191,11 +192,13 @@ module Sequel
|
|
191
192
|
reflection_opts[:argument] = arg
|
192
193
|
end
|
193
194
|
|
194
|
-
|
195
|
-
|
196
|
-
|
195
|
+
opts[:from] = :values
|
196
|
+
if column.is_a?(Symbol) && allow_missing_columns.include?(column)
|
197
|
+
opts[:allow_missing] = true
|
197
198
|
end
|
198
199
|
|
200
|
+
a << column << opts
|
201
|
+
|
199
202
|
if column.is_a?(Array) && column.length == 1
|
200
203
|
column = column.first
|
201
204
|
end
|
@@ -28,7 +28,9 @@ module Sequel
|
|
28
28
|
#
|
29
29
|
# This plugin only works on the postgres adapter when using the pg 0.16+ driver,
|
30
30
|
# PostgreSQL 9.3+ server, and PostgreSQL 9.3+ client library (libpq). In other cases
|
31
|
-
# it will be a no-op.
|
31
|
+
# it will be a no-op. Additionally, the plugin only handles models that select
|
32
|
+
# from tables. It does not handle models that select from subqueries, such as
|
33
|
+
# subclasses of models using the class_table_inheritance plugin.
|
32
34
|
#
|
33
35
|
# Example:
|
34
36
|
#
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module Sequel
|
4
4
|
module Plugins
|
5
5
|
# The prepared_statements plugin modifies the model to use prepared statements for
|
6
|
-
# instance level inserts and updates.
|
6
|
+
# instance level inserts and updates. This plugin exists for backwards compatibility
|
7
|
+
# and is not recommended for general use.
|
7
8
|
#
|
8
9
|
# Note that this plugin is unsafe in some circumstances, as it can allow up to
|
9
10
|
# 2^N prepared statements to be created for each type of insert and update query, where
|
@@ -5,7 +5,8 @@ module Sequel
|
|
5
5
|
# The prepared_statements_safe plugin modifies the model to reduce the number of
|
6
6
|
# prepared statements that can be created, by setting as many columns as possible
|
7
7
|
# before creating, and by changing +save_changes+ to save all columns instead of
|
8
|
-
# just the changed ones.
|
8
|
+
# just the changed ones. This plugin exists for backwards compatibility
|
9
|
+
# and is not recommended for general use.
|
9
10
|
#
|
10
11
|
# This plugin depends on the +prepared_statements+ plugin.
|
11
12
|
#
|
@@ -75,6 +75,10 @@ module Sequel
|
|
75
75
|
# "#{Array(attribute).join(I18n.t('errors.joiner'))} #{error_msg}"
|
76
76
|
# end
|
77
77
|
# end
|
78
|
+
#
|
79
|
+
# It is recommended that users of this plugin that use validates_schema_types also use
|
80
|
+
# the validation_helpers_generic_type_messages plugin for more useful type validation
|
81
|
+
# failure messages.
|
78
82
|
module ValidationHelpers
|
79
83
|
DEFAULT_OPTIONS = {
|
80
84
|
:exact_length=>{:message=>lambda{|exact| "is not #{exact} characters"}},
|
@@ -211,7 +215,7 @@ module Sequel
|
|
211
215
|
klass = klass.to_s.constantize if klass.is_a?(String) || klass.is_a?(Symbol)
|
212
216
|
validatable_attributes_for_type(:type, atts, opts) do |a,v,m|
|
213
217
|
if klass.is_a?(Array) ? !klass.any?{|kls| v.is_a?(kls)} : !v.is_a?(klass)
|
214
|
-
|
218
|
+
validates_type_error_message(m, klass)
|
215
219
|
end
|
216
220
|
end
|
217
221
|
end
|
@@ -338,6 +342,9 @@ module Sequel
|
|
338
342
|
def validation_error_message(message, *args)
|
339
343
|
message.is_a?(Proc) ? message.call(*args) : message
|
340
344
|
end
|
345
|
+
|
346
|
+
# The validation error message for type validations, for the given class.
|
347
|
+
alias validates_type_error_message validation_error_message
|
341
348
|
end
|
342
349
|
end
|
343
350
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require_relative 'validation_helpers'
|
4
|
+
|
5
|
+
module Sequel
|
6
|
+
module Plugins
|
7
|
+
# The validation_helpers_generic_type_messages plugin overrides the default
|
8
|
+
# type validation failure messages in the validation_helpers plugin to be
|
9
|
+
# more generic and understandable by the average user, instead of always
|
10
|
+
# be based on the names of the allowed classes for the type. For example:
|
11
|
+
#
|
12
|
+
# # :blob type
|
13
|
+
# # validation_helpers default: "value is not a valid sequel::sql::blob"
|
14
|
+
# # with this plugin: "value is not a blob"
|
15
|
+
#
|
16
|
+
# # :boolean type
|
17
|
+
# # validation_helpers default: "value is not a valid trueclass or falseclass"
|
18
|
+
# # with this plugin: "value is not true or false"
|
19
|
+
#
|
20
|
+
# # :datetime type
|
21
|
+
# # validation_helpers default: "value is not a valid time or datetime"
|
22
|
+
# # with this plugin: "value is not a valid timestamp"
|
23
|
+
#
|
24
|
+
# # custom/database-specific types
|
25
|
+
# # validation_helpers default: "value is not a valid sequel::class_name"
|
26
|
+
# # with this plugin: "value is not the expected type"
|
27
|
+
#
|
28
|
+
# It is expected that this plugin will become the default behavior of
|
29
|
+
# validation_helpers in Sequel 6.
|
30
|
+
#
|
31
|
+
# To enable this the use of generic type messages for all models, load this
|
32
|
+
# plugin into Sequel::Model.
|
33
|
+
#
|
34
|
+
# Sequel::Model.plugin :validation_helpers_generic_type_messages
|
35
|
+
module ValidationHelpersGenericTypeMessages
|
36
|
+
OVERRIDE_PROC = ValidationHelpers::DEFAULT_OPTIONS[:type][:message]
|
37
|
+
private_constant :OVERRIDE_PROC
|
38
|
+
|
39
|
+
TYPE_ERROR_STRINGS = {
|
40
|
+
String => 'is not a string'.freeze,
|
41
|
+
Integer => 'is not an integer'.freeze,
|
42
|
+
Date => 'is not a valid date'.freeze,
|
43
|
+
[Time, DateTime].freeze => 'is not a valid timestamp'.freeze,
|
44
|
+
Sequel::SQLTime => 'is not a valid time'.freeze,
|
45
|
+
[TrueClass, FalseClass].freeze => 'is not true or false'.freeze,
|
46
|
+
Float => 'is not a number'.freeze,
|
47
|
+
BigDecimal => 'is not a number'.freeze,
|
48
|
+
Sequel::SQL::Blob => 'is not a blob'.freeze,
|
49
|
+
}
|
50
|
+
TYPE_ERROR_STRINGS.default = "is not the expected type".freeze
|
51
|
+
TYPE_ERROR_STRINGS.freeze
|
52
|
+
private_constant :TYPE_ERROR_STRINGS
|
53
|
+
|
54
|
+
def self.apply(mod)
|
55
|
+
mod.plugin :validation_helpers
|
56
|
+
end
|
57
|
+
|
58
|
+
module InstanceMethods
|
59
|
+
private
|
60
|
+
|
61
|
+
# Use a generic error message for type validations.
|
62
|
+
def validates_type_error_message(m, klass)
|
63
|
+
# SEQUEL6: Make this the default behavior in validation_helpers
|
64
|
+
if OVERRIDE_PROC.equal?(m)
|
65
|
+
TYPE_ERROR_STRINGS[klass]
|
66
|
+
else
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/sequel/version.rb
CHANGED
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
8
8
|
# release, generally around once a month.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 68
|
10
10
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
12
12
|
# releases that fix regressions from previous versions.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.68.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -198,6 +198,8 @@ extra_rdoc_files:
|
|
198
198
|
- doc/release_notes/5.64.0.txt
|
199
199
|
- doc/release_notes/5.65.0.txt
|
200
200
|
- doc/release_notes/5.66.0.txt
|
201
|
+
- doc/release_notes/5.67.0.txt
|
202
|
+
- doc/release_notes/5.68.0.txt
|
201
203
|
- doc/release_notes/5.7.0.txt
|
202
204
|
- doc/release_notes/5.8.0.txt
|
203
205
|
- doc/release_notes/5.9.0.txt
|
@@ -292,6 +294,8 @@ files:
|
|
292
294
|
- doc/release_notes/5.64.0.txt
|
293
295
|
- doc/release_notes/5.65.0.txt
|
294
296
|
- doc/release_notes/5.66.0.txt
|
297
|
+
- doc/release_notes/5.67.0.txt
|
298
|
+
- doc/release_notes/5.68.0.txt
|
295
299
|
- doc/release_notes/5.7.0.txt
|
296
300
|
- doc/release_notes/5.8.0.txt
|
297
301
|
- doc/release_notes/5.9.0.txt
|
@@ -376,6 +380,7 @@ files:
|
|
376
380
|
- lib/sequel/dataset.rb
|
377
381
|
- lib/sequel/dataset/actions.rb
|
378
382
|
- lib/sequel/dataset/dataset_module.rb
|
383
|
+
- lib/sequel/dataset/deprecated_singleton_class_methods.rb
|
379
384
|
- lib/sequel/dataset/features.rb
|
380
385
|
- lib/sequel/dataset/graph.rb
|
381
386
|
- lib/sequel/dataset/misc.rb
|
@@ -461,6 +466,7 @@ files:
|
|
461
466
|
- lib/sequel/extensions/sequel_4_dataset_methods.rb
|
462
467
|
- lib/sequel/extensions/server_block.rb
|
463
468
|
- lib/sequel/extensions/server_logging.rb
|
469
|
+
- lib/sequel/extensions/set_literalizer.rb
|
464
470
|
- lib/sequel/extensions/split_array_nil.rb
|
465
471
|
- lib/sequel/extensions/sql_comments.rb
|
466
472
|
- lib/sequel/extensions/sql_expr.rb
|
@@ -579,6 +585,7 @@ files:
|
|
579
585
|
- lib/sequel/plugins/validation_class_methods.rb
|
580
586
|
- lib/sequel/plugins/validation_contexts.rb
|
581
587
|
- lib/sequel/plugins/validation_helpers.rb
|
588
|
+
- lib/sequel/plugins/validation_helpers_generic_type_messages.rb
|
582
589
|
- lib/sequel/plugins/whitelist_security.rb
|
583
590
|
- lib/sequel/plugins/xml_serializer.rb
|
584
591
|
- lib/sequel/sql.rb
|
@@ -615,7 +622,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
615
622
|
- !ruby/object:Gem::Version
|
616
623
|
version: '0'
|
617
624
|
requirements: []
|
618
|
-
rubygems_version: 3.4.
|
625
|
+
rubygems_version: 3.4.10
|
619
626
|
signing_key:
|
620
627
|
specification_version: 4
|
621
628
|
summary: The Database Toolkit for Ruby
|