sequel 5.33.0 → 5.58.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +318 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +40 -9
- data/doc/association_basics.rdoc +77 -13
- data/doc/cheat_sheet.rdoc +13 -5
- data/doc/code_order.rdoc +0 -12
- data/doc/dataset_filtering.rdoc +2 -2
- data/doc/fork_safety.rdoc +84 -0
- data/doc/migration.rdoc +12 -6
- data/doc/model_plugins.rdoc +1 -1
- data/doc/opening_databases.rdoc +15 -3
- data/doc/postgresql.rdoc +9 -1
- data/doc/querying.rdoc +7 -5
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- 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/sql.rdoc +14 -2
- data/doc/testing.rdoc +10 -1
- data/doc/transactions.rdoc +0 -8
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +17 -17
- data/lib/sequel/adapters/amalgalite.rb +3 -5
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +8 -0
- data/lib/sequel/adapters/jdbc/h2.rb +60 -10
- data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +4 -4
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -4
- data/lib/sequel/adapters/jdbc.rb +29 -19
- data/lib/sequel/adapters/mysql.rb +80 -67
- data/lib/sequel/adapters/mysql2.rb +54 -49
- data/lib/sequel/adapters/odbc.rb +8 -6
- data/lib/sequel/adapters/oracle.rb +5 -4
- data/lib/sequel/adapters/postgres.rb +27 -29
- data/lib/sequel/adapters/shared/access.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +30 -0
- data/lib/sequel/adapters/shared/mssql.rb +84 -7
- data/lib/sequel/adapters/shared/mysql.rb +33 -2
- data/lib/sequel/adapters/shared/oracle.rb +82 -7
- data/lib/sequel/adapters/shared/postgres.rb +158 -20
- data/lib/sequel/adapters/shared/sqlanywhere.rb +3 -0
- data/lib/sequel/adapters/shared/sqlite.rb +102 -10
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +60 -18
- data/lib/sequel/adapters/tinytds.rb +2 -1
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +9 -8
- data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
- data/lib/sequel/connection_pool/single.rb +7 -9
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +33 -24
- data/lib/sequel/database/connecting.rb +3 -4
- data/lib/sequel/database/misc.rb +37 -12
- data/lib/sequel/database/query.rb +3 -1
- data/lib/sequel/database/schema_generator.rb +50 -53
- data/lib/sequel/database/schema_methods.rb +45 -23
- data/lib/sequel/database/transactions.rb +9 -6
- data/lib/sequel/dataset/actions.rb +61 -8
- data/lib/sequel/dataset/features.rb +15 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +114 -11
- data/lib/sequel/dataset/sql.rb +172 -46
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/any_not_empty.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/core_refinements.rb +38 -11
- data/lib/sequel/extensions/date_arithmetic.rb +36 -24
- 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 +3 -1
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +9 -1
- data/lib/sequel/extensions/is_distinct_from.rb +139 -0
- data/lib/sequel/extensions/migration.rb +13 -2
- data/lib/sequel/extensions/named_timezones.rb +5 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -0
- data/lib/sequel/extensions/pg_array_ops.rb +6 -2
- data/lib/sequel/extensions/pg_enum.rb +3 -1
- data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +55 -3
- data/lib/sequel/extensions/pg_inet.rb +2 -0
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +35 -8
- data/lib/sequel/extensions/pg_json.rb +3 -5
- data/lib/sequel/extensions/pg_json_ops.rb +119 -4
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_multirange.rb +372 -0
- data/lib/sequel/extensions/pg_range.rb +7 -19
- data/lib/sequel/extensions/pg_range_ops.rb +39 -9
- data/lib/sequel/extensions/pg_row.rb +1 -1
- data/lib/sequel/extensions/pg_row_ops.rb +25 -1
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
- data/lib/sequel/extensions/s.rb +4 -1
- data/lib/sequel/extensions/schema_dumper.rb +16 -5
- data/lib/sequel/extensions/server_block.rb +8 -12
- 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_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model/associations.rb +342 -114
- data/lib/sequel/model/base.rb +45 -24
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +8 -3
- data/lib/sequel/model.rb +3 -1
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/association_proxies.rb +3 -0
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +39 -5
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +3 -8
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +8 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +44 -0
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/json_serializer.rb +39 -24
- data/lib/sequel/plugins/lazy_attributes.rb +4 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +8 -3
- data/lib/sequel/plugins/pg_array_associations.rb +58 -41
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -0
- data/lib/sequel/plugins/prepared_statements.rb +15 -12
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +37 -35
- data/lib/sequel/plugins/serialization.rb +9 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -0
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +1 -1
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/tactical_eager_loading.rb +8 -2
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +9 -4
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/plugins/validation_helpers.rb +18 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/timezones.rb +20 -17
- data/lib/sequel/version.rb +1 -1
- metadata +93 -39
@@ -35,9 +35,9 @@ module Sequel
|
|
35
35
|
data = opts[:data]
|
36
36
|
data = Array(data) if data.is_a?(String)
|
37
37
|
|
38
|
-
if
|
38
|
+
if defined?(yield) && data
|
39
39
|
raise Error, "Cannot provide both a :data option and a block to copy_into"
|
40
|
-
elsif !
|
40
|
+
elsif !defined?(yield) && !data
|
41
41
|
raise Error, "Must provide either a :data option or a block to copy_into"
|
42
42
|
end
|
43
43
|
|
@@ -45,7 +45,7 @@ module Sequel
|
|
45
45
|
begin
|
46
46
|
copy_manager = org.postgresql.copy.CopyManager.new(conn)
|
47
47
|
copier = copy_manager.copy_in(copy_into_sql(table, opts))
|
48
|
-
if
|
48
|
+
if defined?(yield)
|
49
49
|
while buf = yield
|
50
50
|
java_bytes = buf.to_java_bytes
|
51
51
|
copier.writeToCopy(java_bytes, 0, java_bytes.length)
|
@@ -77,7 +77,7 @@ module Sequel
|
|
77
77
|
copy_manager = org.postgresql.copy.CopyManager.new(conn)
|
78
78
|
copier = copy_manager.copy_out(copy_table_sql(table, opts))
|
79
79
|
begin
|
80
|
-
if
|
80
|
+
if defined?(yield)
|
81
81
|
while buf = copier.readFromCopy
|
82
82
|
yield(String.from_java_bytes(buf))
|
83
83
|
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -32,15 +32,13 @@ module Sequel
|
|
32
32
|
|
33
33
|
# Allow loading the necessary JDBC support via a gem.
|
34
34
|
def self.load_gem(name)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
jdbc_module.load_driver if jdbc_module.respond_to?(:load_driver)
|
43
|
-
end
|
35
|
+
require "jdbc/#{name.to_s.downcase}"
|
36
|
+
rescue LoadError
|
37
|
+
# jdbc gem not used, hopefully the user has the .jar in their CLASSPATH
|
38
|
+
else
|
39
|
+
if defined?(::Jdbc) && ( ::Jdbc.const_defined?(name) rescue nil )
|
40
|
+
jdbc_module = ::Jdbc.const_get(name) # e.g. Jdbc::SQLite3
|
41
|
+
jdbc_module.load_driver if jdbc_module.respond_to?(:load_driver)
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
@@ -51,7 +49,19 @@ module Sequel
|
|
51
49
|
# Raise a Sequel::AdapterNotFound if evaluating the class name raises a NameError.
|
52
50
|
def self.load_driver(drv, gem=nil)
|
53
51
|
load_gem(gem) if gem
|
54
|
-
|
52
|
+
if drv.is_a?(String)
|
53
|
+
eval drv
|
54
|
+
else
|
55
|
+
*try, last = drv
|
56
|
+
try.each do |try_drv|
|
57
|
+
begin
|
58
|
+
return eval(try_drv)
|
59
|
+
rescue NameError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
eval last
|
64
|
+
end
|
55
65
|
rescue NameError
|
56
66
|
raise Sequel::AdapterNotFound, "#{drv} not loaded#{", try installing jdbc-#{gem.to_s.downcase} gem" if gem}"
|
57
67
|
end
|
@@ -59,11 +69,11 @@ module Sequel
|
|
59
69
|
class TypeConvertor
|
60
70
|
CONVERTORS = convertors = {}
|
61
71
|
%w'Boolean Float Double Int Long Short'.each do |meth|
|
62
|
-
x = convertors[meth.to_sym] = Object.new
|
72
|
+
x = x = convertors[meth.to_sym] = Object.new
|
63
73
|
class_eval("def x.call(r, i) v = r.get#{meth}(i); v unless r.wasNull end", __FILE__, __LINE__)
|
64
74
|
end
|
65
75
|
%w'Object Array String Time Date Timestamp BigDecimal Blob Bytes Clob'.each do |meth|
|
66
|
-
x = convertors[meth.to_sym] = Object.new
|
76
|
+
x = x = convertors[meth.to_sym] = Object.new
|
67
77
|
class_eval("def x.call(r, i) r.get#{meth}(i) end", __FILE__, __LINE__)
|
68
78
|
end
|
69
79
|
x = convertors[:RubyTime] = Object.new
|
@@ -178,13 +188,13 @@ module Sequel
|
|
178
188
|
args = opts[:args] || []
|
179
189
|
sql = "{call #{name}(#{args.map{'?'}.join(',')})}"
|
180
190
|
synchronize(opts[:server]) do |conn|
|
181
|
-
|
191
|
+
begin
|
192
|
+
cps = conn.prepareCall(sql)
|
182
193
|
|
183
|
-
|
184
|
-
|
194
|
+
i = 0
|
195
|
+
args.each{|arg| set_ps_arg(cps, arg, i+=1)}
|
185
196
|
|
186
|
-
|
187
|
-
if block_given?
|
197
|
+
if defined?(yield)
|
188
198
|
yield log_connection_yield(sql, conn){cps.executeQuery}
|
189
199
|
else
|
190
200
|
log_connection_yield(sql, conn){cps.executeUpdate}
|
@@ -195,7 +205,7 @@ module Sequel
|
|
195
205
|
rescue *DATABASE_ERROR_CLASSES => e
|
196
206
|
raise_error(e)
|
197
207
|
ensure
|
198
|
-
cps.close
|
208
|
+
cps.close if cps
|
199
209
|
end
|
200
210
|
end
|
201
211
|
end
|
@@ -449,7 +459,7 @@ module Sequel
|
|
449
459
|
msg << ")"
|
450
460
|
end
|
451
461
|
begin
|
452
|
-
if
|
462
|
+
if defined?(yield)
|
453
463
|
yield log_connection_yield(msg, conn, args){cps.executeQuery}
|
454
464
|
else
|
455
465
|
case opts[:type]
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen-string-literal: true
|
2
2
|
|
3
3
|
require 'mysql'
|
4
|
-
raise(LoadError, "require 'mysql' did not define Mysql::CLIENT_MULTI_RESULTS
|
4
|
+
raise(LoadError, "require 'mysql' did not define Mysql::CLIENT_MULTI_RESULTS!, so it not supported. Please install the mysql or ruby-mysql gem.\n") unless defined?(Mysql::CLIENT_MULTI_RESULTS)
|
5
5
|
|
6
6
|
require_relative 'utils/mysql_mysql2'
|
7
7
|
require_relative 'utils/mysql_prepared_statements'
|
@@ -71,21 +71,43 @@ module Sequel
|
|
71
71
|
# disconnect this connection (a.k.a @@wait_timeout).
|
72
72
|
def connect(server)
|
73
73
|
opts = server_opts(server)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
74
|
+
|
75
|
+
if Mysql.respond_to?(:init)
|
76
|
+
conn = Mysql.init
|
77
|
+
conn.options(Mysql::READ_DEFAULT_GROUP, opts[:config_default_group] || "client")
|
78
|
+
conn.options(Mysql::OPT_LOCAL_INFILE, opts[:config_local_infile]) if opts.has_key?(:config_local_infile)
|
79
|
+
if encoding = opts[:encoding] || opts[:charset]
|
80
|
+
# Set encoding before connecting so that the mysql driver knows what
|
81
|
+
# encoding we want to use, but this can be overridden by READ_DEFAULT_GROUP.
|
82
|
+
conn.options(Mysql::SET_CHARSET_NAME, encoding)
|
83
|
+
end
|
84
|
+
if read_timeout = opts[:read_timeout] and defined? Mysql::OPT_READ_TIMEOUT
|
85
|
+
conn.options(Mysql::OPT_READ_TIMEOUT, read_timeout)
|
86
|
+
end
|
87
|
+
if connect_timeout = opts[:connect_timeout] and defined? Mysql::OPT_CONNECT_TIMEOUT
|
88
|
+
conn.options(Mysql::OPT_CONNECT_TIMEOUT, connect_timeout)
|
89
|
+
end
|
90
|
+
else
|
91
|
+
# ruby-mysql 3 API
|
92
|
+
conn = Mysql.new
|
93
|
+
# no support for default group
|
94
|
+
conn.local_infile = opts[:config_local_infile] if opts.has_key?(:config_local_infile)
|
95
|
+
if encoding = opts[:encoding] || opts[:charset]
|
96
|
+
conn.charset = encoding
|
97
|
+
end
|
98
|
+
if read_timeout = opts[:read_timeout]
|
99
|
+
conn.read_timeout = read_timeout
|
100
|
+
end
|
101
|
+
if connect_timeout = opts[:connect_timeout]
|
102
|
+
conn.connect_timeout = connect_timeout
|
103
|
+
end
|
104
|
+
conn.singleton_class.class_eval do
|
105
|
+
alias real_connect connect
|
106
|
+
alias use_result store_result
|
107
|
+
end
|
88
108
|
end
|
109
|
+
|
110
|
+
conn.ssl_set(opts[:sslkey], opts[:sslcert], opts[:sslca], opts[:sslcapath], opts[:sslcipher]) if opts[:sslca] || opts[:sslkey]
|
89
111
|
conn.real_connect(
|
90
112
|
opts[:host] || 'localhost',
|
91
113
|
opts[:user],
|
@@ -152,56 +174,49 @@ module Sequel
|
|
152
174
|
super
|
153
175
|
end
|
154
176
|
|
155
|
-
# Return the version of the MySQL server to which we are connecting.
|
156
|
-
def server_version(server=nil)
|
157
|
-
@server_version ||= (synchronize(server){|conn| conn.server_version if conn.respond_to?(:server_version)} || super)
|
158
|
-
end
|
159
|
-
|
160
177
|
private
|
161
178
|
|
162
179
|
# Execute the given SQL on the given connection. If the :type
|
163
180
|
# option is :select, yield the result of the query, otherwise
|
164
181
|
# yield the connection if a block is given.
|
165
182
|
def _execute(conn, sql, opts)
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
break
|
185
|
-
end
|
186
|
-
yield r if opts[:type] == :select
|
183
|
+
r = log_connection_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql, conn){conn.query(sql)}
|
184
|
+
if opts[:type] == :select
|
185
|
+
yield r if r
|
186
|
+
elsif defined?(yield)
|
187
|
+
yield conn
|
188
|
+
end
|
189
|
+
if conn.respond_to?(:more_results?)
|
190
|
+
while conn.more_results? do
|
191
|
+
if r
|
192
|
+
r.free
|
193
|
+
r = nil
|
194
|
+
end
|
195
|
+
begin
|
196
|
+
conn.next_result
|
197
|
+
r = conn.use_result
|
198
|
+
rescue Mysql::Error => e
|
199
|
+
raise_error(e, :disconnect=>true) if MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message)
|
200
|
+
break
|
187
201
|
end
|
202
|
+
yield r if opts[:type] == :select
|
188
203
|
end
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
r.free if r
|
204
|
+
end
|
205
|
+
rescue Mysql::Error => e
|
206
|
+
raise_error(e)
|
207
|
+
ensure
|
208
|
+
r.free if r
|
209
|
+
# Use up all results to avoid a commands out of sync message.
|
210
|
+
if conn.respond_to?(:more_results?)
|
211
|
+
while conn.more_results? do
|
212
|
+
begin
|
213
|
+
conn.next_result
|
214
|
+
r = conn.use_result
|
215
|
+
rescue Mysql::Error => e
|
216
|
+
raise_error(e, :disconnect=>true) if MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message)
|
217
|
+
break
|
204
218
|
end
|
219
|
+
r.free if r
|
205
220
|
end
|
206
221
|
end
|
207
222
|
end
|
@@ -233,17 +248,15 @@ module Sequel
|
|
233
248
|
# the conversion raises an InvalidValue exception, return v
|
234
249
|
# if :string and nil otherwise.
|
235
250
|
def convert_date_time(v)
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
raise
|
246
|
-
end
|
251
|
+
yield v
|
252
|
+
rescue InvalidValue
|
253
|
+
case @convert_invalid_date_time
|
254
|
+
when nil, :nil
|
255
|
+
nil
|
256
|
+
when :string
|
257
|
+
v
|
258
|
+
else
|
259
|
+
raise
|
247
260
|
end
|
248
261
|
end
|
249
262
|
|
@@ -86,20 +86,26 @@ module Sequel
|
|
86
86
|
if NativePreparedStatements
|
87
87
|
# Use a native mysql2 prepared statement to implement prepared statements.
|
88
88
|
def execute_prepared_statement(ps_name, opts, &block)
|
89
|
-
|
89
|
+
if ps_name.is_a?(Sequel::Dataset::ArgumentMapper)
|
90
|
+
ps = ps_name
|
91
|
+
ps_name = ps.prepared_statement_name
|
92
|
+
else
|
93
|
+
ps = prepared_statement(ps_name)
|
94
|
+
end
|
90
95
|
sql = ps.prepared_sql
|
91
96
|
|
92
97
|
synchronize(opts[:server]) do |conn|
|
93
98
|
stmt, ps_sql = conn.prepared_statements[ps_name]
|
94
99
|
unless ps_sql == sql
|
95
100
|
stmt.close if stmt
|
96
|
-
stmt = log_connection_yield(
|
101
|
+
stmt = log_connection_yield("Preparing #{ps_name}: #{sql}", conn){conn.prepare(sql)}
|
97
102
|
conn.prepared_statements[ps_name] = [stmt, sql]
|
98
103
|
end
|
99
104
|
|
100
|
-
|
101
|
-
|
102
|
-
|
105
|
+
opts = Hash[opts]
|
106
|
+
opts[:sql] = "Executing #{ps_name || sql}"
|
107
|
+
if ps_name && ps.log_sql
|
108
|
+
opts[:log_sql] = " (#{sql})"
|
103
109
|
end
|
104
110
|
|
105
111
|
_execute(conn, stmt, opts, &block)
|
@@ -111,56 +117,55 @@ module Sequel
|
|
111
117
|
# option is :select, yield the result of the query, otherwise
|
112
118
|
# yield the connection if a block is given.
|
113
119
|
def _execute(conn, sql, opts)
|
114
|
-
|
115
|
-
|
116
|
-
if
|
117
|
-
|
118
|
-
|
119
|
-
end
|
120
|
+
stream = opts[:stream]
|
121
|
+
if NativePreparedStatements
|
122
|
+
if args = opts[:arguments]
|
123
|
+
args = args.map{|arg| bound_variable_value(arg)}
|
124
|
+
end
|
120
125
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
case sql
|
127
|
+
when ::Mysql2::Statement
|
128
|
+
stmt = sql
|
129
|
+
sql = opts[:sql] || ''
|
130
|
+
when Dataset
|
131
|
+
sql = sql.sql
|
132
|
+
close_stmt = true
|
133
|
+
stmt = conn.prepare(sql)
|
129
134
|
end
|
135
|
+
end
|
130
136
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
137
|
+
r = log_connection_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql, conn, args) do
|
138
|
+
if stmt
|
139
|
+
conn.query_options.merge!(:cache_rows=>true, :database_timezone => timezone, :application_timezone => Sequel.application_timezone, :stream=>stream, :cast_booleans=>convert_tinyint_to_bool)
|
140
|
+
stmt.execute(*args)
|
141
|
+
else
|
142
|
+
conn.query(sql, :database_timezone => timezone, :application_timezone => Sequel.application_timezone, :stream=>stream)
|
138
143
|
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
else
|
151
|
-
yield r
|
144
|
+
end
|
145
|
+
if opts[:type] == :select
|
146
|
+
if r
|
147
|
+
if stream
|
148
|
+
begin
|
149
|
+
r2 = yield r
|
150
|
+
ensure
|
151
|
+
# If r2 is nil, it means the block did not exit normally,
|
152
|
+
# so the rest of the results must be drained to prevent
|
153
|
+
# "commands out of sync" errors.
|
154
|
+
r.each{} unless r2
|
152
155
|
end
|
156
|
+
else
|
157
|
+
yield r
|
153
158
|
end
|
154
|
-
elsif block_given?
|
155
|
-
yield conn
|
156
|
-
end
|
157
|
-
rescue ::Mysql2::Error => e
|
158
|
-
raise_error(e)
|
159
|
-
ensure
|
160
|
-
if stmt
|
161
|
-
conn.query_options.replace(conn.instance_variable_get(:@sequel_default_query_options))
|
162
|
-
stmt.close if close_stmt
|
163
159
|
end
|
160
|
+
elsif defined?(yield)
|
161
|
+
yield conn
|
162
|
+
end
|
163
|
+
rescue ::Mysql2::Error => e
|
164
|
+
raise_error(e)
|
165
|
+
ensure
|
166
|
+
if stmt
|
167
|
+
conn.query_options.replace(conn.instance_variable_get(:@sequel_default_query_options))
|
168
|
+
stmt.close if close_stmt
|
164
169
|
end
|
165
170
|
end
|
166
171
|
|
@@ -244,7 +249,7 @@ module Sequel
|
|
244
249
|
# it hasn't been disabled.
|
245
250
|
def paged_each(opts=OPTS, &block)
|
246
251
|
if STREAMING_SUPPORTED && opts[:stream] != false
|
247
|
-
unless
|
252
|
+
unless defined?(yield)
|
248
253
|
return enum_for(:paged_each, opts)
|
249
254
|
end
|
250
255
|
stream.each(&block)
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -40,7 +40,7 @@ module Sequel
|
|
40
40
|
synchronize(opts[:server]) do |conn|
|
41
41
|
begin
|
42
42
|
r = log_connection_yield(sql, conn){conn.run(sql)}
|
43
|
-
yield(r) if
|
43
|
+
yield(r) if defined?(yield)
|
44
44
|
rescue ::ODBC::Error, ArgumentError => e
|
45
45
|
raise_error(e)
|
46
46
|
ensure
|
@@ -92,12 +92,14 @@ module Sequel
|
|
92
92
|
cols = s.columns(true).map{|c| [output_identifier(c.name), c.type, i+=1]}
|
93
93
|
columns = cols.map{|c| c[0]}
|
94
94
|
self.columns = columns
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
95
|
+
s.each do |row|
|
96
|
+
hash = {}
|
97
|
+
cols.each do |n,t,j|
|
98
|
+
v = row[j]
|
99
|
+
# We can assume v is not false, so this shouldn't convert false to nil.
|
100
|
+
hash[n] = (convert_odbc_value(v, t) if v)
|
100
101
|
end
|
102
|
+
yield hash
|
101
103
|
end
|
102
104
|
end
|
103
105
|
self
|
@@ -14,7 +14,8 @@ module Sequel
|
|
14
14
|
# ORA-02396: exceeded maximum idle time, please connect again
|
15
15
|
# ORA-03113: end-of-file on communication channel
|
16
16
|
# ORA-03114: not connected to ORACLE
|
17
|
-
|
17
|
+
# ORA-03135: connection lost contact
|
18
|
+
CONNECTION_ERROR_CODES = [ 28, 1012, 2396, 3113, 3114, 3135 ].freeze
|
18
19
|
|
19
20
|
ORACLE_TYPES = {
|
20
21
|
:blob=>lambda{|b| Sequel::SQL::Blob.new(b.read)},
|
@@ -87,11 +88,11 @@ module Sequel
|
|
87
88
|
r = conn.parse(sql)
|
88
89
|
args = cursor_bind_params(conn, r, args)
|
89
90
|
nr = log_connection_yield(sql, conn, args){r.exec}
|
90
|
-
r = nr unless
|
91
|
+
r = nr unless defined?(yield)
|
91
92
|
else
|
92
93
|
r = log_connection_yield(sql, conn){conn.exec(sql)}
|
93
94
|
end
|
94
|
-
if
|
95
|
+
if defined?(yield)
|
95
96
|
yield(r)
|
96
97
|
elsif type == :insert
|
97
98
|
last_insert_id(conn, opts)
|
@@ -191,7 +192,7 @@ module Sequel
|
|
191
192
|
log_sql << ")"
|
192
193
|
end
|
193
194
|
r = log_connection_yield(log_sql, conn, args){cursor.exec}
|
194
|
-
if
|
195
|
+
if defined?(yield)
|
195
196
|
yield(cursor)
|
196
197
|
elsif type == :insert
|
197
198
|
last_insert_id(conn, opts)
|
@@ -116,25 +116,23 @@ module Sequel
|
|
116
116
|
# error classes is raised, or a PGError is raised and the connection
|
117
117
|
# status cannot be determined or it is not OK.
|
118
118
|
def check_disconnect_errors
|
119
|
+
yield
|
120
|
+
rescue *DISCONNECT_ERROR_CLASSES => e
|
121
|
+
disconnect = true
|
122
|
+
raise(Sequel.convert_exception_class(e, Sequel::DatabaseDisconnectError))
|
123
|
+
rescue PGError => e
|
124
|
+
disconnect = false
|
119
125
|
begin
|
120
|
-
|
121
|
-
rescue
|
126
|
+
s = status
|
127
|
+
rescue PGError
|
122
128
|
disconnect = true
|
123
|
-
raise(Sequel.convert_exception_class(e, Sequel::DatabaseDisconnectError))
|
124
|
-
rescue PGError => e
|
125
|
-
disconnect = false
|
126
|
-
begin
|
127
|
-
s = status
|
128
|
-
rescue PGError
|
129
|
-
disconnect = true
|
130
|
-
end
|
131
|
-
status_ok = (s == Adapter::CONNECTION_OK)
|
132
|
-
disconnect ||= !status_ok
|
133
|
-
disconnect ||= e.message =~ DISCONNECT_ERROR_RE
|
134
|
-
disconnect ? raise(Sequel.convert_exception_class(e, Sequel::DatabaseDisconnectError)) : raise
|
135
|
-
ensure
|
136
|
-
block if status_ok && !disconnect
|
137
129
|
end
|
130
|
+
status_ok = (s == Adapter::CONNECTION_OK)
|
131
|
+
disconnect ||= !status_ok
|
132
|
+
disconnect ||= e.message =~ DISCONNECT_ERROR_RE
|
133
|
+
disconnect ? raise(Sequel.convert_exception_class(e, Sequel::DatabaseDisconnectError)) : raise
|
134
|
+
ensure
|
135
|
+
block if status_ok && !disconnect
|
138
136
|
end
|
139
137
|
|
140
138
|
# Execute the given SQL with this connection. If a block is given,
|
@@ -143,7 +141,7 @@ module Sequel
|
|
143
141
|
args = args.map{|v| @db.bound_variable_arg(v, self)} if args
|
144
142
|
q = check_disconnect_errors{execute_query(sql, args)}
|
145
143
|
begin
|
146
|
-
|
144
|
+
defined?(yield) ? yield(q) : q.cmd_tuples
|
147
145
|
ensure
|
148
146
|
q.clear if q && q.respond_to?(:clear)
|
149
147
|
end
|
@@ -350,7 +348,7 @@ module Sequel
|
|
350
348
|
synchronize(opts[:server]) do |conn|
|
351
349
|
conn.execute(copy_table_sql(table, opts))
|
352
350
|
begin
|
353
|
-
if
|
351
|
+
if defined?(yield)
|
354
352
|
while buf = conn.get_copy_data
|
355
353
|
yield buf
|
356
354
|
end
|
@@ -400,16 +398,16 @@ module Sequel
|
|
400
398
|
data = opts[:data]
|
401
399
|
data = Array(data) if data.is_a?(String)
|
402
400
|
|
403
|
-
if
|
401
|
+
if defined?(yield) && data
|
404
402
|
raise Error, "Cannot provide both a :data option and a block to copy_into"
|
405
|
-
elsif !
|
403
|
+
elsif !defined?(yield) && !data
|
406
404
|
raise Error, "Must provide either a :data option or a block to copy_into"
|
407
405
|
end
|
408
406
|
|
409
407
|
synchronize(opts[:server]) do |conn|
|
410
408
|
conn.execute(copy_into_sql(table, opts))
|
411
409
|
begin
|
412
|
-
if
|
410
|
+
if defined?(yield)
|
413
411
|
while buf = yield
|
414
412
|
conn.put_copy_data(buf)
|
415
413
|
end
|
@@ -518,11 +516,9 @@ module Sequel
|
|
518
516
|
|
519
517
|
# Convert exceptions raised from the block into DatabaseErrors.
|
520
518
|
def check_database_errors
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
raise_error(e, :classes=>database_error_classes)
|
525
|
-
end
|
519
|
+
yield
|
520
|
+
rescue => e
|
521
|
+
raise_error(e, :classes=>database_error_classes)
|
526
522
|
end
|
527
523
|
|
528
524
|
# Set the DateStyle to ISO if configured, for faster date parsing.
|
@@ -590,7 +586,7 @@ module Sequel
|
|
590
586
|
|
591
587
|
q = conn.check_disconnect_errors{log_connection_yield(log_sql, conn, args){_execute_prepared_statement(conn, ps_name, args, opts)}}
|
592
588
|
begin
|
593
|
-
|
589
|
+
defined?(yield) ? yield(q) : q.cmd_tuples
|
594
590
|
ensure
|
595
591
|
q.clear if q && q.respond_to?(:clear)
|
596
592
|
end
|
@@ -616,7 +612,7 @@ module Sequel
|
|
616
612
|
|
617
613
|
# Use a cursor for paging.
|
618
614
|
def paged_each(opts=OPTS, &block)
|
619
|
-
unless
|
615
|
+
unless defined?(yield)
|
620
616
|
return enum_for(:paged_each, opts)
|
621
617
|
end
|
622
618
|
use_cursor(opts).each(&block)
|
@@ -717,7 +713,9 @@ module Sequel
|
|
717
713
|
sql = String.new
|
718
714
|
sql << "CALL "
|
719
715
|
identifier_append(sql, name)
|
720
|
-
|
716
|
+
sql << "("
|
717
|
+
expression_list_append(sql, args)
|
718
|
+
sql << ")"
|
721
719
|
with_sql_first(sql)
|
722
720
|
end
|
723
721
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../utils/emulate_offset_with_reverse_and_count'
|
4
4
|
require_relative '../utils/unmodified_identifiers'
|
5
|
+
require_relative '../utils/columns_limit_1'
|
5
6
|
|
6
7
|
module Sequel
|
7
8
|
module Access
|
@@ -83,6 +84,7 @@ module Sequel
|
|
83
84
|
end)
|
84
85
|
include EmulateOffsetWithReverseAndCount
|
85
86
|
include UnmodifiedIdentifiers::DatasetMethods
|
87
|
+
include ::Sequel::Dataset::ColumnsLimit1
|
86
88
|
|
87
89
|
EXTRACT_MAP = {:year=>"'yyyy'", :month=>"'m'", :day=>"'d'", :hour=>"'h'", :minute=>"'n'", :second=>"'s'"}.freeze
|
88
90
|
EXTRACT_MAP.each_value(&:freeze)
|