sequel 5.33.0 → 5.58.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 +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)
|