sequel 4.21.0 → 4.22.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 +32 -0
- data/README.rdoc +3 -4
- data/doc/opening_databases.rdoc +10 -75
- data/doc/release_notes/4.22.0.txt +72 -0
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/cubrid.rb +3 -3
- data/lib/sequel/adapters/db2.rb +1 -0
- data/lib/sequel/adapters/dbi.rb +1 -0
- data/lib/sequel/adapters/fdbsql.rb +3 -2
- data/lib/sequel/adapters/firebird.rb +1 -0
- data/lib/sequel/adapters/ibmdb.rb +1 -21
- data/lib/sequel/adapters/informix.rb +1 -0
- data/lib/sequel/adapters/jdbc.rb +37 -49
- data/lib/sequel/adapters/jdbc/fdbsql.rb +1 -0
- data/lib/sequel/adapters/mysql.rb +5 -3
- data/lib/sequel/adapters/mysql2.rb +5 -2
- data/lib/sequel/adapters/odbc.rb +8 -4
- data/lib/sequel/adapters/openbase.rb +1 -0
- data/lib/sequel/adapters/oracle.rb +3 -46
- data/lib/sequel/adapters/postgres.rb +3 -36
- data/lib/sequel/adapters/shared/access.rb +1 -1
- data/lib/sequel/adapters/shared/fdbsql.rb +3 -3
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +12 -44
- data/lib/sequel/adapters/shared/oracle.rb +6 -2
- data/lib/sequel/adapters/shared/postgres.rb +6 -6
- data/lib/sequel/adapters/shared/sqlite.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +3 -46
- data/lib/sequel/adapters/tinytds.rb +12 -28
- data/lib/sequel/adapters/utils/pg_types.rb +1 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +63 -16
- data/lib/sequel/connection_pool/threaded.rb +72 -18
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +2 -2
- data/lib/sequel/database/misc.rb +5 -5
- data/lib/sequel/database/query.rb +3 -2
- data/lib/sequel/database/schema_generator.rb +19 -19
- data/lib/sequel/database/schema_methods.rb +2 -2
- data/lib/sequel/database/transactions.rb +3 -3
- data/lib/sequel/dataset/actions.rb +18 -8
- data/lib/sequel/dataset/graph.rb +2 -2
- data/lib/sequel/dataset/prepared_statements.rb +28 -1
- data/lib/sequel/dataset/query.rb +7 -7
- data/lib/sequel/exceptions.rb +27 -24
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +2 -2
- data/lib/sequel/extensions/date_arithmetic.rb +2 -2
- data/lib/sequel/extensions/pg_array.rb +10 -1
- data/lib/sequel/extensions/pg_row.rb +1 -1
- data/lib/sequel/extensions/pg_static_cache_updater.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +8 -8
- data/lib/sequel/extensions/split_array_nil.rb +1 -1
- data/lib/sequel/model.rb +1 -1
- data/lib/sequel/model/associations.rb +18 -11
- data/lib/sequel/model/base.rb +15 -15
- data/lib/sequel/model/exceptions.rb +11 -2
- data/lib/sequel/plugins/accessed_columns.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +1 -1
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -7
- data/lib/sequel/plugins/composition.rb +1 -1
- data/lib/sequel/plugins/constraint_validations.rb +2 -2
- data/lib/sequel/plugins/csv_serializer.rb +171 -0
- data/lib/sequel/plugins/dirty.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +5 -5
- data/lib/sequel/plugins/pg_array_associations.rb +4 -4
- data/lib/sequel/plugins/prepared_statements.rb +2 -2
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +6 -6
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +3 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +5 -13
- data/lib/sequel/plugins/static_cache.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +2 -2
- data/lib/sequel/plugins/validation_helpers.rb +4 -4
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +17 -0
- data/spec/core/connection_pool_spec.rb +1 -1
- data/spec/core/dataset_spec.rb +22 -0
- data/spec/extensions/auto_validations_spec.rb +1 -1
- data/spec/extensions/blacklist_security_spec.rb +2 -2
- data/spec/extensions/csv_serializer_spec.rb +173 -0
- data/spec/extensions/json_serializer_spec.rb +2 -2
- data/spec/extensions/nested_attributes_spec.rb +9 -9
- data/spec/extensions/pg_array_spec.rb +5 -0
- data/spec/extensions/single_table_inheritance_spec.rb +21 -0
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/tree_spec.rb +4 -0
- data/spec/extensions/xml_serializer_spec.rb +3 -3
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +7 -0
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/associations_spec.rb +108 -14
- data/spec/model/base_spec.rb +8 -8
- data/spec/model/record_spec.rb +7 -7
- metadata +6 -2
|
@@ -119,7 +119,7 @@ module Sequel
|
|
|
119
119
|
# :no_index :: Set to true not to create the second index.
|
|
120
120
|
# :no_primary_key :: Set to true to not create the primary key.
|
|
121
121
|
def create_join_table(hash, options=OPTS)
|
|
122
|
-
keys = hash.keys.sort_by
|
|
122
|
+
keys = hash.keys.sort_by(&:to_s)
|
|
123
123
|
create_table(join_table_name(hash, options), options) do
|
|
124
124
|
keys.each do |key|
|
|
125
125
|
v = hash[key]
|
|
@@ -781,7 +781,7 @@ module Sequel
|
|
|
781
781
|
options[:name]
|
|
782
782
|
else
|
|
783
783
|
table_names = entries.map{|e| join_table_name_extract(e)}
|
|
784
|
-
table_names.map
|
|
784
|
+
table_names.map(&:to_s).sort.join('_')
|
|
785
785
|
end
|
|
786
786
|
end
|
|
787
787
|
|
|
@@ -80,7 +80,7 @@ module Sequel
|
|
|
80
80
|
tot_retries = opts.fetch(:num_retries, 5)
|
|
81
81
|
num_retries = 0 unless tot_retries.nil?
|
|
82
82
|
begin
|
|
83
|
-
transaction(opts.merge(:retry_on=>nil, :retrying=>true), &block)
|
|
83
|
+
transaction(Hash[opts].merge!(:retry_on=>nil, :retrying=>true), &block)
|
|
84
84
|
rescue *retry_on => e
|
|
85
85
|
if num_retries
|
|
86
86
|
num_retries += 1
|
|
@@ -100,7 +100,7 @@ module Sequel
|
|
|
100
100
|
raise Sequel::Error, "cannot set :retry_on options if you are already inside a transaction"
|
|
101
101
|
end
|
|
102
102
|
if opts[:savepoint] != false && (stack = _trans(conn)[:savepoints]) && stack.last
|
|
103
|
-
_transaction(conn, opts.merge(:savepoint=>true), &block)
|
|
103
|
+
_transaction(conn, Hash[opts].merge!(:savepoint=>true), &block)
|
|
104
104
|
else
|
|
105
105
|
return yield(conn)
|
|
106
106
|
end
|
|
@@ -277,7 +277,7 @@ module Sequel
|
|
|
277
277
|
callbacks = _trans(conn)[committed ? :after_commit : :after_rollback]
|
|
278
278
|
Sequel.synchronize{@transactions.delete(conn)}
|
|
279
279
|
if callbacks
|
|
280
|
-
callbacks.each
|
|
280
|
+
callbacks.each(&:call)
|
|
281
281
|
end
|
|
282
282
|
end
|
|
283
283
|
end
|
|
@@ -8,7 +8,7 @@ module Sequel
|
|
|
8
8
|
# ---------------------
|
|
9
9
|
|
|
10
10
|
# Action methods defined by Sequel that execute code on the database.
|
|
11
|
-
ACTION_METHODS = (<<-METHS).split.map
|
|
11
|
+
ACTION_METHODS = (<<-METHS).split.map(&:to_sym)
|
|
12
12
|
<< [] all avg count columns columns! delete each
|
|
13
13
|
empty? fetch_rows first first! get import insert interval last
|
|
14
14
|
map max min multi_insert paged_each range select_hash select_hash_groups select_map select_order_map
|
|
@@ -493,7 +493,8 @@ module Sequel
|
|
|
493
493
|
total_limit = @opts[:limit]
|
|
494
494
|
offset = @opts[:offset]
|
|
495
495
|
if server = @opts[:server]
|
|
496
|
-
opts = opts
|
|
496
|
+
opts = Hash[opts]
|
|
497
|
+
opts[:server] = server
|
|
497
498
|
end
|
|
498
499
|
|
|
499
500
|
rows_per_fetch = opts[:rows_per_fetch] || 1000
|
|
@@ -701,7 +702,7 @@ module Sequel
|
|
|
701
702
|
end
|
|
702
703
|
end
|
|
703
704
|
elsif key_column.is_a?(Array)
|
|
704
|
-
each{|r| h[r
|
|
705
|
+
each{|r| h[key_column.map{|k| r[k]}] = r}
|
|
705
706
|
else
|
|
706
707
|
each{|r| h[r[key_column]] = r}
|
|
707
708
|
end
|
|
@@ -744,7 +745,7 @@ module Sequel
|
|
|
744
745
|
end
|
|
745
746
|
end
|
|
746
747
|
elsif key_column.is_a?(Array)
|
|
747
|
-
each{|r| (h[r
|
|
748
|
+
each{|r| (h[key_column.map{|k| r[k]}] ||= []) << r}
|
|
748
749
|
else
|
|
749
750
|
each{|r| (h[r[key_column]] ||= []) << r}
|
|
750
751
|
end
|
|
@@ -833,7 +834,7 @@ module Sequel
|
|
|
833
834
|
# separate insert commands for each row. Otherwise, call #multi_insert_sql
|
|
834
835
|
# and execute each statement it gives separately.
|
|
835
836
|
def _import(columns, values, opts)
|
|
836
|
-
trans_opts = opts.merge(:server=>@opts[:server])
|
|
837
|
+
trans_opts = Hash[opts].merge!(:server=>@opts[:server])
|
|
837
838
|
if opts[:return] == :primary_key
|
|
838
839
|
@db.transaction(trans_opts){values.map{|v| insert(columns, v)}}
|
|
839
840
|
else
|
|
@@ -901,14 +902,23 @@ module Sequel
|
|
|
901
902
|
|
|
902
903
|
# Set the server to use to :default unless it is already set in the passed opts
|
|
903
904
|
def default_server_opts(opts)
|
|
904
|
-
@db.sharded?
|
|
905
|
+
if @db.sharded?
|
|
906
|
+
opts = Hash[opts]
|
|
907
|
+
opts[:server] = @opts[:server] || :default
|
|
908
|
+
end
|
|
909
|
+
opts
|
|
905
910
|
end
|
|
906
911
|
|
|
907
912
|
# Execute the given select SQL on the database using execute. Use the
|
|
908
913
|
# :read_only server unless a specific server is set.
|
|
909
914
|
def execute(sql, opts=OPTS, &block)
|
|
910
915
|
db = @db
|
|
911
|
-
|
|
916
|
+
if db.sharded?
|
|
917
|
+
opts = Hash[opts]
|
|
918
|
+
opts[:server] = @opts[:server] || :read_only
|
|
919
|
+
opts
|
|
920
|
+
end
|
|
921
|
+
db.execute(sql, opts, &block)
|
|
912
922
|
end
|
|
913
923
|
|
|
914
924
|
# Execute the given SQL on the database using execute_ddl.
|
|
@@ -982,7 +992,7 @@ module Sequel
|
|
|
982
992
|
[v, descending]
|
|
983
993
|
end
|
|
984
994
|
|
|
985
|
-
row_values = yield(row, order_exprs.map
|
|
995
|
+
row_values = yield(row, order_exprs.map(&:first))
|
|
986
996
|
|
|
987
997
|
last_expr = []
|
|
988
998
|
cond = order_exprs.zip(row_values).map do |(v, descending), value|
|
data/lib/sequel/dataset/graph.rb
CHANGED
|
@@ -18,7 +18,7 @@ module Sequel
|
|
|
18
18
|
raise Error, "cannot call add_graph_aliases on a dataset that has not been called with graph or set_graph_aliases"
|
|
19
19
|
end
|
|
20
20
|
columns, graph_aliases = graph_alias_columns(graph_aliases)
|
|
21
|
-
select_more(*columns).clone(:graph_aliases => ga.merge(graph_aliases))
|
|
21
|
+
select_more(*columns).clone(:graph_aliases => Hash[ga].merge!(graph_aliases))
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# Similar to Dataset#join_table, but uses unambiguous aliases for selected
|
|
@@ -72,7 +72,7 @@ module Sequel
|
|
|
72
72
|
when SQL::QualifiedIdentifier
|
|
73
73
|
table_alias ||= split_qualifiers(table).last
|
|
74
74
|
when SQL::AliasedExpression
|
|
75
|
-
return graph(table.expression, join_conditions, {:table_alias=>table.alias}.merge(options), &block)
|
|
75
|
+
return graph(table.expression, join_conditions, {:table_alias=>table.alias}.merge!(options), &block)
|
|
76
76
|
else
|
|
77
77
|
raise Error, "The dataset argument should be a symbol or dataset"
|
|
78
78
|
end
|
|
@@ -7,6 +7,33 @@ module Sequel
|
|
|
7
7
|
# ---------------------
|
|
8
8
|
|
|
9
9
|
PREPARED_ARG_PLACEHOLDER = LiteralString.new('?').freeze
|
|
10
|
+
|
|
11
|
+
DEFAULT_PREPARED_STATEMENT_MODULE_METHODS = %w'execute execute_dui execute_insert'.freeze.each(&:freeze)
|
|
12
|
+
PREPARED_STATEMENT_MODULE_CODE = {
|
|
13
|
+
:bind => "opts = Hash[opts]; opts[:arguments] = bind_arguments".freeze,
|
|
14
|
+
:prepare => "sql = prepared_statement_name".freeze,
|
|
15
|
+
:prepare_bind => "sql = prepared_statement_name; opts = Hash[opts]; opts[:arguments] = bind_arguments".freeze
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
def self.prepared_statements_module(code, mods, meths=DEFAULT_PREPARED_STATEMENT_MODULE_METHODS, &block)
|
|
19
|
+
code = PREPARED_STATEMENT_MODULE_CODE[code] || code
|
|
20
|
+
|
|
21
|
+
Module.new do
|
|
22
|
+
Array(mods).each do |mod|
|
|
23
|
+
include mod
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if block
|
|
27
|
+
module_eval(&block)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
meths.each do |meth|
|
|
31
|
+
module_eval("def #{meth}(sql, opts=Sequel::OPTS) #{code}; super end", __FILE__, __LINE__)
|
|
32
|
+
end
|
|
33
|
+
private *meths
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
private_class_method :prepared_statements_module
|
|
10
37
|
|
|
11
38
|
# Default implementation of the argument mapper to allow
|
|
12
39
|
# native database support for bind variables and prepared
|
|
@@ -221,7 +248,7 @@ module Sequel
|
|
|
221
248
|
# # SELECT * FROM table WHERE id = ? LIMIT 1 -- (1)
|
|
222
249
|
# # => {:id=>1}
|
|
223
250
|
def bind(bind_vars={})
|
|
224
|
-
clone(:bind_vars=>@opts[:bind_vars] ? @opts[:bind_vars].merge(bind_vars) : bind_vars)
|
|
251
|
+
clone(:bind_vars=>@opts[:bind_vars] ? Hash[@opts[:bind_vars]].merge!(bind_vars) : bind_vars)
|
|
225
252
|
end
|
|
226
253
|
|
|
227
254
|
# For the given type (:select, :first, :insert, :insert_select, :update, or :delete),
|
data/lib/sequel/dataset/query.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Sequel
|
|
|
32
32
|
JOIN_METHODS = (CONDITIONED_JOIN_TYPES + UNCONDITIONED_JOIN_TYPES).map{|x| "#{x}_join".to_sym} + [:join, :join_table]
|
|
33
33
|
|
|
34
34
|
# Methods that return modified datasets
|
|
35
|
-
QUERY_METHODS = (<<-METHS).split.map
|
|
35
|
+
QUERY_METHODS = (<<-METHS).split.map(&:to_sym) + JOIN_METHODS
|
|
36
36
|
add_graph_aliases and distinct except exclude exclude_having exclude_where
|
|
37
37
|
filter for_update from from_self graph grep group group_and_count group_by having intersect invert
|
|
38
38
|
limit lock_style naked offset or order order_append order_by order_more order_prepend qualify
|
|
@@ -74,10 +74,10 @@ module Sequel
|
|
|
74
74
|
def clone(opts = nil)
|
|
75
75
|
c = super()
|
|
76
76
|
if opts
|
|
77
|
-
c.instance_variable_set(:@opts, @opts.merge(opts))
|
|
77
|
+
c.instance_variable_set(:@opts, Hash[@opts].merge!(opts))
|
|
78
78
|
c.instance_variable_set(:@columns, nil) if @columns && !opts.each_key{|o| break if COLUMN_CHANGE_OPTS.include?(o)}
|
|
79
79
|
else
|
|
80
|
-
c.instance_variable_set(:@opts, @opts
|
|
80
|
+
c.instance_variable_set(:@opts, Hash[@opts])
|
|
81
81
|
end
|
|
82
82
|
c
|
|
83
83
|
end
|
|
@@ -584,7 +584,7 @@ module Sequel
|
|
|
584
584
|
# Returns a cloned dataset without a row_proc.
|
|
585
585
|
#
|
|
586
586
|
# ds = DB[:items]
|
|
587
|
-
# ds.row_proc = proc
|
|
587
|
+
# ds.row_proc = proc(&:invert)
|
|
588
588
|
# ds.all # => [{2=>:id}]
|
|
589
589
|
# ds.naked.all # => [{:id=>2}]
|
|
590
590
|
def naked
|
|
@@ -939,7 +939,7 @@ module Sequel
|
|
|
939
939
|
s, ds = hoist_cte(dataset)
|
|
940
940
|
s.with(name, ds, opts)
|
|
941
941
|
else
|
|
942
|
-
clone(:with=>(@opts[:with]||[]) + [opts.merge(:name=>name, :dataset=>dataset)])
|
|
942
|
+
clone(:with=>(@opts[:with]||[]) + [Hash[opts].merge!(:name=>name, :dataset=>dataset)])
|
|
943
943
|
end
|
|
944
944
|
end
|
|
945
945
|
|
|
@@ -968,7 +968,7 @@ module Sequel
|
|
|
968
968
|
s, ds = hoist_cte(recursive)
|
|
969
969
|
s.with_recursive(name, nonrecursive, ds, opts)
|
|
970
970
|
else
|
|
971
|
-
clone(:with=>(@opts[:with]||[]) + [opts.merge(:recursive=>true, :name=>name, :dataset=>nonrecursive.union(recursive, {:all=>opts[:union_all] != false, :from_self=>false}))])
|
|
971
|
+
clone(:with=>(@opts[:with]||[]) + [Hash[opts].merge!(:recursive=>true, :name=>name, :dataset=>nonrecursive.union(recursive, {:all=>opts[:union_all] != false, :from_self=>false}))])
|
|
972
972
|
end
|
|
973
973
|
end
|
|
974
974
|
|
|
@@ -1001,7 +1001,7 @@ module Sequel
|
|
|
1001
1001
|
s, ds = hoist_cte(dataset)
|
|
1002
1002
|
return s.compound_clone(type, ds, opts)
|
|
1003
1003
|
end
|
|
1004
|
-
ds = compound_from_self.clone(:compounds=>Array(@opts[:compounds]).map
|
|
1004
|
+
ds = compound_from_self.clone(:compounds=>Array(@opts[:compounds]).map(&:dup) + [[type, dataset.compound_from_self, opts[:all]]])
|
|
1005
1005
|
opts[:from_self] == false ? ds : ds.from_self(opts)
|
|
1006
1006
|
end
|
|
1007
1007
|
|
data/lib/sequel/exceptions.rb
CHANGED
|
@@ -8,70 +8,73 @@ module Sequel
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
# Error raised when the adapter requested doesn't exist or can't be loaded.
|
|
11
|
-
|
|
11
|
+
AdapterNotFound = Class.new(Error)
|
|
12
12
|
|
|
13
13
|
# Generic error raised by the database adapters, indicating a
|
|
14
14
|
# problem originating from the database server. Usually raised
|
|
15
15
|
# because incorrect SQL syntax is used.
|
|
16
|
-
|
|
16
|
+
DatabaseError = Class.new(Error)
|
|
17
17
|
|
|
18
18
|
# Error raised when the Sequel is unable to connect to the database with the
|
|
19
19
|
# connection parameters it was given.
|
|
20
|
-
|
|
20
|
+
DatabaseConnectionError = Class.new(DatabaseError)
|
|
21
21
|
|
|
22
22
|
# Error raised by adapters when they determine that the connection
|
|
23
23
|
# to the database has been lost. Instructs the connection pool code to
|
|
24
24
|
# remove that connection from the pool so that other connections can be acquired
|
|
25
25
|
# automatically.
|
|
26
|
-
|
|
26
|
+
DatabaseDisconnectError = Class.new(DatabaseError)
|
|
27
27
|
|
|
28
28
|
# Generic error raised when Sequel determines a database constraint has been violated.
|
|
29
|
-
|
|
29
|
+
ConstraintViolation = Class.new(DatabaseError)
|
|
30
30
|
|
|
31
31
|
# Error raised when Sequel determines a database check constraint has been violated.
|
|
32
|
-
|
|
32
|
+
CheckConstraintViolation = Class.new(ConstraintViolation)
|
|
33
33
|
|
|
34
34
|
# Error raised when Sequel determines a database foreign key constraint has been violated.
|
|
35
|
-
|
|
35
|
+
ForeignKeyConstraintViolation = Class.new(ConstraintViolation)
|
|
36
36
|
|
|
37
37
|
# Error raised when Sequel determines a database NOT NULL constraint has been violated.
|
|
38
|
-
|
|
38
|
+
NotNullConstraintViolation = Class.new(ConstraintViolation)
|
|
39
39
|
|
|
40
40
|
# Error raised when Sequel determines a database unique constraint has been violated.
|
|
41
|
-
|
|
41
|
+
UniqueConstraintViolation = Class.new(ConstraintViolation)
|
|
42
42
|
|
|
43
43
|
# Error raised when Sequel determines a serialization failure/deadlock in the database.
|
|
44
|
-
|
|
44
|
+
SerializationFailure = Class.new(DatabaseError)
|
|
45
45
|
|
|
46
46
|
# Error raised on an invalid operation, such as trying to update or delete
|
|
47
47
|
# a joined or grouped dataset.
|
|
48
|
-
|
|
48
|
+
InvalidOperation = Class.new(Error)
|
|
49
49
|
|
|
50
50
|
# Error raised when attempting an invalid type conversion.
|
|
51
|
-
|
|
51
|
+
InvalidValue = Class.new(Error)
|
|
52
52
|
|
|
53
53
|
# Error raised when the user requests a record via the first! or similar
|
|
54
54
|
# method, and the dataset does not yield any rows.
|
|
55
|
-
|
|
55
|
+
NoMatchingRow = Class.new(Error)
|
|
56
56
|
|
|
57
57
|
# Error raised when the connection pool cannot acquire a database connection
|
|
58
58
|
# before the timeout.
|
|
59
|
-
|
|
59
|
+
PoolTimeout = Class.new(Error)
|
|
60
60
|
|
|
61
61
|
# Error that you should raise to signal a rollback of the current transaction.
|
|
62
62
|
# The transaction block will catch this exception, rollback the current transaction,
|
|
63
63
|
# and won't reraise it (unless a reraise is requested).
|
|
64
|
-
|
|
64
|
+
Rollback = Class.new(Error)
|
|
65
65
|
|
|
66
66
|
# Error raised when unbinding a dataset that has multiple different values
|
|
67
67
|
# for a given variable.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
UnbindDuplicate = Class.new(Error)
|
|
69
|
+
|
|
70
|
+
# Call name on each class to set the name for the class, so it gets cached.
|
|
71
|
+
constants.map{|c| const_get(c)}.each do |c|
|
|
72
|
+
Class === c && c.name
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
Error::AdapterNotFound = AdapterNotFound
|
|
76
|
+
Error::InvalidOperation = InvalidOperation
|
|
77
|
+
Error::InvalidValue = InvalidValue
|
|
78
|
+
Error::PoolTimeoutError = PoolTimeout
|
|
79
|
+
Error::Rollback = Rollback
|
|
77
80
|
end
|
|
@@ -23,7 +23,7 @@ module Sequel
|
|
|
23
23
|
|
|
24
24
|
# Return the string that #print will print via puts.
|
|
25
25
|
def self.string(records, columns = nil) # records is an array of hashes
|
|
26
|
-
columns ||= records.first.keys.sort_by
|
|
26
|
+
columns ||= records.first.keys.sort_by(&:to_s)
|
|
27
27
|
sizes = column_sizes(records, columns)
|
|
28
28
|
sep_line = separator_line(columns, sizes)
|
|
29
29
|
|
|
@@ -146,7 +146,7 @@ module Sequel
|
|
|
146
146
|
%w'presence unique'.each do |v|
|
|
147
147
|
class_eval(<<-END, __FILE__, __LINE__+1)
|
|
148
148
|
def #{v}(columns, opts=OPTS)
|
|
149
|
-
@generator.validation({:type=>:#{v}, :columns=>Array(columns)}.merge(opts))
|
|
149
|
+
@generator.validation({:type=>:#{v}, :columns=>Array(columns)}.merge!(opts))
|
|
150
150
|
end
|
|
151
151
|
END
|
|
152
152
|
end
|
|
@@ -155,7 +155,7 @@ module Sequel
|
|
|
155
155
|
%w'exact_length min_length max_length length_range format like ilike includes'.each do |v|
|
|
156
156
|
class_eval(<<-END, __FILE__, __LINE__+1)
|
|
157
157
|
def #{v}(arg, columns, opts=OPTS)
|
|
158
|
-
@generator.validation({:type=>:#{v}, :columns=>Array(columns), :arg=>arg}.merge(opts))
|
|
158
|
+
@generator.validation({:type=>:#{v}, :columns=>Array(columns), :arg=>arg}.merge!(opts))
|
|
159
159
|
end
|
|
160
160
|
END
|
|
161
161
|
end
|
|
@@ -60,7 +60,7 @@ module Sequel
|
|
|
60
60
|
MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
|
|
61
61
|
H2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s[0...-1].freeze}).freeze
|
|
62
62
|
DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
|
|
63
|
-
ACCESS_DURATION_UNITS = DURATION_UNITS.zip(%w'yyyy m d h n s'.map
|
|
63
|
+
ACCESS_DURATION_UNITS = DURATION_UNITS.zip(%w'yyyy m d h n s'.map(&:freeze)).freeze
|
|
64
64
|
DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
|
|
65
65
|
FDBSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.chop).freeze}).freeze
|
|
66
66
|
|
|
@@ -180,7 +180,7 @@ module Sequel
|
|
|
180
180
|
else
|
|
181
181
|
h = Hash.new(0)
|
|
182
182
|
interval.parts.each{|unit, value| h[unit] += value}
|
|
183
|
-
|
|
183
|
+
Hash[h]
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
186
|
|
|
@@ -227,7 +227,7 @@ module Sequel
|
|
|
227
227
|
# affect global state, unlike PGArray.register. See PGArray.register for
|
|
228
228
|
# possible options.
|
|
229
229
|
def register_array_type(db_type, opts=OPTS, &block)
|
|
230
|
-
opts = {:type_procs=>conversion_procs, :typecast_method_map=>@pg_array_schema_types, :typecast_methods_module=>(class << self; self; end)}.merge(opts)
|
|
230
|
+
opts = {:type_procs=>conversion_procs, :typecast_method_map=>@pg_array_schema_types, :typecast_methods_module=>(class << self; self; end)}.merge!(opts)
|
|
231
231
|
unless (opts.has_key?(:scalar_oid) || block) && opts.has_key?(:oid)
|
|
232
232
|
array_oid, scalar_oid = from(:pg_type).where(:typname=>db_type.to_s).get([:typarray, :oid])
|
|
233
233
|
opts[:scalar_oid] = scalar_oid unless opts.has_key?(:scalar_oid) || block
|
|
@@ -300,6 +300,15 @@ module Sequel
|
|
|
300
300
|
end
|
|
301
301
|
end
|
|
302
302
|
|
|
303
|
+
# Convert ruby arrays to PostgreSQL arrays when used as default values.
|
|
304
|
+
def column_definition_default_sql(sql, column)
|
|
305
|
+
if (d = column[:default]) && d.is_a?(Array) && !Sequel.condition_specifier?(d)
|
|
306
|
+
sql << " DEFAULT (#{literal(Sequel.pg_array(d))}::#{type_literal(column)})"
|
|
307
|
+
else
|
|
308
|
+
super
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
303
312
|
# Given a value to typecast and the type of PGArray subclass:
|
|
304
313
|
# * If given a PGArray with a matching array_type, use it directly.
|
|
305
314
|
# * If given a PGArray with a different array_type, return a PGArray
|
|
@@ -445,7 +445,7 @@ module Sequel
|
|
|
445
445
|
end
|
|
446
446
|
# Manually cast to integer using to_i, because adapter may not cast oid type
|
|
447
447
|
# correctly (e.g. swift)
|
|
448
|
-
parser_opts[:oid], rel_oid, array_oid = row.values_at(:oid, :typrelid, :typarray).map
|
|
448
|
+
parser_opts[:oid], rel_oid, array_oid = row.values_at(:oid, :typrelid, :typarray).map(&:to_i)
|
|
449
449
|
|
|
450
450
|
# Get column names and oids for each of the members of the composite type.
|
|
451
451
|
res = from(:pg_attribute).
|
|
@@ -123,7 +123,7 @@ SQL
|
|
|
123
123
|
|
|
124
124
|
Thread.new do
|
|
125
125
|
begin
|
|
126
|
-
listen(opts[:channel_name]||default_static_cache_update_name, {:loop=>true}.merge(opts)) do |_, _, oid|
|
|
126
|
+
listen(opts[:channel_name]||default_static_cache_update_name, {:loop=>true}.merge!(opts)) do |_, _, oid|
|
|
127
127
|
if model = oid_map[oid.to_i]
|
|
128
128
|
model.send(:load_cache)
|
|
129
129
|
end
|
|
@@ -73,7 +73,7 @@ module Sequel
|
|
|
73
73
|
<<END_MIG
|
|
74
74
|
Sequel.migration do
|
|
75
75
|
change do
|
|
76
|
-
#{ts.sort_by
|
|
76
|
+
#{ts.sort_by(&:to_s).map{|t| dump_table_foreign_keys(t)}.reject{|x| x == ''}.join("\n\n").gsub(/^/o, ' ')}
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
END_MIG
|
|
@@ -91,7 +91,7 @@ END_MIG
|
|
|
91
91
|
<<END_MIG
|
|
92
92
|
Sequel.migration do
|
|
93
93
|
change do
|
|
94
|
-
#{ts.sort_by
|
|
94
|
+
#{ts.sort_by(&:to_s).map{|t| dump_table_indexes(t, :add_index, options)}.reject{|x| x == ''}.join("\n\n").gsub(/^/o, ' ')}
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
END_MIG
|
|
@@ -207,7 +207,7 @@ END_MIG
|
|
|
207
207
|
def dump_add_fk_constraints(table, fks)
|
|
208
208
|
sfks = "alter_table(#{table.inspect}) do\n"
|
|
209
209
|
sfks << create_table_generator do
|
|
210
|
-
fks.sort_by{|fk| fk[:columns].map
|
|
210
|
+
fks.sort_by{|fk| fk[:columns].map(&:to_s)}.each do |fk|
|
|
211
211
|
foreign_key fk[:columns], fk
|
|
212
212
|
end
|
|
213
213
|
end.dump_constraints.gsub(/^foreign_key /, ' add_foreign_key ')
|
|
@@ -218,7 +218,7 @@ END_MIG
|
|
|
218
218
|
# string that would add the foreign keys if run in a migration.
|
|
219
219
|
def dump_table_foreign_keys(table, options=OPTS)
|
|
220
220
|
if supports_foreign_key_parsing?
|
|
221
|
-
fks = foreign_key_list(table, options).sort_by{|fk| fk[:columns].map
|
|
221
|
+
fks = foreign_key_list(table, options).sort_by{|fk| fk[:columns].map(&:to_s)}
|
|
222
222
|
end
|
|
223
223
|
|
|
224
224
|
if fks.nil? || fks.empty?
|
|
@@ -234,7 +234,7 @@ END_MIG
|
|
|
234
234
|
table = table.value.to_s if table.is_a?(SQL::Identifier)
|
|
235
235
|
raise(Error, "must provide table as a Symbol, String, or Sequel::SQL::Identifier") unless [String, Symbol].any?{|c| table.is_a?(c)}
|
|
236
236
|
s = schema(table).dup
|
|
237
|
-
pks = s.find_all{|x| x.last[:primary_key] == true}.map
|
|
237
|
+
pks = s.find_all{|x| x.last[:primary_key] == true}.map(&:first)
|
|
238
238
|
options = options.merge(:single_pk=>true) if pks.length == 1
|
|
239
239
|
m = method(:recreate_column)
|
|
240
240
|
im = method(:index_to_generator_opts)
|
|
@@ -319,7 +319,7 @@ END_MIG
|
|
|
319
319
|
options[:skipped_foreign_keys] = skipped_foreign_keys
|
|
320
320
|
tables
|
|
321
321
|
else
|
|
322
|
-
tables.sort_by
|
|
322
|
+
tables.sort_by(&:to_s)
|
|
323
323
|
end
|
|
324
324
|
end
|
|
325
325
|
|
|
@@ -351,7 +351,7 @@ END_MIG
|
|
|
351
351
|
end
|
|
352
352
|
|
|
353
353
|
# Add sorted tables from this loop to the final list
|
|
354
|
-
sorted_tables.concat(this_loop.sort_by
|
|
354
|
+
sorted_tables.concat(this_loop.sort_by(&:to_s))
|
|
355
355
|
|
|
356
356
|
# Remove tables that were handled this loop
|
|
357
357
|
this_loop.each{|t| table_fks.delete(t)}
|
|
@@ -417,7 +417,7 @@ END_MIG
|
|
|
417
417
|
if !name and c[:check].length == 1 and c[:check].first.is_a?(Hash)
|
|
418
418
|
"check #{c[:check].first.inspect[1...-1]}"
|
|
419
419
|
else
|
|
420
|
-
"#{name ? "constraint #{name.inspect}," : 'check'} #{c[:check].map
|
|
420
|
+
"#{name ? "constraint #{name.inspect}," : 'check'} #{c[:check].map(&:inspect).join(', ')}"
|
|
421
421
|
end
|
|
422
422
|
when :foreign_key
|
|
423
423
|
c.delete(:on_delete) if c[:on_delete] == :no_action
|