sequel 5.45.0 → 5.77.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +434 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +59 -27
- data/bin/sequel +11 -3
- data/doc/advanced_associations.rdoc +16 -14
- data/doc/association_basics.rdoc +119 -24
- data/doc/cheat_sheet.rdoc +11 -3
- data/doc/mass_assignment.rdoc +1 -1
- data/doc/migration.rdoc +27 -6
- data/doc/model_hooks.rdoc +1 -1
- data/doc/object_model.rdoc +8 -8
- data/doc/opening_databases.rdoc +28 -12
- data/doc/postgresql.rdoc +16 -8
- data/doc/querying.rdoc +5 -3
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/release_notes/5.50.0.txt +78 -0
- data/doc/release_notes/5.51.0.txt +47 -0
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/release_notes/5.53.0.txt +23 -0
- data/doc/release_notes/5.54.0.txt +27 -0
- data/doc/release_notes/5.55.0.txt +21 -0
- data/doc/release_notes/5.56.0.txt +51 -0
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/release_notes/5.59.0.txt +73 -0
- data/doc/release_notes/5.60.0.txt +22 -0
- data/doc/release_notes/5.61.0.txt +43 -0
- data/doc/release_notes/5.62.0.txt +132 -0
- data/doc/release_notes/5.63.0.txt +33 -0
- data/doc/release_notes/5.64.0.txt +50 -0
- data/doc/release_notes/5.65.0.txt +21 -0
- data/doc/release_notes/5.66.0.txt +24 -0
- data/doc/release_notes/5.67.0.txt +32 -0
- data/doc/release_notes/5.68.0.txt +61 -0
- data/doc/release_notes/5.69.0.txt +26 -0
- data/doc/release_notes/5.70.0.txt +35 -0
- data/doc/release_notes/5.71.0.txt +21 -0
- data/doc/release_notes/5.72.0.txt +33 -0
- data/doc/release_notes/5.73.0.txt +66 -0
- data/doc/release_notes/5.74.0.txt +45 -0
- data/doc/release_notes/5.75.0.txt +35 -0
- data/doc/release_notes/5.76.0.txt +86 -0
- data/doc/release_notes/5.77.0.txt +63 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +9 -9
- data/doc/sharding.rdoc +3 -1
- data/doc/sql.rdoc +27 -15
- data/doc/testing.rdoc +23 -13
- data/doc/transactions.rdoc +6 -6
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/amalgalite.rb +3 -5
- data/lib/sequel/adapters/ibmdb.rb +3 -3
- data/lib/sequel/adapters/jdbc/derby.rb +8 -0
- data/lib/sequel/adapters/jdbc/h2.rb +63 -10
- data/lib/sequel/adapters/jdbc/hsqldb.rb +8 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +7 -4
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +15 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +4 -0
- data/lib/sequel/adapters/jdbc.rb +24 -22
- data/lib/sequel/adapters/mysql.rb +92 -67
- data/lib/sequel/adapters/mysql2.rb +56 -51
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/odbc.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +4 -3
- data/lib/sequel/adapters/postgres.rb +89 -45
- data/lib/sequel/adapters/shared/access.rb +11 -1
- data/lib/sequel/adapters/shared/db2.rb +42 -0
- data/lib/sequel/adapters/shared/mssql.rb +91 -10
- data/lib/sequel/adapters/shared/mysql.rb +78 -3
- data/lib/sequel/adapters/shared/oracle.rb +86 -7
- data/lib/sequel/adapters/shared/postgres.rb +576 -171
- data/lib/sequel/adapters/shared/sqlanywhere.rb +21 -5
- data/lib/sequel/adapters/shared/sqlite.rb +92 -8
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +99 -18
- data/lib/sequel/adapters/tinytds.rb +1 -1
- data/lib/sequel/adapters/trilogy.rb +117 -0
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -7
- data/lib/sequel/connection_pool/sharded_threaded.rb +16 -11
- data/lib/sequel/connection_pool/sharded_timed_queue.rb +374 -0
- data/lib/sequel/connection_pool/single.rb +6 -8
- data/lib/sequel/connection_pool/threaded.rb +14 -8
- data/lib/sequel/connection_pool/timed_queue.rb +270 -0
- data/lib/sequel/connection_pool.rb +57 -31
- data/lib/sequel/core.rb +17 -18
- data/lib/sequel/database/connecting.rb +27 -3
- data/lib/sequel/database/dataset.rb +16 -6
- data/lib/sequel/database/misc.rb +70 -14
- data/lib/sequel/database/query.rb +73 -2
- data/lib/sequel/database/schema_generator.rb +11 -6
- data/lib/sequel/database/schema_methods.rb +23 -4
- data/lib/sequel/database/transactions.rb +6 -0
- data/lib/sequel/dataset/actions.rb +111 -15
- data/lib/sequel/dataset/deprecated_singleton_class_methods.rb +42 -0
- data/lib/sequel/dataset/features.rb +20 -1
- data/lib/sequel/dataset/misc.rb +12 -2
- data/lib/sequel/dataset/placeholder_literalizer.rb +20 -9
- data/lib/sequel/dataset/query.rb +170 -41
- data/lib/sequel/dataset/sql.rb +190 -71
- data/lib/sequel/dataset.rb +4 -0
- data/lib/sequel/extensions/_model_pg_row.rb +0 -12
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/any_not_empty.rb +2 -2
- data/lib/sequel/extensions/async_thread_pool.rb +14 -13
- data/lib/sequel/extensions/auto_cast_date_and_time.rb +94 -0
- data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/connection_expiration.rb +15 -9
- data/lib/sequel/extensions/connection_validator.rb +16 -11
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/core_refinements.rb +36 -11
- data/lib/sequel/extensions/date_arithmetic.rb +36 -8
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +5 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +11 -10
- data/lib/sequel/extensions/index_caching.rb +5 -1
- data/lib/sequel/extensions/inflector.rb +1 -1
- data/lib/sequel/extensions/is_distinct_from.rb +141 -0
- data/lib/sequel/extensions/looser_typecasting.rb +3 -0
- data/lib/sequel/extensions/migration.rb +57 -15
- data/lib/sequel/extensions/named_timezones.rb +22 -6
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +33 -4
- data/lib/sequel/extensions/pg_array_ops.rb +2 -2
- data/lib/sequel/extensions/pg_auto_parameterize.rb +509 -0
- data/lib/sequel/extensions/pg_auto_parameterize_in_array.rb +110 -0
- data/lib/sequel/extensions/pg_enum.rb +1 -2
- data/lib/sequel/extensions/pg_extended_date_support.rb +39 -28
- data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
- data/lib/sequel/extensions/pg_hstore.rb +6 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +53 -3
- data/lib/sequel/extensions/pg_inet.rb +10 -11
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +11 -11
- data/lib/sequel/extensions/pg_json.rb +13 -15
- data/lib/sequel/extensions/pg_json_ops.rb +125 -2
- data/lib/sequel/extensions/pg_multirange.rb +367 -0
- data/lib/sequel/extensions/pg_range.rb +13 -26
- data/lib/sequel/extensions/pg_range_ops.rb +37 -9
- data/lib/sequel/extensions/pg_row.rb +20 -19
- data/lib/sequel/extensions/pg_row_ops.rb +1 -1
- data/lib/sequel/extensions/pg_timestamptz.rb +27 -3
- data/lib/sequel/extensions/round_timestamps.rb +1 -1
- data/lib/sequel/extensions/s.rb +2 -1
- data/lib/sequel/extensions/schema_caching.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +45 -11
- data/lib/sequel/extensions/server_block.rb +10 -13
- data/lib/sequel/extensions/set_literalizer.rb +58 -0
- data/lib/sequel/extensions/sql_comments.rb +110 -3
- data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
- data/lib/sequel/extensions/string_agg.rb +1 -1
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/extensions/symbol_aref.rb +2 -0
- data/lib/sequel/extensions/transaction_connection_validator.rb +78 -0
- data/lib/sequel/model/associations.rb +286 -92
- data/lib/sequel/model/base.rb +53 -33
- data/lib/sequel/model/dataset_module.rb +3 -0
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/exceptions.rb +15 -3
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +74 -16
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/column_encryption.rb +29 -8
- data/lib/sequel/plugins/composition.rb +3 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +4 -4
- data/lib/sequel/plugins/constraint_validations.rb +8 -5
- data/lib/sequel/plugins/defaults_setter.rb +16 -0
- data/lib/sequel/plugins/dirty.rb +1 -1
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/finder.rb +4 -2
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/instance_specific_default.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +2 -2
- data/lib/sequel/plugins/lazy_attributes.rb +3 -0
- data/lib/sequel/plugins/list.rb +8 -3
- data/lib/sequel/plugins/many_through_many.rb +109 -10
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -38
- data/lib/sequel/plugins/nested_attributes.rb +4 -4
- data/lib/sequel/plugins/optimistic_locking.rb +9 -42
- data/lib/sequel/plugins/optimistic_locking_base.rb +55 -0
- data/lib/sequel/plugins/paged_operations.rb +181 -0
- data/lib/sequel/plugins/pg_array_associations.rb +46 -34
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +9 -3
- data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +109 -0
- data/lib/sequel/plugins/prepared_statements.rb +12 -2
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -1
- data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
- data/lib/sequel/plugins/rcte_tree.rb +7 -4
- data/lib/sequel/plugins/require_valid_schema.rb +67 -0
- data/lib/sequel/plugins/serialization.rb +1 -0
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +8 -0
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +39 -1
- data/lib/sequel/plugins/static_cache_cache.rb +5 -1
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/tactical_eager_loading.rb +23 -10
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validate_associated.rb +22 -12
- data/lib/sequel/plugins/validation_helpers.rb +41 -11
- data/lib/sequel/plugins/validation_helpers_generic_type_messages.rb +73 -0
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/timezones.rb +12 -14
- data/lib/sequel/version.rb +1 -1
- metadata +109 -19
data/lib/sequel/model/base.rb
CHANGED
@@ -606,6 +606,7 @@ module Sequel
|
|
606
606
|
@db_schema = get_db_schema
|
607
607
|
end
|
608
608
|
|
609
|
+
@fast_pk_lookup_sql = @fast_instance_delete_sql = nil unless @dataset.supports_placeholder_literalizer?
|
609
610
|
reset_instance_dataset
|
610
611
|
self
|
611
612
|
end
|
@@ -680,24 +681,26 @@ module Sequel
|
|
680
681
|
|
681
682
|
private
|
682
683
|
|
683
|
-
# Yield to the passed block and if do_raise is false, swallow
|
684
|
+
# Yield to the passed block and if do_raise is false, swallow Sequel::Errors other than DatabaseConnectionError
|
685
|
+
# and DatabaseDisconnectError.
|
684
686
|
def check_non_connection_error(do_raise=require_valid_table)
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
raise if do_raise
|
691
|
-
end
|
687
|
+
db.transaction(:savepoint=>:only){yield}
|
688
|
+
rescue Sequel::DatabaseConnectionError, Sequel::DatabaseDisconnectError
|
689
|
+
raise
|
690
|
+
rescue Sequel::Error
|
691
|
+
raise if do_raise
|
692
692
|
end
|
693
693
|
|
694
694
|
# Convert the given object to a Dataset that should be used as
|
695
695
|
# this model's dataset.
|
696
696
|
def convert_input_dataset(ds)
|
697
697
|
case ds
|
698
|
-
when Symbol, SQL::Identifier, SQL::QualifiedIdentifier
|
698
|
+
when Symbol, SQL::Identifier, SQL::QualifiedIdentifier
|
699
699
|
self.simple_table = db.literal(ds).freeze
|
700
700
|
ds = db.from(ds)
|
701
|
+
when SQL::AliasedExpression, LiteralString
|
702
|
+
self.simple_table = nil
|
703
|
+
ds = db.from(ds)
|
701
704
|
when Dataset
|
702
705
|
ds = ds.from_self(:alias=>ds.first_source) if ds.joined_dataset?
|
703
706
|
|
@@ -786,7 +789,7 @@ module Sequel
|
|
786
789
|
schema_hash = {}
|
787
790
|
ds_opts = dataset.opts
|
788
791
|
get_columns = proc{check_non_connection_error{columns} || []}
|
789
|
-
schema_array =
|
792
|
+
schema_array = get_db_schema_array(reload) if db.supports_schema_parsing?
|
790
793
|
if schema_array
|
791
794
|
schema_array.each{|k,v| schema_hash[k] = v}
|
792
795
|
|
@@ -823,6 +826,12 @@ module Sequel
|
|
823
826
|
schema_hash
|
824
827
|
end
|
825
828
|
|
829
|
+
# Get the array of schema information for the dataset. Returns nil if
|
830
|
+
# the schema information cannot be determined.
|
831
|
+
def get_db_schema_array(reload)
|
832
|
+
check_non_connection_error(false){db.schema(dataset, :reload=>reload)}
|
833
|
+
end
|
834
|
+
|
826
835
|
# Uncached version of setter_methods, to be overridden by plugins
|
827
836
|
# that want to modify the methods used.
|
828
837
|
def get_setter_methods
|
@@ -1093,7 +1102,7 @@ module Sequel
|
|
1093
1102
|
@modified = true
|
1094
1103
|
initialize_set(values)
|
1095
1104
|
_clear_changed_columns(:initialize)
|
1096
|
-
yield self if
|
1105
|
+
yield self if defined?(yield)
|
1097
1106
|
end
|
1098
1107
|
|
1099
1108
|
# Returns value of the column's attribute.
|
@@ -1133,7 +1142,7 @@ module Sequel
|
|
1133
1142
|
#
|
1134
1143
|
# Artist[1] === Artist[1] # => true
|
1135
1144
|
# Artist.new === Artist.new # => false
|
1136
|
-
# Artist[1].set(:
|
1145
|
+
# Artist[1].set(name: 'Bob') === Artist[1] # => true
|
1137
1146
|
def ===(obj)
|
1138
1147
|
case pkv = pk
|
1139
1148
|
when nil
|
@@ -1152,7 +1161,7 @@ module Sequel
|
|
1152
1161
|
#
|
1153
1162
|
# Artist[1].pk_equal?(Artist[1]) # => true
|
1154
1163
|
# Artist.new.pk_equal?(Artist.new) # => false
|
1155
|
-
# Artist[1].set(:
|
1164
|
+
# Artist[1].set(name: 'Bob').pk_equal?(Artist[1]) # => true
|
1156
1165
|
alias pk_equal? ===
|
1157
1166
|
|
1158
1167
|
# class is defined in Object, but it is also a keyword,
|
@@ -1224,7 +1233,7 @@ module Sequel
|
|
1224
1233
|
#
|
1225
1234
|
# Artist[1] == Artist[1] # => true
|
1226
1235
|
# Artist.new == Artist.new # => true
|
1227
|
-
# Artist[1].set(:
|
1236
|
+
# Artist[1].set(name: 'Bob') == Artist[1] # => false
|
1228
1237
|
def eql?(obj)
|
1229
1238
|
(obj.class == model) && (obj.values == @values)
|
1230
1239
|
end
|
@@ -1235,18 +1244,21 @@ module Sequel
|
|
1235
1244
|
@errors ||= errors_class.new
|
1236
1245
|
end
|
1237
1246
|
|
1247
|
+
EXISTS_SELECT_ = SQL::AliasedExpression.new(1, :one)
|
1248
|
+
private_constant :EXISTS_SELECT_
|
1249
|
+
|
1238
1250
|
# Returns true when current instance exists, false otherwise.
|
1239
1251
|
# Generally an object that isn't new will exist unless it has
|
1240
1252
|
# been deleted. Uses a database query to check for existence,
|
1241
1253
|
# unless the model object is new, in which case this is always
|
1242
1254
|
# false.
|
1243
1255
|
#
|
1244
|
-
# Artist[1].exists? # SELECT 1 FROM artists WHERE (id = 1)
|
1256
|
+
# Artist[1].exists? # SELECT 1 AS one FROM artists WHERE (id = 1)
|
1245
1257
|
# # => true
|
1246
1258
|
# Artist.new.exists?
|
1247
1259
|
# # => false
|
1248
1260
|
def exists?
|
1249
|
-
new? ? false : !this.get(
|
1261
|
+
new? ? false : !this.get(EXISTS_SELECT_).nil?
|
1250
1262
|
end
|
1251
1263
|
|
1252
1264
|
# Ignore the model's setter method cache when this instances extends a module, as the
|
@@ -1326,13 +1338,13 @@ module Sequel
|
|
1326
1338
|
# a = Artist[1]
|
1327
1339
|
# Artist.db.transaction do
|
1328
1340
|
# a.lock!
|
1329
|
-
# a.update(:
|
1341
|
+
# a.update(name: 'A')
|
1330
1342
|
# end
|
1331
1343
|
#
|
1332
1344
|
# a = Artist[2]
|
1333
1345
|
# Artist.db.transaction do
|
1334
1346
|
# a.lock!('FOR NO KEY UPDATE')
|
1335
|
-
# a.update(:
|
1347
|
+
# a.update(name: 'B')
|
1336
1348
|
# end
|
1337
1349
|
def lock!(style=:update)
|
1338
1350
|
_refresh(this.lock_style(style)) unless new?
|
@@ -1630,11 +1642,9 @@ module Sequel
|
|
1630
1642
|
# artist.set(name: 'Invalid').valid? # => false
|
1631
1643
|
# artist.errors.full_messages # => ['name cannot be Invalid']
|
1632
1644
|
def valid?(opts = OPTS)
|
1633
|
-
|
1634
|
-
|
1635
|
-
|
1636
|
-
false
|
1637
|
-
end
|
1645
|
+
_valid?(opts)
|
1646
|
+
rescue HookFailed
|
1647
|
+
false
|
1638
1648
|
end
|
1639
1649
|
|
1640
1650
|
private
|
@@ -1938,8 +1948,10 @@ module Sequel
|
|
1938
1948
|
end
|
1939
1949
|
|
1940
1950
|
# If transactions should be used, wrap the yield in a transaction block.
|
1941
|
-
def checked_transaction(opts=OPTS)
|
1942
|
-
|
1951
|
+
def checked_transaction(opts=OPTS, &block)
|
1952
|
+
h = {:server=>this_server}.merge!(opts)
|
1953
|
+
h[:skip_transaction] = true unless use_transaction?(opts)
|
1954
|
+
db.transaction(h, &block)
|
1943
1955
|
end
|
1944
1956
|
|
1945
1957
|
# Change the value of the column to given value, recording the change.
|
@@ -2024,19 +2036,20 @@ module Sequel
|
|
2024
2036
|
meths = setter_methods(type)
|
2025
2037
|
strict = strict_param_setting
|
2026
2038
|
hash.each do |k,v|
|
2039
|
+
k = k.to_s
|
2027
2040
|
m = "#{k}="
|
2028
2041
|
if meths.include?(m)
|
2029
2042
|
set_column_value(m, v)
|
2030
2043
|
elsif strict
|
2031
2044
|
# Avoid using respond_to? or creating symbols from user input
|
2032
2045
|
if public_methods.map(&:to_s).include?(m)
|
2033
|
-
if Array(model.primary_key).map(&:to_s).member?(k
|
2034
|
-
raise MassAssignmentRestriction
|
2046
|
+
if Array(model.primary_key).map(&:to_s).member?(k) && model.restrict_primary_key?
|
2047
|
+
raise MassAssignmentRestriction.create("#{k} is a restricted primary key", self, k)
|
2035
2048
|
else
|
2036
|
-
raise MassAssignmentRestriction
|
2049
|
+
raise MassAssignmentRestriction.create("#{k} is a restricted column", self, k)
|
2037
2050
|
end
|
2038
2051
|
else
|
2039
|
-
raise MassAssignmentRestriction
|
2052
|
+
raise MassAssignmentRestriction.create("method #{m} doesn't exist", self, k)
|
2040
2053
|
end
|
2041
2054
|
end
|
2042
2055
|
end
|
@@ -2140,8 +2153,9 @@ module Sequel
|
|
2140
2153
|
# # DELETE FROM artists WHERE (id = 2)
|
2141
2154
|
# # ...
|
2142
2155
|
def destroy
|
2143
|
-
|
2144
|
-
|
2156
|
+
@db.transaction(:server=>opts[:server], :skip_transaction=>model.use_transactions == false) do
|
2157
|
+
all(&:destroy).length
|
2158
|
+
end
|
2145
2159
|
end
|
2146
2160
|
|
2147
2161
|
# If there is no order already defined on this dataset, order it by
|
@@ -2221,11 +2235,17 @@ module Sequel
|
|
2221
2235
|
|
2222
2236
|
private
|
2223
2237
|
|
2238
|
+
# Return the dataset ordered by the model's primary key. This should not
|
2239
|
+
# be used if the model does not have a primary key.
|
2240
|
+
def _force_primary_key_order
|
2241
|
+
cached_dataset(:_pk_order_ds){order(*model.primary_key)}
|
2242
|
+
end
|
2243
|
+
|
2224
2244
|
# If the dataset is not already ordered, and the model has a primary key,
|
2225
2245
|
# return a clone ordered by the primary key.
|
2226
2246
|
def _primary_key_order
|
2227
|
-
if @opts[:order].nil? && model &&
|
2228
|
-
|
2247
|
+
if @opts[:order].nil? && model && model.primary_key
|
2248
|
+
_force_primary_key_order
|
2229
2249
|
end
|
2230
2250
|
end
|
2231
2251
|
|
@@ -8,6 +8,9 @@ module Sequel
|
|
8
8
|
# automatically creates class methods for public dataset
|
9
9
|
# methods.
|
10
10
|
class DatasetModule < Dataset::DatasetModule
|
11
|
+
# The model class related to this dataset module.
|
12
|
+
attr_reader :model
|
13
|
+
|
11
14
|
# Store the model related to this dataset module.
|
12
15
|
def initialize(model)
|
13
16
|
@model = model
|
data/lib/sequel/model/errors.rb
CHANGED
@@ -38,7 +38,7 @@ module Sequel
|
|
38
38
|
def full_messages
|
39
39
|
inject([]) do |m, kv|
|
40
40
|
att, errors = *kv
|
41
|
-
errors.each {|e| m << (e.is_a?(LiteralString) ? e :
|
41
|
+
errors.each {|e| m << (e.is_a?(LiteralString) ? e : full_message(att, e))}
|
42
42
|
m
|
43
43
|
end
|
44
44
|
end
|
@@ -53,6 +53,15 @@ module Sequel
|
|
53
53
|
v
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Create full error message to use for the given attribute (or array of attributes)
|
60
|
+
# and error message. This can be overridden for easier internalization.
|
61
|
+
def full_message(att, error_msg)
|
62
|
+
att = att.join(' and ') if att.is_a?(Array)
|
63
|
+
"#{att} #{error_msg}"
|
64
|
+
end
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|
@@ -24,11 +24,23 @@ module Sequel
|
|
24
24
|
UndefinedAssociation = Class.new(Error)
|
25
25
|
).name
|
26
26
|
|
27
|
-
(
|
28
27
|
# Raised when a mass assignment method is called in strict mode with either a restricted column
|
29
28
|
# or a column without a setter method.
|
30
|
-
MassAssignmentRestriction
|
31
|
-
|
29
|
+
class MassAssignmentRestriction < Error
|
30
|
+
# The Sequel::Model object related to this exception.
|
31
|
+
attr_reader :model
|
32
|
+
|
33
|
+
# The column related to this exception, as a string.
|
34
|
+
attr_reader :column
|
35
|
+
|
36
|
+
# Create an instance of this class with the model and column set.
|
37
|
+
def self.create(msg, model, column)
|
38
|
+
e = new("#{msg} for class #{model.class.inspect}")
|
39
|
+
e.instance_variable_set(:@model, model)
|
40
|
+
e.instance_variable_set(:@column, column)
|
41
|
+
e
|
42
|
+
end
|
43
|
+
end
|
32
44
|
|
33
45
|
# Exception class raised when +raise_on_save_failure+ is set and validation fails
|
34
46
|
class ValidationFailed < Error
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module Plugins
|
5
|
+
# The auto_restrict_eager_graph plugin will automatically disallow the use
|
6
|
+
# of eager_graph for associations that have associated blocks but no :graph_*
|
7
|
+
# association options. The reason for this is the block will have an effect
|
8
|
+
# during regular and eager loading, but not loading via eager_graph, and it
|
9
|
+
# is likely that whatever the block is doing should have an equivalent done
|
10
|
+
# when eager_graphing. Most likely, not including a :graph_* option was either
|
11
|
+
# an oversight (and one should be added), or use with eager_graph was never
|
12
|
+
# intended (and usage should be forbidden). Disallowing eager_graph in this
|
13
|
+
# case prevents likely unexpected behavior during eager_graph.
|
14
|
+
#
|
15
|
+
# As an example of this, consider the following code:
|
16
|
+
#
|
17
|
+
# Album.one_to_many :popular_tracks, class: :Track do |ds|
|
18
|
+
# ds = ds.where(popular: true)
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Album.eager(:popular_tracks).all
|
22
|
+
# # SELECT * FROM albums
|
23
|
+
# # SELECT * FROM tracks WHERE ((popular IS TRUE) AND (album_id IN (...)))
|
24
|
+
#
|
25
|
+
# # Notice that no condition for tracks.popular is added.
|
26
|
+
# Album.eager_graph(:popular_tracks).all
|
27
|
+
# # SELECT ... FROM albums LEFT JOIN tracks ON (tracks.album_id = albums.id)
|
28
|
+
#
|
29
|
+
# With the auto_restrict_eager_graph plugin, the eager_graph call above will
|
30
|
+
# raise an error, alerting you to the fact that you either should not be
|
31
|
+
# using eager_graph with the association, or that you should be adding an
|
32
|
+
# appropriate :graph_* option, such as:
|
33
|
+
#
|
34
|
+
# Album.one_to_many :popular_tracks, class: :Track, graph_conditions: {popular: true} do |ds|
|
35
|
+
# ds = ds.where(popular: true)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# Usage:
|
39
|
+
#
|
40
|
+
# # Automatically restrict eager_graph for associations if appropriate for all
|
41
|
+
# # model subclasses (called before loading subclasses)
|
42
|
+
# Sequel::Model.plugin :auto_restrict_eager_graph
|
43
|
+
#
|
44
|
+
# # Automatically restrict eager_graph for associations in Album class
|
45
|
+
# Album.plugin :auto_restrict_eager_graph
|
46
|
+
module AutoRestrictEagerGraph
|
47
|
+
module ClassMethods
|
48
|
+
# When defining an association, if a block is given for the association, but
|
49
|
+
# a :graph_* option is not used, disallow the use of eager_graph.
|
50
|
+
def associate(type, name, opts = OPTS, &block)
|
51
|
+
opts = super
|
52
|
+
|
53
|
+
if opts[:block] && !opts.has_key?(:allow_eager_graph) && !opts[:orig_opts].any?{|k,| /\Agraph_/ =~ k}
|
54
|
+
opts[:allow_eager_graph] = false
|
55
|
+
end
|
56
|
+
|
57
|
+
opts
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -9,14 +9,16 @@ module Sequel
|
|
9
9
|
# 2. not_null validations on NOT NULL columns (optionally, presence validations)
|
10
10
|
# 3. unique validations on columns or sets of columns with unique indexes
|
11
11
|
# 4. max length validations on string columns
|
12
|
+
# 5. no null byte validations on string columns
|
13
|
+
# 6. minimum and maximum values on columns
|
12
14
|
#
|
13
|
-
# To determine the columns to use for the type/not_null/max_length validations,
|
15
|
+
# To determine the columns to use for the type/not_null/max_length/no_null_byte/max_value/min_value validations,
|
14
16
|
# the plugin looks at the database schema for the model's table. To determine
|
15
17
|
# the unique validations, Sequel looks at the indexes on the table. In order
|
16
18
|
# for this plugin to be fully functional, the underlying database adapter needs
|
17
19
|
# to support both schema and index parsing. Additionally, unique validations are
|
18
20
|
# only added for models that select from a simple table, they are not added for models
|
19
|
-
# that select from a subquery
|
21
|
+
# that select from a subquery.
|
20
22
|
#
|
21
23
|
# This plugin uses the validation_helpers plugin underneath to implement the
|
22
24
|
# validations. It does not allow for any per-column validation message
|
@@ -50,7 +52,7 @@ module Sequel
|
|
50
52
|
#
|
51
53
|
# Model.plugin :auto_validations, unique_opts: {only_if_modified: true}
|
52
54
|
#
|
53
|
-
# This works for unique_opts, max_length_opts, schema_types_opts,
|
55
|
+
# This works for unique_opts, max_length_opts, schema_types_opts, max_value_opts, min_value_opts, no_null_byte_opts,
|
54
56
|
# explicit_not_null_opts, and not_null_opts.
|
55
57
|
#
|
56
58
|
# If you only want auto_validations to add validations to columns that do not already
|
@@ -71,25 +73,35 @@ module Sequel
|
|
71
73
|
MAX_LENGTH_OPTIONS = {:from=>:values, :allow_nil=>true}.freeze
|
72
74
|
SCHEMA_TYPES_OPTIONS = NOT_NULL_OPTIONS
|
73
75
|
UNIQUE_OPTIONS = NOT_NULL_OPTIONS
|
76
|
+
NO_NULL_BYTE_OPTIONS = MAX_LENGTH_OPTIONS
|
77
|
+
MAX_VALUE_OPTIONS = {:from=>:values, :allow_nil=>true, :skip_invalid=>true}.freeze
|
78
|
+
MIN_VALUE_OPTIONS = MAX_VALUE_OPTIONS
|
79
|
+
AUTO_VALIDATE_OPTIONS = {
|
80
|
+
:no_null_byte=>NO_NULL_BYTE_OPTIONS,
|
81
|
+
:not_null=>NOT_NULL_OPTIONS,
|
82
|
+
:explicit_not_null=>EXPLICIT_NOT_NULL_OPTIONS,
|
83
|
+
:max_length=>MAX_LENGTH_OPTIONS,
|
84
|
+
:max_value=>MAX_VALUE_OPTIONS,
|
85
|
+
:min_value=>MIN_VALUE_OPTIONS,
|
86
|
+
:schema_types=>SCHEMA_TYPES_OPTIONS,
|
87
|
+
:unique=>UNIQUE_OPTIONS
|
88
|
+
}.freeze
|
89
|
+
|
74
90
|
EMPTY_ARRAY = [].freeze
|
75
91
|
|
76
92
|
def self.apply(model, opts=OPTS)
|
77
93
|
model.instance_exec do
|
78
94
|
plugin :validation_helpers
|
79
95
|
@auto_validate_presence = false
|
96
|
+
@auto_validate_no_null_byte_columns = []
|
80
97
|
@auto_validate_not_null_columns = []
|
81
98
|
@auto_validate_explicit_not_null_columns = []
|
82
99
|
@auto_validate_max_length_columns = []
|
100
|
+
@auto_validate_max_value_columns = []
|
101
|
+
@auto_validate_min_value_columns = []
|
83
102
|
@auto_validate_unique_columns = []
|
84
103
|
@auto_validate_types = true
|
85
|
-
|
86
|
-
@auto_validate_options = {
|
87
|
-
:not_null=>NOT_NULL_OPTIONS,
|
88
|
-
:explicit_not_null=>EXPLICIT_NOT_NULL_OPTIONS,
|
89
|
-
:max_length=>MAX_LENGTH_OPTIONS,
|
90
|
-
:schema_types=>SCHEMA_TYPES_OPTIONS,
|
91
|
-
:unique=>UNIQUE_OPTIONS
|
92
|
-
}.freeze
|
104
|
+
@auto_validate_options = AUTO_VALIDATE_OPTIONS
|
93
105
|
end
|
94
106
|
end
|
95
107
|
|
@@ -102,14 +114,14 @@ module Sequel
|
|
102
114
|
end
|
103
115
|
|
104
116
|
h = @auto_validate_options.dup
|
105
|
-
[:not_null, :explicit_not_null, :max_length, :schema_types, :unique].each do |type|
|
117
|
+
[:not_null, :explicit_not_null, :max_length, :max_value, :min_value, :no_null_byte, :schema_types, :unique].each do |type|
|
106
118
|
if type_opts = opts[:"#{type}_opts"]
|
107
119
|
h[type] = h[type].merge(type_opts).freeze
|
108
120
|
end
|
109
121
|
end
|
110
122
|
|
111
123
|
if opts[:skip_invalid]
|
112
|
-
[:not_null, :explicit_not_null, :max_length, :schema_types].each do |type|
|
124
|
+
[:not_null, :explicit_not_null, :no_null_byte, :max_length, :schema_types].each do |type|
|
113
125
|
h[type] = h[type].merge(:skip_invalid=>true).freeze
|
114
126
|
end
|
115
127
|
end
|
@@ -119,6 +131,9 @@ module Sequel
|
|
119
131
|
end
|
120
132
|
|
121
133
|
module ClassMethods
|
134
|
+
# The columns with automatic no_null_byte validations
|
135
|
+
attr_reader :auto_validate_no_null_byte_columns
|
136
|
+
|
122
137
|
# The columns with automatic not_null validations
|
123
138
|
attr_reader :auto_validate_not_null_columns
|
124
139
|
|
@@ -129,13 +144,31 @@ module Sequel
|
|
129
144
|
# pairs, with the first entry being the column name and second entry being the maximum length.
|
130
145
|
attr_reader :auto_validate_max_length_columns
|
131
146
|
|
147
|
+
# The columns with automatch max value validations, as an array of
|
148
|
+
# pairs, with the first entry being the column name and second entry being the maximum value.
|
149
|
+
attr_reader :auto_validate_max_value_columns
|
150
|
+
|
151
|
+
# The columns with automatch min value validations, as an array of
|
152
|
+
# pairs, with the first entry being the column name and second entry being the minimum value.
|
153
|
+
attr_reader :auto_validate_min_value_columns
|
154
|
+
|
132
155
|
# The columns or sets of columns with automatic unique validations
|
133
156
|
attr_reader :auto_validate_unique_columns
|
134
157
|
|
135
158
|
# Inherited options
|
136
159
|
attr_reader :auto_validate_options
|
137
160
|
|
138
|
-
Plugins.inherited_instance_variables(self,
|
161
|
+
Plugins.inherited_instance_variables(self,
|
162
|
+
:@auto_validate_presence=>nil,
|
163
|
+
:@auto_validate_types=>nil,
|
164
|
+
:@auto_validate_no_null_byte_columns=>:dup,
|
165
|
+
:@auto_validate_not_null_columns=>:dup,
|
166
|
+
:@auto_validate_explicit_not_null_columns=>:dup,
|
167
|
+
:@auto_validate_max_length_columns=>:dup,
|
168
|
+
:@auto_validate_max_value_columns=>:dup,
|
169
|
+
:@auto_validate_min_value_columns=>:dup,
|
170
|
+
:@auto_validate_unique_columns=>:dup,
|
171
|
+
:@auto_validate_options => :dup)
|
139
172
|
Plugins.after_set_dataset(self, :setup_auto_validations)
|
140
173
|
|
141
174
|
# Whether to use a presence validation for not null columns
|
@@ -150,20 +183,27 @@ module Sequel
|
|
150
183
|
|
151
184
|
# Freeze auto_validation settings when freezing model class.
|
152
185
|
def freeze
|
186
|
+
@auto_validate_no_null_byte_columns.freeze
|
153
187
|
@auto_validate_not_null_columns.freeze
|
154
188
|
@auto_validate_explicit_not_null_columns.freeze
|
155
189
|
@auto_validate_max_length_columns.freeze
|
190
|
+
@auto_validate_max_value_columns.freeze
|
191
|
+
@auto_validate_min_value_columns.freeze
|
156
192
|
@auto_validate_unique_columns.freeze
|
157
193
|
|
158
194
|
super
|
159
195
|
end
|
160
196
|
|
161
|
-
# Skip automatic validations for the given validation type
|
197
|
+
# Skip automatic validations for the given validation type
|
198
|
+
# (:not_null, :no_null_byte, :types, :unique, :max_length, :max_value, :min_value).
|
162
199
|
# If :all is given as the type, skip all auto validations.
|
200
|
+
#
|
201
|
+
# Skipping types validation automatically skips max_value and min_value validations,
|
202
|
+
# since those validations require valid types.
|
163
203
|
def skip_auto_validations(type)
|
164
204
|
case type
|
165
205
|
when :all
|
166
|
-
[:not_null, :types, :unique, :max_length].each{|v| skip_auto_validations(v)}
|
206
|
+
[:not_null, :no_null_byte, :types, :unique, :max_length, :max_value, :min_value].each{|v| skip_auto_validations(v)}
|
167
207
|
when :not_null
|
168
208
|
auto_validate_not_null_columns.clear
|
169
209
|
auto_validate_explicit_not_null_columns.clear
|
@@ -183,6 +223,9 @@ module Sequel
|
|
183
223
|
explicit_not_null_cols += Array(primary_key)
|
184
224
|
@auto_validate_explicit_not_null_columns = explicit_not_null_cols.uniq
|
185
225
|
@auto_validate_max_length_columns = db_schema.select{|col, sch| sch[:type] == :string && sch[:max_length].is_a?(Integer)}.map{|col, sch| [col, sch[:max_length]]}
|
226
|
+
@auto_validate_max_value_columns = db_schema.select{|col, sch| sch[:max_value]}.map{|col, sch| [col, sch[:max_value]]}
|
227
|
+
@auto_validate_min_value_columns = db_schema.select{|col, sch| sch[:min_value]}.map{|col, sch| [col, sch[:min_value]]}
|
228
|
+
@auto_validate_no_null_byte_columns = db_schema.select{|_, sch| sch[:type] == :string}.map{|col, _| col}
|
186
229
|
table = dataset.first_source_table
|
187
230
|
@auto_validate_unique_columns = if db.supports_index_parsing? && [Symbol, SQL::QualifiedIdentifier, SQL::Identifier, String].any?{|c| table.is_a?(c)}
|
188
231
|
db.indexes(table).select{|name, idx| idx[:unique] == true}.map{|name, idx| idx[:columns].length == 1 ? idx[:columns].first : idx[:columns]}
|
@@ -209,6 +252,9 @@ module Sequel
|
|
209
252
|
return if skip.include?(:all)
|
210
253
|
opts = model.auto_validate_options
|
211
254
|
|
255
|
+
unless skip.include?(:no_null_byte) || (no_null_byte_columns = model.auto_validate_no_null_byte_columns).empty?
|
256
|
+
validates_no_null_byte(no_null_byte_columns, opts[:no_null_byte])
|
257
|
+
end
|
212
258
|
|
213
259
|
unless skip.include?(:not_null)
|
214
260
|
not_null_method = model.auto_validate_presence? ? :validates_presence : :validates_not_null
|
@@ -228,6 +274,18 @@ module Sequel
|
|
228
274
|
|
229
275
|
unless skip.include?(:types) || !model.auto_validate_types?
|
230
276
|
validates_schema_types(keys, opts[:schema_types])
|
277
|
+
|
278
|
+
unless skip.include?(:max_value) || ((max_value_columns = model.auto_validate_max_value_columns).empty?)
|
279
|
+
max_value_columns.each do |col, max|
|
280
|
+
validates_max_value(max, col, opts[:max_value])
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
unless skip.include?(:min_value) || ((min_value_columns = model.auto_validate_min_value_columns).empty?)
|
285
|
+
min_value_columns.each do |col, min|
|
286
|
+
validates_min_value(min, col, opts[:min_value])
|
287
|
+
end
|
288
|
+
end
|
231
289
|
end
|
232
290
|
|
233
291
|
unless skip.include?(:unique)
|
@@ -104,7 +104,7 @@ module Sequel
|
|
104
104
|
# should reference the subquery alias (and qualified identifiers should not be needed
|
105
105
|
# unless joining to another table):
|
106
106
|
#
|
107
|
-
# a = Executive.where(:
|
107
|
+
# a = Executive.where(id: 1).first # works
|
108
108
|
# a = Executive.where{{employees[:id]=>1}}.first # works
|
109
109
|
# a = Executive.where{{executives[:id]=>1}}.first # doesn't work
|
110
110
|
#
|
@@ -115,7 +115,7 @@ module Sequel
|
|
115
115
|
#
|
116
116
|
# pks = Executive.where{num_staff < 10}.select_map(:id)
|
117
117
|
# Executive.cti_tables.reverse_each do |table|
|
118
|
-
# DB.from(table).where(:
|
118
|
+
# DB.from(table).where(id: pks).delete
|
119
119
|
# end
|
120
120
|
#
|
121
121
|
# = Usage
|
@@ -31,7 +31,6 @@ rescue RuntimeError, OpenSSL::Cipher::CipherError
|
|
31
31
|
# :nocov:
|
32
32
|
end
|
33
33
|
|
34
|
-
require 'base64'
|
35
34
|
require 'securerandom'
|
36
35
|
|
37
36
|
module Sequel
|
@@ -326,7 +325,7 @@ module Sequel
|
|
326
325
|
# DB.alter_table(:ce_test) do
|
327
326
|
# c = Sequel[:encrypted_column_name]
|
328
327
|
# add_constraint(:enc_base64) do
|
329
|
-
# octet_length(decode(regexp_replace(regexp_replace(c, '_', '/', 'g'), '-', '+', 'g'), 'base64')) >= 65
|
328
|
+
# octet_length(decode(regexp_replace(regexp_replace(c, '_', '/', 'g'), '-', '+', 'g'), 'base64')) >= 65
|
330
329
|
# end
|
331
330
|
# end
|
332
331
|
#
|
@@ -356,7 +355,7 @@ module Sequel
|
|
356
355
|
|
357
356
|
# Keys should be an array of arrays containing key_id, key string, auth_data, and padding.
|
358
357
|
def initialize(keys)
|
359
|
-
if keys.empty?
|
358
|
+
if !keys || keys.empty?
|
360
359
|
raise Error, "Cannot initialize encryptor without encryption key"
|
361
360
|
end
|
362
361
|
|
@@ -375,7 +374,7 @@ module Sequel
|
|
375
374
|
# Decrypt using any supported format and any available key.
|
376
375
|
def decrypt(data)
|
377
376
|
begin
|
378
|
-
data =
|
377
|
+
data = urlsafe_decode64(data)
|
379
378
|
rescue ArgumentError
|
380
379
|
raise Error, "Unable to decode encrypted column: invalid base64"
|
381
380
|
end
|
@@ -448,7 +447,7 @@ module Sequel
|
|
448
447
|
# The prefix string of columns for the given search type and the first configured encryption key.
|
449
448
|
# Used to find values that do not use this prefix in order to perform reencryption.
|
450
449
|
def current_key_prefix(search_type)
|
451
|
-
|
450
|
+
urlsafe_encode64("#{search_type.chr}\0#{@key_id.chr}")
|
452
451
|
end
|
453
452
|
|
454
453
|
# The prefix values to search for the given data (an array of strings), assuming the column uses
|
@@ -472,11 +471,33 @@ module Sequel
|
|
472
471
|
|
473
472
|
private
|
474
473
|
|
474
|
+
if RUBY_VERSION >= '2.4'
|
475
|
+
def decode64(str)
|
476
|
+
str.unpack1("m0")
|
477
|
+
end
|
478
|
+
# :nocov:
|
479
|
+
else
|
480
|
+
def decode64(str)
|
481
|
+
str.unpack("m0")[0]
|
482
|
+
end
|
483
|
+
# :nocov:
|
484
|
+
end
|
485
|
+
|
486
|
+
def urlsafe_encode64(bin)
|
487
|
+
str = [bin].pack("m0")
|
488
|
+
str.tr!("+/", "-_")
|
489
|
+
str
|
490
|
+
end
|
491
|
+
|
492
|
+
def urlsafe_decode64(str)
|
493
|
+
decode64(str.tr("-_", "+/"))
|
494
|
+
end
|
495
|
+
|
475
496
|
# An array of strings, one for each configured encryption key, to find encypted values matching
|
476
497
|
# the given data and search format.
|
477
498
|
def _search_prefixes(data, search_type)
|
478
499
|
@key_map.map do |key_id, (key, _)|
|
479
|
-
|
500
|
+
urlsafe_encode64(_search_prefix(data, search_type, key_id, key))
|
480
501
|
end
|
481
502
|
end
|
482
503
|
|
@@ -509,7 +530,7 @@ module Sequel
|
|
509
530
|
cipher_text << cipher.update(data) if data_size > 0
|
510
531
|
cipher_text << cipher.final
|
511
532
|
|
512
|
-
|
533
|
+
urlsafe_encode64("#{prefix}#{random_data}#{cipher_iv}#{cipher.auth_tag}#{cipher_text}")
|
513
534
|
end
|
514
535
|
end
|
515
536
|
|
@@ -608,7 +629,7 @@ module Sequel
|
|
608
629
|
|
609
630
|
# Setup encryption for the given column.
|
610
631
|
def _encrypt_column(column, opts)
|
611
|
-
cryptor ||= if
|
632
|
+
cryptor ||= if defined?(yield)
|
612
633
|
dsl = ColumnDSL.new
|
613
634
|
yield dsl
|
614
635
|
Cryptor.new(dsl.keys)
|