sequel 4.31.0 → 4.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +24 -0
- data/Rakefile +17 -15
- data/doc/association_basics.rdoc +7 -3
- data/doc/opening_databases.rdoc +7 -0
- data/doc/release_notes/4.32.0.txt +132 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +70 -26
- data/doc/testing.rdoc +1 -0
- data/lib/sequel/adapters/jdbc.rb +2 -1
- data/lib/sequel/adapters/postgres.rb +3 -4
- data/lib/sequel/adapters/shared/mysql.rb +14 -1
- data/lib/sequel/adapters/shared/sqlite.rb +2 -2
- data/lib/sequel/extensions/_pretty_table.rb +2 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +2 -0
- data/lib/sequel/extensions/columns_introspection.rb +2 -0
- data/lib/sequel/extensions/connection_validator.rb +2 -0
- data/lib/sequel/extensions/constraint_validations.rb +2 -0
- data/lib/sequel/extensions/core_extensions.rb +1 -5
- data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -0
- data/lib/sequel/extensions/dataset_source_alias.rb +2 -0
- data/lib/sequel/extensions/date_arithmetic.rb +2 -0
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +3 -1
- data/lib/sequel/extensions/error_sql.rb +2 -0
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +2 -0
- data/lib/sequel/extensions/graph_each.rb +2 -0
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +2 -0
- data/lib/sequel/extensions/looser_typecasting.rb +3 -1
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +4 -0
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +2 -0
- data/lib/sequel/extensions/named_timezones.rb +2 -0
- data/lib/sequel/extensions/no_auto_literal_strings.rb +84 -0
- data/lib/sequel/extensions/null_dataset.rb +2 -0
- data/lib/sequel/extensions/pagination.rb +2 -0
- data/lib/sequel/extensions/pg_array.rb +2 -4
- data/lib/sequel/extensions/pg_array_ops.rb +2 -0
- data/lib/sequel/extensions/pg_enum.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -4
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_inet.rb +2 -4
- data/lib/sequel/extensions/pg_inet_ops.rb +2 -0
- data/lib/sequel/extensions/pg_interval.rb +2 -4
- data/lib/sequel/extensions/pg_json.rb +4 -4
- data/lib/sequel/extensions/pg_json_ops.rb +3 -0
- data/lib/sequel/extensions/pg_loose_count.rb +2 -0
- data/lib/sequel/extensions/pg_range.rb +2 -4
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +2 -4
- data/lib/sequel/extensions/pg_row_ops.rb +2 -0
- data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -0
- data/lib/sequel/extensions/pretty_table.rb +2 -0
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/query_literals.rb +7 -5
- data/lib/sequel/extensions/round_timestamps.rb +4 -3
- data/lib/sequel/extensions/schema_caching.rb +2 -0
- data/lib/sequel/extensions/schema_dumper.rb +2 -0
- data/lib/sequel/extensions/select_remove.rb +2 -0
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +2 -0
- data/lib/sequel/extensions/server_block.rb +3 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -0
- data/lib/sequel/extensions/split_array_nil.rb +2 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +2 -0
- data/lib/sequel/model/associations.rb +95 -55
- data/lib/sequel/plugins/association_pks.rb +58 -33
- data/lib/sequel/plugins/eager_each.rb +22 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +44 -3
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/mysql_spec.rb +34 -6
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/bin_spec.rb +2 -2
- data/spec/core/dataset_spec.rb +7 -0
- data/spec/extensions/association_pks_spec.rb +38 -0
- data/spec/extensions/class_table_inheritance_spec.rb +24 -0
- data/spec/extensions/eager_each_spec.rb +25 -1
- data/spec/extensions/no_auto_literal_strings_spec.rb +65 -0
- data/spec/extensions/pg_range_spec.rb +1 -0
- data/spec/extensions/spec_helper.rb +5 -5
- data/spec/extensions/tactical_eager_loading_spec.rb +71 -17
- data/spec/integration/associations_test.rb +77 -62
- data/spec/integration/dataset_test.rb +3 -3
- data/spec/integration/plugin_test.rb +22 -0
- data/spec/integration/prepared_statement_test.rb +8 -8
- data/spec/integration/spec_helper.rb +4 -0
- data/spec/model/association_reflection_spec.rb +30 -0
- data/spec/model/associations_spec.rb +177 -16
- metadata +6 -2
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -632,7 +632,8 @@ module Sequel
|
|
632
632
|
:allow_null=>(h[:nullable] != 0),
|
633
633
|
:primary_key=>pks.include?(h[:column_name]),
|
634
634
|
:column_size=>h[:column_size],
|
635
|
-
:scale=>h[:decimal_digits]
|
635
|
+
:scale=>h[:decimal_digits],
|
636
|
+
:remarks=>h[:remarks]
|
636
637
|
}
|
637
638
|
if s[:primary_key]
|
638
639
|
s[:auto_increment] = h[:is_autoincrement] == "YES"
|
@@ -306,10 +306,9 @@ module Sequel
|
|
306
306
|
|
307
307
|
# Disconnect given connection
|
308
308
|
def disconnect_connection(conn)
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
end
|
309
|
+
conn.finish
|
310
|
+
rescue PGError, IOError
|
311
|
+
nil
|
313
312
|
end
|
314
313
|
|
315
314
|
if SEQUEL_POSTGRES_USES_PG && Object.const_defined?(:PG) && ::PG.const_defined?(:Constants) && ::PG::Constants.const_defined?(:PG_DIAG_SCHEMA_NAME)
|
@@ -682,6 +682,18 @@ module Sequel
|
|
682
682
|
def calc_found_rows
|
683
683
|
clone(:calc_found_rows => true)
|
684
684
|
end
|
685
|
+
|
686
|
+
# Sets up the select methods to delete from if deleting from a
|
687
|
+
# joined dataset:
|
688
|
+
#
|
689
|
+
# DB[:a].join(:b, :a_id=>:id).delete
|
690
|
+
# # DELETE a FROM a INNER JOIN b ON (b.a_id = a.id)
|
691
|
+
#
|
692
|
+
# DB[:a].join(:b, :a_id=>:id).delete_from(:a, :b).delete
|
693
|
+
# # DELETE a, b FROM a INNER JOIN b ON (b.a_id = a.id)
|
694
|
+
def delete_from(*tables)
|
695
|
+
clone(:delete_from=>tables)
|
696
|
+
end
|
685
697
|
|
686
698
|
# Return the results of an EXPLAIN query as a string. Options:
|
687
699
|
# :extended :: Use EXPLAIN EXPTENDED instead of EXPLAIN if true.
|
@@ -847,7 +859,8 @@ module Sequel
|
|
847
859
|
def delete_from_sql(sql)
|
848
860
|
if joined_dataset?
|
849
861
|
sql << SPACE
|
850
|
-
|
862
|
+
tables = @opts[:delete_from] || @opts[:from][0..0]
|
863
|
+
source_list_append(sql, tables)
|
851
864
|
sql << FROM
|
852
865
|
source_list_append(sql, @opts[:from])
|
853
866
|
select_join_sql(sql)
|
@@ -13,9 +13,9 @@ module Sequel
|
|
13
13
|
AUTO_VACUUM = [:none, :full, :incremental].freeze
|
14
14
|
PRIMARY_KEY_INDEX_RE = /\Asqlite_autoindex_/.freeze
|
15
15
|
SYNCHRONOUS = [:off, :normal, :full].freeze
|
16
|
-
TABLES_FILTER =
|
16
|
+
TABLES_FILTER = Sequel.~(:name=>'sqlite_sequence'.freeze) & {:type => 'table'.freeze}
|
17
17
|
TEMP_STORE = [:default, :file, :memory].freeze
|
18
|
-
VIEWS_FILTER =
|
18
|
+
VIEWS_FILTER = {:type => 'view'.freeze}.freeze
|
19
19
|
TRANSACTION_MODE = {
|
20
20
|
:deferred => "BEGIN DEFERRED TRANSACTION".freeze,
|
21
21
|
:immediate => "BEGIN IMMEDIATE TRANSACTION".freeze,
|
@@ -44,6 +44,8 @@
|
|
44
44
|
# threaded pools work fine even in single threaded code, so if
|
45
45
|
# you are currently using a single threaded pool and want to
|
46
46
|
# use this extension, switch to using a threaded pool.
|
47
|
+
#
|
48
|
+
# Related module: Sequel::ConnectionValidator
|
47
49
|
|
48
50
|
#
|
49
51
|
module Sequel
|
@@ -123,6 +123,8 @@
|
|
123
123
|
# <tt>drop_constraint_validations_for(:table=>'table')</tt>, and then
|
124
124
|
# readd all constraints you want to use inside the alter table block,
|
125
125
|
# making no other changes inside the alter_table block.
|
126
|
+
#
|
127
|
+
# Related module: Sequel::ConstraintValidations
|
126
128
|
|
127
129
|
#
|
128
130
|
module Sequel
|
@@ -3,11 +3,7 @@
|
|
3
3
|
# These are extensions to core classes that Sequel enables by default.
|
4
4
|
# They make using Sequel's DSL easier by adding methods to Array,
|
5
5
|
# Hash, String, and Symbol to add methods that return Sequel
|
6
|
-
# expression objects.
|
7
|
-
#
|
8
|
-
# This extension is currently loaded by default, but that will no
|
9
|
-
# longer be true in Sequel 4. Starting in Sequel 4, you will
|
10
|
-
# need to load it manually via:
|
6
|
+
# expression objects. To load the extension:
|
11
7
|
#
|
12
8
|
# Sequel.extension :core_extensions
|
13
9
|
|
@@ -21,11 +21,13 @@
|
|
21
21
|
# is probably the desired behavior if you are using this extension:
|
22
22
|
#
|
23
23
|
# DB.extension(:empty_array_consider_nulls)
|
24
|
+
#
|
25
|
+
# Related module: Sequel::EmptyArrayConsiderNulls
|
24
26
|
|
25
27
|
#
|
26
28
|
module Sequel
|
27
29
|
module EmptyArrayConsiderNulls
|
28
|
-
# Use
|
30
|
+
# Use an expression that returns NULL if the column value is NULL.
|
29
31
|
def empty_array_value(op, cols)
|
30
32
|
c = Array(cols)
|
31
33
|
SQL::BooleanExpression.from_value_pairs(c.zip(c), :AND, op == :IN)
|
@@ -11,6 +11,8 @@
|
|
11
11
|
# To load the extension into the database:
|
12
12
|
#
|
13
13
|
# DB.extension :looser_typecasting
|
14
|
+
#
|
15
|
+
# Related module: Sequel::LooserTypecasting
|
14
16
|
|
15
17
|
#
|
16
18
|
module Sequel
|
@@ -25,7 +27,7 @@ module Sequel
|
|
25
27
|
value.to_i
|
26
28
|
end
|
27
29
|
|
28
|
-
# Typecast the value to an
|
30
|
+
# Typecast the value to an String using to_s instead of Kernel.String
|
29
31
|
def typecast_value_string(value)
|
30
32
|
value.to_s
|
31
33
|
end
|
@@ -7,6 +7,10 @@
|
|
7
7
|
# To load the extension:
|
8
8
|
#
|
9
9
|
# Sequel.extension :migration
|
10
|
+
#
|
11
|
+
# Related modules: Sequel::Migration, Sequel::SimpleMigration,
|
12
|
+
# Sequel::MigrationDSL, Sequel::MigrationReverser, Sequel::MigrationAlterTableReverser,
|
13
|
+
# Sequel::Migrator, Sequel::IntegerMigrator, Sequel::TimestampMigrator
|
10
14
|
|
11
15
|
#
|
12
16
|
module Sequel
|
@@ -38,6 +38,8 @@
|
|
38
38
|
# timezone when fetching rows is dependent on the database adapter,
|
39
39
|
# and only works on adapters where Sequel itself does the conversion.
|
40
40
|
# It should work on mysql, postgres, sqlite, ibmdb, and jdbc.
|
41
|
+
#
|
42
|
+
# Related module: Sequel::NamedTimezones
|
41
43
|
|
42
44
|
require 'tzinfo'
|
43
45
|
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# The no_auto_literal_strings extension removes Sequel's automatic conversion
|
4
|
+
# of strings to literal strings in the dataset filter methods. By default,
|
5
|
+
# Sequel considers a string passed to a filter method as a literal string:
|
6
|
+
#
|
7
|
+
# DB[:table].where("name > 'A'")
|
8
|
+
#
|
9
|
+
# This is fine, except when the string is derived from user input:
|
10
|
+
#
|
11
|
+
# DB[:table].where("name > '#{params[:user]}'") # SQL Injection!
|
12
|
+
#
|
13
|
+
# Sequel does support using placeholders for such strings:
|
14
|
+
#
|
15
|
+
# DB[:table].where("name > ?", params[:user].to_s) # Safe
|
16
|
+
#
|
17
|
+
# However, if you forget to user placeholders, and pass a string to a filter
|
18
|
+
# method that is derived from user input, you open yourself up to SQL injection.
|
19
|
+
# With this extension, using a plain string in a filter method will result
|
20
|
+
# in an exception being raised. You either need to explicitly use a literal
|
21
|
+
# string:
|
22
|
+
#
|
23
|
+
# DB[:table].where(Sequel.lit("name > ?", params[:user].to_s))
|
24
|
+
#
|
25
|
+
# or you need to construct the same SQL using a non-string based approach:
|
26
|
+
#
|
27
|
+
# DB[:table].where{|o| o.name > params[:user].to_s}
|
28
|
+
#
|
29
|
+
# Note that as listed in Sequel's security guide, a large number of dataset
|
30
|
+
# methods call down to a filtering method, and this protects all of those
|
31
|
+
# cases.
|
32
|
+
#
|
33
|
+
# This extension also protects the use of a plain string passed to Dataset#update:
|
34
|
+
#
|
35
|
+
# DB[:table].update("column = column + 1")
|
36
|
+
#
|
37
|
+
# Again, you either need to explicitly use a literal string:
|
38
|
+
#
|
39
|
+
# DB[:table].update(Sequel.lit("column = column + 1"))
|
40
|
+
#
|
41
|
+
# or construct the same SQL using a non-string based approach:
|
42
|
+
#
|
43
|
+
# DB[:table].update(:column => Sequel.expr(:column) + 1)
|
44
|
+
#
|
45
|
+
# Related module: Sequel::Dataset::NoAutoLiteralStrings
|
46
|
+
|
47
|
+
#
|
48
|
+
module Sequel
|
49
|
+
class Dataset
|
50
|
+
module NoAutoLiteralStrings
|
51
|
+
# Raise an error if passing a plain string or an array whose first
|
52
|
+
# entry is a plain string.
|
53
|
+
def filter_expr(expr = nil)
|
54
|
+
case expr
|
55
|
+
when LiteralString
|
56
|
+
super
|
57
|
+
when String
|
58
|
+
raise Error, "plain string passed to a dataset filtering method"
|
59
|
+
when Array
|
60
|
+
if expr.first.is_a?(String) && !expr.first.is_a?(LiteralString)
|
61
|
+
raise Error, "plain string passed to a dataset filtering method"
|
62
|
+
end
|
63
|
+
super
|
64
|
+
else
|
65
|
+
super
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Raise an error if passing a plain string.
|
70
|
+
def update_sql(values=OPTS)
|
71
|
+
case values
|
72
|
+
when LiteralString
|
73
|
+
super
|
74
|
+
when String
|
75
|
+
raise Error, "plain string passed to a dataset filtering method"
|
76
|
+
else
|
77
|
+
super
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
register_extension(:no_auto_literal_strings, NoAutoLiteralStrings)
|
83
|
+
end
|
84
|
+
end
|
@@ -41,10 +41,6 @@
|
|
41
41
|
# See the {schema modification guide}[rdoc-ref:doc/schema_modification.rdoc]
|
42
42
|
# for details on using postgres array columns in CREATE/ALTER TABLE statements.
|
43
43
|
#
|
44
|
-
# If you are not using the native postgres or jdbc/postgresql adapter and are using array
|
45
|
-
# types as model column values you probably should use the the pg_typecast_on_load plugin
|
46
|
-
# if the column values are returned as a string.
|
47
|
-
#
|
48
44
|
# This extension by default includes handlers for array types for
|
49
45
|
# all scalar types that the native postgres adapter handles. It
|
50
46
|
# also makes it easy to add support for other array types. In
|
@@ -84,6 +80,8 @@
|
|
84
80
|
# operators, look into the pg_array_ops extension.
|
85
81
|
#
|
86
82
|
# This extension requires the strscan and delegate libraries.
|
83
|
+
#
|
84
|
+
# Related module: Sequel::Postgres::PGArray
|
87
85
|
|
88
86
|
require 'delegate'
|
89
87
|
require 'strscan'
|